From 60ffdfd339af65be0bdc36f80f2b351d12a157f4 Mon Sep 17 00:00:00 2001 From: duangavin123 Date: Tue, 20 Jul 2021 19:59:51 +0800 Subject: [PATCH] =?UTF-8?q?update=20=E5=AF=BC=E5=85=A5OpenHarmony=E5=B7=A5?= =?UTF-8?q?=E7=A8=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: duangavin123 --- zh-cn/device-dev/bundles/Readme-CN.md | 30 +- .../bundles/bundles-demo-devsample.md | 54 + .../bundles/bundles-demo-environment.md | 139 +++ .../bundles/bundles-demo-hpmdescription.md | 0 zh-cn/device-dev/bundles/bundles-demo.md | 9 + .../bundles/bundles-guide-develop.md | 240 ++++ .../bundles/bundles-guide-overview.md | 54 + .../bundles/bundles-guide-prepare.md | 84 ++ zh-cn/device-dev/bundles/bundles-guide.md | 9 + .../bundles/bundles-standard-rules.md | 549 +++++++++ zh-cn/device-dev/bundles/bundles.md | 9 + ...1\2023-0-4\344\273\245\344\270\212-21.png" | Bin .../zh-cn_image_0000001051452177.png | Bin .../zh-cn_image_0000001051770876.png | Bin .../figure/zh-cn_image_0000001173313501.png | Bin 0 -> 397077 bytes ...6\346\216\245\345\205\263\347\263\273.png" | Bin .../figure/\347\273\204\344\273\2660924.png" | Bin ...6\345\205\263\347\263\273\345\233\276.png" | Bin 359473 -> 0 bytes ...06\345\244\207\345\267\245\344\275\234.md" | 84 -- .../\345\217\221\350\241\214\347\211\210.md" | 56 - ...15\344\275\234\345\256\236\344\276\213.md" | 54 - .../bundles/\346\246\202\350\277\260-0.md" | 54 - .../bundles/\346\246\202\350\277\260.md" | 38 - ...57\345\242\203\345\207\206\345\244\207.md" | 139 --- ...30\351\207\217\350\257\264\346\230\216.md" | 53 - ...04\344\273\266\345\274\200\345\217\221.md" | 241 ---- ...00\345\217\221\346\214\207\345\215\227.md" | 9 - ...00\345\217\221\347\244\272\344\276\213.md" | 9 - ...00\345\217\221\350\247\204\350\214\203.md" | 15 - ...04\344\273\266\346\236\204\346\210\220.md" | 99 -- ...04\344\273\266\347\211\210\346\234\254.md" | 23 - ...04\344\273\266\347\256\241\347\220\206.md" | 237 ---- zh-cn/device-dev/driver/GPIO.md | 9 - ...77\347\224\250\345\256\236\344\276\213.md" | 79 -- ...77\347\224\250\346\214\207\345\257\274.md" | 395 ------ .../driver/GPIO\346\246\202\350\277\260.md" | 82 -- ...00\345\217\221\345\256\236\344\276\213.md" | 238 ---- ...61\345\212\250\346\241\206\346\236\266.md" | 15 - zh-cn/device-dev/driver/I2C.md | 9 - ...77\347\224\250\345\256\236\344\276\213.md" | 192 --- ...77\347\224\250\346\214\207\345\257\274.md" | 171 --- .../driver/I2C\346\246\202\350\277\260.md" | 60 - zh-cn/device-dev/driver/LCD.md | 9 - ...00\345\217\221\345\256\236\344\276\213.md" | 291 ----- ...00\345\217\221\346\214\207\345\257\274.md" | 23 - ...00\345\217\221\346\246\202\350\277\260.md" | 46 - zh-cn/device-dev/driver/MIPI-DSI.md | 9 - ...77\347\224\250\345\256\236\344\276\213.md" | 98 -- ...77\347\224\250\346\214\207\345\257\274.md" | 365 ------ .../MIPI-DSI\346\246\202\350\277\260.md" | 84 -- zh-cn/device-dev/driver/RTC.md | 9 - ...77\347\224\250\345\256\236\344\276\213.md" | 97 -- ...77\347\224\250\346\214\207\345\257\274.md" | 741 ------------ .../driver/RTC\346\246\202\350\277\260.md" | 103 -- zh-cn/device-dev/driver/Readme-CN.md | 95 +- zh-cn/device-dev/driver/SDIO.md | 9 - ...77\347\224\250\345\256\236\344\276\213.md" | 129 -- ...77\347\224\250\346\214\207\345\257\274.md" | 787 ------------ .../driver/SDIO\346\246\202\350\277\260.md" | 149 --- zh-cn/device-dev/driver/SENSOR.md | 11 - zh-cn/device-dev/driver/SPI.md | 9 - ...77\347\224\250\345\256\236\344\276\213.md" | 70 -- ...77\347\224\250\346\214\207\345\257\274.md" | 386 ------ .../driver/SPI\346\246\202\350\277\260.md" | 107 -- zh-cn/device-dev/driver/TOUCHSCREEN.md | 9 - ...00\345\217\221\345\256\236\344\276\213.md" | 300 ----- ...00\345\217\221\346\214\207\345\257\274.md" | 36 - ...00\345\217\221\346\246\202\350\277\260.md" | 71 -- zh-cn/device-dev/driver/UART.md | 9 - ...77\347\224\250\345\256\236\344\276\213.md" | 67 -- ...77\347\224\250\346\214\207\345\257\274.md" | 506 -------- .../driver/UART\346\246\202\350\277\260.md" | 106 -- zh-cn/device-dev/driver/WATCHDOG.md | 9 - zh-cn/device-dev/driver/WLAN.md | 9 - ...00\345\217\221\345\256\236\344\276\213.md" | 372 ------ ...00\345\217\221\346\214\207\345\257\274.md" | 18 - ...00\345\217\221\346\246\202\350\277\260.md" | 229 ---- .../driver/drive-hdf-development.md | 175 +++ zh-cn/device-dev/driver/drive-hdf-manage.md | 437 +++++++ zh-cn/device-dev/driver/drive-hdf-news.md | 193 +++ .../device-dev/driver/drive-hdf-overview.md | 0 zh-cn/device-dev/driver/drive-hdf-sample.md | 238 ++++ .../driver/drive-hdf-servicemanage.md | 0 .../driver/drive-peripherals-external-des.md | 622 ++++++++++ .../driver/drive-peripherals-lcd-des.md | 363 ++++++ .../driver/drive-peripherals-sensor-des.md | 929 ++++++++++++++ .../driver/drive-peripherals-touch-des.md | 410 +++++++ zh-cn/device-dev/driver/drive-peripherals.md | 11 + .../driver/drive-platform-gpio-des.md | 560 +++++++++ .../driver/drive-platform-i2c-des.md | 426 +++++++ .../driver/drive-platform-mipidsi-des.md | 554 +++++++++ .../driver/drive-platform-rtc-des.md | 944 +++++++++++++++ .../driver/drive-platform-sdio-des.md | 1068 +++++++++++++++++ .../driver/drive-platform-spi-des.md | 566 +++++++++ .../driver/drive-platform-uart-des.md | 682 +++++++++++ .../driver/drive-platform-watchdog-des.md | 557 +++++++++ zh-cn/device-dev/driver/drive-platform.md | 19 + zh-cn/device-dev/driver/drive.md | 19 + ...5\346\224\266\346\216\245\345\217\243.png" | Bin ...7\347\244\272\346\204\217\345\233\276.png" | Bin .../MIPI-DSI\346\216\245\345\217\243.png" | Bin ...0\346\250\241\345\236\213\345\233\276.png" | Bin .../figure/TTL\346\216\245\345\217\243.png" | Bin ...0\347\224\250\347\256\241\350\204\232.png" | Bin .../zh-cn_image_0000001053405727.png | Bin .../zh-cn_image_0000001054280608.png | Bin .../zh-cn_image_0000001054564784.png | Bin .../zh-cn_image_0000001123509750.png} | Bin .../zh-cn_image_0000001123514210.png} | Bin .../zh-cn_image_0000001123540984.png} | Bin .../zh-cn_image_0000001123582482.png} | Bin .../zh-cn_image_0000001123675706.png} | Bin .../zh-cn_image_0000001123703482.png} | Bin .../zh-cn_image_0000001123742254.png} | Bin .../zh-cn_image_0000001170187071.png} | Bin .../zh-cn_image_0000001170227689.png} | Bin .../zh-cn_image_0000001170229891.png} | Bin .../zh-cn_image_0000001170262141.png} | Bin .../zh-cn_image_0000001170383063.png} | Bin ...1\345\212\250\346\250\241\345\236\213.png" | Bin ...1\345\212\250\346\250\241\345\236\213.png" | Bin ...\345\210\206\345\270\203\345\233\2764.png" | Bin .../public_sys-resources/icon-caution.gif | Bin 580 -> 0 bytes .../public_sys-resources/icon-danger.gif | Bin 580 -> 0 bytes .../driver/public_sys-resources/icon-note.gif | Bin 394 -> 0 bytes .../public_sys-resources/icon-notice.gif | Bin 406 -> 0 bytes .../driver/public_sys-resources/icon-tip.gif | Bin 253 -> 0 bytes .../public_sys-resources/icon-warning.gif | Bin 580 -> 0 bytes ...00\345\217\221\345\256\236\344\276\213.md" | 583 --------- ...00\345\217\221\346\214\207\345\257\274.md" | 16 - ...00\345\217\221\346\246\202\350\277\260.md" | 244 ---- ...13\350\257\225\346\214\207\345\257\274.md" | 82 -- .../driver/\345\244\226\350\256\276.md" | 11 - ...77\347\224\250\345\256\236\344\276\213.md" | 86 -- ...77\347\224\250\346\214\207\345\257\274.md" | 391 ------ ...50\347\213\227\346\246\202\350\277\260.md" | 78 -- ...15\347\275\256\347\256\241\347\220\206.md" | 437 ------- ...61\345\212\250\345\271\263\345\217\260.md" | 19 - ...61\345\212\250\345\274\200\345\217\221.md" | 175 --- ...72\345\210\266\347\256\241\347\220\206.md" | 193 --- ...26\350\257\221\347\216\257\345\242\203.md" | 313 ----- zh-cn/device-dev/get-code/IDE.md | 17 - zh-cn/device-dev/get-code/Readme-CN.md | 10 +- .../{figures/3.png => figure/3-20.png} | Bin .../zh-cn_image_0000001101413884.png | Bin .../zh-cn_image_0000001119755646.png | Bin .../zh-cn_image_0000001119915556.png | Bin .../zh-cn_image_0000001166715379.png | Bin zh-cn/device-dev/get-code/gettools-acquire.md | 313 +++++ zh-cn/device-dev/get-code/gettools-ide.md | 17 + zh-cn/device-dev/get-code/gettools.md | 7 + .../public_sys-resources/icon-caution.gif | Bin 580 -> 0 bytes .../public_sys-resources/icon-danger.gif | Bin 580 -> 0 bytes .../public_sys-resources/icon-note.gif | Bin 394 -> 0 bytes .../public_sys-resources/icon-notice.gif | Bin 406 -> 0 bytes .../public_sys-resources/icon-tip.gif | Bin 253 -> 0 bytes .../public_sys-resources/icon-warning.gif | Bin 580 -> 0 bytes .../device-dev/get-code/sourcecode-acquire.md | 426 +++++++ zh-cn/device-dev/get-code/sourcecode.md | 5 + ...20\347\240\201\350\216\267\345\217\226.md" | 426 ------- ...67\345\217\226\345\267\245\345\205\267.md" | 7 - zh-cn/device-dev/glossary/Readme-CN.md | 4 +- .../device-dev/glossary/glossary.md | 0 .../public_sys-resources/icon-caution.gif | Bin 580 -> 0 bytes .../public_sys-resources/icon-danger.gif | Bin 580 -> 0 bytes .../public_sys-resources/icon-note.gif | Bin 394 -> 0 bytes .../public_sys-resources/icon-notice.gif | Bin 406 -> 0 bytes .../public_sys-resources/icon-tip.gif | Bin 253 -> 0 bytes .../public_sys-resources/icon-warning.gif | Bin 580 -> 0 bytes ...01\347\250\213\350\247\243\346\236\220.md" | 18 - ...41\345\236\213\347\256\200\344\273\213.md" | 12 - ...26\350\256\276\346\216\247\345\210\266.md" | 9 - zh-cn/device-dev/guide/Readme-CN.md | 109 +- ...61\345\212\250\345\274\200\345\217\221.md" | 17 - ...45\347\261\273\344\272\247\345\223\201.md" | 7 - .../device-camera-control-demo-photoguide.md | 396 ++++++ ...device-camera-control-demo-previewguide.md | 0 .../device-camera-control-demo-videoguide.md | 0 .../guide/device-camera-control-demo.md | 9 + .../guide/device-camera-control-example.md | 63 + .../guide/device-camera-control-overview.md | 10 + .../device-dev/guide/device-camera-control.md | 9 + .../guide/device-camera-visual-addpage.md | 34 + .../guide/device-camera-visual-debug.md | 4 + .../guide/device-camera-visual-details.md | 0 .../guide/device-camera-visual-faqs.md | 0 .../guide/device-camera-visual-first-page.md | 581 +++++++++ .../guide/device-camera-visual-overview.md | 15 + .../guide/device-camera-visual-prepare.md | 27 + .../guide/device-camera-visual-run.md | 29 + .../device-dev/guide/device-camera-visual.md | 19 + zh-cn/device-dev/guide/device-camera.md | 7 + zh-cn/device-dev/guide/device-clock-guide.md | 332 +++++ zh-cn/device-dev/guide/device-drive-demo.md | 453 +++++++ ...ce-iotcamera-control-demo-photodevguide.md | 396 ++++++ ...ce-iotcamera-control-demo-videodevguide.md | 0 .../guide/device-iotcamera-control-demo.md | 7 + .../guide/device-iotcamera-control-example.md | 45 + .../device-iotcamera-control-overview.md | 10 + .../guide/device-iotcamera-control.md | 9 + zh-cn/device-dev/guide/device-iotcamera.md | 5 + .../guide/device-outerdrive-demo.md | 483 ++++++++ .../guide/device-wifi-led-outcontrol.md | 110 ++ zh-cn/device-dev/guide/device-wifi-sdk.md | 325 +++++ zh-cn/device-dev/guide/device-wifi.md | 7 + zh-cn/device-dev/guide/device.md | 15 + .../guide/{figures => figure}/Clock.png | Bin ...D\351\227\252\347\203\201\345\233\276.gif" | Bin .../Video_2020-07-25_173141.gif | Bin .../zh-cn_image_0000001078563230.png | Bin .../zh-cn_image_0000001082434703.png | Bin .../zh-cn_image_0000001169991055.png} | Bin ...7\345\212\250\347\244\272\344\276\213.png" | Bin ...5\347\250\213\347\233\256\345\275\225.png" | Bin ...5\347\250\213\347\233\256\345\275\225.png" | Bin ...3\346\226\207\344\273\266\345\233\276.png" | Bin ...7\346\240\217\346\225\210\346\236\234.png" | Bin ...0\346\240\217\346\225\210\346\236\234.png" | Bin .../figure/\346\241\214\351\235\242.png" | Bin ...3\345\212\240\351\241\265\351\235\242.png" | Bin .../figure/\347\273\230\345\233\2761.png" | Bin ...3\345\215\260\346\227\245\345\277\227.png" | Bin ...3\345\215\260\346\227\245\345\277\227.png" | Bin ...5\351\235\242\345\220\215\347\247\260.png" | Bin ...3\345\215\260\346\227\245\345\277\227.png" | Bin ...3\345\215\260\346\227\245\345\277\227.png" | Bin ...0\346\225\210\346\236\234\345\233\276.png" | Bin ...4\350\247\210\346\225\210\346\236\234.jpg" | Bin .../public_sys-resources/icon-caution.gif | Bin 580 -> 0 bytes .../public_sys-resources/icon-danger.gif | Bin 580 -> 0 bytes .../guide/public_sys-resources/icon-note.gif | Bin 394 -> 0 bytes .../public_sys-resources/icon-notice.gif | Bin 406 -> 0 bytes .../guide/public_sys-resources/icon-tip.gif | Bin 253 -> 0 bytes .../public_sys-resources/icon-warning.gif | Bin 580 -> 0 bytes ...350\207\263HDF\346\241\206\346\236\266.md" | 35 - ...62\350\201\224\345\207\275\346\225\260.md" | 40 - ...350\207\263HDF\346\241\206\346\236\266.md" | 4 - ...00\345\217\221\347\244\272\344\276\213.md" | 15 - ...17\345\244\264\346\216\247\345\210\266.md" | 9 - ...64\347\261\273\344\272\247\345\223\201.md" | 7 - ...350\247\201\351\227\256\351\242\230-10.md" | 39 - ...00\345\217\221\347\244\272\344\276\213.md" | 11 - ...\347\224\250\345\256\236\344\276\213-5.md" | 63 - ...24\347\224\250\345\256\236\344\276\213.md" | 45 - .../guide/\345\274\200\345\217\221-11.md" | 396 ------ .../guide/\345\274\200\345\217\221.md" | 91 -- ...\345\217\221\345\207\206\345\244\207-8.md" | 8 - ...00\345\217\221\345\207\206\345\244\207.md" | 27 - ...00\345\217\221\346\255\245\351\252\244.md" | 230 ---- ...00\345\217\221\351\246\226\351\241\265.md" | 581 --------- ...45\345\277\227\345\210\206\346\236\220.md" | 19 - ...\345\217\221\346\214\207\345\257\274-3.md" | 395 ------ ...00\345\217\221\346\214\207\345\257\274.md" | 395 ------ ...17\345\244\264\346\216\247\345\210\266.md" | 9 - ...64\347\261\273\344\272\247\345\223\201.md" | 5 - ...00\345\217\221\347\244\272\344\276\213.md" | 15 - .../guide/\346\246\202\350\277\260-0.md" | 10 - .../guide/\346\246\202\350\277\260-1.md" | 10 - .../guide/\346\246\202\350\277\260-10.md" | 26 - .../guide/\346\246\202\350\277\260-12.md" | 9 - .../guide/\346\246\202\350\277\260-6.md" | 15 - .../guide/\346\246\202\350\277\260-7.md" | 15 - .../guide/\346\246\202\350\277\260.md" | 4 - ...73\345\212\240\351\241\265\351\235\242.md" | 34 - ...57\345\242\203\345\207\206\345\244\207.md" | 7 - ...57\345\242\203\346\220\255\345\273\272.md" | 7 - ...\346\234\272\350\277\220\350\241\214-9.md" | 35 - ...37\346\234\272\350\277\220\350\241\214.md" | 29 - ...04\346\272\220\344\273\213\347\273\215.md" | 6 - ...\344\276\213\345\274\200\345\217\221-2.md" | 9 - ...72\344\276\213\345\274\200\345\217\221.md" | 7 - ...41\346\201\257\350\247\243\346\236\220.md" | 17 - ...76\345\220\215\346\211\223\345\214\205.md" | 4 - ...350\207\263HDF\346\241\206\346\236\266.md" | 22 - ...345\217\212\347\203\247\345\275\225-13.md" | 17 - ...21\345\217\212\347\203\247\345\275\225.md" | 20 - ...24\347\224\250\345\274\200\345\217\221.md" | 19 - ...03\350\257\225\346\211\223\345\214\205.md" | 4 - ...03\350\257\225\351\252\214\350\257\201.md" | 5 - ...01\346\234\211\351\251\261\345\212\250.md" | 99 -- ...50\344\273\266\344\277\241\346\201\257.md" | 98 -- ...17\350\277\260\344\277\241\346\201\257.md" | 64 - ...346\210\220\344\270\211\346\226\271SDK.md" | 325 ----- .../guide/\351\252\214\350\257\201.md" | 9 - ...1\243\345\205\261\345\273\272ToDo-List.md" | 245 ---- ...70\350\247\201\351\227\256\351\242\230.md" | 51 - ...00\345\217\221\345\256\236\344\276\213.md" | 49 - ...00\345\217\221\346\214\207\345\257\274.md" | 128 -- ...55\345\273\272\347\216\257\345\242\203.md" | 82 -- .../template/\346\246\202\350\277\260.md" | 169 --- .../kernel/C++\346\224\257\346\214\201.md" | 86 -- .../kernel/CMSIS\346\224\257\346\214\201.md" | 487 -------- zh-cn/device-dev/kernel/FAT-20.md | 176 --- zh-cn/device-dev/kernel/IPC.md | 11 - ...04\345\273\272\346\214\207\345\257\274.md" | 47 - zh-cn/device-dev/kernel/LittleFS.md | 7 - zh-cn/device-dev/kernel/NFS.md | 163 --- ...77\347\224\250\346\214\207\345\257\274.md" | 17 - zh-cn/device-dev/kernel/Readme-CN.md | 312 +++-- .../kernel/Shell\344\273\213\347\273\215.md" | 36 - ...77\347\224\250\350\257\246\350\247\243.md" | 13 - ...00\345\217\221\346\214\207\345\257\274.md" | 167 --- zh-cn/device-dev/kernel/VFS.md | 171 --- zh-cn/device-dev/kernel/arp.md | 114 -- zh-cn/device-dev/kernel/cat.md | 53 - zh-cn/device-dev/kernel/cd.md | 57 - zh-cn/device-dev/kernel/chgrp.md | 60 - zh-cn/device-dev/kernel/chmod.md | 60 - zh-cn/device-dev/kernel/chown.md | 70 -- zh-cn/device-dev/kernel/cp.md | 68 -- zh-cn/device-dev/kernel/cpup.md | 65 - zh-cn/device-dev/kernel/date.md | 94 -- zh-cn/device-dev/kernel/dhclient.md | 138 --- zh-cn/device-dev/kernel/dmesg.md | 113 -- zh-cn/device-dev/kernel/exec.md | 60 - ...6\347\244\272\346\204\217\345\233\276.png" | Bin 0 -> 37179 bytes ...7\347\224\250\344\277\241\346\201\257.png" | Bin ...5\345\217\243\346\241\206\346\236\266.png" | Bin .../Snipaste_2021-01-26_10-38-58-18.png} | Bin .../Snipaste_2021-01-26_10-38-58-19.png} | Bin .../Snipaste_2021-01-26_10-38-58.png | Bin ...7\347\232\204\345\205\263\347\263\273.png" | Bin ...1\345\210\260\346\226\207\344\273\266.png" | Bin ...3\345\207\272\350\257\264\346\230\216.png" | Bin ...3\345\207\272\350\257\264\346\230\216.png" | Bin ...3\345\207\272\347\244\272\344\276\213.png" | Bin .../watch-task-\347\273\223\346\236\234.png" | Bin .../zh-cn_image_0000001051690323.png | Bin .../zh-cn_image_0000001052370303.png | Bin .../zh-cn_image_0000001052370305.png | Bin .../zh-cn_image_0000001052370307.png | Bin .../zh-cn_image_0000001052530298.png | Bin .../zh-cn_image_0000001052810300.png | Bin .../zh-cn_image_0000001052810304.png | Bin .../zh-cn_image_0000001053224218.png | Bin .../zh-cn_image_0000001053710680.png | Bin .../zh-cn_image_0000001053826366.png | Bin .../zh-cn_image_0000001054624363.png | Bin .../zh-cn_image_0000001121429646.png | Bin .../zh-cn_image_0000001124146302.png | Bin .../zh-cn_image_0000001124147160.png | Bin .../zh-cn_image_0000001124306828.png | Bin .../zh-cn_image_0000001124307264.png | Bin .../zh-cn_image_0000001124310992.png | Bin .../figure/zh-cn_image_0000001132085260.png | Bin 0 -> 21297 bytes .../figure/zh-cn_image_0000001132778524.png | Bin 0 -> 40753 bytes .../figure/zh-cn_image_0000001132935054.png | Bin 0 -> 19889 bytes .../zh-cn_image_0000001170790681.png | Bin ...4\345\216\237\347\220\206\345\233\276.png" | Bin ...4\347\244\272\346\204\217\345\233\276.png" | Bin 0 -> 34146 bytes ...7\347\224\250\346\203\205\345\206\265.png" | Bin ...1\347\244\272\346\204\217\345\233\276.png" | Bin 0 -> 11238 bytes ...1\351\200\201\345\244\261\350\264\245.png" | Bin ...1\347\273\223\346\236\234\345\233\276.png" | Bin ...4\347\244\272\346\204\217\345\233\276.png" | Bin 0 -> 52280 bytes ...uid\344\270\272100-gid\344\270\272200.png" | Bin ...46\235\203\351\231\220\344\270\272666.png" | Bin ...47\276\244\347\273\204\344\270\272100.png" | Bin ...0\347\244\272\346\204\217\345\233\276.png" | Bin 0 -> 46397 bytes ...7\345\212\250\346\265\201\347\250\213.png" | Bin 0 -> 54835 bytes ...0\346\236\266\346\236\204\345\233\276.png" | Bin ...5\345\255\230\350\266\212\347\225\214.png" | Bin ...0\347\232\204\347\224\250\346\210\267.png" | Bin ...73\272-share-\347\233\256\345\275\225.png" | Bin ...-\347\232\204\346\226\207\344\273\266.png" | Bin ...-\347\232\204\347\233\256\345\275\225.png" | Bin ...0\345\277\203\347\256\227\346\263\225.png" | Bin 0 -> 50972 bytes ...6\347\273\223\346\236\204\345\233\276.png" | Bin 0 -> 36975 bytes ...7\345\256\232\350\277\233\347\250\213.png" | Bin ...6\347\244\272\346\204\217\345\233\276.png" | Bin 0 -> 42208 bytes ...5\345\255\230\350\266\212\347\225\214.png" | Bin ...3\345\207\272\347\273\223\346\236\234.png" | Bin ...3\347\273\237\346\227\245\346\234\237.png" | Bin ...1\345\275\242\347\273\223\346\236\204.png" | Bin ...7\347\244\272\346\204\217\345\233\276.png" | Bin 0 -> 16031 bytes ...46\236\234\345\246\202\344\270\213-17.png" | Bin ...3\346\236\234\345\246\202\344\270\213.png" | Bin ...6\347\232\204\344\277\241\346\201\257.png" | Bin ...5\345\256\271\345\246\202\344\270\213.png" | Bin ...3\345\211\215\350\267\257\345\276\204.png" | Bin ...7\347\224\250\346\203\205\345\206\265.png" | Bin ...7\347\224\250\346\203\205\345\206\265.png" | Bin ...47\234\213\350\277\233\347\250\213PID.png" | Bin ...0\345\210\206\344\277\241\346\201\257.png" | Bin ...6\345\231\250\344\277\241\346\201\257.png" | Bin ...7\351\207\217\344\277\241\346\201\257.png" | Bin ...0\345\205\263\344\277\241\346\201\257.png" | Bin ...51\231\244\347\233\256\345\275\225-sd.png" | Bin ...\244\346\226\207\344\273\266-log1-txt.png" | Bin ...3\347\244\272\346\204\217\345\233\276.png" | Bin .../\350\276\223\345\205\245-telnet-on.png" | Bin ...3\347\244\272\346\204\217\345\233\276.png" | Bin ...0\347\244\272\346\204\217\345\233\276.png" | Bin 0 -> 25459 bytes ...4\347\244\272\346\204\217\345\233\276.png" | Bin 33454 -> 0 bytes ...1\347\244\272\346\204\217\345\233\276.png" | Bin 51242 -> 0 bytes ...4\347\244\272\346\204\217\345\233\276.png" | Bin 45092 -> 0 bytes ...7\345\212\250\346\265\201\347\250\213.png" | Bin 41391 -> 0 bytes ...0\345\277\203\347\256\227\346\263\225.png" | Bin 61957 -> 0 bytes ...6\347\273\223\346\236\204\345\233\276.png" | Bin 32118 -> 0 bytes ...6\347\244\272\346\204\217\345\233\276.png" | Bin 28092 -> 0 bytes ...0\347\244\272\346\204\217\345\233\276.png" | Bin 16217 -> 0 bytes zh-cn/device-dev/kernel/format.md | 69 -- zh-cn/device-dev/kernel/free.md | 119 -- zh-cn/device-dev/kernel/hwi.md | 94 -- .../kernel/kernel-lite-basic-mini-time.md | 7 + .../kernel/kernel-lite-mini-app-code.md | 0 .../kernel/kernel-lite-mini-app-data-list.md | 191 +++ .../kernel/kernel-lite-mini-app-data.md | 5 + .../kernel/kernel-lite-mini-app-lib-cmsis.md | 487 ++++++++ .../kernel/kernel-lite-mini-app-lib-posix.md | 0 .../kernel/kernel-lite-mini-app-lib.md | 7 + .../device-dev/kernel/kernel-lite-mini-app.md | 9 + ...ernel-lite-mini-basic-interrupt-concept.md | 0 .../kernel-lite-mini-basic-interrupt-guide.md | 130 ++ .../kernel-lite-mini-basic-interrupt.md | 7 + .../kernel-lite-mini-basic-ipc-event-basic.md | 194 +++ .../kernel-lite-mini-basic-ipc-event-guide.md | 52 + .../kernel-lite-mini-basic-ipc-event.md | 7 + .../kernel-lite-mini-basic-ipc-mutex-basic.md | 19 + .../kernel-lite-mini-basic-ipc-mutex-guide.md | 205 ++++ .../kernel-lite-mini-basic-ipc-mutex.md | 7 + .../kernel-lite-mini-basic-ipc-queue-basic.md | 67 ++ .../kernel-lite-mini-basic-ipc-queue-guide.md | 199 +++ .../kernel-lite-mini-basic-ipc-queue.md | 7 + .../kernel-lite-mini-basic-ipc-sem-basic.md | 53 + .../kernel-lite-mini-basic-ipc-sem-guide.md | 206 ++++ .../kernel/kernel-lite-mini-basic-ipc-sem.md | 7 + .../kernel/kernel-lite-mini-basic-ipc.md | 11 + .../kernel-lite-mini-basic-memory-basic.md | 0 .../kernel-lite-mini-basic-memory-dynamic.md | 227 ++++ .../kernel-lite-mini-basic-memory-static.md | 182 +++ .../kernel/kernel-lite-mini-basic-memory.md | 9 + .../kernel-lite-mini-basic-soft-basic.md | 0 .../kernel-lite-mini-basic-soft-guide.md | 218 ++++ .../kernel/kernel-lite-mini-basic-soft.md | 7 + .../kernel-lite-mini-basic-task-basic.md | 96 ++ .../kernel-lite-mini-basic-task-guide.md | 306 +++++ .../kernel/kernel-lite-mini-basic-task.md | 7 + .../kernel-lite-mini-basic-time-basic.md | 0 .../kernel-lite-mini-basic-time-guide.md | 159 +++ .../kernel/kernel-lite-mini-basic.md | 15 + .../kernel-lite-mini-extend-cpup-basic.md | 0 .../kernel-lite-mini-extend-cpup-guide.md | 0 .../kernel/kernel-lite-mini-extend-cpup.md | 7 + .../kernel-lite-mini-extend-file-fat.md | 176 +++ .../kernel-lite-mini-extend-file-lit-basic.md | 72 ++ .../kernel-lite-mini-extend-file-lit-guide.md | 0 .../kernel-lite-mini-extend-file-lit.md | 7 + .../kernel/kernel-lite-mini-extend-file.md | 204 ++++ .../kernel/kernel-lite-mini-extend-support.md | 86 ++ .../kernel/kernel-lite-mini-extend.md | 9 + .../kernel-lite-mini-inner-debug-cet.md | 85 ++ .../kernel-lite-mini-inner-debug-det.md | 128 ++ .../kernel-lite-mini-inner-debug-mes.md | 107 ++ .../kernel/kernel-lite-mini-inner-debug.md | 11 + .../kernel-lite-mini-inner-exception.md | 329 +++++ .../kernel/kernel-lite-mini-inner-trace.md | 0 .../kernel/kernel-lite-mini-inner.md | 9 + zh-cn/device-dev/kernel/kernel-lite-mini-m.md | 62 + .../kernel/kernel-lite-mini-start.md | 47 + zh-cn/device-dev/kernel/kernel-lite-mini.md | 13 + .../kernel/kernel-lite-small-basic.md | 11 + .../{FAT.md => kernel-lite-small-file-fat.md} | 0 ...FFS2.md => kernel-lite-small-file-jffs.md} | 0 .../kernel/kernel-lite-small-file-nfs.md | 163 +++ ...MFS.md => kernel-lite-small-file-ramfs.md} | 0 .../kernel/kernel-lite-small-file-vfs.md | 171 +++ .../kernel/kernel-lite-small-file.md | 54 + .../kernel/kernel-lite-small-lib-differ.md | 0 .../kernel/kernel-lite-small-lib-standard.md | 197 +++ .../kernel/kernel-lite-small-lib.md | 7 + .../kernel/kernel-lite-small-memory.md | 353 ++++++ .../kernel/kernel-lite-small-net.md | 303 +++++ .../kernel/kernel-lite-small-process.md | 301 +++++ .../kernel/kernel-lite-small-shell-cmd-abn.md | 0 .../kernel-lite-small-shell-cmd-file-cat.md | 53 + .../kernel-lite-small-shell-cmd-file-cd.md | 57 + .../kernel-lite-small-shell-cmd-file-chgrp.md | 60 + .../kernel-lite-small-shell-cmd-file-chmod.md | 60 + .../kernel-lite-small-shell-cmd-file-chown.md | 70 ++ .../kernel-lite-small-shell-cmd-file-cp.md | 68 ++ ...kernel-lite-small-shell-cmd-file-format.md | 69 ++ .../kernel-lite-small-shell-cmd-file-is.md | 59 + .../kernel-lite-small-shell-cmd-file-isfd.md | 29 + .../kernel-lite-small-shell-cmd-file-mkdir.md | 54 + .../kernel-lite-small-shell-cmd-file-mount.md | 78 ++ .../kernel-lite-small-shell-cmd-file-part.md | 52 + ...ernel-lite-small-shell-cmd-file-partion.md | 62 + .../kernel-lite-small-shell-cmd-file-pwd.md | 34 + .../kernel-lite-small-shell-cmd-file-rm.md | 67 ++ .../kernel-lite-small-shell-cmd-file-rmdir.md | 55 + .../kernel-lite-small-shell-cmd-file-sta.md | 52 + ... kernel-lite-small-shell-cmd-file-sync.md} | 0 .../kernel-lite-small-shell-cmd-file-touch.md | 59 + ...kernel-lite-small-shell-cmd-file-umount.md | 55 + .../kernel-lite-small-shell-cmd-file-write.md | 69 ++ .../kernel-lite-small-shell-cmd-file.md | 45 + .../kernel/kernel-lite-small-shell-cmd-mag.md | 38 + .../kernel-lite-small-shell-cmd-net-arp.md | 114 ++ .../kernel-lite-small-shell-cmd-net-dh.md | 138 +++ ...=> kernel-lite-small-shell-cmd-net-dns.md} | 0 ...=> kernel-lite-small-shell-cmd-net-ipc.md} | 0 ...=> kernel-lite-small-shell-cmd-net-ipd.md} | 0 .../kernel-lite-small-shell-cmd-net-net.md | 83 ++ ...=> kernel-lite-small-shell-cmd-net-ntp.md} | 0 .../kernel-lite-small-shell-cmd-net-ping.md | 99 ++ ... kernel-lite-small-shell-cmd-net-ping6.md} | 0 .../kernel-lite-small-shell-cmd-net-tel.md | 65 + .../kernel-lite-small-shell-cmd-net-tftp.md | 87 ++ .../kernel/kernel-lite-small-shell-cmd-net.md | 25 + .../kernel-lite-small-shell-cmd-sys-cpup.md | 65 + .../kernel-lite-small-shell-cmd-sys-date.md | 94 ++ .../kernel-lite-small-shell-cmd-sys-demsg.md | 113 ++ .../kernel-lite-small-shell-cmd-sys-exec.md | 60 + .../kernel-lite-small-shell-cmd-sys-free.md | 119 ++ ...> kernel-lite-small-shell-cmd-sys-help.md} | 0 .../kernel-lite-small-shell-cmd-sys-hwi.md | 94 ++ .../kernel-lite-small-shell-cmd-sys-kill.md | 82 ++ .../kernel-lite-small-shell-cmd-sys-log.md | 74 ++ .../kernel-lite-small-shell-cmd-sys-mem.md | 38 + .../kernel-lite-small-shell-cmd-sys-oom.md | 120 ++ .../kernel-lite-small-shell-cmd-sys-pmm.md | 91 ++ ... kernel-lite-small-shell-cmd-sys-reset.md} | 0 .../kernel-lite-small-shell-cmd-sys-sem.md | 91 ++ .../kernel-lite-small-shell-cmd-sys-stack.md | 73 ++ .../kernel-lite-small-shell-cmd-sys-su.md | 62 + .../kernel-lite-small-shell-cmd-sys-swymr.md | 110 ++ .../kernel-lite-small-shell-cmd-sys-sys.md | 91 ++ .../kernel-lite-small-shell-cmd-sys-task.md | 125 ++ .../kernel-lite-small-shell-cmd-sys-uname.md | 72 ++ .../kernel-lite-small-shell-cmd-sys-vmm.md | 158 +++ .../kernel-lite-small-shell-cmd-sys-watch.md | 100 ++ .../kernel/kernel-lite-small-shell-cmd-sys.md | 47 + .../kernel/kernel-lite-small-shell-cmd.md | 13 + .../kernel/kernel-lite-small-shell-des.md | 36 + .../kernel/kernel-lite-small-shell-guide.md | 167 +++ .../kernel/kernel-lite-small-shell-sample.md | 0 .../kernel/kernel-lite-small-shell.md | 15 + .../kernel/kernel-lite-small-thread.md | 702 +++++++++++ zh-cn/device-dev/kernel/kernel-lite-small.md | 11 + zh-cn/device-dev/kernel/kernel-lite.md | 7 + .../kernel/kernel-standard-build.md | 47 + .../device-dev/kernel/kernel-standard-des.md | 0 .../kernel/kernel-standard-patch.md | 17 + zh-cn/device-dev/kernel/kernel-standard.md | 9 + zh-cn/device-dev/kernel/kernel.md | 7 + zh-cn/device-dev/kernel/kill.md | 82 -- zh-cn/device-dev/kernel/log.md | 74 -- zh-cn/device-dev/kernel/ls.md | 59 - zh-cn/device-dev/kernel/lsfd.md | 29 - zh-cn/device-dev/kernel/memcheck.md | 38 - zh-cn/device-dev/kernel/mkdir.md | 54 - zh-cn/device-dev/kernel/mount.md | 78 -- zh-cn/device-dev/kernel/netstat.md | 83 -- zh-cn/device-dev/kernel/oom.md | 120 -- zh-cn/device-dev/kernel/partinfo.md | 52 - zh-cn/device-dev/kernel/partition.md | 62 - zh-cn/device-dev/kernel/ping.md | 99 -- zh-cn/device-dev/kernel/pmm.md | 91 -- .../public_sys-resources/icon-caution.gif | Bin 580 -> 0 bytes .../public_sys-resources/icon-danger.gif | Bin 580 -> 0 bytes .../kernel/public_sys-resources/icon-note.gif | Bin 394 -> 0 bytes .../public_sys-resources/icon-notice.gif | Bin 406 -> 0 bytes .../kernel/public_sys-resources/icon-tip.gif | Bin 253 -> 0 bytes .../public_sys-resources/icon-warning.gif | Bin 580 -> 0 bytes zh-cn/device-dev/kernel/pwd.md | 34 - zh-cn/device-dev/kernel/rm.md | 67 -- zh-cn/device-dev/kernel/rmdir.md | 55 - zh-cn/device-dev/kernel/sem.md | 91 -- zh-cn/device-dev/kernel/stack.md | 73 -- zh-cn/device-dev/kernel/statfs.md | 52 - zh-cn/device-dev/kernel/su.md | 62 - zh-cn/device-dev/kernel/swtmr.md | 110 -- zh-cn/device-dev/kernel/systeminfo.md | 91 -- zh-cn/device-dev/kernel/task.md | 125 -- zh-cn/device-dev/kernel/telnet.md | 65 - zh-cn/device-dev/kernel/tftp.md | 87 -- zh-cn/device-dev/kernel/touch.md | 59 - zh-cn/device-dev/kernel/umount.md | 55 - zh-cn/device-dev/kernel/uname.md | 72 -- zh-cn/device-dev/kernel/vmm.md | 158 --- zh-cn/device-dev/kernel/watch.md | 100 -- zh-cn/device-dev/kernel/writeproc.md | 69 -- ...55\346\226\255\347\256\241\347\220\206.md" | 7 - .../kernel/\344\272\213\344\273\266.md" | 7 - .../\344\272\222\346\226\245\351\224\201.md" | 7 - ...73\345\212\241\347\256\241\347\220\206.md" | 7 - .../\344\277\241\345\217\267\351\207\217.md" | 7 - .../kernel/\345\206\205\345\255\230.md" | 353 ------ ...41\346\201\257\347\273\237\350\256\241.md" | 107 -- ...04\346\274\217\346\243\200\346\265\213.md" | 128 -- ...05\345\255\230\347\256\241\347\220\206.md" | 9 - ...05\345\255\230\350\260\203\346\265\213.md" | 11 - ...05\346\240\270\350\260\203\346\265\213.md" | 9 - ...50\346\200\201\345\206\205\345\255\230.md" | 227 ---- ...14\345\220\221\351\223\276\350\241\250.md" | 191 --- ...60\346\215\256\347\273\223\346\236\204.md" | 5 - ...346\234\254\346\246\202\345\277\265-11.md" | 53 - ...\346\234\254\346\246\202\345\277\265-2.md" | 96 -- ...346\234\254\346\246\202\345\277\265-21.md" | 82 -- ...\346\234\254\346\246\202\345\277\265-5.md" | 52 - ...\346\234\254\346\246\202\345\277\265-7.md" | 19 - ...\346\234\254\346\246\202\345\277\265-9.md" | 67 -- ...\347\241\200\345\206\205\346\240\270-1.md" | 15 - ...72\347\241\200\345\206\205\346\240\270.md" | 11 - ...73\347\273\237\345\206\205\346\240\270.md" | 15 - ...345\217\221\346\214\207\345\257\274-10.md" | 199 --- ...345\217\221\346\214\207\345\257\274-12.md" | 206 ---- ...345\217\221\346\214\207\345\257\274-14.md" | 159 --- ...345\217\221\346\214\207\345\257\274-16.md" | 218 ---- ...\345\217\221\346\214\207\345\257\274-3.md" | 306 ----- ...\345\217\221\346\214\207\345\257\274-6.md" | 194 --- ...\345\217\221\346\214\207\345\257\274-8.md" | 205 ---- ...00\345\217\221\346\214\207\345\257\274.md" | 130 -- ...02\345\270\270\350\260\203\346\265\213.md" | 329 ----- ...53\351\200\237\345\205\245\351\227\250.md" | 47 - ...51\345\261\225\347\273\204\344\273\266.md" | 9 - ...07\344\273\266\345\221\275\344\273\244.md" | 45 - ...344\273\266\347\263\273\347\273\237-19.md" | 204 ---- ...07\344\273\266\347\263\273\347\273\237.md" | 54 - ...66\351\227\264\347\256\241\347\220\206.md" | 7 - ...\346\240\207\345\207\206\345\272\223-0.md" | 197 --- .../\346\240\207\345\207\206\345\272\223.md" | 7 - ...06\345\272\223\346\224\257\346\214\201.md" | 7 - ...73\347\273\237\345\206\205\346\240\270.md" | 9 - ...10\346\201\257\351\230\237\345\210\227.md" | 7 - ...73\347\273\237\345\221\275\344\273\244.md" | 47 - .../kernel/\347\272\277\347\250\213.md" | 702 ----------- .../kernel/\347\275\221\347\273\234.md" | 303 ----- ...21\347\273\234\345\221\275\344\273\244.md" | 25 - ...57\206LiteOS-M\345\206\205\346\240\270.md" | 62 - .../kernel/\350\260\203\346\265\213.md" | 15 - ...05\345\255\230\346\243\200\346\265\213.md" | 85 -- ...66\345\256\232\346\227\266\345\231\250.md" | 7 - ...73\347\273\237\345\206\205\346\240\270.md" | 7 - ...73\347\273\237\345\206\205\346\240\270.md" | 11 - .../kernel/\350\277\233\347\250\213.md" | 301 ----- .../kernel/\351\231\204\345\275\225.md" | 9 - ...31\346\200\201\345\206\205\345\255\230.md" | 182 --- ...77\347\224\250\346\226\271\346\263\225.md" | 38 - ...04\345\272\223\347\247\273\346\244\215.md" | 435 ------- ...04\345\272\223\347\247\273\346\244\215.md" | 309 ----- zh-cn/device-dev/porting/Readme-CN.md | 56 +- .../porting/XTS\350\256\244\350\257\201.md" | 65 - zh-cn/device-dev/porting/figure/HDF_WIFI.png | Bin 0 -> 60062 bytes ...0\345\212\237\347\225\214\351\235\242.png" | Bin zh-cn/device-dev/porting/figure/init.jpg | Bin 0 -> 23299 bytes zh-cn/device-dev/porting/figure/shell.jpg | Bin 0 -> 13564 bytes .../zh-cn_image_0000001072304191.png | Bin .../zh-cn_image_0000001073943511.png | Bin .../figure/zh-cn_image_0000001126198996.png | Bin 0 -> 11830 bytes .../figure/zh-cn_image_0000001126354076.png | Bin 0 -> 89981 bytes .../figure/zh-cn_image_0000001126358814.png | Bin 0 -> 55221 bytes ...7\345\212\250\346\241\206\346\236\266.jpg" | Bin 0 -> 612762 bytes .../figure/\345\210\206\347\261\273.png" | Bin 0 -> 20230 bytes ...2\351\205\215\346\265\201\347\250\213.png" | Bin ...3\351\224\256\346\255\245\351\252\244.png" | Bin .../public_sys-resources/icon-caution.gif | Bin 580 -> 0 bytes .../public_sys-resources/icon-danger.gif | Bin 580 -> 0 bytes .../public_sys-resources/icon-note.gif | Bin 394 -> 0 bytes .../public_sys-resources/icon-notice.gif | Bin 406 -> 0 bytes .../porting/public_sys-resources/icon-tip.gif | Bin 253 -> 0 bytes .../public_sys-resources/icon-warning.gif | Bin 580 -> 0 bytes .../porting/transplant-chip-board-bundle.md | 57 + .../transplant-chip-board-component.md | 26 + .../porting/transplant-chip-board-drive.md | 0 .../porting/transplant-chip-board-hal.md | 0 .../porting/transplant-chip-board-overview.md | 57 + .../porting/transplant-chip-board-xts.md | 65 + .../porting/transplant-chip-board.md | 15 + .../porting/transplant-chip-faqs.md | 0 .../transplant-chip-kernel-adjustment.md | 83 ++ .../transplant-chip-kernel-overview.md | 64 + .../porting/transplant-chip-kernel-verify.md | 59 + .../porting/transplant-chip-kernel.md | 9 + .../porting/transplant-chip-prepare-knows.md | 84 ++ .../transplant-chip-prepare-process.md | 0 .../porting/transplant-chip-prepare.md | 7 + zh-cn/device-dev/porting/transplant-chip.md | 11 + .../device-dev/porting/transplant-minichip.md | 11 + .../porting/transplant-smallchip-drive-des.md | 11 + .../porting/transplant-smallchip-drive-oom.md | 390 ++++++ .../transplant-smallchip-drive-plat.md | 165 +++ .../porting/transplant-smallchip-drive.md | 9 + .../porting/transplant-smallchip-kernel-a.md | 265 ++++ .../transplant-smallchip-kernel-linux.md | 125 ++ .../porting/transplant-smallchip-kernel.md | 7 + .../transplant-smallchip-prepare-building.md | 142 +++ .../transplant-smallchip-prepare-needs.md | 98 ++ .../porting/transplant-smallchip-prepare.md | 7 + .../porting/transplant-smallchip.md | 9 + .../porting/transplant-thirdparty-cmake.md | 435 +++++++ .../porting/transplant-thirdparty-makefile.md | 309 +++++ .../porting/transplant-thirdparty-overview.md | 0 .../porting/transplant-thirdparty.md | 9 + zh-cn/device-dev/porting/transplant.md | 9 + ...73\346\244\215\346\214\207\345\257\274.md" | 9 - ...04\344\273\266\351\200\202\351\205\215.md" | 57 - ...73\346\244\215\346\214\207\345\257\274.md" | 11 - ...72\347\241\200\351\200\202\351\205\215.md" | 83 -- ...05\346\240\270\347\247\273\346\244\215.md" | 9 - ...73\346\244\215\351\252\214\350\257\201.md" | 59 - ...73\347\273\237\347\247\273\346\244\215.md" | 15 - ...73\346\244\215\345\207\206\345\244\207.md" | 7 - ...\346\244\215\346\246\202\350\277\260-0.md" | 57 - ...73\346\244\215\346\246\202\350\277\260.md" | 64 - ...73\346\244\215\351\241\273\347\237\245.md" | 84 -- ...04\344\273\266\350\260\203\347\224\250.md" | 26 - .../public_sys-resources/icon-caution.gif | Bin .../public_sys-resources/icon-danger.gif | Bin .../public_sys-resources/icon-note.gif | Bin .../public_sys-resources/icon-notice.gif | Bin .../public_sys-resources/icon-tip.gif | Bin .../public_sys-resources/icon-warning.gif | Bin ...16\345\274\200\345\217\221\346\235\277.md" | 11 - ...21\346\235\277\344\273\213\347\273\215.md" | 42 - ...18\345\274\200\345\217\221\346\235\277.md" | 9 - ...21\346\235\277\344\273\213\347\273\215.md" | 57 - ...61\345\274\200\345\217\221\346\235\277.md" | 11 - ...21\346\235\277\344\273\213\347\273\215.md" | 157 --- zh-cn/device-dev/quick-start/Readme-CN.md | 66 +- ...57\345\242\203\345\207\206\345\244\207.md" | 361 ------ .../WLAN\350\201\224\347\275\221.md" | 142 --- ...\345\242\203\345\207\206\345\244\207-7.md" | 176 --- ...57\345\242\203\345\207\206\345\244\207.md" | 182 --- .../quick-start/{figures => figure}/1.png | Bin .../quick-start/{figures => figure}/10.png | Bin .../quick-start/{figures => figure}/2.png | Bin .../2021-01-27_170334-16.png} | Bin .../2021-01-27_170334-2.png | Bin .../2021-01-27_170334-5.png | Bin .../{figures => figure}/2021-01-27_170334.png | Bin .../quick-start/{figures => figure}/3-0.png | Bin .../quick-start/{figures => figure}/3.png | Bin .../figure/3516\346\255\243\351\235\242.png" | Bin .../figure/3861\346\255\243\351\235\242.png" | Bin .../quick-start/{figures => figure}/4.png | Bin .../quick-start/{figures => figure}/5-1.png | Bin .../quick-start/{figures => figure}/5.png | Bin .../quick-start/{figures => figure}/6.png | Bin ...2\345\244\226\350\247\202\345\233\276.png" | Bin ...8\346\255\243\350\203\214\351\235\242.png" | Bin ...\261\2023-0-4\344\273\245\344\270\212.png" | Bin ...3\346\230\276\347\244\272\345\233\276.png" | Bin .../{figures => figure}/changjian1-10.png | Bin .../{figures => figure}/changjian1.png | Bin .../{figures => figure}/chuankou1-6.png | Bin .../{figures => figure}/chuankou1.png | Bin .../quick-start/{figures => figure}/qi1.png | Bin .../zh-cn_image_0000001057335403.png | Bin .../zh-cn_image_0000001072468991.png | Bin .../zh-cn_image_0000001072757874.png | Bin .../zh-cn_image_0000001073840162.png | Bin .../zh-cn_image_0000001113969542.png | Bin .../zh-cn_image_0000001114129428.png | Bin .../zh-cn_image_0000001114129432.png | Bin .../zh-cn_image_0000001117463460.png | Bin .../zh-cn_image_0000001117621400.png | Bin .../zh-cn_image_0000001128311066.png | Bin .../zh-cn_image_0000001128311070.png | Bin .../zh-cn_image_0000001128311072.png | Bin .../zh-cn_image_0000001128311090.png | Bin .../zh-cn_image_0000001128311092.png | Bin .../zh-cn_image_0000001128311094.png | Bin .../zh-cn_image_0000001128311096.png | Bin .../zh-cn_image_0000001128311098.png | Bin .../zh-cn_image_0000001128311100.png | Bin .../zh-cn_image_0000001128311104.png | Bin .../zh-cn_image_0000001128311116.png | Bin .../zh-cn_image_0000001128311118.png | Bin .../zh-cn_image_0000001128470864.png | Bin .../zh-cn_image_0000001128470880.png | Bin .../zh-cn_image_0000001128470900.png | Bin .../zh-cn_image_0000001128470902.png | Bin .../zh-cn_image_0000001128470904.png | Bin .../zh-cn_image_0000001128470906.png | Bin .../zh-cn_image_0000001128470908.png | Bin .../zh-cn_image_0000001128470922.png | Bin .../zh-cn_image_0000001130278040.png | Bin .../zh-cn_image_0000001130584312.png | Bin .../zh-cn_image_0000001142794291.png | Bin .../zh-cn_image_0000001142802505.png | Bin .../zh-cn_image_0000001174270699.png | Bin .../zh-cn_image_0000001174270713.png | Bin .../zh-cn_image_0000001174270715.png | Bin .../zh-cn_image_0000001174270727.png | Bin .../zh-cn_image_0000001174270729.png | Bin .../zh-cn_image_0000001174270731.png | Bin .../zh-cn_image_0000001174270733.png | Bin .../zh-cn_image_0000001174270735.png | Bin .../zh-cn_image_0000001174270737.png | Bin .../zh-cn_image_0000001174270739.png | Bin .../zh-cn_image_0000001174270743.png | Bin .../zh-cn_image_0000001174270749.png | Bin .../zh-cn_image_0000001174270751.png | Bin .../zh-cn_image_0000001174350615.png | Bin .../zh-cn_image_0000001174350623.png | Bin .../zh-cn_image_0000001174350633.png | Bin .../zh-cn_image_0000001174350641.png | Bin .../zh-cn_image_0000001174350643.png | Bin .../zh-cn_image_0000001174350647.png | Bin .../zh-cn_image_0000001174350649.png | Bin .../zh-cn_image_0000001174350651.png | Bin .../zh-cn_image_0000001174350653.png | Bin .../zh-cn_image_0000001174350655.png | Bin .../zh-cn_image_0000001174350659.png | Bin .../zh-cn_image_0000001174350661.png | Bin .../zh-cn_image_0000001174350669.png | Bin .../zh-cn_image_0000001176317561.png | Bin ...51\227\256\347\275\221\347\273\234-15.png" | Bin ...7\351\227\256\347\275\221\347\273\234.png" | Bin ...345\217\243\347\273\210\347\253\257-9.png" | Bin ...2\345\217\243\347\273\210\347\253\257.png" | Bin ...0\347\250\213\345\272\217\345\233\276.png" | Bin ...0\347\250\213\345\272\217\345\233\276.png" | Bin .../figure/\346\210\252\345\233\276.png" | Bin ...345\244\261\350\264\245\345\233\276-7.png" | Bin ...3\345\244\261\350\264\245\345\233\276.png" | Bin ...45\272\224\347\224\250\345\233\276-14.png" | Bin ...e\345\272\224\347\224\250\345\233\276.png" | Bin ...347\232\204\347\273\210\347\253\257-8.png" | Bin ...3\347\232\204\347\273\210\347\253\257.png" | Bin ...5\275\242\345\244\207\344\273\275-292.png" | Bin ...350\277\236\347\272\277\345\233\276-3.png" | Bin ...6\350\277\236\347\272\277\345\233\276.png" | Bin ...46\226\207\344\273\266\345\233\276-11.png" | Bin ...6\346\226\207\344\273\266\345\233\276.png" | Bin ...50\256\276\347\275\256\345\233\276-12.png" | Bin ...1\350\256\276\347\275\256\345\233\276.png" | Bin ...347\275\256\345\233\276\344\276\213-4.png" | Bin ...6\347\275\256\345\233\276\344\276\213.png" | Bin ...47\225\214\351\235\242\345\233\276-13.png" | Bin ...4\347\225\214\351\235\242\345\233\276.png" | Bin .../3516\346\255\243\351\235\242-16.png" | Bin 420903 -> 0 bytes ...5\351\227\250\346\265\201\347\250\213.png" | Bin 19686 -> 0 bytes .../public_sys-resources/icon-caution.gif | Bin 580 -> 0 bytes .../public_sys-resources/icon-danger.gif | Bin 580 -> 0 bytes .../public_sys-resources/icon-note.gif | Bin 394 -> 0 bytes .../public_sys-resources/icon-notice.gif | Bin 406 -> 0 bytes .../public_sys-resources/icon-tip.gif | Bin 253 -> 0 bytes .../public_sys-resources/icon-warning.gif | Bin 580 -> 0 bytes .../quickstart-lite-env-setup-des.md | 0 .../quickstart-lite-env-setup-faqs.md | 0 .../quickstart-lite-env-setup-lin.md | 361 ++++++ .../quickstart-lite-env-setup-win.md | 182 +++ .../quick-start/quickstart-lite-env-setup.md | 11 + .../quickstart-lite-introduction-hi3516.md | 42 + .../quickstart-lite-introduction-hi3518.md | 57 + .../quickstart-lite-introduction-hi3861.md | 157 +++ .../quickstart-lite-introduction.md | 9 + .../quick-start/quickstart-lite-overview.md | 0 .../quickstart-lite-steps-board3516-faqs.md | 175 +++ ...quickstart-lite-steps-board3516-program.md | 503 ++++++++ ...quickstart-lite-steps-board3516-running.md | 269 +++++ ...quickstart-lite-steps-board3516-setting.md | 122 ++ .../quickstart-lite-steps-board3516.md | 11 + .../quickstart-lite-steps-board3518-faqs.md | 174 +++ ...quickstart-lite-steps-board3518-running.md | 262 ++++ ...quickstart-lite-steps-board3518-setting.md | 114 ++ .../quickstart-lite-steps-board3518.md | 9 + ...ckstart-lite-steps-board3861-connection.md | 142 +++ .../quickstart-lite-steps-board3861-faqs.md | 292 +++++ ...quickstart-lite-steps-board3861-running.md | 158 +++ ...quickstart-lite-steps-board3861-setting.md | 367 ++++++ .../quickstart-lite-steps-board3861.md | 11 + .../quick-start/quickstart-lite-steps.md | 9 + .../device-dev/quick-start/quickstart-lite.md | 11 + .../quick-start/quickstart-standard-burn.md | 201 ++++ .../quickstart-standard-docker-environment.md | 118 ++ .../quick-start/quickstart-standard-faq.md | 0 ...quickstart-standard-package-environment.md | 98 ++ ...quickstart-standard-windows-environment.md | 179 +++ .../quick-start/quickstart-standard.md | 15 + zh-cn/device-dev/quick-start/quickstart.md | 7 + ...43\345\274\200\345\217\221\346\235\277.md" | 9 - ...45\351\227\250\344\273\213\347\273\215.md" | 54 - ...\346\235\277\347\216\257\345\242\203-2.md" | 122 -- ...\346\235\277\347\216\257\345\242\203-4.md" | 114 -- ...21\346\235\277\347\216\257\345\242\203.md" | 367 ------ ...\350\247\201\351\227\256\351\242\230-1.md" | 292 ----- ...\350\247\201\351\227\256\351\242\230-3.md" | 175 --- ...\350\247\201\351\227\256\351\242\230-6.md" | 174 --- ...00\345\217\221\346\255\245\351\252\244.md" | 9 - ...er\346\226\271\345\274\217\357\274\211.md" | 118 -- ...05\346\226\271\345\274\217\357\274\211.md" | 98 -- ...73\347\273\237\347\216\257\345\242\203.md" | 11 - ...73\347\273\237\345\205\245\351\227\250.md" | 15 - ...73\347\273\237\345\205\245\351\227\250.md" | 11 - .../\350\277\220\350\241\214Hello-OHOS-5.md" | 262 ---- .../\350\277\220\350\241\214Hello-OHOS.md" | 269 ----- .../\350\277\220\350\241\214Hello-World.md" | 158 --- ...34\345\203\217\347\203\247\345\275\225.md" | 201 ---- ...00\345\217\221\347\244\272\344\276\213.md" | 503 -------- zh-cn/device-dev/security/Readme-CN.md | 4 +- ...3\351\231\220\345\274\271\347\252\227.png" | Bin ...0\351\242\204\346\216\210\346\235\203.png" | Bin ...0\347\247\201\345\243\260\346\230\216.png" | Bin ...0\346\233\264\351\200\232\347\237\245.png" | Bin ...0\346\230\216\345\205\245\345\217\243.png" | Bin ...0\346\230\216\346\222\244\351\224\200.png" | Bin ...0\346\230\216\346\222\244\351\224\200.png" | Bin ...C\346\265\201\347\250\213\345\233\276.png" | Bin ...5\347\273\223\346\236\204\345\233\276.png" | Bin ...4\347\244\272\346\204\217\345\233\276.png" | Bin ...3\346\265\201\347\250\213\345\233\276.png" | Bin .../public_sys-resources/icon-caution.gif | Bin 580 -> 0 bytes .../public_sys-resources/icon-danger.gif | Bin 580 -> 0 bytes .../public_sys-resources/icon-note.gif | Bin 394 -> 0 bytes .../public_sys-resources/icon-notice.gif | Bin 406 -> 0 bytes .../public_sys-resources/icon-tip.gif | Bin 253 -> 0 bytes .../public_sys-resources/icon-warning.gif | Bin 580 -> 0 bytes .../safety-protection-privacyguide.md | 264 ++++ .../security/safety-safeguide-security.md | 275 +++++ zh-cn/device-dev/security/safety.md | 7 + ...11\345\205\250\346\214\207\345\215\227.md" | 271 ----- ...20\347\247\201\344\277\235\346\212\244.md" | 264 ---- ...00\345\217\221\346\214\207\345\215\227.md" | 9 - .../subsystems/AI\346\241\206\346\236\266.md" | 13 - zh-cn/device-dev/subsystems/DFX.md | 11 - .../OTA\345\215\207\347\272\247.md" | 358 ------ zh-cn/device-dev/subsystems/Readme-CN.md | 172 ++- ...00\345\217\221\350\277\207\347\250\213.md" | 162 --- .../Sensor\346\234\215\345\212\241.md" | 9 - ...77\347\224\250\346\214\207\345\257\274.md" | 72 -- ...20\347\263\273\346\246\202\350\277\260.md" | 99 -- ...00\345\217\221\346\214\207\345\215\227.md" | 648 ---------- ...77\347\224\250\346\214\207\345\257\274.md" | 119 -- .../20200721-223604(eSpace).gif | Bin ...4\345\205\263\347\263\273\345\233\276.png" | Bin ...7\346\241\206\346\236\266\345\233\276.png" | Bin ...5\345\212\241\345\220\257\345\212\250.png" | Bin ...6\346\200\247\350\276\223\345\207\272.png" | Bin ...6\346\200\247\350\276\223\345\207\272.png" | Bin ...1\345\207\273\346\225\210\346\236\234.gif" | Bin ...3\346\225\210\346\236\234\345\233\276.png" | Bin .../{figures => figure}/unnaming.png | Bin .../zh-cn_image_0000001051782526.png | Bin .../zh-cn_image_0000001052582522.png | Bin .../zh-cn_image_0000001052662559.png | Bin .../zh-cn_image_0000001052782555.png | Bin .../zh-cn_image_0000001052942531.png | Bin .../zh-cn_image_0000001053207924.gif | Bin .../zh-cn_image_0000001053247975.gif | Bin .../zh-cn_image_0000001054101094.png | Bin .../zh-cn_image_0000001054421113.png | Bin .../zh-cn_image_0000001059334449.png | Bin .../zh-cn_image_0000001060200050.png | Bin .../zh-cn_image_0000001061889268.png | Bin .../zh-cn_image_0000001062334618.png | Bin .../zh-cn_image_0000001062476933.png | Bin .../zh-cn_image_0000001062942690.png | Bin .../zh-cn_image_0000001063839940.png | Bin .../zh-cn_image_0000001077724150.png | Bin .../zh-cn_image_0000001077727032.png | Bin .../zh-cn_image_0000001119924146.gif | Bin .../zh-cn_image_0000001166643927.jpg | Bin ...0\346\225\210\346\236\234\345\233\276.gif" | Bin ...7\346\241\206\346\236\266\345\233\276.png" | Bin .../figure/\345\233\276\347\211\2071.png" | Bin ...0\345\255\220\347\263\273\347\273\237.png" | Bin ...7\346\225\210\346\236\234\345\233\276.png" | Bin ...7\345\212\250\346\265\201\347\250\213.png" | Bin ...4\273\266\344\276\235\350\265\226-(2).jpg" | Bin ...4\344\273\266\347\273\223\346\236\204.png" | Bin ...6\346\240\221\347\273\223\346\236\204.png" | Bin ...0\346\225\210\346\236\234\345\233\276.gif" | Bin ...3\345\217\260\346\236\266\346\236\204.png" | Bin ...0\350\241\214\346\227\266\345\272\217.png" | Bin ...4\347\244\272\346\204\217\345\233\276.png" | Bin ...4\345\273\272\346\265\201\347\250\213.jpg" | Bin ...7\346\225\210\346\236\234\345\233\276.png" | Bin ...3\350\241\214\345\270\203\345\261\200.png" | Bin .../subsystems/figures/RIL-Adapter.png | Bin 24049 -> 0 bytes .../figures/\345\216\273\347\224\265.png" | Bin 25300 -> 0 bytes .../figures/\346\235\245\347\224\265.png" | Bin 39328 -> 0 bytes ...77\347\224\250\346\214\207\345\257\274.md" | 658 ---------- ...70\350\247\201\351\227\256\351\242\230.md" | 39 - .../public_sys-resources/icon-caution.gif | Bin 580 -> 0 bytes .../public_sys-resources/icon-danger.gif | Bin 580 -> 0 bytes .../public_sys-resources/icon-note.gif | Bin 394 -> 0 bytes .../public_sys-resources/icon-notice.gif | Bin 406 -> 0 bytes .../public_sys-resources/icon-tip.gif | Bin 253 -> 0 bytes .../public_sys-resources/icon-warning.gif | Bin 580 -> 0 bytes .../subsys-aiframework-demo-conf.md | 0 .../subsys-aiframework-demo-plugin.md | 0 .../subsystems/subsys-aiframework-demo-sdk.md | 81 ++ .../subsystems/subsys-aiframework-demo.md | 13 + .../subsys-aiframework-devguide-conf.md | 0 .../subsys-aiframework-devguide-plugin.md | 0 .../subsys-aiframework-devguide-sdk.md | 162 +++ .../subsystems/subsys-aiframework-devguide.md | 11 + .../subsystems/subsys-aiframework-envbuild.md | 5 + .../subsystems/subsys-aiframework-guide.md | 9 + .../subsys-aiframework-tech-codemanage.md | 40 + .../subsys-aiframework-tech-interface.md | 0 .../subsys-aiframework-tech-name.md | 0 .../subsystems/subsys-aiframework-tech.md | 15 + .../subsystems/subsys-aiframework.md | 13 + .../subsys-application-framework-builden.md | 7 + .../subsys-application-framework-demo.md | 0 .../subsys-application-framework-guide.md | 711 +++++++++++ .../subsys-application-framework-overview.md | 141 +++ .../subsys-application-framework.md | 11 + .../subsystems/subsys-boot-appspawn.md | 0 .../subsystems/subsys-boot-bootstrap.md | 0 .../device-dev/subsystems/subsys-boot-faqs.md | 56 + .../device-dev/subsystems/subsys-boot-init.md | 0 .../subsystems/subsys-boot-overview.md | 66 + .../device-dev/subsystems/subsys-boot-ref.md | 0 .../subsystems/subsys-boot-syspara.md | 0 zh-cn/device-dev/subsystems/subsys-boot.md | 17 + .../subsystems/subsys-build-mini-lite.md | 996 +++++++++++++++ .../subsystems/subsys-build-mini.md | 5 + .../subsystems/subsys-build-standard-large.md | 235 ++++ .../subsystems/subsys-build-standard.md | 5 + zh-cn/device-dev/subsystems/subsys-build.md | 7 + .../subsystems/subsys-densor-demo.md | 0 .../subsystems/subsys-densor-guide.md | 72 ++ .../subsystems/subsys-densor-overview.md | 99 ++ zh-cn/device-dev/subsystems/subsys-densor.md | 9 + .../subsystems/subsys-dfx-hilog-lite.md | 0 .../subsystems/subsys-dfx-hilog-rich.md | 0 .../subsystems/subsys-dfx-hisysevent.md | 0 .../subsystems/subsys-dfx-hisyseventread.md | 103 ++ .../subsystems/subsys-dfx-overview.md | 0 zh-cn/device-dev/subsystems/subsys-dfx.md | 11 + .../subsys-graphics-animation-guide.md | 190 +++ .../subsys-graphics-bundle-guide1.md | 244 ++++ .../subsys-graphics-bundle-guide2.md | 216 ++++ .../subsys-graphics-bundle-guide3.md | 555 +++++++++ .../subsystems/subsys-graphics-overview.md | 0 .../device-dev/subsystems/subsys-graphics.md | 13 + .../subsys-multimedia-camera-overview.md | 116 ++ .../subsys-multimedia-camera-photo-guide.md | 396 ++++++ .../subsys-multimedia-camera-preview-guide.md | 0 .../subsys-multimedia-camera-record-guide.md | 0 .../subsystems/subsys-multimedia-camera.md | 11 + .../subsys-multimedia-video-overview.md | 0 .../subsys-multimedia-video-play-guide.md | 0 .../subsys-multimedia-video-record-guide.md | 0 .../subsystems/subsys-multimedia-video.md | 9 + .../subsystems/subsys-multimedia.md | 7 + .../device-dev/subsystems/subsys-ota-guide.md | 358 ++++++ .../subsystems/subsys-remote-start.md | 0 .../subsys-security-communicationverify.md | 0 .../subsystems/subsys-security-overview.md | 76 ++ .../subsys-security-rightmanagement.md | 228 ++++ .../subsystems/subsys-security-sigverify.md | 272 +++++ .../device-dev/subsystems/subsys-security.md | 11 + .../subsystems/subsys-testguide-test.md | 989 +++++++++++++++ .../subsys-toolchain-bytrace-guide.md | 115 ++ .../subsystems/subsys-toolchain-hdc-guide.md | 685 +++++++++++ .../device-dev/subsystems/subsys-toolchain.md | 6 + .../subsystems/subsys-utils-faqs.md | 0 .../subsystems/subsys-utils-guide.md | 298 +++++ .../subsystems/subsys-utils-overview.md | 0 zh-cn/device-dev/subsystems/subsys-utils.md | 9 + .../device-dev/subsystems/subsys-xts-guide.md | 715 +++++++++++ zh-cn/device-dev/subsystems/subsys.md | 33 + ...41\347\220\206\350\247\204\350\214\203.md" | 40 - ...54\345\205\261\345\237\272\347\241\200.md" | 9 - ...00\345\217\221\346\214\207\345\257\274.md" | 298 ----- ...00\345\217\221\346\214\207\345\257\274.md" | 190 --- ...57\345\212\250\346\201\242\345\244\215.md" | 17 - ...73\347\273\237\346\246\202\350\277\260.md" | 66 - ...00\345\217\221\347\244\272\344\276\213.md" | 81 -- ...76\345\275\242\345\233\276\345\203\217.md" | 13 - .../subsystems/\345\252\222\344\275\223.md" | 7 - .../subsystems/\345\256\211\345\205\250.md" | 13 - ...00\345\217\221\346\214\207\345\257\274.md" | 244 ---- ...00\345\217\221\346\214\207\345\257\274.md" | 216 ---- ...70\350\247\201\351\227\256\351\242\230.md" | 56 - ...00\345\217\221\346\214\207\345\257\274.md" | 228 ---- ...00\345\217\221\346\214\207\345\257\274.md" | 272 ----- ...\345\217\221\345\256\236\344\276\213-6.md" | 112 -- ...\345\217\221\346\214\207\345\257\274-3.md" | 711 ----------- ...00\345\217\221\346\214\207\345\257\274.md" | 11 - ...00\345\217\221\347\244\272\344\276\213.md" | 13 - ...00\346\234\257\350\247\204\350\214\203.md" | 15 - ...00\345\217\221\346\214\207\345\257\274.md" | 395 ------ ...\345\273\272\347\216\257\345\242\203-2.md" | 7 - ...55\345\273\272\347\216\257\345\242\203.md" | 5 - ...00\345\217\221\346\214\207\345\257\274.md" | 555 --------- ...04\345\273\272\346\214\207\345\257\274.md" | 7 - .../subsystems/\346\246\202\350\277\260-7.md" | 76 -- .../subsystems/\346\246\202\350\277\260.md" | 141 --- .../subsystems/\346\265\213\350\257\225.md" | 989 --------------- ...13\345\272\217\346\241\206\346\236\266.md" | 11 - .../subsystems/\347\233\270\346\234\272.md" | 11 - ...00\345\217\221\346\246\202\350\277\260.md" | 116 -- ...21\345\267\245\345\205\267\351\223\276.md" | 9 - ...26\350\257\221\346\236\204\345\273\272.md" | 7 - ...\347\224\250\346\214\207\345\257\274-1.md" | 176 --- ...77\347\224\250\346\214\207\345\257\274.md" | 431 ------- ...70\350\247\201\351\227\256\351\242\230.md" | 121 -- ...\345\273\272\346\246\202\350\277\260-0.md" | 58 - ...04\345\273\272\346\246\202\350\277\260.md" | 381 ------ ...04\345\273\272\346\214\207\345\257\274.md" | 9 - .../\351\237\263\350\247\206\351\242\221.md" | 9 - .../device-dev/\345\257\274\350\257\273.md" | 28 +- zh-cn/readme.md | 62 +- 1101 files changed, 40888 insertions(+), 40432 deletions(-) create mode 100644 zh-cn/device-dev/bundles/bundles-demo-devsample.md create mode 100644 zh-cn/device-dev/bundles/bundles-demo-environment.md rename "zh-cn/device-dev/bundles/HPM\344\273\213\347\273\215.md" => zh-cn/device-dev/bundles/bundles-demo-hpmdescription.md (100%) mode change 100755 => 100644 create mode 100644 zh-cn/device-dev/bundles/bundles-demo.md create mode 100644 zh-cn/device-dev/bundles/bundles-guide-develop.md create mode 100644 zh-cn/device-dev/bundles/bundles-guide-overview.md create mode 100644 zh-cn/device-dev/bundles/bundles-guide-prepare.md create mode 100644 zh-cn/device-dev/bundles/bundles-guide.md create mode 100644 zh-cn/device-dev/bundles/bundles-standard-rules.md create mode 100644 zh-cn/device-dev/bundles/bundles.md rename "zh-cn/device-dev/bundles/figures/SCons\345\256\211\350\243\205\346\210\220\345\212\237\347\225\214\351\235\242-\347\211\210\346\234\254\350\246\201\346\261\2023-0-4\344\273\245\344\270\212.png" => "zh-cn/device-dev/bundles/figure/SCons\345\256\211\350\243\205\346\210\220\345\212\237\347\225\214\351\235\242-\347\211\210\346\234\254\350\246\201\346\261\2023-0-4\344\273\245\344\270\212-21.png" (100%) rename zh-cn/device-dev/bundles/{figures => figure}/zh-cn_image_0000001051452177.png (100%) mode change 100755 => 100644 rename zh-cn/device-dev/bundles/{figures => figure}/zh-cn_image_0000001051770876.png (100%) mode change 100755 => 100644 create mode 100644 zh-cn/device-dev/bundles/figure/zh-cn_image_0000001173313501.png rename "zh-cn/device-dev/bundles/figures/\347\241\254\344\273\266\347\216\257\345\242\203\350\277\236\346\216\245\345\205\263\347\263\273.png" => "zh-cn/device-dev/bundles/figure/\347\241\254\344\273\266\347\216\257\345\242\203\350\277\236\346\216\245\345\205\263\347\263\273.png" (100%) mode change 100755 => 100644 rename "zh-cn/device-dev/bundles/figures/\347\273\204\344\273\2660924.png" => "zh-cn/device-dev/bundles/figure/\347\273\204\344\273\2660924.png" (100%) mode change 100755 => 100644 delete mode 100755 "zh-cn/device-dev/bundles/figures/\347\273\204\344\273\266\345\214\205\344\276\235\350\265\226\345\205\263\347\263\273\345\233\276.png" delete mode 100755 "zh-cn/device-dev/bundles/\345\207\206\345\244\207\345\267\245\344\275\234.md" delete mode 100755 "zh-cn/device-dev/bundles/\345\217\221\350\241\214\347\211\210.md" delete mode 100755 "zh-cn/device-dev/bundles/\346\223\215\344\275\234\345\256\236\344\276\213.md" delete mode 100755 "zh-cn/device-dev/bundles/\346\246\202\350\277\260-0.md" delete mode 100755 "zh-cn/device-dev/bundles/\346\246\202\350\277\260.md" delete mode 100755 "zh-cn/device-dev/bundles/\347\216\257\345\242\203\345\207\206\345\244\207.md" delete mode 100755 "zh-cn/device-dev/bundles/\347\216\257\345\242\203\345\217\230\351\207\217\350\257\264\346\230\216.md" delete mode 100755 "zh-cn/device-dev/bundles/\347\273\204\344\273\266\345\274\200\345\217\221.md" delete mode 100755 "zh-cn/device-dev/bundles/\347\273\204\344\273\266\345\274\200\345\217\221\346\214\207\345\215\227.md" delete mode 100755 "zh-cn/device-dev/bundles/\347\273\204\344\273\266\345\274\200\345\217\221\347\244\272\344\276\213.md" delete mode 100755 "zh-cn/device-dev/bundles/\347\273\204\344\273\266\345\274\200\345\217\221\350\247\204\350\214\203.md" delete mode 100755 "zh-cn/device-dev/bundles/\347\273\204\344\273\266\346\236\204\346\210\220.md" delete mode 100755 "zh-cn/device-dev/bundles/\347\273\204\344\273\266\347\211\210\346\234\254.md" delete mode 100755 "zh-cn/device-dev/bundles/\347\273\204\344\273\266\347\256\241\347\220\206.md" delete mode 100755 zh-cn/device-dev/driver/GPIO.md delete mode 100755 "zh-cn/device-dev/driver/GPIO\344\275\277\347\224\250\345\256\236\344\276\213.md" delete mode 100755 "zh-cn/device-dev/driver/GPIO\344\275\277\347\224\250\346\214\207\345\257\274.md" delete mode 100755 "zh-cn/device-dev/driver/GPIO\346\246\202\350\277\260.md" delete mode 100755 "zh-cn/device-dev/driver/HDF\345\274\200\345\217\221\345\256\236\344\276\213.md" delete mode 100755 "zh-cn/device-dev/driver/HDF\351\251\261\345\212\250\346\241\206\346\236\266.md" delete mode 100755 zh-cn/device-dev/driver/I2C.md delete mode 100755 "zh-cn/device-dev/driver/I2C\344\275\277\347\224\250\345\256\236\344\276\213.md" delete mode 100755 "zh-cn/device-dev/driver/I2C\344\275\277\347\224\250\346\214\207\345\257\274.md" delete mode 100755 "zh-cn/device-dev/driver/I2C\346\246\202\350\277\260.md" delete mode 100755 zh-cn/device-dev/driver/LCD.md delete mode 100755 "zh-cn/device-dev/driver/LCD\345\274\200\345\217\221\345\256\236\344\276\213.md" delete mode 100755 "zh-cn/device-dev/driver/LCD\345\274\200\345\217\221\346\214\207\345\257\274.md" delete mode 100755 "zh-cn/device-dev/driver/LCD\345\274\200\345\217\221\346\246\202\350\277\260.md" delete mode 100755 zh-cn/device-dev/driver/MIPI-DSI.md delete mode 100755 "zh-cn/device-dev/driver/MIPI-DSI\344\275\277\347\224\250\345\256\236\344\276\213.md" delete mode 100755 "zh-cn/device-dev/driver/MIPI-DSI\344\275\277\347\224\250\346\214\207\345\257\274.md" delete mode 100755 "zh-cn/device-dev/driver/MIPI-DSI\346\246\202\350\277\260.md" delete mode 100755 zh-cn/device-dev/driver/RTC.md delete mode 100755 "zh-cn/device-dev/driver/RTC\344\275\277\347\224\250\345\256\236\344\276\213.md" delete mode 100755 "zh-cn/device-dev/driver/RTC\344\275\277\347\224\250\346\214\207\345\257\274.md" delete mode 100755 "zh-cn/device-dev/driver/RTC\346\246\202\350\277\260.md" delete mode 100755 zh-cn/device-dev/driver/SDIO.md delete mode 100755 "zh-cn/device-dev/driver/SDIO\344\275\277\347\224\250\345\256\236\344\276\213.md" delete mode 100755 "zh-cn/device-dev/driver/SDIO\344\275\277\347\224\250\346\214\207\345\257\274.md" delete mode 100755 "zh-cn/device-dev/driver/SDIO\346\246\202\350\277\260.md" delete mode 100755 zh-cn/device-dev/driver/SENSOR.md delete mode 100755 zh-cn/device-dev/driver/SPI.md delete mode 100755 "zh-cn/device-dev/driver/SPI\344\275\277\347\224\250\345\256\236\344\276\213.md" delete mode 100755 "zh-cn/device-dev/driver/SPI\344\275\277\347\224\250\346\214\207\345\257\274.md" delete mode 100755 "zh-cn/device-dev/driver/SPI\346\246\202\350\277\260.md" delete mode 100755 zh-cn/device-dev/driver/TOUCHSCREEN.md delete mode 100755 "zh-cn/device-dev/driver/Touchscreen\345\274\200\345\217\221\345\256\236\344\276\213.md" delete mode 100755 "zh-cn/device-dev/driver/Touchscreen\345\274\200\345\217\221\346\214\207\345\257\274.md" delete mode 100755 "zh-cn/device-dev/driver/Touchscreen\345\274\200\345\217\221\346\246\202\350\277\260.md" delete mode 100755 zh-cn/device-dev/driver/UART.md delete mode 100755 "zh-cn/device-dev/driver/UART\344\275\277\347\224\250\345\256\236\344\276\213.md" delete mode 100755 "zh-cn/device-dev/driver/UART\344\275\277\347\224\250\346\214\207\345\257\274.md" delete mode 100755 "zh-cn/device-dev/driver/UART\346\246\202\350\277\260.md" delete mode 100755 zh-cn/device-dev/driver/WATCHDOG.md delete mode 100755 zh-cn/device-dev/driver/WLAN.md delete mode 100755 "zh-cn/device-dev/driver/WLAN\345\274\200\345\217\221\345\256\236\344\276\213.md" delete mode 100755 "zh-cn/device-dev/driver/WLAN\345\274\200\345\217\221\346\214\207\345\257\274.md" delete mode 100755 "zh-cn/device-dev/driver/WLAN\345\274\200\345\217\221\346\246\202\350\277\260.md" create mode 100644 zh-cn/device-dev/driver/drive-hdf-development.md create mode 100644 zh-cn/device-dev/driver/drive-hdf-manage.md create mode 100644 zh-cn/device-dev/driver/drive-hdf-news.md rename "zh-cn/device-dev/driver/HDF\345\274\200\345\217\221\346\246\202\350\277\260.md" => zh-cn/device-dev/driver/drive-hdf-overview.md (100%) mode change 100755 => 100644 create mode 100644 zh-cn/device-dev/driver/drive-hdf-sample.md rename "zh-cn/device-dev/driver/\351\251\261\345\212\250\346\234\215\345\212\241\347\256\241\347\220\206.md" => zh-cn/device-dev/driver/drive-hdf-servicemanage.md (100%) mode change 100755 => 100644 create mode 100644 zh-cn/device-dev/driver/drive-peripherals-external-des.md create mode 100644 zh-cn/device-dev/driver/drive-peripherals-lcd-des.md create mode 100644 zh-cn/device-dev/driver/drive-peripherals-sensor-des.md create mode 100644 zh-cn/device-dev/driver/drive-peripherals-touch-des.md create mode 100644 zh-cn/device-dev/driver/drive-peripherals.md create mode 100644 zh-cn/device-dev/driver/drive-platform-gpio-des.md create mode 100644 zh-cn/device-dev/driver/drive-platform-i2c-des.md create mode 100644 zh-cn/device-dev/driver/drive-platform-mipidsi-des.md create mode 100644 zh-cn/device-dev/driver/drive-platform-rtc-des.md create mode 100644 zh-cn/device-dev/driver/drive-platform-sdio-des.md create mode 100644 zh-cn/device-dev/driver/drive-platform-spi-des.md create mode 100644 zh-cn/device-dev/driver/drive-platform-uart-des.md create mode 100644 zh-cn/device-dev/driver/drive-platform-watchdog-des.md create mode 100644 zh-cn/device-dev/driver/drive-platform.md create mode 100644 zh-cn/device-dev/driver/drive.md rename "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" => "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" (100%) mode change 100755 => 100644 rename "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" => "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" (100%) mode change 100755 => 100644 rename "zh-cn/device-dev/driver/figures/MIPI-DSI\346\216\245\345\217\243.png" => "zh-cn/device-dev/driver/figure/MIPI-DSI\346\216\245\345\217\243.png" (100%) mode change 100755 => 100644 rename "zh-cn/device-dev/driver/figures/Sensor\351\251\261\345\212\250\346\250\241\345\236\213\345\233\276.png" => "zh-cn/device-dev/driver/figure/Sensor\351\251\261\345\212\250\346\250\241\345\236\213\345\233\276.png" (100%) mode change 100755 => 100644 rename "zh-cn/device-dev/driver/figures/TTL\346\216\245\345\217\243.png" => "zh-cn/device-dev/driver/figure/TTL\346\216\245\345\217\243.png" (100%) mode change 100755 => 100644 rename "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" => "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" (100%) mode change 100755 => 100644 rename zh-cn/device-dev/driver/{figures => figure}/zh-cn_image_0000001053405727.png (100%) mode change 100755 => 100644 rename zh-cn/device-dev/driver/{figures => figure}/zh-cn_image_0000001054280608.png (100%) mode change 100755 => 100644 rename zh-cn/device-dev/driver/{figures => figure}/zh-cn_image_0000001054564784.png (100%) mode change 100755 => 100644 rename zh-cn/device-dev/driver/{figures/zh-cn_image_0000001057902344.png => figure/zh-cn_image_0000001123509750.png} (100%) mode change 100755 => 100644 rename zh-cn/device-dev/driver/{figures/zh-cn_image_0000001072553354.png => figure/zh-cn_image_0000001123514210.png} (100%) mode change 100755 => 100644 rename zh-cn/device-dev/driver/{figures/zh-cn_image_0000001054440624.png => figure/zh-cn_image_0000001123540984.png} (100%) mode change 100755 => 100644 rename zh-cn/device-dev/driver/{figures/zh-cn_image_0000001054007499.png => figure/zh-cn_image_0000001123582482.png} (100%) mode change 100755 => 100644 rename zh-cn/device-dev/driver/{figures/zh-cn_image_0000001054728498.png => figure/zh-cn_image_0000001123675706.png} (100%) mode change 100755 => 100644 rename zh-cn/device-dev/driver/{figures/zh-cn_image_0000001054726248.png => figure/zh-cn_image_0000001123703482.png} (100%) mode change 100755 => 100644 rename zh-cn/device-dev/driver/{figures/zh-cn_image_0000001054142582.png => figure/zh-cn_image_0000001123742254.png} (100%) mode change 100755 => 100644 rename zh-cn/device-dev/driver/{figures/zh-cn_image_0000001057342245.png => figure/zh-cn_image_0000001170187071.png} (100%) mode change 100755 => 100644 rename zh-cn/device-dev/driver/{figures/zh-cn_image_0000001054006983.png => figure/zh-cn_image_0000001170227689.png} (100%) mode change 100755 => 100644 rename zh-cn/device-dev/driver/{figures/zh-cn_image_0000001057622716.png => figure/zh-cn_image_0000001170229891.png} (100%) mode change 100755 => 100644 rename zh-cn/device-dev/driver/{figures/zh-cn_image_0000001053926237.png => figure/zh-cn_image_0000001170262141.png} (100%) mode change 100755 => 100644 rename zh-cn/device-dev/driver/{figures/zh-cn_image_0000001055299108.png => figure/zh-cn_image_0000001170383063.png} (100%) mode change 100755 => 100644 rename "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" => "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" (100%) mode change 100755 => 100644 rename "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" => "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" (100%) mode change 100755 => 100644 rename "zh-cn/device-dev/driver/figures/\346\216\245\345\217\243\345\210\206\345\270\203\345\233\2764.png" => "zh-cn/device-dev/driver/figure/\346\216\245\345\217\243\345\210\206\345\270\203\345\233\2764.png" (100%) mode change 100755 => 100644 delete mode 100755 zh-cn/device-dev/driver/public_sys-resources/icon-caution.gif delete mode 100755 zh-cn/device-dev/driver/public_sys-resources/icon-danger.gif delete mode 100755 zh-cn/device-dev/driver/public_sys-resources/icon-note.gif delete mode 100755 zh-cn/device-dev/driver/public_sys-resources/icon-notice.gif delete mode 100755 zh-cn/device-dev/driver/public_sys-resources/icon-tip.gif delete mode 100755 zh-cn/device-dev/driver/public_sys-resources/icon-warning.gif delete mode 100755 "zh-cn/device-dev/driver/\344\274\240\346\204\237\345\231\250\351\251\261\345\212\250\345\274\200\345\217\221\345\256\236\344\276\213.md" delete mode 100755 "zh-cn/device-dev/driver/\344\274\240\346\204\237\345\231\250\351\251\261\345\212\250\345\274\200\345\217\221\346\214\207\345\257\274.md" delete mode 100755 "zh-cn/device-dev/driver/\344\274\240\346\204\237\345\231\250\351\251\261\345\212\250\345\274\200\345\217\221\346\246\202\350\277\260.md" delete mode 100755 "zh-cn/device-dev/driver/\344\274\240\346\204\237\345\231\250\351\251\261\345\212\250\346\265\213\350\257\225\346\214\207\345\257\274.md" delete mode 100755 "zh-cn/device-dev/driver/\345\244\226\350\256\276.md" delete mode 100755 "zh-cn/device-dev/driver/\347\234\213\351\227\250\347\213\227\344\275\277\347\224\250\345\256\236\344\276\213.md" delete mode 100755 "zh-cn/device-dev/driver/\347\234\213\351\227\250\347\213\227\344\275\277\347\224\250\346\214\207\345\257\274.md" delete mode 100755 "zh-cn/device-dev/driver/\347\234\213\351\227\250\347\213\227\346\246\202\350\277\260.md" delete mode 100755 "zh-cn/device-dev/driver/\351\205\215\347\275\256\347\256\241\347\220\206.md" delete mode 100755 "zh-cn/device-dev/driver/\351\251\261\345\212\250\345\271\263\345\217\260.md" delete mode 100755 "zh-cn/device-dev/driver/\351\251\261\345\212\250\345\274\200\345\217\221.md" delete mode 100755 "zh-cn/device-dev/driver/\351\251\261\345\212\250\346\266\210\346\201\257\346\234\272\345\210\266\347\256\241\347\220\206.md" delete mode 100644 "zh-cn/device-dev/get-code/Docker\347\274\226\350\257\221\347\216\257\345\242\203.md" delete mode 100644 zh-cn/device-dev/get-code/IDE.md rename zh-cn/device-dev/get-code/{figures/3.png => figure/3-20.png} (100%) rename zh-cn/device-dev/get-code/{figures => figure}/zh-cn_image_0000001101413884.png (100%) rename zh-cn/device-dev/get-code/{figures => figure}/zh-cn_image_0000001119755646.png (100%) rename zh-cn/device-dev/get-code/{figures => figure}/zh-cn_image_0000001119915556.png (100%) rename zh-cn/device-dev/get-code/{figures => figure}/zh-cn_image_0000001166715379.png (100%) create mode 100644 zh-cn/device-dev/get-code/gettools-acquire.md create mode 100644 zh-cn/device-dev/get-code/gettools-ide.md create mode 100644 zh-cn/device-dev/get-code/gettools.md delete mode 100755 zh-cn/device-dev/get-code/public_sys-resources/icon-caution.gif delete mode 100755 zh-cn/device-dev/get-code/public_sys-resources/icon-danger.gif delete mode 100755 zh-cn/device-dev/get-code/public_sys-resources/icon-note.gif delete mode 100755 zh-cn/device-dev/get-code/public_sys-resources/icon-notice.gif delete mode 100755 zh-cn/device-dev/get-code/public_sys-resources/icon-tip.gif delete mode 100755 zh-cn/device-dev/get-code/public_sys-resources/icon-warning.gif create mode 100644 zh-cn/device-dev/get-code/sourcecode-acquire.md create mode 100644 zh-cn/device-dev/get-code/sourcecode.md delete mode 100755 "zh-cn/device-dev/get-code/\346\272\220\347\240\201\350\216\267\345\217\226.md" delete mode 100755 "zh-cn/device-dev/get-code/\350\216\267\345\217\226\345\267\245\345\205\267.md" rename "zh-cn/device-dev/glossary/\346\234\257\350\257\255.md" => zh-cn/device-dev/glossary/glossary.md (100%) mode change 100755 => 100644 delete mode 100755 zh-cn/device-dev/glossary/public_sys-resources/icon-caution.gif delete mode 100755 zh-cn/device-dev/glossary/public_sys-resources/icon-danger.gif delete mode 100755 zh-cn/device-dev/glossary/public_sys-resources/icon-note.gif delete mode 100755 zh-cn/device-dev/glossary/public_sys-resources/icon-notice.gif delete mode 100755 zh-cn/device-dev/glossary/public_sys-resources/icon-tip.gif delete mode 100755 zh-cn/device-dev/glossary/public_sys-resources/icon-warning.gif delete mode 100644 "zh-cn/device-dev/guide/Input\346\250\241\345\236\213\345\267\245\344\275\234\346\265\201\347\250\213\350\247\243\346\236\220.md" delete mode 100644 "zh-cn/device-dev/guide/Input\346\250\241\345\236\213\347\256\200\344\273\213.md" delete mode 100755 "zh-cn/device-dev/guide/LED\345\244\226\350\256\276\346\216\247\345\210\266.md" delete mode 100644 "zh-cn/device-dev/guide/TouchScreen\345\231\250\344\273\266\351\251\261\345\212\250\345\274\200\345\217\221.md" delete mode 100755 "zh-cn/device-dev/guide/WLAN\350\277\236\346\216\245\347\261\273\344\272\247\345\223\201.md" create mode 100644 zh-cn/device-dev/guide/device-camera-control-demo-photoguide.md rename "zh-cn/device-dev/guide/\351\242\204\350\247\210\345\274\200\345\217\221\346\214\207\345\257\274.md" => zh-cn/device-dev/guide/device-camera-control-demo-previewguide.md (100%) mode change 100755 => 100644 rename "zh-cn/device-dev/guide/\345\275\225\345\203\217\345\274\200\345\217\221\346\214\207\345\257\274-4.md" => zh-cn/device-dev/guide/device-camera-control-demo-videoguide.md (100%) mode change 100755 => 100644 create mode 100644 zh-cn/device-dev/guide/device-camera-control-demo.md create mode 100644 zh-cn/device-dev/guide/device-camera-control-example.md create mode 100644 zh-cn/device-dev/guide/device-camera-control-overview.md create mode 100644 zh-cn/device-dev/guide/device-camera-control.md create mode 100644 zh-cn/device-dev/guide/device-camera-visual-addpage.md create mode 100644 zh-cn/device-dev/guide/device-camera-visual-debug.md rename "zh-cn/device-dev/guide/\345\274\200\345\217\221\350\257\246\346\203\205\351\241\265.md" => zh-cn/device-dev/guide/device-camera-visual-details.md (100%) mode change 100755 => 100644 rename "zh-cn/device-dev/guide/\345\270\270\350\247\201\351\227\256\351\242\230.md" => zh-cn/device-dev/guide/device-camera-visual-faqs.md (100%) mode change 100755 => 100644 create mode 100644 zh-cn/device-dev/guide/device-camera-visual-first-page.md create mode 100644 zh-cn/device-dev/guide/device-camera-visual-overview.md create mode 100644 zh-cn/device-dev/guide/device-camera-visual-prepare.md create mode 100644 zh-cn/device-dev/guide/device-camera-visual-run.md create mode 100644 zh-cn/device-dev/guide/device-camera-visual.md create mode 100644 zh-cn/device-dev/guide/device-camera.md create mode 100644 zh-cn/device-dev/guide/device-clock-guide.md create mode 100644 zh-cn/device-dev/guide/device-drive-demo.md create mode 100644 zh-cn/device-dev/guide/device-iotcamera-control-demo-photodevguide.md rename "zh-cn/device-dev/guide/\345\275\225\345\203\217\345\274\200\345\217\221\346\214\207\345\257\274.md" => zh-cn/device-dev/guide/device-iotcamera-control-demo-videodevguide.md (100%) mode change 100755 => 100644 create mode 100644 zh-cn/device-dev/guide/device-iotcamera-control-demo.md create mode 100644 zh-cn/device-dev/guide/device-iotcamera-control-example.md create mode 100644 zh-cn/device-dev/guide/device-iotcamera-control-overview.md create mode 100644 zh-cn/device-dev/guide/device-iotcamera-control.md create mode 100644 zh-cn/device-dev/guide/device-iotcamera.md create mode 100644 zh-cn/device-dev/guide/device-outerdrive-demo.md create mode 100644 zh-cn/device-dev/guide/device-wifi-led-outcontrol.md create mode 100644 zh-cn/device-dev/guide/device-wifi-sdk.md create mode 100644 zh-cn/device-dev/guide/device-wifi.md create mode 100644 zh-cn/device-dev/guide/device.md rename zh-cn/device-dev/guide/{figures => figure}/Clock.png (100%) rename "zh-cn/device-dev/guide/figures/LED\351\227\252\347\203\201\345\233\276.gif" => "zh-cn/device-dev/guide/figure/LED\351\227\252\347\203\201\345\233\276.gif" (100%) mode change 100755 => 100644 rename zh-cn/device-dev/guide/{figures => figure}/Video_2020-07-25_173141.gif (100%) mode change 100755 => 100644 rename zh-cn/device-dev/guide/{figures => figure}/zh-cn_image_0000001078563230.png (100%) mode change 100755 => 100644 rename zh-cn/device-dev/guide/{figures => figure}/zh-cn_image_0000001082434703.png (100%) mode change 100755 => 100644 rename zh-cn/device-dev/guide/{figures/zh-cn_image_0000001161922745.png => figure/zh-cn_image_0000001169991055.png} (100%) rename "zh-cn/device-dev/guide/figures/\345\220\257\345\212\250\347\244\272\344\276\213.png" => "zh-cn/device-dev/guide/figure/\345\220\257\345\212\250\347\244\272\344\276\213.png" (100%) mode change 100755 => 100644 rename "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" => "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" (100%) mode change 100755 => 100644 rename "zh-cn/device-dev/guide/figures/\345\267\245\347\250\213\347\233\256\345\275\225.png" => "zh-cn/device-dev/guide/figure/\345\267\245\347\250\213\347\233\256\345\275\225.png" (100%) mode change 100755 => 100644 rename "zh-cn/device-dev/guide/figures/\346\237\245\347\234\213\346\226\207\344\273\266\345\233\276.png" => "zh-cn/device-dev/guide/figure/\346\237\245\347\234\213\346\226\207\344\273\266\345\233\276.png" (100%) mode change 100755 => 100644 rename "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" => "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" (100%) mode change 100755 => 100644 rename "zh-cn/device-dev/guide/figures/\346\240\207\351\242\230\346\240\217\346\225\210\346\236\234.png" => "zh-cn/device-dev/guide/figure/\346\240\207\351\242\230\346\240\217\346\225\210\346\236\234.png" (100%) mode change 100755 => 100644 rename "zh-cn/device-dev/guide/figures/\346\241\214\351\235\242.png" => "zh-cn/device-dev/guide/figure/\346\241\214\351\235\242.png" (100%) mode change 100755 => 100644 rename "zh-cn/device-dev/guide/figures/\346\267\273\345\212\240\351\241\265\351\235\242.png" => "zh-cn/device-dev/guide/figure/\346\267\273\345\212\240\351\241\265\351\235\242.png" (100%) mode change 100755 => 100644 rename "zh-cn/device-dev/guide/figures/\347\273\230\345\233\2761.png" => "zh-cn/device-dev/guide/figure/\347\273\230\345\233\2761.png" (100%) rename "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" => "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" (100%) mode change 100755 => 100644 rename "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" => "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" (100%) mode change 100755 => 100644 rename "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" => "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" (100%) mode change 100755 => 100644 rename "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" => "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" (100%) mode change 100755 => 100644 rename "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" => "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" (100%) mode change 100755 => 100644 rename "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" => "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" (100%) mode change 100755 => 100644 rename "zh-cn/device-dev/guide/figures/\351\242\204\350\247\210\346\225\210\346\236\234.jpg" => "zh-cn/device-dev/guide/figure/\351\242\204\350\247\210\346\225\210\346\236\234.jpg" (100%) mode change 100755 => 100644 delete mode 100755 zh-cn/device-dev/guide/public_sys-resources/icon-caution.gif delete mode 100755 zh-cn/device-dev/guide/public_sys-resources/icon-danger.gif delete mode 100755 zh-cn/device-dev/guide/public_sys-resources/icon-note.gif delete mode 100755 zh-cn/device-dev/guide/public_sys-resources/icon-notice.gif delete mode 100755 zh-cn/device-dev/guide/public_sys-resources/icon-tip.gif delete mode 100755 zh-cn/device-dev/guide/public_sys-resources/icon-warning.gif delete mode 100644 "zh-cn/device-dev/guide/\345\205\254\345\205\261\351\251\261\345\212\250\345\261\202\345\210\235\345\247\213\345\214\226\345\217\212\346\263\250\345\206\214\351\251\261\345\212\250\350\207\263HDF\346\241\206\346\236\266.md" delete mode 100644 "zh-cn/device-dev/guide/\345\205\267\344\275\223\350\260\203\347\224\250\351\200\273\350\276\221\344\270\262\350\201\224\345\207\275\346\225\260.md" delete mode 100644 "zh-cn/device-dev/guide/\345\231\250\344\273\266\351\251\261\345\212\250\345\261\202\345\210\235\345\247\213\345\214\226\345\217\212\346\263\250\345\206\214\351\251\261\345\212\250\350\207\263HDF\346\241\206\346\236\266.md" delete mode 100644 "zh-cn/device-dev/guide/\345\244\226\350\256\276\351\251\261\345\212\250\345\274\200\345\217\221\347\244\272\344\276\213.md" delete mode 100755 "zh-cn/device-dev/guide/\345\261\217\345\271\225\345\222\214\346\221\204\345\203\217\345\244\264\346\216\247\345\210\266.md" delete mode 100755 "zh-cn/device-dev/guide/\345\270\246\345\261\217\346\221\204\345\203\217\345\244\264\347\261\273\344\272\247\345\223\201.md" delete mode 100644 "zh-cn/device-dev/guide/\345\270\270\350\247\201\351\227\256\351\242\230-10.md" delete mode 100644 "zh-cn/device-dev/guide/\345\271\263\345\217\260\351\251\261\345\212\250\345\274\200\345\217\221\347\244\272\344\276\213.md" delete mode 100755 "zh-cn/device-dev/guide/\345\272\224\347\224\250\345\256\236\344\276\213-5.md" delete mode 100755 "zh-cn/device-dev/guide/\345\272\224\347\224\250\345\256\236\344\276\213.md" delete mode 100644 "zh-cn/device-dev/guide/\345\274\200\345\217\221-11.md" delete mode 100755 "zh-cn/device-dev/guide/\345\274\200\345\217\221.md" delete mode 100755 "zh-cn/device-dev/guide/\345\274\200\345\217\221\345\207\206\345\244\207-8.md" delete mode 100755 "zh-cn/device-dev/guide/\345\274\200\345\217\221\345\207\206\345\244\207.md" delete mode 100644 "zh-cn/device-dev/guide/\345\274\200\345\217\221\346\255\245\351\252\244.md" delete mode 100755 "zh-cn/device-dev/guide/\345\274\200\345\217\221\351\246\226\351\241\265.md" delete mode 100644 "zh-cn/device-dev/guide/\345\274\200\346\234\272\346\227\245\345\277\227\345\210\206\346\236\220.md" delete mode 100755 "zh-cn/device-dev/guide/\346\213\215\347\205\247\345\274\200\345\217\221\346\214\207\345\257\274-3.md" delete mode 100755 "zh-cn/device-dev/guide/\346\213\215\347\205\247\345\274\200\345\217\221\346\214\207\345\257\274.md" delete mode 100755 "zh-cn/device-dev/guide/\346\221\204\345\203\217\345\244\264\346\216\247\345\210\266.md" delete mode 100755 "zh-cn/device-dev/guide/\346\227\240\345\261\217\346\221\204\345\203\217\345\244\264\347\261\273\344\272\247\345\223\201.md" delete mode 100644 "zh-cn/device-dev/guide/\346\227\266\351\222\237\345\272\224\347\224\250\345\274\200\345\217\221\347\244\272\344\276\213.md" delete mode 100755 "zh-cn/device-dev/guide/\346\246\202\350\277\260-0.md" delete mode 100755 "zh-cn/device-dev/guide/\346\246\202\350\277\260-1.md" delete mode 100644 "zh-cn/device-dev/guide/\346\246\202\350\277\260-10.md" delete mode 100644 "zh-cn/device-dev/guide/\346\246\202\350\277\260-12.md" delete mode 100755 "zh-cn/device-dev/guide/\346\246\202\350\277\260-6.md" delete mode 100755 "zh-cn/device-dev/guide/\346\246\202\350\277\260-7.md" delete mode 100755 "zh-cn/device-dev/guide/\346\246\202\350\277\260.md" delete mode 100755 "zh-cn/device-dev/guide/\346\267\273\345\212\240\351\241\265\351\235\242.md" delete mode 100644 "zh-cn/device-dev/guide/\347\216\257\345\242\203\345\207\206\345\244\207.md" delete mode 100644 "zh-cn/device-dev/guide/\347\216\257\345\242\203\346\220\255\345\273\272.md" delete mode 100644 "zh-cn/device-dev/guide/\347\234\237\346\234\272\350\277\220\350\241\214-9.md" delete mode 100755 "zh-cn/device-dev/guide/\347\234\237\346\234\272\350\277\220\350\241\214.md" delete mode 100644 "zh-cn/device-dev/guide/\347\241\254\344\273\266\350\265\204\346\272\220\344\273\213\347\273\215.md" delete mode 100755 "zh-cn/device-dev/guide/\347\244\272\344\276\213\345\274\200\345\217\221-2.md" delete mode 100755 "zh-cn/device-dev/guide/\347\244\272\344\276\213\345\274\200\345\217\221.md" delete mode 100644 "zh-cn/device-dev/guide/\347\247\201\346\234\211\351\205\215\347\275\256\344\277\241\346\201\257\350\247\243\346\236\220.md" delete mode 100644 "zh-cn/device-dev/guide/\347\255\276\345\220\215\346\211\223\345\214\205.md" delete mode 100644 "zh-cn/device-dev/guide/\347\256\241\347\220\206\351\251\261\345\212\250\345\261\202\345\210\235\345\247\213\345\214\226\345\217\212\346\263\250\345\206\214\351\251\261\345\212\250\350\207\263HDF\346\241\206\346\236\266.md" delete mode 100644 "zh-cn/device-dev/guide/\347\274\226\350\257\221\345\217\212\347\203\247\345\275\225-13.md" delete mode 100644 "zh-cn/device-dev/guide/\347\274\226\350\257\221\345\217\212\347\203\247\345\275\225.md" delete mode 100755 "zh-cn/device-dev/guide/\350\247\206\350\247\211\345\272\224\347\224\250\345\274\200\345\217\221.md" delete mode 100755 "zh-cn/device-dev/guide/\350\260\203\350\257\225\346\211\223\345\214\205.md" delete mode 100644 "zh-cn/device-dev/guide/\350\260\203\350\257\225\351\252\214\350\257\201.md" delete mode 100644 "zh-cn/device-dev/guide/\351\200\202\351\205\215\345\231\250\344\273\266\347\247\201\346\234\211\351\251\261\345\212\250.md" delete mode 100644 "zh-cn/device-dev/guide/\351\205\215\347\275\256Touchscreen\345\231\250\344\273\266\344\277\241\346\201\257.md" delete mode 100644 "zh-cn/device-dev/guide/\351\205\215\347\275\256\350\256\276\345\244\207\346\217\217\350\277\260\344\277\241\346\201\257.md" delete mode 100755 "zh-cn/device-dev/guide/\351\233\206\346\210\220\344\270\211\346\226\271SDK.md" delete mode 100755 "zh-cn/device-dev/guide/\351\252\214\350\257\201.md" delete mode 100644 "zh-cn/device-dev/kernel-contribution/OpenHarmony\345\206\205\346\240\270\346\226\207\346\241\243\345\205\261\345\273\272ToDo-List.md" delete mode 100644 "zh-cn/device-dev/kernel-contribution/template/\345\270\270\350\247\201\351\227\256\351\242\230.md" delete mode 100644 "zh-cn/device-dev/kernel-contribution/template/\345\274\200\345\217\221\345\256\236\344\276\213.md" delete mode 100644 "zh-cn/device-dev/kernel-contribution/template/\345\274\200\345\217\221\346\214\207\345\257\274.md" delete mode 100644 "zh-cn/device-dev/kernel-contribution/template/\346\220\255\345\273\272\347\216\257\345\242\203.md" delete mode 100644 "zh-cn/device-dev/kernel-contribution/template/\346\246\202\350\277\260.md" delete mode 100644 "zh-cn/device-dev/kernel/C++\346\224\257\346\214\201.md" delete mode 100644 "zh-cn/device-dev/kernel/CMSIS\346\224\257\346\214\201.md" delete mode 100644 zh-cn/device-dev/kernel/FAT-20.md delete mode 100644 zh-cn/device-dev/kernel/IPC.md delete mode 100755 "zh-cn/device-dev/kernel/Linux\345\206\205\346\240\270\347\274\226\350\257\221\344\270\216\346\236\204\345\273\272\346\214\207\345\257\274.md" delete mode 100644 zh-cn/device-dev/kernel/LittleFS.md delete mode 100755 zh-cn/device-dev/kernel/NFS.md delete mode 100755 "zh-cn/device-dev/kernel/OpenHarmony\345\274\200\345\217\221\346\235\277Patch\344\275\277\347\224\250\346\214\207\345\257\274.md" delete mode 100755 "zh-cn/device-dev/kernel/Shell\344\273\213\347\273\215.md" delete mode 100755 "zh-cn/device-dev/kernel/Shell\345\221\275\344\273\244\344\275\277\347\224\250\350\257\246\350\247\243.md" delete mode 100755 "zh-cn/device-dev/kernel/Shell\345\221\275\344\273\244\345\274\200\345\217\221\346\214\207\345\257\274.md" delete mode 100755 zh-cn/device-dev/kernel/VFS.md delete mode 100755 zh-cn/device-dev/kernel/arp.md delete mode 100755 zh-cn/device-dev/kernel/cat.md delete mode 100755 zh-cn/device-dev/kernel/cd.md delete mode 100755 zh-cn/device-dev/kernel/chgrp.md delete mode 100755 zh-cn/device-dev/kernel/chmod.md delete mode 100755 zh-cn/device-dev/kernel/chown.md delete mode 100755 zh-cn/device-dev/kernel/cp.md delete mode 100755 zh-cn/device-dev/kernel/cpup.md delete mode 100755 zh-cn/device-dev/kernel/date.md delete mode 100755 zh-cn/device-dev/kernel/dhclient.md delete mode 100755 zh-cn/device-dev/kernel/dmesg.md delete mode 100755 zh-cn/device-dev/kernel/exec.md create mode 100644 "zh-cn/device-dev/kernel/figure/Cow\346\234\272\345\210\266\347\244\272\346\204\217\345\233\276.png" rename "zh-cn/device-dev/kernel/figures/PID\344\270\2723\347\232\204\350\277\233\347\250\213\350\231\232\346\213\237\345\206\205\345\255\230\344\275\277\347\224\250\344\277\241\346\201\257.png" => "zh-cn/device-dev/kernel/figure/PID\344\270\2723\347\232\204\350\277\233\347\250\213\350\231\232\346\213\237\345\206\205\345\255\230\344\275\277\347\224\250\344\277\241\346\201\257.png" (100%) mode change 100755 => 100644 rename "zh-cn/device-dev/kernel/figures/POSIX\346\216\245\345\217\243\346\241\206\346\236\266.png" => "zh-cn/device-dev/kernel/figure/POSIX\346\216\245\345\217\243\346\241\206\346\236\266.png" (100%) mode change 100755 => 100644 rename zh-cn/device-dev/kernel/{figures/Snipaste_2021-01-26_10-38-58-1.png => figure/Snipaste_2021-01-26_10-38-58-18.png} (100%) mode change 100755 => 100644 rename zh-cn/device-dev/kernel/{figures/Snipaste_2021-01-26_10-38-58-2.png => figure/Snipaste_2021-01-26_10-38-58-19.png} (100%) mode change 100755 => 100644 rename zh-cn/device-dev/kernel/{figures => figure}/Snipaste_2021-01-26_10-38-58.png (100%) mode change 100755 => 100644 rename "zh-cn/device-dev/kernel/figures/VFS\345\222\214\345\220\204\344\270\252\346\226\207\344\273\266\347\263\273\347\273\237\347\232\204\345\205\263\347\263\273.png" => "zh-cn/device-dev/kernel/figure/VFS\345\222\214\345\220\204\344\270\252\346\226\207\344\273\266\347\263\273\347\273\237\347\232\204\345\205\263\347\263\273.png" (100%) mode change 100755 => 100644 rename "zh-cn/device-dev/kernel/figures/dmesg\351\207\215\345\256\232\345\220\221\345\210\260\346\226\207\344\273\266.png" => "zh-cn/device-dev/kernel/figure/dmesg\351\207\215\345\256\232\345\220\221\345\210\260\346\226\207\344\273\266.png" (100%) mode change 100755 => 100644 rename "zh-cn/device-dev/kernel/figures/lsfd\350\276\223\345\207\272\350\257\264\346\230\216.png" => "zh-cn/device-dev/kernel/figure/lsfd\350\276\223\345\207\272\350\257\264\346\230\216.png" (100%) mode change 100755 => 100644 rename "zh-cn/device-dev/kernel/figures/statfs\350\276\223\345\207\272\350\257\264\346\230\216.png" => "zh-cn/device-dev/kernel/figure/statfs\350\276\223\345\207\272\350\257\264\346\230\216.png" (100%) mode change 100755 => 100644 rename "zh-cn/device-dev/kernel/figures/umount\350\276\223\345\207\272\347\244\272\344\276\213.png" => "zh-cn/device-dev/kernel/figure/umount\350\276\223\345\207\272\347\244\272\344\276\213.png" (100%) mode change 100755 => 100644 rename "zh-cn/device-dev/kernel/figures/watch-task-\347\273\223\346\236\234.png" => "zh-cn/device-dev/kernel/figure/watch-task-\347\273\223\346\236\234.png" (100%) mode change 100755 => 100644 rename zh-cn/device-dev/kernel/{figures => figure}/zh-cn_image_0000001051690323.png (100%) mode change 100755 => 100644 rename zh-cn/device-dev/kernel/{figures => figure}/zh-cn_image_0000001052370303.png (100%) mode change 100755 => 100644 rename zh-cn/device-dev/kernel/{figures => figure}/zh-cn_image_0000001052370305.png (100%) mode change 100755 => 100644 rename zh-cn/device-dev/kernel/{figures => figure}/zh-cn_image_0000001052370307.png (100%) mode change 100755 => 100644 rename zh-cn/device-dev/kernel/{figures => figure}/zh-cn_image_0000001052530298.png (100%) mode change 100755 => 100644 rename zh-cn/device-dev/kernel/{figures => figure}/zh-cn_image_0000001052810300.png (100%) mode change 100755 => 100644 rename zh-cn/device-dev/kernel/{figures => figure}/zh-cn_image_0000001052810304.png (100%) mode change 100755 => 100644 rename zh-cn/device-dev/kernel/{figures => figure}/zh-cn_image_0000001053224218.png (100%) mode change 100755 => 100644 rename zh-cn/device-dev/kernel/{figures => figure}/zh-cn_image_0000001053710680.png (100%) mode change 100755 => 100644 rename zh-cn/device-dev/kernel/{figures => figure}/zh-cn_image_0000001053826366.png (100%) mode change 100755 => 100644 rename zh-cn/device-dev/kernel/{figures => figure}/zh-cn_image_0000001054624363.png (100%) mode change 100755 => 100644 rename zh-cn/device-dev/kernel/{figures => figure}/zh-cn_image_0000001121429646.png (100%) rename zh-cn/device-dev/kernel/{figures => figure}/zh-cn_image_0000001124146302.png (100%) rename zh-cn/device-dev/kernel/{figures => figure}/zh-cn_image_0000001124147160.png (100%) rename zh-cn/device-dev/kernel/{figures => figure}/zh-cn_image_0000001124306828.png (100%) rename zh-cn/device-dev/kernel/{figures => figure}/zh-cn_image_0000001124307264.png (100%) rename zh-cn/device-dev/kernel/{figures => figure}/zh-cn_image_0000001124310992.png (100%) create mode 100644 zh-cn/device-dev/kernel/figure/zh-cn_image_0000001132085260.png create mode 100644 zh-cn/device-dev/kernel/figure/zh-cn_image_0000001132778524.png create mode 100644 zh-cn/device-dev/kernel/figure/zh-cn_image_0000001132935054.png rename zh-cn/device-dev/kernel/{figures => figure}/zh-cn_image_0000001170790681.png (100%) rename "zh-cn/device-dev/kernel/figures/\344\272\213\344\273\266\350\277\220\344\275\234\345\216\237\347\220\206\345\233\276.png" => "zh-cn/device-dev/kernel/figure/\344\272\213\344\273\266\350\277\220\344\275\234\345\216\237\347\220\206\345\233\276.png" (100%) create mode 100644 "zh-cn/device-dev/kernel/figure/\344\272\222\346\226\245\351\224\201\350\277\220\344\275\234\347\244\272\346\204\217\345\233\276.png" rename "zh-cn/device-dev/kernel/figures/\344\273\245\344\270\211\347\247\215\346\226\271\345\274\217\346\230\276\347\244\272\345\206\205\345\255\230\344\275\277\347\224\250\346\203\205\345\206\265.png" => "zh-cn/device-dev/kernel/figure/\344\273\245\344\270\211\347\247\215\346\226\271\345\274\217\346\230\276\347\244\272\345\206\205\345\255\230\344\275\277\347\224\250\346\203\205\345\206\265.png" (100%) mode change 100755 => 100644 create mode 100644 "zh-cn/device-dev/kernel/figure/\344\273\273\345\212\241\347\212\266\346\200\201\347\244\272\346\204\217\345\233\276.png" rename "zh-cn/device-dev/kernel/figures/\344\277\241\345\217\267\345\217\221\351\200\201\345\244\261\350\264\245.png" => "zh-cn/device-dev/kernel/figure/\344\277\241\345\217\267\345\217\221\351\200\201\345\244\261\350\264\245.png" (100%) mode change 100755 => 100644 rename "zh-cn/device-dev/kernel/figures/\344\277\241\345\217\267\345\217\221\351\200\201\347\273\223\346\236\234\345\233\276.png" => "zh-cn/device-dev/kernel/figure/\344\277\241\345\217\267\345\217\221\351\200\201\347\273\223\346\236\234\345\233\276.png" (100%) mode change 100755 => 100644 create mode 100644 "zh-cn/device-dev/kernel/figure/\344\277\241\345\217\267\351\207\217\350\277\220\344\275\234\347\244\272\346\204\217\345\233\276.png" rename "zh-cn/device-dev/kernel/figures/\344\277\256\346\224\271-hello-harmony-txt-\346\226\207\344\273\266\347\232\204uid\344\270\272100-gid\344\270\272200.png" => "zh-cn/device-dev/kernel/figure/\344\277\256\346\224\271-hello-harmony-txt-\346\226\207\344\273\266\347\232\204uid\344\270\272100-gid\344\270\272200.png" (100%) mode change 100755 => 100644 rename "zh-cn/device-dev/kernel/figures/\344\277\256\346\224\271-hello-harmony-txt-\346\226\207\344\273\266\347\232\204\346\235\203\351\231\220\344\270\272666.png" => "zh-cn/device-dev/kernel/figure/\344\277\256\346\224\271-hello-harmony-txt-\346\226\207\344\273\266\347\232\204\346\235\203\351\231\220\344\270\272666.png" (100%) mode change 100755 => 100644 rename "zh-cn/device-dev/kernel/figures/\344\277\256\346\224\271-hello-harmony-txt-\346\226\207\344\273\266\347\232\204\347\276\244\347\273\204\344\270\272100.png" => "zh-cn/device-dev/kernel/figure/\344\277\256\346\224\271-hello-harmony-txt-\346\226\207\344\273\266\347\232\204\347\276\244\347\273\204\344\270\272100.png" (100%) mode change 100755 => 100644 create mode 100644 "zh-cn/device-dev/kernel/figure/\345\205\203\346\225\260\346\215\256\345\255\230\345\202\250\347\244\272\346\204\217\345\233\276.png" create mode 100644 "zh-cn/device-dev/kernel/figure/\345\206\205\346\240\270\345\220\257\345\212\250\346\265\201\347\250\213.png" rename "zh-cn/device-dev/kernel/figures/\345\206\205\346\240\270\346\236\266\346\236\204\345\233\276.png" => "zh-cn/device-dev/kernel/figure/\345\206\205\346\240\270\346\236\266\346\236\204\345\233\276.png" (100%) rename "zh-cn/device-dev/kernel/figures/\345\207\272\347\216\260\345\206\205\345\255\230\350\266\212\347\225\214.png" => "zh-cn/device-dev/kernel/figure/\345\207\272\347\216\260\345\206\205\345\255\230\350\266\212\347\225\214.png" (100%) mode change 100755 => 100644 rename "zh-cn/device-dev/kernel/figures/\345\210\207\346\215\242\345\210\260\344\270\272uid\344\270\2721000-gid\344\270\2721000\347\232\204\347\224\250\346\210\267.png" => "zh-cn/device-dev/kernel/figure/\345\210\207\346\215\242\345\210\260\344\270\272uid\344\270\2721000-gid\344\270\2721000\347\232\204\347\224\250\346\210\267.png" (100%) mode change 100755 => 100644 rename "zh-cn/device-dev/kernel/figures/\345\210\233\345\273\272-share-\347\233\256\345\275\225.png" => "zh-cn/device-dev/kernel/figure/\345\210\233\345\273\272-share-\347\233\256\345\275\225.png" (100%) mode change 100755 => 100644 rename "zh-cn/device-dev/kernel/figures/\345\210\233\345\273\272\344\270\200\344\270\252\345\220\215\344\270\272-file-c-\347\232\204\346\226\207\344\273\266.png" => "zh-cn/device-dev/kernel/figure/\345\210\233\345\273\272\344\270\200\344\270\252\345\220\215\344\270\272-file-c-\347\232\204\346\226\207\344\273\266.png" (100%) mode change 100755 => 100644 rename "zh-cn/device-dev/kernel/figures/\345\210\240\351\231\244\344\270\200\344\270\252\345\220\215\344\270\272-dir-\347\232\204\347\233\256\345\275\225.png" => "zh-cn/device-dev/kernel/figure/\345\210\240\351\231\244\344\270\200\344\270\252\345\220\215\344\270\272-dir-\347\232\204\347\233\256\345\275\225.png" (100%) mode change 100755 => 100644 create mode 100644 "zh-cn/device-dev/kernel/figure/\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" create mode 100644 "zh-cn/device-dev/kernel/figure/\345\212\250\346\200\201\345\206\205\345\255\230\347\256\241\347\220\206\347\273\223\346\236\204\345\233\276.png" rename "zh-cn/device-dev/kernel/figures/\345\217\221\351\200\201\344\277\241\345\217\267\347\273\231\346\214\207\345\256\232\350\277\233\347\250\213.png" => "zh-cn/device-dev/kernel/figure/\345\217\221\351\200\201\344\277\241\345\217\267\347\273\231\346\214\207\345\256\232\350\277\233\347\250\213.png" (100%) mode change 100755 => 100644 create mode 100644 "zh-cn/device-dev/kernel/figure/\345\240\206\346\240\210\345\210\206\346\236\220\345\216\237\347\220\206\347\244\272\346\204\217\345\233\276.png" rename "zh-cn/device-dev/kernel/figures/\345\275\223\345\211\215\346\262\241\346\234\211\345\206\205\345\255\230\350\266\212\347\225\214.png" => "zh-cn/device-dev/kernel/figure/\345\275\223\345\211\215\346\262\241\346\234\211\345\206\205\345\255\230\350\266\212\347\225\214.png" (100%) mode change 100755 => 100644 rename "zh-cn/device-dev/kernel/figures/\346\214\207\344\273\244\350\276\223\345\207\272\347\273\223\346\236\234.png" => "zh-cn/device-dev/kernel/figure/\346\214\207\344\273\244\350\276\223\345\207\272\347\273\223\346\236\234.png" (100%) mode change 100755 => 100644 rename "zh-cn/device-dev/kernel/figures/\346\214\211\346\214\207\345\256\232\346\240\274\345\274\217\346\211\223\345\215\260\347\263\273\347\273\237\346\227\245\346\234\237.png" => "zh-cn/device-dev/kernel/figure/\346\214\211\346\214\207\345\256\232\346\240\274\345\274\217\346\211\223\345\215\260\347\263\273\347\273\237\346\227\245\346\234\237.png" (100%) mode change 100755 => 100644 rename "zh-cn/device-dev/kernel/figures/\346\226\207\344\273\266\347\263\273\347\273\237\346\240\221\345\275\242\347\273\223\346\236\204.png" => "zh-cn/device-dev/kernel/figure/\346\226\207\344\273\266\347\263\273\347\273\237\346\240\221\345\275\242\347\273\223\346\236\204.png" (100%) mode change 100755 => 100644 create mode 100644 "zh-cn/device-dev/kernel/figure/\346\227\245\345\277\227\346\226\271\345\274\217\347\244\272\346\204\217\345\233\276.png" rename "zh-cn/device-dev/kernel/figures/\346\230\276\347\244\272\347\273\223\346\236\234\345\246\202\344\270\213-0.png" => "zh-cn/device-dev/kernel/figure/\346\230\276\347\244\272\347\273\223\346\236\234\345\246\202\344\270\213-17.png" (100%) mode change 100755 => 100644 rename "zh-cn/device-dev/kernel/figures/\346\230\276\347\244\272\347\273\223\346\236\234\345\246\202\344\270\213.png" => "zh-cn/device-dev/kernel/figure/\346\230\276\347\244\272\347\273\223\346\236\234\345\246\202\344\270\213.png" (100%) mode change 100755 => 100644 rename "zh-cn/device-dev/kernel/figures/\346\237\245\347\234\213-hello-harmony-txt-\346\226\207\344\273\266\347\232\204\344\277\241\346\201\257.png" => "zh-cn/device-dev/kernel/figure/\346\237\245\347\234\213-hello-harmony-txt-\346\226\207\344\273\266\347\232\204\344\277\241\346\201\257.png" (100%) mode change 100755 => 100644 rename "zh-cn/device-dev/kernel/figures/\346\237\245\347\234\213\345\275\223\345\211\215\347\263\273\347\273\237\350\267\257\345\276\204\344\270\213\347\232\204\347\233\256\345\275\225-\346\230\276\347\244\272\347\232\204\345\206\205\345\256\271\345\246\202\344\270\213.png" => "zh-cn/device-dev/kernel/figure/\346\237\245\347\234\213\345\275\223\345\211\215\347\263\273\347\273\237\350\267\257\345\276\204\344\270\213\347\232\204\347\233\256\345\275\225-\346\230\276\347\244\272\347\232\204\345\206\205\345\256\271\345\246\202\344\270\213.png" (100%) mode change 100755 => 100644 rename "zh-cn/device-dev/kernel/figures/\346\237\245\347\234\213\345\275\223\345\211\215\350\267\257\345\276\204.png" => "zh-cn/device-dev/kernel/figure/\346\237\245\347\234\213\345\275\223\345\211\215\350\267\257\345\276\204.png" (100%) mode change 100755 => 100644 rename "zh-cn/device-dev/kernel/figures/\346\237\245\347\234\213\347\211\251\347\220\206\351\241\265\344\275\277\347\224\250\346\203\205\345\206\265.png" => "zh-cn/device-dev/kernel/figure/\346\237\245\347\234\213\347\211\251\347\220\206\351\241\265\344\275\277\347\224\250\346\203\205\345\206\265.png" (100%) mode change 100755 => 100644 rename "zh-cn/device-dev/kernel/figures/\346\237\245\347\234\213\347\263\273\347\273\237\350\265\204\346\272\220\344\275\277\347\224\250\346\203\205\345\206\265.png" => "zh-cn/device-dev/kernel/figure/\346\237\245\347\234\213\347\263\273\347\273\237\350\265\204\346\272\220\344\275\277\347\224\250\346\203\205\345\206\265.png" (100%) mode change 100755 => 100644 rename "zh-cn/device-dev/kernel/figures/\346\237\245\347\234\213\350\277\233\347\250\213PID.png" => "zh-cn/device-dev/kernel/figure/\346\237\245\347\234\213\350\277\233\347\250\213PID.png" (100%) mode change 100755 => 100644 rename "zh-cn/device-dev/kernel/figures/\346\237\245\350\257\242\344\273\273\345\212\241\351\203\250\345\210\206\344\277\241\346\201\257.png" => "zh-cn/device-dev/kernel/figure/\346\237\245\350\257\242\344\273\273\345\212\241\351\203\250\345\210\206\344\277\241\346\201\257.png" (100%) mode change 100755 => 100644 rename "zh-cn/device-dev/kernel/figures/\346\237\245\350\257\242\345\257\271\345\272\224-ID-\347\232\204\350\275\257\344\273\266\345\256\232\346\227\266\345\231\250\344\277\241\346\201\257.png" => "zh-cn/device-dev/kernel/figure/\346\237\245\350\257\242\345\257\271\345\272\224-ID-\347\232\204\350\275\257\344\273\266\345\256\232\346\227\266\345\231\250\344\277\241\346\201\257.png" (100%) mode change 100755 => 100644 rename "zh-cn/device-dev/kernel/figures/\346\237\245\350\257\242\346\211\200\346\234\211\345\234\250\347\224\250\347\232\204\344\277\241\345\217\267\351\207\217\344\277\241\346\201\257.png" => "zh-cn/device-dev/kernel/figure/\346\237\245\350\257\242\346\211\200\346\234\211\345\234\250\347\224\250\347\232\204\344\277\241\345\217\267\351\207\217\344\277\241\346\201\257.png" (100%) mode change 100755 => 100644 rename "zh-cn/device-dev/kernel/figures/\346\237\245\350\257\242\346\211\200\346\234\211\350\275\257\344\273\266\345\256\232\346\227\266\345\231\250\347\233\270\345\205\263\344\277\241\346\201\257.png" => "zh-cn/device-dev/kernel/figure/\346\237\245\350\257\242\346\211\200\346\234\211\350\275\257\344\273\266\345\256\232\346\227\266\345\231\250\347\233\270\345\205\263\344\277\241\346\201\257.png" (100%) mode change 100755 => 100644 rename "zh-cn/device-dev/kernel/figures/\347\224\250-rm--r-\345\210\240\351\231\244\347\233\256\345\275\225-sd.png" => "zh-cn/device-dev/kernel/figure/\347\224\250-rm--r-\345\210\240\351\231\244\347\233\256\345\275\225-sd.png" (100%) mode change 100755 => 100644 rename "zh-cn/device-dev/kernel/figures/\347\224\250-rm-\345\221\275\344\273\244\345\210\240\351\231\244\346\226\207\344\273\266-log1-txt.png" => "zh-cn/device-dev/kernel/figure/\347\224\250-rm-\345\221\275\344\273\244\345\210\240\351\231\244\346\226\207\344\273\266-log1-txt.png" (100%) mode change 100755 => 100644 rename "zh-cn/device-dev/kernel/figures/\347\272\277\347\250\213\347\212\266\346\200\201\350\277\201\347\247\273\347\244\272\346\204\217\345\233\276.png" => "zh-cn/device-dev/kernel/figure/\347\272\277\347\250\213\347\212\266\346\200\201\350\277\201\347\247\273\347\244\272\346\204\217\345\233\276.png" (100%) mode change 100755 => 100644 rename "zh-cn/device-dev/kernel/figures/\350\276\223\345\205\245-telnet-on.png" => "zh-cn/device-dev/kernel/figure/\350\276\223\345\205\245-telnet-on.png" (100%) mode change 100755 => 100644 rename "zh-cn/device-dev/kernel/figures/\350\277\233\347\250\213\347\212\266\346\200\201\350\277\201\347\247\273\347\244\272\346\204\217\345\233\276.png" => "zh-cn/device-dev/kernel/figure/\350\277\233\347\250\213\347\212\266\346\200\201\350\277\201\347\247\273\347\244\272\346\204\217\345\233\276.png" (100%) mode change 100755 => 100644 create mode 100644 "zh-cn/device-dev/kernel/figure/\351\235\231\346\200\201\345\206\205\345\255\230\347\244\272\346\204\217\345\233\276.png" delete mode 100644 "zh-cn/device-dev/kernel/figures/\344\272\222\346\226\245\351\224\201\350\277\220\344\275\234\347\244\272\346\204\217\345\233\276.png" delete mode 100644 "zh-cn/device-dev/kernel/figures/\344\273\273\345\212\241\347\212\266\346\200\201\347\244\272\346\204\217\345\233\276.png" delete mode 100644 "zh-cn/device-dev/kernel/figures/\344\277\241\345\217\267\351\207\217\350\277\220\344\275\234\347\244\272\346\204\217\345\233\276.png" delete mode 100644 "zh-cn/device-dev/kernel/figures/\345\206\205\346\240\270\345\220\257\345\212\250\346\265\201\347\250\213.png" delete mode 100644 "zh-cn/device-dev/kernel/figures/\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" delete mode 100644 "zh-cn/device-dev/kernel/figures/\345\212\250\346\200\201\345\206\205\345\255\230\347\256\241\347\220\206\347\273\223\346\236\204\345\233\276.png" delete mode 100644 "zh-cn/device-dev/kernel/figures/\345\240\206\346\240\210\345\210\206\346\236\220\345\216\237\347\220\206\347\244\272\346\204\217\345\233\276.png" delete mode 100644 "zh-cn/device-dev/kernel/figures/\351\235\231\346\200\201\345\206\205\345\255\230\347\244\272\346\204\217\345\233\276.png" delete mode 100755 zh-cn/device-dev/kernel/format.md delete mode 100755 zh-cn/device-dev/kernel/free.md delete mode 100755 zh-cn/device-dev/kernel/hwi.md create mode 100644 zh-cn/device-dev/kernel/kernel-lite-basic-mini-time.md rename "zh-cn/device-dev/kernel/\345\206\205\346\240\270\347\274\226\347\240\201\350\247\204\350\214\203.md" => zh-cn/device-dev/kernel/kernel-lite-mini-app-code.md (100%) create mode 100644 zh-cn/device-dev/kernel/kernel-lite-mini-app-data-list.md create mode 100644 zh-cn/device-dev/kernel/kernel-lite-mini-app-data.md create mode 100644 zh-cn/device-dev/kernel/kernel-lite-mini-app-lib-cmsis.md rename "zh-cn/device-dev/kernel/POSIX\346\224\257\346\214\201.md" => zh-cn/device-dev/kernel/kernel-lite-mini-app-lib-posix.md (100%) create mode 100644 zh-cn/device-dev/kernel/kernel-lite-mini-app-lib.md create mode 100644 zh-cn/device-dev/kernel/kernel-lite-mini-app.md rename "zh-cn/device-dev/kernel/\345\237\272\346\234\254\346\246\202\345\277\265.md" => zh-cn/device-dev/kernel/kernel-lite-mini-basic-interrupt-concept.md (100%) create mode 100644 zh-cn/device-dev/kernel/kernel-lite-mini-basic-interrupt-guide.md create mode 100644 zh-cn/device-dev/kernel/kernel-lite-mini-basic-interrupt.md create mode 100644 zh-cn/device-dev/kernel/kernel-lite-mini-basic-ipc-event-basic.md create mode 100644 zh-cn/device-dev/kernel/kernel-lite-mini-basic-ipc-event-guide.md create mode 100644 zh-cn/device-dev/kernel/kernel-lite-mini-basic-ipc-event.md create mode 100644 zh-cn/device-dev/kernel/kernel-lite-mini-basic-ipc-mutex-basic.md create mode 100644 zh-cn/device-dev/kernel/kernel-lite-mini-basic-ipc-mutex-guide.md create mode 100644 zh-cn/device-dev/kernel/kernel-lite-mini-basic-ipc-mutex.md create mode 100644 zh-cn/device-dev/kernel/kernel-lite-mini-basic-ipc-queue-basic.md create mode 100644 zh-cn/device-dev/kernel/kernel-lite-mini-basic-ipc-queue-guide.md create mode 100644 zh-cn/device-dev/kernel/kernel-lite-mini-basic-ipc-queue.md create mode 100644 zh-cn/device-dev/kernel/kernel-lite-mini-basic-ipc-sem-basic.md create mode 100644 zh-cn/device-dev/kernel/kernel-lite-mini-basic-ipc-sem-guide.md create mode 100644 zh-cn/device-dev/kernel/kernel-lite-mini-basic-ipc-sem.md create mode 100644 zh-cn/device-dev/kernel/kernel-lite-mini-basic-ipc.md rename "zh-cn/device-dev/kernel/\345\237\272\346\234\254\346\246\202\345\277\265-4.md" => zh-cn/device-dev/kernel/kernel-lite-mini-basic-memory-basic.md (100%) create mode 100644 zh-cn/device-dev/kernel/kernel-lite-mini-basic-memory-dynamic.md create mode 100644 zh-cn/device-dev/kernel/kernel-lite-mini-basic-memory-static.md create mode 100644 zh-cn/device-dev/kernel/kernel-lite-mini-basic-memory.md rename "zh-cn/device-dev/kernel/\345\237\272\346\234\254\346\246\202\345\277\265-15.md" => zh-cn/device-dev/kernel/kernel-lite-mini-basic-soft-basic.md (100%) create mode 100644 zh-cn/device-dev/kernel/kernel-lite-mini-basic-soft-guide.md create mode 100644 zh-cn/device-dev/kernel/kernel-lite-mini-basic-soft.md create mode 100644 zh-cn/device-dev/kernel/kernel-lite-mini-basic-task-basic.md create mode 100644 zh-cn/device-dev/kernel/kernel-lite-mini-basic-task-guide.md create mode 100644 zh-cn/device-dev/kernel/kernel-lite-mini-basic-task.md rename "zh-cn/device-dev/kernel/\345\237\272\346\234\254\346\246\202\345\277\265-13.md" => zh-cn/device-dev/kernel/kernel-lite-mini-basic-time-basic.md (100%) create mode 100644 zh-cn/device-dev/kernel/kernel-lite-mini-basic-time-guide.md create mode 100644 zh-cn/device-dev/kernel/kernel-lite-mini-basic.md rename "zh-cn/device-dev/kernel/\345\237\272\346\234\254\346\246\202\345\277\265-17.md" => zh-cn/device-dev/kernel/kernel-lite-mini-extend-cpup-basic.md (100%) rename "zh-cn/device-dev/kernel/\345\274\200\345\217\221\346\214\207\345\257\274-18.md" => zh-cn/device-dev/kernel/kernel-lite-mini-extend-cpup-guide.md (100%) create mode 100644 zh-cn/device-dev/kernel/kernel-lite-mini-extend-cpup.md create mode 100644 zh-cn/device-dev/kernel/kernel-lite-mini-extend-file-fat.md create mode 100644 zh-cn/device-dev/kernel/kernel-lite-mini-extend-file-lit-basic.md rename "zh-cn/device-dev/kernel/\345\274\200\345\217\221\346\214\207\345\257\274-22.md" => zh-cn/device-dev/kernel/kernel-lite-mini-extend-file-lit-guide.md (100%) create mode 100644 zh-cn/device-dev/kernel/kernel-lite-mini-extend-file-lit.md create mode 100644 zh-cn/device-dev/kernel/kernel-lite-mini-extend-file.md create mode 100644 zh-cn/device-dev/kernel/kernel-lite-mini-extend-support.md create mode 100644 zh-cn/device-dev/kernel/kernel-lite-mini-extend.md create mode 100644 zh-cn/device-dev/kernel/kernel-lite-mini-inner-debug-cet.md create mode 100644 zh-cn/device-dev/kernel/kernel-lite-mini-inner-debug-det.md create mode 100644 zh-cn/device-dev/kernel/kernel-lite-mini-inner-debug-mes.md create mode 100644 zh-cn/device-dev/kernel/kernel-lite-mini-inner-debug.md create mode 100644 zh-cn/device-dev/kernel/kernel-lite-mini-inner-exception.md rename "zh-cn/device-dev/kernel/Trace\350\260\203\346\265\213.md" => zh-cn/device-dev/kernel/kernel-lite-mini-inner-trace.md (100%) create mode 100644 zh-cn/device-dev/kernel/kernel-lite-mini-inner.md create mode 100644 zh-cn/device-dev/kernel/kernel-lite-mini-m.md create mode 100644 zh-cn/device-dev/kernel/kernel-lite-mini-start.md create mode 100644 zh-cn/device-dev/kernel/kernel-lite-mini.md create mode 100644 zh-cn/device-dev/kernel/kernel-lite-small-basic.md rename zh-cn/device-dev/kernel/{FAT.md => kernel-lite-small-file-fat.md} (100%) mode change 100755 => 100644 rename zh-cn/device-dev/kernel/{JFFS2.md => kernel-lite-small-file-jffs.md} (100%) mode change 100755 => 100644 create mode 100644 zh-cn/device-dev/kernel/kernel-lite-small-file-nfs.md rename zh-cn/device-dev/kernel/{RAMFS.md => kernel-lite-small-file-ramfs.md} (100%) mode change 100755 => 100644 create mode 100644 zh-cn/device-dev/kernel/kernel-lite-small-file-vfs.md create mode 100644 zh-cn/device-dev/kernel/kernel-lite-small-file.md rename "zh-cn/device-dev/kernel/\344\270\216Linux\346\240\207\345\207\206\345\272\223\347\232\204\345\267\256\345\274\202.md" => zh-cn/device-dev/kernel/kernel-lite-small-lib-differ.md (100%) mode change 100755 => 100644 create mode 100644 zh-cn/device-dev/kernel/kernel-lite-small-lib-standard.md create mode 100644 zh-cn/device-dev/kernel/kernel-lite-small-lib.md create mode 100644 zh-cn/device-dev/kernel/kernel-lite-small-memory.md create mode 100644 zh-cn/device-dev/kernel/kernel-lite-small-net.md create mode 100644 zh-cn/device-dev/kernel/kernel-lite-small-process.md rename "zh-cn/device-dev/kernel/\347\224\250\346\210\267\346\200\201\345\274\202\345\270\270\344\277\241\346\201\257\350\257\264\346\230\216.md" => zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-abn.md (100%) mode change 100755 => 100644 create mode 100644 zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file-cat.md create mode 100644 zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file-cd.md create mode 100644 zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file-chgrp.md create mode 100644 zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file-chmod.md create mode 100644 zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file-chown.md create mode 100644 zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file-cp.md create mode 100644 zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file-format.md create mode 100644 zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file-is.md create mode 100644 zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file-isfd.md create mode 100644 zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file-mkdir.md create mode 100644 zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file-mount.md create mode 100644 zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file-part.md create mode 100644 zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file-partion.md create mode 100644 zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file-pwd.md create mode 100644 zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file-rm.md create mode 100644 zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file-rmdir.md create mode 100644 zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file-sta.md rename zh-cn/device-dev/kernel/{sync.md => kernel-lite-small-shell-cmd-file-sync.md} (100%) mode change 100755 => 100644 create mode 100644 zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file-touch.md create mode 100644 zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file-umount.md create mode 100644 zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file-write.md create mode 100644 zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file.md create mode 100644 zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-mag.md create mode 100644 zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-net-arp.md create mode 100644 zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-net-dh.md rename zh-cn/device-dev/kernel/{dns.md => kernel-lite-small-shell-cmd-net-dns.md} (100%) mode change 100755 => 100644 rename zh-cn/device-dev/kernel/{ifconfig.md => kernel-lite-small-shell-cmd-net-ipc.md} (100%) mode change 100755 => 100644 rename zh-cn/device-dev/kernel/{ipdebug.md => kernel-lite-small-shell-cmd-net-ipd.md} (100%) mode change 100755 => 100644 create mode 100644 zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-net-net.md rename zh-cn/device-dev/kernel/{ntpdate.md => kernel-lite-small-shell-cmd-net-ntp.md} (100%) mode change 100755 => 100644 create mode 100644 zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-net-ping.md rename zh-cn/device-dev/kernel/{ping6.md => kernel-lite-small-shell-cmd-net-ping6.md} (100%) mode change 100755 => 100644 create mode 100644 zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-net-tel.md create mode 100644 zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-net-tftp.md create mode 100644 zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-net.md create mode 100644 zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys-cpup.md create mode 100644 zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys-date.md create mode 100644 zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys-demsg.md create mode 100644 zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys-exec.md create mode 100644 zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys-free.md rename zh-cn/device-dev/kernel/{help.md => kernel-lite-small-shell-cmd-sys-help.md} (100%) mode change 100755 => 100644 create mode 100644 zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys-hwi.md create mode 100644 zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys-kill.md create mode 100644 zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys-log.md create mode 100644 zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys-mem.md create mode 100644 zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys-oom.md create mode 100644 zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys-pmm.md rename zh-cn/device-dev/kernel/{reset.md => kernel-lite-small-shell-cmd-sys-reset.md} (100%) mode change 100755 => 100644 create mode 100644 zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys-sem.md create mode 100644 zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys-stack.md create mode 100644 zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys-su.md create mode 100644 zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys-swymr.md create mode 100644 zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys-sys.md create mode 100644 zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys-task.md create mode 100644 zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys-uname.md create mode 100644 zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys-vmm.md create mode 100644 zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys-watch.md create mode 100644 zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys.md create mode 100644 zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd.md create mode 100644 zh-cn/device-dev/kernel/kernel-lite-small-shell-des.md create mode 100644 zh-cn/device-dev/kernel/kernel-lite-small-shell-guide.md rename "zh-cn/device-dev/kernel/Shell\345\221\275\344\273\244\347\274\226\347\250\213\345\256\236\344\276\213.md" => zh-cn/device-dev/kernel/kernel-lite-small-shell-sample.md (100%) mode change 100755 => 100644 create mode 100644 zh-cn/device-dev/kernel/kernel-lite-small-shell.md create mode 100644 zh-cn/device-dev/kernel/kernel-lite-small-thread.md create mode 100644 zh-cn/device-dev/kernel/kernel-lite-small.md create mode 100644 zh-cn/device-dev/kernel/kernel-lite.md create mode 100644 zh-cn/device-dev/kernel/kernel-standard-build.md rename "zh-cn/device-dev/kernel/Linux\345\206\205\346\240\270\346\246\202\350\277\260.md" => zh-cn/device-dev/kernel/kernel-standard-des.md (100%) mode change 100755 => 100644 create mode 100644 zh-cn/device-dev/kernel/kernel-standard-patch.md create mode 100644 zh-cn/device-dev/kernel/kernel-standard.md create mode 100644 zh-cn/device-dev/kernel/kernel.md delete mode 100755 zh-cn/device-dev/kernel/kill.md delete mode 100755 zh-cn/device-dev/kernel/log.md delete mode 100755 zh-cn/device-dev/kernel/ls.md delete mode 100755 zh-cn/device-dev/kernel/lsfd.md delete mode 100755 zh-cn/device-dev/kernel/memcheck.md delete mode 100755 zh-cn/device-dev/kernel/mkdir.md delete mode 100755 zh-cn/device-dev/kernel/mount.md delete mode 100755 zh-cn/device-dev/kernel/netstat.md delete mode 100755 zh-cn/device-dev/kernel/oom.md delete mode 100755 zh-cn/device-dev/kernel/partinfo.md delete mode 100755 zh-cn/device-dev/kernel/partition.md delete mode 100755 zh-cn/device-dev/kernel/ping.md delete mode 100755 zh-cn/device-dev/kernel/pmm.md delete mode 100755 zh-cn/device-dev/kernel/public_sys-resources/icon-caution.gif delete mode 100755 zh-cn/device-dev/kernel/public_sys-resources/icon-danger.gif delete mode 100755 zh-cn/device-dev/kernel/public_sys-resources/icon-note.gif delete mode 100755 zh-cn/device-dev/kernel/public_sys-resources/icon-notice.gif delete mode 100755 zh-cn/device-dev/kernel/public_sys-resources/icon-tip.gif delete mode 100755 zh-cn/device-dev/kernel/public_sys-resources/icon-warning.gif delete mode 100755 zh-cn/device-dev/kernel/pwd.md delete mode 100755 zh-cn/device-dev/kernel/rm.md delete mode 100755 zh-cn/device-dev/kernel/rmdir.md delete mode 100755 zh-cn/device-dev/kernel/sem.md delete mode 100755 zh-cn/device-dev/kernel/stack.md delete mode 100755 zh-cn/device-dev/kernel/statfs.md delete mode 100755 zh-cn/device-dev/kernel/su.md delete mode 100755 zh-cn/device-dev/kernel/swtmr.md delete mode 100755 zh-cn/device-dev/kernel/systeminfo.md delete mode 100755 zh-cn/device-dev/kernel/task.md delete mode 100755 zh-cn/device-dev/kernel/telnet.md delete mode 100755 zh-cn/device-dev/kernel/tftp.md delete mode 100755 zh-cn/device-dev/kernel/touch.md delete mode 100755 zh-cn/device-dev/kernel/umount.md delete mode 100755 zh-cn/device-dev/kernel/uname.md delete mode 100755 zh-cn/device-dev/kernel/vmm.md delete mode 100755 zh-cn/device-dev/kernel/watch.md delete mode 100755 zh-cn/device-dev/kernel/writeproc.md delete mode 100644 "zh-cn/device-dev/kernel/\344\270\255\346\226\255\347\256\241\347\220\206.md" delete mode 100644 "zh-cn/device-dev/kernel/\344\272\213\344\273\266.md" delete mode 100644 "zh-cn/device-dev/kernel/\344\272\222\346\226\245\351\224\201.md" delete mode 100644 "zh-cn/device-dev/kernel/\344\273\273\345\212\241\347\256\241\347\220\206.md" delete mode 100644 "zh-cn/device-dev/kernel/\344\277\241\345\217\267\351\207\217.md" delete mode 100755 "zh-cn/device-dev/kernel/\345\206\205\345\255\230.md" delete mode 100644 "zh-cn/device-dev/kernel/\345\206\205\345\255\230\344\277\241\346\201\257\347\273\237\350\256\241.md" delete mode 100644 "zh-cn/device-dev/kernel/\345\206\205\345\255\230\346\263\204\346\274\217\346\243\200\346\265\213.md" delete mode 100644 "zh-cn/device-dev/kernel/\345\206\205\345\255\230\347\256\241\347\220\206.md" delete mode 100644 "zh-cn/device-dev/kernel/\345\206\205\345\255\230\350\260\203\346\265\213.md" delete mode 100644 "zh-cn/device-dev/kernel/\345\206\205\346\240\270\350\260\203\346\265\213.md" delete mode 100644 "zh-cn/device-dev/kernel/\345\212\250\346\200\201\345\206\205\345\255\230.md" delete mode 100644 "zh-cn/device-dev/kernel/\345\217\214\345\220\221\351\223\276\350\241\250.md" delete mode 100644 "zh-cn/device-dev/kernel/\345\237\272\346\234\254\346\225\260\346\215\256\347\273\223\346\236\204.md" delete mode 100644 "zh-cn/device-dev/kernel/\345\237\272\346\234\254\346\246\202\345\277\265-11.md" delete mode 100644 "zh-cn/device-dev/kernel/\345\237\272\346\234\254\346\246\202\345\277\265-2.md" delete mode 100644 "zh-cn/device-dev/kernel/\345\237\272\346\234\254\346\246\202\345\277\265-21.md" delete mode 100644 "zh-cn/device-dev/kernel/\345\237\272\346\234\254\346\246\202\345\277\265-5.md" delete mode 100644 "zh-cn/device-dev/kernel/\345\237\272\346\234\254\346\246\202\345\277\265-7.md" delete mode 100644 "zh-cn/device-dev/kernel/\345\237\272\346\234\254\346\246\202\345\277\265-9.md" delete mode 100644 "zh-cn/device-dev/kernel/\345\237\272\347\241\200\345\206\205\346\240\270-1.md" delete mode 100644 "zh-cn/device-dev/kernel/\345\237\272\347\241\200\345\206\205\346\240\270.md" delete mode 100644 "zh-cn/device-dev/kernel/\345\260\217\345\236\213\347\263\273\347\273\237\345\206\205\346\240\270.md" delete mode 100644 "zh-cn/device-dev/kernel/\345\274\200\345\217\221\346\214\207\345\257\274-10.md" delete mode 100644 "zh-cn/device-dev/kernel/\345\274\200\345\217\221\346\214\207\345\257\274-12.md" delete mode 100644 "zh-cn/device-dev/kernel/\345\274\200\345\217\221\346\214\207\345\257\274-14.md" delete mode 100644 "zh-cn/device-dev/kernel/\345\274\200\345\217\221\346\214\207\345\257\274-16.md" delete mode 100644 "zh-cn/device-dev/kernel/\345\274\200\345\217\221\346\214\207\345\257\274-3.md" delete mode 100644 "zh-cn/device-dev/kernel/\345\274\200\345\217\221\346\214\207\345\257\274-6.md" delete mode 100644 "zh-cn/device-dev/kernel/\345\274\200\345\217\221\346\214\207\345\257\274-8.md" delete mode 100644 "zh-cn/device-dev/kernel/\345\274\200\345\217\221\346\214\207\345\257\274.md" delete mode 100644 "zh-cn/device-dev/kernel/\345\274\202\345\270\270\350\260\203\346\265\213.md" delete mode 100644 "zh-cn/device-dev/kernel/\345\277\253\351\200\237\345\205\245\351\227\250.md" delete mode 100644 "zh-cn/device-dev/kernel/\346\211\251\345\261\225\347\273\204\344\273\266.md" delete mode 100755 "zh-cn/device-dev/kernel/\346\226\207\344\273\266\345\221\275\344\273\244.md" delete mode 100644 "zh-cn/device-dev/kernel/\346\226\207\344\273\266\347\263\273\347\273\237-19.md" delete mode 100644 "zh-cn/device-dev/kernel/\346\226\207\344\273\266\347\263\273\347\273\237.md" delete mode 100644 "zh-cn/device-dev/kernel/\346\227\266\351\227\264\347\256\241\347\220\206.md" delete mode 100755 "zh-cn/device-dev/kernel/\346\240\207\345\207\206\345\272\223-0.md" delete mode 100755 "zh-cn/device-dev/kernel/\346\240\207\345\207\206\345\272\223.md" delete mode 100644 "zh-cn/device-dev/kernel/\346\240\207\345\207\206\345\272\223\346\224\257\346\214\201.md" delete mode 100644 "zh-cn/device-dev/kernel/\346\240\207\345\207\206\347\263\273\347\273\237\345\206\205\346\240\270.md" delete mode 100644 "zh-cn/device-dev/kernel/\346\266\210\346\201\257\351\230\237\345\210\227.md" delete mode 100755 "zh-cn/device-dev/kernel/\347\263\273\347\273\237\345\221\275\344\273\244.md" delete mode 100755 "zh-cn/device-dev/kernel/\347\272\277\347\250\213.md" delete mode 100755 "zh-cn/device-dev/kernel/\347\275\221\347\273\234.md" delete mode 100755 "zh-cn/device-dev/kernel/\347\275\221\347\273\234\345\221\275\344\273\244.md" delete mode 100644 "zh-cn/device-dev/kernel/\350\256\244\350\257\206LiteOS-M\345\206\205\346\240\270.md" delete mode 100755 "zh-cn/device-dev/kernel/\350\260\203\346\265\213.md" delete mode 100644 "zh-cn/device-dev/kernel/\350\270\251\345\206\205\345\255\230\346\243\200\346\265\213.md" delete mode 100644 "zh-cn/device-dev/kernel/\350\275\257\344\273\266\345\256\232\346\227\266\345\231\250.md" delete mode 100644 "zh-cn/device-dev/kernel/\350\275\273\351\207\217\345\222\214\345\260\217\345\236\213\347\263\273\347\273\237\345\206\205\346\240\270.md" delete mode 100644 "zh-cn/device-dev/kernel/\350\275\273\351\207\217\347\263\273\347\273\237\345\206\205\346\240\270.md" delete mode 100755 "zh-cn/device-dev/kernel/\350\277\233\347\250\213.md" delete mode 100644 "zh-cn/device-dev/kernel/\351\231\204\345\275\225.md" delete mode 100644 "zh-cn/device-dev/kernel/\351\235\231\346\200\201\345\206\205\345\255\230.md" delete mode 100755 "zh-cn/device-dev/kernel/\351\255\224\346\263\225\351\224\256\344\275\277\347\224\250\346\226\271\346\263\225.md" delete mode 100755 "zh-cn/device-dev/porting/CMake\346\226\271\345\274\217\347\273\204\347\273\207\347\274\226\350\257\221\347\232\204\345\272\223\347\247\273\346\244\215.md" delete mode 100755 "zh-cn/device-dev/porting/Makefile\346\226\271\345\274\217\347\273\204\347\273\207\347\274\226\350\257\221\347\232\204\345\272\223\347\247\273\346\244\215.md" delete mode 100755 "zh-cn/device-dev/porting/XTS\350\256\244\350\257\201.md" create mode 100644 zh-cn/device-dev/porting/figure/HDF_WIFI.png rename "zh-cn/device-dev/porting/figures/OpenHarmony\345\220\257\345\212\250\346\210\220\345\212\237\347\225\214\351\235\242.png" => "zh-cn/device-dev/porting/figure/OpenHarmony\345\220\257\345\212\250\346\210\220\345\212\237\347\225\214\351\235\242.png" (100%) mode change 100755 => 100644 create mode 100644 zh-cn/device-dev/porting/figure/init.jpg create mode 100644 zh-cn/device-dev/porting/figure/shell.jpg rename zh-cn/device-dev/porting/{figures => figure}/zh-cn_image_0000001072304191.png (100%) mode change 100755 => 100644 rename zh-cn/device-dev/porting/{figures => figure}/zh-cn_image_0000001073943511.png (100%) mode change 100755 => 100644 create mode 100644 zh-cn/device-dev/porting/figure/zh-cn_image_0000001126198996.png create mode 100644 zh-cn/device-dev/porting/figure/zh-cn_image_0000001126354076.png create mode 100644 zh-cn/device-dev/porting/figure/zh-cn_image_0000001126358814.png create mode 100644 "zh-cn/device-dev/porting/figure/\345\206\205\346\240\270\345\220\257\345\212\250\346\241\206\346\236\266.jpg" create mode 100644 "zh-cn/device-dev/porting/figure/\345\210\206\347\261\273.png" rename "zh-cn/device-dev/porting/figures/\345\215\225\346\235\277\351\251\261\345\212\250\351\200\202\351\205\215\346\265\201\347\250\213.png" => "zh-cn/device-dev/porting/figure/\345\215\225\346\235\277\351\251\261\345\212\250\351\200\202\351\205\215\346\265\201\347\250\213.png" (100%) mode change 100755 => 100644 rename "zh-cn/device-dev/porting/figures/\350\212\257\347\211\207\347\247\273\346\244\215\345\205\263\351\224\256\346\255\245\351\252\244.png" => "zh-cn/device-dev/porting/figure/\350\212\257\347\211\207\347\247\273\346\244\215\345\205\263\351\224\256\346\255\245\351\252\244.png" (100%) mode change 100755 => 100644 delete mode 100755 zh-cn/device-dev/porting/public_sys-resources/icon-caution.gif delete mode 100755 zh-cn/device-dev/porting/public_sys-resources/icon-danger.gif delete mode 100755 zh-cn/device-dev/porting/public_sys-resources/icon-note.gif delete mode 100755 zh-cn/device-dev/porting/public_sys-resources/icon-notice.gif delete mode 100755 zh-cn/device-dev/porting/public_sys-resources/icon-tip.gif delete mode 100755 zh-cn/device-dev/porting/public_sys-resources/icon-warning.gif create mode 100644 zh-cn/device-dev/porting/transplant-chip-board-bundle.md create mode 100644 zh-cn/device-dev/porting/transplant-chip-board-component.md rename "zh-cn/device-dev/porting/\346\235\277\347\272\247\351\251\261\345\212\250\351\200\202\351\205\215.md" => zh-cn/device-dev/porting/transplant-chip-board-drive.md (100%) mode change 100755 => 100644 rename "zh-cn/device-dev/porting/HAL\345\261\202\345\256\236\347\216\260.md" => zh-cn/device-dev/porting/transplant-chip-board-hal.md (100%) mode change 100755 => 100644 create mode 100644 zh-cn/device-dev/porting/transplant-chip-board-overview.md create mode 100644 zh-cn/device-dev/porting/transplant-chip-board-xts.md create mode 100644 zh-cn/device-dev/porting/transplant-chip-board.md rename "zh-cn/device-dev/porting/\345\270\270\350\247\201\351\227\256\351\242\230.md" => zh-cn/device-dev/porting/transplant-chip-faqs.md (100%) mode change 100755 => 100644 create mode 100644 zh-cn/device-dev/porting/transplant-chip-kernel-adjustment.md create mode 100644 zh-cn/device-dev/porting/transplant-chip-kernel-overview.md create mode 100644 zh-cn/device-dev/porting/transplant-chip-kernel-verify.md create mode 100644 zh-cn/device-dev/porting/transplant-chip-kernel.md create mode 100644 zh-cn/device-dev/porting/transplant-chip-prepare-knows.md rename "zh-cn/device-dev/porting/\347\274\226\350\257\221\346\236\204\345\273\272\351\200\202\351\205\215\346\265\201\347\250\213.md" => zh-cn/device-dev/porting/transplant-chip-prepare-process.md (100%) mode change 100755 => 100644 create mode 100644 zh-cn/device-dev/porting/transplant-chip-prepare.md create mode 100644 zh-cn/device-dev/porting/transplant-chip.md create mode 100644 zh-cn/device-dev/porting/transplant-minichip.md create mode 100644 zh-cn/device-dev/porting/transplant-smallchip-drive-des.md create mode 100644 zh-cn/device-dev/porting/transplant-smallchip-drive-oom.md create mode 100644 zh-cn/device-dev/porting/transplant-smallchip-drive-plat.md create mode 100644 zh-cn/device-dev/porting/transplant-smallchip-drive.md create mode 100644 zh-cn/device-dev/porting/transplant-smallchip-kernel-a.md create mode 100644 zh-cn/device-dev/porting/transplant-smallchip-kernel-linux.md create mode 100644 zh-cn/device-dev/porting/transplant-smallchip-kernel.md create mode 100644 zh-cn/device-dev/porting/transplant-smallchip-prepare-building.md create mode 100644 zh-cn/device-dev/porting/transplant-smallchip-prepare-needs.md create mode 100644 zh-cn/device-dev/porting/transplant-smallchip-prepare.md create mode 100644 zh-cn/device-dev/porting/transplant-smallchip.md create mode 100644 zh-cn/device-dev/porting/transplant-thirdparty-cmake.md create mode 100644 zh-cn/device-dev/porting/transplant-thirdparty-makefile.md rename "zh-cn/device-dev/porting/\346\246\202\350\277\260.md" => zh-cn/device-dev/porting/transplant-thirdparty-overview.md (100%) mode change 100755 => 100644 create mode 100644 zh-cn/device-dev/porting/transplant-thirdparty.md create mode 100644 zh-cn/device-dev/porting/transplant.md delete mode 100755 "zh-cn/device-dev/porting/\344\270\211\346\226\271\345\272\223\347\247\273\346\244\215\346\214\207\345\257\274.md" delete mode 100644 "zh-cn/device-dev/porting/\344\270\211\346\226\271\347\273\204\344\273\266\351\200\202\351\205\215.md" delete mode 100755 "zh-cn/device-dev/porting/\344\270\211\346\226\271\350\212\257\347\211\207\347\247\273\346\244\215\346\214\207\345\257\274.md" delete mode 100755 "zh-cn/device-dev/porting/\345\206\205\346\240\270\345\237\272\347\241\200\351\200\202\351\205\215.md" delete mode 100755 "zh-cn/device-dev/porting/\345\206\205\346\240\270\347\247\273\346\244\215.md" delete mode 100755 "zh-cn/device-dev/porting/\345\206\205\346\240\270\347\247\273\346\244\215\351\252\214\350\257\201.md" delete mode 100755 "zh-cn/device-dev/porting/\346\235\277\347\272\247\347\263\273\347\273\237\347\247\273\346\244\215.md" delete mode 100755 "zh-cn/device-dev/porting/\347\247\273\346\244\215\345\207\206\345\244\207.md" delete mode 100755 "zh-cn/device-dev/porting/\347\247\273\346\244\215\346\246\202\350\277\260-0.md" delete mode 100755 "zh-cn/device-dev/porting/\347\247\273\346\244\215\346\246\202\350\277\260.md" delete mode 100755 "zh-cn/device-dev/porting/\347\247\273\346\244\215\351\241\273\347\237\245.md" delete mode 100755 "zh-cn/device-dev/porting/\347\263\273\347\273\237\347\273\204\344\273\266\350\260\203\347\224\250.md" rename zh-cn/device-dev/{bundles => }/public_sys-resources/icon-caution.gif (100%) mode change 100755 => 100644 rename zh-cn/device-dev/{bundles => }/public_sys-resources/icon-danger.gif (100%) mode change 100755 => 100644 rename zh-cn/device-dev/{bundles => }/public_sys-resources/icon-note.gif (100%) mode change 100755 => 100644 rename zh-cn/device-dev/{bundles => }/public_sys-resources/icon-notice.gif (100%) mode change 100755 => 100644 rename zh-cn/device-dev/{bundles => }/public_sys-resources/icon-tip.gif (100%) mode change 100755 => 100644 rename zh-cn/device-dev/{bundles => }/public_sys-resources/icon-warning.gif (100%) mode change 100755 => 100644 delete mode 100755 "zh-cn/device-dev/quick-start/Hi3516\345\274\200\345\217\221\346\235\277.md" delete mode 100755 "zh-cn/device-dev/quick-start/Hi3516\345\274\200\345\217\221\346\235\277\344\273\213\347\273\215.md" delete mode 100755 "zh-cn/device-dev/quick-start/Hi3518\345\274\200\345\217\221\346\235\277.md" delete mode 100755 "zh-cn/device-dev/quick-start/Hi3518\345\274\200\345\217\221\346\235\277\344\273\213\347\273\215.md" delete mode 100755 "zh-cn/device-dev/quick-start/Hi3861\345\274\200\345\217\221\346\235\277.md" delete mode 100755 "zh-cn/device-dev/quick-start/Hi3861\345\274\200\345\217\221\346\235\277\344\273\213\347\273\215.md" delete mode 100755 "zh-cn/device-dev/quick-start/Ubuntu\347\274\226\350\257\221\347\216\257\345\242\203\345\207\206\345\244\207.md" delete mode 100755 "zh-cn/device-dev/quick-start/WLAN\350\201\224\347\275\221.md" delete mode 100644 "zh-cn/device-dev/quick-start/Windows\345\274\200\345\217\221\347\216\257\345\242\203\345\207\206\345\244\207-7.md" delete mode 100755 "zh-cn/device-dev/quick-start/Windows\345\274\200\345\217\221\347\216\257\345\242\203\345\207\206\345\244\207.md" rename zh-cn/device-dev/quick-start/{figures => figure}/1.png (100%) mode change 100755 => 100644 rename zh-cn/device-dev/quick-start/{figures => figure}/10.png (100%) mode change 100755 => 100644 rename zh-cn/device-dev/quick-start/{figures => figure}/2.png (100%) mode change 100755 => 100644 rename zh-cn/device-dev/quick-start/{figures/2021-01-27_170334-17.png => figure/2021-01-27_170334-16.png} (100%) rename zh-cn/device-dev/quick-start/{figures => figure}/2021-01-27_170334-2.png (100%) mode change 100755 => 100644 rename zh-cn/device-dev/quick-start/{figures => figure}/2021-01-27_170334-5.png (100%) rename zh-cn/device-dev/quick-start/{figures => figure}/2021-01-27_170334.png (100%) mode change 100755 => 100644 rename zh-cn/device-dev/quick-start/{figures => figure}/3-0.png (100%) mode change 100755 => 100644 rename zh-cn/device-dev/quick-start/{figures => figure}/3.png (100%) mode change 100755 => 100644 rename "zh-cn/device-dev/quick-start/figures/3516\346\255\243\351\235\242.png" => "zh-cn/device-dev/quick-start/figure/3516\346\255\243\351\235\242.png" (100%) mode change 100755 => 100644 rename "zh-cn/device-dev/quick-start/figures/3861\346\255\243\351\235\242.png" => "zh-cn/device-dev/quick-start/figure/3861\346\255\243\351\235\242.png" (100%) mode change 100755 => 100644 rename zh-cn/device-dev/quick-start/{figures => figure}/4.png (100%) mode change 100755 => 100644 rename zh-cn/device-dev/quick-start/{figures => figure}/5-1.png (100%) mode change 100755 => 100644 rename zh-cn/device-dev/quick-start/{figures => figure}/5.png (100%) mode change 100755 => 100644 rename zh-cn/device-dev/quick-start/{figures => figure}/6.png (100%) mode change 100755 => 100644 rename "zh-cn/device-dev/quick-start/figures/Hi3518EV300\345\215\225\346\235\277\346\255\243\351\235\242\345\244\226\350\247\202\345\233\276.png" => "zh-cn/device-dev/quick-start/figure/Hi3518EV300\345\215\225\346\235\277\346\255\243\351\235\242\345\244\226\350\247\202\345\233\276.png" (100%) mode change 100755 => 100644 rename "zh-cn/device-dev/quick-start/figures/Hi3518\346\255\243\350\203\214\351\235\242.png" => "zh-cn/device-dev/quick-start/figure/Hi3518\346\255\243\350\203\214\351\235\242.png" (100%) mode change 100755 => 100644 rename "zh-cn/device-dev/quick-start/figures/SCons\345\256\211\350\243\205\346\210\220\345\212\237\347\225\214\351\235\242-\347\211\210\346\234\254\350\246\201\346\261\2023-0-4\344\273\245\344\270\212.png" => "zh-cn/device-dev/quick-start/figure/SCons\345\256\211\350\243\205\346\210\220\345\212\237\347\225\214\351\235\242-\347\211\210\346\234\254\350\246\201\346\261\2023-0-4\344\273\245\344\270\212.png" (100%) mode change 100755 => 100644 rename "zh-cn/device-dev/quick-start/figures/U-boot\347\203\247\345\206\231\345\256\214\346\210\220\344\270\262\345\217\243\346\230\276\347\244\272\345\233\276.png" => "zh-cn/device-dev/quick-start/figure/U-boot\347\203\247\345\206\231\345\256\214\346\210\220\344\270\262\345\217\243\346\230\276\347\244\272\345\233\276.png" (100%) mode change 100755 => 100644 rename zh-cn/device-dev/quick-start/{figures => figure}/changjian1-10.png (100%) rename zh-cn/device-dev/quick-start/{figures => figure}/changjian1.png (100%) mode change 100755 => 100644 rename zh-cn/device-dev/quick-start/{figures => figure}/chuankou1-6.png (100%) rename zh-cn/device-dev/quick-start/{figures => figure}/chuankou1.png (100%) mode change 100755 => 100644 rename zh-cn/device-dev/quick-start/{figures => figure}/qi1.png (100%) mode change 100755 => 100644 rename zh-cn/device-dev/quick-start/{figures => figure}/zh-cn_image_0000001057335403.png (100%) mode change 100755 => 100644 rename zh-cn/device-dev/quick-start/{figures => figure}/zh-cn_image_0000001072468991.png (100%) mode change 100755 => 100644 rename zh-cn/device-dev/quick-start/{figures => figure}/zh-cn_image_0000001072757874.png (100%) mode change 100755 => 100644 rename zh-cn/device-dev/quick-start/{figures => figure}/zh-cn_image_0000001073840162.png (100%) mode change 100755 => 100644 rename zh-cn/device-dev/quick-start/{figures => figure}/zh-cn_image_0000001113969542.png (100%) rename zh-cn/device-dev/quick-start/{figures => figure}/zh-cn_image_0000001114129428.png (100%) rename zh-cn/device-dev/quick-start/{figures => figure}/zh-cn_image_0000001114129432.png (100%) rename zh-cn/device-dev/quick-start/{figures => figure}/zh-cn_image_0000001117463460.png (100%) rename zh-cn/device-dev/quick-start/{figures => figure}/zh-cn_image_0000001117621400.png (100%) rename zh-cn/device-dev/quick-start/{figures => figure}/zh-cn_image_0000001128311066.png (100%) rename zh-cn/device-dev/quick-start/{figures => figure}/zh-cn_image_0000001128311070.png (100%) rename zh-cn/device-dev/quick-start/{figures => figure}/zh-cn_image_0000001128311072.png (100%) rename zh-cn/device-dev/quick-start/{figures => figure}/zh-cn_image_0000001128311090.png (100%) mode change 100755 => 100644 rename zh-cn/device-dev/quick-start/{figures => figure}/zh-cn_image_0000001128311092.png (100%) mode change 100755 => 100644 rename zh-cn/device-dev/quick-start/{figures => figure}/zh-cn_image_0000001128311094.png (100%) mode change 100755 => 100644 rename zh-cn/device-dev/quick-start/{figures => figure}/zh-cn_image_0000001128311096.png (100%) rename zh-cn/device-dev/quick-start/{figures => figure}/zh-cn_image_0000001128311098.png (100%) rename zh-cn/device-dev/quick-start/{figures => figure}/zh-cn_image_0000001128311100.png (100%) rename zh-cn/device-dev/quick-start/{figures => figure}/zh-cn_image_0000001128311104.png (100%) rename zh-cn/device-dev/quick-start/{figures => figure}/zh-cn_image_0000001128311116.png (100%) mode change 100755 => 100644 rename zh-cn/device-dev/quick-start/{figures => figure}/zh-cn_image_0000001128311118.png (100%) mode change 100755 => 100644 rename zh-cn/device-dev/quick-start/{figures => figure}/zh-cn_image_0000001128470864.png (100%) rename zh-cn/device-dev/quick-start/{figures => figure}/zh-cn_image_0000001128470880.png (100%) rename zh-cn/device-dev/quick-start/{figures => figure}/zh-cn_image_0000001128470900.png (100%) mode change 100755 => 100644 rename zh-cn/device-dev/quick-start/{figures => figure}/zh-cn_image_0000001128470902.png (100%) rename zh-cn/device-dev/quick-start/{figures => figure}/zh-cn_image_0000001128470904.png (100%) rename zh-cn/device-dev/quick-start/{figures => figure}/zh-cn_image_0000001128470906.png (100%) rename zh-cn/device-dev/quick-start/{figures => figure}/zh-cn_image_0000001128470908.png (100%) rename zh-cn/device-dev/quick-start/{figures => figure}/zh-cn_image_0000001128470922.png (100%) mode change 100755 => 100644 rename zh-cn/device-dev/quick-start/{figures => figure}/zh-cn_image_0000001130278040.png (100%) rename zh-cn/device-dev/quick-start/{figures => figure}/zh-cn_image_0000001130584312.png (100%) rename zh-cn/device-dev/quick-start/{figures => figure}/zh-cn_image_0000001142794291.png (100%) mode change 100755 => 100644 rename zh-cn/device-dev/quick-start/{figures => figure}/zh-cn_image_0000001142802505.png (100%) mode change 100755 => 100644 rename zh-cn/device-dev/quick-start/{figures => figure}/zh-cn_image_0000001174270699.png (100%) rename zh-cn/device-dev/quick-start/{figures => figure}/zh-cn_image_0000001174270713.png (100%) rename zh-cn/device-dev/quick-start/{figures => figure}/zh-cn_image_0000001174270715.png (100%) rename zh-cn/device-dev/quick-start/{figures => figure}/zh-cn_image_0000001174270727.png (100%) rename zh-cn/device-dev/quick-start/{figures => figure}/zh-cn_image_0000001174270729.png (100%) rename zh-cn/device-dev/quick-start/{figures => figure}/zh-cn_image_0000001174270731.png (100%) rename zh-cn/device-dev/quick-start/{figures => figure}/zh-cn_image_0000001174270733.png (100%) rename zh-cn/device-dev/quick-start/{figures => figure}/zh-cn_image_0000001174270735.png (100%) rename zh-cn/device-dev/quick-start/{figures => figure}/zh-cn_image_0000001174270737.png (100%) rename zh-cn/device-dev/quick-start/{figures => figure}/zh-cn_image_0000001174270739.png (100%) rename zh-cn/device-dev/quick-start/{figures => figure}/zh-cn_image_0000001174270743.png (100%) rename zh-cn/device-dev/quick-start/{figures => figure}/zh-cn_image_0000001174270749.png (100%) rename zh-cn/device-dev/quick-start/{figures => figure}/zh-cn_image_0000001174270751.png (100%) mode change 100755 => 100644 rename zh-cn/device-dev/quick-start/{figures => figure}/zh-cn_image_0000001174350615.png (100%) rename zh-cn/device-dev/quick-start/{figures => figure}/zh-cn_image_0000001174350623.png (100%) rename zh-cn/device-dev/quick-start/{figures => figure}/zh-cn_image_0000001174350633.png (100%) mode change 100755 => 100644 rename zh-cn/device-dev/quick-start/{figures => figure}/zh-cn_image_0000001174350641.png (100%) rename zh-cn/device-dev/quick-start/{figures => figure}/zh-cn_image_0000001174350643.png (100%) mode change 100755 => 100644 rename zh-cn/device-dev/quick-start/{figures => figure}/zh-cn_image_0000001174350647.png (100%) rename zh-cn/device-dev/quick-start/{figures => figure}/zh-cn_image_0000001174350649.png (100%) mode change 100755 => 100644 rename zh-cn/device-dev/quick-start/{figures => figure}/zh-cn_image_0000001174350651.png (100%) rename zh-cn/device-dev/quick-start/{figures => figure}/zh-cn_image_0000001174350653.png (100%) rename zh-cn/device-dev/quick-start/{figures => figure}/zh-cn_image_0000001174350655.png (100%) rename zh-cn/device-dev/quick-start/{figures => figure}/zh-cn_image_0000001174350659.png (100%) rename zh-cn/device-dev/quick-start/{figures => figure}/zh-cn_image_0000001174350661.png (100%) rename zh-cn/device-dev/quick-start/{figures => figure}/zh-cn_image_0000001174350669.png (100%) mode change 100755 => 100644 rename zh-cn/device-dev/quick-start/{figures => figure}/zh-cn_image_0000001176317561.png (100%) rename "zh-cn/device-dev/quick-start/figures/\345\205\201\350\256\270Visual-Studio-Code\345\272\224\347\224\250\350\256\277\351\227\256\347\275\221\347\273\234-15.png" => "zh-cn/device-dev/quick-start/figure/\345\205\201\350\256\270Visual-Studio-Code\345\272\224\347\224\250\350\256\277\351\227\256\347\275\221\347\273\234-15.png" (100%) rename "zh-cn/device-dev/quick-start/figures/\345\205\201\350\256\270Visual-Studio-Code\345\272\224\347\224\250\350\256\277\351\227\256\347\275\221\347\273\234.png" => "zh-cn/device-dev/quick-start/figure/\345\205\201\350\256\270Visual-Studio-Code\345\272\224\347\224\250\350\256\277\351\227\256\347\275\221\347\273\234.png" (100%) mode change 100755 => 100644 rename "zh-cn/device-dev/quick-start/figures/\345\205\263\351\227\255\344\270\262\345\217\243\347\273\210\347\253\257-9.png" => "zh-cn/device-dev/quick-start/figure/\345\205\263\351\227\255\344\270\262\345\217\243\347\273\210\347\253\257-9.png" (100%) rename "zh-cn/device-dev/quick-start/figures/\345\205\263\351\227\255\344\270\262\345\217\243\347\273\210\347\253\257.png" => "zh-cn/device-dev/quick-start/figure/\345\205\263\351\227\255\344\270\262\345\217\243\347\273\210\347\253\257.png" (100%) mode change 100755 => 100644 rename "zh-cn/device-dev/quick-start/figures/\345\220\257\345\212\250\345\271\266\346\210\220\345\212\237\346\211\247\350\241\214\345\272\224\347\224\250\347\250\213\345\272\217\345\233\276.png" => "zh-cn/device-dev/quick-start/figure/\345\220\257\345\212\250\345\271\266\346\210\220\345\212\237\346\211\247\350\241\214\345\272\224\347\224\250\347\250\213\345\272\217\345\233\276.png" (100%) mode change 100755 => 100644 rename "zh-cn/device-dev/quick-start/figures/\345\220\257\345\212\250\346\210\220\345\212\237\345\271\266\346\211\247\350\241\214\345\272\224\347\224\250\347\250\213\345\272\217\345\233\276.png" => "zh-cn/device-dev/quick-start/figure/\345\220\257\345\212\250\346\210\220\345\212\237\345\271\266\346\211\247\350\241\214\345\272\224\347\224\250\347\250\213\345\272\217\345\233\276.png" (100%) mode change 100755 => 100644 rename "zh-cn/device-dev/quick-start/figures/\346\210\252\345\233\276.png" => "zh-cn/device-dev/quick-start/figure/\346\210\252\345\233\276.png" (100%) mode change 100755 => 100644 rename "zh-cn/device-dev/quick-start/figures/\346\211\223\345\274\200\344\270\262\345\217\243\345\244\261\350\264\245\345\233\276-7.png" => "zh-cn/device-dev/quick-start/figure/\346\211\223\345\274\200\344\270\262\345\217\243\345\244\261\350\264\245\345\233\276-7.png" (100%) rename "zh-cn/device-dev/quick-start/figures/\346\211\223\345\274\200\344\270\262\345\217\243\345\244\261\350\264\245\345\233\276.png" => "zh-cn/device-dev/quick-start/figure/\346\211\223\345\274\200\344\270\262\345\217\243\345\244\261\350\264\245\345\233\276.png" (100%) mode change 100755 => 100644 rename "zh-cn/device-dev/quick-start/figures/\346\237\245\346\211\276Visual-Studio-Code\345\272\224\347\224\250\345\233\276-14.png" => "zh-cn/device-dev/quick-start/figure/\346\237\245\346\211\276Visual-Studio-Code\345\272\224\347\224\250\345\233\276-14.png" (100%) rename "zh-cn/device-dev/quick-start/figures/\346\237\245\346\211\276Visual-Studio-Code\345\272\224\347\224\250\345\233\276.png" => "zh-cn/device-dev/quick-start/figure/\346\237\245\346\211\276Visual-Studio-Code\345\272\224\347\224\250\345\233\276.png" (100%) mode change 100755 => 100644 rename "zh-cn/device-dev/quick-start/figures/\346\237\245\346\211\276\346\230\257\345\220\246\345\255\230\345\234\250\345\215\240\347\224\250\344\270\262\345\217\243\347\232\204\347\273\210\347\253\257-8.png" => "zh-cn/device-dev/quick-start/figure/\346\237\245\346\211\276\346\230\257\345\220\246\345\255\230\345\234\250\345\215\240\347\224\250\344\270\262\345\217\243\347\232\204\347\273\210\347\253\257-8.png" (100%) rename "zh-cn/device-dev/quick-start/figures/\346\237\245\346\211\276\346\230\257\345\220\246\345\255\230\345\234\250\345\215\240\347\224\250\344\270\262\345\217\243\347\232\204\347\273\210\347\253\257.png" => "zh-cn/device-dev/quick-start/figure/\346\237\245\346\211\276\346\230\257\345\220\246\345\255\230\345\234\250\345\215\240\347\224\250\344\270\262\345\217\243\347\232\204\347\273\210\347\253\257.png" (100%) mode change 100755 => 100644 rename "zh-cn/device-dev/quick-start/figures/\347\237\251\345\275\242\345\244\207\344\273\275-292.png" => "zh-cn/device-dev/quick-start/figure/\347\237\251\345\275\242\345\244\207\344\273\275-292.png" (100%) mode change 100755 => 100644 rename "zh-cn/device-dev/quick-start/figures/\347\241\254\344\273\266\350\277\236\347\272\277\345\233\276-3.png" => "zh-cn/device-dev/quick-start/figure/\347\241\254\344\273\266\350\277\236\347\272\277\345\233\276-3.png" (100%) rename "zh-cn/device-dev/quick-start/figures/\347\241\254\344\273\266\350\277\236\347\272\277\345\233\276.png" => "zh-cn/device-dev/quick-start/figure/\347\241\254\344\273\266\350\277\236\347\272\277\345\233\276.png" (100%) mode change 100755 => 100644 rename "zh-cn/device-dev/quick-start/figures/\347\275\221\347\273\234\344\270\215\351\200\232-\345\215\225\346\235\277\346\227\240\346\263\225\350\216\267\345\217\226\346\226\207\344\273\266\345\233\276-11.png" => "zh-cn/device-dev/quick-start/figure/\347\275\221\347\273\234\344\270\215\351\200\232-\345\215\225\346\235\277\346\227\240\346\263\225\350\216\267\345\217\226\346\226\207\344\273\266\345\233\276-11.png" (100%) rename "zh-cn/device-dev/quick-start/figures/\347\275\221\347\273\234\344\270\215\351\200\232-\345\215\225\346\235\277\346\227\240\346\263\225\350\216\267\345\217\226\346\226\207\344\273\266\345\233\276.png" => "zh-cn/device-dev/quick-start/figure/\347\275\221\347\273\234\344\270\215\351\200\232-\345\215\225\346\235\277\346\227\240\346\263\225\350\216\267\345\217\226\346\226\207\344\273\266\345\233\276.png" (100%) mode change 100755 => 100644 rename "zh-cn/device-dev/quick-start/figures/\347\275\221\347\273\234\351\230\262\347\201\253\345\242\231\350\256\276\347\275\256\345\233\276-12.png" => "zh-cn/device-dev/quick-start/figure/\347\275\221\347\273\234\351\230\262\347\201\253\345\242\231\350\256\276\347\275\256\345\233\276-12.png" (100%) rename "zh-cn/device-dev/quick-start/figures/\347\275\221\347\273\234\351\230\262\347\201\253\345\242\231\350\256\276\347\275\256\345\233\276.png" => "zh-cn/device-dev/quick-start/figure/\347\275\221\347\273\234\351\230\262\347\201\253\345\242\231\350\256\276\347\275\256\345\233\276.png" (100%) mode change 100755 => 100644 rename "zh-cn/device-dev/quick-start/figures/\350\256\276\347\275\256\345\233\276\344\276\213-4.png" => "zh-cn/device-dev/quick-start/figure/\350\256\276\347\275\256\345\233\276\344\276\213-4.png" (100%) rename "zh-cn/device-dev/quick-start/figures/\350\256\276\347\275\256\345\233\276\344\276\213.png" => "zh-cn/device-dev/quick-start/figure/\350\256\276\347\275\256\345\233\276\344\276\213.png" (100%) mode change 100755 => 100644 rename "zh-cn/device-dev/quick-start/figures/\351\230\262\347\201\253\345\242\231\345\222\214\347\275\221\347\273\234\344\277\235\346\212\244\347\225\214\351\235\242\345\233\276-13.png" => "zh-cn/device-dev/quick-start/figure/\351\230\262\347\201\253\345\242\231\345\222\214\347\275\221\347\273\234\344\277\235\346\212\244\347\225\214\351\235\242\345\233\276-13.png" (100%) rename "zh-cn/device-dev/quick-start/figures/\351\230\262\347\201\253\345\242\231\345\222\214\347\275\221\347\273\234\344\277\235\346\212\244\347\225\214\351\235\242\345\233\276.png" => "zh-cn/device-dev/quick-start/figure/\351\230\262\347\201\253\345\242\231\345\222\214\347\275\221\347\273\234\344\277\235\346\212\244\347\225\214\351\235\242\345\233\276.png" (100%) mode change 100755 => 100644 delete mode 100644 "zh-cn/device-dev/quick-start/figures/3516\346\255\243\351\235\242-16.png" delete mode 100644 "zh-cn/device-dev/quick-start/figures/\346\240\207\345\207\206\347\216\257\345\242\203\345\277\253\351\200\237\345\205\245\351\227\250\346\265\201\347\250\213.png" delete mode 100755 zh-cn/device-dev/quick-start/public_sys-resources/icon-caution.gif delete mode 100755 zh-cn/device-dev/quick-start/public_sys-resources/icon-danger.gif delete mode 100755 zh-cn/device-dev/quick-start/public_sys-resources/icon-note.gif delete mode 100755 zh-cn/device-dev/quick-start/public_sys-resources/icon-notice.gif delete mode 100755 zh-cn/device-dev/quick-start/public_sys-resources/icon-tip.gif delete mode 100755 zh-cn/device-dev/quick-start/public_sys-resources/icon-warning.gif rename "zh-cn/device-dev/quick-start/\346\246\202\350\277\260-0.md" => zh-cn/device-dev/quick-start/quickstart-lite-env-setup-des.md (100%) rename "zh-cn/device-dev/quick-start/\345\270\270\350\247\201\351\227\256\351\242\230.md" => zh-cn/device-dev/quick-start/quickstart-lite-env-setup-faqs.md (100%) mode change 100755 => 100644 create mode 100644 zh-cn/device-dev/quick-start/quickstart-lite-env-setup-lin.md create mode 100644 zh-cn/device-dev/quick-start/quickstart-lite-env-setup-win.md create mode 100644 zh-cn/device-dev/quick-start/quickstart-lite-env-setup.md create mode 100644 zh-cn/device-dev/quick-start/quickstart-lite-introduction-hi3516.md create mode 100644 zh-cn/device-dev/quick-start/quickstart-lite-introduction-hi3518.md create mode 100644 zh-cn/device-dev/quick-start/quickstart-lite-introduction-hi3861.md create mode 100644 zh-cn/device-dev/quick-start/quickstart-lite-introduction.md rename "zh-cn/device-dev/quick-start/\346\246\202\350\277\260.md" => zh-cn/device-dev/quick-start/quickstart-lite-overview.md (100%) create mode 100644 zh-cn/device-dev/quick-start/quickstart-lite-steps-board3516-faqs.md create mode 100644 zh-cn/device-dev/quick-start/quickstart-lite-steps-board3516-program.md create mode 100644 zh-cn/device-dev/quick-start/quickstart-lite-steps-board3516-running.md create mode 100644 zh-cn/device-dev/quick-start/quickstart-lite-steps-board3516-setting.md create mode 100644 zh-cn/device-dev/quick-start/quickstart-lite-steps-board3516.md create mode 100644 zh-cn/device-dev/quick-start/quickstart-lite-steps-board3518-faqs.md create mode 100644 zh-cn/device-dev/quick-start/quickstart-lite-steps-board3518-running.md create mode 100644 zh-cn/device-dev/quick-start/quickstart-lite-steps-board3518-setting.md create mode 100644 zh-cn/device-dev/quick-start/quickstart-lite-steps-board3518.md create mode 100644 zh-cn/device-dev/quick-start/quickstart-lite-steps-board3861-connection.md create mode 100644 zh-cn/device-dev/quick-start/quickstart-lite-steps-board3861-faqs.md create mode 100644 zh-cn/device-dev/quick-start/quickstart-lite-steps-board3861-running.md create mode 100644 zh-cn/device-dev/quick-start/quickstart-lite-steps-board3861-setting.md create mode 100644 zh-cn/device-dev/quick-start/quickstart-lite-steps-board3861.md create mode 100644 zh-cn/device-dev/quick-start/quickstart-lite-steps.md create mode 100644 zh-cn/device-dev/quick-start/quickstart-lite.md create mode 100644 zh-cn/device-dev/quick-start/quickstart-standard-burn.md create mode 100644 zh-cn/device-dev/quick-start/quickstart-standard-docker-environment.md rename "zh-cn/device-dev/quick-start/\345\270\270\350\247\201\351\227\256\351\242\230-8.md" => zh-cn/device-dev/quick-start/quickstart-standard-faq.md (100%) create mode 100644 zh-cn/device-dev/quick-start/quickstart-standard-package-environment.md create mode 100644 zh-cn/device-dev/quick-start/quickstart-standard-windows-environment.md create mode 100644 zh-cn/device-dev/quick-start/quickstart-standard.md create mode 100644 zh-cn/device-dev/quick-start/quickstart.md delete mode 100755 "zh-cn/device-dev/quick-start/\344\272\206\350\247\243\345\274\200\345\217\221\346\235\277.md" delete mode 100644 "zh-cn/device-dev/quick-start/\345\205\245\351\227\250\344\273\213\347\273\215.md" delete mode 100644 "zh-cn/device-dev/quick-start/\345\256\211\350\243\205\345\274\200\345\217\221\346\235\277\347\216\257\345\242\203-2.md" delete mode 100644 "zh-cn/device-dev/quick-start/\345\256\211\350\243\205\345\274\200\345\217\221\346\235\277\347\216\257\345\242\203-4.md" delete mode 100644 "zh-cn/device-dev/quick-start/\345\256\211\350\243\205\345\274\200\345\217\221\346\235\277\347\216\257\345\242\203.md" delete mode 100644 "zh-cn/device-dev/quick-start/\345\270\270\350\247\201\351\227\256\351\242\230-1.md" delete mode 100644 "zh-cn/device-dev/quick-start/\345\270\270\350\247\201\351\227\256\351\242\230-3.md" delete mode 100644 "zh-cn/device-dev/quick-start/\345\270\270\350\247\201\351\227\256\351\242\230-6.md" delete mode 100644 "zh-cn/device-dev/quick-start/\345\274\200\345\217\221\346\255\245\351\252\244.md" delete mode 100644 "zh-cn/device-dev/quick-start/\346\220\255\345\273\272Ubuntu\347\216\257\345\242\203\345\217\212\347\274\226\350\257\221\357\274\210Docker\346\226\271\345\274\217\357\274\211.md" delete mode 100644 "zh-cn/device-dev/quick-start/\346\220\255\345\273\272Ubuntu\347\216\257\345\242\203\345\217\212\347\274\226\350\257\221\357\274\210\345\256\211\350\243\205\345\214\205\346\226\271\345\274\217\357\274\211.md" delete mode 100755 "zh-cn/device-dev/quick-start/\346\220\255\345\273\272\347\263\273\347\273\237\347\216\257\345\242\203.md" delete mode 100755 "zh-cn/device-dev/quick-start/\346\240\207\345\207\206\347\263\273\347\273\237\345\205\245\351\227\250.md" delete mode 100644 "zh-cn/device-dev/quick-start/\350\275\273\351\207\217\345\222\214\345\260\217\345\236\213\347\263\273\347\273\237\345\205\245\351\227\250.md" delete mode 100644 "zh-cn/device-dev/quick-start/\350\277\220\350\241\214Hello-OHOS-5.md" delete mode 100755 "zh-cn/device-dev/quick-start/\350\277\220\350\241\214Hello-OHOS.md" delete mode 100755 "zh-cn/device-dev/quick-start/\350\277\220\350\241\214Hello-World.md" delete mode 100644 "zh-cn/device-dev/quick-start/\351\225\234\345\203\217\347\203\247\345\275\225.md" delete mode 100755 "zh-cn/device-dev/quick-start/\351\251\261\345\212\250\345\274\200\345\217\221\347\244\272\344\276\213.md" rename "zh-cn/device-dev/security/figures/1-\346\225\217\346\204\237\346\235\203\351\231\220\345\274\271\347\252\227.png" => "zh-cn/device-dev/security/figure/1-\346\225\217\346\204\237\346\235\203\351\231\220\345\274\271\347\252\227.png" (100%) mode change 100755 => 100644 rename "zh-cn/device-dev/security/figures/2-\345\272\224\347\224\250\345\220\257\345\212\250\351\242\204\346\216\210\346\235\203.png" => "zh-cn/device-dev/security/figure/2-\345\272\224\347\224\250\345\220\257\345\212\250\351\242\204\346\216\210\346\235\203.png" (100%) mode change 100755 => 100644 rename "zh-cn/device-dev/security/figures/3-\345\272\224\347\224\250\351\232\220\347\247\201\345\243\260\346\230\216.png" => "zh-cn/device-dev/security/figure/3-\345\272\224\347\224\250\351\232\220\347\247\201\345\243\260\346\230\216.png" (100%) mode change 100755 => 100644 rename "zh-cn/device-dev/security/figures/4-\351\232\220\347\247\201\345\243\260\346\230\216\345\217\230\346\233\264\351\200\232\347\237\245.png" => "zh-cn/device-dev/security/figure/4-\351\232\220\347\247\201\345\243\260\346\230\216\345\217\230\346\233\264\351\200\232\347\237\245.png" (100%) mode change 100755 => 100644 rename "zh-cn/device-dev/security/figures/5-\345\272\224\347\224\250\351\232\220\347\247\201\345\243\260\346\230\216\345\205\245\345\217\243.png" => "zh-cn/device-dev/security/figure/5-\345\272\224\347\224\250\351\232\220\347\247\201\345\243\260\346\230\216\345\205\245\345\217\243.png" (100%) mode change 100755 => 100644 rename "zh-cn/device-dev/security/figures/6-1-\351\232\220\347\247\201\345\243\260\346\230\216\346\222\244\351\224\200.png" => "zh-cn/device-dev/security/figure/6-1-\351\232\220\347\247\201\345\243\260\346\230\216\346\222\244\351\224\200.png" (100%) mode change 100755 => 100644 rename "zh-cn/device-dev/security/figures/6-2-\351\232\220\347\247\201\345\243\260\346\230\216\346\222\244\351\224\200.png" => "zh-cn/device-dev/security/figure/6-2-\351\232\220\347\247\201\345\243\260\346\230\216\346\222\244\351\224\200.png" (100%) mode change 100755 => 100644 rename "zh-cn/device-dev/security/figures/DAC\346\265\201\347\250\213\345\233\276.png" => "zh-cn/device-dev/security/figure/DAC\346\265\201\347\250\213\345\233\276.png" (100%) mode change 100755 => 100644 rename "zh-cn/device-dev/security/figures/HUKS\345\212\237\350\203\275\347\273\223\346\236\204\345\233\276.png" => "zh-cn/device-dev/security/figure/HUKS\345\212\237\350\203\275\347\273\223\346\236\204\345\233\276.png" (100%) mode change 100755 => 100644 rename "zh-cn/device-dev/security/figures/\345\256\211\345\205\250\344\277\235\351\232\234\347\244\272\346\204\217\345\233\276.png" => "zh-cn/device-dev/security/figure/\345\256\211\345\205\250\344\277\235\351\232\234\347\244\272\346\204\217\345\233\276.png" (100%) mode change 100755 => 100644 rename "zh-cn/device-dev/security/figures/\350\256\276\345\244\207\351\227\264\345\273\272\347\253\213\345\217\257\344\277\241\345\205\263\347\263\273\346\265\201\347\250\213\345\233\276.png" => "zh-cn/device-dev/security/figure/\350\256\276\345\244\207\351\227\264\345\273\272\347\253\213\345\217\257\344\277\241\345\205\263\347\263\273\346\265\201\347\250\213\345\233\276.png" (100%) mode change 100755 => 100644 delete mode 100755 zh-cn/device-dev/security/public_sys-resources/icon-caution.gif delete mode 100755 zh-cn/device-dev/security/public_sys-resources/icon-danger.gif delete mode 100755 zh-cn/device-dev/security/public_sys-resources/icon-note.gif delete mode 100755 zh-cn/device-dev/security/public_sys-resources/icon-notice.gif delete mode 100755 zh-cn/device-dev/security/public_sys-resources/icon-tip.gif delete mode 100755 zh-cn/device-dev/security/public_sys-resources/icon-warning.gif create mode 100644 zh-cn/device-dev/security/safety-protection-privacyguide.md create mode 100644 zh-cn/device-dev/security/safety-safeguide-security.md create mode 100644 zh-cn/device-dev/security/safety.md delete mode 100755 "zh-cn/device-dev/security/\345\256\211\345\205\250\346\214\207\345\215\227.md" delete mode 100755 "zh-cn/device-dev/security/\351\232\220\347\247\201\344\277\235\346\212\244.md" delete mode 100755 "zh-cn/device-dev/subsystems/AI\345\274\225\346\223\216\346\241\206\346\236\266\345\274\200\345\217\221\346\214\207\345\215\227.md" delete mode 100755 "zh-cn/device-dev/subsystems/AI\346\241\206\346\236\266.md" delete mode 100755 zh-cn/device-dev/subsystems/DFX.md delete mode 100755 "zh-cn/device-dev/subsystems/OTA\345\215\207\347\272\247.md" delete mode 100755 "zh-cn/device-dev/subsystems/SDK\345\274\200\345\217\221\350\277\207\347\250\213.md" delete mode 100755 "zh-cn/device-dev/subsystems/Sensor\346\234\215\345\212\241.md" delete mode 100755 "zh-cn/device-dev/subsystems/Sensor\346\234\215\345\212\241\345\255\220\347\263\273\344\275\277\347\224\250\346\214\207\345\257\274.md" delete mode 100755 "zh-cn/device-dev/subsystems/Sensor\346\234\215\345\212\241\345\255\220\347\263\273\346\246\202\350\277\260.md" delete mode 100755 "zh-cn/device-dev/subsystems/XTS\350\256\244\350\257\201\345\255\220\347\263\273\347\273\237\345\274\200\345\217\221\346\214\207\345\215\227.md" delete mode 100644 "zh-cn/device-dev/subsystems/bytrace\344\275\277\347\224\250\346\214\207\345\257\274.md" rename zh-cn/device-dev/subsystems/{figures => figure}/20200721-223604(eSpace).gif (100%) mode change 100755 => 100644 rename "zh-cn/device-dev/subsystems/figures/Ability\344\270\216AbilitySlice\347\232\204\345\205\263\347\263\273\345\233\276.png" => "zh-cn/device-dev/subsystems/figure/Ability\344\270\216AbilitySlice\347\232\204\345\205\263\347\263\273\345\233\276.png" (100%) mode change 100755 => 100644 rename "zh-cn/device-dev/subsystems/figures/Ability\345\255\220\347\263\273\347\273\237\346\241\206\346\236\266\345\233\276.png" => "zh-cn/device-dev/subsystems/figure/Ability\345\255\220\347\263\273\347\273\237\346\241\206\346\236\266\345\233\276.png" (100%) mode change 100755 => 100644 rename "zh-cn/device-dev/subsystems/figures/Ability\347\256\241\347\220\206\346\234\215\345\212\241\345\222\214\345\214\205\347\256\241\347\220\206\346\234\215\345\212\241\345\220\257\345\212\250.png" => "zh-cn/device-dev/subsystems/figure/Ability\347\256\241\347\220\206\346\234\215\345\212\241\345\222\214\345\214\205\347\256\241\347\220\206\346\234\215\345\212\241\345\220\257\345\212\250.png" (100%) mode change 100755 => 100644 rename "zh-cn/device-dev/subsystems/figures/LiteOS-A\345\271\263\345\217\260dump\347\263\273\347\273\237\345\261\236\346\200\247\350\276\223\345\207\272.png" => "zh-cn/device-dev/subsystems/figure/LiteOS-A\345\271\263\345\217\260dump\347\263\273\347\273\237\345\261\236\346\200\247\350\276\223\345\207\272.png" (100%) mode change 100755 => 100644 rename "zh-cn/device-dev/subsystems/figures/LiteOS-M\345\271\263\345\217\260dump\347\263\273\347\273\237\345\261\236\346\200\247\350\276\223\345\207\272.png" => "zh-cn/device-dev/subsystems/figure/LiteOS-M\345\271\263\345\217\260dump\347\263\273\347\273\237\345\261\236\346\200\247\350\276\223\345\207\272.png" (100%) mode change 100755 => 100644 rename "zh-cn/device-dev/subsystems/figures/UIButton\347\202\271\345\207\273\346\225\210\346\236\234.gif" => "zh-cn/device-dev/subsystems/figure/UIButton\347\202\271\345\207\273\346\225\210\346\236\234.gif" (100%) mode change 100755 => 100644 rename "zh-cn/device-dev/subsystems/figures/ViewGroup\346\267\273\345\212\240view\345\256\236\344\276\213\346\225\210\346\236\234\345\233\276.png" => "zh-cn/device-dev/subsystems/figure/ViewGroup\346\267\273\345\212\240view\345\256\236\344\276\213\346\225\210\346\236\234\345\233\276.png" (100%) mode change 100755 => 100644 rename zh-cn/device-dev/subsystems/{figures => figure}/unnaming.png (100%) mode change 100755 => 100644 rename zh-cn/device-dev/subsystems/{figures => figure}/zh-cn_image_0000001051782526.png (100%) mode change 100755 => 100644 rename zh-cn/device-dev/subsystems/{figures => figure}/zh-cn_image_0000001052582522.png (100%) mode change 100755 => 100644 rename zh-cn/device-dev/subsystems/{figures => figure}/zh-cn_image_0000001052662559.png (100%) mode change 100755 => 100644 rename zh-cn/device-dev/subsystems/{figures => figure}/zh-cn_image_0000001052782555.png (100%) mode change 100755 => 100644 rename zh-cn/device-dev/subsystems/{figures => figure}/zh-cn_image_0000001052942531.png (100%) mode change 100755 => 100644 rename zh-cn/device-dev/subsystems/{figures => figure}/zh-cn_image_0000001053207924.gif (100%) mode change 100755 => 100644 rename zh-cn/device-dev/subsystems/{figures => figure}/zh-cn_image_0000001053247975.gif (100%) mode change 100755 => 100644 rename zh-cn/device-dev/subsystems/{figures => figure}/zh-cn_image_0000001054101094.png (100%) mode change 100755 => 100644 rename zh-cn/device-dev/subsystems/{figures => figure}/zh-cn_image_0000001054421113.png (100%) mode change 100755 => 100644 rename zh-cn/device-dev/subsystems/{figures => figure}/zh-cn_image_0000001059334449.png (100%) mode change 100755 => 100644 rename zh-cn/device-dev/subsystems/{figures => figure}/zh-cn_image_0000001060200050.png (100%) mode change 100755 => 100644 rename zh-cn/device-dev/subsystems/{figures => figure}/zh-cn_image_0000001061889268.png (100%) mode change 100755 => 100644 rename zh-cn/device-dev/subsystems/{figures => figure}/zh-cn_image_0000001062334618.png (100%) mode change 100755 => 100644 rename zh-cn/device-dev/subsystems/{figures => figure}/zh-cn_image_0000001062476933.png (100%) mode change 100755 => 100644 rename zh-cn/device-dev/subsystems/{figures => figure}/zh-cn_image_0000001062942690.png (100%) mode change 100755 => 100644 rename zh-cn/device-dev/subsystems/{figures => figure}/zh-cn_image_0000001063839940.png (100%) mode change 100755 => 100644 rename zh-cn/device-dev/subsystems/{figures => figure}/zh-cn_image_0000001077724150.png (100%) mode change 100755 => 100644 rename zh-cn/device-dev/subsystems/{figures => figure}/zh-cn_image_0000001077727032.png (100%) mode change 100755 => 100644 rename zh-cn/device-dev/subsystems/{figures => figure}/zh-cn_image_0000001119924146.gif (100%) rename zh-cn/device-dev/subsystems/{figures => figure}/zh-cn_image_0000001166643927.jpg (100%) rename "zh-cn/device-dev/subsystems/figures/\345\212\250\347\224\273\345\256\236\347\216\260\346\225\210\346\236\234\345\233\276.gif" => "zh-cn/device-dev/subsystems/figure/\345\212\250\347\224\273\345\256\236\347\216\260\346\225\210\346\236\234\345\233\276.gif" (100%) mode change 100755 => 100644 rename "zh-cn/device-dev/subsystems/figures/\345\214\205\347\256\241\347\220\206\345\255\220\347\263\273\347\273\237\346\241\206\346\236\266\345\233\276.png" => "zh-cn/device-dev/subsystems/figure/\345\214\205\347\256\241\347\220\206\345\255\220\347\263\273\347\273\237\346\241\206\346\236\266\345\233\276.png" (100%) mode change 100755 => 100644 rename "zh-cn/device-dev/subsystems/figures/\345\233\276\347\211\2071.png" => "zh-cn/device-dev/subsystems/figure/\345\233\276\347\211\2071.png" (100%) mode change 100755 => 100644 rename "zh-cn/device-dev/subsystems/figures/\345\256\211\345\205\250\345\255\220\347\263\273\347\273\237.png" => "zh-cn/device-dev/subsystems/figure/\345\256\211\345\205\250\345\255\220\347\263\273\347\273\237.png" (100%) mode change 100755 => 100644 rename "zh-cn/device-dev/subsystems/figures/\345\271\263\351\223\272\346\250\241\345\274\217\345\233\276\347\211\207\346\225\210\346\236\234\345\233\276.png" => "zh-cn/device-dev/subsystems/figure/\345\271\263\351\223\272\346\250\241\345\274\217\345\233\276\347\211\207\346\225\210\346\236\234\345\233\276.png" (100%) mode change 100755 => 100644 rename "zh-cn/device-dev/subsystems/figures/\345\272\224\347\224\250\345\220\257\345\212\250\346\265\201\347\250\213.png" => "zh-cn/device-dev/subsystems/figure/\345\272\224\347\224\250\345\220\257\345\212\250\346\265\201\347\250\213.png" (100%) mode change 100755 => 100644 rename "zh-cn/device-dev/subsystems/figures/\346\217\222\344\273\266\344\276\235\350\265\226-(2).jpg" => "zh-cn/device-dev/subsystems/figure/\346\217\222\344\273\266\344\276\235\350\265\226-(2).jpg" (100%) mode change 100755 => 100644 rename "zh-cn/device-dev/subsystems/figures/\346\231\256\351\200\232\345\256\271\345\231\250\347\261\273\347\273\204\344\273\266\347\273\223\346\236\204.png" => "zh-cn/device-dev/subsystems/figure/\346\231\256\351\200\232\345\256\271\345\231\250\347\261\273\347\273\204\344\273\266\347\273\223\346\236\204.png" (100%) mode change 100755 => 100644 rename "zh-cn/device-dev/subsystems/figures/\346\231\256\351\200\232\347\273\204\344\273\266\346\240\221\347\273\223\346\236\204.png" => "zh-cn/device-dev/subsystems/figure/\346\231\256\351\200\232\347\273\204\344\273\266\346\240\221\347\273\223\346\236\204.png" (100%) mode change 100755 => 100644 rename "zh-cn/device-dev/subsystems/figures/\346\260\264\345\271\263-\345\236\202\347\233\264\346\226\271\345\220\221\345\217\257\346\273\221\345\212\250\346\225\210\346\236\234\345\233\276.gif" => "zh-cn/device-dev/subsystems/figure/\346\260\264\345\271\263-\345\236\202\347\233\264\346\226\271\345\220\221\345\217\257\346\273\221\345\212\250\346\225\210\346\236\234\345\233\276.gif" (100%) mode change 100755 => 100644 rename "zh-cn/device-dev/subsystems/figures/\346\265\213\350\257\225\345\271\263\345\217\260\346\236\266\346\236\204.png" => "zh-cn/device-dev/subsystems/figure/\346\265\213\350\257\225\345\271\263\345\217\260\346\236\266\346\236\204.png" (100%) mode change 100755 => 100644 rename "zh-cn/device-dev/subsystems/figures/\346\265\213\350\257\225\345\271\263\345\217\260\350\277\220\350\241\214\346\227\266\345\272\217.png" => "zh-cn/device-dev/subsystems/figure/\346\265\213\350\257\225\345\271\263\345\217\260\350\277\220\350\241\214\346\227\266\345\272\217.png" (100%) mode change 100755 => 100644 rename "zh-cn/device-dev/subsystems/figures/\347\273\204\344\273\266\346\240\221\347\273\223\346\236\204\347\244\272\346\204\217\345\233\276.png" => "zh-cn/device-dev/subsystems/figure/\347\273\204\344\273\266\346\240\221\347\273\223\346\236\204\347\244\272\346\204\217\345\233\276.png" (100%) mode change 100755 => 100644 rename "zh-cn/device-dev/subsystems/figures/\347\274\226\350\257\221\346\236\204\345\273\272\346\265\201\347\250\213.jpg" => "zh-cn/device-dev/subsystems/figure/\347\274\226\350\257\221\346\236\204\345\273\272\346\265\201\347\250\213.jpg" (100%) mode change 100755 => 100644 rename "zh-cn/device-dev/subsystems/figures/\350\207\252\351\200\202\345\272\224\346\250\241\345\274\217\345\233\276\347\211\207\346\225\210\346\236\234\345\233\276.png" => "zh-cn/device-dev/subsystems/figure/\350\207\252\351\200\202\345\272\224\346\250\241\345\274\217\345\233\276\347\211\207\346\225\210\346\236\234\345\233\276.png" (100%) mode change 100755 => 100644 rename "zh-cn/device-dev/subsystems/figures/\350\256\276\347\275\2562-2\347\275\221\346\240\274\345\271\266\346\267\273\345\212\2404\344\270\252button\347\273\204\344\273\266\350\277\233\350\241\214\345\270\203\345\261\200.png" => "zh-cn/device-dev/subsystems/figure/\350\256\276\347\275\2562-2\347\275\221\346\240\274\345\271\266\346\267\273\345\212\2404\344\270\252button\347\273\204\344\273\266\350\277\233\350\241\214\345\270\203\345\261\200.png" (100%) mode change 100755 => 100644 delete mode 100644 zh-cn/device-dev/subsystems/figures/RIL-Adapter.png delete mode 100755 "zh-cn/device-dev/subsystems/figures/\345\216\273\347\224\265.png" delete mode 100644 "zh-cn/device-dev/subsystems/figures/\346\235\245\347\224\265.png" delete mode 100644 "zh-cn/device-dev/subsystems/hdc_std-\344\275\277\347\224\250\346\214\207\345\257\274.md" delete mode 100644 "zh-cn/device-dev/subsystems/hdc_std\345\270\270\350\247\201\351\227\256\351\242\230.md" delete mode 100755 zh-cn/device-dev/subsystems/public_sys-resources/icon-caution.gif delete mode 100755 zh-cn/device-dev/subsystems/public_sys-resources/icon-danger.gif delete mode 100755 zh-cn/device-dev/subsystems/public_sys-resources/icon-note.gif delete mode 100755 zh-cn/device-dev/subsystems/public_sys-resources/icon-notice.gif delete mode 100755 zh-cn/device-dev/subsystems/public_sys-resources/icon-tip.gif delete mode 100755 zh-cn/device-dev/subsystems/public_sys-resources/icon-warning.gif rename "zh-cn/device-dev/subsystems/\345\224\244\351\206\222\350\257\215\350\257\206\345\210\253\351\205\215\347\275\256\346\226\207\344\273\266\347\232\204\345\274\200\345\217\221\347\244\272\344\276\213.md" => zh-cn/device-dev/subsystems/subsys-aiframework-demo-conf.md (100%) mode change 100755 => 100644 rename "zh-cn/device-dev/subsystems/\345\224\244\351\206\222\350\257\215\350\257\206\345\210\253\346\217\222\344\273\266\347\232\204\345\274\200\345\217\221\347\244\272\344\276\213.md" => zh-cn/device-dev/subsystems/subsys-aiframework-demo-plugin.md (100%) mode change 100755 => 100644 create mode 100644 zh-cn/device-dev/subsystems/subsys-aiframework-demo-sdk.md create mode 100644 zh-cn/device-dev/subsystems/subsys-aiframework-demo.md rename "zh-cn/device-dev/subsystems/\351\205\215\347\275\256\346\226\207\344\273\266\347\232\204\345\274\200\345\217\221\350\277\207\347\250\213.md" => zh-cn/device-dev/subsystems/subsys-aiframework-devguide-conf.md (100%) mode change 100755 => 100644 rename "zh-cn/device-dev/subsystems/\346\217\222\344\273\266\347\232\204\345\274\200\345\217\221\350\277\207\347\250\213.md" => zh-cn/device-dev/subsystems/subsys-aiframework-devguide-plugin.md (100%) mode change 100755 => 100644 create mode 100644 zh-cn/device-dev/subsystems/subsys-aiframework-devguide-sdk.md create mode 100644 zh-cn/device-dev/subsystems/subsys-aiframework-devguide.md create mode 100644 zh-cn/device-dev/subsystems/subsys-aiframework-envbuild.md create mode 100644 zh-cn/device-dev/subsystems/subsys-aiframework-guide.md create mode 100644 zh-cn/device-dev/subsystems/subsys-aiframework-tech-codemanage.md rename "zh-cn/device-dev/subsystems/\346\216\245\345\217\243\345\274\200\345\217\221\350\247\204\350\214\203.md" => zh-cn/device-dev/subsystems/subsys-aiframework-tech-interface.md (100%) mode change 100755 => 100644 rename "zh-cn/device-dev/subsystems/\345\221\275\345\220\215\350\247\204\350\214\203.md" => zh-cn/device-dev/subsystems/subsys-aiframework-tech-name.md (100%) mode change 100755 => 100644 create mode 100644 zh-cn/device-dev/subsystems/subsys-aiframework-tech.md create mode 100644 zh-cn/device-dev/subsystems/subsys-aiframework.md create mode 100644 zh-cn/device-dev/subsystems/subsys-application-framework-builden.md rename "zh-cn/device-dev/subsystems/\345\274\200\345\217\221\345\256\236\344\276\213.md" => zh-cn/device-dev/subsystems/subsys-application-framework-demo.md (100%) mode change 100755 => 100644 create mode 100644 zh-cn/device-dev/subsystems/subsys-application-framework-guide.md create mode 100644 zh-cn/device-dev/subsystems/subsys-application-framework-overview.md create mode 100644 zh-cn/device-dev/subsystems/subsys-application-framework.md rename "zh-cn/device-dev/subsystems/appspawn\345\272\224\347\224\250\345\255\265\345\214\226\347\273\204\344\273\266.md" => zh-cn/device-dev/subsystems/subsys-boot-appspawn.md (100%) mode change 100755 => 100644 rename "zh-cn/device-dev/subsystems/bootstrap\346\234\215\345\212\241\345\220\257\345\212\250\347\273\204\344\273\266.md" => zh-cn/device-dev/subsystems/subsys-boot-bootstrap.md (100%) mode change 100755 => 100644 create mode 100644 zh-cn/device-dev/subsystems/subsys-boot-faqs.md rename "zh-cn/device-dev/subsystems/init\345\220\257\345\212\250\345\274\225\345\257\274\347\273\204\344\273\266.md" => zh-cn/device-dev/subsystems/subsys-boot-init.md (100%) mode change 100755 => 100644 create mode 100644 zh-cn/device-dev/subsystems/subsys-boot-overview.md rename "zh-cn/device-dev/subsystems/\345\217\202\350\200\203.md" => zh-cn/device-dev/subsystems/subsys-boot-ref.md (100%) mode change 100755 => 100644 rename "zh-cn/device-dev/subsystems/syspara\347\263\273\347\273\237\345\261\236\346\200\247\347\273\204\344\273\266.md" => zh-cn/device-dev/subsystems/subsys-boot-syspara.md (100%) mode change 100755 => 100644 create mode 100644 zh-cn/device-dev/subsystems/subsys-boot.md create mode 100644 zh-cn/device-dev/subsystems/subsys-build-mini-lite.md create mode 100644 zh-cn/device-dev/subsystems/subsys-build-mini.md create mode 100644 zh-cn/device-dev/subsystems/subsys-build-standard-large.md create mode 100644 zh-cn/device-dev/subsystems/subsys-build-standard.md create mode 100644 zh-cn/device-dev/subsystems/subsys-build.md rename "zh-cn/device-dev/subsystems/Sensor\346\234\215\345\212\241\345\255\220\347\263\273\344\275\277\347\224\250\345\256\236\344\276\213.md" => zh-cn/device-dev/subsystems/subsys-densor-demo.md (100%) mode change 100755 => 100644 create mode 100644 zh-cn/device-dev/subsystems/subsys-densor-guide.md create mode 100644 zh-cn/device-dev/subsystems/subsys-densor-overview.md create mode 100644 zh-cn/device-dev/subsystems/subsys-densor.md rename "zh-cn/device-dev/subsystems/HiLog_Lite\345\274\200\345\217\221\346\214\207\345\257\274.md" => zh-cn/device-dev/subsystems/subsys-dfx-hilog-lite.md (100%) mode change 100755 => 100644 rename "zh-cn/device-dev/subsystems/HiLog\345\274\200\345\217\221\346\214\207\345\257\274.md" => zh-cn/device-dev/subsystems/subsys-dfx-hilog-rich.md (100%) mode change 100755 => 100644 rename "zh-cn/device-dev/subsystems/HiSysEvent\345\274\200\345\217\221\346\214\207\345\257\274.md" => zh-cn/device-dev/subsystems/subsys-dfx-hisysevent.md (100%) mode change 100755 => 100644 create mode 100644 zh-cn/device-dev/subsystems/subsys-dfx-hisyseventread.md rename "zh-cn/device-dev/subsystems/DFX\346\246\202\350\277\260.md" => zh-cn/device-dev/subsystems/subsys-dfx-overview.md (100%) mode change 100755 => 100644 create mode 100644 zh-cn/device-dev/subsystems/subsys-dfx.md create mode 100644 zh-cn/device-dev/subsystems/subsys-graphics-animation-guide.md create mode 100644 zh-cn/device-dev/subsystems/subsys-graphics-bundle-guide1.md create mode 100644 zh-cn/device-dev/subsystems/subsys-graphics-bundle-guide2.md create mode 100644 zh-cn/device-dev/subsystems/subsys-graphics-bundle-guide3.md rename "zh-cn/device-dev/subsystems/\345\233\276\345\275\242\345\233\276\345\203\217\346\246\202\350\277\260.md" => zh-cn/device-dev/subsystems/subsys-graphics-overview.md (100%) mode change 100755 => 100644 create mode 100644 zh-cn/device-dev/subsystems/subsys-graphics.md create mode 100644 zh-cn/device-dev/subsystems/subsys-multimedia-camera-overview.md create mode 100644 zh-cn/device-dev/subsystems/subsys-multimedia-camera-photo-guide.md rename "zh-cn/device-dev/subsystems/\351\242\204\350\247\210\345\274\200\345\217\221\346\214\207\345\257\274.md" => zh-cn/device-dev/subsystems/subsys-multimedia-camera-preview-guide.md (100%) mode change 100755 => 100644 rename "zh-cn/device-dev/subsystems/\345\275\225\345\203\217\345\274\200\345\217\221\346\214\207\345\257\274.md" => zh-cn/device-dev/subsystems/subsys-multimedia-camera-record-guide.md (100%) mode change 100755 => 100644 create mode 100644 zh-cn/device-dev/subsystems/subsys-multimedia-camera.md rename "zh-cn/device-dev/subsystems/\351\237\263\350\247\206\351\242\221\345\274\200\345\217\221\346\246\202\350\277\260.md" => zh-cn/device-dev/subsystems/subsys-multimedia-video-overview.md (100%) mode change 100755 => 100644 rename "zh-cn/device-dev/subsystems/\351\237\263\350\247\206\351\242\221\346\222\255\346\224\276\345\274\200\345\217\221\346\214\207\345\257\274.md" => zh-cn/device-dev/subsystems/subsys-multimedia-video-play-guide.md (100%) mode change 100755 => 100644 rename "zh-cn/device-dev/subsystems/\351\237\263\350\247\206\351\242\221\345\275\225\345\210\266\345\274\200\345\217\221\346\214\207\345\257\274.md" => zh-cn/device-dev/subsystems/subsys-multimedia-video-record-guide.md (100%) mode change 100755 => 100644 create mode 100644 zh-cn/device-dev/subsystems/subsys-multimedia-video.md create mode 100644 zh-cn/device-dev/subsystems/subsys-multimedia.md create mode 100644 zh-cn/device-dev/subsystems/subsys-ota-guide.md rename "zh-cn/device-dev/subsystems/\345\210\206\345\270\203\345\274\217\350\277\234\347\250\213\345\220\257\345\212\250.md" => zh-cn/device-dev/subsystems/subsys-remote-start.md (100%) mode change 100755 => 100644 rename "zh-cn/device-dev/subsystems/IPC\351\200\232\344\277\241\351\211\264\346\235\203\345\274\200\345\217\221\346\214\207\345\257\274.md" => zh-cn/device-dev/subsystems/subsys-security-communicationverify.md (100%) mode change 100755 => 100644 create mode 100644 zh-cn/device-dev/subsystems/subsys-security-overview.md create mode 100644 zh-cn/device-dev/subsystems/subsys-security-rightmanagement.md create mode 100644 zh-cn/device-dev/subsystems/subsys-security-sigverify.md create mode 100644 zh-cn/device-dev/subsystems/subsys-security.md create mode 100644 zh-cn/device-dev/subsystems/subsys-testguide-test.md create mode 100644 zh-cn/device-dev/subsystems/subsys-toolchain-bytrace-guide.md create mode 100644 zh-cn/device-dev/subsystems/subsys-toolchain-hdc-guide.md create mode 100644 zh-cn/device-dev/subsystems/subsys-toolchain.md rename "zh-cn/device-dev/subsystems/\345\205\254\345\205\261\345\237\272\347\241\200\345\272\223\345\270\270\350\247\201\351\227\256\351\242\230.md" => zh-cn/device-dev/subsystems/subsys-utils-faqs.md (100%) mode change 100755 => 100644 create mode 100644 zh-cn/device-dev/subsystems/subsys-utils-guide.md rename "zh-cn/device-dev/subsystems/\345\205\254\345\205\261\345\237\272\347\241\200\345\272\223\346\246\202\350\277\260.md" => zh-cn/device-dev/subsystems/subsys-utils-overview.md (100%) mode change 100755 => 100644 create mode 100644 zh-cn/device-dev/subsystems/subsys-utils.md create mode 100644 zh-cn/device-dev/subsystems/subsys-xts-guide.md create mode 100644 zh-cn/device-dev/subsystems/subsys.md delete mode 100755 "zh-cn/device-dev/subsystems/\344\273\243\347\240\201\347\256\241\347\220\206\350\247\204\350\214\203.md" delete mode 100755 "zh-cn/device-dev/subsystems/\345\205\254\345\205\261\345\237\272\347\241\200.md" delete mode 100755 "zh-cn/device-dev/subsystems/\345\205\254\345\205\261\345\237\272\347\241\200\345\272\223\345\274\200\345\217\221\346\214\207\345\257\274.md" delete mode 100755 "zh-cn/device-dev/subsystems/\345\212\250\347\224\273\345\274\200\345\217\221\346\214\207\345\257\274.md" delete mode 100755 "zh-cn/device-dev/subsystems/\345\220\257\345\212\250\346\201\242\345\244\215.md" delete mode 100755 "zh-cn/device-dev/subsystems/\345\220\257\345\212\250\346\201\242\345\244\215\345\255\220\347\263\273\347\273\237\346\246\202\350\277\260.md" delete mode 100755 "zh-cn/device-dev/subsystems/\345\224\244\351\206\222\350\257\215\350\257\206\345\210\253SDK\347\232\204\345\274\200\345\217\221\347\244\272\344\276\213.md" delete mode 100755 "zh-cn/device-dev/subsystems/\345\233\276\345\275\242\345\233\276\345\203\217.md" delete mode 100755 "zh-cn/device-dev/subsystems/\345\252\222\344\275\223.md" delete mode 100755 "zh-cn/device-dev/subsystems/\345\256\211\345\205\250.md" delete mode 100755 "zh-cn/device-dev/subsystems/\345\256\271\345\231\250\347\261\273\347\273\204\344\273\266\345\274\200\345\217\221\346\214\207\345\257\274.md" delete mode 100755 "zh-cn/device-dev/subsystems/\345\270\203\345\261\200\345\256\271\345\231\250\347\261\273\347\273\204\344\273\266\345\274\200\345\217\221\346\214\207\345\257\274.md" delete mode 100755 "zh-cn/device-dev/subsystems/\345\270\270\350\247\201\351\227\256\351\242\230.md" delete mode 100755 "zh-cn/device-dev/subsystems/\345\272\224\347\224\250\346\235\203\351\231\220\347\256\241\347\220\206\345\274\200\345\217\221\346\214\207\345\257\274.md" delete mode 100755 "zh-cn/device-dev/subsystems/\345\272\224\347\224\250\351\252\214\347\255\276\345\274\200\345\217\221\346\214\207\345\257\274.md" delete mode 100755 "zh-cn/device-dev/subsystems/\345\274\200\345\217\221\345\256\236\344\276\213-6.md" delete mode 100644 "zh-cn/device-dev/subsystems/\345\274\200\345\217\221\346\214\207\345\257\274-3.md" delete mode 100755 "zh-cn/device-dev/subsystems/\345\274\200\345\217\221\346\214\207\345\257\274.md" delete mode 100755 "zh-cn/device-dev/subsystems/\345\274\200\345\217\221\347\244\272\344\276\213.md" delete mode 100755 "zh-cn/device-dev/subsystems/\346\212\200\346\234\257\350\247\204\350\214\203.md" delete mode 100755 "zh-cn/device-dev/subsystems/\346\213\215\347\205\247\345\274\200\345\217\221\346\214\207\345\257\274.md" delete mode 100755 "zh-cn/device-dev/subsystems/\346\220\255\345\273\272\347\216\257\345\242\203-2.md" delete mode 100755 "zh-cn/device-dev/subsystems/\346\220\255\345\273\272\347\216\257\345\242\203.md" delete mode 100755 "zh-cn/device-dev/subsystems/\346\231\256\351\200\232\347\273\204\344\273\266\345\274\200\345\217\221\346\214\207\345\257\274.md" delete mode 100644 "zh-cn/device-dev/subsystems/\346\240\207\345\207\206\347\263\273\347\273\237\347\274\226\350\257\221\346\236\204\345\273\272\346\214\207\345\257\274.md" delete mode 100644 "zh-cn/device-dev/subsystems/\346\246\202\350\277\260-7.md" delete mode 100755 "zh-cn/device-dev/subsystems/\346\246\202\350\277\260.md" delete mode 100755 "zh-cn/device-dev/subsystems/\346\265\213\350\257\225.md" delete mode 100755 "zh-cn/device-dev/subsystems/\347\224\250\346\210\267\347\250\213\345\272\217\346\241\206\346\236\266.md" delete mode 100755 "zh-cn/device-dev/subsystems/\347\233\270\346\234\272.md" delete mode 100755 "zh-cn/device-dev/subsystems/\347\233\270\346\234\272\345\274\200\345\217\221\346\246\202\350\277\260.md" delete mode 100644 "zh-cn/device-dev/subsystems/\347\240\224\345\217\221\345\267\245\345\205\267\351\223\276.md" delete mode 100755 "zh-cn/device-dev/subsystems/\347\274\226\350\257\221\346\236\204\345\273\272.md" delete mode 100755 "zh-cn/device-dev/subsystems/\347\274\226\350\257\221\346\236\204\345\273\272\344\275\277\347\224\250\346\214\207\345\257\274-1.md" delete mode 100755 "zh-cn/device-dev/subsystems/\347\274\226\350\257\221\346\236\204\345\273\272\344\275\277\347\224\250\346\214\207\345\257\274.md" delete mode 100755 "zh-cn/device-dev/subsystems/\347\274\226\350\257\221\346\236\204\345\273\272\345\270\270\350\247\201\351\227\256\351\242\230.md" delete mode 100755 "zh-cn/device-dev/subsystems/\347\274\226\350\257\221\346\236\204\345\273\272\346\246\202\350\277\260-0.md" delete mode 100755 "zh-cn/device-dev/subsystems/\347\274\226\350\257\221\346\236\204\345\273\272\346\246\202\350\277\260.md" delete mode 100755 "zh-cn/device-dev/subsystems/\350\275\273\351\207\217\345\222\214\345\260\217\345\236\213\347\263\273\347\273\237\347\274\226\350\257\221\346\236\204\345\273\272\346\214\207\345\257\274.md" delete mode 100755 "zh-cn/device-dev/subsystems/\351\237\263\350\247\206\351\242\221.md" diff --git a/zh-cn/device-dev/bundles/Readme-CN.md b/zh-cn/device-dev/bundles/Readme-CN.md index 6b1ae76002..7233ea64d4 100755 --- a/zh-cn/device-dev/bundles/Readme-CN.md +++ b/zh-cn/device-dev/bundles/Readme-CN.md @@ -1,20 +1,12 @@ -# 组件开发 - -- [组件开发规范](组件开发规范.md) - - [概述](概述.md) - - [组件构成](组件构成.md) - - [组件管理](组件管理.md) - - [组件版本](组件版本.md) - - [发行版](发行版.md) - - [环境变量说明](环境变量说明.md) - -- [组件开发指南](组件开发指南.md) - - [概述](概述-0.md) - - [准备工作](准备工作.md) - - [组件开发](组件开发.md) - -- [组件开发示例](组件开发示例.md) - - [HPM介绍](HPM介绍.md) - - [环境准备](环境准备.md) - - [操作实例](操作实例.md) +# 组件开发指南 + +- [组件开发规范](bundles-standard-rules.md) +- [组件开发指南](bundles-guide.md) + - [组件开发指南](bundles-guide-overview.md) + - [准备工作](bundles-guide-prepare.md) + - [组件开发](bundles-guide-develop.md) +- [组件开发示例](bundles-demo.md) + - [HPM介绍](bundles-demo-hpmdescription.md) + - [环境准备](bundles-demo-environment.md) + - [操作实例](bundles-demo-devsample.md) diff --git a/zh-cn/device-dev/bundles/bundles-demo-devsample.md b/zh-cn/device-dev/bundles/bundles-demo-devsample.md new file mode 100644 index 0000000000..1de6091e00 --- /dev/null +++ b/zh-cn/device-dev/bundles/bundles-demo-devsample.md @@ -0,0 +1,54 @@ +# 操作实例 + +环境准备好后,接下来本文以Hi3861平台为例,演示如何利用HPM进行组件的安装、编译和打包。 + +1. 执行以下命令,初始化安装目录(目录名可自行设置): + + ``` + mkdir test3861 + cd test3861 + hpm init -t dist + ``` + + 初始化成功则显示: + + ``` + Initialization finished. + ``` + +2. 安装wifi\_iot发行版。 + + ``` + hpm install @ohos/wifi_iot + ``` + + 安装成功则显示: + + ``` + Installed. + ``` + + >![](../public_sys-resources/icon-note.gif) **说明:** + >Hi3516平台采用下述命令: + >``` + >hpm install @ohos/ip_camera_hi3516dv300 + >``` + >Hi3518平台采用下述命令: + >``` + >hpm install @ohos/ip_camera_hi3518ev300 + >``` + +3. 编译打包 + + ``` + hpm dist + ``` + + 编译成功会显示: + + ``` + {{name}}: distribution building completed. + ``` + +4. 上述所有命令执行成功后,在 ./out 目录下会生成编译结果,开发者可以将编译结果烧录到对应的开发板上进行测试。 + diff --git a/zh-cn/device-dev/bundles/bundles-demo-environment.md b/zh-cn/device-dev/bundles/bundles-demo-environment.md new file mode 100644 index 0000000000..1a05b2a302 --- /dev/null +++ b/zh-cn/device-dev/bundles/bundles-demo-environment.md @@ -0,0 +1,139 @@ +# 环境准备 + +- [linux服务器](#section20979554791) +- [安装Node.js](#section9954105413153) +- [安装HPM](#section15937194904819) +- [安装python环境](#section1621819180417) +- [安装文件打包工具](#section77617165913) +- [安装SCons](#section20558439191516) + +## linux服务器 + +准备一台装有Ubuntu 16.04 及以上 64 位系统的linux服务器(hpm是支持windows的,但是目前OpenHarmony开源的Hi3861、Hi3516、Hi3518三个解决方案都只支持Ubuntu)。 + +将linux shell改为bash: + +``` +ls -l $(which sh) +# 如果指向的不是bash,则按以下方式修改: +# 方法一:执行以下命令,然后选择no +dpkg-reconfigure dash +# 方法二:先删除sh,再重新创建软连接 +rm -f /bin/sh +ln -s bash /bin/sh +``` + +## 安装Node.js + +>![](../public_sys-resources/icon-note.gif) **说明:** +>如果配置的源的nodejs版本太低,可以执行以下语句后再执行apt-get install: +>``` +>curl -L https://deb.nodesource.com/setup_12.x | bash +>``` + +推荐安装 Node.js 12.x (包含 npm 6.14.4)或更高版本(推荐 12.13.0+): + +``` +sudo apt-get install nodejs +sudo apt-get install npm +``` + +查看版本: + +``` +node --version # 查看nodejs版本 +npm --version # 查看npm版本 +``` + +## 安装HPM + +通过 Node.js 自带的 npm(使用默认的源 https://registry.npmjs.org/ )安装 hpm-cli 命令行工具: + +``` +npm install -g @ohos/hpm-cli +``` + +安装完hpm-cli命令行工具后,执行以下命令可以查看hpm配置: + +``` +hpm config +``` + +上述命令执行后将会显示hpm的默认配置,您可以根据自己的喜好对默认配置进行修改,以下是hpm的常用配置: + +``` +registry = https://hpm.harmonyos.com # hpm注册中心地址,下载组件必须 +strictSsl = true # 通过https连接时,是否需要校验证书 +http_proxy = http://your-proxy-server:port # 配置HTTP代理 +https_proxy = http://your-proxy-server:port # 配置HTTPS代理 +``` + +hpm-cli的命令介绍可以参考:[hpm操作命令](bundles-standard-rules.md) + +## 安装python环境 + +需使用python3.7以上版本,采用以下命令进行安装: + +``` +sudo apt-get install python3.8 +sudo apt-get install python3-pip +sudo pip3 install setuptools +sudo pip3 install kconfiglib # 建议安装kconfiglib 13.2.0+版本 +``` + +>![](../public_sys-resources/icon-note.gif) **说明:** +>上述方式适用Hi3518和Hi3516两种平台,针对Hi3861平台采用以下方式安装python环境: +>``` +>sudo apt-get install python3.8 +>sudo apt-get install python3-pip +>sudo pip3 install setuptools +>sudo pip3 install kconfiglib # 建议安装kconfiglib 13.2.0+版本 +>sudo pip3 install pycryptodome +>sudo pip3 install six --upgrade --ignore-installed six +>sudo pip3 install ecdsa +>``` + +如果当前系统中既存在python2又存在python3,参考以下方法将默认python修改为python3: + +``` +ll `which python` +rm /usr/bin/python +ln -s python3.8 /usr/bin/python +``` + +## 安装文件打包工具 + +采用以下命令进行安装: + +``` +which mkfs.vfat # 如果没找到,执行以下命令安装 +sudo apt-get install dosfstools +which mcopy # 如果没找到,执行以下命令安装 +sudo apt-get install mtools +``` + +>![](../public_sys-resources/icon-note.gif) **说明:** +>Hi3518和Hi3516两种平台需要安装打包工具,Hi3861平台不需要。 + +## 安装SCons + +1. 打开Linux编译服务器终端。 +2. 运行如下命令,安装SCons安装包。 + + ``` + python3 -m pip install scons + ``` + +3. 运行如下命令,查看是否安装成功。如果安装成功,查询结果下图所示。 + + ``` + scons -v + ``` + + **图 1** SCons安装成功界面,版本要求3.0.4以上 + ![](figure/SCons安装成功界面-版本要求3-0-4以上-21.png "SCons安装成功界面-版本要求3-0-4以上-21") + + +>![](../public_sys-resources/icon-note.gif) **说明:** +>Hi3861平台需要安装SCons,Hi3518和Hi3516两种平台不需要。 + diff --git "a/zh-cn/device-dev/bundles/HPM\344\273\213\347\273\215.md" b/zh-cn/device-dev/bundles/bundles-demo-hpmdescription.md old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/bundles/HPM\344\273\213\347\273\215.md" rename to zh-cn/device-dev/bundles/bundles-demo-hpmdescription.md diff --git a/zh-cn/device-dev/bundles/bundles-demo.md b/zh-cn/device-dev/bundles/bundles-demo.md new file mode 100644 index 0000000000..bcdc877e6d --- /dev/null +++ b/zh-cn/device-dev/bundles/bundles-demo.md @@ -0,0 +1,9 @@ +# 组件开发示例 + +- **[HPM介绍](bundles-demo-hpmdescription.md)** + +- **[环境准备](bundles-demo-environment.md)** + +- **[操作实例](bundles-demo-devsample.md)** + + diff --git a/zh-cn/device-dev/bundles/bundles-guide-develop.md b/zh-cn/device-dev/bundles/bundles-guide-develop.md new file mode 100644 index 0000000000..bc462fd12d --- /dev/null +++ b/zh-cn/device-dev/bundles/bundles-guide-develop.md @@ -0,0 +1,240 @@ +# 组件开发 + +- [创建OpenHarmony组件](#section1976410130540) +- [新建组件](#section717481119145) +- [改造组件](#section102861955201410) +- [从模板创建组件](#section15882846181510) +- [编译组件](#section136732148541) +- [定义编译脚本](#section10274147111610) +- [执行编译](#section879301916172) +- [定义发行版](#section413216495619) +- [定义脚本](#section11503171219190) +- [发行](#section4694125521912) +- [烧录](#section1746331545413) +- [运行调试](#section6742131615549) + +## 创建OpenHarmony组件 + +创建OpenHarmony组件有如下几种方式: + +- 从头开发一个全新的组件。 +- 将一个现有的非组件的代码改造成组件。 +- hpm提供了一些组件模板方便快速创建组件。 + +## 新建组件 + +通常情况下,[HPM网站](https://hpm.harmonyOS.com)上能找到您开发常用的组件,如果现有的组件不能完全满足开发,这时可以自己动手开发一个组件。 + +如果您愿意,可以将组件发布到HPM的仓库中供其他用户使用。假设要在D:/source目录下新建一个全新的组件my-bundle: + +可以使用hpm init 创建该组件的脚手架代码,例如,进入D:/source目录,执行如下命令: + +``` +hpm init -t default -d demo my-bundle +``` + +会在 source 目录下生成如下文件: + +``` +mybundle +├── bundle.json # 组件元数据描述文件 +├── example # 测试组件功能的示例 +│ └── main.c +├── include # 组件的内部头文件 +│ └── mybundle.h +├── README.md # 组件的简要说明 +└── src # 组件的源代码 + └─ mybundle.c +``` + +接下来根据您的业务需要,实现组件内部的功能代码,完成代码开发后,通过git将代码(包括bundle.json文件)提交到组件代码托管仓库中(如gitee)。 + +## 改造组件 + +如果您已经有了代码,只是还不满足OpenHarmony的组件结构,需要改造成为hpm的组件包,只需要在当前要改造的代码目录下(例如mybundle2),执行如下命令,会提示您输入组件名称和版本。 + +``` +hpm init +``` + +1. 输入名称后回车(如mybundle2)。 +2. 输入版本后(如1.0.0)回车,在当前组件目录下会生成一个bundle.json文件。 +3. 打开bundle.json文件再添加其他的描述,这时候他已经是一个具备可发布的组件了。 + + ``` + $ hpm init + Your bundle will be created in dirname E:\demo\mybundle2 + ? bundle name mybundel2 + ? version 1.0.0 + Init finished! + ``` + + +1. 打开bundle.json文件修改其他信息(如作者,代码仓库,代码目录,命令脚本,依赖组件等),如下: + + ``` + { + "name": "mybundle2", + "version": "1.0.0", + "publishAs": "source", + "dirs":{ + ".":[ + "README.md" + ], + "src":[ + "test.c" + ], + "header":[ + "header/test.h" + ], + "src/common":[ + "src/common/foobar.txt" + ] + }, + "scripts": { + "build": "make -${args}" + }, + "dependencies": { + "@ohos/cjson": "^1.0.0", + "@ohos/": "^1.2.0" + } + } + ``` + + +## 从模板创建组件 + +hpm 除了提供了默认模板 default和simple两个简单的模板之外,其他模板均存储在服务器端。 + +可以使用命令hpm search -t template 从服务器端搜索模板。 + +![](figure/zh-cn_image_0000001051452177.png) + +根据description简要中的描述,找到适合的模板,基于模板可以快速创建一个组件的脚手架,执行如下初始化命令(指定-t -d 参数)。 + +``` +hpm init -t {templatename} -d dir name +``` + +- \{templatename\} :指的是模板名称。 +- -d 后面的参数dir:是要创建的组件所存放的路径。 +- name:为要创建的组件名称。 + +## 编译组件 + +完成代码开发后,需要对组件进行编译。hpm提供了命令集成的能力,您可以选择任意的适合项目的编译工具(如make,gcc,gn等等)。只需在当前项目的bundle.json文件中定义scripts脚本中的build命令,就可以通过执行hpm build执行编译。 + +## 定义编译脚本 + +以编译一个app目录下helloworld可执行文件为例: + +``` +app +├── BUILD.gn +├── include +│ └── helloworld.h +└── src + └── helloworld.c +``` + +在helloworld.c同级目录下新建一个BUILD.gn + +``` +touch BUILD.gn +vim BUILD.gn +``` + +以下是BUILD.gn的样例,仅供参考 + +``` +executable("hello_world") { + sources = [ + "src/helloworld.c" + ] + + include_dirs = [ + "include" + ] +} +``` + +>![](../public_sys-resources/icon-note.gif) **说明:** +>- “executable”是gn内置模板,可以用“gn help executable ”查看使用方法。 +>- “sources ”是源码路径,“include\_dirs ”是头文件路径。 + +## 执行编译 + +在当前文件夹下,执行编译命令: + +``` +hpm build +``` + +在完成一系列的编译动作后,显示build succeed。检查编译的输出结果: + +![](figure/zh-cn_image_0000001051770876.png) + +## 定义发行版 + +发行版是将一组组件组合起来的,编译生成可以运行的OpenHarmony解决方案,里面包含了较多依赖的组件,以及以脚本形式描述如何完整编译、链接这些组件。 + +## 定义脚本 + +bundle.json中定义 + +``` +{ +"name": "my_dist", +"version": "1.0.0", +"publishAs": "distribution", +"scripts": { +"dist": "make -${args}" + }, +"base": { +"name": "dist-bundle", +"version": "1.0.0" + }, +"envs": { +"args": "x86" + }, +"dependencies": { +} +} +``` + +## 发行 + +在当前发行版根目录下,执行如下命令。 + +``` +hpm dist +``` + +hpm-cli工具会自动执行编译,打包操作,将根据scripts定义的dist脚本生成镜像文件,如: + +``` +out +|-xxdist.img +|-xx.file +``` + +## 烧录 + +发行版的编译结果可以烧录到设备中运行,例如使用hiburn工具进行烧录。在发行版的bundle.json文件配置烧录参数。 + +``` +"scripts": { +"flash": "{$DEP_HIBURN}/hiburn" +}, +``` + +配置烧录相关的参数(参考烧录工具的说明进行配置)。 + +``` +hpm run flash +``` + +## 运行调试 + +将发行版的镜像烧录到设备中后,就可以启动运行调试了,由于运行调试和具体的开发板和IDE调试工具相关,此处不再详细描述。 + diff --git a/zh-cn/device-dev/bundles/bundles-guide-overview.md b/zh-cn/device-dev/bundles/bundles-guide-overview.md new file mode 100644 index 0000000000..332a8fc007 --- /dev/null +++ b/zh-cn/device-dev/bundles/bundles-guide-overview.md @@ -0,0 +1,54 @@ +# 概述 + +本章节将简要介绍如何开发OpenHarmony组件和发行版,并通过命令行工具方式完成组件创建、开发、编译、烧录、调试等开发过程。 + +- 一个组件(bundle)通常和一个代码仓库对应,在代码的基础上增加bundle.json、README文件、LICENSE描述文件。 +- 一个发行版(distribution)是由多个组件构成的。发行版中集合了一个完整系统的各种组件(如驱动、内核、框架、应用),可以用于设备的烧录。 + +**表 1** 组件和发行版的差异对比 + + + + + + + + + + + + + + + + + + + + + + + + +

异同点

+

组件

+

发行版

+

应用场景

+

面向功能特性开发

+

面向系统开发

+

内容

+

功能或特性的实现代码或二进制库

+

依赖的组件清单及编译构建脚本

+

完整程度

+

操作系统的一部分

+

一个完整操作系统版本

+

编译后结果

+

组件包

+

系统镜像

+
+ +**图 1** 组件和发行版的构成 + + +![](figure/组件0924.png) + diff --git a/zh-cn/device-dev/bundles/bundles-guide-prepare.md b/zh-cn/device-dev/bundles/bundles-guide-prepare.md new file mode 100644 index 0000000000..4068e7d7be --- /dev/null +++ b/zh-cn/device-dev/bundles/bundles-guide-prepare.md @@ -0,0 +1,84 @@ +# 准备工作 + +- [硬件要求](#section98535485518) +- [安装Node.js和hpm命令行工具](#section106591616205311) +- [更改hpm的配置(可选)](#section71821165412) +- [下载OpenHarmony代码](#section102338221707) +- [安装开发依赖的组件](#section19233183315020) + +## 硬件要求 + +- 准备设备开发的开发板(如Hi3861、Hi3516DV300、Hi3518EV300) +- 主机电脑(Windows工作台) +- Linux服务器 + +**图 1** 硬件环境连接关系 +![](figure/硬件环境连接关系.png "硬件环境连接关系") + +## 安装Node.js和hpm命令行工具 + +1. 安装Node.js。 + + 从官网下载并在本地安装Node.js. + + 推荐安装 [Node.js](https://nodejs.org/) 12.x \(包含 npm 6.14.4\)或更高版本 \(推荐 12.13.0+\)。 + +2. 通过Node.js自带的npm安装hpm-cli命令行工具。执行以下命令: + + ``` + npm install -g @ohos/hpm-cli + ``` + +3. 安装完成后执行如下命令,显示hpm版本,即安装成功。 + + ``` + hpm -V 或 hpm --version + ``` + +4. (可选)如果需要升级hpm版本,请执行如下命令: + + ``` + npm update -g @ohos/hpm-cli + ``` + + +## 更改hpm的配置(可选) + +安装完hpm-cli命令行工具后,执行以下命令可以查看hpm配置: + +``` +hpm config +``` + +上述命令执行后将会显示hpm的默认配置,您可以根据自己的喜好对默认配置进行修改,以下是hpm的常用配置: + +``` +registry = https://hpm.harmonyos.com/hpm/registry/api # hpm注册中心地址,下载组件必须 +login = https://hpm.harmonyos.com/hpm/auth/pk # hpm处理登录地址,发布组件必须 +loginUser = {your-account} # 配置hpm登录账号,发布组件必须 +shellPath = C:\WINDOWS\System32\cmd.exe # hpm命令执行使用的shell +globalRepo = C:\Users\yourname\.global # 配置全局安装的组件存放路径 +http_proxy = http://your-proxy-server:port # 配置HTTP代理 +https_proxy = http://your-proxy-server:port # 配置HTTPS代理 +``` + +hpm-cli的命令介绍可以参考:[hpm操作命令](bundles-guide-overview.md) + +## 下载OpenHarmony代码 + +参考[《源码获取》](../get-code/sourcecode-acquire.md)。 + +## 安装开发依赖的组件 + +hpm包管理器将常用开发开发工具(如烧录,编译,压缩等)也发布成了组件。可以通过如下命令方式进行安装,执行完该命令后,系统会自动将开发依赖的工具下载安装,且这些组件只需全局安装一次。 + +``` +hpm i -g @ohos/llvm +hpm i -g @ohos/ninja +hpm i -g @ohos/gn +hpm i -g @ohos/hc_gen +hpm i -g @ohos/sysroot +``` + +这是一组开发工具的组件包(如包含gn,ninja等工具),有了这些开发态的组件,就可以进行常规的源码组件的开发了。 + diff --git a/zh-cn/device-dev/bundles/bundles-guide.md b/zh-cn/device-dev/bundles/bundles-guide.md new file mode 100644 index 0000000000..ca5ee5824b --- /dev/null +++ b/zh-cn/device-dev/bundles/bundles-guide.md @@ -0,0 +1,9 @@ +# 组件开发指南 + +- **[概述](bundles-guide-overview.md)** + +- **[准备工作](bundles-guide-prepare.md)** + +- **[组件开发](bundles-guide-develop.md)** + + diff --git a/zh-cn/device-dev/bundles/bundles-standard-rules.md b/zh-cn/device-dev/bundles/bundles-standard-rules.md new file mode 100644 index 0000000000..350c2f80db --- /dev/null +++ b/zh-cn/device-dev/bundles/bundles-standard-rules.md @@ -0,0 +1,549 @@ +# 组件开发规范 + +- [概述](#section1725818533344) + - [定义](#section4821219183514) + - [组件划分原则](#section1089794263513) + - [组件依赖](#section25701647163710) + +- [组件构成](#section185538333914) + - [代码文件](#section8431268393) + - [说明文件](#section168121548173914) + - [元数据描述文件](#section7107181819406) + +- [组件管理](#section32061634104110) + - [依赖关系](#section791115242423) + - [hpm操作命令参考](#section1183205411429) + +- [组件版本](#section12612142864316) + - [版本号命名规范](#section1487612416432) + - [版本发布](#section1548171014440) + +- [发行版](#section1264139114413) +- [环境变量说明](#section15352105174512) + +## 概述 + +本文档将介绍组件的基本概念以及如何按照规范定义组件。 + +### 定义 + +OpenHarmony软件以组件\(bundle\)作为基本单元,从系统角度看,凡是运行在OpenHarmony上的软件都可以定义为组件;一般来讲,根据组件的应用范围,可以分为: + +- 板级组件:如board、arch、mcu这些与设备硬件相关的组件。 +- 系统组件:一组独立功能的集合,如内核、文件系统、框架等。 +- 应用组件:直接面向用户提供服务的应用\(如wifi\_iot,ip\_camera\)。 + +从形式上看,组件是为复用而生,一切可以复用的模块都可以定义为组件,可以分为: + +- 源代码 +- 二进制 +- 代码片段 +- 发行版 + +### 组件划分原则 + +原则上应尽可能划分为细颗粒度的组件,以满足最大限度的复用。主要考虑以下几点: + +- 独立性:组件的功能应该相对独立,支持独立编译,可以单独对外提供接口和服务; +- 耦合性:如果组件必须依赖其他的组件,才能对外提供服务,应考虑和被依赖的组件合并为一个组件。 +- 相关性:如果一组组件共同完成一项功能,且没有被其他组件依赖,未来也没有被依赖的可能,则可以考虑合并为一个组件。 + +### 组件依赖 + +组件的依赖关系分为两种:必选依赖和可选依赖。 + +- 必选依赖:是指组件A在完成某个功能时,必须引入组件B,调用B的接口或服务配合才能完成。称B为A的必选依赖。 +- 可选依赖:是在组件A在完成某个功能时,可以引入组件C,也可以引入组件D。C和D可以相互替换,称C和D为A的可选依赖。 + +## 组件构成 + +一个组件包一般包含如下内容: + +- 组件包的代码或库(src目录下的代码文件) +- ohos\_bundles文件夹(存放依赖的组件,安装组件时自动生成,无需提交到代码库) +- 组件包的说明文件\(README.md\) +- 组件包元数据声明文件\(bundle.json\) +- 开源许可文件\(LICENSE\) + + ``` + my-bundle + |_ohos_bundles + |_src + |_bundle.json + |_README.md + |_LICENSE + ``` + + +### 代码文件 + +组件的代码文件和普通的代码目录没有差异。但要注意的是,组件中对外暴露的接口(头文件),会被其他组件所引用,需要单独在bundle.json的dirs中声明。 + +### 说明文件 + +README.md,为markdown格式的描述关于组件自述说明文件。([语法参考](https://www.markdownguide.org/getting-started/)\) + +为了帮助他人在hpm上找到该组件,并更方便的使用它,在组件的根目录中包含一个README文件。 + +README文件可能包括如何安装,配置和使用组件包中的实例代码说明,以及可能会对用户有所帮助的任何其他信息。 + +每个组件的自述文件将显示在hpm系统的组件详情页面的描述中。 + +### 元数据描述文件 + +bundle.json文件是对当前组件的元数据描述,每个组件中必须包含一个bundle.json文件。 + +``` +{ + "name": "@myorg/demo-bundle", + "version": "1.0.0", + "license": "MIT", + "description": "bundle description", + "keywords": ["hos"], + "tags": ["applications", "drivers"], + "author": {"name":"","email":"","url":""}, + "contributors":[{"name":"","email":"","url":""},{"name":"","email":"","url":""}], + "homepage": "http://www.foo.bar.com", + "repository": "https://git@gitee.com:foo/bar.git", + "publishAs": "code-segment", + "segment":{ + "destPath":"/the/dest/path" + }, + "dirs": { + "src": ["src/**/*.c"], + "headers": ["headers/**/*.h"], + "bin": ["bin/**/*.o"] + }, + "scripts": { + "build": "make" + }, + "envs": {}, + "ohos": { + "os": "2.0.0", + "board": "hi3516", + "kernel": "liteos-a" + }, + "rom": "10240", + "ram": "1024", + "dependencies": { + "@myorg/net":"1.0.0" + } +} +``` + +bundle.json文件具有如下功能: + +- name:定义组件的名称,放到组织下, 以@开头,/分割,如:@myorg/mybundle + +- version:定义组件版本号,如1.0.0,需满足semver的标准。 + +- description:一句话对组件进行简要的描述。 +- dependencies:定义组件的依赖组件。 + +- envs: 定义组件编译时所需要的参数,包括全局参数以及依赖所需的参数。 + +- scripts:定义在当前组件下能够执行的命令(如编译,构建,测试,烧录等)。 + +- publishAs:定义组件的发布类型(source:源码,binary:二进制,distribution:发行版,code-segment:代码片段)。 + +- segment: 仅针对code-segment类型的组件,定义组件的目标路径(即安装后,组件包中包含的文件复制到的目标路径) +- dirs:定义发布时打包的目录结构(如头文件)。 + +- ram&rom:统计相关信息:预计占用ROM和RAM信息。 +- ohos:描述OpenHarmony系统版本、开发板及内核的匹配关系(多个请用英文逗号的“,”分割)。 +- 定义其他扩展信息:作者,主页,代码仓库,许可协议,标签,关键字。 +- 对于发行版类型,还有个base,可以定义继承自的发行版。 + +## 组件管理 + +### 依赖关系 + +生成基础bundle.json以后,需要继续添加组件依赖来实现更复杂的功能。此时需要知道所依赖组件的名称和版本号,并且把它们定义在bundle.json里面的dependencies字段中。 + +``` +{ + "name": "my-bundle", + "version": "1.0.0", + "dependencies": { + "net": "1.0.0" + } +} +``` + +上述示例中,my-bundle组件依赖于net 1.0.0组件。在全局安装了 hpm CLI 工具之后,执行如下命令可以从远端仓库获取到依赖: + +``` +hpm install +``` + +依赖获取以后,会保存到当前组件根目录下到ohos\_bundles文件夹中。组件以及依赖之间会形成一个依赖关系的树状结构。全局安装了 hpm CLI 工具之后,在组件根目录下执行如下命令: + +``` +username@server MINGW64 /f/showcase/demo/demo +$ hpm list ++--demo@1.0.0 +| +--@huawei/media@1.0.2 +| +--@demo/sport_hi3518ev300_liteos_a@1.0.0 +| | +--@demo/app@4.0.1 +| | | +--@demo/build@4.0.1 +| | | +--@demo/arm_harmonyeabi_gcc@4.0.0 +| | +--@demo/liteos_a@4.0.0 +| | | +--@demo/third_party_fatfs@4.0.0 +| | | +--@demo/arm_harmonyeabi_gcc@4.0.0 +| | +--@demo/init@4.0.0 +| | +--@demo/dist_tools@4.0.0 +``` + +还可以使用可视化的形式,来查看当前组件的依赖关系,执行如下命令: + +``` +hpm ui +``` + +会在本地启动一个web服务(默认会打开浏览器并进入项目页),点击侧边栏的项目依赖图标,打开页面,可以看到项目的依赖组件列表,点击右侧按钮切换到树状视图,就可以看到依赖关系的图形化展示\(如下图\)。 + +**图 1** 组件包依赖关系图 + + +![](figure/zh-cn_image_0000001173313501.png) + +### hpm操作命令参考 + +组件的全生命周期管理,可以通过hpm命令工具进行操作,hpm的操作命令如下(详细帮助可以执行 hpm -h学习): + +**表 1** hpm操作命令 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

命令类别

+

命令行

+

含义说明

+

版本查询

+

hpm -V 或 hpm --version

+

查看hpm-cli 版本号。

+

帮助查询

+

hpm -h 或 hpm --version

+

查看命令列表及帮助。

+

hpm -h

+

查看命令帮助。

+

创建

+

+

hpm init bundle

+

创建组件工程。

+

hpm init -t template

+

根据模板创建脚手架工程。

+

安装

+

+

hpm install 或hpm i

+

安装bundle.json中依赖的组件。

+

hpm install bundle@version

+

安装指定组件版本。

+

卸载

+

+

hpm uninstall bundle

+

删除depedencies依赖的组件。

+

hpm remove 或hpm rm bundlename

+

删除depedencies依赖的组件。

+

查看

+

+

hpm list 或者 hpm ls

+

显示当前组件/发行版所有的组件树。

+

hpm dependencies

+

生成当前组件/发行版依赖关系数据(在hpm ui也集成了该命令的调用,可以图形化的展示)

+

搜索

+

hpm search name

+

搜索组件,--json,可以以json格式输出 -type 可以设置搜索组件的类型,包括bundle,distribution,code-segment三种。

+

设置hpm配置项

+

hpm config set key value

+

设置配置值,如服务器地址,网络代理。

+

hpm config delete key

+

删除配置。

+

更新

+

+

hpm update

+

更新当前组件依赖的组件的版本。

+

hpm check-update

+

检查依赖的组件版本是否有更新。

+

编译

+

+

hpm build

+

编译组件/发行版。

+

hpm dist

+

针对发行版(distribution),发行版编译构建(依赖bundle.json的scripts中的dist脚本)。

+

打包

+

hpm pack

+

本地组件打包依赖。

+

烧录

+

hpm run flash

+

烧录固件(依赖bundle.json的scripts中的flash脚本)。

+

发布

+

hpm publish

+

发布组件,发布的组件在仓库中必须唯一,且版本唯一(需要账号登录)。

+

执行扩展命令

+

hpm run

+

执行bundle.json文件中定义的scripts脚本命令,支持多个命令可用 && 连接。

+

解压包

+

hpm extract

+

解压文件. 支持格式'zip','tar','tgz' 和'.tar.gz'

+

启动图形化界面

+

hpm ui

+

本地启动HPM UI,可通过-p参数指定端口,Windows平台下会启动默认的浏览器打开

+

多语言切换

+

hpm lang

+

切换中英文操作界面(同时支持命令行和UI)

+

转换为hpm包格式

+

hpm x2h

+

将一个maven格式或npm格式包转换成hpm的包格式,并发布到HPM

+

代码段还原或清理

+

hpm code clean|restore

+

针对依赖的代码段(code-segment)组件,执行清理或还原操作(即根据segment.destPath执行拷贝/删除操作)

+

生成秘钥

+

hpm gen-keys

+

生成公钥/私钥对,将公钥配置到HPM服务端,可以实现hpm-cli 免密登录,发布组件。

+

生成第三方开源说明

+

hpm gen-notice

+

根据每个组件的说明,生成一份合并后的第三方开源说明的合并文件。

+
+ +## 组件版本 + +### 版本号命名规范 + +名称需要为全小写字母,中间可以使用中划线或者下划线分隔。比如 "bundle", "my\_bundle"。 + +版本号的格式为 "主版本号.次版本号.修订号" 或 "主版本号.次版本号.修订号-先行版本号",比如 "1.0.0", "1.0.0-beta",详细规格可以参考 [https://semver.org](https://semver.org/)。 + +### 版本发布 + +为了使组件能被其他开发者使用,组件需要上传到远端仓库。组件上传使用如下命令: + +``` +hpm publish +``` + +命令执行以后,系统会对的整个依赖关系进行检查,下载缺失依赖组件。依赖检查完成后,如果发布类型为binary,系统会对整个组件进行编译,生成二进制文件,然后打包上传。如果使其他上传类型,则直接根据定义的打包规则进行打包,然后上传。 + +注意:发布组件需要用户账号登录,需要先拥有hpm的系统账号后,并注册组织,申请组织认证通过后,才拥有发布的权限。 + +## 发行版 + +发行版通常是将一系列组件组合起来,成为编译可以运行的OpenHarmony解决方案镜像,里面包含了多个依赖的组件,以及脚本,用于描述如何完整编译、链接这些组件。 + +发行版本身通常不需要包含功能实现代码,仅包含bundle.json描述(设置publishAs为distribution)和一些编译脚本组成。 + +因为发行版编译的过程需要系统提供环境变量,所以发行版使用scripts脚本中内置的dist命令: + +``` +{ + "publishAs":"distribution", + "scripts": { + "dist": "script compile command" + } +} +``` + +编译执行使用如下命令: + +``` +hpm dist +``` + +重新定义一个发行版所具有的功能是一个复杂的过程,所以系统允许对发行版进行继承,从而在现有功能的基础上进行定制。继承发行版需要在bundle.json中定义base字段。 + +``` +{ + "base": { + "name": "dist_wifi_iot", + "version": "1.0.0" + } +} +``` + +上述定义表明当前组件继承自发行版组件dist-wifi-iot 1.0.0。 + +发行版由很多的依赖组件组成,通过bundle.json中的dependencies段来描述,有些依赖是必须的,有些依赖则是根据可以需求增加或删除的。bundle.json中名称前带有?的依赖表示可选依赖,继承它的发行版,可以移除掉该可选组件,再增加别的组件进行替换。 + +``` +{ + "dependencies": { + "?my_bundle": "1.0.0" + } +} +``` + +上述声明表示my\_bundle依赖可以被移除。如果想要移除my\_bundle,在上层依赖方需要使用excludes关键字来进行定义 + +``` +{ + "excludes": [ "my_bundle" ] +} +``` + +依赖被移除后,就不会参入组件的构建过程。只有标记为可选的依赖才能够被移除,强行移除未被标记的依赖会出现错误提示。 + +## 环境变量说明 + +组件在编译的过程中需要依赖系统提供的环境变量来自定义输出,链接所需二进制文件等等。这里提出的环境变量均指根据需求把所需变量注入脚本执行的上下文中。所以在脚本中可以直接获取到变量的值。下面介绍当前系统存在的几种环境变量。 + +全局变量由bundle.json中的envs属性来定义。整个组件中的依赖都可以获取到全局变量定义的值。 + +``` +{ + "envs": { + "compileEnv": "arm" + } +} +``` + +不同组件在引入依赖的过程中可以传入不同的参数,从而使依赖的编译可以满足当前组件的需求。依赖中定义的参数可以在对应依赖脚本执行的上下文中获取到。 + +``` +{ + "dependencies": { + "my-bundle": { + "version": "1.0.0", + "mode": "debug" + } + } +} +``` + +组件在链接二进制文件的时候,需要知道二进制文件在依赖中的路径,所以依赖的路径会作为环境变量传入编译组件中。 + +传入的环境变量的格式为DEP\_BundleName,BundleName为依赖的名称,例如 DEP\_first\_bundle。 + +依赖中可以定义标签,对引入的依赖进行分组。在脚本中可以根据标签,获得这一组依赖的路径。定义的标签以\#开头,具体定义的方式为: + +``` +{ + "dependencies": { + "#tool": { + "first-bundle": "1.0.0", + "second-bundle": "1.0.0" + }, + "#drivers": { + "xx-bundle": "1.0.0", + "yy-bundle": "1.0.0" + } + } +} +``` + +系统中存在两个固定环境变量: + +- DEP\_OHOS\_BUNDLES:表示ohos\_bundles文件夹所在的路径。 +- DEP\_BUNDLE\_BASE:表示最外层组件的路径。 + diff --git a/zh-cn/device-dev/bundles/bundles.md b/zh-cn/device-dev/bundles/bundles.md new file mode 100644 index 0000000000..9c560fca9d --- /dev/null +++ b/zh-cn/device-dev/bundles/bundles.md @@ -0,0 +1,9 @@ +# 组件开发指南 + +- **[组件开发规范](bundles-standard-rules.md)** + +- **[组件开发指南](bundles-guide.md)** + +- **[组件开发示例](bundles-demo.md)** + + diff --git "a/zh-cn/device-dev/bundles/figures/SCons\345\256\211\350\243\205\346\210\220\345\212\237\347\225\214\351\235\242-\347\211\210\346\234\254\350\246\201\346\261\2023-0-4\344\273\245\344\270\212.png" "b/zh-cn/device-dev/bundles/figure/SCons\345\256\211\350\243\205\346\210\220\345\212\237\347\225\214\351\235\242-\347\211\210\346\234\254\350\246\201\346\261\2023-0-4\344\273\245\344\270\212-21.png" similarity index 100% rename from "zh-cn/device-dev/bundles/figures/SCons\345\256\211\350\243\205\346\210\220\345\212\237\347\225\214\351\235\242-\347\211\210\346\234\254\350\246\201\346\261\2023-0-4\344\273\245\344\270\212.png" rename to "zh-cn/device-dev/bundles/figure/SCons\345\256\211\350\243\205\346\210\220\345\212\237\347\225\214\351\235\242-\347\211\210\346\234\254\350\246\201\346\261\2023-0-4\344\273\245\344\270\212-21.png" diff --git a/zh-cn/device-dev/bundles/figures/zh-cn_image_0000001051452177.png b/zh-cn/device-dev/bundles/figure/zh-cn_image_0000001051452177.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/bundles/figures/zh-cn_image_0000001051452177.png rename to zh-cn/device-dev/bundles/figure/zh-cn_image_0000001051452177.png diff --git a/zh-cn/device-dev/bundles/figures/zh-cn_image_0000001051770876.png b/zh-cn/device-dev/bundles/figure/zh-cn_image_0000001051770876.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/bundles/figures/zh-cn_image_0000001051770876.png rename to zh-cn/device-dev/bundles/figure/zh-cn_image_0000001051770876.png diff --git a/zh-cn/device-dev/bundles/figure/zh-cn_image_0000001173313501.png b/zh-cn/device-dev/bundles/figure/zh-cn_image_0000001173313501.png new file mode 100644 index 0000000000000000000000000000000000000000..bc682a3dbd7e3de6a83a7292d9c6942c43909c98 GIT binary patch literal 397077 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 z zkA8IxUB`tzeG5)70<(FS&t}U7*`(eYS!NtLG@3n|*K$KD}2a0a@pg^W(dGKIHBbi|LHSu<7BCW4!*8Fe=t&u*J*i zBKljXc<2M@sQ4@AfLFd3ovHiUbj-?A(!z@#<1e5)W` z!iBEfk{-GlIsqmtg?>_7053om#1`n0Dx|2>HLwrbrB`8Ic>~VG85q+Ya4sK!JJ0|( zRs%a+4l76@Y=#p4UfuEs|5{1WTYFEj_{=VrK#}=UA~f$rIcB&7Zug5YM>}EPx&lkr z;R%g4Rhp&xr=KK~ak5spCR|H{o?OP#+!R(OLb!IW9EUdk1164dhSgDyuYT+IaPr90 zczN?@F?W0eUVZkjvG?h3VB*+jy!hl7(f8sO{P53z3uh`HLHCP~;zaqkF?zfJOR;kF zzq}cn|Lzl*4iuu{iO=F}^%HpHbN?5rpZFrS|MW{}{MnaK`_s=Oap4I1k8eiVk3Na( zZQG#5>hZ?&Uq(mC|3spz9P@33*!`nFz^#)TVTP+P+g5<~?T;aH=yA-1pTdT}{5{N{ zJ%nW2CbXA*4bx{fVdAwXvFowlN3iibXe$2}W=}tpzCO7C+eeTr`?$~Cq`8L#){Ke| z!zlkS&OZ968Gwz+HpjxX5bmeAdz&YJ|p zGS_WO#`Tdx^teJj8j2Kn}|k z38e9S$#4T(#riaXu*irDSHTKbL625J@2Q5-+W?d10E2sBTzCP-=u0pzz6$NiDI~|6 zk(y{lYB~yQp%2E&1sL(mFp`sSj5&B#0&oblo6;3q%<7pR@SNwxy(-;u*5|rph|{f@ zV44HZwqWTRT+@V=Ou(7H1Y>3d`gAu^*H1woI|_aDMOghiVfE~U6>WeO;jwIk7N*YI z7C@Yz=i!Amzzc26VfyiU%5y~)SuxO62+q|ic#e2|(q0_hjE(K|Iu2>-g?%KSgOc%fquGXKoP3 zv(`EN_j-@V#p9KKKVKr68T0q!QXXK-18nzWzkb&zlJE9JIKTfYS2hiyJ?45$7pGQ*}B7z zoiJM))4-Yn*w~t_b+9^i!igP*ceNF6VhUg)qxLC#rdRL1n_AZsc@+zO+B<{T@bJfR zW#=bgQ-iJS{kKJ`?ERRn{4JC{^Z}f!{5q`ea*?!BD~+PkbQ8^u%nx7n1Ng1BOh~dr zB`O)_2pM!_IZ&%jfdf9HO$dGyoRW+;CUCCMTO&9~4Wc69Ag6^(k%|-}6)l0;UkCfb z3vkDdz`bz_-eefK)&cv%X=t(6k?g5NB36WW_clL@u+mL;Lb4)CBs)SeCRk1+N{Yxh z$c=kt97spUt#B#)pAF#Aq#;-dD_RG;e>dE**J021!%a@Yv-AulMGdICwoJHnOk5el zp6yi_>N$+d!-w$jXFrXzhwHHanXll&>rdj~vtL5P<6p-4BTr)Q&%c1nr?#W#l_${f z)SsgAhY#V%wtq&?k!Nr-REXHin^5)0!!SBau=^)pz?s@7@ciHZF4}hd2*by=;&jdT zQT5oTF(2KF@C#32^FRJBrrM|pwF{@WejP2v-w>{`GcARv{r>M_^7LjTqjeZL@+8`7 z|0jaGAHn&<|BC1S>UW^U4q^1jkI`KAx9HjRFBsbYFF3yC3+O%YD2{CSB4$pl4Y0*a zKMcL>BQVO}a%hE&v_z01EdEISc^gwOE5&`tEWR#A!MxX+Epb~nh0jX}XUk@N2 zdl4%=hq2Q43X%h_BRP5ssmo`OxE_RYs~6hLAdI;YSc{ioFJFa|xCu9P3$7^7T!3dT z!Znu!Ys@8k%t^xWOzE^OEP?nK%JD<$oC#cw_&V`3{uATfkxVp8gJ-7T>C5m^^YG$h za2C(QnTo<4>w-6S9Pa1~u!au68aM#GZx8HP4QL) zuFhsusX5s~Y0=8}Dg3 z_c$7W_z#yvpCsdsj*s<54we5!4ESYR%t~qCSz-ihEw@EVBtma0)q*S_ynk|j6 z2&}a>!fYk8t>(_rT8DW58Msr!@U$g(RBLAP!hdPdVhu3xoqX=I0k(4iJpY-G;mWSx zhgJ4I7-b*0Ez$tn!yiC<<=?=JmctWTLM(;)Ak*=!Z*;#LAPOaPz|dSoj!0&U?cp)Hn(?10((D!fZgz+?!R>;`VW3iI+_ zBnGx)ska)7-Q|eW`I1Rdc6pLW*p>5~WYDP6GS#j=wl!a~ES3x$CV}gLAHi)%g)1;0 zJAl;CDcCoM;l;1Rah3otDRtP`SF_7U*IM=fEv4b;;iIUo{W*5;e-_{S?)P!Aw+k;6 zJ&L21-^Pn2Kg7@e?z5=)$>(vZ_EB6t-GH4>{RwtF`6(PP{SHo4d>_@1eGZ+Wglj{D=P+rz^gN^DjSzl7Ig1IQZ-rQ1in-#P%Qk5vE&< zVfO66&Z{hIspTo`{{SgKZ{1{hW zeGUhn{1jq)et?&r`ZNwd{ioX{@wMpoJitWJd9Ntba}33b3ZWqxSQjTe?DqZx8M#fm|8V{ZKld zW`G8ZrQRZnU@=)WlbaEU?CsKkd3V6!2#jpb+h&c7#0FX@~aARt7| zNS2q=Or->RxEy-097b2U513Uz3syo4RYQ+d!|bkw7HxppvkTV1AvnV?!yP#y!n=GD zxZVs*b^z01V5S$|!jJ&5JncH5-vG=>cnmsddP{)gYnOS{`_$oiwg}f#_ZD^Y@NYAa z4@4~2gD12X37qje7CiC&6yQ-aZ5fWf2@JWm!K!w3^BquVU!e_r!!a7~uqu6FAbj-8@^t7G*YKz)GC3U3x5Vj2|Y zcoG_UTO{~K08T}S-<9J-j1ga(RIsPhKpMwbrq2o&UH`oC*laSceX|DPz#A@xM}wen zDO@@@lLaYEy=7EXZ`e0F3_}dvA)QKhgLH$0NXO9pX+c_GhElpqx|RV6p&3AhBx;miek|F)J$Xj{o`?l8j;cdOO4? zTC3JVSocxSL&^Ic>z?*Q`_GQQHodqhJ=l6%DSee!X5CRt*5f|g?Oq3-MW|s5MX10+ zNVJky(~`GAWtgbAMm)1=>Lb z?8e`Q?~c1!72NF@I<7)(9EclKP?8G99N2>}nRtRQBG>ds8=RrP&Egac7`Bab2YXsI zDWuPcP5rNwRp4QjrLW$XV#B9(!qk=N24j&z4|d(~>U*~$`;$#x(8#$r)TQju`m4bs zD-kK3Y~hBi^jl!Zc`q-=+pwwlAe_P6Cz3QH##az+h#3lIb2Aq6gW`f$bC=yb)eTIh zp6Cu)70{$NT9C2x`_+zVaA@dyPRJAF_(DV>lc|BXI?QNkfnW` zJ-^~zm{0X9hpH5oAchdTlGCvNWHRS`_~%V^9901C>q0U2;g`IdYixszC^X=>)LzUF zTVb@{*<=WH*IiT;F(uvP>)Jq(6tGi&W~*40>m#N8M{{Nj3z_pCO9%NHSt_x(>3&vb zo}B)3Ly0uj9uGslLdeA@b zdx5hB^{!7K=ynf_iwW=Kw9+HbdEnbQJ}#Llm<>>c8=<)bZS+9dw!#^174Cbj#mM(8 zu3Lnw600Xq#~!xQh2}rO%4|KsM7sP{@78a(V5~=Vn*KopTGHNhF0KyYFRJi+4dHqa z7?*MkdLPLBaFP8_A|~(BXSGKh^rKH6k8V`=A=!0i$4EnEMVUFjKOp2Vpzs9^6G8N2 zkx_Cv$D>4=;g7EY2!4tJkBoJ!3>yq3 zQFJv$l`-j8rU_XI)_)!KJ3w*_((xM(VcY&qv`?=+JNz4!qSv#H{mli^+`3C;xF$`Y*CzHo+!>iyVfnO zS*#c*q597#1lsDU9XvFjh;k~PT~gjY$~G7T66-erU4O_(4o|3NgCu16NVbyw%aRMz z+%TArpD-F9tJTtuaUo2T15am0l6ypdu27mT&nn-Y0$JR}M{22yiC4^9(&G@Bt`Sl` zc*s;rfVvsH50-#mG~!hFmJBJ|4aGh=nqH+uE9jPrDHa3u!xk$LTbaO0&^{!5I3j6>C#yRR z2{|X%&i;234{P#XS5QJPZz-bG@YRRbL6xH2x+KBhwBg}?Ca;)NC z=v}w8lp?JRM0PVbpnBGWZ#6+&v&qgB{5~Z0iVaxq7wY`O3ygE4XEKofs9VC+DoV>? zK_eNGc^*PmI;9`eZeSZik~Jsklo3}5wlg7GAxi?+NG2%-L;MsYg-qaU6y1c6@9`u| z83czLw9y*0#V%FC-P4PEi^k1j{OF8_Ap?{M90^&1E49Fh7S7|E%S&)K!=*N z2^Gf85P)_7d^z4u#ry%-z`n2fvCU1cW4+d7oN9k{_8E`r(D++yJ2_d;_65cQtlZ0t2Z{^-0TO{)a2{Ja```7 zinPT6hTL;UHl6++-MhPsBxxSx%prUYYm{l6IT3T$Ks_sAVII6sjLPXbZ|$8l_U^SB zb|B7l@|rY$70wqj)lTE;NwbvpiqPAMYc{sYan8uH@k6(BP1v#yu7n}J%Nm8QHABV} zIc$p>QexATdW;I1=LgS8*daM^T7q57^}C7BB*_@GA?A1V4dwB275881@a1a!35LJL zTYo?9f-K5+MKmF!L1Jcp)p1y$Dz~=RlG<9!efDkSrm}dklA)Rx0mc0=NM<9v8ku>t zi3CuN_zjH`3>W)a{CotDz1DFo`{m28TI>;_cXTAZYrsNSz~~?~qhczG>3IlRIwPAC z5x0DYZmA*2^wt|^`_62#$ScWG9;)ncVDn4yW1>_d^A^l zSDr_vZ2{!@lWJvyMJ5Yn7tbLR+B^C}eo)gB(^qHtip(^vjN2?kNE+z$oo-eS=QS$D-5h&+PH7T$PR0OC0-IK3Gse1v~|ucjh)N;Ms+6H2SDiZgZBgt}OUxWCO( zgc_3grZb)(IcND+%W%w~GWx6vBBg|H5J?Nt$=*~(lCP;TdW@7+A!KDTmFDgRUWgVC-F(hBgAJ6J?33KqG9N%5lJFbcJk z--ibx?ZF{_d$x1r7O;RbuaL953K~pL+=ckp}`^~HZRnx19esbFdIuyNu@I< z5@4xy)t&nmKfn(2`ti+Se>7aby2rc~3#kvnD`O;*SdFcRLUuC{?p)pq8`qOCL2s* zATI9?%6?_P8*oGf`mX}<$JQ5n$5J!ga%ng0V`>C&FyZHCin8D7`M7inj_!1$E5^GZ zMY$RGP*Qi`AF=l-%lG&0oIInT5nNlg{C%H!KqbVcN{G%LX1DhR*Xl`2wKVS5i|hT4 zYXjw=qJ_O`C`}cVW;hJelK78oqvI<+^_vs=UT~_V*N+Lzn2I_b{@bvD^;h_mvu!tz z9xD?_81;YJrge}qCrLz;_k?eAS4Ge#WOu6Q-K}DB`r}P-?G{h)^NP!kRxRTA&(CTN z*9I|Bf!;}F@q7$?rr&kg?>uRKw2_rMIb3l2YF^2_=bAJ{t7&x%bdN=tkhKihqQQ-J zm?!N%O?U4)LunV{OS)M(Ee@1F|EH5O&GviG$0qMRfC^e2N8kDIKsQ)h`l6)}d}|&S zd<&3^AHtMAH&>wb_f>~kj)@}#iaM_k z8;$q5l9zg7lFE5wOT>(lyZlc%;9X`GWH*5@8QUEbswq0DiXH+1@v&h}X=+C)kI+2^ z{l_*ksZU9ujrnYz1Ozh5)xR;0)pL^~3Jpl4_9Gpb@pN~)>dEOqdDx~Otu;tITxFXb zBg^SJaFpD{x%twAaKEs}5M5-RZ#cYH&Vx`6Lic#OE3 zOL5i=+Z`8SnYoVz;p!3CS);5!O-cq*)TRx92<%t)VNx@=PW(8Yh1lDDMj3zOx?4U| z%<=ckG-KQV7_o%*mnbQ5vZHM+Y?KT$8iw|_+ef6MzCKmU? z5+?=9C0Eja?*CEud`;~=`j3EXhKH zn;e2q8zJROay`kxSozx;&W#)w&TtJ4-gUS8znYy9fL9~6#w#GtcJQn(RpkMwm1J@T z?E*a%;E^6v1{mGr9nHiXop;T+=;-iJ}mefAZKmE6#u>tdMTjH9m(KE9`XBGF4U>_n_ChFSluY z6-JunximQ0kJl)Tjn)2H#z5NjNf8Zx=T@)dpEWIW(PAdbSiB>osW{iHDI39^kZ&BiKW^fNSqAy@dS*V(}L1VBvuGb(ZCdGpx$0 zj&eMfRrD{5XA(YPjJl>uY_^iet}XKyJUJ?duz3^wWSqto|6M6BUVlf+%W1^d54~SM zAm4uXAsdWv5uK?CO<#*)bWT4*r*7*;Qc5wE_UuZOBi^+5%< zwIi5+B?@_3m>-x|L7Qj9T|kQ-JBZ-Czep3wG9FiZ<`eRkL7vAh(|sm>?l&uUjy>Xy z^l~esU?>l4B`m38Ar7RI^li zLoj~cr?jAH~7(|ypNzElfymD4e6)C^9e`% zCds}fS?c>F4oXnq9mc<{G9FZ435lWfRgLiHGAXuGn3wnzq7BM7TeD4ur<4Fj^2z*umZ$IAqWu>M}pSy1| zl$*j}*;SJ%MmTE|hbxZJ1>7Qc_}n4rt||EN@8Os4_;?qFet1OCVNWk?URGEt5{jj2 zS-~@PL#xgWleovK><)!b5Z^ALwFP6utf1>`m)=bO@{rK+FhCK}#WmoKQL|K3FL$^@f|Wz3Q#NwV zv|r@i*v`Z;4bEeNXHwmg)@2@IhcalDGNhw2EV?i?PVW@U&UzG2vj<+fm3ZG9S!U}m z@XybfMDnlm&5lC?oB%65fc8`dnJ(aNIv|il#T=l24=Z`&UO|%~367!r;&b(;JsJs6 zzXcSzktgvvKF%;uR>-m|MVO#99AoL+j}m!xQ(w?{^q+m1_M^9MWTxpMP)M=xaNTL# z=!i!!Ta0*)UmT#ThtEV=&mz4lH8BFY?~Pa$Zh@ty?#O!*!lf9RAUT={yJ3I;T9nI=s$X7DnA#_1(#V zA-!=Jb1Qxw=SOozOBP}$mBr#+Zg&TX|AX}=Okre*mH@l< zHW%u*Ur=NM&sd4uE651?-@ZD)Uv|s9Mf8p$YW18eWTtf7UUf$XRwuN!_Q23Qs`q0{ z^0Rbp*Fo)h##OCNWF?(6b(771OV2sk@;6f|cj>baVT)@)w@%>vUf8CnJI%a@U)9fh93 zzgGhdb0)eEeewJsSc@0(Lg(+=31pSSZ2dL*GJY&mO~t69_m`ydUbp~EZjk_}7v&Yua$Wu?3?7eRe?^wE-PzV^tzN`Onb~$iLCFi5h4rF5VW>^pn`J@B`$E)fkD30 z!wE5+fj=qGWXRFBn(qPmd7lIlv3`GuW6@#(LXyShf{45^WR9+%CYYr+40{z-!bbQO zJ5U7@J2LR;l*(T~m+GO2Ke%)@Omi{_gI`+U>@eR`nxDq^^@p7&!Qm9jc1SnmXK3sw zvk>|ps-b6jN9*~jLYg}l{XKJU%Dg2%jOv5$4-fl66Mw5+x*IiX@yuxVuHP8>q66fC zym2V;mF#t8qDp_U(!kGO^J_(;I<#rD6HyOB>nOmVBvglJN#ApI^3G9~UXo9)D$oi7=5sDk|vlHMcsu)iNL zF^llhoX8QRGE1zY-I{Pzs`XE4h-1$186!LqUDTLEjPG%%Q%4AA979S#QYh4m@N@v> z{V|fdjVTL^i+f@m zndMVeB1Xc{&G|R7NN#1m%gdwX%~y>ZMJT5Iwok#42HJ*;;cMQWDgf=ySD4HySZ;?N z$n%<$b!y*OIxC|TiDD`noneA2Ei_4M86#~ zT$~h153j8V-vtm-a2L5yRi??!xhS3%Ucm<^dd&AjD{y-o^_fR{$Anc*A%3)inLXHF zWlIo}tY=y|KB+ua$#yb> z?YxSUA$O%uQa4myfXAfisrMQrjk!DGa1GqqUxK51NTSBdkQN&fRE%3MU&=T2BEFO{ zoklncSkGrQLLzZ0!ZNIui8V&&j5!mosB@paGdMfWU@Zhfo3~6s9a~6tle2%l=|3B| z(BN4DxP*A&tHO=v*Swl9epSRP8z1ONF*c%kUGc14TS)5zYphBFFo@R09lF&VNcKxt z$ma2oz?sJzLoS<^gyoHBjhZgEq%xnK8W^X49FP!m1nk6yJFGSxIDbAQ}% z8>*#nilr?yUz>A7>{CgsZVo_m3ZAwen2SMPAMS)(bWW zOdW{ghKSlI+TLgGNAKaU&Yc+3YuOC;U6MTMez3Jex~4GVm|K=7zIq zI)gcZAuW~O`hmHfK})Y5zDSm4egNlxWL+blk-lRASCvgX;$kB-_R#Mi2Ka3ZY7d8? z#n<2P;QCl)sOj%)sa_E$>gT zu}c`4KW*6>IPltGMbpE60ZEmX{# zXrY9OH^Mw*C77VB6Mgsh5pVBI$g*WvS+YJO=p5WRA2k2LHS$f~Ge=dX2nO6pqdf$) z*%ax)`epc|zTtY+B%|V2qU71WL$-fZ=%Q@eom;(;~3^}N^~TDK6sNAZSSR22m( z=1H>RmL@?50^7<8K+|EEU&p`3qz#FVK@hjZrM8gnI(zNQ*{OG>_Tk$m@?ltdLA+3J z_E(uaN+_Q+=yed-bzhu1kSwki^u;!`3FU8rdLb^b6o_NTA+Cx3Rp*Ii`TmK0neapD z9+vI<&&&dSwrpYfiFCTS|{`zxaB;Iod z7ER4e_xK@C_!?y){kkxVt>Ib3<6j;%GMJeAvue9L+T8v$zl` z?5v4sJnHt`@+I>OJ?Q@DwBDdmrBR1LBMRbrg7_rF$Pvet^fo@_i@{Q%PFy`gWc&pa zJ(};L`OSRxUM+=JxbJZH=Fq@IBtSmflG#+28Gpwagl2(9e<&S_UKikYFq$gA55yoi zng5cy`;JqYD!izOwv2F_LNIg^?24f#qp8Z(Kx!98zeq;04%{u^;#DNU>fjcyL57wW zyysK@sd%>`tTUjJmI`cBpyDJN<L;gH+f0kF8M|UE!q}r}`83y3}_3!~bdl{3$Kj))!HKxOWjUP6(hz!J0(|ZZVYd@`UMv$_>Xi|^6^tG5qI|C>0@evfCWn1t~n3OHe-=aGm zie@|6uP^TcT$R?xa=*0kV!Ab<9`i4^*Yv2GLYt@Y-8%7CK1;Wo@U0DqLE6!d{|WF$ ztjg4#pfOto5S*+;`Z~W(>%ld|a#5Bv#O2b)kx%*Hu^I(YP*a%XN};C`8pBKiL%8}d z*ggXoLi4k6%qO_cGtf*<{90g|K=`JgF*ZfpR6zC@gNYfWA;hV&?Y`~i?*Y>6RMy&UuTb%5nwcV$7qk@8=;ky@7`a{AoFqb!1 zq&Ao2d|MnR1eblwiS4u_>U|Px)z>~_m-MP&E`IfWn#QF2MI-Xq!OdU;bIq5<^69h( z)q3=-d#x!ru?U3AJd|%0H-Hha_!Et?jqO5u`{=qYLM zcfL@-FXlPcc_$~nxs)Kyh;F52X2&hVb*|>{>G1;VEYNyb9A0=sKzRanAnB|P2b=(v zD1DvF0wyE?I$99hl~+#O4Infw#)@-z-PO?PaB|DIoQS|G;@Ky;{~U2?DV)6KR;>rh}1&qr${h>iqxNV#gp;~VL>Xg&Mqi2bgE zMyJbzfVt99cC5Jz6QQ)g+;j>$)A^UzUCsLvot>FTqruOQ8qu4{o67Wyj%`NP7SKzZ z6!3QnLS8z8o6pOF@fQgb6rNtbc$rq>lIq0OIn}K=l+o^^iY=ceG&EJyCvHjFZA1PA zahiUS2u2$}L=zQwa(BH#e2eS;sahXRKN_h|@%LMS#eZ^+hd8?At1^yTLdD$F;lgmb zvgbgRtE2FhHf;3%O>04HdPt`xU>}ru$eR<+qHPuN#+QeNc~6jYz-?i^Zq6R8y3Fwk zP1F)hpgP8rR${Mq^@C=BesSn}L^=o1%pg?vN8G4e*B8a{DRYc<28p()kNATg|G{Xp1TKIxx$a6R^V?VFq0C%?I-OaI=xnY2r zV<0#*17Rl$?v$^cWJ#AmOkzpCKTDq8J|HvHbSii20@hD)umANyU8xvt|m zjmIO*TY(bYU+@jqSq9M@PD)tU`UheC74B}ah-?a|9|!QsA8_+g#V<%CJJ)ee zN(f$v?3%avrV1IcRP6vrgF{r|x=rWQlK|PDmi4w443h&yLDdtRj2TU;VfWhcXBAhEa)Ta^7HJx0Q*N$^8ssD2U^!!(2j0)lS zGNY45>~GH!^A3yuF9JM^h!jNZOMIP1Dzwa4)j2Sq{P7zyM|jg&*ZSPLHOG642wD|g z-q8Iw)QQUXKz35mmr=<}D^1D#sblk@?xmR6i;nU=(qmACDV&`brarCy+~MVhd+-@P zzUWa?FTE94R=kRV**6|#{Y%N9h1TL>@J-+Fp5PBuJFMy^909)g=~1*@k@0S736OQh zf;~z0_cr5N97jekLYw!lj*n;KwrEkduX!jTvGml*f~;!%ty}~evCd~M{I5*Aof+D~ zOU!MgNiYXOmsJbS*)vcd65IcTOdkR`pU5QZyd0u3^)ugP|%K*~%V{m z{D(D{+dB#~FZB-n7| zvH3z=DiV%=wXpbo!8%UIxy znHFs5!!6#}oYb%GHgCrXu*BJxjMd_n-4W{eNIP)#j$-qOx0-;$DI#c(1P91L9@j%1 zL^v=hyBms;pSOxp@Amq#Q)%}}h&Nyaa-D|s+{%`hQW*QNjlxNy{xa1GG1^WR^{Xg? zFI^)D=Wzt&K0a0fnSU3WKoprCfZr1HNW)aMd!O}Hv-5}+}lm&ddP3n2B@qvGs0qN#L1zC7eK7n(WhFG&Ve z_J&lr#|W2&Qx^Kku^b-zBdcff&3s80N~|ZVg?qD|zj#$(kDFp1|M{Bnm)eDrmX5+` zTCL=PUDgPfdsSVt*SHfeaF1Vi3RNY}hvDO%=;iNp2+mRH)GE@z#HR3cbnIct$+VPx z2kn*Ki2&$=9oW+-ci4ehCWKb+~uC!<#}oAL8BA@G2jYCn&I8+F-ODu)^dmy<`e)G zuD|vUUzW~!Ky3%bkn2MQg;NEE^N|pIyoz+jeLS(&J7A0duTATld8a)?w5ItTHOt2I zp4}e`{D$#187vxYiBZS$?K_Ia_i+dcU)<}-kG@5vuv+~!e}W8Tx z!x^79_@@ztGu9%kmj5-{uMS&8^h522TYLn@M}+2(OBMD&kzT*bWYpBrf%H|G%4Nu{QJO2XI@XG%q9TMlUas z$cIk9)n%LHu?ki13s#irSSoq|5j_|P!rV}zG4k7~KWn$J`%r*cr|RWY^*xHl&0fDC zu5y&8tNaG3ypECqzaU!twsB2@faH(yNqXsnDWgKN$l7iOQMgtubG`!?>O330ANIH$ zUEP#Uv73dWt!zS{umZgr?9)xoS0(s{9L;V}i$=iejemccOPL zd`vu$1Qj`l)M6Mvp`eBHzHio;e=LZpc*6zx_ksr9Ft#@`AhNGR8OWfG;FcQ+%O%Nh zjT749e!Z;o-~Q6O5T;~BKI5SVFhZt3YFOw=Yc-F#;rH+fc!7OF zcS4jq+NcUk7$s3v826eYO3Td(#`LgEZv)YXbDZ%XRX8)wG2$}MQonL z-%3@k|7E>4BdSFbl%BNpMarE{VQoBoeJp%!%$uF3e9sAfVg{4)0$=A~!`%awEioh!$>DZIt2}q&z?ep*0YfHTqc$JjTUff_YddaxGxrbGIVruRWS%L_Sr# zJ(@v6yi!T$P&AZAl#D>;(gFj8&q ztje9pWW8@>t&bzDOiBM6Wf?KPJgbN?Fix-sEP?Qc%cb) zxhaYmFlr0-8jT$UAfMARL3$1@fZo(0~aLnCW)9^?ltg)L(Wkodnu*%i& zM$UbE=qD{GZ4h<^o?D=%Ry8rxr*#lUbrW5oWaY&$6o3Yit7ri@dJ&(2D;k)yIS0JM z8q{xr)@y)<&cGpNZ+aRRl1$beoAKsu)6oQ~aREQ5I@;=~=(kJwWfLWj?Kr?tj!i1g?md<3AeCwbC#8#~(qyTCL{xSl8L&O4#i zw?H+tRW>vkt{u1Zx89e*9PH+6Z0&D|DzVjhOi@G1sMIPkXmegjlat8PLQdj({@KO9 zl>V#%!KLz`z1w-^Ab2XEX-s(_;AtheT&eZ4lO^H1AiA3M8ciImr*uRSP|)~Kma7&)o1rdZ z$+a5M=s|V8Z#H*uv%crtGMiG9lo>Ks$A8L+%By*{SNM76nv=IR@$?mnu)laWH(>rV zLE|LW{xG>O=C9wa=9Zyx_B|e-3l1QvO}fn@b%p=E>)Of+`0ZBRX#~L<%a*U z6V~ADx&nTFE6%`F21M=!nyMx1%@N#o#xTM0 zm=}=UC+rw^p-}>=2Xu#Z|KeWUp*}XgMKl+8j5_(Y1RAlgmy?#v81Eo~r#MNWJBidk zpDk20sBrH+u%ql+PpY!L{V)kKBk*N;39|P=%Bb$^inmmOBsJ?Pru^7R9(zc+)vbGO52VNZfSMw!`zjw8Xz00|zWBX??q2l za@nrL{r1NlUyCo{Xbn3;G31raV_ET-95gDj9OM+*n!ss=Qfgx{eMheHYCS?vtbldS zk~NDcW|@<)kyg#>S8MdewUW0{0dupvnX0PT>z(cvh*WT`^~G6tw6G+1f4|-bo*v%V z*ngNRzoMn6qVtUj5_DQfB6q*z2*<5Lht1lTKAT|QJiP=Tut1MG@VF#LuG0ZcM2Kt7 z&3_#ib3J&C4dy^eHS2sq^xQT+nbUq~mJv)$BI0mTY;IYC7HzJ&v8VML#&Y(7i@Uf9 zWXh?k0_<&1oFbTVuKht87qRUvggE+64c9N0xpXfe8Q#-RBK~(E7fk-a+lS>)8}$%w z<@95_4(#6mRw|~nYe3Tvn_*Sl^iMu0aM@kG_PIR{eynjnD~X5fV$dm_NPpHYKcRd3 z_4y>1e zIn+hPKk`QLQY{$ULvJ%gu6wDaaGV}74^5OUSH)0vj^+gFC|*GJl4YBKMg@H$lj>1868=kLSXn(ruN1D$DKbsc z3syyAY^=VVZ=6y2qvRKwtSe>u8?bgNl@}Cb$HanzFWsEwZnNdwtK2)Z+4}~EJ;TFw z@wk4YSUd3W`w+wR2i9zdpHJsu*RPfir82MsRWwag6go5}@bb#!*)mT0Q=C$K>8L&k ze?$H#x($=Jv)3Xh$~+(M>Vzz?Oj^dA1yKj0jdjKKj}2B1O=8A9?RLs7^^+E&OzFck zuXWn7np7V2Jj!K-!6gosA!0&9{Jf0%Y%=Ps`jMY1arSQYi-~!drs~m*+kr+vg<2)| z82e3^$&I5SX7Pk~pXih4BJ?JNIlp9myf_?b@hPL__}yU`cRXlynJ_JPNw8g5qc)~s z(LGl}LlIno=2Y7;bm^^9vVoBpbwb9Q0^PMsWz>GlguAT!t7K}ynRA)m##px=a9C~-KlzhuxPf6&l|Tu2>?A!{jRiYrwZ1&Fy-iIk?N zjG;!A%$?aFXU%tS!Lj>+qjaNh^sAQm+EC2&?5I#xO7;~ia~k%p>?}+4IRrgCfuU~@ zQ=4g1on{IO?(+LA5EHoLxN`VsdCUl#saahna?Nq>`q zt0S@m|G-1Rq~>w@z#ZV|Jb`Zg(ki>WNPtcD(1SDW?m0LK~2VC$xhcn);S0B4G zNytMnrR}B`B^j~Q{FdTDzT$pDqAk~@FHN1s#Nj+jhZ}j!^D=J)o-Cah*!mH7&Sy1D zWQ@5Lt`Y^8{LTzVxAlUVrsC4iJ1Tm%f37)ym)H3wz5phX>A^`uE9lGp9y^&RV!bM+ zr)3cwaG8VP~3Y^ea z4$T>3#cgWH48i@Yl*A+!0H)#u+5*!e8)^yxrcAd=|E012r-UZDMo|``9s%xH-tck{ z*kA8EupA_TvvwM7Cu0mLiR__Tz@b2s z(ZaY`0HGK>QkVZj_Zb7G;vS2v-!K2v7+qCjKk6}+)TGO(zSteX_{J9>U>Okl=7lT7 zY2W*qf+L{->s<^E)63n4H5r`B$=0Mwrkr*27d|Q`M}#&aY{@xOx(j&9g+Jg7@=G=S zCS!u9P2m20&HLC5mc4lMF2*IC%UOt@dn9bnXox@AFAjhwwZNRyg3exI$VCeO02l|+ zkFlypaAQ)u(cth8D9@1@X?Bh8awV2KJDTv9dug+Qp}Un4#+tB46h#n>Qm5eh02e z;KhDl{Irp*B-YRdsGI<(iy+ggEVax+y>_rT@7Y%*!GR8Rby75wg=3S9v6H=5yggoT z+Y;~uz+zp{C38t?^Ndfr zO9YXF~BbWDJ2nUL@bVcoz z*2B;KF}1zxB3#q|@=~r<|HF~Au!b6HY%^qst3n<@hjZo>f5jo@mirD&l@(X;npx~Q zI}5ka`FZrB3bSF;9-2w{@}O7fCToNW`rlG3lne`4U%aI%wU-Cj6PiHiPk%=5J0*6x zF`_*fo+pKhyy$QLv~5=WxXrn-v>UXCG`M|c=E(`WA|3Pgf2)vI2Z9HpNa zOx>RNM|1I7He6CLrh&Z33=-Tj{PtR%Pj6(SICvFh(CT#iLY=WI=SJW}CXfO12*LnD zyDi0x-&N;6K>TjcF<*?)K4BZ;2L-Zb?+ea`VS-t5|HR*}J+*aE-^2N!^MX7jwo0Mu zhjlzOSfW_8$f|;cYUF1`T zo>FP>XNIAqx>1K7rK5jHx*KxXu&)YLcE55It2{P#_{$FY^cO(_XnAFhPt|2C3KE!K zW8Jq2d|J>-0j1(PSP)l=O3O3FaK|Ou{r8IN?6R=NAT;T%5|syp3Z+@kp44vQ88Cdz z?i(rr>s~&M2w6Z4*aaLGgaRofTNYvh?3)OV~kdY%{Pv`egI%_64RtTIDxLrqdP}aC)mfK*_3-fHgE%$K1|E;F62~kKcQ>)EhI)xb=3jCI-@Z1pe9x^Vw5sVTHv1g zCjNlLRCv)jbDj$almbi;+$o!Nlx=EI`Z&Un8jwJ04V~;|J`TUrQ#9tr6WRCC4r6w} zoahP`itsT;s$|7nYImz)%VEeEH?a)rn>ciVDCK z4IEq(c~Km!g(ecv6A?Xg&Pg>jLmDv3Cu0-JBro7gm7kAhB$o?*ht1$?N5a2wE7RLU zaC3d^DK5Tg4i`87Mpz(^{Kpj$Lr=&*pSVCX3|?{UuLra#h?q}!{wPSS(N^os4vEDl z)~D~lPuNtzm5;!8TE4R}2fAkWUP`HXyb6rxSjx8ETQbbvHF{SHKD&@koDO@h^vbU} zNX58tS;Eteu&5h@9yzPFX@>9Z>84y6&J?OZc6PB$>L~d@Bxs7jn$%cCWBrrk0nxix zhKHhGcZC2e^#-8EtscXiY4mR`$)tjKux2k>@V(g49{{BdHnuT2b$1lz#zIoD`>2>w z*V4h1LWwXjUu}Q5gk>Idbnm@8;f)dLQsj>Hd_QZ;EY3Kh>U`TKbswCwJhEM+w-Ha z^4nUfa?TEfsxE^L&Ii8;FLJZ&H*F~y?)EX| z4Z3;^@JvrC$9CKjB2D*W6sPby9Un6~c8-zk!nrwnQ3MFN+|ed|MhNh%N4lMKm947P zP>wD){k>1(`3`7$ztb_|mfkIC&cH@%3%t_`pq6wh8s<%FBmx=QHXO?i;BqgGOp7W-4*7;HRsvl3wevig~%6;GbVj#XPG zK*Xy2ywB^Xn=?Lj*yyBMJ3nv{x6ZZtn4|{OZR1pK;fpzjE=n1Kq#)nFBk1q=2mm(#$XoG2tnM>^gNaq8NxjJO`6ofTZrPYrO}1% z0HHF_L^yhfboA4p{Tr8OIS0BBKwC#AAjF+RlF;* zV+`PXTdB`+rf9y3I<&9?a>a`~!KHPHU0Z2j|HUqZnU$_OXlixt5$Xo#at~0gB6$SR z@WT6{j`eAaj(~{1qO+j3zT*vSkN47D>D`|3{sUC&NFJUPT`$-Hp>AhErut}51!(OU#*+bCa5KP2`?4F}E_3;aMwi~kl5r1>Ba2j?ma{WI*T>}+u=0t}M&TSAw z*CcW2cOs$gr5}lrEt@yrfv$f31V>ssRq_L&)zB#=@{y2PawWjhH0xh7tOtr;Z96>L z*Wch}%F5}0>pgDML@%iRe4t}g=ovj}4`s1c2_pb6}LOcw5I zfi|0sB>#3`dGl6~zh#=12v_H4Lv1K z`bNNuj4gY*gp|xb!`jCSa(89ams9?JS=zM4E+O%nYSeSZz}V>4_tZfG3A<)Ge>CYf zh|Kqq?i(1}-R^AjtH-|dct*q^Y1`b2MOQ1iSFH2bN8Q=q8YJQK*`rDCvH)_dC;hp0 z=Ct4*9=J3uHD`Hj#H-C6OWSQfbm?0)mF_>M38l1&f5kQ=mrkX5{?%xG({GUXypo0~ zT=oiW^L(n*w7PA3bvU{^^yp7IidvdYnr`K>dA$wC3GR7b5qa8qMfg%99Y3aSDGMj9 zbIpL>%tYxKB2>YHd{zA49Bm=c<|$Nvt?4dR`%Ny2=yO23hXD{O*!+~0k>`fYDdD{V z570*ct*yR~oK}m9%ke}p<)kb^$Wz_l4A+ROuoqiq$i6e!w$B)epfjwLaZ?Ej^~34Y z(vN(1IWh*&;;-|ZOdAHhB7Gqlr(ql=|1g&FD@ zd_((a01hZu+k_@VHWLCOAx6PQwb(I^b)h(gUP4wE9&#=w2Yor`q;njbO(~LwCIuyM zL=1fE5zWv-H3`)ak?Y*VK24_|ATAG%I7fg^JVWm+z!$Wl+T>TciZjMmiNp2tvyfR@c7+Gwx_?h-aP(I+&v(O(q z=UIT(G;HvTRG(2mPYzSsrX)6gRz$C&M81m64}q%iPkgk0vk|R1 zt2{;Du91|8w9lXMhX7|8!B}Z?Wkv|DLKM91m#Say7o`WH-Du*MF2<${;N{lrqj1)*D_J%D zC-zaP^C={-&qHhN84@4mt5X=I$4eoL<=?6;$+pnT{fjUs2;wwM*a@*INlB71R&WN$ z(StF6pe>U5Wplk3(?1a4eo=ha&^OxuUA-M~6~rT4f|;Y6chM^C_rdD#5+m`#Lt2+V z@jNWdv73s%mngNSA$Q9!w>oq;I5*$AU-O<`(vvz{N9yk-(Th3|=$d%=d2rbZn};?~bwgg#ogocJWV!d7is*c)=En z@<|9gNWcX2?Xz=KMK{SIf0a!1L~u)zsK4n(jh@SIcgJ$VIv4 z&K%7vw}yT=@uTJ4RQu`;)oS;XWMSP4C?)rqjC(E|FY}8<|J+UErrAV^)hkAc!Zy_Z z^Yw{>Z5+ zmjsU;#olM>z8^v8Ci@=)zMo%`irv$nl&nUjoQ7a}oZO2S!qa1O#9h*uXX(vi-y0I0 z6tWGxy%joG^%zhD;~dBDg4pR;xW&5Efp!yxTJTZsp$w8`$Y5CeOiOY|0qXJM{6b za$W^X#hZCHTaThRuS>#l(=S^Zg>k}x$S21>HOv|V-M*m7pI(b?7SV5lP;XF~{snJg zy2sBhU<EFQAnjbq>tjsE5U)5s-uj0M59HHM0{=AofktLZ$XqjucV%GAE8e&*u?A26D#y)R{}bJ1w2rvdE4q`L#9sCueaOy`Do`A zWccaDQsh}Yj2W=f`CMMm_$6sMnsFcqNROtnd@i&Y+G&N^6?JsRMw+=`wSF4g{qFKq z+>=w6Zz*c%=9}sRF(0WF_Q{M$Qa)?b4of=OVybO3S-xYmz=4GxpY>u|)8B7MoU0PQ zF8|&lG;YsI^ZR zz0Zi)&v)M!FXmn&CK19@%cbw%6gE6@!sG3Qy;>h!+FOrVzCK;Bc>Or{5i!60((dJq zk@9r#UF7ECH8#^O`~xh-W6OHY@Yj=JZ*smc#ed!!)4{<*zq0WG{y3>t-BM0$KBjU~ z<>&>@k9)Bey(-4$^qboW8W#TLe^+31e6Q&GJg^~iIK!dj@75Q)#{)jP`j{vA%)i`o zuWhz^sb1Ld%)x11jXxz31u`)dJSpTF7&vi*Vbdu1{qe*$V}MmbTjY4-E&HBYgw%?- zuyLC}T5S{I#54(M8nuh;lIUxvyGuBJpz~Jg@3>q)ZVlo$#lAo5Zy#ZK9BA$Oh5pYlYVH zqWJZLNrw)s4s06xNTm~xemdp(^FTkHMDbC?3+6^VLvU_pP*+=4WSr4q5`d=5h;J28 zUKWIQ;|N&}$X4Idna|rlMZkpRbD-epZ!Cm{oS5toR2Mh$y$i;=d&Kd47s!cuT;L<9 z`P(cEvpa4aDy7V*p=g?x(DE?H8J4*ED$1*}n26a~YDgoe1Uo5zuT!b#{i?iORe?s3 zqzAp|M2EP2B76vlz)DwfHRyB5z!2(M{1dFO40@N|mxodsFnK2451w(ZGjl~jog_z# zs-&6@_NQOzC3u*&uvN4G?khg;IUTf3_T{ysx@_YYuHfU(C3AKol*~8AznJXTN^VO|DU8As4B`CfgzZvrxa>O>X57hqht!D}3?rEQ}0VVvE z#ViN#{}m#sZk%C}P*@{cMX3caE~Bx zk0Ef5B5>CGM~{b9!7Hy*S4bHT02U-6W4gZb*MvWoSheoh@D@m+cKqQX9DGyfxz9+VN1X>-(JgP*?`_2Hd z_t-q_VWzCRQ^hO_L<{bD6*f8zq(TY1AftTR`ts|%TXSpqGs&-xeN$5SndLSJ1tyqV z4yK=mqlb$3rsn&sXx-dz{7h)#DRo&9hEOj>+ep9YQig10w*P*DM^fB_<_9JmUza_= zV++!eA3I-=*{a@S>+K|8Ol|9|2}6jTpwYFa-~NgB#&)Rg8leeWAN|4c3|(26_CHu@ z_kB3kK3{r`nBxfc+`p#T47#+mIcO;X9~@vTKCf-aZBJu}Sd;^VqNTz?kh#s1C2tzA zI6Y@;M0XCtq5^gwxi(;>+lNRg-ic8|nUX0&!k-#Jhlny0eB_31Pb6_t^a@8Xx3U0Z zDB}k&w2S2;-(|@Zus>-1dXvT!@iD>$aZztGUZoJr_Dibe#ifsB#})O}fF$D|xqjY& z;s@H)-aj{N^JKGjmw#&$wFxW8kYysQA@*>f)ew1lq7dDHz^0@4e^h?k;^{|g81<)s z@pZ$^D;hZVh4KbwoVP;)*06}=n?nj_#`NdLcJLydoMBy^Q*Iw|617|%=QKN}GYcgv z&X2LN+cY9KQ$*>;V-ksYZx}iC#F$OlnbkH|BEdiNuBkW%ZmDV^-Xg;RxRD!`L|lS# zPu>&W6#auRuSZGwQ9c~h@+#oKu}M|qM>}fuyAB56vKYp9HKmFN=EhhII&75{y{Y`@ z*#fQj7D*QQS>X@fONvhn8+H+Hx}M3yXW9|TKw|egkVPHkhwNPr6K0Y(j2*iD1|m6Z zp)9;}6(Ex`EZ%|RjLE{J(>|RID^48vCV-;R+U66gsd6Ju(@c~yHn$P^X?}#s z$@`IOEB8qVIX}Wube+D?dk`5I0eCOX7y_!ebIv97E^&Cst1m5b=;DrD@mui=3#4ct zPC(_Se;yClLfzrB*B)^Ewx%v<5ngGW=LJZ)dn{{ZL0dKzwVjN~F)I1aFvO5W1~6cI zkMH?#Ba21U{3}kAThKj1k#9!bjBa@b$d)Mmu4qFh=aorhcR z7Y4AZY34Lo0Smup7^W4fu@Nv)A+h9J54*7xp*d)gEyK?dSf9LTz$-U)dasj@ybI@E zc@s228bBc=(y#V>X<_;wfTBOzpf<6s&~nZsS2B>f+St)w=pnSgs5g}8@0{{t7Bb3f zVh>66at6LrHTKj5RPYP9{tAu<1NzvuF`78L28f|4@wTK#B&(PP@6)Qj1ei*teM%6f zU7JnX?PDimNLef#O4#dY@?9ifrfZAMiOcey)w$;kuj`_F%KEB>#Ixf%mG^u|*eX?kzUk8EZeZ%kpAXmTu_TiUIEO-afzuL~!jDTyf3a0y2>Uv<3}Ug;F4! z;;KOJRX|dt7kCX>*4s5of`hMhnC@zUpN-S`Nw@0%69yMMTFJjg1beSfJ8O(xUrV`k zf_|{Y?zlDwQz$6CZKf0NLfJczU9?f$T$Mm~*d{C#cK}bkALyWo6kb8`2*X|P7lBA1 z33me)l=@o)0)%E0umT#ernY`q7i;@*F)dHhrp`w1ut|L~`>1^v%Da-1Nt?F&lY zIF)DQZ*;g$7^V@QR@jv|cisl^-VrcBhKJ7F5>?=Lrlt7Hd=!-VXdr8|?bLs(gy9iM z5k_Wlz|_vUjxE6vYV5LUM+WIi%mu1??qtxe*t_=m>(W1nux;4`D3+kRXWOP*gRP+S zT<={4ix`R^Ja||Nq_eI6h&%q5KGH{$dR7GZW;=L?wJzAuN*Z%ud^NIKy?<1rZ+>B` z%Fv2yYM=lE_$C*;AsKzOs9lFcBjSUUDMz;U_W8M5=^ujJx8786#H43GN z5=Xep%dG5#)BNdGT%S0tD7kilD|3@)$1eS9|0~kncT;>3)IE~e zNls`Po1y=wqKfp0j!VRX`RSK??L#9L`@t*o*?bY=s`nLm?2>x1=!8}Oyv)@~m`G`r z^lIfcZg?Wu%D#(BA$MkD3XRH1w|`zA!)&D#A95J^O7qb3E4YH)W1b7GQtj|h=smOC zH&0kbb^O8#qM8{Z3>EGqsM}p+Y1oIxp;4ruc8g&DbS=E#d4uJ1&fT1#YD5u$wN$K7 zQ7#C}Sfd61-1#*2?V>eY_yD;Z~MS1d}=3Iu;GA-8Q+`gkgG#B$%Bvr#O#PUvj)&1}f`L#T> zRQ3HWhtfm4$KeTjMwO5m4`o2>8#|+;b#CO#y|dZ^kZV?=RQqyb@ct-KG?&hv>bsJn zK4#2%dSYcLbKv}LxmvcfD>DjDPCUsvu~VUv=$u(8xgJs%(WuT@Q$tX5E9l^}*nt{iW*j?UN$+xMXz|0GE9?3&p)iAr zGGqAS!e{@-T&-*I(}8Gnn&{aFSyC>VFhtv63xLp^4DL8RQ~^wf12IMdQ1rnjK4Ddb zHN@W9h`vWv-T7k0nLO}D5Utx&0)rSRGG{mtL?P6NG?- z!E2}fW^EJC1U*Ki3R+6qYpGcFE+_+PjCBGr+`C=*7aye9+~G4?R?`?@3Aw5YXricE~Nm*QeERgtkWc zNO-k-ke=oE^RSZS{Oky))ZE5r2{E;A&i+=-D@*Rq<>j_MghKV(UWKgVk=g7_j2m)i~mMpKUs0oD^}$ zed-CM$Af2h`b4-z-?!ZvvNf`&Fzr&bieemmQ}>$wNy3Ez6jCWXhWaZn^4LNpdSd8y z5V-EEexs}+3|uH0ITZ37f)x(rzT`Q9n(#<75zR*N*nDiz-I7UPIqt<|MK)0Q-}bhO zDbw80UoqJVj?N^v4g7OLd05%vd-ilBf&TuP9(p!p5gGaqwQyty`rB#qr2zUw1pY>0 zlmHr$mFWZ?WJUy%KpcR%oD+fowdFte%CyO{0JT-d9nQRZqDztXzrf4N|I-36zKuxo zG}`>2Fx5{9-CMke;*R!7?tU5?HnENP!A-fbqxCH>u*U(&fOT-mYsj2dtN{+>kBR+N zYeXrQI@lwZr`c@7HXqeeY`};XaodF{*+Y~QVGs9Q#!&IZla#xD2YtB1?8SW^t^pvc zo&~7tI3XN4W@eE&#gMt-IyL@#Q;a(LwJhmI+nzM?ZuJ~J#S}t#D#(PvMcJr{0MUM# z^ogFa;%`aZH$eL2gyJ=t< zmBBa=2R#*m{kFMI=(3y0$8x2$k6`yBF2=_chS^K8)jOesbT_3~)3n5FI-*7yF$*TP znxJMfp?xZYX0#82AUU*^ea(SNzMxmW z_cF&6AXlA!+Z`{58m?Qi${(^w318rP78*_F(!J1g^i)lENs*KnxNtNSpfC_`W%;^w zxzr}@@V`EseOIMN8i(&R3zd&T9)+rpmCcrLCr$@7f@W}lk0r7uJdTK(lEg0vY5u}3 z?_(Qy^;B-p5A|awig=nD*TImBdmTPi>O!?3PtUYR(LpKd)(q!6Rv>>npA8rZkR^+!N~M+h|= zN?%o}9zCu4y#9A(02dgO@cXM!ryG;=7A73$cFDgwh$fOxWK|oOg0$e19u<#yJSHDC zg4Z`xjMhxno-bc<5}QsX!8x3^E{6UT&5 z;P3}zLOq5YZV@rn`2B_0RMcaOXac+ZgEg$n`q^PFTT9Q}^3Vl7 za#eT~%RdZJ7*V(mKX?-GN7ulpe+6Zav=i*-*)yn2mui0#D#P^ss!z)|{0&BSNo|hU zH?AZ)&YJv>gEmaSGTxxbM39eKG5aR`pn?FR7F2+6?@UVW18vsEcSR#`2ummOy>l+IM=}7shOKo#E%i zNDjXGjdtL4GcT8@BV0u{WWaQg7h~;ivLauM4G6_d%LRd+oT244Rvv3@EOz${H zpRpNEqn3{RT|cX&-W7RO|4~WTM3U&OvsmJ9HPGJ<5z1F?QV_!md9E z=M5EJy#;fdf5l1(O8J4Nfrw%$Si`=EunXIyKy*T(r!2D)W9GlTQFt7SYE>JBgg;Ov z_I#-C_xmpOmOP2T8odJi>!^9gY*00H)?+)8O*?9+MNw3T0Gdr0?t>ZPP&Ws}y*T1c z2*CYSqg_&+J$9xSA`4Ki%*Lm*32y>vY19Zu)t7{oQ*GpnhhTvC+WM8Mf_#IgelUf%s?f7exB`Wt%&v4N?urx8_ zFYlFTJrfQS;G0$=gND&Q3}L^*+uS~QO4D`-)9`p3@&`7phJfBn!E9*sP>;2p~nTyN~U0N}c!70?VIHogz;N%Ib{rfZTiG2ExwS@5r3|LYx zlG{~MgxB)4wqtao3nD~20EVyEEeSuWzeC54f_BgprFubWgWl~ zaA?!n$CHvOrGCKI43|)=Rn<%<%pPcu?tVdiwPfKatjVy_W;otnGPLpU%d(;xdXj#B ziXJpEOYWn=2R%WCFi&y#I3-FljB@hs-x;+=G=g!jG)0kgv z2ntg|j-hVT4=a%MPK2><$E2dVv7HMhkV26U*>`lDKXLXCt)6(J$fbL!Z1z7va92|F zG%<9#>tR2Mz7{Dre}*)}39IvxlZR}NEpUSs})65{Cq-Ti5 zTtVq7P%P6&F{u^o?^>e7633HmrWH~d#QpG>&UL5Vk$uUROg&_JeUTr28k1)3gEe~4 zY%cJ}S8_`?x&fhw{7JzJ6<5JUyr;2S<3BeiuloyVB5q4JZW%j){^!J9l`CgCryven zM0H?wu*?Is%srKyfQaVbEGzDZI+!n189{CAJ&f_Pdo0AMYJa9Sjh34rnC+J>|M#&- z2Kmx4X{V@IlM58C{V{-Jd4=(r>rPh$IcH=bA*(lNH->{ ze;A(pZ#?H&taz}YVT%}#vZOc9W00!#2+@17q;CvLI46ot9>N(3l1jrjv=l2qIqm?h zGG*LyOpBN>N4PI3JGby|WDo?-gVwTN`$zH021J7vIYE3<96A#PwxYYL85W@lR&HLL4(GdpoFoCE1`tpBZ25(ayr8B@KHS{Z; z1SVzXPO2VlWMo0sVOZ*Y`!!Ocb5Pxqr%PuYGn!)bDvD-hDL#( z5QU=CGJ*t|y_0@Qv{!K>X8~GQCA3ZMJC+dsYe9Kl#T@eYl}iju$^vBLm+Fusz=we! z#gL2b#Im^0jEiLyVmEY0U$Pt0U!=uimC*Cf`^ct*HkD1x@mtkB>X`J0K&wX*tK*XG z)o4xztJz-dYCWdy!2K=Mq*yvq9Av8rEV`#5YQ2z)==R=A21tPvz&y_-@Mc*Yc@abq zZV`yn(DQiPac%-xH}wCY#6ES>(z-t(*|qkb+Nm6@uAnu>NjJ10{I(~-5gs(y}krtrBSx${ewA&o8Ns$ z^#fOTzNBNqV8&sf2k{wd&b_UK>@T&xcZ?K$K319EP(UtOD{STd$~qOI5`7};95do! zekx}nnE^qB_^w_}XRcVq*-;Mlaz=0GK@y?J4Wd|zy(o&E&5Sp$I>VVswv%NCUeFn%rfs%&B@bOQwr1w+<0k>#L{zXuu1-9y64Vmq~ ze9_C-zVMQZC46>a;e8W8w)BW5;$zi*sjZy(p62JK)Q5+`YmwD^#8s4TihowptAn!b zs&byWaa-J}UFvHQsu4N+N9_NYS6fUy7mU>!Y}X93e;^2lk~H|?6boSqi*r4W%ytxB zyI{lP7p4LZNHVz%H~Bti&~Z+Fvix^;#3=Cw$;b&h|3uF^w3#Du#)M)BumLr^oM-O9 zcB+|qscrOukh-`K?D6e^Cz_f*Lbe!wQJ$>N`GwRkG{O>^Cj{TW7skw9!pK`>dESi* z-vb&t>_`*n)wKMQz11t29oj-FwolKg6*1jsdB%;DZ z6J_R{xxz*e_VaJK5sIY7hRi4_g;j!seRRg1vJRgdEotcmej$ulU#*PkyHln&B2ivwwMs7 zQZNI|s*zjAGjsM~jmT1V$Xh=Dxu7lo_>3wQ+-O(}g0d4D`0~r=neF`m9QetHyIp-G zBsTi0cEi3RN*k%DUJuka)2KXthR+Lr4MD$a#7}jFFWTWpr@Lof3T>ooNXIZ|!Bdiv zptyaX5vP&DcV_RBBv8xr5_ly8Ar6_9vKyRI)ADtX=%Z4Xjh-I2idKR>8xD|e_;doN zf=I=<0$5hTWPvf&NC|6Q+QA@Ch(POGfb?gFb%zdQp)4jApf%0I4t2&GLf*W~F|_iz zxcTSaPUhZ@U|(U3d6#S?I*)SrS@S4biY88(_k)E)@s{fJZ-4Kt0D1{KG7KfjqgW|# zT$3*I3caZxTpqUpd{Q`kyyX@lsi>`N;e2z8x((SHaA~$~a`p>5CzhU-RWtR!%V3C5 zFjeiWDn#H-ZqC@ZcX7oW8QK^rE(2Ao`J6)7YV68bE#pg;L}6zv^|g_Qsm>`UP?9l& z7Z1uY#J~zz1pVWPbo@n?$!KVC+utHP6PPoyjxyH2e=bIv+zc(P?Ad1KeGkj%87^Z= z4Lr0hJ(#nlvXZ-rYA98rVSWEddJNsgqmJqB-l3KEVkTW68DRp-)N@WZ_m@{B1)&A# z{w@FoufL~T>bZSZ+cr_=1;IsS!rZG|1@$PGL~_6wR5E~j2thc55Ww{XRcmDwg@AV_ zta6H}&se%H8eEzrOac>&a0i(X`*{-$EweTc$}$NSrqKFyQskezz)~n9q}oyJJut>a z_G9WHay)bt)v*d_+>sohHyJ-+@02ES5VKIN?~6^;-V?KZmNvX=@;Mj0%>Ryl1>S`1 z$zYrsrfP%LwgM?7zMS>+`|hS2Vu0M7I|(jRo$Jv*z$jB-~@Gpi)q zWI12s#iygLetK1WnY2EZC0xEBtrO(epOu*hV5@)Y-!$Et^Y_o zf)?;9z+~KVrsJCtrLzV;@Eurjta|4E-re0j=m^sFIH zjQ;rvCyZz|_(j+Vs~2;JjIqoX)pZ#H>H9F(kIPd{j%EOE2Q^-0+V#=g>6`~GdVLb- zFo?iwj3aV*qr(&SHU(CZ)f}7Jwta2=q_&hq)EF&4`)GtPPMW+x0and$?g^~)_%wNp z8|^yCuXVvTD5RyvE!2`V&k9NYr!$2LLHkIrhn5K~5%3mN8mdW$uf`}gfNp2Fb$>Mi zTz1at;?GtqD4PLwTC|9jZipB<^xfZy71O!{LDfCoyw#+i&nC zT#y=C&{r&C|1R<(xm;{6A@))NNqoe5v7)c}Hom;99g>U>u^@7rW>uOru*e&;Kc9kV zxQuoD)c0tYO4NLbh`%;vk4aC4qlo6-jY<%wa1za?tTf^dPy(lJ4@Y|ypv&xL7f5Jj zc!WWT_7B-o;S+{3x9E-x-cH_>k?fu9M3~Kt2UUV;6 zx`hXx`YN_{Q~-~hav9vO?@17HUWM=V1Hv};C+v#MD{zmZEj}{`q$4@1M1@dXM6}lc zIaA}OI2}-3i)|A^_P9sxiVr=rA2_RO?C%K18)CF;8cy%=diUpN^?En#r#~&liHy+i zDt4WC*9z>oLh&mUh7ShF;wamO57a?jy>Ayw0s*mqQwtYFdT|}uZ3)!|tR4P(iypxY;_2&X z7&B8wHdvQS!Ze&L3TnnPDI+GAoY@XeI}wc-pXRIZu#mNH!dR+iExZo{-y=i92w?p6 zKGYDh;wEl2rKuS>|7FBCJW;{lAST@wc$3V~IYts$Db zp=Yie6sh5DHdls>(cC=ySzr|4_8k>Wz_x^m3*7MFnvph&p%}Ky*lRm9(sequR#1?Ec`Sq9dvx%7k9rTl@K~MGmx(UE0!H{S z?&@eJyzvYSW~5y^bGm49eJ_cV?ukhhe&&+5^lYk$xL8&DYO42i()%;JN;-bF4a+^x z5IRD=ljnJiVH>>3v5VwJG<9$}odQh$!uCVQGd z9X5oPCx~hqRr-k=`S#kAU}BnpOGcBct5~f4c>)r=Vs-5ny|jV-#Y6n47+VBwUGrWm znzYBkdIB~BuuyBDu%)1k3PQ{d;h~4}hb#w`+AV zSl&Ut0spQS!KQf}_t*<7r2-zv%~&v))A%E`B6LKn5Cc$8co{djlVUCM+BEtPHaJS6 z)f<;jrFOC5N94O&Y6k9DHqy~tp4Y0n7Q<1Lyeb16flAjl-^d9R>zT)h0Hp9M5EPVDmGQyzv_Q7CF|ndO~)MjI!-i&H>jfnR)cUSF-Sw{ z!L?pw5%#J4P|}_zWwdeuz@ZT6<^B>X9Jv#a?5}udy8PM;Fd!0 z6`ILSnvuy)Y6GH=+SD`&_(Qq2ZN6er#qs%phK?7k)Jq}+S1?@8k?XF-Ax*WAWJ1a} z7*pp=>&2fd+9YzSMFVR6tt8^01QujjqGcir2K zk527{{|Gk+r}A>|F)j^yqD4G*ReLl;nDdo{Lk%q9ydwyyM2hNUXibP#%7)8TbEb}z zBRXX*NLMzHkG0+HQ6>kpIl865!E{gX%NZg8T+Jei0)a&r3{a=-6`wG~GY&tYJjKMq z0;N=PzJWaJAyXRTm3NusPdQcoMawuOwmh6kGA^&JNIvsxXX!PTWesBE=Pa*XMa6ktz zV8*PC_i&eYSh3u)9<~Gv{RZsp$+pWqdOg;QQF1-fb2mRpQkyvr!TNfKR|mzEO@9yQ zN94(Wr#qizjWt)Cm(3PXSSN_68U|{Cc;jGUR&o|-@3MchfEBd-l!c6hEHJv;fJ>3s z6{m&qL-yHwXFYwLyn&^z%Oe+`U4MJ2FAk9>&2>(nn#V~s(-1F3Xr_HS_efnc0R93g z{9KVdIS*%nltQ($gPeX1bNxd7(uQ^drfB~59j0a`>sLci9n0H%ZS@p>)a~HO_&0F> z{<>#1e#K}#zEjK9>}Qc55BD~=HBZHCLo+{1y;Ab~3U~sPxBxwy4rLJb2$?sg!!k5j zKrQ&R`<8gOcJmkYF-3Bm@b1hjck%56BDy2EijPuzmTHblv&+~xwobsqe)nNGLck58Q? z9gvfJpTm5zzP2fs=v|f0#oqoYMA1y=0rVH}y0yc)cDQM~B0A6%u(=l{#e~ffqIyhx zKI!9-XyDjVQjz(QU)?VZhqWm+PR-}{d-F+l-^M|1BTrtn)$BccL z5_`fBOe!(0*FQGomFeR73$J_8&vq}uo#n9c+DG_23GC}Jl(kKF{Ets(f>gOfsE(e7 z1kAnJ6=~MIo+{>zmtf+pV?JkCsr<=-+d!4uAfC*r|3h7W((j#^+H?V#{)eutOI_OD z3Kdl#p|&y~!eTLxotd5uP;EBRs2+?#s2a<5!2g_{)$|c?7CY(NEd{DTrz=5@kIAVP zP~Bz8F^m26Jz;es)b^1lEtrr_cqT%acJ_@?5m zlFWs}_UCgl>#?&Q9=dp|&NUsIiEOi;qMD9+?Rgo#K6}>b*YIS68o~S<3}aR!#uW~n zhB9AvHEoA6f0!Kmt}%O>YBZ0y!N<(6gUX{VZP;JdJam%-j;{l#d;_ZEmXw4xs~vx; z*7d6jY*m_^=}fQ}{$?+%c*o$^gvX+tO3-N7iajceK%XbLJ(?v z;vA;v?LXPIEIkDa+TRk72S~mb+^Qna`l0cgA`ax*qhe(bXls^@0>~DD3`FvZ^aqff zMU~UBvIzW|;zG)RwGIptQYgBTV4T`A;x|wI@yh6}%AX*FKwjo=#TIror?k4~^YXGQ zy(dsb_8sLkwhN0Q0qqi zU8zN;g`s}<9p>_}8EBR1qkF7Yq2U?=pTdkS{;H{M8eaWC5>EInSv5dJW=C_(HS zT}bgAAL5+F1BU6%h9$Stt06#8Lh$@wPpj4w^0^lH&b3H79|vP_h- z;N!9i&=;EY-BA{`iOhQ%at=WO-5LSyYW=qrI)Tm!jX8LYKMCb^x+qx;QYbhEJ|^7e z7|;8D@hcp4Nm4 zzk~*4>Y(`<$!SNH-%I2%8}$s+&(dy5Anl|5IqCa}bu^6D^sJM8L%W`Qyf`}GE_fdU z70^bXcj2vyNV}n(UH6PlI|^(IO^*k@S+|jbVOsFqlXEY)K7$#R>ahR?5nn&uI{lv( zKyvL><*aP%%=&akeq#XRRi~OFyPr=lisSE39RX$wjY*y`x|-cCm2X7y{%rS33F!Gk zdJk@*qS`@<>?1KXBQehKBAL$`Yw=uP1k}4+a4u%@{=LwSZ`-D?@RqN@!GY_~f6h^p z%msa7uJ(hYZ}&@NRoOS zxP=#aAxs2Z8*0Z5&U~M{@)#z&lp9u%(R*J~{W|(OG=IqBWi{ItaC!Nfl0y@gQog&f zsWxXwDt-B;wfm*>z55Hbe&aK-`D55*Yn$}&jqpo`czjr&X$jn+R{r|8*JefB(wg65 z_^jjh|1tFzPEmeu+%S!lNSAbjw6uhTbS>=CUD6FJ9n#$(-LSBfbax6!cb9bM5)Z%c zGw(C+UvSUdGv}O7Ue^L_+%oLcGgi-*Ab$4sPi3-Uz)#E&`E-HCgzacU+74K%6l+IM zF~7m)W|3z$#XXMK+Os-}M1AJ^lZvh98Nqv?Ur?mYx(URF)!9Ls{(s7>Uwg` z36L<^!_xZ*G)!FSw* zA2P)D5|R$zfZ|HOl-r!CXlHL_oQNm8+b@9zGQl|LejY+&U5wxU>fGBITziBFWs z(>s@Y_`T^2;-LAV_k}}ZVTqkY^z)PqKHJ>W?L@?9LSx`Tr*GZ}^j=6$FT^S(+RLc@nz5yUw<^Jx{dr>1e?lL=yfrd6Q}l+07| z1s@qlhwPu-oQiINPI$-EAHXN_BbAwy@XT`t;aUxTzDk>NOQ)**&BCea{{+XUcYIOs zyoi<2n`}T4>=z0dKpeI&&y(=WG*s+x)>q5)2EFwTt3Cc>YVODgN(xjjqJ3*Y|5`uz zl5w<21mo!hkWI}y)2hjds!8%0D2N)IiD{J%%4-!BU0|DdXWCD=2JR?uvydP17n}QvNIbzUK_c)U5fz*e zdWzUsXXQV)BG1d38r43y8{LDA@1?syNVb%Q4v%zf2hwC;2TmH(3Rps|fvR=$+G{dmS0~Y&l=@Dq%dF@5KSr7Tw-PPT=@RX=2 zds^Nj$2VPn(|Y{rHD9?NO_S66mRz~=fpAqu;Q;zf+S+-QlisG)-7B(g^vdxX*nKWk zX$uo1^Sec_nWJf`GcQpieepqhvNg(NeQ17H@+e*d?baKGEBZTMYUY**G_=9sHf3|FE% z#}nq--bUh9r<9uU)e$e{ClApP@!k0c{(MX{2}sYXfYq zusCjxH#qgkE;?Ire^fpzfbD#>&lc{xnMQ4L_Y|8~rrdZ;UtJOH3?SQYxGa4BFxN$& zna7vONaTb%zWGHkk_Sv`x$${?TYX}ni#bz<@vVS*u^}+tYbtOTv#}x)=(1l;8S40m zZM;s1ydZk4>s8}$+|$v40b5c&F2`N2fi-Mj+s#h?Ml12cQ{G3(9CusDDz9nz#U=cU zbIE5`D?eK?KSUAo(-x4gQU60NVPI5N#%4IgW+>QtDAbx$f;TNs=Qs{*I$QRa;V~Ip zgRaMAmMTG9gG&IaL!xa%pw;`<0mUqUVwOWOTa`APk@c7Z8o0l+4z|)z=pw))6^Fl# zj5CcPfyozz&7yO0CC0&}33c^)? zgo`=?JuUW?v)!+R*6SS5Sqp2YUs?jbfV6 zFz=rj_qhYaAf(JS=@zgO%~>ExUdVWAWKn#9B!ybGkT0K@WB`oTnF>IjiIfLu*x-Q| zzqXaxG;Qk(sF*A~57xBunM!H0g5L)2rrkFo!&CyG{XS%3wtmkeXA`J4-ACy*mscn2 z!SERx7zBQ*0l@&wV)z=7YLjxud@O-Yp-VNjul!5|7JTg3=sIcgmBw@(DS7vv-_$dP zu1^`}8?o;OaGHERo@R%@_8lp+2Ynsi%gp3p@BDK7us>&z*cL0^bw*0 zitTH`r4cKV?WL60){58hkGtQl$2wp6nj@fM4;)DyH}juhlZMrotvSVet$q^V>7$Po z;N%p3vBCZnhszyB62qsg*X&(G7`YI(#&3s*#)G9tMEesMpSj{NKUQSq9L9xj5M!a%;MggU{RLMLN=~h}L&RQ&$G#Oj z5q74OhdOaAuE{!uZfN7SboHJNsrm;sye;5E99l=eNcsrU6ZL# z(}R*e|iOFqX#IQ2=e z(>h;cmWN)S86d$9kYLc0XV6pT1IaPy$qDI6GXNC$bS9DtLDFP#frRPbF&6KIoQJVk zM1HU|qz~VJD^55{SFSYWuFnW)U~?t6%0H80^55NopdGWuO;YXlj!lQNfU*CBsmY;%b6*aDRwwD%A1oK#Mi~JL}?i)^u5nbXlHs zM?93KvGs!LKY4+uoLWPn=al;LeQhKtfxKCtd4CGKMJg6%4 zSIp2$866oLJrRMbc4bf8GmABWT3aas?Uob4^{RCzZWaDy=|%LekEBb{Im=)|L<~#c zzHCZSD&y#k#kHq)%q8t7O@>={*@(=rb>n)_P@h8mdOD<(2}ppvf|kU>sUHj691+4t z;9K{S_nWxtso!v^eVR)D@Yds~@7nMstUj>L*_vb+(ct=r=y2Bi=LlajHqsmk%)>4KwNv*H`ubTM}uqi&I$QH? z3k|(ECGTr>fjhhPeWu!fR9-m}cJypWP=K0pul#Xsim!`6nZjxI4X?@tqs^6n)=f5{ zg!V_E?Ocg06skaO2#KM|^R?uV!*W0_no)TlevUx$<0nTw|2#@xbAbN!*C~-_Ch!LJ zvq2{%e%d=<#+PJ2N8@Mntx%)#{|I|v$GLMo$I?bkQ%7(?)s}0G*nfQe&k3Re zl5O*&id9$fmxYcUuWBF@9Io}FOiZ$0x(&=v{zmh~qhZ!N3sFgI%W>Ny%v{khhG-zhV!uRTj8!EpJqhiT8JJGgcIKIGAJKvQQZu|d`fDH@ z&X8T$G21hD_}Kck*@I;`)GK;;)MUi49Hom}3x_uY!b$3&vAk3F#+sl5NBTj_t?#Qm zpw?M2pbBt-!xWpv!9>VCIUBHhFT~mrxwb5#0#H_sRK{ZY4KgHis9|Q7JKK)DeTux2 z=i7GuA)7aRfA6{bx2yfdTcwLw`VVZ3>$qmQDTv6CGN<=&b<`E+IaOm(@psEO^hiu_ z1gWz&M+2%p`}7nMWS@^BtP%1n;h1~ z4F7G*uJAdUPQ)g!x(5IS<*IXv&rVx+wCxYB+##b_RTI=9n7X=2Tp(wVnUu2c9ma5L z83wQ!nETdCXBjYCoB?>%b-0@6t=@(`)4ND&BwenxsS*&<-&otvDk3w}5onZ6_AwcV z76fE5`Sq<^S>#Bu4zqSLVr5wX{%9nB!z#)Q%gi8!plKz}yK6|=1IL_DkU(WF0-RNT zl^|d+CRLQZB~@hFDD0fwAH5~PJQ*^>?9WEYp-x@q0)PjUZ^%0pY6YODYvyY>0)X0p z-2Q3#GurksK)q%q`8O#*i>9#@*|0R(&;Z$RT_gAE@A!ibax;fx>iJH}?HB5((0xt{ z#vv>Z^Sh*Kf!x`ei#pSOf3Yu1(vnO^<7QFD2)P z-%AbMP}2L^F*c7!LmYoHKeM)FD%#Q?EXe-}(~vSKL#GB)UsUUcvm#UN1z#r@Nw}IH za#)uJ-shU*``XWqIyZ2Pw3NRTM_|dmPLIxwWKwl;z^5X5-L|p@jESQ zk;`3Zl_v-@*PuE-_D8F2o+}M(gcSUi(Stu)VLB{MeA~ zl;#$+0vBF)nMf9Vqy8gczwHlI+M~)ReqebO5vUYJ7xFV?SEp!RrK&)Wf5)M)E6BgT zM*`b7!a~(doIvKo`ALa81OyOay%A&NI*Ph>aa&_TF0DGhj{N%XO3pXcdhh4U zGL4Z}Gs->3z}$Z#Ks&LBTbYga$INl^%>SQoH{@ef<_|qp$DDoja*YqttSPKblP6)e zd|Ki5Z1fH-_wrNpo^EXN^Q8BPttvEy9qEakqipAqeq+~kvU}B4{01Sx20CtU9AO%0 zjYB0J9DUAIh+D5aE^XzZukSsup90%3A?ne3t55n%hn?g1>AQ-Vh69Os4%-an#KKqa z8{fZVZo2HQd^yLcJbPtUPc3h9IcLkx{*ek}Tr2PyR5@6LVW22iZTy2(IlAm0?EvZd z|Kvf||(>$NUW{+RK&50V~tD9Nwxt*wNtHsY|(=I3VmH}`ySY{c&> zM)iYton#>)8B)-~A^AQGSB|Uxa5xhm{~3B~M?4>6EYgI4=h6LZj@jTc;}nr^`KG$R zYIJ0~nM98ql}IBO(zB z(1i_R$sMTYK~R>ZU0T-UiMXuq-4T4obT-3%<--kZ>QoBiv6Hmbl2dr)z<6X5rhKf_H1(6I+uSTP5`|jiAk*-~fQwk3HWrkdtAQHK& z=^$`GUQuKS{ei1-c&x(i?*(TI>cCS;Qcos=h(g-OV8rW-zai)H^+gaybYhr*Bvi!`uF!B1!xLW4Y1FKCIyye90FfF{yq= z$FDO*_21u7_@l#z>74Ay1*=`SL>|VC3>aug-1?9MZYJMpnubUt0|V2wVwmTX`&cSw zgg!DiId8)?zu@gqW_A-}#*=kMa0&V+Qw)qn2MShBIO%#%dB=XeX{9A{R4b7iDJk@~ zsAnt?$u<>Z$Uwxr`4Tme72eXeKHlGV2nIrq$6HP63;N;BYGsX?!QA6J+~SVgdD5^aOhoK^Nt;7Nya~LjF)jS_9|dyNZS%;8cT{ zDfBOJGr`P@s>lzj$j#M-9pNTl#iKN!*U8e{3kd-#g%O+6XYs8xD2H1IbZWp4`IreG zX5%Qt!<@y74rHxW^GOPPc-_ywwJi%@P#h07*CVphANWO^nU-sWX}4Cq%8*n2d2Vf{ zl4f4&;g(J8c1WfmzB}$|@gs4#CzZVslTp0uZqWZY*v~EUT($_4Ed`;dX1l9U6416t_HVSN;SVCQf2lL?Rx_@ta4 z^Wr16ciTY;saqrS@*SV)mw$6bb~ky+q5JaF^9#?Buc@0?^l4=le{SU&I8t019wU#- zpD?jwIJQqu?}$a`#ZR5lES9-59kCW!c~`^?MznPC-0%1*D(%2N8P%=)TesF-77-Cp z2iBm}Url}$QLegK+>Z_Yl!{-e<|mX#B06$G^YJoi#orhzP#h$iL#8ck%lA=xL{==ynOA{l&@#7%F(Wtp}s>JaOm#( z@lPyjx>5JWs=yTQn=`L_K0G6PStG*n^XG{srnA6n3H{lH1k)-bjl9Pr!{P~cq`;j= ze#*)+QyOdeB23Jglp^$Z8C>uV<`7a#K7h24#+a*aJ*1}$zkE_>ATeXum3*Mh4gN~) zodXlRX%<*r^P<>(%lvdBx_(onJ@D=y?)VsOQ@gNZE5ETvMXziFq)rLAs1C#<&|=^J zoq5FST0ZWOUZNfYT&lmeEMmtP=UR;YJueJ=BW>Z@9}s3fw*a`X;dmSiyfRJ8=zFl*I@Z1=qk)?mChypN*Ho;#Z_-sQncLmv+y@%t6l;Hn%3- zph2!KPj^zrYsj@-3>gXqB{=8?&}MU~t$)^^LMXtJJ4`*D> z++RWs9o20ALisk}QYcTUV!SeJUsz66DNl=hz?!$)!TekFarr?-kVRw`Hj<(8i4yB`Au`8p?&|WtS3+b?cvws8tf0_Ty&`~cyOc;{ zqhIW5)hoM2#;4yg;a98z=i`(vKKplq>JN>dUYB2!Cwb@>!aa+Z*R~IDDV=S14QozH zI!9CHU*T961LIj3YxZ=HyrjPY-9S!ohd70VbKwH^P7%FdKHjRa;4?h1j{25L5$3a$+0Bp5zhd zCAvVIM)N4oODkdvDg7uX6Fi3Hf<%B`{A}887=iq53H<1a1Y)g0=hQ8s?e?cGoTg%R z^P(a<gt(9@Cl zXcD=CQLQ4LJ@cTvY0=9_6rQyJ16_-K0rKhm>J>EN)0#Q)fO&h3)Xew{$?cZf*Jc0= zR&OZ@$V-zkCDHXa$OFF;h|6k0YEw2E*amTKvLFjA^J<+F=$N2j>ALWCJsFJcZ6TCM zHcRRo9k>MzWbIDp3Nro5%7BCv+rbp$L68wWBnh%~s1xd9N_Kj})`W;!&CrrOk(v4y z{U125!1;3^qlmpmH@!Ztr4n{=$`)0BW+YTENx*q7Vg4cErTQaBn_khF{H#vT+1Gy} zVfW8ew-g47g(%-m{+vnI)k-Rk?3T4_yjq>9=lQ_2m#2E7%jc^VBh?3E)%8K&ylB3v$e?2J^0wXl&Z#XvR%&2} zaiiLF_9p%#w9m5NI`VruV|t#Woc3w@74y7X;d|wYNx*p80PhebcpGS?#Wb0O(;~_8@-<@-a zU${jK>2AqL_xJSo z4fJ004gfpC(SMD>vOdsf9KGM%4RI_v+lngQ$S(b)doEPyS*nMagB@2&!}8VIwiI0x z&OHNc6KWeEI4+V}o%)VJ` z$ouh4iL+113N7_W*|M2lC`C1%QM)|TnR<8)i?oMkQ4I1F4UN)eU*OLZ_YY$kTb^!U z_B%OH_S&q6q}l?pb?Z#j@hwR?g=#q@mabIb=l`P5-t{Fa`)9wL;7-(`M9CJgh*B{_ zCT%+bl0dg#&mSLdJ#ea#%j){^C-=#hI%RWM5gOijXZ+*QRn<`& zAB`OsS|EC@980mX!c_4_f=&rlro7Vhxx9ZSdXacy5j#)Q>>BlDuk_W3k#B zgqYb$%=Oqy&Z6H(Wp%Uw{>v=RJ_-zF-biMGh zwR5aeX?^=~Qr`OY;I3)m9^3X|*UmM`5CtXLjW*9*l7`!fnK3@5Vdh01da`lwXGc6k7I<81L!^jVdIWyEbAw&7 z4h*`A?y&iC8paTCT+v+o$%1%;7wUrztj2+Ipxpyue~q44w(C3g+6-G3AgvYkp~MJX zRbl%FLnY(EBJL97n2WxnTLj;s4y)GK0M6tuFuf;VrRA0&iq?--PgNT1=oA z!)l4CSac1qmu9LXI)9}n68&VMPa8EF1g>#3RL*NhsFL*~RVoC{YW~o3@9F7)2<;O* zH<7v3}6btl*S4 zdHN{`Mzo*!f8Tgz2mO&>gs3AqD*?_I3;3~0HP~-N769`vr+oLeM)i8aH>jJpGgKSq zFvI~jkJN-UfiHN^t?cz1#n#%tm|FK7N#DL2F_s7V>B=}g&@x{t1B>54`h%x0^;;=y zmP&f+t4|YQS#SKgx|%s0j)qARXnkXX{C;SIQ+2m=?hb|{ol&}+RIBvB9{vhwj@Tz> zlGTY74^?bKE^wec&Ei?WW;aD(WmdQ!SI> z?wX$6Nz%+Jm7no`vS@GVp1J9Sg%6@0s?v>gDYgqIe z9WbRwVHHQSBYBALCHm~!!Ts}(^l}q)8P7mL{v)UU%sYff#;;qdDI9AZ=Hp)Z^pR1w zb3iLUUG_+9`e{te_;uNE>!pUjxu!fJ$M5lV^E4pm_sxwM6{~?unRN`CS8`;s7$cdD z@eV+ct?HTa+jtnNKB9_p`)KgMe3<VC_9%(H%|KgA;z8xuh?f#v2Gc?XMSx8P@YlbM zqHm{^hQk`V$srvz&Yc`qot2Aqz1qCWZ_zEhJ&pb8za|Z0;|Nfa>iWX3Co3Hk{(C(U zKYw>=6a7`S3fPJ*feXs)ED|#3raN##Ai8b{3-8nzojCw+3DX-X;+H2l{|n90VfG6x zO?bMJgBv;K8&^KchoeV74RbIS)rrNaQYY|4c6=wr-fh_}fe5+d9J^8{ukuih&jnoGUp@7pAYi zPlN+zV(yRBmEd2yp4m)J7V4t(z)UgenRmhoXp zlq}LJg0>}(_csPu28AdbpVT6WD%GjyuY)VY50@Y;YJ?Kh&6RSmQ`ky%CW^KQ5Fj;) zu%3+Q+|T&${of5k7u(Ucm-yart424xS2dPP1(D2#_HBSD#RGNQAH0=G*g|Z}(0ZHf z%OQwcpX|-Uq$P6zK7SR@W6JNRRe{k)L}(Z97dsGjfc)7i)NN)FY0SAkWKy=kg)N~V zCzliWYlueGs%ZQHeNOf%Oxe$o{QCIs$;DXoe#%D&67-1uQ>y-igB2`GS4H&bqrTsE zO#;NyZ0Mxwn}EVqjQN*h!xdwY@9(D*Y4ISPZ21+i(s8`_R%cDDkK3kV6GckDPvIVV z-SKO9w-DiflDMuQHbTnob`E;-cIq-bM(h_=Jx1h^qI?%xkmR$+PptQBI5hu)jRBcQ zs+J>AV|I4z*kpwy6a!MnFln-}@d?&cC;S_*KPo;Nu@$#>(CKTiE((K;dHN(Glpt!F!|GY=JS=#hkQ(;9}8YX{(I2QbH}6kW~6$MR46 znF*eGzwncstxDLgFCUlPv$V^weqX*|pI7Gp3s4_BNHjiO_5IUdU|GshW@c>?$RiWu zvfG2)V815i_i9IabW~anHJ+%<`Y7TW_q{24mQ6`9M#OyQR&Av7&Pw^T)VS0|tT#cF zsC@r)lb`uv{7k*&DdYG}qSsx630IyziQ25+S7q8hS~j#@VQ1QUM} zxHMgluB^W*xWDYEa4r3EOkgXV^GhvYeGQl#HILF`H{L$#935%~WM{MO4vlo~+MZ|% zfF9`GJ74*2J&&%Ur1)xW7T2AP$L<#OFQwf-!Gzz>`X%nj^`)M@f~ zI|()_w@s*)lKggHJQ!zdS|xLAncH-$8a!F~xmu5Qbx4T9F?X@Cz&)k8bAPB|u}X=M z*6QdN*HMW&bSW5scO{v^FC514@mvhH_~55|uk+Z#G)&j8;$7z|3n?OFQM2-`EbW#^ z@YN11e6*s{ucQJw#xS{+V#`|?`)B$g;9Psk7b$W*q}H8xO)J!23h6|UCDPD!j5zGI zy`KY~aU=)s_X_IzH))I#gfXt?u`pY2F#c5mekTwc&=PzA6EsV)HJc$Wn$aH2coqwJ zaL(3;9;`hp-jEwT4xkmEHO7-D#*=i&yYCS0^^sSUp=wRXI`YI)iJ=q+?58bM2IFaL z_sswWFVuzgvwF&$el>7lR$yA{sFk2;W4s9REg(#VT+{|NHN#g7`&Q&}&TaE7@Ou~= zu7<2O!}Bzg@-WAh!K(u~2>qF`DR;U93zs7izg=L z|40O{`xSZG=%LnDzaFGnIotX5cW3Zpqr8~F1+}48gPg`s;D^ePxc3|to7rrf+APVC zP&QvOf)7mAt+;>w$w&P|$F!m)fNa$k*2%-ulv$UvEJF}5Oy+Ypa{=)q&Fs(Peqeg2 zUSuHOLJ4W+xF}P`DxqN!@fWEK_&E5m8N1EPAoC*|gX)QtH9~k@M;uSVH#hB#+NA!r zBtjkG=o4>FE7nzfp3R-A?~+#av>4xPV?r4%VHDM6j6A!#GnIv=pkUONgp zXiY=(c}v4x3Djk~(XZ!w@5U~u!SwC3?5J|Iq+O3x7Vlryah4xZX!C$8Ump2F%f%*& z>es1KZB4fHc=;PTVtk~#tk`-j*S7!FYBtrshAM{0AFSO@?DPN?4Oj{+ukL<$Kk08B zy@V$M{U*S50eP&zKEAer0v`IzQW&mGxuJP3G+^||U|a8Mepu#k*pQGw2^lX{^RM5N z2%YrI>8f&r52F2@XXbc4c&m4=Sq-tFgY8SR)@YFFnN3$QzCMDK+sH~(PvOQFt?$_( z1n}R{bx6RYwXVn#tLQ@s*L#cbuUpTmDR^CG@Ib(3HU20zSFPq>rHAhi{z~1ARQf<7 zL?=^U;Hnm~z2ekj;iXla5X&KBz!z>#LdT8r0JE&wJ2Wk($yvtdK!yi!QK0eGYHf}tHjXp%hj1}amMqlTAFr}Q6t>AyUOW~RctTuBDxT?5#=w8Vn8|+kUCwKk&T8hnRKbRKGpp1)ic{& zM%|fLEx+uY{d1j#($U;UTg*@V(e&Ad;{s{DV1)C5Gb6E+9#2P{?Kw1OO>7o8f!U6j zvfEj+9^S%U-W_wwpKkr87Ztw)H6HfiY*~B^ir!-3{vCHk{^$YLJb8cvo4Q|GBDry) z_!xtKdU0pZ3ROfYujk(ig;%o+^2neu*V+)~i)tGO^A<1iHyY(=pYt{q8ZBhYXa&*q zU4@!sNH^)vKO)B$HfbsVv$K$DPme^a^#KhNHuVbz?gV>E{USSrq!xt^%@RG7h|%2S zn_mH6DeqypdR~?j{2nMF2X)$lltC^+0Ur$J|;&%mpATY_rgb1{YpUUM2|nwKh~SPg(LScC0HzA`EJaR- zA@S@!p?~_elURU4!6DNBO&`PV1`+%(c#rI}xoaKi&(<``($L@WhD-WI&jB}Yi(`s% z=Fl6kQEWTq#&TYD$7j)uY=Hi3{$j7rQ0#?3#zXnpJXE-mP&Sr0=z9(W>~NIXk-9&L zY0ru$f5g9PSU5{^Sn;qt&5&jp6wIP>Yo)gzVEfDd_5C~631a;hkXGoBLM^KPke!uw zw{3lHCmR0d@`PRVp%h8{U8nWC`#K60N95yLA{=6v)f!Fik%{<Z9qSsB2sbZM^9lx^rY(|kYNYNU>|AXupb3stw*A;~mDc9KEhJ+zi zS#RS{xPsXgp=7L#te)Z|8OAi8&|sNQM)MCSo@HI))9N&_&+@Ro@K2vJx^MHOMH1XX zM>U?L)v&{129U{MpMM*Uiubd`sAJ;p%F2t|DaHMJZ8hck`O5|;ZSc_%#9 zizVsi3ktfCIP}uESD(3z|L1iHjVo7!>!Zks& zSA_7e_eQYyMx{`}%>!XNC|7Qt{_IxcPGyz4Z*4Y7QG>|%iUHY(+KPC^+HhAd)`Q#G z9U+}zw@T{udXxe$a*GL}sO*~^FZcLX_oNl*Z?n_j;V)6~J}XN0)v+so-J*=ue9 zV|i|fYYXBg0*p6F-uDcDk-1MD8dS`xJP-s|M(@kBUd^IfR8CK2?RE#%9oi)iFdt+$ zT&k+CeV6TN%Xwk8%B{tmhnGPo-02?MT(qkA^I)!b9CTN?}vH_Q-wEuK_ShE8x0(6B=S-aUN=v(sB|@nhOOz_xJ^*f zDz-HuC;drO!c-@P+^gCq>+kEw5l`5fRd}+Qu&*3DFf@HBY_&OSST{7i!|zvFJbP{8 zJlAg(M|zRD;j*JB%a|<-N|UH{DzOjrE_YwvvS?|CdZT7-@xx$5Gm7%n0h}h?Yg7H$1%HRJ0(_`1r zp&RSM%@*qLhaaZD+hbiIES)dRnkORi67hntp*#2 zy#>1ZhMFKh!JV%-M9TVGBa1G2C-Pih?mtN8hVi0oStWM_i_FFHc#`cqp~KWZ9vQ!T z%j9wME5~&>W!m0}I_tL%dDv3r*wRn0jc65STgf@$hQ8B#%_G*5Kv;D>bQwCI~Z*l3>{N9V|+V*27m>zGdY- z|E-2Cx0AG5Mgkf|+BGJ6@kWR0&@>XSM{%K?iDyiuwfBEq;lUY7qnW|BUppImu0)W6 zUPPA11DmPZf8+AtD<1h0G7Ve;Zq#XL)Rfp+-fn|56w|FA7X74dePlJb<<+=K#KR1i z%;AK!Cr86>_H^s@LEaPgwe6@w*W^?#&mR^uWQJCRB#K{&7h4%QPxZT+JkYMb5??u? zAIWjtPL~Tv&O3!VFkSr^uvD6e^r2o zW2VZDeE061%QFJJEN;nEUh`WOX9TrLD?9SUvk9Ol4*%H)2Gy!*yWKClqf4HykF(Co zPE^mi%lxuH3*O^Ywt(}xgdgt%9>*iiZJ1ZcSaP1`P`Q{=9%Pg62=m9QKG|RJ!4VD<`Hlaf+g5Pui0;odg*((8g zp-t(bag=aZ%m%(6gk302FNGd9DVzae8*AFN^Y0T**8p)mN{F0%T7@nZm?P?`$RV?Wji(&)+-NmG60bVb% zN~3x#rm8O-t&K2@jZ;@b!wNtp>k!-JaDZ*Xl}p2r3@!&QRpXRP_9T5a5tG8QrTbL_ zfF5@HFL$6+6%bUJvKb6|wvD^F^qd$(Pp<|p&qggTM$Iq&T<(yE=i}E7{h9b7R`OzS znwp?1=#3|QwXOk3h;HWyWpE3Xf6r(SL4L0NP>XzJv8-*>aPFk@^!#R@2s-wf=&B*v zN_RDAt%Ga!-{{a={NR7y=bJXFu!w44)^%&kQmTvwH2AJ2M+;S#XHes54);8k5&^YQ zsH3nWEFuL;BL`Yhl0r?UEe?P4KVPAuVXW>z#9x;3&&1-gknwk6 z3C~XL550J_aI7{<)AFJ1MTTtiz+^<80?c)NQ(Q)#z$}WM^rl!IcT`KME=9^)RicLg z{JEfab6JsEjs3lcbZ?pOoyYfaC##YzUStQS&_ZE8o~$J)zWQKW6WYa};w?93>PKnz zhP@hItm#s;g5fc4n4!A=L<}a{G2U8k;%?OX}Xab{^r3e}`U5&tgXOHd;GX)Ec> zdN9Kx;Re0)9Mc4Z1FI?BkyWAU6O`2lynqm_LRF-P!v)xOdPownu$y)=2om41O zhX)1J5e24$1P)3Bno9&8s6Uz#&!=^bscev{H-X;I*Eo`s4Z78QlnFgD5oT`?=bY%j zki0g@W-x+KqCH)HB!{4v0Ftfr)BlYkM5hORl7u)}OaF4^*Zqz4{&6!gWs47k;0RNZ{@)B#{K(UIoIZFCg{WsQ^v4+`!}_bet`nY9k%I5*YH4pT7zg3qAr%_+)VF^q)b4@flUQ|Z@di@;U$5Oyj;_9PPW0Mp{n;# zuY`qUStO(8vB6k>HO9wI*nS1EC1|XrO-yhzfo7!E7xG6K&Rtvv=+v8 z{$iu%; z{twl>p9YnK&poa4_CEvV3f4Dz(IQao%ZxggV+K@mT8)5Iy}7J6*8xOC)pGq`DN70J zgxr+N1EqFpXWyM@K|KLgQzlEAn{uw7H{B}$h*($)-q^pu_43Ku-j3&+{IFoeFBdt# zqN>cf8-97`^&Ku2dN(KOSZB*D>s9lWH%$j= zWJ&D)VbbkOEXNVnJM(fwL&8627}y3pXrKh=muiJDmTB2>4-xQ26(Wsn*b*qulUA;J zcKtoSKWhEzYfe(446;=7?|d#_01-eY#f?FbirLeT9B1K>Si01mwQv~UR* zP_%HhzsTwGUV@uH8~A=y`7_}{+XPVJ^g*>eWEnT(IMt#Y|4w=8$Um+sJZ^-)KP;Wu z?XsYvVv0@C`@@m=t{Z2in`h@NCs(XCdZrt+q;gE<3g)>8B0Kof5#6_W(-&h;=WB~M zNlO;?(O_cr9{v)W!$|B)(e|YFv5cjKA?g)|&i*7x<{<9n;_n5-{c6;4Q!&9<5ipMB zKkji=VoRn79vYlp61j~iSEJaX>Omn#vsMN(vZ^g*gWjz3=rZy9)EEok9jxpsQntgX#5M|vFb-wx*AVv`k9%*;agghdv?tlUX(kzQH71z z!Hzw5*;rb*kgXgW5eHAecP_csL@TZaj$XVow&cr_w{9N?K$@F)1*3W*QVay|nrMa9 zY-1rF?N4^Wn&_&pCNQS-@CjH&#NwP=$$I!i*u+2)m0$en>UqFoHaJZQ? z+6cvOgd&wdk#t#xLO>fukc$@gx3Xmr?_@yYNk2}Ubvl^Ed~VLF3DRc$o>5rQbB7(z zLx}hki)*Pp@*>7=VbY>vh^453*R-=Q`~_DNAh!Dp&j5b&4b-zyUwp>f)r!0Pa@Qg{ z_@}dL!B12R!+^-ZFUO%}13ujE%kCq`L6%gJ<4@(Qq-|m*W$7QqQ-!8mMViqBM2_?X zPBz2e%7>*OLsG0m=(Y-=cmfrP1H&w~CR(-3|Ca^OoZo)SoiBG{+^un~pblP~=Ja_v zBAikLXQ0+Rx|?3x4j!*W&335CnBaYDlNO<>-Ja4UbJ`vg;F3cl2zJLxdHpMUC)b>U zp;tafeJGF)TC-d7VEfk^d@^{m+<5Q&-<7rGV6$11rTRj!AYm5OK(DLed<@Lll#~HWcg0r=x_{y3cEs|w>o%}vxdejfbAk?YmS4H1Np?hH5&04<)%)3Ox(4ihk8j_g2P`jj4DFWyE5 zZVxFCsmk0y^;eB!2dA*g8u}C*d67SWQv06}{z~1D*QJWjx1d~cc;JFHEesCdN4%Wy z^KbF?V|o$z^VdR091Q3yU>_N#bi4W#clXmLqDA4PwkQ+#0S;QTO_|veoP(T z*YKNSyPHw>lsFy4i}A7zLSU$yw-!w;gq}JzLZrh3EWpC;XtS*w$h#or`b_8oGdi7| z7^rO47ybXxbQVl;bX~Nb8DwyGcL*Nb-GU{-f-|_o;O-tgxI2UZ!QBQ37Tn!~dvFMF zdB1yaRsVtRu6=f`z1LY!9pGSdl})5s^Rf7QVs4bPh4L9({S&5DiBtt)#!W=>aY~04 z^y80OX5MT>#ITKOQP^IopN&FEg)U-V%9UZqoy9a!N(2OXJ_Tho+D+NW+MK5~Wh#zV zd0jPu+~;dza}C1x-%c7wQm-PJf>M}0?TCjX&>f@(N0}eOEEmPTyA5q0@%)_)z9oB= zd%xS9jBE-SmB%r`H^Hy=v;cJJ`>piE`z)FgAM)Qz&N9?=Jfw*esdp{sLo zVFGrFC8FGGg(p|Yxrm6#0n179el^fT?W`!MC+1&@B(E6!I%^ze%h~J9mby))MpT3% zy@WXn2`^Cy*TAW|UC@*^)cl}Zjwu`Ty;-_R)-m2cuy|TR)9s@Ho2zxVQ}lBeo6}2& zsYudo$HDo21V=a0qJ`>Ynsed*)`TS|i`@KrN}UfZ{_EX6m=4#`_O%@US7O&a!bT7m z_b`b-Lj?CDculGu^B<}0vp>+|4>A14e`tRgdE8u}gkQ7(BLVf*{jFXC-!z9QPghj= zv1KjeS&%5ofTpJ>MRn)ra#}j{4{&^<7Y!yQM3-DCUwKd$%|5Zr?WTejWyTm1RFk>4 z9kq(OCL-VT6iBMP#x51jM}6O$HK z+_^g6elrRnDz`FTNG`{eWL@A;B8~+)ibcJHx7%){N3!B;ym*)>>35J9t6eAxl)*pC z>a|A5@6hqmrcU^KcZmkc8m!={LAx#0n3zR*zu=OL!6xvwPFkR2z4#j#dVsB>kDqG9 z1B)=RVMI;G{>X!>7uJoW12zw1DDR_aI^J&M`)RwiT&g9Xfk=eIVCIsbx>GWfFubW! z<}@HbjJ`_${5|QUbL5Xh9<|T2z|I<&*kNPb%9%T9m{+-!WGM0*)1G|8SJ#GM*M^{& z;6V_TVq<&(*Eyz!6-iAwa{_1q4+-mI-O|;U($`&}UhH3@e*%Ckeg0YAPgLpp3&lvv zPr5B$fL#4q$aDwle1aNJn{)3wxBUBAWX_3@l%8>APSJm%*Ey&nhfDnuHt6#yjoJka z;%@a8><5_n0WFX&wTOp>;eM)-j)yj;!FuQ^Es$?RU3Ja$3ird+5)V&FETQ%5KOGrTx&d6wdPlJ{hQMPYP1>elEWgr|e z(@9$7C;ae>psseTn3go%PEVdeL$R&u&F(LF*o5*7Wh_idQuJf^p>Q)PEs=G5+d$L! z{nMPZ+eXR;Z;&!*hR)uNKmftd$Kk1`+x#lUyyv)ezvti8cB>Hw;+Op#%ZW}A1ig?` z7Uo4mIjsN5!dtG}V;VZ$lkpCL?nVCpg+CZxh+X^zHidzKL2U&!b2Tc{HZsPatMT9s zol}DC>54g}s?;nar>@YxUsV7Q;gYH7HJ|QT|E(zzGYODaEn>#)D6aucu{fU7S0xl5 zh;)W6PFgg+CIPj`Eo8p(jh5y{IW?h)gz!uO@V@i?7@IYJ+V{qIU^tA1g<|U7`BrAQ zI^(wf6kTkNGZF2I5hZ(@6bEs?4@{%zA5oF=N14F8@<#pg0QE`-tpz6tm-Ua+0#%~> zO#=8f7?8GZ*p!%R7Il|Kqnjd6TH&1k(y}4 zfOCHZGQJ-6aKSzr^%if+@l{Q*!iVyDd~H%#58}!v74H~AuoAA^fRZuESG>F-!F=s! zg*OoY?Xm&R&<7o>(8ZK(wTT2SCL9<=_1se{F1` z|6*l;z^fBrWj>BEAWk-eL&-$;9qWj3g?VT(VzxZ=E85`OtF^^Z&-j7LUy>BibLA}l zkTuj|ZYt|X+-(wc9In8w4O-%*pcX5Tjc!DrKRhQ}ebDx-tzX(E*_N?7!Sr9yX-m`N zH92=QFAC?Nrow-z_5B}OhczrdO~g|-K8C6qlwVOvG>+-`_3WuRi*T zB0#{)YI(NNSAPRdh#~6nRg@*S>fjo`+xonIqvtuJEz*tqa3ocib&d{+{1ct#XW{NE zK{MWCT+G~A%BSvC{`x^*WOk1F2SC9p|8Cd2eF;IZ;S|}u6XIgA7LE$W{c(V3HWB%p z*(6cVu@z3xID=>Q$249efF989!QB?Ei4h&ei`DxLrt&I$L7^YoIgQF8is)z$f9Cpz z?@&2_+s}7Xn~5!4#=q!wEloOer7)1CMN3UDU!+DnR+GsN%p_CzU=i&akOY?-3+dg7 zOJgsej%_4HR8lPRNjMb=RX#^Hix`)pY)3QQe*4;#J-R2sjY1%nS`^`&z$)`iqD-O_ z+)8XFoJ5|_sc%?SoDIR`+f-e%X!}c(o^v;wv>%%J8qf?CAZ!~wV0A%qbClz96c|&| zRF%poRJtgyA9tn6@;JJ{sy?EQ`|;DAD|Xj__S!8KFE>MdRg$O}7ICHc7Wx!(Z#CZtI2_tbyh8?^{NWpwk)d~N4#n3dp%jY6v z*$!-P57d}0IL^oT9wKkd@kLpIH#}`l8=^-W`t3FO7KN>fQHY=$@#7yb=iqn`nIN+L zAGVgx2uS}OEb{8585c3&0%8<3y-E&6PL;I{4W|r}N>thgV}LZd7Dn~QHSb#)dw3WX z>!Tq|v}o(qwy4s{zBrL=ql1H;sr%a>0(CE+%mb@7Gd}rWM%}>5KoHu%+mY^nBOsZl zBJsx}vX)W_zHwTl0dqt8nkuv!KNGJGC;5`D*_8bhV2CqDvP*t8T;3xY6XN1^=_`JT zN$nxy=hx#`EdHz)BKHM~fP|;)E~w)p3olrw-{^13z{Jd{&s9&jStL`9$_vi8C=IDJCfxo z@FaszoAzAtT!@P7LA$p&!UKlnQuEt+BHyzOeyT;3_@ABs59#jzexCbj9T#ZLr-$q5?d2nQc##WiQB7ac= z%A^1uQTXo3Hum?aH<^M*X{Hyn3#~yXArj@Ko+{j+aTi_*BEn+7X64l5($G@MQQkkM z#GGjWKkP|M;3;-OCI}}9w%h`p`!!8f!vh%Y4_sne&2V3wq3rR!z`nj*nH;Q^X!igv z9|)SsO;CyYk{tGUlvLQ>VHdY!_7!uR_+nmrqBanbyV@4WXW*ihKglO3#%oB%YeaU? zdzLnIATiY9&7gciC6|hzAD!K1hPu%$Y9X^|AanmMMY2IwtK4wdpzcM+wyH>^d2|h= z8ya|SSm;rELdAxfzTkW+dMZPcw@P&qJC{5XO1q>d3?C%^m_ zA6dz4k#kjGnGoJfo0mbdVUPm~XIhwGxcuN^c{`^Z2d%It&Qk6(r!dLZn`3yh^WZ_b zVuGM!UlF3P9`ODBhg&WD>`$H0lTkrxTr*r{?xWwso3^<|LOw#E#cwMm7Q{V2U5kki zk=8!x6?jmF%FYBP)^k$a570(?KsXxvGP>b>ZZSs7^`K=xVHqs|%WJah9*=}m;ZVCf zpqbDe)mo2!X_1{M*Ck9e=}s>Z&I}V*TRlcbb>s@Qj@hp?`&jt*^pZ~M)yOx0ZZ!nj zUj3gqc8b=)wbH3)^}czq%vXK27@Ijo{uM&BnyCFy6Ok(~n5Cf@(y!n9Op+?RZ1Lq( z0q{PtFi(n4yMmYw$HOyW6SQX^1%jWbOlzYLyl2EirtUEdcwcCVV#TRTW5WZ`p2j`+ zC1$fWflxkmdIM{#}{Co?VB>&H=%F6ovRzqTlPt?Op zVV6Q`^HVuxc7RFuQJPChHp?!VC$-=t#n=4D`d892zNZ z++Q9)Zff-fgv~601n(KyIl+me3x^qF=sl*_`` zMst9K%(F}50yyagcH8rQq)^sB@Bd9*!~{yWdEl58y=W5rOvGW2Yw7|i>4le1^bCzl zeH0CC6+i}21qFt}=aJJp{9<8FcM^AyWO2RJH>_N+@S1_D>uV+fhvraV}tzt|fKF(qRJ! zl62Q#50zqWQrc7o*r8}lgvgkzNa6y4F&aUYbRc@~VjPl290V&GqvI*XLmrY+cb%ep zvgw@U7{1^r_*jkE-q`cdg?6yvs~F^j>AIDV$abfu&f1fKcNz)C^~IMT71Z!TS*9&` zLNYSBFp!vWEb;e6g$OPJ;=zZ!<-dM4+vr$Ze2K8y_je`PFO6egy-f%H;h7QQ^_mT(R825A(xSV(Z|gsW&XgJF7bm$-H(r zA6`U`_ZS@SFHB42aLj}&xO;6|D>N-mNK9`+% z>!4Gxzg5zNh2|ccp7oK0Tw}5n6)g4TI}W((AL`<3e?aUTG4BY@P8`^INjYS7FJE)+ zD{sKQdy9V-^o0bXzL{zALsaF7Ind5L@RZ)7>(N=q!DtB3jHV_!X!JTFs5?I8j3J_l z@ypcd-|)UzwD{BN#7;%`bN&65(G!2`{qO2mw64FT;vv<3XRollmw}0G5C2O`=;^FK zU71gfkTdwW$Rm;L2`Op{Gm)q@s&VTLN7?eVF=#~lv^_8-*G2nKBxE-(Njr{w(D@Hi zDlNDcM=Yjs$lt6`*!Y*NasSZcr*5lyyi(odg&J2yPJk}~U?fz)GtpdqBJVweqK^P{ zzj~9J*ajl82UwFY5887-fqy)FamRA_QUOh-6`%sMg~5?Dz6{#GbIplsgi(l~kA{Wr ze7CIXdp{k>hst;fST15`#nkWBb>;sC&ntj+11=H_&t%g4O=&u57c}Akki-{e<{(v}dfzVeP zPA`P?4n$=GxYFvLtXA}$p10(Sj))+=i1&ZDuwzz*Vx~x+IK4%&_-{>42E@?T1ws#R zi#WmSLEP6r7a1x1kVaP%R3kp>Y4ht2#!w9 z9Up|~(Sud=dQ<+Gd-l)Xm4oh5(L9o<{8Fe3(x_7fHIf2@nY}ktmU(}Om_#DryE0{n zYbcfw3^?%wp?eQS7*yowq?@6~C8gSt=5b;}u;bv}bbH?5&jWvzx!)>MbXd%J*((Qo z(}W2Q7);L#f~Z5Je^%;nX3*Kn)tHA~u}QLWZ5=#nqjUeFdWvn8w_H{H{B4jDPTTOe zUzD@D6B*erT#=pkN!D72?GAr+6Yl8FBK#!6W3p3Q$H)i-&(rLG+h&JTKS1KZMlQOB zgl?eXQMqPXY-^ZqF~ad>k@l${apQKEAZra>$OPl=^Xu)DTo(Gw9gswTNh00JpBl z-(kj|a0HsCft|1|?hqDW<_3>H$?y9UO=%r$S(x>WDadB+UMZ};BLCC47qaq7O)=3& z4$rxtQds8*+slKL4QGG;S=IZTyvJkK@L>M4ga0em!+>pUK98FOJrlid!I~U;7xSWP zk|wo;SlybHnR*tt1r~&x*ny|vV#!Y=Ud@sdQ)bxZm}8%kFusbaxA8&>{X**IVN-;n zyE>{Ym)^ukM7~gF0UX)?{vun=yMREq7(+K1aOmE$h4LD~XBdzFcNveBuWtK~(2*e( zjPLV+%7sCy3vMVOb$Z!oqN2d*3S6K-kkf-{9{x|MM|WOT-`%v!al!x`ma$i|^3s4{ z<*{xVi@}dH>d#3-8qZ4U{BLokJ#JnLdZ$5O2q3hyr`CW*wUMq9=P52&(;Sa4a3lp> z`H>gG24`UotIUSmCA)9;vF>oLrcRSU)qozP&bq<`b6x zAt74{v@Z>#NHWFwqZ2kZ>1SU$%6c-3S9yc1U2zAgLhI8#is0P<+OoeL$$0al@|<$2 zJqIh86%pIJDx5o9tTqKvR93S2-%K#LF(pzOU>;hjn-vA zOM65vIv85P)~Bcf%WXw0dgaWvN&;ZA=IJEaA^@m>NCl$(J?TX0P6-;7_`BS4Umw$h zFUYK%pt6Kwh-Jg0`AflOocHJ0%F*_?*#DG2=I)6Jz*2W|eFvT>T487IazVjdTW9&~F&PaO-_;t2=O#hEJn!l2T@i(2$w z?Ou<$jK-hTab`l?;N{$|0yWeL=^A@*x%Zse1~3gnO;Z}r=}JS(kK}9HZYsI@>RFfrBho5Bixti!~qu)}(c6BfRI=`XpW-M#4 zA+#5=?(y)sW)E~haK`MDs!g%1mLn-zdx*ocz278KX2-TKFWWBS6I*HY$q%o!S%~ac z#haxk;~=PaJ^D$4L(Xl?z)E5oN<3}(3#rs~Y>4S0Q^sequ_Vr+u z{ZH%MD=ad^Rb~~4fp_SFvY$#70l}?T*#F4#HXGVFE=d@__u2}s)uKj?YZX7nOLf0e zR6Z?ijjjjPFJpLgQfiY2HH*M|*b|*eVUB_q5{N}YT<=zTW9V^LXoX^*v6z|bY?TJmexF^z-4o_%jns5N zVj1vx7m!RNtt^y>lK-Wp|B-=TcK?Iu2ptv!kWXiThL8hp=7B8v81S+pj=jq=&}Qu|GIR-H|@bHREK2THVxJmU~~~A z$OU9`62Hr-^_s}1wg0{jJ~02eeA-b;ykg$)rOzgf%KgY)G|u;sTj0^??M!&`CmDG= z7os)A!%B_4IjP{Y3rAm35OQ z;$p5xn^^ztZ-5>#gyp|+-EYB*qBJ;Pw8*bKn6p{V{tTE$GzjBEj-M9Q?Sp^vk zh93*5twgZ6z{>2<`!_$nXZe?UK2<(`2@ak8TF8)4)WbUsZJ^6O!5RHSt38r5xi6pS zg(Yus&sP_+pK!VnuW?6F+~!WxU)MW?nJ?>)v}P&cR|hAF@#c*|0#86g0AKV$cGBQ2 z^s~3!0V)F!=?EaofTS#PQ;W)n28O8>4aPYKzKAva!P94W_{% zU$tO2o{>R&R-;X8@I+0&h*z82U#cX4BdwWf`8TPhI+4W#tHAYzuh$1oi7}!||34SN ztn6p6Ze*`s8>XWlP}>NEQv^-*F&qSs zBMo}5WAg)Gh;Za+_OqO91r4&}%U-m8C*>6wyMU~`@fosG=_HX zPd)=mc)&Qj8DgY7q-#;i4agZxIzzL`D~Q}}zqP+4GbUhj?PX6nZ>eBdMi}y?=!`jr9 zXqOkUR|Nd%zt31q!^&VBV!&%GK`l<-*TdOcXWSg37whvGJRbYJNg$Vf^0kX9w5<2JH};a&)?p^RIdoS2O5}f}b!j9hzYi4H>JJB5@{~NU9J}%pmvFlY||$yGOioNu=5V0)wrQVm?b^aJ4q@~vOluH z_`5Gcd(&nToX0J%L~AY~`Dx6&S4;LC{_yvud$^$$2?Ho*V^Mxsk&qAOIipvev@xFK zTvNKm->+mWG&>LuJz2CKHwLyBy(-095KpHJT3B)11aLXbPHsJUVo--_Qk&CWF zVIOa^5(E&R2tWFSH$1;6nqw>Z__f<-#Ie=l)+i_`27eEOt@?Emb1fax#1kAk915_B zac^FIZ$RtkPVC4<_V=q^7u^tLUrep131hc==DH-x-i)_q>rAPghquRQxF^=}3u(0# zV-a_u05dO45K1C<_kOX~;`6OCn}mvh*F17+l353iz|MoklF(ByY0j??2UVi0HBJJbP?xI4RZJgq`0+=9)tfh1+*zMa03aNXZ>6U-%#=g); z1$IQA9S$d`!TODs&t?kzB2pZ-1dF-VCq=!gWG&K#T|PsGNiD?1rp#~-NGlFpl_l}7 zl!bSgFC&7V#)F(OI!pv%@^X`(KZ{BQ-}&A6*PwS9iBzSsesG_XDXaFqKGg$exePRJRq z4WNGT4xB{BnMj{cb8a;RBqO$EeO*Sj+@$I_RKFOAi>i~PReWX+wtvWXm>US%--)Z@ zsSk#0v#Ug2(q`czXH0C{U>^nO*DX53xq~u^J?F_f{$O<+qFy}S_Qf?Sq~-vq<~BQc zU>3iQ@}s_osjhX5BVOmeFv~f|FCY#{wdldb3R?|uJOXt&)WF6+Gz*-|>-4k}qr?~<-S zTeq7h|Lq2ZMR9M065C>L@71RT1mbQy;-5Sn=gDuBSMT)APwc#uI7;se=3{yJkWYgk z6)@)~v4SeCQGNAleuTwPxo@m4c$xZzt2GJuDVFjd?B8pamgpi-;Bzm*M_wm;WmqON zS$yd7Ya?4>eMJiYqazfuP}aVVt#@`@T5w$R7+ZZ&%WU*N$!!)2H1duC7A5&K2p_;E2R%Uah^wL`7)lw z5eSGr1^Ntbjjab}QAF5|_0{hOoiHaDhByDiI#Z^+o_Z@OvG|+C6$QCF8hqOHCQ`W; z9U^Vch;+t|bAduK?IS1b101TBd+hK9)&S)M67L_HB?DpN5ctQM?~eT7#p0%7lik|U z_Y>Oc7~?-ubc=%R2c}&>rrXO9WLMD+1$?aX>x`mrvdl1R;LpU?;im)lVVvEz+4r$u zdSVt}+s}fASuFG=dA% zRvU`r9^&c)UkeL%3#KV_0laA;w`FnGGo}n1Q|+Che0zGhiLNeU1U&~>MRJvFC7W)A zL>Pe+N|5Q2ih zf2vmScP3*{xj3MD*(Mq}HeBZF(=3>F<)|F7rQ}W9SX@b`yMBzBgPl+%IZ&=nH7AaZ z_Bwsx-{XB6=P@4pXzce7L+g

6xRa1*=Uctfa7xCvG&Cf6Mh0Hl5QwIJC6jv>9vE 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 Y-$mh#Bf3y370&?=dMr3_CZedRLp+ zy?wPLen)X(|MT|In^U-Pzc!OOBblDaaIf;#*H`1ui*SW99!QYYPy zJe=3BVZBCTNHa=~CxFehm_Tt17?P}t!y%h35#DwZDF1g~ZE44QpQmH|`|LfJYtNxT z^F|8M2b2HAq3IcS)^Yn6&Ph`PrT*jp=6K+}UoK+^_{1oFTFR%SU)sRj1x9bC3sZ3? zT2*-+_H!kOKQ4Vf!~A%jM9Ug&V0kPlKC^~WJFCpI>JlAVNy`d!QfXVrefwA5oS(d zH?GNs7+Z!+^3E0-?=_`!{Rc;{n|09TNe{VTxc3p~aXoFcq4oMx26rtN*Cr`V!*|u{ zhz=I_!+UPUJ86Iw1tmwn4_d6*ib^PxeuJ%;D2bEPLQYpwC+G_C z5a~nG=-fZtCB8vViZv(RLdb*d%;!r(%w zyu+RyZ8r88-XFA74BwPvhrJv|J%`o!vw14bFR=a(;A%Upr0Q)*{W;$CegT+w26fzn z2i?{lZ)VZ(m(MfW(jivK64}(ws>)sG8Zj`h5g52Zq>_p1whQ>^h1|D#Lw%J4Q8{>Y|DN+RlxB#gO36DB(PPGrX(1! z!;>tQeyk1T&H+stg{##%=$}K$)ho;qoQwa>MBLnC2{Jf=T&)Fn<{stjxGg`wX}}TW4~ZA`OQMHn*#oC zM9$C;Hse&&Uv~AE8QUr1(26_~QL1;EZeD%5<>U*&O_I_k_YU|2Bh;wlF#Z(#twsnn z#~UYyGITU1Th|~wFH^3zudxH-5yH0>Eo5XZO-u~igxjmyT8l(fwo?2q@{df%F?QoFW z!D$Ni5nrCU69D5VowKa_%SAT%H8pjml@a{_Ofo*MWbJ|Csrf#ERmV`cAjoP-H%_X; zW1THu)$<^f+AUvr>HJ;_Zp^fbK%6ux68b0rHa~^kklL2{)lMykgsI3TT9@wxpb|$sNJ*7!31{Ur`1N?_$dxb&!?_p+aJW z9m0W@nkp=5Doi9!Dy$omV1$$jejEi|!8xY2ydR;?)|A_7_zy*IYzEA&v=qxI@*n}_ z7S{RXW*hSSU#07$1eKuJQbGY38RLe)>qZ26a-RVS^?R1bG;RzbnjxYnrF)Jq+UZ;t z+=D?=(9~9@;xw{MU=%DpTa3u3$+@g@DTi{A!e8NSB`31?q9HHII^nOLYElcvMT1EQ zrP=ogRORJa?duqMT`U^IDLIXo)ai>H=U%_|GNJJPrqGt>wwAa`o+V)F-=>Km-hJLD z<2cT}*--A-Quu2g0{F)5DVo-_9O09gWN{vyHEoVFY$YT68bv9GEsg-9h?-)iD)T-Z zMrF?`I@CyDDt~9d0^{jG8@pM{N@4z-E<|c(n$h5Tn#~1?7A4b`>Qc=&9b!u`_Aht} z(LHM&m4-nvqgmJS>zRIr?B)^s2sPl`PucVa?42I52|wLcxGJQ7d24R?LZIS9Pt-N- zwd&(<&fP`cn4GV*Z-4*u4h>klrYfqvr>wXDQPh9BA#NBoM3i zHjxic|Dj2V6@kKzcaDHX*)1AbF5tghErEZVVL4CzI^n+z!+%4d@b{wH8<|8+i$L(| z|6YL(uOxzFP;~`8VZb5_-#gO%ss|MxrO{y&++amDBXEzuWg literal 0 HcmV?d00001 diff --git "a/zh-cn/device-dev/bundles/figures/\347\241\254\344\273\266\347\216\257\345\242\203\350\277\236\346\216\245\345\205\263\347\263\273.png" "b/zh-cn/device-dev/bundles/figure/\347\241\254\344\273\266\347\216\257\345\242\203\350\277\236\346\216\245\345\205\263\347\263\273.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/bundles/figures/\347\241\254\344\273\266\347\216\257\345\242\203\350\277\236\346\216\245\345\205\263\347\263\273.png" rename to "zh-cn/device-dev/bundles/figure/\347\241\254\344\273\266\347\216\257\345\242\203\350\277\236\346\216\245\345\205\263\347\263\273.png" diff --git "a/zh-cn/device-dev/bundles/figures/\347\273\204\344\273\2660924.png" "b/zh-cn/device-dev/bundles/figure/\347\273\204\344\273\2660924.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/bundles/figures/\347\273\204\344\273\2660924.png" rename to "zh-cn/device-dev/bundles/figure/\347\273\204\344\273\2660924.png" diff --git "a/zh-cn/device-dev/bundles/figures/\347\273\204\344\273\266\345\214\205\344\276\235\350\265\226\345\205\263\347\263\273\345\233\276.png" "b/zh-cn/device-dev/bundles/figures/\347\273\204\344\273\266\345\214\205\344\276\235\350\265\226\345\205\263\347\263\273\345\233\276.png" deleted file mode 100755 index 1b936a2cbc95d3f9d7ddab0187305c3d0c486b0a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 359473 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 z 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

  • !iS|UkW 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ⅇMIH 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
    pYa54~EAUi>+ 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 - -- [硬件要求](#section98535485518) -- [安装Node.js和hpm命令行工具](#section106591616205311) -- [更改hpm的配置(可选)](#section71821165412) -- [下载OpenHarmony代码](#section102338221707) -- [安装开发依赖的组件](#section19233183315020) - -## 硬件要求 - -- 准备设备开发的开发板(如Hi3861、Hi3516DV300、Hi3518EV300) -- 主机电脑(Windows工作台) -- Linux服务器 - -**图 1** 硬件环境连接关系 -![](figures/硬件环境连接关系.png "硬件环境连接关系") - -## 安装Node.js和hpm命令行工具 - -1. 安装Node.js。 - - 从官网下载并在本地安装Node.js. - - 推荐安装 [Node.js](https://nodejs.org/) 12.x \(包含 npm 6.14.4\)或更高版本 \(推荐 12.13.0+\)。 - -2. 通过Node.js自带的npm安装hpm-cli命令行工具。执行以下命令: - - ``` - npm install -g @ohos/hpm-cli - ``` - -3. 安装完成后执行如下命令,显示hpm版本,即安装成功。 - - ``` - hpm -V 或 hpm --version - ``` - -4. (可选)如果需要升级hpm版本,请执行如下命令: - - ``` - npm update -g @ohos/hpm-cli - ``` - - -## 更改hpm的配置(可选) - -安装完hpm-cli命令行工具后,执行以下命令可以查看hpm配置: - -``` -hpm config -``` - -上述命令执行后将会显示hpm的默认配置,您可以根据自己的喜好对默认配置进行修改,以下是hpm的常用配置: - -``` -registry = https://hpm.harmonyos.com/hpm/registry/api # hpm注册中心地址,下载组件必须 -login = https://hpm.harmonyos.com/hpm/auth/pk # hpm处理登录地址,发布组件必须 -loginUser = {your-account} # 配置hpm登录账号,发布组件必须 -shellPath = C:\WINDOWS\System32\cmd.exe # hpm命令执行使用的shell -globalRepo = C:\Users\yourname\.global # 配置全局安装的组件存放路径 -http_proxy = http://your-proxy-server:port # 配置HTTP代理 -https_proxy = http://your-proxy-server:port # 配置HTTPS代理 -``` - -hpm-cli的命令介绍可以参考:[hpm操作命令](组件管理.md) - -## 下载OpenHarmony代码 - -参考[《源码获取》](../get-code/源码获取.md) - -## 安装开发依赖的组件 - -hpm包管理器将常用开发开发工具(如烧录,编译,压缩等)也发布成了组件。可以通过如下命令方式进行安装,执行完该命令后,系统会自动将开发依赖的工具下载安装,且这些组件只需全局安装一次。 - -``` -hpm i -g @ohos/llvm -hpm i -g @ohos/ninja -hpm i -g @ohos/gn -hpm i -g @ohos/hc_gen -hpm i -g @ohos/sysroot -``` - -这是一组开发工具的组件包(如包含gn,ninja等工具),有了这些开发态的组件,就可以进行常规的源码组件的开发了。 - diff --git "a/zh-cn/device-dev/bundles/\345\217\221\350\241\214\347\211\210.md" "b/zh-cn/device-dev/bundles/\345\217\221\350\241\214\347\211\210.md" deleted file mode 100755 index 00640e5599..0000000000 --- "a/zh-cn/device-dev/bundles/\345\217\221\350\241\214\347\211\210.md" +++ /dev/null @@ -1,56 +0,0 @@ -# 发行版 - -发行版通常是将一系列组件组合起来,成为编译可以运行的OpenHarmony解决方案镜像,里面包含了多个依赖的组件,以及脚本,用于描述如何完整编译、链接这些组件。 - -发行版本身通常不需要包含功能实现代码,仅包含bundle.json描述(设置publishAs为distribution)和一些编译脚本组成。 - -因为发行版编译的过程需要系统提供环境变量,所以发行版使用scripts脚本中内置的dist命令: - -``` -{ - "publishAs":"distribution", - "scripts": { - "dist": "script compile command" - } -} -``` - -编译执行使用如下命令: - -``` -hpm dist -``` - -重新定义一个发行版所具有的功能是一个复杂的过程,所以系统允许对发行版进行继承,从而在现有功能的基础上进行定制。继承发行版需要在bundle.json中定义base字段。 - -``` -{ - "base": { - "name": "dist_wifi_iot", - "version": "1.0.0" - } -} -``` - -上述定义表明当前组件继承自发行版组件dist-wifi-iot 1.0.0。 - -发行版由很多的依赖组件组成,通过bundle.json中的dependencies段来描述,有些依赖是必须的,有些依赖则是根据可以需求增加或删除的。bundle.json中名称前带有?的依赖表示可选依赖,继承它的发行版,可以移除掉该可选组件,再增加别的组件进行替换。 - -``` -{ - "dependencies": { - "?my_bundle": "1.0.0" - } -} -``` - -上述声明表示my\_bundle依赖可以被移除。如果想要移除my\_bundle,在上层依赖方需要使用excludes关键字来进行定义 - -``` -{ - "excludes": [ "my_bundle" ] -} -``` - -依赖被移除后,就不会参入组件的构建过程。只有标记为可选的依赖才能够被移除,强行移除未被标记的依赖会出现错误提示。 - diff --git "a/zh-cn/device-dev/bundles/\346\223\215\344\275\234\345\256\236\344\276\213.md" "b/zh-cn/device-dev/bundles/\346\223\215\344\275\234\345\256\236\344\276\213.md" deleted file mode 100755 index d49c4267cc..0000000000 --- "a/zh-cn/device-dev/bundles/\346\223\215\344\275\234\345\256\236\344\276\213.md" +++ /dev/null @@ -1,54 +0,0 @@ -# 操作实例 - -环境准备好后,接下来本文以Hi3861平台为例,演示如何利用HPM进行组件的安装、编译和打包。 - -1. 执行以下命令,初始化安装目录(目录名可自行设置): - - ``` - mkdir test3861 - cd test3861 - hpm init -t dist - ``` - - 初始化成功则显示: - - ``` - Initialization finished. - ``` - -2. 安装wifi\_iot发行版。 - - ``` - hpm install @ohos/wifi_iot - ``` - - 安装成功则显示: - - ``` - Installed. - ``` - - >![](public_sys-resources/icon-note.gif) **说明:** - >Hi3516平台采用下述命令: - >``` - >hpm install @ohos/ip_camera_hi3516dv300 - >``` - >Hi3518平台采用下述命令: - >``` - >hpm install @ohos/ip_camera_hi3518ev300 - >``` - -3. 编译打包 - - ``` - hpm dist - ``` - - 编译成功会显示: - - ``` - {{name}}: distribution building completed. - ``` - -4. 上述所有命令执行成功后,在 ./out 目录下会生成编译结果,开发者可以将编译结果烧录到对应的开发板上进行测试。 - diff --git "a/zh-cn/device-dev/bundles/\346\246\202\350\277\260-0.md" "b/zh-cn/device-dev/bundles/\346\246\202\350\277\260-0.md" deleted file mode 100755 index 758ec2fb9f..0000000000 --- "a/zh-cn/device-dev/bundles/\346\246\202\350\277\260-0.md" +++ /dev/null @@ -1,54 +0,0 @@ -# 概述 - -本章节将简要介绍如何开发OpenHarmony组件和发行版,并通过命令行工具方式完成组件创建、开发、编译、烧录、调试等开发过程。 - -- 一个组件(bundle)通常和一个代码仓库对应,在代码的基础上增加bundle.json、README文件、LICENSE描述文件。 -- 一个发行版(distribution)是由多个组件构成的。发行版中集合了一个完整系统的各种组件(如驱动、内核、框架、应用),可以用于设备的烧录。 - -**表 1** 组件和发行版的差异对比 - - - - - - - - - - - - - - - - - - - - - - - - -

    异同点

    -

    组件

    -

    发行版

    -

    应用场景

    -

    面向功能特性开发

    -

    面向系统开发

    -

    内容

    -

    功能或特性的实现代码或二进制库

    -

    依赖的组件清单及编译构建脚本

    -

    完整程度

    -

    操作系统的一部分

    -

    一个完整操作系统版本

    -

    编译后结果

    -

    组件包

    -

    系统镜像

    -
    - -**图 1** 组件和发行版的构成 - - -![](figures/组件0924.png) - diff --git "a/zh-cn/device-dev/bundles/\346\246\202\350\277\260.md" "b/zh-cn/device-dev/bundles/\346\246\202\350\277\260.md" deleted file mode 100755 index 2eea128f92..0000000000 --- "a/zh-cn/device-dev/bundles/\346\246\202\350\277\260.md" +++ /dev/null @@ -1,38 +0,0 @@ -# 概述 - -- [定义](#section177563344911) -- [组件划分原则](#section2487162541016) -- [组件依赖](#section185955409107) - -本文档将介绍组件的基本概念以及如何按照规范定义组件。 - -## 定义 - -OpenHarmony软件以组件\(bundle\)作为基本单元,从系统角度看,凡是运行在OpenHarmony上的软件都可以定义为组件;一般来讲,根据组件的应用范围,可以分为: - -- 板级组件:如board、arch、mcu这些与设备硬件相关的组件。 -- 系统组件:一组独立功能的集合,如内核、文件系统、框架等。 -- 应用组件:直接面向用户提供服务的应用\(如wifi\_iot,ip\_camera\)。 - -从形式上看,组件是为复用而生,一切可以复用的模块都可以定义为组件,可以分为: - -- 源代码 -- 二进制 -- 代码片段 -- 发行版 - -## 组件划分原则 - -原则上应尽可能划分为细颗粒度的组件,以满足最大限度的复用。主要考虑以下几点: - -- 独立性:组件的功能应该相对独立,支持独立编译,可以单独对外提供接口和服务; -- 耦合性:如果组件必须依赖其他的组件,才能对外提供服务,应考虑和被依赖的组件合并为一个组件。 -- 相关性:如果一组组件共同完成一项功能,且没有被其他组件依赖,未来也没有被依赖的可能,则可以考虑合并为一个组件。 - -## 组件依赖 - -组件的依赖关系分为两种:必选依赖和可选依赖。 - -- 必选依赖:是指组件A在完成某个功能时,必须引入组件B,调用B的接口或服务配合才能完成。称B为A的必选依赖。 -- 可选依赖:是在组件A在完成某个功能时,可以引入组件C,也可以引入组件D。C和D可以相互替换,称C和D为A的可选依赖。 - diff --git "a/zh-cn/device-dev/bundles/\347\216\257\345\242\203\345\207\206\345\244\207.md" "b/zh-cn/device-dev/bundles/\347\216\257\345\242\203\345\207\206\345\244\207.md" deleted file mode 100755 index d4d5662f29..0000000000 --- "a/zh-cn/device-dev/bundles/\347\216\257\345\242\203\345\207\206\345\244\207.md" +++ /dev/null @@ -1,139 +0,0 @@ -# 环境准备 - -- [linux服务器](#section20979554791) -- [安装Node.js](#section9954105413153) -- [安装HPM](#section15937194904819) -- [安装python环境](#section1621819180417) -- [安装文件打包工具](#section77617165913) -- [安装SCons](#section20558439191516) - -## linux服务器 - -准备一台装有Ubuntu 16.04 及以上 64 位系统的linux服务器(hpm是支持windows的,但是目前OpenHarmony开源的Hi3861、Hi3516、Hi3518三个解决方案都只支持Ubuntu)。 - -将linux shell改为bash: - -``` -ls -l $(which sh) -# 如果指向的不是bash,则按以下方式修改: -# 方法一:执行以下命令,然后选择no -dpkg-reconfigure dash -# 方法二:先删除sh,再重新创建软连接 -rm -f /bin/sh -ln -s bash /bin/sh -``` - -## 安装Node.js - ->![](public_sys-resources/icon-note.gif) **说明:** ->如果配置的源的nodejs版本太低,可以执行以下语句后再执行apt-get install: ->``` ->curl -L https://deb.nodesource.com/setup_12.x | bash ->``` - -推荐安装 Node.js 12.x (包含 npm 6.14.4)或更高版本(推荐 12.13.0+): - -``` -sudo apt-get install nodejs -sudo apt-get install npm -``` - -查看版本: - -``` -node --version # 查看nodejs版本 -npm --version # 查看npm版本 -``` - -## 安装HPM - -通过 Node.js 自带的 npm(使用默认的源 https://registry.npmjs.org/ )安装 hpm-cli 命令行工具: - -``` -npm install -g @ohos/hpm-cli -``` - -安装完hpm-cli命令行工具后,执行以下命令可以查看hpm配置: - -``` -hpm config -``` - -上述命令执行后将会显示hpm的默认配置,您可以根据自己的喜好对默认配置进行修改,以下是hpm的常用配置: - -``` -registry = https://hpm.harmonyos.com # hpm注册中心地址,下载组件必须 -strictSsl = true # 通过https连接时,是否需要校验证书 -http_proxy = http://your-proxy-server:port # 配置HTTP代理 -https_proxy = http://your-proxy-server:port # 配置HTTPS代理 -``` - -hpm-cli的命令介绍可以参考:[hpm操作命令](组件管理.md) - -## 安装python环境 - -需使用python3.7以上版本,采用以下命令进行安装: - -``` -sudo apt-get install python3.8 -sudo apt-get install python3-pip -sudo pip3 install setuptools -sudo pip3 install kconfiglib # 建议安装kconfiglib 13.2.0+版本 -``` - ->![](public_sys-resources/icon-note.gif) **说明:** ->上述方式适用Hi3518和Hi3516两种平台,针对Hi3861平台采用以下方式安装python环境: ->``` ->sudo apt-get install python3.8 ->sudo apt-get install python3-pip ->sudo pip3 install setuptools ->sudo pip3 install kconfiglib # 建议安装kconfiglib 13.2.0+版本 ->sudo pip3 install pycryptodome ->sudo pip3 install six --upgrade --ignore-installed six ->sudo pip3 install ecdsa ->``` - -如果当前系统中既存在python2又存在python3,参考以下方法将默认python修改为python3: - -``` -ll `which python` -rm /usr/bin/python -ln -s python3.8 /usr/bin/python -``` - -## 安装文件打包工具 - -采用以下命令进行安装: - -``` -which mkfs.vfat # 如果没找到,执行以下命令安装 -sudo apt-get install dosfstools -which mcopy # 如果没找到,执行以下命令安装 -sudo apt-get install mtools -``` - ->![](public_sys-resources/icon-note.gif) **说明:** ->Hi3518和Hi3516两种平台需要安装打包工具,Hi3861平台不需要。 - -## 安装SCons - -1. 打开Linux编译服务器终端。 -2. 运行如下命令,安装SCons安装包。 - - ``` - python3 -m pip install scons - ``` - -3. 运行如下命令,查看是否安装成功。如果安装成功,查询结果下图所示。 - - ``` - scons -v - ``` - - **图 1** SCons安装成功界面,版本要求3.0.4以上 - ![](figures/SCons安装成功界面-版本要求3-0-4以上.png "SCons安装成功界面-版本要求3-0-4以上") - - ->![](public_sys-resources/icon-note.gif) **说明:** ->Hi3861平台需要安装SCons,Hi3518和Hi3516两种平台不需要。 - diff --git "a/zh-cn/device-dev/bundles/\347\216\257\345\242\203\345\217\230\351\207\217\350\257\264\346\230\216.md" "b/zh-cn/device-dev/bundles/\347\216\257\345\242\203\345\217\230\351\207\217\350\257\264\346\230\216.md" deleted file mode 100755 index 1ebf8fb99e..0000000000 --- "a/zh-cn/device-dev/bundles/\347\216\257\345\242\203\345\217\230\351\207\217\350\257\264\346\230\216.md" +++ /dev/null @@ -1,53 +0,0 @@ -# 环境变量说明 - -组件在编译的过程中需要依赖系统提供的环境变量来自定义输出,链接所需二进制文件等等。这里提出的环境变量均指根据需求把所需变量注入脚本执行的上下文中。所以在脚本中可以直接获取到变量的值。下面介绍当前系统存在的几种环境变量。全局变量 - -全局变量由bundle.json中的envs属性来定义。整个组件中的依赖都可以获取到全局变量定义的值。 - -``` -{ - "envs": { - "compileEnv": "arm" - } -} -``` - -不同组件在引入依赖的过程中可以传入不同的参数,从而使依赖的编译可以满足当前组件的需求。依赖中定义的参数可以在对应依赖脚本执行的上下文中获取到。 - -``` -{ - "dependencies": { - "my-bundle": { - "version": "1.0.0", - "mode": "debug" - } - } -} -``` - -组件在链接二进制文件的时候,需要知道二进制文件在依赖中的路径,所以依赖的路径会作为环境变量传入编译组件中。 - -传入的环境变量的格式为DEP\_BundleName,BundleName为依赖的名称,例如 DEP\_first\_bundle。 - -依赖中可以定义标签,对引入的依赖进行分组。在脚本中可以根据标签,获得这一组依赖的路径。定义的标签以\#开头,具体定义的方式为: - -``` -{ - "dependencies": { - "#tool": { - "first-bundle": "1.0.0", - "second-bundle": "1.0.0" - }, - "#drivers": { - "xx-bundle": "1.0.0", - "yy-bundle": "1.0.0" - } - } -} -``` - -系统中存在两个固定环境变量: - -- DEP\_OHOS\_BUNDLES:表示ohos\_bundles文件夹所在的路径。 -- DEP\_BUNDLE\_BASE:表示最外层组件的路径。 - diff --git "a/zh-cn/device-dev/bundles/\347\273\204\344\273\266\345\274\200\345\217\221.md" "b/zh-cn/device-dev/bundles/\347\273\204\344\273\266\345\274\200\345\217\221.md" deleted file mode 100755 index 292c88d6d2..0000000000 --- "a/zh-cn/device-dev/bundles/\347\273\204\344\273\266\345\274\200\345\217\221.md" +++ /dev/null @@ -1,241 +0,0 @@ -# 组件开发 - -- [创建OpenHarmony组件](#section1976410130540) -- [新建组件](#section717481119145) -- [改造组件](#section102861955201410) -- [从模板创建组件](#section15882846181510) -- [编译组件](#section136732148541) -- [定义编译脚本](#section10274147111610) -- [执行编译](#section879301916172) -- [定义发行版](#section413216495619) -- [定义脚本](#section11503171219190) -- [发行](#section4694125521912) -- [烧录](#section1746331545413) -- [运行调试](#section6742131615549) - -## 创建OpenHarmony组件 - -创建OpenHarmony组件有如下几种方式: - -- 从头开发一个全新的组件。 -- 将一个现有的非组件的代码改造成组件。 - -- hpm提供了一些组件模板方便快速创建组件。 - -## 新建组件 - -通常情况下,[HPM网站](https://hpm.harmonyOS.com)上能找到您开发常用的组件,如果现有的组件不能完全满足开发,这时可以自己动手开发一个组件。 - -如果您愿意,可以将组件发布到HPM的仓库中供其他用户使用。假设要在D:/source目录下新建一个全新的组件my-bundle: - -可以使用hpm init 创建该组件的脚手架代码,例如,进入D:/source目录,执行如下命令: - -``` -hpm init -t default -d demo my-bundle -``` - -会在 source 目录下生成如下文件: - -``` -mybundle -├── bundle.json # 组件元数据描述文件 -├── example # 测试组件功能的示例 -│ └── main.c -├── include # 组件的内部头文件 -│ └── mybundle.h -├── README.md # 组件的简要说明 -└── src # 组件的源代码 - └─ mybundle.c -``` - -接下来根据您的业务需要,实现组件内部的功能代码,完成代码开发后,通过git将代码(包括bundle.json文件)提交到组件代码托管仓库中(如gitee)。 - -## 改造组件 - -如果您已经有了代码,只是还不满足OpenHarmony的组件结构,需要改造成为hpm的组件包,只需要在当前要改造的代码目录下(例如mybundle2),执行如下命令,会提示您输入组件名称和版本。 - -``` -hpm init -``` - -1. 输入名称后回车(如mybundle2)。 -2. 输入版本后(如1.0.0)回车,在当前组件目录下会生成一个bundle.json文件。 -3. 打开bundle.json文件再添加其他的描述,这时候他已经是一个具备可发布的组件了。 - - ``` - $ hpm init - Your bundle will be created in dirname E:\demo\mybundle2 - ? bundle name mybundel2 - ? version 1.0.0 - Init finished! - ``` - - -1. 打开bundle.json文件修改其他信息(如作者,代码仓库,代码目录,命令脚本,依赖组件等),如下: - - ``` - { - "name": "mybundle2", - "version": "1.0.0", - "publishAs": "source", - "dirs":{ - ".":[ - "README.md" - ], - "src":[ - "test.c" - ], - "header":[ - "header/test.h" - ], - "src/common":[ - "src/common/foobar.txt" - ] - }, - "scripts": { - "build": "make -${args}" - }, - "dependencies": { - "@ohos/cjson": "^1.0.0", - "@ohos/": "^1.2.0" - } - } - ``` - - -## 从模板创建组件 - -hpm 除了提供了默认模板 default和simple两个简单的模板之外,其他模板均存储在服务器端。 - -可以使用命令hpm search -t template 从服务器端搜索模板。 - -![](figures/zh-cn_image_0000001051452177.png) - -根据description简要中的描述,找到适合的模板,基于模板可以快速创建一个组件的脚手架,执行如下初始化命令(指定-t -d 参数)。 - -``` -hpm init -t {templatename} -d dir name -``` - -- \{templatename\} :指的是模板名称。 -- -d 后面的参数dir:是要创建的组件所存放的路径。 -- name:为要创建的组件名称。 - -## 编译组件 - -完成代码开发后,需要对组件进行编译。hpm提供了命令集成的能力,您可以选择任意的适合项目的编译工具(如make,gcc,gn等等)。只需在当前项目的bundle.json文件中定义scripts脚本中的build命令,就可以通过执行hpm build执行编译。 - -## 定义编译脚本 - -以编译一个app目录下helloworld可执行文件为例: - -``` -app -├── BUILD.gn -├── include -│ └── helloworld.h -└── src - └── helloworld.c -``` - -在helloworld.c同级目录下新建一个BUILD.gn - -``` -touch BUILD.gn -vim BUILD.gn -``` - -以下是BUILD.gn的样例,仅供参考 - -``` -executable("hello_world") { - sources = [ - "src/helloworld.c" - ] - - include_dirs = [ - "include" - ] -} -``` - ->![](public_sys-resources/icon-note.gif) **说明:** ->- “executable”是gn内置模板,可以用“gn help executable ”查看使用方法。 ->- “sources ”是源码路径,“include\_dirs ”是头文件路径。 - -## 执行编译 - -在当前文件夹下,执行编译命令: - -``` -hpm build -``` - -在完成一系列的编译动作后,显示build succeed。检查编译的输出结果: - -![](figures/zh-cn_image_0000001051770876.png) - -## 定义发行版 - -发行版是将一组组件组合起来的,编译生成可以运行的OpenHarmony解决方案,里面包含了较多依赖的组件,以及以脚本形式描述如何完整编译、链接这些组件。 - -## 定义脚本 - -bundle.json中定义 - -``` -{ -"name": "my_dist", -"version": "1.0.0", -"publishAs": "distribution", -"scripts": { -"dist": "make -${args}" - }, -"base": { -"name": "dist-bundle", -"version": "1.0.0" - }, -"envs": { -"args": "x86" - }, -"dependencies": { -} -} -``` - -## 发行 - -在当前发行版根目录下,执行如下命令。 - -``` -hpm dist -``` - -hpm-cli工具会自动执行编译,打包操作,将根据scripts定义的dist脚本生成镜像文件,如: - -``` -out -|-xxdist.img -|-xx.file -``` - -## 烧录 - -发行版的编译结果可以烧录到设备中运行,例如使用hiburn工具进行烧录。在发行版的bundle.json文件配置烧录参数。 - -``` -"scripts": { -"flash": "{$DEP_HIBURN}/hiburn" -}, -``` - -配置烧录相关的参数(参考烧录工具的说明进行配置)。 - -``` -hpm run flash -``` - -## 运行调试 - -将发行版的镜像烧录到设备中后,就可以启动运行调试了,由于运行调试和具体的开发板和IDE调试工具相关,此处不再详细描述。 - diff --git "a/zh-cn/device-dev/bundles/\347\273\204\344\273\266\345\274\200\345\217\221\346\214\207\345\215\227.md" "b/zh-cn/device-dev/bundles/\347\273\204\344\273\266\345\274\200\345\217\221\346\214\207\345\215\227.md" deleted file mode 100755 index cb1868b0b4..0000000000 --- "a/zh-cn/device-dev/bundles/\347\273\204\344\273\266\345\274\200\345\217\221\346\214\207\345\215\227.md" +++ /dev/null @@ -1,9 +0,0 @@ -# 组件开发指南 - -- **[概述](概述-0.md)** - -- **[准备工作](准备工作.md)** - -- **[组件开发](组件开发.md)** - - diff --git "a/zh-cn/device-dev/bundles/\347\273\204\344\273\266\345\274\200\345\217\221\347\244\272\344\276\213.md" "b/zh-cn/device-dev/bundles/\347\273\204\344\273\266\345\274\200\345\217\221\347\244\272\344\276\213.md" deleted file mode 100755 index d3e1375211..0000000000 --- "a/zh-cn/device-dev/bundles/\347\273\204\344\273\266\345\274\200\345\217\221\347\244\272\344\276\213.md" +++ /dev/null @@ -1,9 +0,0 @@ -# 组件开发示例 - -- **[HPM介绍](HPM介绍.md)** - -- **[环境准备](环境准备.md)** - -- **[操作实例](操作实例.md)** - - diff --git "a/zh-cn/device-dev/bundles/\347\273\204\344\273\266\345\274\200\345\217\221\350\247\204\350\214\203.md" "b/zh-cn/device-dev/bundles/\347\273\204\344\273\266\345\274\200\345\217\221\350\247\204\350\214\203.md" deleted file mode 100755 index 4205b8d538..0000000000 --- "a/zh-cn/device-dev/bundles/\347\273\204\344\273\266\345\274\200\345\217\221\350\247\204\350\214\203.md" +++ /dev/null @@ -1,15 +0,0 @@ -# 组件开发规范 - -- **[概述](概述.md)** - -- **[组件构成](组件构成.md)** - -- **[组件管理](组件管理.md)** - -- **[组件版本](组件版本.md)** - -- **[发行版](发行版.md)** - -- **[环境变量说明](环境变量说明.md)** - - diff --git "a/zh-cn/device-dev/bundles/\347\273\204\344\273\266\346\236\204\346\210\220.md" "b/zh-cn/device-dev/bundles/\347\273\204\344\273\266\346\236\204\346\210\220.md" deleted file mode 100755 index 98e4e2dd60..0000000000 --- "a/zh-cn/device-dev/bundles/\347\273\204\344\273\266\346\236\204\346\210\220.md" +++ /dev/null @@ -1,99 +0,0 @@ -# 组件构成 - -- [代码文件](#section101483489110) -- [说明文件](#section10519101221211) -- [元数据描述文件](#section45511827111211) - -一个组件包一般包含如下内容: - -- 组件包的代码或库(src目录下的代码文件) -- ohos\_bundles文件夹(存放依赖的组件,安装组件时自动生成,无需提交到代码库) -- 组件包的说明文件\(README.md\) -- 组件包元数据声明文件\(bundle.json\) -- 开源许可文件\(LICENSE\) - - ``` - my-bundle - |_ohos_bundles - |_src - |_bundle.json - |_README.md - |_LICENSE - ``` - - -## 代码文件 - -组件的代码文件和普通的代码目录没有差异。但要注意的是,组件中对外暴露的接口(头文件),会被其他组件所引用,需要单独在bundle.json的dirs中声明。 - -## 说明文件 - -README.md,为markdown格式的描述关于组件自述说明文件。([语法参考](https://www.markdownguide.org/getting-started/)\) - -为了帮助他人在hpm上找到该组件,并更方便的使用它,在组件的根目录中包含一个README文件。 - -README文件可能包括如何安装,配置和使用组件包中的实例代码说明,以及可能会对用户有所帮助的任何其他信息。 - -每个组件的自述文件将显示在hpm系统的组件详情页面的描述中。 - -## 元数据描述文件 - -bundle.json文件是对当前组件的元数据描述,每个组件中必须包含一个bundle.json文件。 - -``` -{ - "name": "@myorg/demo-bundle", - "version": "1.0.0", - "license": "MIT", - "description": "bundle description", - "keywords": ["hos"], - "tags": ["applications", "drivers"], - "author": {"name":"","email":"","url":""}, - "contributors":[{"name":"","email":"","url":""},{"name":"","email":"","url":""}], - "homepage": "http://www.foo.bar.com", - "repository": "https://git@gitee.com:foo/bar.git", - "publishAs": "source", - "dirs": { - "src": ["src/**/*.c"], - "headers": ["headers/**/*.h"], - "bin": ["bin/**/*.o"] - }, - "scripts": { - "build": "make" - }, - "envs": {}, - "ohos": { - "os": "2.0.0", - "board": "hi3516", - "kernel": "liteos-a" - }, - "rom": "10240", - "ram": "1024", - "dependencies": { - "@myorg/net":"1.0.0" - } -} -``` - -bundle.json文件具有如下功能: - -- name:定义组件的名称,放到组织下, 以@开头,/分割,如:@myorg/mybundle - -- version:定义组件版本号,如1.0.0,需满足semver的标准。 - -- description:一句话对组件进行简要的描述。 -- dependencies:定义组件的依赖组件。 - -- envs: 定义组件编译时所需要的参数,包括全局参数以及依赖所需的参数。 - -- scripts:定义在当前组件下能够执行的命令(如编译,构建,测试,烧录等)。 - -- publishAs:定义组件的发布类型(source:源码,binary:二进制,distribution:发行版,code-segment:代码片段)。 - -- dirs:定义发布时打包的目录结构(如头文件)。 - -- ram&rom:统计相关信息:预计占用ROM和RAM信息。 -- ohos:描述OpenHarmony系统版本、开发板及内核的匹配关系(多个请用英文逗号的“,”分割)。 -- 定义其他扩展信息:作者,主页,代码仓库,许可协议,标签,关键字。 -- 对于发行版类型,还有个base,可以定义继承自的发行版。 - diff --git "a/zh-cn/device-dev/bundles/\347\273\204\344\273\266\347\211\210\346\234\254.md" "b/zh-cn/device-dev/bundles/\347\273\204\344\273\266\347\211\210\346\234\254.md" deleted file mode 100755 index 55647fdcb7..0000000000 --- "a/zh-cn/device-dev/bundles/\347\273\204\344\273\266\347\211\210\346\234\254.md" +++ /dev/null @@ -1,23 +0,0 @@ -# 组件版本 - -- [版本号命名规范](#section16893854141310) -- [版本发布](#section43401320171420) - -## 版本号命名规范 - -名称需要为全小写字母,中间可以使用中划线或者下划线分隔。比如 "bundle", "my\_bundle"。 - -版本号的格式为 "主版本号.次版本号.修订号" 或 "主版本号.次版本号.修订号-先行版本号",比如 "1.0.0", "1.0.0-beta",详细规格可以参考 [https://semver.org](https://semver.org/)。 - -## 版本发布 - -为了使组件能被其他开发者使用,组件需要上传到远端仓库。组件上传使用如下命令: - -``` -hpm publish -``` - -命令执行以后,系统会对的整个依赖关系进行检查,下载缺失依赖组件。依赖检查完成后,如果发布类型为binary,系统会对整个组件进行编译,生成二进制文件,然后打包上传。如果使其他上传类型,则直接根据定义的打包规则进行打包,然后上传。 - -注意:发布组件需要用户账号登录,需要先拥有hpm的系统账号后,并注册组织,申请组织认证通过后,才拥有发布的权限。 - diff --git "a/zh-cn/device-dev/bundles/\347\273\204\344\273\266\347\256\241\347\220\206.md" "b/zh-cn/device-dev/bundles/\347\273\204\344\273\266\347\256\241\347\220\206.md" deleted file mode 100755 index 852d9929b0..0000000000 --- "a/zh-cn/device-dev/bundles/\347\273\204\344\273\266\347\256\241\347\220\206.md" +++ /dev/null @@ -1,237 +0,0 @@ -# 组件管理 - -- [依赖关系](#section12657593129) -- [hpm操作命令参考](#section1258849181312) - -## 依赖关系 - -生成基础bundle.json以后,需要继续添加组件依赖来实现更复杂的功能。此时需要知道所依赖组件的名称和版本号,并且把它们定义在bundle.json里面的dependencies字段中。 - -``` -{ - "name": "my-bundle", - "version": "1.0.0", - "dependencies": { - "net": "1.0.0" - } -} -``` - -上述示例中,my-bundle组件依赖于net 1.0.0组件。在全局安装了 hpm CLI 工具之后,执行如下命令可以从远端仓库获取到依赖: - -``` -hpm install -``` - -依赖获取以后,会保存到当前组件根目录下到ohos\_bundles文件夹中。组件以及依赖之间会形成一个依赖关系的树状结构。全局安装了 hpm CLI 工具之后,在组件根目录下执行如下命令: - -``` -username@server MINGW64 /f/showcase/demo/demo -$ hpm list -+--demo@1.0.0 -| +--@huawei/media@1.0.2 -| +--@demo/sport_hi3518ev300_liteos_a@1.0.0 -| | +--@demo/app@4.0.1 -| | | +--@demo/build@4.0.1 -| | | +--@demo/arm_harmonyeabi_gcc@4.0.0 -| | +--@demo/liteos_a@4.0.0 -| | | +--@demo/third_party_fatfs@4.0.0 -| | | +--@demo/arm_harmonyeabi_gcc@4.0.0 -| | +--@demo/init@4.0.0 -| | +--@demo/dist_tools@4.0.0 -``` - -还可以使用图的形式,来查看当前组件的依赖关系,执行如下命令: - -``` -hpm dependencies -``` - -在当前目录下会生成deps\_visual文件夹,里面包含两个文件,deps.html 和 deps-data.js。在浏览器中打开 deps.html 文件,就可以看到依赖关系的图形化展示\(如下图\)。 - -根据不同的依赖类型,图形结点呈现出不同的颜色。鼠标悬浮在结点上,可以查看当前结点的状态。 - -**图 1** 组件包依赖关系图 -![](figures/组件包依赖关系图.png "组件包依赖关系图") - -## hpm操作命令参考 - -组件的全生命周期管理,可以通过hpm命令工具进行操作,hpm的操作命令如下(详细帮助可以执行 hpm -h学习): - -**表 1** hpm操作命令 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    命令类别

    -

    命令行

    -

    含义说明

    -

    版本查询

    -

    hpm -V 或 hpm --version

    -

    查看hpm-cli 版本号。

    -

    帮助查询

    -

    hpm -h 或 hpm --version

    -

    查看命令列表及帮助。

    -

    hpm -h

    -

    查看命令帮助。

    -

    创建

    -

    -

    hpm init bundle

    -

    创建组件工程。

    -

    hpm init -t template

    -

    根据模板创建脚手架工程。

    -

    安装

    -

    -

    hpm install 或hpm i

    -

    安装bundle.json中依赖的组件。

    -

    hpm install bundle@version

    -

    安装指定组件版本。

    -

    卸载

    -

    -

    hpm uninstall bundle

    -

    删除depedencies依赖的组件。

    -

    hpm remove 或hpm rm bundlename

    -

    删除depedencies依赖的组件。

    -

    查看

    -

    -

    hpm list 或者 hpm ls

    -

    显示当前组件/发行版所有的组件树。

    -

    hpm dependencies

    -

    生成当前组件/发行版依赖关系图(html格式)。

    -

    搜索

    -

    hpm search name

    -

    搜索组件,--json,可以以json格式输出 -type 可以设置搜索组件的类型,包括bundle,distribution,code-segment三种。

    -

    设置hpm配置项

    -

    hpm config set key value

    -

    设置配置值,如服务器地址,网络代理。

    -

    hpm config delete key

    -

    删除配置。

    -

    更新

    -

    -

    hpm update

    -

    更新当前组件依赖的组件的版本。

    -

    hpm check-update

    -

    检查依赖的组件版本是否有更新。

    -

    编译

    -

    -

    hpm build

    -

    编译组件/发行版。

    -

    hpm dist

    -

    发行版打包(依赖bundle.json的scripts中的dist脚本)。

    -

    打包

    -

    hpm pack

    -

    本地组件打包依赖。

    -

    烧录

    -

    hpm run flash

    -

    烧录固件(依赖bundle.json的scripts中的flash脚本)。

    -

    发布

    -

    hpm publish

    -

    发布组件,发布的组件在仓库中必须唯一,且版本唯一(需要账号登录)。

    -

    执行扩展命令

    -

    hpm run

    -

    执行bundle.json文件中定义的scripts脚本命令,支持多个命令可用 && 连接。

    -

    生成秘钥

    -

    hpm gen-keys

    -

    生成公钥/私钥对,将公钥配置到HPM服务端,可以实现hpm-cli 免密登录,发布组件。

    -

    生成第三方开源说明

    -

    hpm gen-notice

    -

    根据每个组件的说明,生成一份合并后的第三方开源说明的合并文件。

    -
    - - - - -
    - diff --git a/zh-cn/device-dev/driver/GPIO.md b/zh-cn/device-dev/driver/GPIO.md deleted file mode 100755 index afffef57ab..0000000000 --- a/zh-cn/device-dev/driver/GPIO.md +++ /dev/null @@ -1,9 +0,0 @@ -# GPIO - -- **[GPIO概述](GPIO概述.md)** - -- **[GPIO使用指导](GPIO使用指导.md)** - -- **[GPIO使用实例](GPIO使用实例.md)** - - diff --git "a/zh-cn/device-dev/driver/GPIO\344\275\277\347\224\250\345\256\236\344\276\213.md" "b/zh-cn/device-dev/driver/GPIO\344\275\277\347\224\250\345\256\236\344\276\213.md" deleted file mode 100755 index 86231b7af2..0000000000 --- "a/zh-cn/device-dev/driver/GPIO\344\275\277\347\224\250\345\256\236\344\276\213.md" +++ /dev/null @@ -1,79 +0,0 @@ -# GPIO使用实例 - -本实例程序中,我们将测试一个GPIO管脚的中断触发:为管脚设置中断服务函数,触发方式为边沿触发,然后通过交替写高低电平到管脚,产生电平波动,制造触发条件,观察中断服务函数的执行。 - -首先需要选取一个空闲的GPIO管脚,本例程基于Hi3516DV300某开发板,GPIO管脚选择GPIO10\_3,换算成GPIO号为83。 - -读者可以根据自己使用的开发板,参考其原理图,选择一个空闲的GPIO管脚即可。 - -``` -#include "gpio_if.h" -#include "hdf_log.h" -#include "osal_irq.h" -#include "osal_time.h" - -static uint32_t g_irqCnt; - -/* 中断服务函数*/ -static int32_t TestCaseGpioIrqHandler(uint16_t gpio, void *data) -{ - HDF_LOGE("%s: irq triggered! on gpio:%u, data=%p", __func__, gpio, data); - g_irqCnt++; /* 如果中断服务函数触发执行,则将全局中断计数加1 */ - return GpioDisableIrq(gpio); -} - -/* 测试用例函数 */ -static int32_t TestCaseGpioIrqEdge(void) -{ - int32_t ret; - uint16_t valRead; - uint16_t mode; - uint16_t gpio = 83; /* 待测试的GPIO管脚号 */ - uint32_t timeout; - - /* 将管脚方向设置为输出 */ - ret = GpioSetDir(gpio, GPIO_DIR_OUT); - if (ret != HDF_SUCCESS) { - HDF_LOGE("%s: set dir fail! ret:%d\n", __func__, ret); - return ret; - } - - /* 先禁止该管脚中断 */ - ret = GpioDisableIrq(gpio); - if (ret != HDF_SUCCESS) { - HDF_LOGE("%s: disable irq fail! ret:%d\n", __func__, ret); - return ret; - } - - /* 为管脚设置中断服务函数,触发模式为上升沿和下降沿共同触发 */ - mode = OSAL_IRQF_TRIGGER_RISING | OSAL_IRQF_TRIGGER_FALLING; - HDF_LOGE("%s: mode:%0x\n", __func__, mode); - ret = GpioSetIrq(gpio, mode, TestCaseGpioIrqHandler, NULL); - if (ret != HDF_SUCCESS) { - HDF_LOGE("%s: set irq fail! ret:%d\n", __func__, ret); - return ret; - } - - /* 使能此管脚中断 */ - ret = GpioEnableIrq(gpio); - if (ret != HDF_SUCCESS) { - HDF_LOGE("%s: enable irq fail! ret:%d\n", __func__, ret); - (void)GpioUnSetIrq(gpio); - return ret; - } - - g_irqCnt = 0; /* 清除全局计数器 */ - timeout = 0; /* 等待时间清零 */ - /* 等待此管脚中断服务函数触发,等待超时时间为1000毫秒 */ - while (g_irqCnt <= 0 && timeout < 1000) { - (void)GpioRead(gpio, &valRead); - (void)GpioWrite(gpio, (valRead == GPIO_VAL_LOW) ? GPIO_VAL_HIGH : GPIO_VAL_LOW); - HDF_LOGE("%s: wait irq timeout:%u\n", __func__, timeout); - OsalMDelay(200); /* wait for irq trigger */ - timeout += 200; - } - (void)GpioUnSetIrq(gpio); - return (g_irqCnt > 0) ? HDF_SUCCESS : HDF_FAILURE; -} -``` - diff --git "a/zh-cn/device-dev/driver/GPIO\344\275\277\347\224\250\346\214\207\345\257\274.md" "b/zh-cn/device-dev/driver/GPIO\344\275\277\347\224\250\346\214\207\345\257\274.md" deleted file mode 100755 index 1bc136ee21..0000000000 --- "a/zh-cn/device-dev/driver/GPIO\344\275\277\347\224\250\346\214\207\345\257\274.md" +++ /dev/null @@ -1,395 +0,0 @@ -# GPIO使用指导 - -- [使用流程](#section1583613406410) -- [确定GPIO管脚号](#section135943361443) -- [使用API操作GPIO管脚](#section69151114115315) - -## 使用流程 - -GPIO标准API通过GPIO管脚号来操作指定管脚,使用GPIO的一般流程如[图1](#fig1399416053717)所示。 - -**图 1** GPIO使用流程图 - - -![](figures/zh-cn_image_0000001057342245.png) - -## 确定GPIO管脚号 - -不同SOC芯片由于其GPIO控制器型号、参数、以及控制器驱动的不同,GPIO管脚号的换算方式不一样。 - -- Hi3516DV300 - - 控制器管理12组GPIO管脚,每组8个。 - - GPIO号 = GPIO组索引 \(0\~11\) \* 每组GPIO管脚数\(8\) + 组内偏移 - - 举例:GPIO10\_3的GPIO号 = 10 \* 8 + 3 = 83 - -- Hi3518EV300 - - 控制器管理10组GPIO管脚,每组10个。 - - GPIO号 = GPIO组索引 \(0\~9\) \* 每组GPIO管脚数\(10\) + 组内偏移 - - 举例:GPIO7\_3的GPIO管脚号 = 7 \* 10 + 3 = 73 - - -## 使用API操作GPIO管脚 - -- 设置GPIO管脚方向 - - 在进行GPIO管脚读写前,需要先通过如下函数设置GPIO管脚方向: - - int32\_t GpioSetDir\(uint16\_t gpio, uint16\_t dir\); - - **表 1** GpioSetDir参数和返回值描述 - - - - - - - - - - - - - - - - - - - - - -

    参数

    -

    参数描述

    -

    gpio

    -

    待设置的GPIO管脚号

    -

    dir

    -

    待设置的方向值

    -

    返回值

    -

    返回值描述

    -

    0

    -

    设置成功

    -

    负数

    -

    设置失败

    -
    - -- 读写GPIO管脚 - - 如果要读取一个GPIO管脚电平,通过以下函数完成: - - int32\_t GpioRead\(uint16\_t gpio, uint16\_t \*val\); - - **表 2** GpioRead参数和返回值描述 - - - - - - - - - - - - - - - - - - - - - -

    参数

    -

    参数描述

    -

    gpio

    -

    待读取的GPIO管脚号

    -

    val

    -

    接收读取电平值的指针

    -

    返回值

    -

    返回值描述

    -

    0

    -

    读取成功

    -

    负数

    -

    读取失败

    -
    - - 如果要向GPIO管脚写入电平值,通过以下函数完成: - - int32\_t GpioWrite\(uint16\_t gpio, uint16\_t val\); - - **表 3** GpioWrite参数和返回值描述 - - - - - - - - - - - - - - - - - - - - - -

    参数

    -

    参数描述

    -

    gpio

    -

    待写入的GPIO管脚号

    -

    val

    -

    待写入的电平值

    -

    返回值

    -

    返回值描述

    -

    0

    -

    写入成功

    -

    负数

    -

    写入失败

    -
    - - 示例代码: - - ``` - int32_t ret; - uint16_t val; - /* 将3号GPIO管脚配置为输出 */ - ret = GpioSetDir(3, GPIO_DIR_OUT); - if (ret != 0) { - HDF_LOGE("GpioSerDir: failed, ret %d\n", ret); - return; - } - /* 向3号GPIO管脚写入低电平GPIO_VAL_LOW */ - ret = GpioWrite(3, GPIO_VAL_LOW); - if (ret != 0) { - HDF_LOGE("GpioWrite: failed, ret %d\n", ret); - return; - } - /* 将6号GPIO管脚配置为输入 */ - ret = GpioSetDir(6, GPIO_DIR_IN); - if (ret != 0) { - HDF_LOGE("GpioSetDir: failed, ret %d\n", ret); - return; - } - /* 读取6号GPIO管脚的电平值 */ - ret = GpioRead(6, &val); - ``` - - -- 设置GPIO中断 - - 如果要为一个GPIO管脚设置中断响应程序,使用如下函数: - - int32\_t GpioSetIrq\(uint16\_t gpio, uint16\_t mode, GpioIrqFunc func, void \*arg\); - - **表 4** GpioSetIrq参数和返回值描述 - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    参数

    -

    参数描述

    -

    gpio

    -

    GPIO管脚号

    -

    mode

    -

    中断触发模式

    -

    func

    -

    中断服务程序

    -

    arg

    -

    传递给中断服务程序的入参

    -

    返回值

    -

    返回值描述

    -

    0

    -

    设置成功

    -

    负数

    -

    设置失败

    -
    - - >![](public_sys-resources/icon-caution.gif) **注意:** - >同一时间,只能为某个GPIO管脚设置一个中断服务函数,如果重复调用GpioSetIrq函数,则之前设置的中断服务函数会被取代。 - - 当不再需要响应中断服务函数时,使用如下函数取消中断设置: - - int32\_t GpioUnSetIrq\(uint16\_t gpio\); - - **表 5** GpioUnSetIrq参数和返回值描述 - - - - - - - - - - - - - - - - - - -

    参数

    -

    参数描述

    -

    gpio

    -

    GPIO管脚号

    -

    返回值

    -

    返回值描述

    -

    0

    -

    取消成功

    -

    负数

    -

    取消失败

    -
    - - 在中断服务程序设置完成后,还需要先通过如下函数使能GPIO管脚的中断: - - int32\_t GpioEnableIrq\(uint16\_t gpio\); - - **表 6** GpioEnableIrq参数和返回值描述 - - - - - - - - - - - - - - - - - - -

    参数

    -

    参数描述

    -

    gpio

    -

    GPIO管脚号

    -

    返回值

    -

    返回值描述

    -

    0

    -

    使能成功

    -

    负数

    -

    使能失败

    -
    - - >![](public_sys-resources/icon-caution.gif) **注意:** - >必须通过此函数使能管脚中断,之前设置的中断服务函数才能被正确响应。 - - 如果要临时屏蔽此中断,可以通过如下函数禁止GPIO管脚中断: - - int32\_t GpioDisableIrq\(uint16\_t gpio\); - - **表 7** GpioDisableIrq参数和返回值描述 - - - - - - - - - - - - - - - - - - -

    参数

    -

    参数描述

    -

    gpio

    -

    GPIO管脚号

    -

    返回值

    -

    返回值描述

    -

    0

    -

    禁止成功

    -

    负数

    -

    禁止失败

    -
    - - 示例代码: - - ``` - /* 中断服务函数 - */ - int32_t MyCallBackFunc(uint16_t gpio, void *data) - { - HDF_LOGI("%s: gpio:%u interrupt service in! data=%p\n", __func__, gpio, data); - return 0; - } - - int32_t ret; - /* 设置中断服务程序为MyCallBackFunc,入参为NULL,中断触发模式为上升沿触发 */ - ret = GpioSetIrq(3, OSAL_IRQF_TRIGGER_RISING, MyCallBackFunc, NULL); - if (ret != 0) { - HDF_LOGE("GpioSetIrq: failed, ret %d\n", ret); - return; - } - - /* 使能3号GPIO管脚中断 */ - ret = GpioEnableIrq(3); - if (ret != 0) { - HDF_LOGE("GpioEnableIrq: failed, ret %d\n", ret); - return; - } - - /* 禁止3号GPIO管脚中断 */ - ret = GpioDisableIrq(3); - if (ret != 0) { - HDF_LOGE("GpioDisableIrq: failed, ret %d\n", ret); - return; - } - - /* 取消3号GPIO管脚中断服务程序 */ - ret = GpioUnSetIrq(3); - if (ret != 0) { - HDF_LOGE("GpioUnSetIrq: failed, ret %d\n", ret); - return; - } - ``` - - diff --git "a/zh-cn/device-dev/driver/GPIO\346\246\202\350\277\260.md" "b/zh-cn/device-dev/driver/GPIO\346\246\202\350\277\260.md" deleted file mode 100755 index 1c4bcfc9c0..0000000000 --- "a/zh-cn/device-dev/driver/GPIO\346\246\202\350\277\260.md" +++ /dev/null @@ -1,82 +0,0 @@ -# GPIO概述 - -- [简介](#section15318165672215) -- [接口说明](#section18977142162418) - -## 简介 - -GPIO(General-purpose input/output)即通用型输入输出。通常,GPIO控制器通过分组的方式管理所有GPIO管脚,每组GPIO有一个或多个寄存器与之关联,通过读写寄存器完成对GPIO管脚的操作。 - -GPIO接口定义了操作GPIO管脚的标准方法集合,包括: - -- 设置管脚方向: 方向可以是输入或者输出\(暂不支持高阻态\) - -- 读写管脚电平值: 电平值可以是低电平或高电平 -- 设置管脚中断服务函数:设置一个管脚的中断响应函数,以及中断触发方式 -- 使能和禁止管脚中断:禁止或使能管脚中断 - -## 接口说明 - -**表 1** GPIO驱动API接口功能介绍 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    功能分类

    -

    接口名

    -

    描述

    -

    GPIO读写

    -

    GpioRead

    -

    读管脚电平值

    -

    GpioWrite

    -

    写管脚电平值

    -

    GPIO配置

    -

    GpioSetDir

    -

    设置管脚方向

    -

    GpioGetDir

    -

    获取管脚方向

    -

    GPIO中断设置

    -

    GpioSetIrq

    -

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

    -

    GpioUnSetIrq

    -

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

    -

    GpioEnableIrq

    -

    使能管脚中断

    -

    GpioDisableIrq

    -

    禁止管脚中断

    -
    - ->![](public_sys-resources/icon-note.gif) **说明:** ->本文涉及的所有接口,仅限内核态使用,不支持在用户态使用。 - diff --git "a/zh-cn/device-dev/driver/HDF\345\274\200\345\217\221\345\256\236\344\276\213.md" "b/zh-cn/device-dev/driver/HDF\345\274\200\345\217\221\345\256\236\344\276\213.md" deleted file mode 100755 index f9b3ca1aca..0000000000 --- "a/zh-cn/device-dev/driver/HDF\345\274\200\345\217\221\345\256\236\344\276\213.md" +++ /dev/null @@ -1,238 +0,0 @@ -# HDF开发实例 - -- [添加配置](#section27261067111) -- [编写驱动代码](#section177988005) -- [编写用户程序和驱动交互代码](#section6205173816412) - -下面基于HDF框架,提供一个完整的样例,包含配置文件的添加,驱动代码的实现以及用户态程序和驱动交互的流程。 - -## 添加配置 - -在HDF框架的配置文件(例如vendor/hisilicon/xxx/config/device\_info)中添加该驱动的配置信息,如下所示: - -``` -root { - device_info { - match_attr = "hdf_manager"; - template host { - hostName = ""; - priority = 100; - template device { - template deviceNode { - policy = 0; - priority = 100; - preload = 0; - permission = 0664; - moduleName = ""; - serviceName = ""; - deviceMatchAttr = ""; - } - } - } - sample_host :: host { - hostName = "sample_host"; - sample_device :: device { - device0 :: deviceNode { - policy = 2; - priority = 100; - preload = 1; - permission = 0664; - moduleName = "sample_driver"; - serviceName = "sample_service"; - } - } - } - } -} -``` - -## 编写驱动代码 - -基于HDF框架编写的sample驱动代码如下: - -``` -#include -#include -#include -#include "hdf_log.h" -#include "hdf_base.h" -#include "hdf_device_desc.h" - -#define HDF_LOG_TAG "sample_driver" - -#define SAMPLE_WRITE_READ 123 - -int32_t HdfSampleDriverDispatch( - struct HdfDeviceObject *deviceObject, int id, struct HdfSBuf *data, struct HdfSBuf *reply) -{ - HDF_LOGE("%s: received cmd %d", __func__, id); - if (id == SAMPLE_WRITE_READ) { - const char *readData = HdfSbufReadString(data); - if (readData != NULL) { - HDF_LOGE("%s: read data is: %s", __func__, readData); - } - if (!HdfSbufWriteInt32(reply, INT32_MAX)) { - HDF_LOGE("%s: reply int32 fail", __func__); - } - return HdfDeviceSendEvent(deviceObject, id, data); - } - return HDF_FAILURE; -} - -void HdfSampleDriverRelease(struct HdfDeviceObject *deviceObject) -{ - // release resources here - return; -} - -int HdfSampleDriverBind(struct HdfDeviceObject *deviceObject) -{ - if (deviceObject == NULL) { - return HDF_FAILURE; - } - static struct IDeviceIoService testService = { - .Dispatch = HdfSampleDriverDispatch, - }; - deviceObject->service = &testService; - return HDF_SUCCESS; -} - -int HdfSampleDriverInit(struct HdfDeviceObject *deviceObject) -{ - if (deviceObject == NULL) { - HDF_LOGE("%s::ptr is null!", __func__); - return HDF_FAILURE; - } - HDF_LOGE("Sample driver Init success"); - return HDF_SUCCESS; -} - -struct HdfDriverEntry g_sampleDriverEntry = { - .moduleVersion = 1, - .moduleName = "sample_driver", - .Bind = HdfSampleDriverBind, - .Init = HdfSampleDriverInit, - .Release = HdfSampleDriverRelease, -}; - -HDF_INIT(g_sampleDriverEntry); -``` - -## 编写用户程序和驱动交互代码 - -基于HDF框架编写的用户态程序和驱动交互的代码如下: - -``` -#include -#include -#include -#include -#include "hdf_log.h" -#include "hdf_sbuf.h" -#include "hdf_io_service_if.h" - -#define HDF_LOG_TAG "sample_test" -#define SAMPLE_SERVICE_NAME "sample_service" - -#define SAMPLE_WRITE_READ 123 - -int g_replyFlag = 0; - -static int OnDevEventReceived(void *priv, uint32_t id, struct HdfSBuf *data) -{ - const char *string = HdfSbufReadString(data); - if (string == NULL) { - HDF_LOGE("fail to read string in event data"); - g_replyFlag = 1; - return HDF_FAILURE; - } - HDF_LOGE("%s: dev event received: %u %s", (char *)priv, id, string); - g_replyFlag = 1; - return HDF_SUCCESS; -} - -static int SendEvent(struct HdfIoService *serv, char *eventData) -{ - int ret = 0; - struct HdfSBuf *data = HdfSBufObtainDefaultSize(); - if (data == NULL) { - HDF_LOGE("fail to obtain sbuf data"); - return 1; - } - - struct HdfSBuf *reply = HdfSBufObtainDefaultSize(); - if (reply == NULL) { - HDF_LOGE("fail to obtain sbuf reply"); - ret = HDF_DEV_ERR_NO_MEMORY; - goto out; - } - - if (!HdfSbufWriteString(data, eventData)) { - HDF_LOGE("fail to write sbuf"); - ret = HDF_FAILURE; - goto out; - } - - ret = serv->dispatcher->Dispatch(&serv->object, SAMPLE_WRITE_READ, data, reply); - if (ret != HDF_SUCCESS) { - HDF_LOGE("fail to send service call"); - goto out; - } - - int replyData = 0; - if (!HdfSbufReadInt32(reply, &replyData)) { - HDF_LOGE("fail to get service call reply"); - ret = HDF_ERR_INVALID_OBJECT; - goto out; - } - HDF_LOGE("Get reply is: %d", replyData); -out: - HdfSBufRecycle(data); - HdfSBufRecycle(reply); - return ret; -} - -int main() -{ - char *sendData = "default event info"; - struct HdfIoService *serv = HdfIoServiceBind(SAMPLE_SERVICE_NAME); - if (serv == NULL) { - HDF_LOGE("fail to get service %s", SAMPLE_SERVICE_NAME); - return HDF_FAILURE; - } - - static struct HdfDevEventlistener listener = { - .callBack = OnDevEventReceived, - .priv ="Service0" - }; - - if (HdfDeviceRegisterEventListener(serv, &listener) != HDF_SUCCESS) { - HDF_LOGE("fail to register event listener"); - return HDF_FAILURE; - } - if (SendEvent(serv, sendData)) { - HDF_LOGE("fail to send event"); - return HDF_FAILURE; - } - - while (g_replyFlag == 0) { - sleep(1); - } - - if (HdfDeviceUnregisterEventListener(serv, &listener)) { - HDF_LOGE("fail to unregister listener"); - return HDF_FAILURE; - } - - HdfIoServiceRecycle(serv); - return HDF_SUCCESS; -} -``` - ->![](public_sys-resources/icon-note.gif) **说明:** ->用户态应用程序使用了HDF框架中的消息发送接口,因此在编译用户态程序的过程中需要依赖HDF框架对外提供的hdf\_core和osal的动态库,在gn编译文件中添加如下依赖项: ->deps = \[ ->"//drivers/adapter/lite/uhdf/manager:hdf\_core", ->"//drivers/adapter/lite/uhdf/posix:hdf\_posix\_osal", ->\] - diff --git "a/zh-cn/device-dev/driver/HDF\351\251\261\345\212\250\346\241\206\346\236\266.md" "b/zh-cn/device-dev/driver/HDF\351\251\261\345\212\250\346\241\206\346\236\266.md" deleted file mode 100755 index fb6f985a6e..0000000000 --- "a/zh-cn/device-dev/driver/HDF\351\251\261\345\212\250\346\241\206\346\236\266.md" +++ /dev/null @@ -1,15 +0,0 @@ -# HDF驱动框架 - -- **[HDF开发概述](HDF开发概述.md)** - -- **[驱动开发](驱动开发.md)** - -- **[驱动服务管理](驱动服务管理.md)** - -- **[驱动消息机制管理](驱动消息机制管理.md)** - -- **[配置管理](配置管理.md)** - -- **[HDF开发实例](HDF开发实例.md)** - - diff --git a/zh-cn/device-dev/driver/I2C.md b/zh-cn/device-dev/driver/I2C.md deleted file mode 100755 index 5bc8c5bf3c..0000000000 --- a/zh-cn/device-dev/driver/I2C.md +++ /dev/null @@ -1,9 +0,0 @@ -# I2C - -- **[I2C概述](I2C概述.md)** - -- **[I2C使用指导](I2C使用指导.md)** - -- **[I2C使用实例](I2C使用实例.md)** - - diff --git "a/zh-cn/device-dev/driver/I2C\344\275\277\347\224\250\345\256\236\344\276\213.md" "b/zh-cn/device-dev/driver/I2C\344\275\277\347\224\250\345\256\236\344\276\213.md" deleted file mode 100755 index a75da59b1b..0000000000 --- "a/zh-cn/device-dev/driver/I2C\344\275\277\347\224\250\345\256\236\344\276\213.md" +++ /dev/null @@ -1,192 +0,0 @@ -# I2C使用实例 - -本例程以操作开发板上的I2C设备为例,详细展示I2C接口的完整使用流程。 - -本例拟对Hi3516DV300某开发板上TouchPad设备进行简单的寄存器读写访问,基本硬件信息如下: - -- SOC:hi3516dv300。 - -- Touch IC:I2C地址为0x38, IC内部寄存器位宽为1字节。 - -- 原理图信息:TouchPad设备挂接在3号I2C控制器下;IC的复位管脚为3号GPIO。 - -本例程首先对Touch IC进行复位操作(开发板上电默认会给TouchIC供电,本例程不考虑供电),然后对其内部寄存器进行随机读写,测试I2C通路是否正常。 - ->![](public_sys-resources/icon-note.gif) **说明:** ->本例程重点在于展示I2C设备访问流程,并验证I2C通路,所以对于设备寄存器读写值不做关注,读写寄存器导致的行为由设备自身决定。 - -示例如下: - -``` -#include "i2c_if.h" /* I2C标准接口头文件 */ -#include "gpio_if.h" /* GPIO标准接口头文件 */ -#include "hdf_log.h" /* 标准日志打印头文件 */ -#include "osal_io.h" /* 标准IO读写接口头文件 */ -#include "osal_time.h" /* 标准延迟&睡眠接口头文件 */ - -/* 定义一个表示TP设备的结构体,存储i2c及gpio相关硬件信息 */ -struct TpI2cDevice { - uint16_t rstGpio; /* 复位管脚 */ - uint16_t busId; /* I2C总线号 */ - uint16_t addr; /* I2C设备地址 */ - uint16_t regLen; /* 寄存器字节宽度 */ - DevHandle i2cHandle; /* I2C控制器句柄 */ -}; - -/* I2C管脚io配置,需要查阅SOC寄存器手册 */ -#define I2C3_DATA_REG_ADDR 0x112f008c /* 3号I2C控制器SDA管脚配置寄存器地址 */ -#define I2C3_CLK_REG_ADDR 0x112f0090 /* 3号I2C控制器SCL管脚配置寄存器地址 */ -#define I2C_REG_CFG 0x5f1 /* 3号I2C控制器SDA及SCL管脚配置值 */ - -static void TpSocIoCfg(void) -{ - /* 将3号I2C控制器对应两个管脚的IO功能设置为I2C */ - OSAL_WRITEL(I2C_REG_CFG, IO_DEVICE_ADDR(I2C3_DATA_REG_ADDR)); - OSAL_WRITEL(I2C_REG_CFG, IO_DEVICE_ADDR(I2C3_CLK_REG_ADDR)); -} - -/* 对TP的复位管脚进行初始化, 拉高维持20ms, 再拉底维持50ms,最后再拉高维持20ms, 完成复位动作 */ -static int32_t TestCaseGpioInit(struct TpI2cDevice *tpDevice) -{ - int32_t ret; - - /* 设置复位管脚方向为输出 */ - ret = GpioSetDir(tpDevice->rstGpio, GPIO_DIR_OUT); - if (ret != HDF_SUCCESS) { - HDF_LOGE("%s: set rst dir fail!:%d", __func__, ret); - return ret; - } - - ret = GpioWrite(tpDevice->rstGpio, GPIO_VAL_HIGH); - if (ret != HDF_SUCCESS) { - HDF_LOGE("%s: set rst hight fail!:%d", __func__, ret); - return ret; - } - OsalMSleep(20); - - ret = GpioWrite(tpDevice->rstGpio, GPIO_VAL_LOW); - if (ret != HDF_SUCCESS) { - HDF_LOGE("%s: set rst low fail!:%d", __func__, ret); - return ret; - } - OsalMSleep(50); - - ret = GpioWrite(tpDevice->rstGpio, GPIO_VAL_HIGH); - if (ret != HDF_SUCCESS) { - HDF_LOGE("%s: set rst high fail!:%d", __func__, ret); - return ret; - } - OsalMSleep(20); - - return HDF_SUCCESS; -} - -/* 基于I2cTransfer方法封装一个寄存器读写的辅助函数, 通过flag表示读或写 */ -static int TpI2cReadWrite(struct TpI2cDevice *tpDevice, unsigned int regAddr, - unsigned char *regData, unsigned int dataLen, uint8_t flag) -{ - int index = 0; - unsigned char regBuf[4] = {0}; - struct I2cMsg msgs[2] = {0}; - - /* 单双字节寄存器长度适配 */ - if (tpDevice->regLen == 1) { - regBuf[index++] = regAddr & 0xFF; - } else { - regBuf[index++] = (regAddr >> 8) & 0xFF; - regBuf[index++] = regAddr & 0xFF; - } - - /* 填充I2cMsg消息结构 */ - msgs[0].addr = tpDevice->addr; - msgs[0].flags = 0; /* 标记为0,表示写入 */ - msgs[0].len = tpDevice->regLen; - msgs[0].buf = regBuf; - - msgs[1].addr = tpDevice->addr; - msgs[1].flags = (flag == 1) ? I2C_FLAG_READ : 0; /* 添加读标记位,表示读取 */ - msgs[1].len = dataLen; - msgs[1].buf = regData; - - if (I2cTransfer(tpDevice->i2cHandle, msgs, 2) != 2) { - HDF_LOGE("%s: i2c read err", __func__); - return HDF_FAILURE; - } - return HDF_SUCCESS; -} - -/* TP寄存器读函数 */ -static inline int TpI2cReadReg(struct TpI2cDevice *tpDevice, unsigned int regAddr, - unsigned char *regData, unsigned int dataLen) -{ - return TpI2cReadWrite(tpDevice, regAddr, regData, dataLen, 1); -} - -/* TP寄存器写函数 */ -static inline int TpI2cWriteReg(struct TpI2cDevice *tpDevice, unsigned int regAddr, - unsigned char *regData, unsigned int dataLen) -{ - return TpI2cReadWrite(tpDevice, regAddr, regData, dataLen, 0); -} - -/* I2C例程总入口 */ -static int32_t TestCaseI2c(void) -{ - int32_t i; - int32_t ret; - unsigned char bufWrite[7] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xA, 0xB, 0xC }; - unsigned char bufRead[7] = {0}; - static struct TpI2cDevice tpDevice; - - /* IO管脚功能配置 */ - TpSocIoCfg(); - - /* TP设备信息初始化 */ - tpDevice.rstGpio = 3; - tpDevice.busId = 3; - tpDevice.addr = 0x38; - tpDevice.regLen = 1; - tpDevice.i2cHandle = NULL; - - /* GPIO管脚初始化 */ - ret = TestCaseGpioInit(&tpDevice); - if (ret != HDF_SUCCESS) { - HDF_LOGE("%s: gpio init fail!:%d", __func__, ret); - return ret; - } - - /* 打开I2C控制器 */ - tpDevice.i2cHandle = I2cOpen(tpDevice.busId); - if (tpDevice.i2cHandle == NULL) { - HDF_LOGE("%s: Open I2c:%u fail!", __func__, tpDevice.busId); - return -1; - } - - /* 向TP-IC的0xD5寄存器连续写7字节数据 */ - ret = TpI2cWriteReg(&tpDevice, 0xD5, bufWrite, 7); - if (ret != HDF_SUCCESS) { - HDF_LOGE("%s: tp i2c write reg fail!:%d", __func__, ret); - I2cClose(tpDevice.i2cHandle); - return -1; - } - OsalMSleep(10); - - /* 从TP-IC的0xDO寄存器连续读7字节数据 */ - ret = TpI2cReadReg(&tpDevice, 0xD5, bufRead, 7); - if (ret != HDF_SUCCESS) { - HDF_LOGE("%s: tp i2c read reg fail!:%d", __func__, ret); - I2cClose(tpDevice.i2cHandle); - return -1; - } - - HDF_LOGE("%s: tp i2c write&read reg success!", __func__); - for (i = 0; i < 7; i++) { - HDF_LOGE("%s: bufRead[%d] = 0x%x", __func__, i, bufRead[i]); - } - - /* 访问完毕关闭I2C控制器 */ - I2cClose(tpDevice.i2cHandle); - return ret; -} -``` - diff --git "a/zh-cn/device-dev/driver/I2C\344\275\277\347\224\250\346\214\207\345\257\274.md" "b/zh-cn/device-dev/driver/I2C\344\275\277\347\224\250\346\214\207\345\257\274.md" deleted file mode 100755 index 38341ca1d4..0000000000 --- "a/zh-cn/device-dev/driver/I2C\344\275\277\347\224\250\346\214\207\345\257\274.md" +++ /dev/null @@ -1,171 +0,0 @@ -# I2C使用指导 - -- [使用流程](#section333203315215) -- [打开I2C控制器](#section123631358135713) -- [进行I2C通信](#section11091522125812) -- [关闭I2C控制器](#section13519505589) - -## 使用流程 - -使用I2C设备的一般流程如[图1](#fig166181128151112)所示。 - -**图 1** I2C设备使用流程图 - - -![](figures/zh-cn_image_0000001057902344.png) - -## 打开I2C控制器 - -在进行I2C通信前,首先要调用I2cOpen打开I2C控制器。 - -DevHandle I2cOpen\(int16\_t number\); - -**表 1** I2cOpen参数和返回值描述 - - - - - - - - - - - - - - - - - - - -

    参数

    -

    参数描述

    -

    number

    -

    I2C控制器号

    -

    返回值

    -

    返回值描述

    -

    NULL

    -

    打开I2C控制器失败

    -

    设备句柄

    -

    打开的I2C控制器设备句柄

    -
    - -假设系统中存在8个I2C控制器,编号从0到7,那么我们现在获取3号控制器 - -``` -DevHandle i2cHandle = NULL; /* I2C控制器句柄 / - -/* 打开I2C控制器 */ -i2cHandle = I2cOpen(3); -if (i2cHandle == NULL) { - HDF_LOGE("I2cOpen: failed\n"); - return; -} -``` - -## 进行I2C通信 - -消息传输 - -int32\_t I2cTransfer\(DevHandle handle, struct I2cMsg \*msgs, int16\_t count\); - -**表 2** I2cTransfer参数和返回值描述 - - - - - - - - - - - - - - - - - - - - - - - - - -

    参数

    -

    参数描述

    -

    handle

    -

    I2C控制器设备句柄

    -

    msgs

    -

    待传输数据的消息结构体数组

    -

    count

    -

    消息数组长度

    -

    返回值

    -

    返回值描述

    -

    正整数

    -

    成功传输的消息结构体数目

    -

    负数

    -

    执行失败

    -
    - -I2C传输消息类型为I2cMsg,每个传输消息结构体表示一次读或写,通过一个消息数组,可以执行若干次的读写组合操作。 - -``` -int32_t ret; -uint8_t wbuff[2] = { 0x12, 0x13 }; -uint8_t rbuff[2] = { 0 }; -struct I2cMsg msgs[2]; /* 自定义传输的消息结构体数组 */ -msgs[0].buf = wbuff; /* 写入的数据 */ -msgs[0].len = 2; /* 写入数据长度为2 */ -msgs[0].addr = 0x5A; /* 写入设备地址为0x5A */ -msgs[0].flags = 0; /* 传输标记为0,默认为写 */ -msgs[1].buf = rbuff; /* 要读取的数据 */ -msgs[1].len = 2; /* 读取数据长度为2 */ -msgs[1].addr = 0x5A; /* 读取设备地址为0x5A */ -msgs[1].flags = I2C_FLAG_READ /* I2C_FLAG_READ置位 */ -/* 进行一次自定义传输,传输的消息个数为2 */ -ret = I2cTransfer(i2cHandle, msgs, 2); -if (ret != 2) { - HDF_LOGE("I2cTransfer: failed, ret %d\n", ret); - return; -} -``` - ->![](public_sys-resources/icon-caution.gif) **注意:** ->- I2cMsg结构体中的设备地址不包含读写标志位,读写信息由flags成员变量的读写控制位传递。 ->- 本函数不对消息结构体个数count做限制,其最大个数度由具体I2C控制器决定。 ->- 本函数也不对每个消息结构体中的数据长度做限制,同样由具体I2C控制器决定。 ->- 本函数可能会引起系统休眠,不允许在中断上下文调用 - -## 关闭I2C控制器 - -I2C通信完成之后,需要关闭2C控制器,关闭函数如下所示: - -void I2cClose\(DevHandle handle\); - -**表 3** I2cClose参数和返回值描述 - - - - - - - - - - -

    参数

    -

    参数描述

    -

    handle

    -

    I2C控制器设备句柄

    -
    - -``` -I2cClose(i2cHandle); /* 关闭I2C控制器 */ -``` - diff --git "a/zh-cn/device-dev/driver/I2C\346\246\202\350\277\260.md" "b/zh-cn/device-dev/driver/I2C\346\246\202\350\277\260.md" deleted file mode 100755 index 7961b58a82..0000000000 --- "a/zh-cn/device-dev/driver/I2C\346\246\202\350\277\260.md" +++ /dev/null @@ -1,60 +0,0 @@ -# I2C概述 - -- [简介](#section5361140416) -- [接口说明](#section7606310210) - -## 简介 - -- I2C\(Inter Integrated Circuit\)总线是由Philips公司开发的一种简单、双向二线制同步串行总线。 -- I2C以主从方式工作,通常有一个主设备和一个或者多个从设备,主从设备通过SDA\(SerialData\)串行数据线以及SCL\(SerialClock\)串行时钟线两根线相连,如[图1 ](#fig1135561232714)所示。 - -- I2C数据的传输必须以一个起始信号作为开始条件,以一个结束信号作为传输的停止条件。数据传输以字节为单位,高位在前,逐个bit进行传输。 -- I2C总线上的每一个设备都可以作为主设备或者从设备,而且每一个设备都会对应一个唯一的地址,当主设备需要和某一个从设备通信时,通过广播的方式,将从设备地址写到总线上,如果某个从设备符合此地址,将会发出应答信号,建立传输。 - -- I2C接口定义了完成I2C传输的通用方法集合,包括: - - - I2C控制器管理: 打开或关闭I2C控制器 - - I2C消息传输:通过消息传输结构体数组进行自定义传输 - - **图 1** I2C物理连线示意图 - ![](figures/I2C物理连线示意图.png "I2C物理连线示意图") - - -## 接口说明 - -**表 1** I2C驱动API接口功能介绍 - - - - - - - - - - - - - - - - - - - -

    功能分类

    -

    接口名

    -

    描述

    -

    I2C控制器管理接口

    -

    I2cOpen

    -

    打开I2C控制器

    -

    I2cClose

    -

    关闭I2C控制器

    -

    I2c消息传输接口

    -

    I2cTransfer

    -

    自定义传输

    -
    - ->![](public_sys-resources/icon-note.gif) **说明:** ->本文涉及的所有接口,仅限内核态使用,不支持在用户态使用。 - diff --git a/zh-cn/device-dev/driver/LCD.md b/zh-cn/device-dev/driver/LCD.md deleted file mode 100755 index b6352ca833..0000000000 --- a/zh-cn/device-dev/driver/LCD.md +++ /dev/null @@ -1,9 +0,0 @@ -# LCD - -- **[LCD开发概述](LCD开发概述.md)** - -- **[LCD开发指导](LCD开发指导.md)** - -- **[LCD开发实例](LCD开发实例.md)** - - diff --git "a/zh-cn/device-dev/driver/LCD\345\274\200\345\217\221\345\256\236\344\276\213.md" "b/zh-cn/device-dev/driver/LCD\345\274\200\345\217\221\345\256\236\344\276\213.md" deleted file mode 100755 index 6de1970400..0000000000 --- "a/zh-cn/device-dev/driver/LCD\345\274\200\345\217\221\345\256\236\344\276\213.md" +++ /dev/null @@ -1,291 +0,0 @@ -# LCD开发实例 - -添加设备描述配置: - -``` -/* Display驱动相关的设备描述配置 */ -display :: host { - hostName = "display_host"; - /* Display平台驱动设备描述 */ - device_hdf_disp :: device { - device0 :: deviceNode { - policy = 2; - priority = 200; - permission = 0660; - moduleName = "HDF_DISP"; - serviceName = "hdf_disp"; - } - } - /* SOC适配层驱动设备描述 */ - device_hi35xx_disp :: device { - device0 :: deviceNode { - policy = 0; - priority = 199; - moduleName = "HI351XX_DISP"; - } - } - /* LCD器件驱动设备描述 */ - device_lcd :: device { - device0 :: deviceNode { - policy = 0; - priority = 100; - preload = 0; - moduleName = "LCD_Sample"; - } - device1 :: deviceNode { - policy = 0; - priority = 100; - preload = 2; - moduleName = "LCD_SampleXX"; - } - } -} -``` - -SOC适配层驱动,以Hi35xx系列芯片为例,需要在本层驱动中适配MIPI等和芯片平台相关的配置,示例如下: - -``` -static int32_t MipiDsiInit(struct PanelInfo *info) -{ - int32_t ret; - struct DevHandle *mipiHandle = NULL; - struct MipiCfg cfg; - - mipiHandle = MipiDsiOpen(0); - if (mipiHandle == NULL) { - HDF_LOGE("%s: MipiDsiOpen failure", __func__); - return HDF_FAILURE; - } - cfg.lane = info->mipi.lane; - cfg.mode = info->mipi.mode; - cfg.format = info->mipi.format; - cfg.burstMode = info->mipi.burstMode; - cfg.timing.xPixels = info->width; - cfg.timing.hsaPixels = info->hsw; - cfg.timing.hbpPixels = info->hbp; - cfg.timing.hlinePixels = info->width + info->hbp + info->hfp + info->hsw; - cfg.timing.vsaLines = info->vsw; - cfg.timing.vbpLines = info->vbp; - cfg.timing.vfpLines = info->vfp; - cfg.timing.ylines = info->height; - /* 0 : no care */ - cfg.timing.edpiCmdSize = 0; - cfg.pixelClk = CalcPixelClk(info); - cfg.phyDataRate = CalcDataRate(info); - /* config mipi device */ - ret = MipiDsiSetCfg(mipiHandle, &cfg); - if (ret != HDF_SUCCESS) { - HDF_LOGE("%s:MipiDsiSetCfg failure", __func__); - } - MipiDsiClose(mipiHandle); - HDF_LOGI("%s:pixelClk = %d, phyDataRate = %d\n", __func__, - cfg.pixelClk, cfg.phyDataRate); - return ret; -} -``` - -LCD器件驱动示例如下: - -``` -#define RESET_GPIO 5 -#define MIPI_DSI0 0 -#define BLK_PWM1 1 -#define PWM_MAX_PERIOD 100000 -/* backlight setting */ -#define MIN_LEVEL 0 -#define MAX_LEVEL 255 -#define DEFAULT_LEVEL 100 - -#define WIDTH 480 -#define HEIGHT 960 -#define HORIZONTAL_BACK_PORCH 20 -#define HORIZONTAL_FRONT_PORCH 20 -#define HORIZONTAL_SYNC_WIDTH 10 -#define VERTIACL_BACK_PORCH 14 -#define VERTIACL_FRONT_PORCH 16 -#define VERTIACL_SYNC_WIDTH 2 -#define FRAME_RATE 60 - -/* Panel Info结构体结构体 */ -struct PanelInfo { - uint32_t width; - uint32_t height; - uint32_t hbp; - uint32_t hfp; - uint32_t hsw; - uint32_t vbp; - uint32_t vfp; - uint32_t vsw; - uint32_t frameRate; - enum LcdIntfType intfType; - enum IntfSync intfSync; - struct MipiDsiDesc mipi; - struct BlkDesc blk; - struct PwmCfg pwm; -}; - -/* LCD屏的初始化序列 */ -static uint8_t g_payLoad0[] = { 0xF0, 0x5A, 0x5A }; -static uint8_t g_payLoad1[] = { 0xF1, 0xA5, 0xA5 }; -static uint8_t g_payLoad2[] = { 0xB3, 0x03, 0x03, 0x03, 0x07, 0x05, 0x0D, 0x0F, 0x11, 0x13, 0x09, 0x0B }; -static uint8_t g_payLoad3[] = { 0xB4, 0x03, 0x03, 0x03, 0x06, 0x04, 0x0C, 0x0E, 0x10, 0x12, 0x08, 0x0A }; -static uint8_t g_payLoad4[] = { 0xB0, 0x54, 0x32, 0x23, 0x45, 0x44, 0x44, 0x44, 0x44, 0x60, 0x00, 0x60, 0x1C }; -static uint8_t g_payLoad5[] = { 0xB1, 0x32, 0x84, 0x02, 0x87, 0x12, 0x00, 0x50, 0x1C }; -static uint8_t g_payLoad6[] = { 0xB2, 0x73, 0x09, 0x08 }; -static uint8_t g_payLoad7[] = { 0xB6, 0x5C, 0x5C, 0x05 }; -static uint8_t g_payLoad8[] = { 0xB8, 0x23, 0x41, 0x32, 0x30, 0x03 }; -static uint8_t g_payLoad9[] = { 0xBC, 0xD2, 0x0E, 0x63, 0x63, 0x5A, 0x32, 0x22, 0x14, 0x22, 0x03 }; -static uint8_t g_payLoad10[] = { 0xb7, 0x41 }; -static uint8_t g_payLoad11[] = { 0xC1, 0x0c, 0x10, 0x04, 0x0c, 0x10, 0x04 }; -static uint8_t g_payLoad12[] = { 0xC2, 0x10, 0xE0 }; -static uint8_t g_payLoad13[] = { 0xC3, 0x22, 0x11 }; -static uint8_t g_payLoad14[] = { 0xD0, 0x07, 0xFF }; -static uint8_t g_payLoad15[] = { 0xD2, 0x63, 0x0B, 0x08, 0x88 }; -static uint8_t g_payLoad16[] = { 0xC6, 0x08, 0x15, 0xFF, 0x10, 0x16, 0x80, 0x60 }; -static uint8_t g_payLoad17[] = { 0xc7, 0x04 }; -static uint8_t g_payLoad18[] = { - 0xC8, 0x7C, 0x50, 0x3B, 0x2C, 0x25, 0x16, 0x1C, 0x08, 0x27, 0x2B, 0x2F, 0x52, 0x43, 0x4C, 0x40, - 0x3D, 0x30, 0x1E, 0x06, 0x7C, 0x50, 0x3B, 0x2C, 0x25, 0x16, 0x1C, 0x08, 0x27, 0x2B, 0x2F, 0x52, - 0x43, 0x4C, 0x40, 0x3D, 0x30, 0x1E, 0x06 -}; -static uint8_t g_payLoad19[] = { 0x11 }; -static uint8_t g_payLoad20[] = { 0x29 }; - -struct DsiCmdDesc g_OnCmd[] = { - { 0x29, 0, sizeof(g_payLoad0), g_payLoad0 }, - { 0x29, 0, sizeof(g_payLoad1), g_payLoad1 }, - { 0x29, 0, sizeof(g_payLoad2), g_payLoad2 }, - { 0x29, 0, sizeof(g_payLoad3), g_payLoad3 }, - { 0x29, 0, sizeof(g_payLoad4), g_payLoad4 }, - { 0x29, 0, sizeof(g_payLoad5), g_payLoad5 }, - { 0x29, 0, sizeof(g_payLoad6), g_payLoad6 }, - { 0x29, 0, sizeof(g_payLoad7), g_payLoad7 }, - { 0x29, 0, sizeof(g_payLoad8), g_payLoad8 }, - { 0x29, 0, sizeof(g_payLoad9), g_payLoad9 }, - { 0x23, 0, sizeof(g_payLoad10), g_payLoad10 }, - { 0x29, 0, sizeof(g_payLoad11), g_payLoad11 }, - { 0x29, 0, sizeof(g_payLoad12), g_payLoad12 }, - { 0x29, 0, sizeof(g_payLoad13), g_payLoad13 }, - { 0x29, 0, sizeof(g_payLoad14), g_payLoad14 }, - { 0x29, 0, sizeof(g_payLoad15), g_payLoad15 }, - { 0x29, 0, sizeof(g_payLoad16), g_payLoad16 }, - { 0x23, 0, sizeof(g_payLoad17), g_payLoad17 }, - { 0x29, 1, sizeof(g_payLoad18), g_payLoad18 }, - { 0x05, 120, sizeof(g_payLoad19), g_payLoad19 }, - { 0x05, 120, sizeof(g_payLoad20), g_payLoad20 }, -}; -static DevHandle g_mipiHandle = NULL; -static DevHandle g_pwmHandle = NULL; - -/* 设置Reset Pin脚状态 */ -static int32_t LcdResetOn(void) -{ - int32_t ret; - ret = GpioSetDir(RESET_GPIO, GPIO_DIR_OUT); - if (ret != HDF_SUCCESS) { - HDF_LOGE("GpioSetDir failure, ret:%d", ret); - return HDF_FAILURE; - } - ret = GpioWrite(RESET_GPIO, GPIO_VAL_HIGH); - if (ret != HDF_SUCCESS) { - HDF_LOGE("GpioWrite failure, ret:%d", ret); - return HDF_FAILURE; - } - /* delay 20ms */ - OsalMSleep(20); - return HDF_SUCCESS; -} - -static int32_t SampleInit(void) -{ - /* 获取MIPI DSI设备操作句柄 */ - g_mipiHandle = MipiDsiOpen(MIPI_DSI0); - if (g_mipiHandle == NULL) { - HDF_LOGE("%s: MipiDsiOpen failure", __func__); - return HDF_FAILURE; - } - return HDF_SUCCESS; -} - -static int32_t SampleOn(void) -{ - int32_t ret; - /* LCD上电序列 */ - ret = LcdResetOn(); - if (ret != HDF_SUCCESS) { - HDF_LOGE("%s: LcdResetOn failure", __func__); - return HDF_FAILURE; - } - if (g_mipiHandle == NULL) { - HDF_LOGE("%s: g_mipiHandle is null", __func__); - return HDF_FAILURE; - } - /* 使用mipi下发初始化序列 */ - int32_t count = sizeof(g_OnCmd) / sizeof(g_OnCmd[0]); - int32_t i; - for (i = 0; i < count; i++) { - ret = MipiDsiTx(g_mipiHandle, &(g_OnCmd[i])); - if (ret != HDF_SUCCESS) { - HDF_LOGE("MipiDsiTx failure"); - return HDF_FAILURE; - } - } - /* 将mipi切换到HS模式 */ - MipiDsiSetHsMode(g_mipiHandle); - return HDF_SUCCESS; -} - -/* PanelInfo结构体变量 */ -static struct PanelInfo g_panelInfo = { - .width = WIDTH, /* width */ - .height = HEIGHT, /* height */ - .hbp = HORIZONTAL_BACK_PORCH, /* horizontal back porch */ - .hfp = HORIZONTAL_FRONT_PORCH, /* horizontal front porch */ - .hsw = HORIZONTAL_SYNC_WIDTH, /* horizontal sync width */ - .vbp = VERTIACL_BACK_PORCH, /* vertiacl back porch */ - .vfp = VERTIACL_FRONT_PORCH, /* vertiacl front porch */ - .vsw = VERTIACL_SYNC_WIDTH, /* vertiacl sync width */ - .frameRate = FRAME_RATE, /* frame rate */ - .intfType = MIPI_DSI, /* panel interface type */ - .intfSync = OUTPUT_USER, /* output timming type */ - /* mipi config info */ - .mipi = { DSI_2_LANES, DSI_VIDEO_MODE, VIDEO_BURST_MODE, FORMAT_RGB_24_BIT }, - /* backlight config info */ - .blk = { BLK_PWM, MIN_LEVEL, MAX_LEVEL, DEFAULT_LEVEL }, - .pwm = { BLK_PWM1, PWM_MAX_PERIOD }, -}; - -/* 器件驱动需要适配的基础接口 */ -static struct PanelData g_panelData = { - .info = &g_panelInfo, - .init = SampleInit, - .on = SampleOn, - .off = SampleOff, - .setBacklight = SampleSetBacklight, -}; - -/* 器件驱动入口函数 */ -int32_t SampleEntryInit(struct HdfDeviceObject *object) -{ - HDF_LOGI("%s: enter", __func__); - if (object == NULL) { - HDF_LOGE("%s: param is null!", __func__); - return HDF_FAILURE; - } - /* 器件驱动接口注册,ops提供给平台驱动调用 */ - if (PanelDataRegister(&g_panelData) != HDF_SUCCESS) { - HDF_LOGE("%s: PanelDataRegister error!", __func__); - return HDF_FAILURE; - } - return HDF_SUCCESS; -} - -struct HdfDriverEntry g_sampleDevEntry = { - .moduleVersion = 1, - .moduleName = "LCD_SAMPLE", - .Init = SampleEntryInit, -}; - -HDF_INIT(g_sampleDevEntry); -``` - diff --git "a/zh-cn/device-dev/driver/LCD\345\274\200\345\217\221\346\214\207\345\257\274.md" "b/zh-cn/device-dev/driver/LCD\345\274\200\345\217\221\346\214\207\345\257\274.md" deleted file mode 100755 index 12161e4cef..0000000000 --- "a/zh-cn/device-dev/driver/LCD\345\274\200\345\217\221\346\214\207\345\257\274.md" +++ /dev/null @@ -1,23 +0,0 @@ -# LCD开发指导 - -- [开发步骤](#section3904154911218) - -Display驱动模型基于HDF驱动框架、Platform接口及OSAL接口开发,可以做到不区分OS(LiteOS、Linux)和芯片平台(Hi35xx、Hi38xx、V3S等),为LCD器件提供统一的驱动模型。 - -## 开发步骤 - -1. 添加LCD驱动相关的设备描述配置。 -2. 在SOC平台驱动适配层中适配对应的芯片平台驱动。 -3. 添加器件驱动,并在驱动入口函数Init中注册Panel驱动数据,驱动数据接口主要包括如下接口: - - LCD上下电 - - 根据LCD硬件连接,使用Platform接口层提供的GPIO操作接口操作对应LCD管脚,例如复位管脚、IOVCC管脚,上电时序参考LCD供应商提供的SPEC。 - - - 发送初始化序列 - - 根据LCD硬件接口,使用Platform接口层提供的I2C、SPI、MIPI等接口,下载LCD初始化序列,初始化参数序列可以参考LCD供应商提供的SPEC。 - - -4. 根据需求实现HDF框架其他接口,比如Release接口。 -5. 根据需求使用HDF框架可创建其他设备节点,用于业务逻辑或者调试功能。 - diff --git "a/zh-cn/device-dev/driver/LCD\345\274\200\345\217\221\346\246\202\350\277\260.md" "b/zh-cn/device-dev/driver/LCD\345\274\200\345\217\221\346\246\202\350\277\260.md" deleted file mode 100755 index ab5e824934..0000000000 --- "a/zh-cn/device-dev/driver/LCD\345\274\200\345\217\221\346\246\202\350\277\260.md" +++ /dev/null @@ -1,46 +0,0 @@ -# LCD开发概述 - -- [简介](#section3781515122118) -- [接口说明](#section20280192712120) - -## 简介 - -LCD(Liquid Crystal Display)液晶显示驱动,对LCD进行上电,并通过接口初始化LCD内部寄存器,使LCD正常工作。Display驱动模型基于HDF( Hardware Driver Foundation)[驱动框架](HDF开发概述.md)开发,实现跨OS、跨平台,为LCD硬件提供上下电功能、发送初始化序列功能,使LCD进入正常的工作模式,显示芯片平台侧的图像数据,基于HDF驱动框架的Display驱动模型如[图1](#fig69138814229)。 - -**图 1** 基于HDF驱动框架的Display驱动模型 -![](figures/基于HDF驱动框架的Display驱动模型.png "基于HDF驱动框架的Display驱动模型") - -- **Display驱动模型介绍** - - Display驱动模型主要由平台驱动层、芯片平台适配层、LCD器件驱动层三部分组成。驱动模型基于HDF驱动框架开发,通过Platform层和OSAL层提供的接口,屏蔽内核形态的差异,使得器件驱动可以便利的迁移到不同OS及芯片平台。模型向上对接Display公共hal层,支撑HDI接口的实现,通过Display-HDI(Hardware Display Interface)对图形服务提供各类驱动能力接口。 - - (1)Display平台驱动层:通过HDF提供的IOService数据通道,与公共Hal层对接,集中接收并处理各类上层调用指令; - - (2)SOC平台驱动适配层:借助此SOC适配层,实现Display驱动和SOC侧驱动解耦,主要完成芯片平台相关的参数配置,并传递平台驱动层的调用到器件驱动层; - - (3)LCD器件驱动层:在器件驱动层中,主要实现和器件自身强相关的驱动适配接口,例如发送初始化序列、上下电、背光设置等。 - - 基于Display驱动模型开发LCD驱动,可以借助平台提供的各种能力及接口,较大程度的降低器件驱动的开发周期和难度,提升开发效率。 - - -## 接口说明 - -LCD接口通常可分为MIPI DSI接口、TTL接口和LVDS接口,常用的是MIPI DSI接口和TTL接口,下面对常用的MIPI DSI接口和TTL接口作简要介绍。 - -- MIPI DSI接口 - - **图 2** MIPI DSI接口 - ![](figures/MIPI-DSI接口.png "MIPI-DSI接口") - - MIPI DSI接口是MIPI(移动行业处理器接口)联盟定义的显示接口,主要用于移动终端显示屏接口,接口数据传输遵循MIPI协议,MIPI DSI接口为数据接口,传输图像数据,通常情况下MIPI DSI接口的控制信息以MIPI包形式通过MIPI DSI接口发送到对端IC,不需要额外的外设接口。 - -- TTL接口 - - **图 3** TTL接口 - ![](figures/TTL接口.png "TTL接口") - - TTL(Transistor Transistor Logic)即晶体管-晶体管逻辑,TTL电平信号由TTL器件产生,TTL器件是数字集成电路的一大门类,它采用双极型工艺制造,具有高速度、低功耗和品种多等特点。 - - TTL接口是并行方式传输数据的接口,有数据信号、时钟信号和控制信号(行同步、帧同步、数据有效信号等),在控制信号控制下完成数据传输。通常TTL接口的LCD,内部寄存器读写需要额外的外设接口,比如SPI接口、I2C接口等。 - - diff --git a/zh-cn/device-dev/driver/MIPI-DSI.md b/zh-cn/device-dev/driver/MIPI-DSI.md deleted file mode 100755 index 2dcbddcdd0..0000000000 --- a/zh-cn/device-dev/driver/MIPI-DSI.md +++ /dev/null @@ -1,9 +0,0 @@ -# MIPI DSI - -- **[MIPI DSI概述](MIPI-DSI概述.md)** - -- **[MIPI DSI使用指导](MIPI-DSI使用指导.md)** - -- **[MIPI DSI使用实例](MIPI-DSI使用实例.md)** - - diff --git "a/zh-cn/device-dev/driver/MIPI-DSI\344\275\277\347\224\250\345\256\236\344\276\213.md" "b/zh-cn/device-dev/driver/MIPI-DSI\344\275\277\347\224\250\345\256\236\344\276\213.md" deleted file mode 100755 index 77e9242f30..0000000000 --- "a/zh-cn/device-dev/driver/MIPI-DSI\344\275\277\347\224\250\345\256\236\344\276\213.md" +++ /dev/null @@ -1,98 +0,0 @@ -# MIPI DSI使用实例 - -MIPI-DSI完整的使用示例如下所示: - -``` -#include "hdf.h" -#include "mipi_dsi_if.h" - -void PalMipiDsiTestSample(void) -{ - uint8_t chnId; - int32_t ret; - DevHandle handle = NULL; - - /* 设备通道编号 */ - chnId = 0; - /* 获取操作句柄 */ - handle = MipiDsiOpen(chnId); - if (handle == NULL) { - HDF_LOGE("MipiDsiOpen: failed!\n"); - return; - } - /* 配置相应参数 */ - struct MipiCfg cfg = {0}; - cfg.lane = DSI_4_LANES; - cfg.mode = DSI_CMD_MODE; - cfg.burstMode = VIDEO_NON_BURST_MODE_SYNC_EVENTS; - cfg.format = FORMAT_RGB_24_BIT; - cfg.pixelClk = 174; - cfg.phyDataRate = 384; - cfg.timingInfo.hsaPixels = 50; - cfg.timingInfo.hbpPixels = 55; - cfg.timingInfo.hlinePixels = 1200; - cfg.timingInfo.yResLines = 1800; - cfg.timingInfo.vbpLines = 33; - cfg.timingInfo.vsaLines = 76; - cfg.timingInfo.vfpLines = 120; - cfg.timingInfo.xResPixels = 1342; - /* 写入配置数据 */ - ret = MipiDsiSetCfg(g_handle, &cfg); - if (ret != 0) { - HDF_LOGE("%s: SetMipiCfg fail! ret=%d\n", __func__, ret); - return; - } - /* 发送PANEL初始化指令 */ - struct DsiCmdDesc *cmd = OsalMemCalloc(sizeof(struct DsiCmdDesc)); - if (cmd == NULL) { - return; - } - cmd->dtype = DTYPE_DCS_WRITE; - cmd->dlen = 1; - cmd->payload = OsalMemCalloc(sizeof(uint8_t)); - if (cmd->payload == NULL) { - HdfFree(cmd); - return; - } - *(cmd->payload) = DTYPE_GEN_LWRITE; - MipiDsiSetLpMode(mipiHandle); - ret = MipiDsiTx(mipiHandle, cmd); - MipiDsiSetHsMode(mipiHandle); - if (ret != HDF_SUCCESS) { - HDF_LOGE("%s: MipiDsiTx fail! ret=%d\n", __func__, ret); - HdfFree(cmd->payload); - HdfFree(cmd); - return; - } - HdfFree(cmd->payload); - HdfFree(cmd); - /* 回读panel状态寄存器 */ - uint8_t readVal = 0; - struct DsiCmdDesc *cmdRead = OsalMemCalloc(sizeof(struct DsiCmdDesc)); - if (cmdRead == NULL) { - return; - } - cmdRead->dtype = DTYPE_DCS_READ; - cmdRead->dlen = 1; - cmdRead->payload = OsalMemCalloc(sizeof(uint8_t)); - if (cmdRead->payload == NULL) { - HdfFree(cmdRead); - return; - } - *(cmdRead->payload) = DDIC_REG_STATUS; - MipiDsiSetLpMode(g_handle); - ret = MipiDsiRx(g_handle, cmdRead, sizeof(readVal), &readVal); - MipiDsiSetHsMode(g_handle); - if (ret != HDF_SUCCESS) { - HDF_LOGE("%s: MipiDsiRx fail! ret=%d\n", __func__, ret); - HdfFree(cmdRead->payload); - HdfFree(cmdRead); - return; - } - HdfFree(cmdRead->payload); - HdfFree(cmdRead); - /* 释放MIPI DSI设备句柄 */ - MipiDsiClose(handle); -} -``` - diff --git "a/zh-cn/device-dev/driver/MIPI-DSI\344\275\277\347\224\250\346\214\207\345\257\274.md" "b/zh-cn/device-dev/driver/MIPI-DSI\344\275\277\347\224\250\346\214\207\345\257\274.md" deleted file mode 100755 index 58603da99a..0000000000 --- "a/zh-cn/device-dev/driver/MIPI-DSI\344\275\277\347\224\250\346\214\207\345\257\274.md" +++ /dev/null @@ -1,365 +0,0 @@ -# MIPI DSI使用指导 - -- [使用流程](#section8982671284) -- [获取MIPI-DSI操作句柄](#section57982569176) -- [MIPI-DSI相应配置](#section5935410201815) -- [发送/回读控制指令](#section611661316194) -- [释放MIPI-DSI操作句柄](#section217313211199) - -## 使用流程 - -使用MIPI-DSI的一般流程如[图1](#fig99821771782)所示。 - -**图 1** MIPI-DSI使用流程图 - - -![](figures/zh-cn_image_0000001072553354.png) - -## 获取MIPI-DSI操作句柄 - -在进行MIPI-DSI进行通信前,首先要调用MipiDsiOpen获取操作句柄,该函数会返回指定通道ID的操作句柄。 - -DevHandle MipiDsiOpen\(uint8\_t id\); - -**表 1** MipiDsiOpen的参数和返回值描述 - - - - - - - - - - - - - - - - - - -

    参数

    -

    参数描述

    -

    id

    -

    MIPI DSI通道ID

    -

    返回值

    -

    返回值描述

    -

    NULL

    -

    获取失败

    -

    设备句柄

    -

    获取到指令通道的操作句柄, 类型为DevHandle

    -
    - -假设系统中的MIPI-DSI通道为0,获取该通道操作句柄的示例如下: - -``` -DevHandle mipiDsiHandle = NULL; /* 设备句柄 */ -chnId = 0; /* MIPI-DSI通道ID */ - -/* 获取操作句柄 */ -mipiDsiHandle = MipiDsiOpen(chnId); -if (mipiDsiHandle == NULL) { - HDF_LOGE("MipiDsiOpen: failed\n"); - return; -} -``` - -## MIPI-DSI相应配置 - -- 写入MIPI-DSI配置 - -int32\_t MipiDsiSetCfg\(DevHandle handle, struct MipiCfg \*cfg\); - -**表 2** MipiDsiSetCfg的参数和返回值描述 - - - - - - - - - - - - - - - - - - - - - -

    参数

    -

    参数描述

    -

    handle

    -

    操作句柄

    -

    cfg

    -

    MIPI-DSI相应配置buf 指针

    -

    返回值

    -

    返回值描述

    -

    0

    -

    设置成功

    -

    负数

    -

    设置失败

    -
    - -``` -int32_t ret; -struct MipiCfg cfg = {0}; - -/* 当前对接的屏幕配置如下 */ -cfg.lane = DSI_4_LANES; -cfg.mode = DSI_CMD_MODE; -cfg.burstMode = VIDEO_NON_BURST_MODE_SYNC_EVENTS; -cfg.format = FORMAT_RGB_24_BIT; -cfg.pixelClk = 174; -cfg.phyDataRate = 384; -cfg.timingInfo.hsaPixels = 50; -cfg.timingInfo.hbpPixels = 55; -cfg.timingInfo.hlinePixels = 1200; -cfg.timingInfo.yResLines = 1800; -cfg.timingInfo.vbpLines = 33; -cfg.timingInfo.vsaLines = 76; -cfg.timingInfo.vfpLines = 120; -cfg.timingInfo.xResPixels = 1342; -/* 写入配置数据 */ -ret = MipiDsiSetCfg(g_handle, &cfg); -if (ret != 0) { - HDF_LOGE("%s: SetMipiCfg fail! ret=%d\n", __func__, ret); - return -1; -} -``` - -- 获取当前MIPI-DSI的配置 - -int32\_t MipiDsiGetCfg\(DevHandle handle, struct MipiCfg \*cfg\); - -**表 3** MipiDsiGetCfg的参数和返回值描述 - - - - - - - - - - - - - - - - - - - - - -

    参数

    -

    参数描述

    -

    handle

    -

    操作句柄

    -

    cfg

    -

    MIPI-DSI相应配置buf 指针

    -

    返回值

    -

    返回值描述

    -

    0

    -

    获取成功

    -

    负数

    -

    获取失败

    -
    - -``` -int32_t ret; -struct MipiCfg cfg; -memset(&cfg, 0, sizeof(struct MipiCfg)); -ret = MipiDsiGetCfg(g_handle, &cfg); -if (ret != HDF_SUCCESS) { - HDF_LOGE("%s: GetMipiCfg fail!\n", __func__); - return HDF_FAILURE; -} -``` - -## 发送/回读控制指令 - -- 发送指令 - -int32\_t MipiDsiTx\(PalHandle handle, struct DsiCmdDesc \*cmd\); - -**表 4** MipiDsiTx的参数和返回值描述 - - - - - - - - - - - - - - - - - - - - - -

    参数

    -

    参数描述

    -

    handle

    -

    操作句柄

    -

    cmd

    -

    需要发送的指令数据指针

    -

    返回值

    -

    返回值描述

    -

    0

    -

    发送成功

    -

    负数

    -

    发送失败

    -
    - -``` -int32_t ret; -struct DsiCmdDesc *cmd = OsalMemCalloc(sizeof(struct DsiCmdDesc)); -if (cmd == NULL) { - return HDF_FAILURE; -} -cmd->dtype = DTYPE_DCS_WRITE; -cmd->dlen = 1; -cmd->payload = OsalMemCalloc(sizeof(uint8_t)); -if (cmd->payload == NULL) { - HdfFree(cmd); - return HDF_FAILURE; -} -*(cmd->payload) = DTYPE_GEN_LWRITE; -MipiDsiSetLpMode(mipiHandle); -ret = MipiDsiTx(mipiHandle, cmd); -MipiDsiSetHsMode(mipiHandle); -if (ret != HDF_SUCCESS) { - HDF_LOGE("%s: PalMipiDsiTx fail! ret=%d\n", __func__, ret); - HdfFree(cmd->payload); - HdfFree(cmd); - return HDF_FAILURE; -} -HdfFree(cmd->payload); -HdfFree(cmd); -``` - -- 回读指令 - -int32\_t MipiDsiRx\(DevHandle handle, struct DsiCmdDesc \*cmd, uint32\_t readLen, uint8\_t \*out\); - -**表 5** MipiDsiRx的参数和返回值描述 - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    参数

    -

    参数描述

    -

    handle

    -

    操作句柄

    -

    cmd

    -

    需要回读的指令数据指针

    -

    readLen

    -

    期望回读的数据长度

    -

    out

    -

    回读的数据buf指针

    -

    返回值

    -

    返回值描述

    -

    0

    -

    获取成功

    -

    负数

    -

    获取失败

    -
    - -``` -int32_t ret; -uint8_t readVal = 0; - -struct DsiCmdDesc *cmdRead = OsalMemCalloc(sizeof(struct DsiCmdDesc)); -if (cmdRead == NULL) { - return HDF_FAILURE; -} -cmdRead->dtype = DTYPE_DCS_READ; -cmdRead->dlen = 1; -cmdRead->payload = OsalMemCalloc(sizeof(uint8_t)); -if (cmdRead->payload == NULL) { - HdfFree(cmdRead); - return HDF_FAILURE; -} -*(cmdRead->payload) = DDIC_REG_STATUS; -MipiDsiSetLpMode(g_handle); -ret = MipiDsiRx(g_handle, cmdRead, sizeof(readVal), &readVal); -MipiDsiSetHsMode(g_handle); -if (ret != HDF_SUCCESS) { - HDF_LOGE("%s: MipiDsiRx fail! ret=%d\n", __func__, ret); - HdfFree(cmdRead->payload); - HdfFree(cmdRead); - return HDF_FAILURE; -} -HdfFree(cmdRead->payload); -HdfFree(cmdRead); -``` - -## 释放MIPI-DSI操作句柄 - -MIPI-DSI使用完成之后,需要释放操作句柄,释放句柄的函数如下所示: - -void MipiDsiClose\(DevHandle handle\); - -该函数会释放掉由MipiDsiOpen申请的资源。 - -**表 6** MipiDsiClose的参数和返回值描述 - - - - - - - - - - -

    参数

    -

    参数描述

    -

    handle

    -

    MIPI-DSI操作句柄

    -
    - -``` -MipiDsiClose(mipiHandle); /* 释放掉MIPI-DSI操作句柄 */ -``` - diff --git "a/zh-cn/device-dev/driver/MIPI-DSI\346\246\202\350\277\260.md" "b/zh-cn/device-dev/driver/MIPI-DSI\346\246\202\350\277\260.md" deleted file mode 100755 index 5af73287eb..0000000000 --- "a/zh-cn/device-dev/driver/MIPI-DSI\346\246\202\350\277\260.md" +++ /dev/null @@ -1,84 +0,0 @@ -# MIPI DSI概述 - -- [简介](#section1369320102013) -- [接口说明](#section6577545192317) - -## 简介 - -- DSI(Display Serial Interface)是由移动行业处理器接口联盟(Mobile Industry Processor Interface \(MIPI\) Alliance)制定的规范,旨在降低移动设备中显示控制器的成本。它以串行的方式发送像素数据或指令给外设\(通常是LCD或者类似的显示设备\),或从外设中读取状态信息或像素信息;它定义了主机、图像数据源和目标设备之间的串行总线和通信协议。 - -- MIPI-DSI具备高速模式和低速模式两种工作模式,全部数据通道都可以用于单向的高速传输,但只有第一个数据通道才可用于低速双向传输,从属端的状态信息、像素等是通过该数据通道返回。时钟通道专用于在高速传输数据的过程中传输同步时钟信号。 - - 图1显示了简化的DSI接口。从概念上看,符合DSI的接口与基于DBI-2和DPI-2标准的接口具有相同的功能。它向外围设备传输像素或命令数据,并且可以从外围设备读取状态或像素信息。主要区别在于,DSI对所有像素数据、命令和事件进行序列化,而在传统接口中,这些像素数据、命令和事件通常需要附加控制信号才能在并行数据总线上传输。 - - **图 1** DSI发送、接收接口 - ![](figures/DSI发送-接收接口.png "DSI发送-接收接口") - - - -## 接口说明 - -**表 1** MIPI-DSI API接口功能介绍 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    功能分类

    -

    接口名

    -

    描述

    -

    设置/获取当前MIPI-DSI相关配置

    -

    MipiDsiSetCfg

    -

    设置MIPI-DSI相关配置

    -

    MipiDsiGetCfg

    -

    获取当前MIPI-DSI相关配置

    -

    获取/释放MIPI-DSI操作句柄

    -

    MipiDsiOpen

    -

    获取MIPI-DSI操作句柄

    -

    MipiDsiClose

    -

    释放MIPI-DSI操作句柄

    -

    设置MIPI-DSI进入Low power模式/High speed模式

    -

    MipiDsiSetLpMode

    -

    设置MIPI-DSI进入Low power模式

    -

    MipiDsiSetHsMode

    -

    设置MIPI-DSI进入High speed模式

    -

    MIPI-DSI发送/回读指令

    -

    MipiDsiTx

    -

    MIPI-DSI发送相应指令的接口

    -

    MipiDsiRx

    -

    MIPI-DSI按期望长度回读的接口

    -
    - ->![](public_sys-resources/icon-note.gif) **说明:** ->本文涉及的所有接口,仅限内核态使用,不支持在用户态使用 - diff --git a/zh-cn/device-dev/driver/RTC.md b/zh-cn/device-dev/driver/RTC.md deleted file mode 100755 index de745a39f9..0000000000 --- a/zh-cn/device-dev/driver/RTC.md +++ /dev/null @@ -1,9 +0,0 @@ -# RTC - -- **[RTC概述](RTC概述.md)** - -- **[RTC使用指导](RTC使用指导.md)** - -- **[RTC使用实例](RTC使用实例.md)** - - diff --git "a/zh-cn/device-dev/driver/RTC\344\275\277\347\224\250\345\256\236\344\276\213.md" "b/zh-cn/device-dev/driver/RTC\344\275\277\347\224\250\345\256\236\344\276\213.md" deleted file mode 100755 index d413efda41..0000000000 --- "a/zh-cn/device-dev/driver/RTC\344\275\277\347\224\250\345\256\236\344\276\213.md" +++ /dev/null @@ -1,97 +0,0 @@ -# RTC使用实例 - -本实例提供RTC接口的完整使用流程: - -1. 系统启动,驱动管理模块会识别系统当前的RTC器件; -2. 驱动管理模块完成RTC设备的初始化和设备创建; -3. 用户通过不同API,对该RTC设备进行对应的操作; -4. 关闭RTC设备,释放设备资源。 - -示例如下: - -``` -#include "rtc_if.h" -int32_t RtcAlarmACallback(enum RtcAlarmIndex alarmIndex) -{ - if (alarmIndex == RTC_ALARM_INDEX_A) { - /* 报警A的处理 */ - printf("RTC Alarm A callback function\n\r"); - } else if (alarmIndex == RTC_ALARM_INDEX_B) { - /* 报警B的处理 */ - printf("RTC Alarm B callback function\n\r"); - } else { - /* 错误处理 */ - } - return 0; -} - -void RtcTestSample(void) -{ - int32_t ret; - struct RtcTime tm; - struct RtcTime alarmTime; - uint32_t freq; - DevHandle handle = NULL; - - /* 获取RTC设备句柄 */ - handle = RtcOpen(); - if (handle == NULL) { - /* 错误处理 */ - } - /* 注册报警A的定时回调函数 */ - ret = RtcRegisterAlarmCallback(handle, RTC_ALARM_INDEX_A, RtcAlarmACallback); - if (ret != 0) { - /* 错误处理 */ - } - /* 设置RTC外接晶体振荡频率,注意按照器件手册要求配置RTC外频 */ - freq = 32768; /* 32768 Hz */ - ret = RtcSetFreq(handle, freq); - if (ret != 0) { - /* 错误处理 */ - } - /* 设置RTC报警中断使能 */ - ret = RtcAlarmInterruptEnable(handle, RTC_ALARM_INDEX_A, 1); - if (ret != 0) { - /* 错误处理 */ - } - /* 设置RTC时间为2020/01/01 00:00:10 .990 */ - tm.year = 2020; - tm.month = 01; - tm.day = 01; - tm.hour= 0; - tm.minute = 0; - tm.second = 10; - tm.millisecond = 990; - /* 写RTC时间信息 */ - ret = RtcWriteTime(handle, &tm); - if (ret != 0) { - /* 错误处理 */ - } - /* 设置RTC报警时间为2020/01/01 00:00:30 .100 */ - alarmTime.year = 2020; - alarmTime.month = 01; - alarmTime.day = 01; - alarmTime.hour = 0; - alarmTime.minute = 0; - alarmTime.second = 30; - alarmTime.millisecond = 100; - /* 设置RTC_ALARM_INDEX_A索引定时报警时间信息, 定时时间到后会打印"RTC Alarm A callback function" */ - ret = RtcWriteAlarm(handle, RTC_ALARM_INDEX_A, &alarmTime); - if (ret != 0) { - /* 错误处理 */ - } - - /* 读取RTC实时时间 */ - ret = RtcReadTime(handle, &tm); - if (ret != 0) { - /* 错误处理 */ - } - sleep(5) - printf("RTC read time:\n\r"); - printf("year-month-date-weekday hour:minute:second .millisecond %04u-%02u-%02u-%u %02u:%02u:%02u .%03u", - tm.year, tm.month, tm.day, tm.weekday, tm.hour, tm.minute, tm.second, tm.millisecond); - /* 销毁RTC设备句柄 */ - RtcClose(handle); -} -``` - diff --git "a/zh-cn/device-dev/driver/RTC\344\275\277\347\224\250\346\214\207\345\257\274.md" "b/zh-cn/device-dev/driver/RTC\344\275\277\347\224\250\346\214\207\345\257\274.md" deleted file mode 100755 index 45065165bd..0000000000 --- "a/zh-cn/device-dev/driver/RTC\344\275\277\347\224\250\346\214\207\345\257\274.md" +++ /dev/null @@ -1,741 +0,0 @@ -# RTC使用指导 - -- [使用流程](#section620515765714) -- [创建RTC设备句柄](#section0702183665711) -- [销毁RTC设备句柄](#section639962619542) -- [注册RTC定时报警回调函数](#section123631358135713) -- [操作RTC](#section11091522125812) - -## 使用流程 - -在操作系统启动过程中,驱动管理模块根据配置文件加载RTC驱动,RTC驱动会检测RTC器件并初始化驱动。 - -使用RTC设备的一般流程如[图1](#fig166181128151112)所示。 - -**图 1** RTC设备使用流程图 - - -![](figures/zh-cn_image_0000001054728498.png) - -## 创建RTC设备句柄 - -RTC驱动加载成功后,驱动开发者使用驱动框架提供的查询接口并调用RTC设备驱动接口。 - ->![](public_sys-resources/icon-note.gif) **说明:** ->当前操作系统支持一个RTC设备。 - -DevHandle RtcOpen\(void\); - -**表 1** RtcOpen参数和返回值描述 - - - - - - - - - - - - - - - - - - -

    参数

    -

    参数描述

    -

    void

    -

    NA

    -

    返回值

    -

    返回值描述

    -

    handle

    -

    操作成功返回 指针类型

    -

    NULL

    -

    操作失败

    -
    - -``` -DevHandle handle = NULL; - -/* 获取RTC句柄 */ -handle = RtcOpen(); -if (handle == NULL) { - /* 错误处理 */ -} -``` - -## 销毁RTC设备句柄 - -销毁RTC设备句柄,系统释放对应的资源。 - -void RtcClose\(DevHandle handle\); - -**表 2** RtcClose参数描述 - - - - - - - - - -

    参数

    -

    参数描述

    -

    handle

    -

    RTC设备句柄

    -
    - -``` -/* 销毁RTC句柄 */ -RtcClose(handle); -``` - -## 注册RTC定时报警回调函数 - -系统启动后需要注册RTC定时报警回调函数,报警超时后触发回调函数。 - -int32\_t RtcRegisterAlarmCallback\(DevHandle handle, enum RtcAlarmIndex alarmIndex, RtcAlarmCallback cb\); - -**表 3** RtcRegisterAlarmCallback参数和返回值描述 - - - - - - - - - - - - - - - - - - - - - - - - - -

    参数

    -

    参数描述

    -

    handle

    -

    RTC设备句柄

    -

    alarmIndex

    -

    报警索引

    -

    cb

    -

    定时报警回调函数

    -

    返回值

    -

    返回值描述

    -

    0

    -

    操作成功

    -

    负数

    -

    操作失败

    -
    - -注册RTC\_ALARM\_INDEX\_A的定时报警处理函数, 示例如下: - -``` -/* 用户注册RTC定时报警回调函数的方法 */ -int32_t RtcAlarmACallback(enum RtcAlarmIndex alarmIndex) -{ - if (alarmIndex == RTC_ALARM_INDEX_A) { - /* 报警A的处理 */ - } else if (alarmIndex == RTC_ALARM_INDEX_B) { - /* 报警B的处理 */ - } else { - /* 错误处理 */ - } - return 0; -} -int32_t ret; -/* 注册报警A的定时回调函数 */ -ret = RtcRegisterAlarmCallback(handle, RTC_ALARM_INDEX_A, RtcAlarmACallback); -if (ret != 0) { - /* 错误处理 */ -} -``` - -## 操作RTC - -- 读取RTC时间。 - -系统从RTC读取时间信息,包括年、月、星期、日、时、分、秒、毫秒,则可以通过以下函数完成: - -int32\_t RtcReadTime\(DevHandle handle, struct RtcTime \*time\); - -**表 4** RtcReadTime参数和返回值描述 - - - - - - - - - - - - - - - - - - - - - -

    参数

    -

    参数描述

    -

    handle

    -

    RTC设备句柄

    -

    time

    -

    RTC读取时间信息,包括年、月、星期、日、时、分、秒、毫秒

    -

    返回值

    -

    返回值描述

    -

    0

    -

    操作成功

    -

    负数

    -

    操作失败

    -
    - -``` -int32_t ret; -struct RtcTime tm; - -/* 系统从RTC读取时间信息 */ -ret = RtcReadTime(handle, &tm); -if (ret != 0) { - /* 错误处理 */ -} -``` - -- 设置RTC时间 - -设置RTC时间,则可以通过以下函数完成: - -int32\_t RtcWriteTime\(DevHandle handle, struct RtcTime \*time\); - -**表 5** RtcWriteTime参数和返回值描述 - - - - - - - - - - - - - - - - - - - - - -

    参数

    -

    参数描述

    -

    handle

    -

    RTC设备句柄

    -

    time

    -

    写RTC时间信息,包括年、月、星期、日、时、分、秒、毫秒

    -

    返回值

    -

    返回值描述

    -

    0

    -

    操作成功

    -

    负数

    -

    操作失败

    -
    - ->![](public_sys-resources/icon-note.gif) **说明:** ->RTC起始时间为UTC 1970/01/01 Thursday 00:00:00,年的最大取值按照用户器件手册要求计算配置,星期不用配置。 - -``` -int32_t ret; -struct RtcTime tm; - -/* 设置RTC时间为 UTC 2020/01/01 00:59:00 .000 */ -tm.year = 2020; -tm.month = 01; -tm.day = 01; -tm.hour= 00; -tm.minute = 59; -tm.second = 00; -tm.millisecond = 0; -/* 写RTC时间信息 */ -ret = RtcWriteTime(handle, &tm); -if (ret != 0) { - /* 错误处理 */ -} -``` - -- 读取RTC报警时间 - -如果需要读取定时报警时间,则可以通过以下函数完成: - -int32\_t RtcReadAlarm\(DevHandle handle, enum RtcAlarmIndex alarmIndex, struct RtcTime \*time\); - -**表 6** RtcReadAlarm参数和返回值描述 - - - - - - - - - - - - - - - - - - - - - - - - -

    参数

    -

    参数描述

    -

    handle

    -

    RTC设备句柄

    -

    alarmIndex

    -

    报警索引

    -

    time

    -

    RTC报警时间信息,包括年、月、星期、日、时、分、秒、毫秒

    -

    返回值

    -

    返回值描述

    -

    0

    -

    操作成功

    -

    负数

    -

    操作失败

    -
    - -``` -int32_t ret; -struct RtcTime alarmTime; - -/* 读RTC_ALARM_INDEX_A索引的RTC定时报警时间信息 */ -ret = RtcReadAlarm(handle, RTC_ALARM_INDEX_A, &alarmTime); -if (ret != 0) { - /* 错误处理 */ -} -``` - -- 设置RTC报警时间 - -根据报警索引设置RTC报警时间,通过以下函数完成: - -int32\_t RtcWriteAlarm\(DevHandle handle, enum RtcAlarmIndex alarmIndex, struct RtcTime \*time\); - -**表 7** RtcWriteAlarm参数和返回值描述 - - - - - - - - - - - - - - - - - - - - - - - - -

    参数

    -

    参数描述

    -

    handle

    -

    RTC设备句柄

    -

    alarmIndex

    -

    报警索引

    -

    time

    -

    RTC报警时间信息,包括年、月、星期、日、时、分、秒、毫秒

    -

    返回值

    -

    返回值描述

    -

    0

    -

    操作成功

    -

    负数

    -

    操作失败

    -
    - ->![](public_sys-resources/icon-note.gif) **说明:** ->RTC起始时间为UTC 1970/01/01 Thursday 00:00:00,年的最大取值按照用户器件手册要求计算配置,星期不用配置。 - -``` -int32_t ret; -struct RtcTime alarmTime; - -/* 设置RTC报警时间为2020/01/01 00:59:59 .000 */ -alarmTime.year = 2020; -alarmTime.month = 01; -alarmTime.day = 01; -alarmTime.hour = 00; -alarmTime.minute = 59; -alarmTime.second = 59; -alarmTime.millisecond = 0; -/* 设置RTC_ALARM_INDEX_A索引的定时报警时间 */ -ret = RtcWriteAlarm(handle, RTC_ALARM_INDEX_A, &alarmTime); -if (ret != 0) { - /* 错误处理 */ -} -``` - -- 设置定时报警中断使能或去使能 - -在启动报警操作前,需要先设置报警中断使能,报警超时后会触发告警回调函数,可以通过以下函数完成: - -int32\_t RtcAlarmInterruptEnable\(DevHandle handle, enum RtcAlarmIndex alarmIndex, uint8\_t enable\); - -**表 8** RtcAlarmInterruptEnable参数和返回值描述 - - - - - - - - - - - - - - - - - - - - - - - - -

    参数

    -

    参数描述

    -

    handle

    -

    RTC设备句柄

    -

    alarmIndex

    -

    报警索引

    -

    enable

    -

    RTC报警中断配置,1:使能,0:去使能

    -

    返回值

    -

    返回值描述

    -

    0

    -

    操作成功

    -

    负数

    -

    操作失败

    -
    - -``` -int32_t ret; - -/* 设置RTC报警中断使能 */ -ret = RtcAlarmInterruptEnable(handle, RTC_ALARM_INDEX_A, 1); -if (ret != 0) { - /* 错误处理 */ -} -``` - -- 读取RTC外频 - -读取RTC外接晶体振荡频率,可以通过以下函数完成: - -int32\_t RtcGetFreq\(DevHandle handle, uint32\_t \*freq\); - -**表 9** RtcGetFreq参数和返回值描述 - - - - - - - - - - - - - - - - - - - - - -

    参数

    -

    参数描述

    -

    handle

    -

    RTC设备句柄

    -

    freq

    -

    RTC的外接晶体振荡频率,单位(HZ)

    -

    返回值

    -

    返回值描述

    -

    0

    -

    操作成功

    -

    负数

    -

    操作失败

    -
    - -``` -int32_t ret; -uint32_t freq = 0; - -/* 读取RTC外接晶体振荡频率 */ -ret = RtcGetFreq(handle, &freq); -if (ret != 0) { - /* 错误处理 */ -} -``` - -- 配置RTC外频 - -配置RTC外接晶体振荡频率,可以通过以下函数完成: - -int32\_t RtcSetFreq\(DevHandle handle, uint32\_t freq\); - -**表 10** RtcSetFreq参数和返回值描述 - - - - - - - - - - - - - - - - - - - - - -

    参数

    -

    参数描述

    -

    handle

    -

    RTC设备句柄

    -

    freq

    -

    RTC的外接晶体振荡频率,单位(HZ)

    -

    返回值

    -

    返回值描述

    -

    0

    -

    操作成功

    -

    负数

    -

    操作失败

    -
    - -``` -int32_t ret; -uint32_t freq = 32768; /* 32768 Hz */ - -/* 设置RTC外接晶体振荡频率,注意按照器件手册要求配置RTC外频 */ -ret = RtcSetFreq(handle, freq); -if (ret != 0) { - /* 错误处理 */ -} -``` - -- 复位RTC - -复位RTC,复位RTC后各配置寄存器恢复默认值,可以通过以下函数完成: - -int32\_t RtcReset\(DevHandle handle\); - -**表 11** RtcReset参数和返回值描述 - - - - - - - - - - - - - - - - - - -

    参数

    -

    参数描述

    -

    handle

    -

    RTC设备句柄

    -

    返回值

    -

    返回值描述

    -

    0

    -

    操作成功

    -

    负数

    -

    操作失败

    -
    - -``` -int32_t ret; - -/* 复位RTC,复位RTC后各配置寄存器恢复默认值 */ -ret = RtcReset(handle); -if (ret != 0) { - /* 错误处理 */ -} -``` - -- 读取RTC自定义寄存器配置 - -按照用户定义的寄存器索引,读取对应的寄存器配置,一个索引对应一字节的配置值,通过以下函数完成: - -int32\_t RtcReadReg\(DevHandle handle, uint8\_t usrDefIndex, uint8\_t \*value\); - -**表 12** RtcReadReg参数和返回值描述 - - - - - - - - - - - - - - - - - - - - - - - - -

    参数

    -

    参数描述

    -

    handle

    -

    RTC设备句柄

    -

    usrDefIndex

    -

    用户定义的寄存器对应索引

    -

    value

    -

    寄存器值

    -

    返回值

    -

    返回值描述

    -

    0

    -

    操作成功

    -

    负数

    -

    操作失败

    -
    - -``` -int32_t ret; -uint8_t usrDefIndex = 0; /* 定义0索引对应用户定义的第一个寄存器*/ -uint8_t value = 0; - -/* 按照用户定义的寄存器索引,读取对应的寄存器配置,一个索引对应一字节的配置值 */ -ret = RtcReadReg(handle, usrDefIndex, &value); -if (ret != 0) { - /* 错误处理 */ -} -``` - -- 设置RTC自定义寄存器配置 - -按照用户定义的寄存器索引,设置对应的寄存器配置,一个索引对应一字节的配置值,通过以下函数完成: - -int32\_t RtcWriteReg\(DevHandle handle, uint8\_t usrDefIndex, uint8\_t value\); - -**表 13** RtcWriteReg参数和返回值描述 - - - - - - - - - - - - - - - - - - - - - - - - -

    参数

    -

    参数描述

    -

    handle

    -

    RTC设备句柄

    -

    usrDefIndex

    -

    用户定义的寄存器对应索引

    -

    value

    -

    寄存器值

    -

    返回值

    -

    返回值描述

    -

    0

    -

    操作成功

    -

    负数

    -

    操作失败

    -
    - -``` -int32_t ret; -uint8_t usrDefIndex = 0; /* 定义0索引对应用户定义第一个寄存器*/ -uint8_t value = 0x10; - -/* 按照用户的定义的寄存器索引,设置对应的寄存器配置,一个索引对应一字节的配置值 */ -ret = RtcWriteReg(handle, usrDefIndex, value); -if (ret != 0) { - /* 错误处理 */ -} -``` - diff --git "a/zh-cn/device-dev/driver/RTC\346\246\202\350\277\260.md" "b/zh-cn/device-dev/driver/RTC\346\246\202\350\277\260.md" deleted file mode 100755 index 19b903394c..0000000000 --- "a/zh-cn/device-dev/driver/RTC\346\246\202\350\277\260.md" +++ /dev/null @@ -1,103 +0,0 @@ -# RTC概述 - -- [简介](#section104842041574) -- [接口说明](#section16892932155715) - -## 简介 - -RTC\(real-time clock\)为操作系统中的实时时钟设备,为操作系统提供精准的实时时间和定时报警功能。当设备下电后,通过外置电池供电,RTC继续记录操作系统时间;设备上电后,RTC提供实时时钟给操作系统,确保断电后系统时间的连续性。 - -## 接口说明 - -**表 1** RTC设备API接口功能介绍 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    功能分类

    -

    接口名

    -

    描述

    -

    RTC句柄操作

    -

    RtcOpen

    -

    获取RTC设备驱动句柄

    -

    RtcClose

    -

    释放RTC设备驱动句柄

    -

    RTC时间操作接口

    -

    RtcReadTime

    -

    读RTC时间信息,包括年、月、星期、日、时、分、秒、毫秒

    -

    RtcWriteTime

    -

    写RTC时间信息,包括年、月、星期、日、时、分、秒、毫秒

    -

    RTC报警操作接口

    -

    RtcReadAlarm

    -

    读RTC报警时间信息

    -

    RtcWriteAlarm

    -

    写RTC报警时间信息

    -

    RtcRegisterAlarmCallback

    -

    注册报警超时回调函数

    -

    RtcAlarmInterruptEnable

    -

    使能/去使能RTC报警中断

    -

    RTC配置操作

    -

    RtcGetFreq

    -

    读RTC外接晶振频率

    -

    RtcSetFreq

    -

    配置RTC外接晶振频率

    -

    RtcReset

    -

    RTC复位

    -

    读写用户定义寄存器

    -

    RtcReadReg

    -

    读用户自定义寄存器

    -

    RtcWriteReg

    -

    写用户自定义寄存器

    -
    - ->![](public_sys-resources/icon-note.gif) **说明:** ->本文涉及的所有接口,仅限内核态使用,不支持在用户态使用。 - diff --git a/zh-cn/device-dev/driver/Readme-CN.md b/zh-cn/device-dev/driver/Readme-CN.md index f86ff0362e..39991f33ca 100755 --- a/zh-cn/device-dev/driver/Readme-CN.md +++ b/zh-cn/device-dev/driver/Readme-CN.md @@ -1,73 +1,24 @@ -# 驱动 - -- [HDF驱动框架](HDF驱动框架.md) - - [HDF开发概述](HDF开发概述.md) - - [驱动开发](驱动开发.md) - - [驱动服务管理](驱动服务管理.md) - - [驱动消息机制管理](驱动消息机制管理.md) - - [配置管理](配置管理.md) - - [HDF开发实例](HDF开发实例.md) - -- [驱动平台](驱动平台.md) - - [GPIO](GPIO.md) - - [GPIO概述](GPIO概述.md) - - [GPIO使用指导](GPIO使用指导.md) - - [GPIO使用实例](GPIO使用实例.md) - - - [I2C](I2C.md) - - [I2C概述](I2C概述.md) - - [I2C使用指导](I2C使用指导.md) - - [I2C使用实例](I2C使用实例.md) - - - [RTC](RTC.md) - - [RTC概述](RTC概述.md) - - [RTC使用指导](RTC使用指导.md) - - [RTC使用实例](RTC使用实例.md) - - - [SDIO](SDIO.md) - - [SDIO概述](SDIO概述.md) - - [SDIO使用指导](SDIO使用指导.md) - - [SDIO使用实例](SDIO使用实例.md) - - - [SPI](SPI.md) - - [SPI概述](SPI概述.md) - - [SPI使用指导](SPI使用指导.md) - - [SPI使用实例](SPI使用实例.md) - - - [UART](UART.md) - - [UART概述](UART概述.md) - - [UART使用指导](UART使用指导.md) - - [UART使用实例](UART使用实例.md) - - - [WATCHDOG](WATCHDOG.md) - - [看门狗概述](看门狗概述.md) - - [看门狗使用指导](看门狗使用指导.md) - - [看门狗使用实例](看门狗使用实例.md) - - - [MIPI DSI](MIPI-DSI.md) - - [MIPI DSI概述](MIPI-DSI概述.md) - - [MIPI DSI使用指导](MIPI-DSI使用指导.md) - - [MIPI DSI使用实例](MIPI-DSI使用实例.md) - -- [外设](外设.md) - - [LCD](LCD.md) - - [LCD开发概述](LCD开发概述.md) - - [LCD开发指导](LCD开发指导.md) - - [LCD开发实例](LCD开发实例.md) - - - [TOUCHSCREEN](TOUCHSCREEN.md) - - [Touchscreen开发概述](Touchscreen开发概述.md) - - [Touchscreen开发指导](Touchscreen开发指导.md) - - [Touchscreen开发实例](Touchscreen开发实例.md) - - - [SENSOR](SENSOR.md) - - [传感器驱动开发概述](传感器驱动开发概述.md) - - [传感器驱动开发指导](传感器驱动开发指导.md) - - [传感器驱动开发实例](传感器驱动开发实例.md) - - [传感器驱动测试指导](传感器驱动测试指导.md) - - - [WLAN](WLAN.md) - - [WLAN开发概述](WLAN开发概述.md) - - [WLAN开发指导](WLAN开发指导.md) - - [WLAN开发实例](WLAN开发实例.md) +# 驱动使用指南 + +- [HDF驱动框架](drive.md) + - [HDF开发概述](drive-hdf-overview.md) + - [驱动开发](drive-hdf-development.md) + - [驱动服务管理](drive-hdf-servicemanage.md) + - [驱动消息机制管理](drive-hdf-news.md) + - [配置管理](drive-hdf-manage.md) + - [HDF开发实例](drive-hdf-sample.md) +- [平台驱动](drive-platform.md) + - [GPIO](drive-platform-gpio-des.md) + - [I2C](drive-platform-i2c-des.md) + - [RTC](drive-platform-rtc-des.md) + - [SDIO](drive-platform-sdio-des.md) + - [SPI](drive-platform-spi-des.md) + - [UART](drive-platform-uart-des.md) + - [WATCHDOG](drive-platform-watchdog-des.md) + - [MIPI DSI](drive-platform-mipidsi-des.md) +- [外设](drive-peripherals.md) + - [LCD](drive-peripherals-lcd-des.md) + - [TOUCHSCREEN](drive-peripherals-touch-des.md) + - [SENSOR](drive-peripherals-sensor-des.md) + - [WLAN](drive-peripherals-external-des.md) diff --git a/zh-cn/device-dev/driver/SDIO.md b/zh-cn/device-dev/driver/SDIO.md deleted file mode 100755 index 192dd216b5..0000000000 --- a/zh-cn/device-dev/driver/SDIO.md +++ /dev/null @@ -1,9 +0,0 @@ -# SDIO - -- **[SDIO概述](SDIO概述.md)** - -- **[SDIO使用指导](SDIO使用指导.md)** - -- **[SDIO使用实例](SDIO使用实例.md)** - - diff --git "a/zh-cn/device-dev/driver/SDIO\344\275\277\347\224\250\345\256\236\344\276\213.md" "b/zh-cn/device-dev/driver/SDIO\344\275\277\347\224\250\345\256\236\344\276\213.md" deleted file mode 100755 index 18ddb74593..0000000000 --- "a/zh-cn/device-dev/driver/SDIO\344\275\277\347\224\250\345\256\236\344\276\213.md" +++ /dev/null @@ -1,129 +0,0 @@ -# SDIO使用实例 - -SDIO设备完整的使用示例如下所示,首先打开总线号为1的SDIO控制器,然后独占HOST、使能设备、注册中断,接着进行SDIO通信(读写等),通信完成之后,释放中断、去使能设备、释放HOST,最后关闭SDIO控制器。 - -``` -#include "hdf_log.h" -#include "sdio_if.h" - -#define TEST_FUNC_NUM 1 /* 本测试用例中,使用编号为1的I/O function */ -#define TEST_FBR_BASE_ADDR 0x100 /* 编号为1的I/O function的FBR基地址 */ -#define TEST_ADDR_OFFSET 9 /* 本测试用例中,需要读写的寄存器的地址偏移 */ -#define TEST_DATA_LEN 3 /* 本测试用例中,读写数据的长度 */ -#define TEST_BLOCKSIZE 2 /* 本测试用例中,数据块的大小,单位字节 */ - -/* 中断服务函数,需要根据各自平台的情况去实现 */ -static void SdioIrqFunc(void *data) -{ - if (data == NULL) { - HDF_LOGE("SdioIrqFunc: data is NULL.\n"); - return; - } - /* 需要开发者自行添加具体的实现 */ -} - -void SdioTestSample(void) -{ - int32_t ret; - DevHandle handle = NULL; - uint8_t data[TEST_DATA_LEN] = {0}; - struct SdioFunctionConfig config = {1, 0x123, 0x456}; - uint8_t val; - uint32_t addr; - - /* 打开总线号为1的SDIO设备 */ - handle = SdioOpen(1, &config); - if (handle == NULL) { - HDF_LOGE("SdioOpen: failed!\n"); - return; - } - /* 独占HOST */ - SdioClaimHost(handle); - /* 使能SDIO设备 */ - ret = SdioEnableFunc(handle); - if (ret != 0) { - HDF_LOGE("SdioEnableFunc: failed, ret %d\n", ret); - goto ENABLE_ERR; - } - /* 注册中断 */ - ret = SdioClaimIrq(handle, SdioIrqFunc); - if (ret != 0) { - HDF_LOGE("SdioClaimIrq: failed, ret %d\n", ret); - goto CLAIM_IRQ_ERR; - } - /* 设置块大小为2字节 */ - ret = SdioSetBlockSize(handle, TEST_BLOCKSIZE); - if (ret != 0) { - HDF_LOGE("SdioSetBlockSize: failed, ret %d\n", ret); - goto COMM_ERR; - } - /* 从SDIO设备增量地址读取3字节的数据 */ - addr = TEST_FBR_BASE_ADDR * TEST_FUNC_NUM + TEST_ADDR_OFFSET; - ret = SdioReadBytes(handle, data, addr, TEST_DATA_LEN); - if (ret != 0) { - HDF_LOGE("SdioReadBytes: failed, ret %d\n", ret); - goto COMM_ERR; - } - /* 向SDIO设备增量地址写入3字节的数据 */ - ret = SdioWriteBytes(handle, data, addr, TEST_DATA_LEN); - if (ret != 0) { - HDF_LOGE("SdioWriteBytes: failed, ret %d\n", ret); - goto COMM_ERR; - } - /* 从SDIO设备读取1字节的数据 */ - ret = SdioReadBytes(handle, &val, addr, 1); - if (ret != 0) { - HDF_LOGE("SdioReadBytes: failed, ret %d\n", ret); - goto COMM_ERR; - } - /* 向SDIO设备写入1字节的数据 */ - ret = SdioWriteBytes(handle, &val, addr, 1); - if (ret != 0) { - HDF_LOGE("SdioWriteBytes: failed, ret %d\n", ret); - goto COMM_ERR; - } - /* 从SDIO设备固定地址读取3字节的数据 */ - ret = SdioReadBytesFromFixedAddr(handle, data, addr, TEST_DATA_LEN, 0); - if (ret != 0) { - HDF_LOGE("SdioReadBytesFromFixedAddr: failed, ret %d\n", ret); - goto COMM_ERR; - } - /* 向SDIO设备固定地址写入1字节的数据 */ - ret = SdioWriteBytesToFixedAddr(handle, data, addr, 1, 0); - if (ret != 0) { - HDF_LOGE("SdioWriteBytesToFixedAddr: failed, ret %d\n", ret); - goto COMM_ERR; - } - /* 从SDIO function 0读取1字节的数据 */ - addr = 0x02; - ret = SdioReadBytesFromFunc0(handle, &val, addr, 1); - if (ret != 0) { - HDF_LOGE("SdioReadBytesFromFunc0: failed, ret %d\n", ret); - goto COMM_ERR; - } - /* 向SDIO function 0写入1字节的数据 */ - ret = SdioWriteBytesToFunc0(handle, &val, addr, 1); - if (ret != 0) { - HDF_LOGE("SdioWriteBytesToFunc0: failed, ret %d\n", ret); - goto COMM_ERR; - } -COMM_ERR: - /* 释放中断 */ - ret = SdioReleaseIrq(handle); - if (ret != 0) { - HDF_LOGE("SdioReleaseIrq: failed, ret %d\n", ret); - } -CLAIM_IRQ_ERR: - /* 去使能SDIO设备 */ - ret = SdioDisableFunc(handle); - if (ret != 0) { - HDF_LOGE("SdioDisableFunc: failed, ret %d\n", ret); - } -ENABLE_ERR: - /* 释放HOST */ - SdioReleaseHost(handle); - /* 关闭SDIO设备 */ - SdioClose(handle); -} -``` - diff --git "a/zh-cn/device-dev/driver/SDIO\344\275\277\347\224\250\346\214\207\345\257\274.md" "b/zh-cn/device-dev/driver/SDIO\344\275\277\347\224\250\346\214\207\345\257\274.md" deleted file mode 100755 index fd65e6de6a..0000000000 --- "a/zh-cn/device-dev/driver/SDIO\344\275\277\347\224\250\346\214\207\345\257\274.md" +++ /dev/null @@ -1,787 +0,0 @@ -# SDIO使用指导 - -- [使用流程](#section1962415610383) -- [打开SDIO控制器](#section814751015461) -- [独占HOST](#section49274582455) -- [使能SDIO设备](#section1431520410489) -- [注册SDIO中断](#section3662781537) -- [进行SDIO通信](#section391941913484) -- [释放SDIO中断](#section56205204481) -- [去使能SDIO设备](#section181181621124815) -- [释放HOST](#section657117215486) -- [关闭SDIO控制器](#section1898172114818) - -## 使用流程 - -使用SDIO的一般流程如[图1](SPI使用指导.md#fig23885455594)所示。 - -**图 1** SDIO使用流程图 - - -![](figures/zh-cn_image_0000001054440624.png) - -## 打开SDIO控制器 - -在使用SDIO进行通信前,首先要调用SdioOpen获取SDIO控制器的设备句柄,该函数会返回指定总线号的SDIO控制器的设备句柄。 - -DevHandle SdioOpen\(int16\_t mmcBusNum, struct SdioFunctionConfig \*config\); - -**表 1** SdioOpen函数的参数和返回值描述 - - - - - - - - - - - - - - - - - - - - - - -

    参数

    -

    参数描述

    -

    mmcBusNum

    -

    总线号

    -

    config

    -

    SDIO功能配置信息

    -

    返回值

    -

    返回值描述

    -

    NULL

    -

    获取SDIO控制器的设备句柄失败

    -

    设备句柄

    -

    SDIO控制器的设备句柄

    -
    - -打开SDIO控制器的示例如下: - -``` -DevHandle handle = NULL; -struct SdioFunctionConfig config; -config.funcNr = 1; -config.vendorId = 0x123; -config.deviceId = 0x456; -/* 打开总线号为1的SDIO控制器 */ -handle = SdioOpen(1, &config); -if (handle == NULL) { - HDF_LOGE("SdioOpen: failed!\n"); -} -``` - -## 独占HOST - -获取到SDIO控制器的设备句柄之后,需要先独占HOST才能进行SDIO后续的一系列操作,独占HOST函数如下所示: - -void SdioClaimHost\(DevHandle handle\); - -**表 2** SdioClaimHost函数的参数描述 - - - - - - - - - - -

    参数

    -

    参数描述

    -

    handle

    -

    SDIO控制器的设备句柄

    -
    - -独占HOST示例如下: - -``` -SdioClaimHost(handle); /* 独占HOST */ -``` - -## 使能SDIO设备 - -在访问寄存器之前,需要先使能SDIO设备,使能SDIO设备的函数如下所示: - -int32\_t SdioEnableFunc\(DevHandle handle\); - -**表 3** SdioEnableFunc函数的参数和返回值描述 - - - - - - - - - - - - - - - - - - - -

    参数

    -

    参数描述

    -

    handle

    -

    SDIO控制器的设备句柄

    -

    返回值

    -

    返回值描述

    -

    0

    -

    SDIO使能成功

    -

    负数

    -

    SDIO使能失败

    -
    - -使能SDIO设备的示例如下: - -``` -int32_t ret; -/* 使能SDIO设备 */ -ret = SdioEnableFunc(handle); -if (ret != 0) { - HDF_LOGE("SdioEnableFunc: failed, ret %d\n", ret); -} -``` - -## 注册SDIO中断 - -在通信之前,还需要注册SDIO中断,注册SDIO中断函数如下图所示: - -int32\_t SdioClaimIrq\(DevHandle handle, SdioIrqHandler \*handler\); - -**表 4** SdioClaimIrq函数的参数和返回值描述 - - - - - - - - - - - - - - - - - - - - - - -

    参数

    -

    参数描述

    -

    handle

    -

    SDIO控制器的设备句柄

    -

    handler

    -

    中断服务函数指针

    -

    返回值

    -

    返回值描述

    -

    0

    -

    注册中断成功

    -

    负数

    -

    注册中断失败

    -
    - -注册SDIO中的示例如下: - -``` -/* 中断服务函数需要根据各自平台的情况去实现 */ -static void SdioIrqFunc(void *data) -{ - if (data == NULL) { - HDF_LOGE("SdioIrqFunc: data is NULL.\n"); - return; - } - /* 需要开发者自行添加具体实现 */ -} - -int32_t ret; -/* 注册SDIO中断 */ -ret = SdioClaimIrq(handle, SdioIrqFunc); -if (ret != 0) { - HDF_LOGE("SdioClaimIrq: failed, ret %d\n", ret); -} -``` - -## 进行SDIO通信 - -- 向SDIO设备增量写入指定长度的数据 - -对应的接口函数如下所示: - -int32\_t SdioWriteBytes\(DevHandle handle, uint8\_t \*data, uint32\_t addr, uint32\_t size\); - -**表 5** SdioWriteBytes函数的参数和返回值描述 - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    参数

    -

    参数描述

    -

    handle

    -

    SDIO控制器的设备句柄

    -

    data

    -

    待写入数据的指针

    -

    addr

    -

    待写入数据的起始地址

    -

    size

    -

    待写入数据的长度

    -

    返回值

    -

    返回值描述

    -

    0

    -

    SDIO写数据成功

    -

    负数

    -

    SDIO写数据失败

    -
    - -向SDIO设备增量写入指定长度的数据的示例如下: - -``` -int32_t ret; -uint8_t wbuff[] = {1,2,3,4,5}; -uint32_t addr = 0x100 + 0x09; -/* 向SDIO设备起始地址0x109,增量写入5个字节的数据 */ -ret = SdioWriteBytes(handle, wbuff, addr, sizeof(wbuff) / sizeof(wbuff[0])); -if (ret != 0) { - HDF_LOGE("SdioWriteBytes: failed, ret %d\n", ret); -} -``` - -- 从SDIO设备增量读取指定长度的数据 - -对应的接口函数如下所示: - -int32\_t SdioReadBytes\(DevHandle handle, uint8\_t \*data, uint32\_t addr, uint32\_t size\); - -**表 6** SdioReadBytes函数的参数和返回值描述 - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    参数

    -

    参数描述

    -

    handle

    -

    SDIO控制器的设备句柄

    -

    data

    -

    接收读取数据的指针

    -

    addr

    -

    待读取数据的起始地址

    -

    size

    -

    待读取数据的长度

    -

    返回值

    -

    返回值描述

    -

    0

    -

    SDIO读数据成功

    -

    负数

    -

    SDIO读数据失败

    -
    - -从SDIO设备增量读取指定长度的数据的示例如下: - -``` -int32_t ret; -uint8_t rbuff[5] = {0}; -uint32_t addr = 0x100 + 0x09; -/* 从SDIO设备起始地址0x109,增量读取5个字节的数据 */ -ret = SdioReadBytes(handle, rbuff, addr, 5); -if (ret != 0) { - HDF_LOGE("SdioReadBytes: failed, ret %d\n", ret); -} -``` - -- 向SDIO设备的固定地址写入指定长度的数据 - - 对应的接口函数如下所示: - - int32\_t SdioWriteBytesToFixedAddr\(DevHandle handle, uint8\_t \*data, uint32\_t addr, uint32\_t size, uint32\_t scatterLen\); - - **表 7** SdioWriteBytesToFixedAddr函数的参数和返回值描述 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    参数

    -

    参数描述

    -

    handle

    -

    SDIO控制器的设备句柄

    -

    data

    -

    待写入数据的指针

    -

    addr

    -

    待写入数据的固定地址

    -

    size

    -

    待写入数据的长度

    -

    scatterLen

    -

    集散表的长度。如果该字段不为0,则data为集散表类型。

    -

    返回值

    -

    返回值描述

    -

    0

    -

    SDIO写数据成功

    -

    负数

    -

    SDIO写数据失败

    -
    - - 向SDIO设备的固定地址写入指定长度的数据的示例如下: - - ``` - int32_t ret; - uint8_t wbuff[] = {1,2,3,4,5}; - uint32_t addr = 0x100 + 0x09; - /* 向SDIO设备固定地址0x109写入5个字节的数据 */ - ret = SdioWriteBytesToFixedAddr(handle, wbuff, addr, sizeof(wbuff) / sizeof(wbuff[0]), 0); - if (ret != 0) { - HDF_LOGE("SdioWriteBytesToFixedAddr: failed, ret %d\n", ret); - } - ``` - -- 从SDIO设备的固定地址读取指定长度的数据 - - 对应的接口函数如下所示: - - int32\_t SdioReadBytesFromFixedAddr\(DevHandle handle, uint8\_t \*data, uint32\_t addr, uint32\_t size, uint32\_t scatterLen\); - - **表 8** SdioReadBytesFromFixedAddr函数的参数和返回值描述 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    参数

    -

    参数描述

    -

    handle

    -

    SDIO控制器的设备句柄

    -

    data

    -

    接收读取数据的指针

    -

    addr

    -

    待读取数据的起始地址

    -

    size

    -

    待读取数据的长度

    -

    scatterLen

    -

    集散表的长度。如果该字段不为0,则data为集散表类型。

    -

    返回值

    -

    返回值描述

    -

    0

    -

    SDIO读数据成功

    -

    负数

    -

    SDIO读数据失败

    -
    - - 从SDIO设备的固定地址读取指定长度的数据的示例如下: - - ``` - int32_t ret; - uint8_t rbuff[5] = {0}; - uint32_t addr = 0x100 + 0x09; - /* 从SDIO设备固定地址0x109中读取5个字节的数据 */ - ret = SdioReadBytesFromFixedAddr(handle, rbuff, addr, 5, 0); - if (ret != 0) { - HDF_LOGE("SdioReadBytesFromFixedAddr: failed, ret %d\n", ret); - } - ``` - - -- 向SDIO function 0的指定地址空间写入指定长度的数据 - -当前只支持写入一个字节的数据,对应的接口函数如下所示: - -int32\_t SdioWriteBytesToFunc0\(DevHandle handle, uint8\_t \*data, uint32\_t addr, uint32\_t size\); - -**表 9** SdioWriteBytesToFunc0函数的参数和返回值描述 - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    参数

    -

    参数描述

    -

    handle

    -

    SDIO控制器的设备句柄

    -

    data

    -

    待写入数据的指针

    -

    addr

    -

    待写入数据的起始地址

    -

    size

    -

    待写入数据的长度

    -

    返回值

    -

    返回值描述

    -

    0

    -

    SDIO写数据成功

    -

    负数

    -

    SDIO写数据失败

    -
    - -向SDIO function 0的指定地址空间写入指定长度的数据的示例如下: - -``` -int32_t ret; -uint8_t wbuff = 1; -/* 向SDIO function 0地址0x2中写入1字节的数据 */ -ret = SdioWriteBytesToFunc0(handle, &wbuff, 0x2, 1); -if (ret != 0) { - HDF_LOGE("SdioWriteBytesToFunc0: failed, ret %d\n", ret); -} -``` - -- 从SDIO function 0的指定地址空间读取指定长度的数据 - -当前只支持读取一个字节的数据,对应的接口函数如下所示: - -int32\_t SdioReadBytesFromFunc0\(DevHandle handle, uint8\_t \*data, uint32\_t addr, uint32\_t size\); - -**表 10** SdioReadBytesFromFunc0函数的参数和返回值描述 - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    参数

    -

    参数描述

    -

    handle

    -

    SDIO控制器的设备句柄

    -

    data

    -

    接收读取数据的指针

    -

    addr

    -

    待读取数据的起始地址

    -

    size

    -

    待读取数据的长度

    -

    返回值

    -

    返回值描述

    -

    0

    -

    SDIO读数据成功

    -

    负数

    -

    SDIO读数据失败

    -
    - -从SDIO function 0的指定地址空间读取指定长度的数据的示例如下: - -``` -int32_t ret; -uint8_t rbuff; -/* 从SDIO function 0设备地址0x2中读取1字节的数据 */ -ret = SdioReadBytesFromFunc0(handle, &rbuff, 0x2, 1); -if (ret != 0) { - HDF_LOGE("SdioReadBytesFromFunc0: failed, ret %d\n", ret); -} -``` - -## 释放SDIO中断 - -通信完成之后,需要释放SDIO中断,函数如下所示: - -int32\_t SdioReleaseIrq\(DevHandle handle\); - -**表 11** SdioReleaseIrq函数的参数和返回值描述 - - - - - - - - - - - - - - - - - - - -

    参数

    -

    参数描述

    -

    handle

    -

    SDIO控制器的设备句柄

    -

    返回值

    -

    返回值描述

    -

    0

    -

    释放SDIO中断成功

    -

    负数

    -

    释放SDIO中断失败

    -
    - -释放SDIO中断的示例如下: - -``` -int32_t ret; -/* 释放SDIO中断 */ -ret = SdioReleaseIrq(handle); -if (ret != 0) { - HDF_LOGE("SdioReleaseIrq: failed, ret %d\n", ret); -} -``` - -## 去使能SDIO设备 - -通信完成之后,还需要去使能SDIO设备,函数如下所示: - -int32\_t SdioDisableFunc\(DevHandle handle\); - -**表 12** SdioDisableFunc函数的参数和返回值描述 - - - - - - - - - - - - - - - - - - - -

    参数

    -

    参数描述

    -

    handle

    -

    SDIO控制器的设备句柄

    -

    返回值

    -

    返回值描述

    -

    0

    -

    去使能SDIO设备成功

    -

    负数

    -

    去使能SDIO设备失败

    -
    - -去使能SDIO设备的示例如下: - -``` -int32_t ret; -/* 去使能SDIO设备 */ -ret = SdioDisableFunc(handle); -if (ret != 0) { - HDF_LOGE("SdioDisableFunc: failed, ret %d\n", ret); -} -``` - -## 释放HOST - -通信完成之后,还需要释放去HOST,函数如下所示: - -void SdioReleaseHost\(DevHandle handle\); - -**表 13** SdioReleaseHost函数的参数描述 - - - - - - - - - - -

    参数

    -

    参数描述

    -

    handle

    -

    SDIO控制器的设备句柄

    -
    - -释放HOST的示例如下: - -``` -SdioReleaseHost(handle); /* 释放HOST */ -``` - -## 关闭SDIO控制器 - -SDIO通信完成之后,最后需要关闭SDIO控制器,函数如下所示: - -void SdioClose\(DevHandle handle\); - -该函数会释放掉申请的资源。 - -**表 14** SdioClose函数的参数描述 - - - - - - - - - - -

    参数

    -

    参数描述

    -

    handle

    -

    SDIO控制器的设备句柄

    -
    - -关闭SDIO控制器的示例如下: - -``` -SdioClose(handle); /* 关闭SDIO控制器 */ -``` - diff --git "a/zh-cn/device-dev/driver/SDIO\346\246\202\350\277\260.md" "b/zh-cn/device-dev/driver/SDIO\346\246\202\350\277\260.md" deleted file mode 100755 index 69b7487447..0000000000 --- "a/zh-cn/device-dev/driver/SDIO\346\246\202\350\277\260.md" +++ /dev/null @@ -1,149 +0,0 @@ -# SDIO概述 - -- [简介](#section1155271783811) -- [接口说明](#section10204143763819) - -## 简介 - -- SDIO是安全数字输入输出接口(Secure Digital Input and Output)的缩写,是从SD内存卡接口的基础上演化出来的一种外设接口。SDIO接口兼容以前的SD内存卡,并且可以连接支持SDIO接口的设备。 -- SDIO的应用比较广泛,目前,有许多手机都支持SDIO功能,并且很多SDIO外设也被开发出来,使得手机外接外设更加容易。常见的SDIO外设有WLAN、GPS、CAMERA、蓝牙等。 -- SDIO总线有两端,其中一端是主机端(HOST),另一端是设备端(DEVICE)。所有的通信都是由HOST端发出命令开始的,在DEVICE端只要能解析HOST的命令,就可以同HOST进行通信了。SDIO的HOST可以连接多个DEVICE,如下图所示: - - - CLK信号:HOST给DEVICE的时钟信号。 - - VDD信号:电源信号。 - - VSS信号:Ground信号。 - - D0-3信号:4条数据线,其中,DAT1信号线复用为中断线,在1BIT模式下DAT0用来传输数据,在4BIT模式下DAT0-DAT3用来传输数据。 - - CMD信号:用于HOST发送命令和DEVICE回复响应。 - - **图 1** SDIO的HOST-DEVICE连接示意图 - - - ![](figures/zh-cn_image_0000001054280608.png) - -- SDIO接口定义了操作SDIO的通用方法集合,包括打开/关闭SDIO控制器、独占/释放HOST、使能/去使能设备、申请/释放中断、读写、获取/设置公共信息等。 - -## 接口说明 - -**表 1** SDIO驱动API接口功能介绍 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    功能分类

    -

    接口名

    -

    描述

    -

    SDIO设备打开/关闭接口

    -

    SdioOpen

    -

    打开指定总线号的SDIO控制器

    -

    SdioClose

    -

    关闭SDIO控制器

    -

    SDIO读写接口

    -

    SdioReadBytes

    -

    从指定地址开始,增量读取指定长度的数据

    -

    SdioWriteBytes

    -

    从指定地址开始,增量写入指定长度的数据

    -

    SdioReadBytesFromFixedAddr

    -

    从固定地址读取指定长度的数据

    -

    SdioWriteBytesToFixedAddr

    -

    向固定地址写入指定长度的数据

    -

    SdioReadBytesFromFunc0

    -

    从SDIO function 0的指定地址空间读取指定长度的数据

    -

    SdioWriteBytesToFunc0

    -

    向SDIO function 0的指定地址空间写入指定长度的数据

    -

    SDIO设置块大小接口

    -

    SdioSetBlockSize

    -

    设置块的大小

    -

    SDIO获取/设置公共信息接口

    -

    SdioGetCommonInfo

    -

    获取公共信息

    -

    SdioSetCommonInfo

    -

    设置公共信息

    -

    SDIO刷新数据接口

    -

    SdioFlushData

    -

    刷新数据

    -

    SDIO独占/释放HOST接口

    -

    SdioClaimHost

    -

    独占Host

    -

    SdioReleaseHost

    -

    释放Host

    -

    SDIO使能/去使能功能设备接口

    -

    SdioEnableFunc

    -

    使能SDIO功能设备

    -

    SdioDisableFunc

    -

    去使能SDIO功能设备

    -

    SDIO申请/释放中断接口

    -

    SdioClaimIrq

    -

    申请中断

    -

    SdioReleaseIrq

    -

    释放中断

    -
    - ->![](public_sys-resources/icon-note.gif) **说明:** ->本文涉及的所有接口,目前只支持在内核态使用,不支持在用户态使用。 - diff --git a/zh-cn/device-dev/driver/SENSOR.md b/zh-cn/device-dev/driver/SENSOR.md deleted file mode 100755 index 5907809028..0000000000 --- a/zh-cn/device-dev/driver/SENSOR.md +++ /dev/null @@ -1,11 +0,0 @@ -# SENSOR - -- **[传感器驱动开发概述](传感器驱动开发概述.md)** - -- **[传感器驱动开发指导](传感器驱动开发指导.md)** - -- **[传感器驱动开发实例](传感器驱动开发实例.md)** - -- **[传感器驱动测试指导](传感器驱动测试指导.md)** - - diff --git a/zh-cn/device-dev/driver/SPI.md b/zh-cn/device-dev/driver/SPI.md deleted file mode 100755 index 394692a783..0000000000 --- a/zh-cn/device-dev/driver/SPI.md +++ /dev/null @@ -1,9 +0,0 @@ -# SPI - -- **[SPI概述](SPI概述.md)** - -- **[SPI使用指导](SPI使用指导.md)** - -- **[SPI使用实例](SPI使用实例.md)** - - diff --git "a/zh-cn/device-dev/driver/SPI\344\275\277\347\224\250\345\256\236\344\276\213.md" "b/zh-cn/device-dev/driver/SPI\344\275\277\347\224\250\345\256\236\344\276\213.md" deleted file mode 100755 index 4c3a628030..0000000000 --- "a/zh-cn/device-dev/driver/SPI\344\275\277\347\224\250\345\256\236\344\276\213.md" +++ /dev/null @@ -1,70 +0,0 @@ -# SPI使用实例 - -SPI设备完整的使用示例如下所示,首先获取SPI设备句柄,然后配置SPI设备属性,接着调用读写接口进行数据传输,最后销毁SPI设备句柄。 - -``` -#include "hdf_log.h" -#include "spi_if.h" - -void SpiTestSample(void) -{ - int32_t ret; - struct SpiCfg cfg; /* SPI配置信息 */ - struct SpiDevInfo spiDevinfo; /* SPI设备描述符 */ - DevHandle spiHandle = NULL; /* SPI设备句柄 */ - struct SpiMsg msg; /* 自定义传输的消息 */ - uint8_t rbuff[4] = { 0 }; - uint8_t wbuff[4] = { 0x12, 0x34, 0x56, 0x78 }; - uint8_t wbuff2[4] = { 0xa1, 0xb2, 0xc3, 0xd4 }; - - spiDevinfo.busNum = 0; /* SPI设备总线号 */ - spiDevinfo.csNum = 0; /* SPI设备片选号 */ - spiHandle = SpiOpen(&spiDevinfo); /* 根据spiDevinfo获取SPI设备句柄 */ - if (spiHandle == NULL) { - HDF_LOGE("SpiOpen: failed\n"); - return; - } - /* 获取SPI设备属性 */ - ret = SpiGetCfg(spiHandle, &cfg); - if (ret != 0) { - HDF_LOGE("SpiGetCfg: failed, ret %d\n", ret); - goto err; - } - cfg.maxSpeedHz = 115200; /* 将最大时钟频率改为115200 */ - cfg.bitsPerWord = 8; /* 传输位宽改为8比特 */ - /* 配置SPI设备属性 */ - ret = SpiSetCfg(spiHandle, &cfg); - if (ret != 0) { - HDF_LOGE("SpiSetCfg: failed, ret %d\n", ret); - goto err; - } - /* 向SPI设备写入指定长度的数据 */ - ret = SpiWrite(spiHandle, wbuff, 4); - if (ret != 0) { - HDF_LOGE("SpiWrite: failed, ret %d\n", ret); - goto err; - } - /* 从SPI设备读取指定长度的数据 */ - ret = SpiRead(spiHandle, rbuff, 4); - if (ret != 0) { - HDF_LOGE("SpiRead: failed, ret %d\n", ret); - goto err; - } - msg.wbuf = wbuff2; /* 写入的数据 */ - msg.rbuf = rbuff; /* 读取的数据 */ - msg.len = 4; /* 读取写入数据的长度为4 */ - msg.csChange = 1; /* 进行下一次传输前关闭片选 */ - msg.delayUs = 0; /* 进行下一次传输前不进行延时 */ - msg.speed = 115200; /* 本次传输的速度 */ - /* 进行一次自定义传输,传输的msg个数为1 */ - ret = SpiTransfer(spiHandle, &msg, 1); - if (ret != 0) { - HDF_LOGE("SpiTransfer: failed, ret %d\n", ret); - goto err; - } -err: - /* 销毁SPI设备句柄 */ - SpiClose(spiHandle); -} -``` - diff --git "a/zh-cn/device-dev/driver/SPI\344\275\277\347\224\250\346\214\207\345\257\274.md" "b/zh-cn/device-dev/driver/SPI\344\275\277\347\224\250\346\214\207\345\257\274.md" deleted file mode 100755 index 58698a9460..0000000000 --- "a/zh-cn/device-dev/driver/SPI\344\275\277\347\224\250\346\214\207\345\257\274.md" +++ /dev/null @@ -1,386 +0,0 @@ -# SPI使用指导 - -- [使用流程](#section691514116412) -- [获取SPI设备句柄](#section12372204616215) -- [获取SPI设备属性](#section17121446171311) -- [配置SPI设备属性](#section97691946634) -- [进行SPI通信](#section197116254416) -- [销毁SPI设备句柄](#section117661819108) - -## 使用流程 - -使用SPI的一般流程如[图1](#fig23885455594)所示。 - -**图 1** SPI使用流程图 - - -![](figures/zh-cn_image_0000001054726248.png) - -## 获取SPI设备句柄 - -在使用SPI进行通信时,首先要调用SpiOpen获取SPI设备句柄,该函数会返回指定总线号和片选号的SPI设备句柄。 - -DevHandle SpiOpen\(const struct SpiDevInfo \*info\); - -**表 1** SpiOpen参数和返回值描述 - - - - - - - - - - - - - - - - - - -

    参数

    -

    参数描述

    -

    info

    -

    SPI设备描述符

    -

    返回值

    -

    返回值描述

    -

    NULL

    -

    获取SPI设备句柄失败

    -

    设备句柄

    -

    对应的SPI设备句柄

    -
    - -假设系统中的SPI设备总线号为0,片选号为0,获取该SPI设备句柄的示例如下: - -``` -struct SpiDevInfo spiDevinfo; /* SPI设备描述符 */ -DevHandle spiHandle = NULL; /* SPI设备句柄 */ -spiDevinfo.busNum = 0; /* SPI设备总线号 */ -spiDevinfo.csNum = 0; /* SPI设备片选号 */ - -/* 获取SPI设备句柄 */ -spiHandle = SpiOpen(&spiDevinfo); -if (spiHandle == NULL) { - HDF_LOGE("SpiOpen: failed\n"); - return; -} -``` - -## 获取SPI设备属性 - -在获取到SPI设备句柄之后,需要配置SPI设备属性。配置SPI设备属性之前,可以先获取SPI设备属性,获取SPI设备属性的函数如下所示: - -int32\_t SpiGetCfg\(DevHandle handle, struct SpiCfg \*cfg\); - -**表 2** SpiGetCfg参数和返回值描述 - - - - - - - - - - - - - - - - - - - - - -

    参数

    -

    参数描述

    -

    handle

    -

    SPI设备句柄

    -

    cfg

    -

    SPI设备配置参数

    -

    返回值

    -

    返回值描述

    -

    0

    -

    获取配置成功

    -

    负数

    -

    获取配置失败

    -
    - -``` -int32_t ret; -struct SpiCfg cfg = {0}; /* SPI配置信息*/ -ret = SpiGetCfg(spiHandle, &cfg); /* 配置SPI设备属性 */ -if (ret != 0) { - HDF_LOGE("SpiGetCfg: failed, ret %d\n", ret); -} -``` - -## 配置SPI设备属性 - -在获取到SPI设备句柄之后,需要配置SPI设备属性,配置SPI设备属性的函数如下所示: - -int32\_t SpiSetCfg\(DevHandle handle, struct SpiCfg \*cfg\); - -**表 3** SpiSetCfg参数和返回值描述 - - - - - - - - - - - - - - - - - - - - - -

    参数

    -

    参数描述

    -

    handle

    -

    SPI设备句柄

    -

    cfg

    -

    SPI设备配置参数

    -

    返回值

    -

    返回值描述

    -

    0

    -

    配置成功

    -

    负数

    -

    配置失败

    -
    - -``` -int32_t ret; -struct SpiCfg cfg = {0}; /* SPI配置信息*/ -cfg.mode = SPI_MODE_LOOP; /* 以回环模式进行通信 */ -cfg.transferMode = PAL_SPI_POLLING_TRANSFER; /* 以轮询的方式进行通信 */ -cfg.maxSpeedHz = 115200; /* 最大传输频率 */ -cfg.bitsPerWord = 8; /* 读写位宽为8个比特 */ -ret = SpiSetCfg(spiHandle, &cfg); /* 配置SPI设备属性 */ -if (ret != 0) { - HDF_LOGE("SpiSetCfg: failed, ret %d\n", ret); -} -``` - -## 进行SPI通信 - -- 向SPI设备写入指定长度的数据 - -如果只向SPI设备写一次数据,则可以通过以下函数完成: - -int32\_t SpiWrite\(DevHandle handle, uint8\_t \*buf, uint32\_t len\); - -**表 4** SpiWrite参数和返回值描述 - - - - - - - - - - - - - - - - - - - - - - - - -

    参数

    -

    参数描述

    -

    handle

    -

    SPI设备句柄

    -

    buf

    -

    待写入数据的指针

    -

    len

    -

    待写入的数据长度

    -

    返回值

    -

    返回值描述

    -

    0

    -

    写入成功

    -

    负数

    -

    写入失败

    -
    - -``` -int32_t ret; -uint8_t wbuff[4] = {0x12, 0x34, 0x56, 0x78}; -/* 向SPI设备写入指定长度的数据 */ -ret = SpiWrite(spiHandle, wbuff, 4); -if (ret != 0) { - HDF_LOGE("SpiWrite: failed, ret %d\n", ret); -} -``` - -- 从SPI设备读取指定长度的数据 - -如果只读取一次数据,则可以通过以下函数完成: - -int32\_t SpiRead\(DevHandle handle, uint8\_t \*buf, uint32\_t len\); - -**表 5** SpiRead参数和返回值描述 - - - - - - - - - - - - - - - - - - - - - - - - -

    参数

    -

    参数描述

    -

    handle

    -

    SPI设备句柄

    -

    buf

    -

    待读取数据的指针

    -

    len

    -

    待读取的数据长度

    -

    返回值

    -

    返回值描述

    -

    0

    -

    读取成功

    -

    负数

    -

    读取失败

    -
    - -``` -int32_t ret; -uint8_t rbuff[4] = {0}; -/* 从SPI设备读取指定长度的数据 */ -ret = SpiRead(spiHandle, rbuff, 4); -if (ret != 0) { - HDF_LOGE("SpiRead: failed, ret %d\n", ret); -} -``` - -- 自定义传输 - -如果需要发起一次自定义传输,则可以通过以下函数完成: - -int32\_t SpiTransfer\(DevHandle handle, struct SpiMsg \*msgs, uint32\_t count\); - -**表 6** SpiTransfer参数和返回值描述 - - - - - - - - - - - - - - - - - - - - - - - - -

    参数

    -

    参数描述

    -

    handle

    -

    SPI设备句柄

    -

    msgs

    -

    待传输数据的数组

    -

    count

    -

    msgs数组长度

    -

    返回值

    -

    返回值描述

    -

    0

    -

    执行成功

    -

    负数

    -

    执行失败

    -
    - -``` -int32_t ret; -uint8_t wbuff[1] = {0x12}; -uint8_t rbuff[1] = {0}; -struct SpiMsg msg; /* 自定义传输的消息*/ -msg.wbuf = wbuff; /* 写入的数据 */ -msg.rbuf = rbuff; /* 读取的数据 */ -msg.len = 1; /* 读取、写入数据的长度都是1 */ -msg.csChange = 1; /* 进行下一次传输前关闭片选 */ -msg.delayUs = 0; /* 进行下一次传输前不进行延时 */ -msg.speed = 115200; /* 本次传输的速度 */ -/* 进行一次自定义传输,传输的msg个数为1 */ -ret = SpiTransfer(spiHandle, &msg, 1); -if (ret != 0) { - HDF_LOGE("SpiTransfer: failed, ret %d\n", ret); -} -``` - -## 销毁SPI设备句柄 - -SPI通信完成之后,需要销毁SPI设备句柄,销毁SPI设备句柄的函数如下所示: - -void SpiClose\(DevHandle handle\); - -该函数会释放掉申请的资源。 - -**表 7** SpiClose参数描述 - - - - - - - - - -

    参数

    -

    参数描述

    -

    handle

    -

    SPI设备句柄

    -
    - -``` -SpiClose(spiHandle); /* 销毁SPI设备句柄 */ -``` - diff --git "a/zh-cn/device-dev/driver/SPI\346\246\202\350\277\260.md" "b/zh-cn/device-dev/driver/SPI\346\246\202\350\277\260.md" deleted file mode 100755 index 3d3567489a..0000000000 --- "a/zh-cn/device-dev/driver/SPI\346\246\202\350\277\260.md" +++ /dev/null @@ -1,107 +0,0 @@ -# SPI概述 - -- [简介](#section9202632114011) -- [接口说明](#section1859594134119) - -## 简介 - -- SPI是串行外设接口(Serial Peripheral Interface)的缩写,是一种高速的,全双工,同步的通信总线。 -- SPI是由Motorola公司开发,用于在主设备和从设备之间进行通信,常用于与闪存、实时时钟、传感器以及模数转换器等进行通信。 -- SPI以主从方式工作,通常有一个主设备和一个或者多个从设备。主设备和从设备之间一般用4根线相连,它们分别是: - - SCLK – 时钟信号,由主设备产生; - - MOSI – 主设备数据输出,从设备数据输入; - - MISO – 主设备数据输入,从设备数据输出; - - CS – 片选,从设备使能信号,由主设备控制。 - - -- 一个主设备和两个从设备的连接示意图如[图1](#fig15227181812587)所示,Device A和Device B共享主设备的SCLK、MISO和MOSI三根引脚,Device A的片选CS0连接主设备的CS0,Device B的片选CS1连接主设备的CS1。 - -**图 1** SPI主从设备连接示意图。 - - -![](figures/zh-cn_image_0000001054142582.png) - -- SPI通信通常由主设备发起,通过以下步骤完成一次通信: - -1. 通过CS选中要通信的从设备,在任意时刻,一个主设备上最多只能有一个从设备被选中。 -2. 通过SCLK给选中的从设备提供时钟信号。 -3. 基于SCLK时钟信号,主设备数据通过MOSI发送给从设备,同时通过MISO接收从设备发送的数据,完成通信。 - -- 根据SCLK时钟信号的CPOL(Clock Polarity,时钟极性)和CPHA(Clock Phase,时钟相位)的不同组合,SPI有以下四种工作模式: - - CPOL=0,CPHA=0 时钟信号idle状态为低电平,第一个时钟边沿采样数据。 - - CPOL=0,CPHA=1 时钟信号idle状态为低电平,第二个时钟边沿采样数据。 - - CPOL=1,CPHA=0 时钟信号idle状态为高电平,第一个时钟边沿采样数据。 - - CPOL=1,CPHA=1 时钟信号idle状态为高电平,第二个时钟边沿采样数据。 - - -- SPI接口定义了操作SPI设备的通用方法集合,包括: - - SPI设备句柄获取和释放。 - - SPI读写: 从SPI设备读取或写入指定长度数据。 - - SPI自定义传输:通过消息传输结构体执行任意读写组合过程。 - - SPI设备配置:获取和设置SPI设备属性。 - - ->![](public_sys-resources/icon-note.gif) **说明:** ->当前只支持主机模式,不支持从机模式。 - -## 接口说明 - -**表 1** SPI驱动API接口功能介绍 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    功能分类

    -

    接口名

    -

    描述

    -

    SPI设备句柄获取释放接口

    -

    SpiOpen

    -

    获取SPI设备句柄

    -

    SpiClose

    -

    释放SPI设备句柄

    -

    SPI读写接口

    -

    SpiRead

    -

    读取指定长度的数据

    -

    SpiWrite

    -

    写入指定长度的数据

    -

    SpiTransfer

    -

    SPI数据传输接口

    -

    SPI设备配置接口

    -

    -

    SpiSetCfg

    -

    根据指定参数,配置SPI设备

    -

    SpiGetCfg

    -

    获取SPI设备配置参数

    -
    - ->![](public_sys-resources/icon-note.gif) **说明:** ->本文涉及的所有接口,仅限内核态使用,不支持在用户态使用。 - diff --git a/zh-cn/device-dev/driver/TOUCHSCREEN.md b/zh-cn/device-dev/driver/TOUCHSCREEN.md deleted file mode 100755 index ce5156c848..0000000000 --- a/zh-cn/device-dev/driver/TOUCHSCREEN.md +++ /dev/null @@ -1,9 +0,0 @@ -# TOUCHSCREEN - -- **[Touchscreen开发概述](Touchscreen开发概述.md)** - -- **[Touchscreen开发指导](Touchscreen开发指导.md)** - -- **[Touchscreen开发实例](Touchscreen开发实例.md)** - - diff --git "a/zh-cn/device-dev/driver/Touchscreen\345\274\200\345\217\221\345\256\236\344\276\213.md" "b/zh-cn/device-dev/driver/Touchscreen\345\274\200\345\217\221\345\256\236\344\276\213.md" deleted file mode 100755 index a298d618c1..0000000000 --- "a/zh-cn/device-dev/driver/Touchscreen\345\274\200\345\217\221\345\256\236\344\276\213.md" +++ /dev/null @@ -1,300 +0,0 @@ -# Touchscreen开发实例 - -- [设备描述配置](#section85281142102317) -- [板级配置及器件私有配置](#section189081946192410) -- [添加器件驱动](#section19856687253) - -本实例提供touchscreen驱动开发示例,并简要对具体关键点进行开发说明。 - -## 设备描述配置 - -如下配置主要包含input驱动模型各模块层级信息,具体原理可参考[HDF驱动开发指南](驱动开发.md),HDF框架依据该配置信息实现对Input模型各模块的依次加载等。 - -``` -input :: host { - hostName = "input_host"; - priority = 100; - device_input_manager :: device { - device0 :: deviceNode { - policy = 2; // 向外发布服务 - priority = 100; // 加载优先级,在input模块内,manager模块优先级应为最高 - preload = 0; // 加载该驱动 0:加载 1:不加载 - permission = 0660; - moduleName = "HDF_INPUT_MANAGER"; - serviceName = "input_dev_manager"; - deviceMatchAttr = ""; - } - } - device_hdf_touch :: device { - device0 :: deviceNode { - policy = 2; - priority = 120; - preload = 0; - permission = 0660; - moduleName = "HDF_TOUCH"; - serviceName = "event1"; - deviceMatchAttr = "touch_device1"; - } - } - - device_touch_chip :: device { - device0 :: deviceNode { - policy = 0; - priority = 130; - preload = 0; - permission = 0660; - moduleName = "HDF_TOUCH_SAMPLE"; - serviceName = "hdf_touch_sample_service"; - deviceMatchAttr = "zsj_sample_5p5"; - } - } -} -``` - -## 板级配置及器件私有配置 - -如下配置包含板级硬件配置及器件私有数据配置,实际业务开发时,可根据具体需求增删及修改如下配置文件信息。 - -``` -root { - input_config { - touchConfig { - touch0 { - boardConfig { - match_attr = "touch_device1"; - inputAttr { - inputType = 0; // 0代表触摸屏 - solutionX = 480; - solutionY = 960; - devName = "main_touch"; // 设备名称 - } - busConfig { - busType = 0; // 0代表I2C - busNum = 6; - clkGpio = 86; - dataGpio = 87; - i2cClkIomux = [0x114f0048, 0x403]; // i2c_clk对应pin的寄存器配置 - i2cDataIomux = [0x114f004c, 0x403]; // i2c_data对应pin的寄存器配置 - } - pinConfig { - rstGpio = 3; - intGpio = 4; - rstRegCfg = [0x112f0094, 0x400]; // reset对应pin的寄存器配置 - intRegCfg = [0x112f0098, 0x400]; // interrupt对应pin的寄存器配置 - } - powerConfig { - vccType = 2; // 1代表LDO、2代表GPIO、3代表PMIC - vccNum = 20; // GPIO号为20 - vccValue = 1800; // 电压幅值为1800mV - vciType = 1; - vciNum = 12; - vciValue = 3300; - } - featureConfig { - capacitanceTest = 0; - gestureMode = 0; - gloverMOde = 0; - coverMode = 0; - chargerMode = 0; - knuckleMode = 0; - } - } - chipConfig { - template touchChip { - match_attr = ""; - chipName = "sample"; - vendorName = "zsj"; - chipInfo = "AAAA11222"; // 1~4字符代表产品名,5~6字符代表IC型号,7~9字符代表模型型号 - busType = 0; - deviceAddr = 0x5D; - irqFlag = 2; // 1代表上升沿触发,2代表下降沿触发,4代表高电平触发,8代表低电平触发 - maxSpeed = 400; - chipVersion = 0; - powerSequence { - /* 上电时序的配置含义说明: - [类型, 状态, 方向 , 延时] - 0代表空,1代表vcc电源(1.8V),2代表VCI电源(3.3V),3代表复位管脚,4代表中断管脚 - 0代表下电或拉低,1代表上电或拉高,2代表无操作 - 0代表输入方向,1代表输出方向,2代表无操作 - 代表延时多少毫秒, 例如20代表延时20ms - */ - powerOnSeq = [4, 0, 1, 0, - 3, 0, 1, 10, - 3, 1, 2, 60, - 4, 2, 0, 0]; - suspendSeq = [3, 0, 2, 10]; - resumeSeq = [3, 1, 2, 10]; - powerOffSeq = [3, 0, 2, 10, - 1, 0, 2, 20]; - } - } - chip0 :: touchChip { - match_attr = "zsj_sample_5p5"; - chipInfo = "ZIDN45100"; - chipVersion = 0; - } - } - } - } - } -} -``` - -## 添加器件驱动 - -在器件驱动中,主要实现了平台预留的差异化接口,以器件数据获取及解析进行示例说明。具体开发过程,需要根据实际使用的单板及器件进行适配。 - -``` -/* 将从器件中读取到的报点数据解析为坐标 */ -static void ParsePointData(ChipDevice *device, FrameData *frame, uint8_t *buf, uint8_t pointNum) -{ - int32_t resX = device->driver->boardCfg->attr.resolutionX; - int32_t resY = device->driver->boardCfg->attr.resolutionY; - - for (int32_t i = 0; i < pointNum; i++) { - frame->fingers[i].y = (buf[GT_POINT_SIZE * i + GT_X_LOW] & ONE_BYTE_MASK) | - ((buf[GT_POINT_SIZE * i + GT_X_HIGH] & ONE_BYTE_MASK) << ONE_BYTE_OFFSET); - frame->fingers[i].x = (buf[GT_POINT_SIZE * i + GT_Y_LOW] & ONE_BYTE_MASK) | - ((buf[GT_POINT_SIZE * i + GT_Y_HIGH] & ONE_BYTE_MASK) << ONE_BYTE_OFFSET); - frame->fingers[i].valid = true; - } -} -/* 从器件中获取报点数据 */ -static int32_t ChipDataHandle(ChipDevice *device) -{ - int32_t ret; - uint8_t touchStatus = 0; - uint8_t pointNum; - uint8_t buf[GT_POINT_SIZE * MAX_SUPPORT_POINT] = {0}; - InputI2cClient *i2cClient = &device->driver->i2cClient; - uint8_t reg[GT_ADDR_LEN] = {0}; - FrameData *frame = &device->driver->frameData; - reg[0] = (GT_BUF_STATE_ADDR >> ONE_BYTE_OFFSET) & ONE_BYTE_MASK; - reg[1] = GT_BUF_STATE_ADDR & ONE_BYTE_MASK; - ret = InputI2cRead(i2cClient, reg, GT_ADDR_LEN, &touchStatus, 1); - if (ret < 0 || touchStatus == GT_EVENT_INVALID) { - return HDF_FAILURE; - } - OsalMutexLock(&device->driver->mutex); - (void)memset_s(frame, sizeof(FrameData), 0, sizeof(FrameData)); - if (touchStatus == GT_EVENT_UP) { - frame->realPointNum = 0; - frame->definedEvent = TOUCH_UP; - goto exit; - } - reg[0] = (GT_X_LOW_BYTE_BASE >> ONE_BYTE_OFFSET) & ONE_BYTE_MASK; - reg[1] = GT_X_LOW_BYTE_BASE & ONE_BYTE_MASK; - pointNum = touchStatus & GT_FINGER_NUM_MASK; - if (pointNum <= 0 || pointNum > MAX_SUPPORT_POINT) { - HDF_LOGE("%s: pointNum is invalid, %d", __func__, pointNum); - (void)ChipCleanBuffer(i2cClient); - OsalMutexUnlock(&device->driver->mutex); - return HDF_FAILURE; - } - frame->realPointNum = pointNum; - frame->definedEvent = TOUCH_DOWN; - /* 从寄存器中读取报点值 */ - (void)InputI2cRead(i2cClient, reg, GT_ADDR_LEN, buf, GT_POINT_SIZE * pointNum); - /* 解析报点值 */ - ParsePointData(device, frame, buf, pointNum); -exit: - OsalMutexUnlock(&device->driver->mutex); - if (ChipCleanBuffer(i2cClient) != HDF_SUCCESS) { - return HDF_FAILURE; - } - return HDF_SUCCESS; -} - -static struct TouchChipOps g_sampleChipOps = { - .Init = ChipInit, - .Detect = ChipDetect, - .Resume = ChipResume, - .Suspend = ChipSuspend, - .DataHandle = ChipDataHandle, -}; - -static TouchChipCfg *ChipConfigInstance(struct HdfDeviceObject *device) -{ - TouchChipCfg *chipCfg = (TouchChipCfg *)OsalMemAlloc(sizeof(TouchChipCfg)); - if (chipCfg == NULL) { - HDF_LOGE("%s: instance chip config failed", __func__); - return NULL; - } - (void)memset_s(chipCfg, sizeof(TouchChipCfg), 0, sizeof(TouchChipCfg)); - /* 解析器件私有配置 */ - if (ParseTouchChipConfig(device->property, chipCfg) != HDF_SUCCESS) { - HDF_LOGE("%s: parse chip config failed", __func__); - OsalMemFree(chipCfg); - chipCfg = NULL; - } - return chipCfg; -} - -static ChipDevice *ChipDeviceInstance(void) -{ - ChipDevice *chipDev = (ChipDevice *)OsalMemAlloc(sizeof(ChipDevice)); - if (chipDev == NULL) { - HDF_LOGE("%s: instance chip device failed", __func__); - return NULL; - } - (void)memset_s(chipDev, sizeof(ChipDevice), 0, sizeof(ChipDevice)); - return chipDev; -} - -static void FreeChipConfig(TouchChipCfg *config) -{ - if (config->pwrSeq.pwrOn.buf != NULL) { - OsalMemFree(config->pwrSeq.pwrOn.buf); - } - if (config->pwrSeq.pwrOff.buf != NULL) { - OsalMemFree(config->pwrSeq.pwrOff.buf); - } - OsalMemFree(config); -} - -static int32_t HdfSampleChipInit(struct HdfDeviceObject *device) -{ - TouchChipCfg *chipCfg = NULL; - ChipDevice *chipDev = NULL; - HDF_LOGE("%s: enter", __func__); - if (device == NULL) { - return HDF_ERR_INVALID_PARAM; - } - /* 器件私有配置解析 */ - chipCfg = ChipConfigInstance(device); - if (chipCfg == NULL) { - return HDF_ERR_MALLOC_FAIL; - } - /* 器件设备实例化 */ - chipDev = ChipDeviceInstance(); - if (chipDev == NULL) { - goto freeCfg; - } - chipDev->chipCfg = chipCfg; - chipDev->ops = &g_sampleChipOps; - chipDev->chipName = chipCfg->chipName; - chipDev->vendorName = chipCfg->vendorName; - - /* 器件设备注册到平台驱动 */ - if (RegisterChipDevice(chipDev) != HDF_SUCCESS) { - goto freeDev; - } - HDF_LOGI("%s: exit succ, chipName = %s", __func__, chipCfg->chipName); - return HDF_SUCCESS; - -freeDev: - OsalMemFree(chipDev); -freeCfg: - FreeChipConfig(chipCfg); - return HDF_FAILURE; -} - -struct HdfDriverEntry g_touchSampleChipEntry = { - .moduleVersion = 1, - .moduleName = "HDF_TOUCH_SAMPLE", - .Init = HdfSampleChipInit, -}; - -HDF_INIT(g_touchSampleChipEntry); -``` - diff --git "a/zh-cn/device-dev/driver/Touchscreen\345\274\200\345\217\221\346\214\207\345\257\274.md" "b/zh-cn/device-dev/driver/Touchscreen\345\274\200\345\217\221\346\214\207\345\257\274.md" deleted file mode 100755 index 09dc518533..0000000000 --- "a/zh-cn/device-dev/driver/Touchscreen\345\274\200\345\217\221\346\214\207\345\257\274.md" +++ /dev/null @@ -1,36 +0,0 @@ -# Touchscreen开发指导 - -- [开发步骤](#section1255740132616) - -Input驱动模型是基于HDF框架、Platform接口和OSAL接口开发,不区分操作系统和芯片平台,为touchscreen等输入器件提供统一的驱动开发架构。 - -- 如下以touchscreen器件驱动为例,说明input驱动模型的完整加载流程: - - (1)设备描述配置:由开发者参考已有模板进行设备描述配置,包括驱动加载顺序、板级硬件信息、器件私有数据信息等。 - - (2)加载input设备管理驱动:input设备管理驱动由HDF驱动加载,完成设备manager的创建并对其初始化。 - - (3)加载平台驱动:平台驱动由HDF框架加载,主要完成板级配置解析及硬件初始化,并提供器件注册接口。 - - (4)加载器件驱动:器件驱动也由HDF框架加载,完成器件设备的实例化,包括器件私有配置解析和平台预留的差异化接口适配。 - - (5)器件设备向平台驱动注册:将实例化的器件设备向平台驱动注册,实现设备和驱动的绑定,并完成中断注册、上下电等器件初始化工作。 - - (6)input设备注册:在器件初始化完成后,实例化input设备,并将其注册到input manager进行管理。 - - -## 开发步骤 - -1. 设备描述配置 - - 目前Input驱动基于HDF驱动框架编写,驱动的加载启动由HDF驱动管理框架统一处理。首先需要在对应的配置文件中,将驱动信息注册进去,如是否加载、加载优先级,此后HDF驱动框架会逐一启动注册过的驱动模块。驱动的相关配置请参考[HDF驱动框架配置指导](驱动开发.md#section1969312275533)。 - -2. 板级配置及Touchscreen器件私有配置 - - 配置对应的IO管脚功能,例如对单板上为touchscreen设计预留的I2C Pin脚,需设置对应的寄存器,使其选择I2C的通信功能。 - -3. 实现器件差异化适配接口 - - 根据硬件单板设计的通信接口,使用Platform接口层提供的管脚操作接口配置对应的复位管脚、中断管脚以及电源操作,对于GPIO的操作,可参考[GPIO操作接口指导](GPIO使用指导.md) - - diff --git "a/zh-cn/device-dev/driver/Touchscreen\345\274\200\345\217\221\346\246\202\350\277\260.md" "b/zh-cn/device-dev/driver/Touchscreen\345\274\200\345\217\221\346\246\202\350\277\260.md" deleted file mode 100755 index b6456936b0..0000000000 --- "a/zh-cn/device-dev/driver/Touchscreen\345\274\200\345\217\221\346\246\202\350\277\260.md" +++ /dev/null @@ -1,71 +0,0 @@ -# Touchscreen开发概述 - -- [简介](#section124332411260) -- [接口说明](#section10542625172618) - -## 简介 - -- **Touchscreen驱动主要任务** - - Touchscreen驱动用于驱动触摸屏使其正常工作,该驱动主要完成如下工作:对触摸屏驱动IC进行上电、配置硬件管脚并初始化其状态、注册中断、配置通信接口(I2C或SPI)、设定input相关配置、下载及更新固件等操作。 - - -- **Touchscreen驱动层次说明** - - 本节主要介绍基于input驱动模型开发touchscreen器件驱动,其整体的框架模型如[图1](#fig6251184817261)。 - - Input驱动模型基于HDF驱动框架、PLATFORM接口、OSAL接口进行开发,向上对接规范化的驱动接口HDI(Hardware Driver Interface)层,通过Input-HDI层对外提供硬件能力,即上层input service可以通过HDI接口层获取相应的驱动能力,进而操控touchscreen等输入设备。 - - -**图 1** 基于HDF驱动框架的input驱动模型 -![](figures/基于HDF驱动框架的input驱动模型.png "基于HDF驱动框架的input驱动模型") - -- **Input驱动模型介绍** - - Input驱动模型核心部分由设备管理层、公共驱动层、器件驱动层组成。器件产生的数据借助平台数据通道能力从内核传递到用户态,驱动模型通过配置文件适配不同器件及硬件平台,提高开发者的器件驱动开发效率。如下部分为模型各部分的说明: - - (1)input设备管理:为各类输入设备驱动提供input设备的注册、注销接口,同时统一管理input设备列表; - - (2)input平台驱动:指各类input设备的公共抽象驱动(例如触摸屏的公共驱动),负责对板级硬件进行初始化、硬件中断处理、向manager注册input设备等; - - (3)input器件驱动:指各器件厂家的差异化驱动,通过适配平台驱动预留的差异化接口,实现器件驱动开发量最小化; - - (4)input数据通道:提供一套通用的数据上报通道,各类别的input设备驱动均可用此通道上报input事件; - - (5)input配置解析:负责对input设备的板级配置及器件私有配置进行解析及管理。 - - -- **基于HDF驱动框架开发器件驱动的优势** - - 在HDF(Hardware Driver Foundation)[驱动管理框架](驱动开发.md)的基础上,input驱动模型调用OSAL接口层和Platfom接口层提供的基础接口进行开发,包括bus通信接口、操作系统原生接口(memory、lock、thread、timer等)。由于OSAL接口和Platform接口屏蔽了芯片平台差异,所以基于input驱动模型实现的touchscreen驱动可以进行跨平台、跨OS迁移,以便逐步实现驱动的一次开发,多端部署。 - - -## 接口说明 - -Touchscreen器件的硬件接口相对简单,根据PIN脚的属性,可以简单分为如下三类: - -- 电源接口 -- IO控制接口 -- 通信接口 - -**图 2** Touchscreen器件常用管脚 -![](figures/Touchscreen器件常用管脚.png "Touchscreen器件常用管脚") - -如上图所示的三类接口,分别做简要说明如下: - -1. **电源接口** - - LDO\_1P8:1.8v数字电路 - - LDO\_3P3:3.3v模拟电路 - - 通常情况下,touchscreen驱动IC和LCD驱动IC是相互分离的,这种情况下,touchscreen驱动IC一般同时需要1.8v和3.3v两路供电。随着芯片演进,业内已有touchscreen驱动IC和LCD驱动IC集成在一颗IC中的芯片案例,对touchscreen而言,只需要关注1.8v供电即可,其内部需要的3.3v电源,会在驱动IC内部从LCD的VSP电源(典型值5.5V)中分出来。 - - -2. **IO控制接口** - - Reset:reset管脚,用于在系统休眠、唤醒时,由主机侧对驱动IC进行复位操作。 - - INT:中断管脚,需要在驱动初始化时,配置为输入上拉状态。在驱动IC检测到外部触摸信号后,通过操作中断管脚来触发中断,器件驱动则会在中断处理函数中进行报点数据读取等操作。 - -3. **通信接口** - - I2C:由于touchscreen的报点数据量相对较少,所以一般选用I2C方式传输数据。I2C的具体协议及对应操作接口,可以参考Platform接口层中的[“I2C”使用指南](I2C使用指导.md)。 - - SPI:部分厂商,由于需要传递的数据不止报点坐标,而是需要获取基础容值,数据量较大,所以会选用SPI通信方式。SPI的具体协议及对应操作接口,可以参考Platform接口层中的[“SPI” 使用指南](SPI使用指导.md)。 - - diff --git a/zh-cn/device-dev/driver/UART.md b/zh-cn/device-dev/driver/UART.md deleted file mode 100755 index 5d81f12e15..0000000000 --- a/zh-cn/device-dev/driver/UART.md +++ /dev/null @@ -1,9 +0,0 @@ -# UART - -- **[UART概述](UART概述.md)** - -- **[UART使用指导](UART使用指导.md)** - -- **[UART使用实例](UART使用实例.md)** - - diff --git "a/zh-cn/device-dev/driver/UART\344\275\277\347\224\250\345\256\236\344\276\213.md" "b/zh-cn/device-dev/driver/UART\344\275\277\347\224\250\345\256\236\344\276\213.md" deleted file mode 100755 index d049e3d021..0000000000 --- "a/zh-cn/device-dev/driver/UART\344\275\277\347\224\250\345\256\236\344\276\213.md" +++ /dev/null @@ -1,67 +0,0 @@ -# UART使用实例 - -UART设备完整的使用示例如下所示,首先获取UART设备句柄,接着设置波特率、设备属性和传输模式,之后进行UART通信,最后销毁UART设备句柄。 - -``` -#include "hdf_log.h" -#include "uart_if.h" - -void UartTestSample(void) -{ - int32_t ret; - uint32_t port; - DevHandle handle = NULL; - uint8_t wbuff[5] = { 1, 2, 3, 4, 5 }; - uint8_t rbuff[5] = { 0 }; - struct UartAttribute attribute; - attribute.dataBits = UART_ATTR_DATABIT_7; /* UART传输数据位宽,一次传输7个bit */ - attribute.parity = UART_ATTR_PARITY_NONE; /* UART传输数据无校检 */ - attribute.stopBits = UART_ATTR_STOPBIT_1; /* UART传输数据停止位为1位 */ - attribute.rts = UART_ATTR_RTS_DIS; /* UART禁用RTS */ - attribute.cts = UART_ATTR_CTS_DIS; /* UART禁用CTS */ - attribute.fifoRxEn = UART_ATTR_RX_FIFO_EN; /* UART使能RX FIFO */ - attribute.fifoTxEn = UART_ATTR_TX_FIFO_EN; /* UART使能TX FIFO */ - /* UART设备端口号,要填写实际平台上的端口号 */ - port = 1; - /* 获取UART设备句柄 */ - handle = UartOpen(port); - if (handle == NULL) { - HDF_LOGE("UartOpen: failed!\n"); - return; - } - /* 设置UART波特率为9600 */ - ret = UartSetBaud(handle, 9600); - if (ret != 0) { - HDF_LOGE("UartSetBaud: failed, ret %d\n", ret); - goto _ERR; - } - /* 设置UART设备属性 */ - ret = UartSetAttribute(handle, &attribute); - if (ret != 0) { - HDF_LOGE("UartSetAttribute: failed, ret %d\n", ret); - goto _ERR; - } - /* 设置UART传输模式为非阻塞模式 */ - ret = UartSetTransMode(handle, UART_MODE_RD_NONBLOCK); - if (ret != 0) { - HDF_LOGE("UartSetTransMode: failed, ret %d\n", ret); - goto _ERR; - } - /* 向UART设备写入5字节的数据 */ - ret = UartWrite(handle, wbuff, 5); - if (ret != 0) { - HDF_LOGE("UartWrite: failed, ret %d\n", ret); - goto _ERR; - } - /* 从UART设备读取5字节的数据 */ - ret = UartRead(handle, rbuff, 5); - if (ret < 0) { - HDF_LOGE("UartRead: failed, ret %d\n", ret); - goto _ERR; - } -_ERR: - /* 销毁UART设备句柄 */ - UartClose(handle); -} -``` - diff --git "a/zh-cn/device-dev/driver/UART\344\275\277\347\224\250\346\214\207\345\257\274.md" "b/zh-cn/device-dev/driver/UART\344\275\277\347\224\250\346\214\207\345\257\274.md" deleted file mode 100755 index 1d1ee50a8c..0000000000 --- "a/zh-cn/device-dev/driver/UART\344\275\277\347\224\250\346\214\207\345\257\274.md" +++ /dev/null @@ -1,506 +0,0 @@ -# UART使用指导 - -- [使用流程](#section47784125013) -- [获取UART设备句柄](#section146445153110) -- [UART设置波特率](#section1862705516339) -- [UART获取波特率](#section1263651563414) -- [UART设置设备属性](#section1770091483814) -- [UART获取设备属性](#section117543316384) -- [设置UART传输模式](#section187233112369) -- [向UART设备写入指定长度的数据](#section82416423368) -- [从UART设备中读取指定长度的数据](#section192177171373) -- [销毁UART设备句柄](#section63131236354) - -## 使用流程 - -使用UART的一般流程如[图1](#p58686354483)所示。 - -**图 1** UART使用流程图 - - -![](figures/zh-cn_image_0000001054006983.png) - -## 获取UART设备句柄 - -在使用UART进行通信时,首先要调用UartOpen获取UART设备句柄,该函数会返回指定端口号的UART设备句柄。 - -DevHandle UartOpen\(uint32\_t port\); - -**表 1** UartOpen参数和返回值描述 - - - - - - - - - - - - - - - - - - - -

    参数

    -

    参数描述

    -

    port

    -

    UART设备号

    -

    返回值

    -

    返回值描述

    -

    NULL

    -

    获取UART设备句柄失败

    -

    设备句柄

    -

    UART设备句柄

    -
    - -假设系统中的UART端口号为3,获取该UART设备句柄的示例如下: - -``` -DevHandle handle = NULL; /* UART设备句柄 */ -uint32_t port = 3; /* UART设备端口号 */ -handle = UartOpen(port); -if (handle == NULL) { - HDF_LOGE("UartOpen: failed!\n"); - return; -} -``` - -## UART设置波特率 - -在通信之前,需要设置UART的波特率,设置波特率的函数如下所示: - -int32\_t UartSetBaud\(DevHandle handle, uint32\_t baudRate\); - -**表 2** UartSetBaud参数和返回值描述 - - - - - - - - - - - - - - - - - - - - - - -

    参数

    -

    参数描述

    -

    handle

    -

    UART设备句柄

    -

    baudRate

    -

    待设置的波特率值

    -

    返回值

    -

    返回值描述

    -

    0

    -

    UART设置波特率成功

    -

    负数

    -

    UART设置波特率失败

    -
    - -假设需要设置的UART波特率为9600,设置波特率的实例如下: - -``` -int32_t ret; -/* 设置UART波特率 */ -ret = UartSetBaud(handle, 9600); -if (ret != 0) { - HDF_LOGE("UartSetBaud: failed, ret %d\n", ret); -} -``` - -## UART获取波特率 - -设置UART的波特率后,可以通过获取波特率接口来查看UART当前的波特率,获取波特率的函数如下所示: - -int32\_t UartGetBaud\(DevHandle handle, uint32\_t \*baudRate\); - -**表 3** UartGetBaud参数和返回值描述 - - - - - - - - - - - - - - - - - - - - - - -

    参数

    -

    参数描述

    -

    handle

    -

    UART设备句柄

    -

    baudRate

    -

    接收波特率值的指针

    -

    返回值

    -

    返回值描述

    -

    0

    -

    UART获取波特率成功

    -

    负数

    -

    UART获取波特率失败

    -
    - -获取波特率的实例如下: - -``` -int32_t ret; -uint32_t baudRate; -/* 获取UART波特率 */ -ret = UartGetBaud(handle, &baudRate); -if (ret != 0) { - HDF_LOGE("UartGetBaud: failed, ret %d\n", ret); -} -``` - -## UART设置设备属性 - -在通信之前,需要设置UART的设备属性,设置设备属性的函数如下图所示: - -int32\_t UartSetAttribute\(DevHandle handle, struct UartAttribute \*attribute\); - -**表 4** UartSetAttribute参数和返回值描述 - - - - - - - - - - - - - - - - - - - - - - -

    参数

    -

    参数描述

    -

    handle

    -

    UART设备句柄

    -

    attribute

    -

    待设置的设备属性

    -

    返回值

    -

    返回值描述

    -

    0

    -

    UART设置设备属性成功

    -

    负数

    -

    UART设置设备属性失败

    -
    - -设置UART的设备属性的实例如下: - -``` -int32_t ret; -struct UartAttribute attribute; -attribute.dataBits = UART_ATTR_DATABIT_7; /* UART传输数据位宽,一次传输7个bit */ -attribute.parity = UART_ATTR_PARITY_NONE; /* UART传输数据无校检 */ -attribute.stopBits = UART_ATTR_STOPBIT_1; /* UART传输数据停止位为1位 */ -attribute.rts = UART_ATTR_RTS_DIS; /* UART禁用RTS */ -attribute.cts = UART_ATTR_CTS_DIS; /* UART禁用CTS */ -attribute.fifoRxEn = UART_ATTR_RX_FIFO_EN; /* UART使能RX FIFO */ -attribute.fifoTxEn = UART_ATTR_TX_FIFO_EN; /* UART使能TX FIFO */ -/* 设置UART设备属性 */ -ret = UartSetAttribute(handle, &attribute); -if (ret != 0) { - HDF_LOGE("UartSetAttribute: failed, ret %d\n", ret); -} -``` - -## UART获取设备属性 - -设置UART的设备属性后,可以通过获取设备属性接口来查看UART当前的设备属性,获取设备属性的函数如下图所示: - -int32\_t UartGetAttribute\(DevHandle handle, struct UartAttribute \*attribute\); - -**表 5** UartGetAttribute参数和返回值描述 - - - - - - - - - - - - - - - - - - - - - - -

    参数

    -

    参数描述

    -

    handle

    -

    UART设备句柄

    -

    attribute

    -

    接收UART设备属性的指针

    -

    返回值

    -

    返回值描述

    -

    0

    -

    UART获取设备属性成功

    -

    负数

    -

    UART获取设备属性失败

    -
    - -获取UART的设备属性的实例如下: - -``` -int32_t ret; -struct UartAttribute attribute; -/* 获取UART设备属性 */ -ret = UartGetAttribute(handle, &attribute); -if (ret != 0) { - HDF_LOGE("UartGetAttribute: failed, ret %d\n", ret); -} -``` - -## 设置UART传输模式 - -在通信之前,需要设置UART的传输模式,设置传输模式的函数如下图所示: - -int32\_t UartSetTransMode\(DevHandle handle, enum UartTransMode mode\); - -**表 6** UartSetTransMode参数和返回值描述 - - - - - - - - - - - - - - - - - - - - - - -

    参数

    -

    参数描述

    -

    handle

    -

    UART设备句柄

    -

    mode

    -

    待设置的传输模式,

    -

    返回值

    -

    返回值描述

    -

    0

    -

    UART设置传输模式成功

    -

    负数

    -

    UART设置传输模式失败

    -
    - -假设需要设置的UART传输模式为UART\_MODE\_RD\_BLOCK,设置传输模式的实例如下: - -``` -int32_t ret; -/* 设置UART传输模式 */ -ret = UartSetTransMode(handle, UART_MODE_RD_BLOCK); -if (ret != 0) { - HDF_LOGE("UartSetTransMode: failed, ret %d\n", ret); -} -``` - -## 向UART设备写入指定长度的数据 - -对应的接口函数如下所示: - -int32\_t UartWrite\(DevHandle handle, uint8\_t \*data, uint32\_t size\); - -**表 7** UartWrite参数和返回值描述 - - - - - - - - - - - - - - - - - - - - - - - - - -

    参数

    -

    参数描述

    -

    handle

    -

    UART设备句柄

    -

    data

    -

    待写入数据的指针

    -

    size

    -

    待写入数据的长度

    -

    返回值

    -

    返回值描述

    -

    0

    -

    UART写数据成功

    -

    负数

    -

    UART写数据失败

    -
    - -写入指定长度数据的实例如下: - -``` -int32_t ret; -uint8_t wbuff[5] = {1, 2, 3, 4, 5}; -/* 向UART设备写入指定长度的数据 */ -ret = UartWrite(handle, wbuff, 5); -if (ret != 0) { - HDF_LOGE("UartWrite: failed, ret %d\n", ret); -} -``` - -## 从UART设备中读取指定长度的数据 - -对应的接口函数如下所示: - -int32\_t UartRead\(DevHandle handle, uint8\_t \*data, uint32\_t size\); - -**表 8** UartRead参数和返回值描述 - - - - - - - - - - - - - - - - - - - - - - - - - -

    参数

    -

    参数描述

    -

    handle

    -

    UART设备句柄

    -

    data

    -

    接收读取数据的指针

    -

    size

    -

    待读取数据的长度

    -

    返回值

    -

    返回值描述

    -

    非负数

    -

    UART读取到的数据长度

    -

    负数

    -

    UART读取数据失败

    -
    - -读取指定长度数据的实例如下: - -``` -int32_t ret; -uint8_t rbuff[5] = {0}; -/* 从UART设备读取指定长度的数据 */ -ret = UartRead(handle, rbuff, 5); -if (ret < 0) { - HDF_LOGE("UartRead: failed, ret %d\n", ret); -} -``` - ->![](public_sys-resources/icon-caution.gif) **注意:** ->UART返回值为非负值,表示UART读取成功。若返回值等于0,表示UART无有效数据可以读取。若返回值大于0,表示实际读取到的数据长度,该长度小于或等于传入的参数size的大小,并且不超过当前正在使用的UART控制器规定的最大单次读取数据长度的值。 - -## 销毁UART设备句柄 - -UART通信完成之后,需要销毁UART设备句柄,函数如下所示: - -void UartClose\(DevHandle handle\); - -该函数会释放申请的资源。 - -**表 9** UartClose参数和返回值描述 - - - - - - - - - - -

    参数

    -

    参数描述

    -

    handle

    -

    UART设备句柄

    -
    - -销毁UART设备句柄的实例如下: - -``` -UartClose(handle); /* 销毁UART设备句柄 * -``` - diff --git "a/zh-cn/device-dev/driver/UART\346\246\202\350\277\260.md" "b/zh-cn/device-dev/driver/UART\346\246\202\350\277\260.md" deleted file mode 100755 index 2f295bddd9..0000000000 --- "a/zh-cn/device-dev/driver/UART\346\246\202\350\277\260.md" +++ /dev/null @@ -1,106 +0,0 @@ -# UART概述 - -- [简介](#section14770623164917) -- [接口说明](#section149505462492) - -## 简介 - -- UART是通用异步收发传输器(Universal Asynchronous Receiver/Transmitter)的缩写,是通用串行数据总线,用于异步通信。该总线双向通信,可以实现全双工传输。 -- UART应用比较广泛,常用于输出打印信息,也可以外接各种模块,如GPS、蓝牙等。 -- 两个UART设备的连接示意图如下,UART与其他模块一般用2线(图1)或4线(图2)相连,它们分别是: - - TX:发送数据端,和对端的RX相连; - - RX:接收数据端,和对端的TX相连; - - RTS:发送请求信号,用于指示本设备是否准备好,可接受数据,和对端CTS相连; - - CTS:允许发送信号,用于判断是否可以向对端发送数据,和对端RTS相连; - - **图 1** 2线UART设备连接示意图 - - - ![](figures/zh-cn_image_0000001053926237.png) - - **图 2** 4线UART设备连接示意图 - - - ![](figures/zh-cn_image_0000001054007499.png) - - -- UART通信之前,收发双方需要约定好一些参数:波特率、数据格式(起始位、数据位、校验位、停止位)等。通信过程中,UART通过TX发送给对端数据,通过RX接收对端发送的数据。当UART接收缓存达到预定的门限值时,RTS变为不可发送数据,对端的CTS检测到不可发送数据,则停止发送数据。 -- UART接口定义了操作UART端口的通用方法集合,包括获取、释放设备句柄、读写数据、获取和设置波特率、获取和设置设备属性。 - -## 接口说明 - -**表 1** UART驱动API接口功能介绍 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    功能分类

    -

    接口名

    -

    描述

    -

    UART获取/释放设备句柄

    -

    -

    UartOpen

    -

    UART获取设备句柄

    -

    UartClose

    -

    UART释放设备句柄

    -

    UART读写接口

    -

    -

    UartRead

    -

    从UART设备中读取指定长度的数据

    -

    UartWrite

    -

    向UART设备中写入指定长度的数据

    -

    UART获取/设置波特率接口

    -

    UartGetBaud

    -

    UART获取波特率

    -

    UartSetBaud

    -

    UART设置波特率

    -

    UART获取/设置设备属性

    -

    -

    UartGetAttribute

    -

    UART获取设备属性

    -

    UartSetAttribute

    -

    UART设置设备属性

    -

    UART设置传输模式

    -

    UartSetTransMode

    -

    UART设置传输模式

    -
    - ->![](public_sys-resources/icon-note.gif) **说明:** ->本文涉及的所有接口,仅限内核态使用,不支持在用户态使用。 - diff --git a/zh-cn/device-dev/driver/WATCHDOG.md b/zh-cn/device-dev/driver/WATCHDOG.md deleted file mode 100755 index 0d7afef9e3..0000000000 --- a/zh-cn/device-dev/driver/WATCHDOG.md +++ /dev/null @@ -1,9 +0,0 @@ -# WATCHDOG - -- **[看门狗概述](看门狗概述.md)** - -- **[看门狗使用指导](看门狗使用指导.md)** - -- **[看门狗使用实例](看门狗使用实例.md)** - - diff --git a/zh-cn/device-dev/driver/WLAN.md b/zh-cn/device-dev/driver/WLAN.md deleted file mode 100755 index af39a0d3a2..0000000000 --- a/zh-cn/device-dev/driver/WLAN.md +++ /dev/null @@ -1,9 +0,0 @@ -# WLAN - -- **[WLAN开发概述](WLAN开发概述.md)** - -- **[WLAN开发指导](WLAN开发指导.md)** - -- **[WLAN开发实例](WLAN开发实例.md)** - - diff --git "a/zh-cn/device-dev/driver/WLAN\345\274\200\345\217\221\345\256\236\344\276\213.md" "b/zh-cn/device-dev/driver/WLAN\345\274\200\345\217\221\345\256\236\344\276\213.md" deleted file mode 100755 index bc558cb653..0000000000 --- "a/zh-cn/device-dev/driver/WLAN\345\274\200\345\217\221\345\256\236\344\276\213.md" +++ /dev/null @@ -1,372 +0,0 @@ -# WLAN开发实例 - -本例程提供WLAN模块初始化过程的完整使用流程。示例如下(以hi3881WLAN芯片为例): - -1、根据硬件,修改配置参数 - -``` -/* 根据硬件参数,通过wlan_platform.hcs配置相关参数,以下是WLAN平台配置的示例 */ -hisi :& deviceList { - device0 :: deviceInst { - deviceInstId = 0; - powers { - power0 { - powerSeqDelay = 0; /* 电源序列延时 */ - powerType = 1; /* 电源类型:0--总是打开;1--GPIO */ - gpioId = 1; /* GPIO管脚号 */ - activeLevel=1; /* 有效电平:0--低;1--高 */ - } - power1 { - powerSeqDelay = 0; /* 电源序列延时 */ - powerType = 0; /* 电源类型:0--总是打开;1--GPIO */ - } - } - reset { - resetType = 0; /* 复位类型:0--不管理;1--GPIO */ - gpioId = 2; /* GPIO管脚号 */ - activeLevel=1; /* 有效电平:0--低;1--高 */ - resetHoldTime = 30; /* 复位配置后的等待时间(ms) */ - } - bootUpTimeout = 30; /* 启动超时时间(ms) */ - bus { - busType = 0; /* 总线类型:0-sdio */ - busId = 2; /* 总线号 */ - funcNum = [1]; /* SDIO功能号 */ - timeout = 1000; /* 读/写数据的超时时间 */ - blockSize = 512; /* 读/写数据的块大小 */ - } - } -} -/* 每一块芯片添加配置文件wlan_chip_<芯片名>.hcs(如:wlan_chip_hi3881.hcs),配置相关参数。以下是hi3881的配置示例 */ -root { - wlan_config { - hi3881 :& chipList { - chipHi3881 :: chipInst { - match_attr = "hdf_wlan_chips_hi3881"; /* 配置匹配标识 */ - chipName = "hi3881"; /* WLAN芯片的名称 */ - sdio { - vendorId = 0x0296; /* 厂商Id */ - deviceId = [0x5347]; /* 设备Id */ - } - } - } - } -} -``` - -2、适配挂接WLAN芯片的初始化和去初始化、WLAN芯片驱动的初始化和去初始化 - -``` -/* WLAN初始化挂接流程 */ -#include "hdf_device_desc.h" -#include "hdf_wifi_product.h" -#include "hdf_log.h" -#include "osal_mem.h" -#include "hdf_wlan_chipdriver_manager.h" -#include "securec.h" -#include "wifi_module.h" -#include "hi_wifi_api.h" -#include "hi_types_base.h" - -#define HDF_LOG_TAG Hi3881Driver - -/* WLAN芯片的初始化和去初始化函数 */ -int32_t InitHi3881Chip(struct HdfWlanDevice *device); -int32_t DeinitHi3881Chip(struct HdfWlanDevice *device); -/* WLAN芯片驱动的初始化和去初始化函数 */ -int32_t Hi3881Deinit(struct HdfChipDriver* chipDriver, struct NetDevice *netDevice); -int32_t Hi3881Init(struct HdfChipDriver* chipDriver, struct NetDevice *netDevice); - -/* 初始化mac80211与芯片侧的函数挂接 */ -hi_void HiMac80211Init(struct HdfChipDriver *chipDriver); - -static const char* const HI3881_DRIVER_NAME = "hisi"; - -/* WLAN芯片驱动挂接以及mac80211与芯片侧的函数挂接 */ -static struct HdfChipDriver *BuildHi3881Driver(struct HdfWlanDevice *device, uint8_t ifIndex) -{ - struct HdfChipDriver *specificDriver = NULL; - if (device == NULL) { - HDF_LOGE("%s fail : channel is NULL", __func__); - return NULL; - } - (void)device; - (void)ifIndex; - specificDriver = (struct HdfChipDriver *)OsalMemCalloc(sizeof(struct HdfChipDriver)); - if (specificDriver == NULL) { - HDF_LOGE("%s fail: OsalMemCalloc fail!", __func__); - return NULL; - } - if (memset_s(specificDriver, sizeof(struct HdfChipDriver), 0, sizeof(struct HdfChipDriver)) != EOK) { - HDF_LOGE("%s fail: memset_s fail!", __func__); - OsalMemFree(specificDriver); - return NULL; - } - - if (strcpy_s(specificDriver->name, MAX_WIFI_COMPONENT_NAME_LEN, HI3881_DRIVER_NAME) != EOK) { - HDF_LOGE("%s fail : strcpy_s fail", __func__); - OsalMemFree(specificDriver); - return NULL; - } - specificDriver->init = Hi3881Init; - specificDriver->deinit = Hi3881Deinit; - - HiMac80211Init(specificDriver); - - return specificDriver; -} - -/* 释放WLAN芯片驱动 */ -static void ReleaseHi3881Driver(struct HdfChipDriver *chipDriver) -{ - if (chipDriver == NULL) { - return; - } - if (strcmp(chipDriver->name, HI3881_DRIVER_NAME) != 0) { - HDF_LOGE("%s:Not my driver!", __func__); - return; - } - OsalMemFree(chipDriver); -} - -static uint8_t GetHi3881GetMaxIFCount(struct HdfChipDriverFactory *factory) { - (void)factory; - return 1; -} - -/* WLAN芯片相关函数的注册 */ -static int32_t HDFWlanRegHisiDriverFactory(void) -{ - static struct HdfChipDriverFactory tmpFactory = { 0 }; - struct HdfChipDriverManager *driverMgr = NULL; - driverMgr = HdfWlanGetChipDriverMgr(); - if (driverMgr == NULL && driverMgr->RegChipDriver != NULL) { - HDF_LOGE("%s fail: driverMgr is NULL!", __func__); - return HDF_FAILURE; - } - tmpFactory.driverName = HI3881_DRIVER_NAME; - tmpFactory.GetMaxIFCount = GetHi3881GetMaxIFCount; - tmpFactory.InitChip = InitHi3881Chip; - tmpFactory.DeinitChip = DeinitHi3881Chip; - tmpFactory.Build = BuildHi3881Driver; - tmpFactory.Release = ReleaseHi3881Driver; - tmpFactory.ReleaseFactory = NULL; - if (driverMgr->RegChipDriver(&tmpFactory) != HDF_SUCCESS) { - HDF_LOGE("%s fail: driverMgr is NULL!", __func__); - return HDF_FAILURE; - } - - return HDF_SUCCESS; -} - -static int32_t HdfWlanHisiChipDriverInit(struct HdfDeviceObject *device) -{ - (void)device; - return HDFWlanRegHisiDriverFactory(); -} - -struct HdfDriverEntry g_hdfHisiChipEntry = { - .moduleVersion = 1, - .Init = HdfWlanHisiChipDriverInit, - .moduleName = "HDF_WLAN_CHIPS" -}; - -HDF_INIT(g_hdfHisiChipEntry); -``` - -``` -#include "hdf_wifi_product.h" -#include "hi_wifi_api.h" -#if (_PRE_OS_VERSION_LINUX == _PRE_OS_VERSION) -#include "oal_thread.h" -#include "osal_time.h" -#endif -#include "wifi_mac80211_ops.h" -#include "wal_cfg80211.h" -#include "net_adpater.h" -#include "hdf_wlan_utils.h" - -#define HDF_LOG_TAG Hi3881Driver - -/* WLAN芯片的初始化函数 */ -int32_t InitHi3881Chip(struct HdfWlanDevice *device) -{ - uint8_t maxPortCount = 1; - int32_t ret = HI_SUCCESS; - uint8_t maxRetryCount = 2; - if (device == NULL) { - HDF_LOGE("%s:NULL ptr!", __func__); - return HI_FAIL; - } - - do { - if (ret != HI_SUCCESS) { - if (device->reset != NULL && device->reset->Reset != NULL) { - device->reset->Reset(device->reset); - } - HDF_LOGE("%s:Retry init hi3881!last ret=%d", __func__, ret); - } - ret = hi_wifi_init(maxPortCount); - } while (ret != 0 && --maxRetryCount > 0); - - if (ret != 0) { - HDF_LOGE("%s:Init hi3881 driver failed!", __func__); - return ret; - } - return HI_SUCCESS; -} - -/* WLAN芯片的去初始化函数 */ -int32_t DeinitHi3881Chip(struct HdfWlanDevice *device) -{ - (void)device; - int32_t ret = hi_wifi_deinit(); - if (ret != 0) { - HDF_LOGE("%s:Deinit failed!ret=%d", __func__, ret); - } - return ret; -} - -/* WLAN芯片驱动的初始化函数 */ -int32_t Hi3881Init(struct HdfChipDriver *chipDriver, struct NetDevice *netDevice) -{ - HDF_LOGI("%s: start...", __func__); - hi_u16 mode = wal_get_vap_mode(); - int32_t ret; - nl80211_iftype_uint8 type; - (void)chipDriver; - - if (mode >= WAL_WIFI_MODE_BUTT) { - oam_error_log1(0, 0, "wal_init_drv_netdev:: invalid mode[%d]", mode); - return HI_FAIL; - } - - if (mode == WAL_WIFI_MODE_STA) { - type = NL80211_IFTYPE_STATION; - } else if (mode == WAL_WIFI_MODE_AP) { - type = NL80211_IFTYPE_AP; - } else { - oam_error_log1(0, 0, "wal_init_drv_netdev:: invalid mode[%d]", mode); - return HI_FAIL; - } - - ret = wal_init_drv_wlan_netdev(type, WAL_PHY_MODE_11N, netDevice); - if (ret != HI_SUCCESS) { - oam_error_log2(0, OAM_SF_ANY, "wal_init_drv_netdev %s failed.l_return:%d\n", netDevice->name, ret); - } - return ret; -} - -/* WLAN芯片驱动的去初始化函数 */ -int32_t Hi3881Deinit(struct HdfChipDriver *chipDriver, struct NetDevice *netDevice) -{ - (void)chipDriver; - int32_t ret = wal_deinit_drv_wlan_netdev(netDevice); - if (ret != HDF_SUCCESS) { - return ret; - } - return ReleasePlatformNetDevice(netDevice); -} -``` - -3、在芯片侧初始化过程中调用netdev的init和add接口进行初始化netdev,并挂接netdev的一些函数指针 - -``` -hi_s32 wal_init_drv_wlan_netdev(nl80211_iftype_uint8 type, wal_phy_mode mode, hi_char* ifname, hi_u32* len) -{ - oal_net_device_stru *netdev = HI_NULL; - - ...... - /* 初始化网络设备,获取对应的实例。*/ - netdev = NetDeviceInit(ifname, *len, LITE_OS); - oal_wireless_dev *wdev = (oal_wireless_dev *)oal_mem_alloc(OAL_MEM_POOL_ID_LOCAL, sizeof(oal_wireless_dev)); - ret = wal_init_netif(type, netdev, wdev); - - ...... - - return HI_SUCCESS; -} -/* 挂接netdev的一些函数指针,详细挂接函数{@link NetDeviceInterFace} */ -oal_net_device_ops_stru g_wal_net_dev_ops = -{ - .getStats = wal_netdev_get_stats, - .open = wal_netdev_open, - .stop = wal_netdev_stop, - .xmit = hmac_bridge_vap_xmit, - .ioctl = wal_net_device_ioctl, - .changeMtu = oal_net_device_change_mtu, - .init = oal_net_device_init, - .deInit = oal_net_free_netdev, -#if (defined(_PRE_WLAN_FEATURE_FLOWCTL) || defined(_PRE_WLAN_FEATURE_OFFLOAD_FLOWCTL)) - .selectQueue = wal_netdev_select_queue, -#endif - .setMacAddr = wal_netdev_set_mac_addr, -#if (_PRE_OS_VERSION_LITEOS == _PRE_OS_VERSION) - .netifNotify = HI_NULL, -#endif - .specialEtherTypeProcess = SpecialEtherTypeProcess, -}; - -hi_s32 wal_init_netif(nl80211_iftype_uint8 type, oal_net_device_stru *netdev, const oal_wireless_dev *wdev) -{ - /* 添加网络设备到协议栈 */ - hi_u32 ret = NetDeviceAdd(netdev, (Protocol80211IfType)type); - - ...... - - return HI_SUCCESS; -} -``` - -4、WifiMac80211Ops中的函数挂接实现 - -``` -/* 挂接mac80211的一些函数指针 */ - -/* 驱动需要实现的MAC层基本能力的控制接口 */ -static struct HdfMac80211BaseOps g_baseOps = { - .SetMode = WalSetMode, - .AddKey = WalAddKey, - .DelKey = WalDelKey, - .SetDefaultKey = WalSetDefaultKey, - .GetDeviceMacAddr = WalGetDeviceMacAddr, - .SetMacAddr = WalSetMacAddr, - .SetTxPower = WalSetTxPower, - .GetValidFreqsWithBand = WalGetValidFreqsWithBand, - .GetHwCapability = WalGetHwCapability -}; - -/* 驱动需要实现的MAC层STA能力的控制接口 */ -static struct HdfMac80211STAOps g_staOps = { - .Connect = WalConnect, - .Disconnect = WalDisconnect, - .StartScan = WalStartScan, - .AbortScan = WalAbortScan, - .SetScanningMacAddress = WalSetScanningMacAddress, -}; - -/* 驱动需要实现的MAC层AP能力的控制接口 */ -static struct HdfMac80211APOps g_apOps = { - .ConfigAp = WalConfigAp, - .StartAp = WalStartAp, - .StopAp = WalStopAp, - .ConfigBeacon = WalChangeBeacon, - .DelStation = WalDelStation, - .SetCountryCode = WalSetCountryCode, - .GetAssociatedStasCount = WalGetAssociatedStasCount, - .GetAssociatedStasInfo = WalGetAssociatedStasInfo -}; - -/* 初始化mac80211与芯片侧的函数挂接 */ -hi_void HiMac80211Init(struct HdfChipDriver *chipDriver) -{ - if (chipDriver == NULL) { - oam_error_log(0, OAM_SF_ANY, "%s:input is NULL!", __func__); - return; - } - chipDriver->ops = &g_baseOps; - chipDriver->staOps = &g_staOps; - chipDriver->apOps = &g_apOps; -} -``` - diff --git "a/zh-cn/device-dev/driver/WLAN\345\274\200\345\217\221\346\214\207\345\257\274.md" "b/zh-cn/device-dev/driver/WLAN\345\274\200\345\217\221\346\214\207\345\257\274.md" deleted file mode 100755 index 1a5d63663a..0000000000 --- "a/zh-cn/device-dev/driver/WLAN\345\274\200\345\217\221\346\214\207\345\257\274.md" +++ /dev/null @@ -1,18 +0,0 @@ -# WLAN开发指导 - -- [开发步骤](#section96091936185820) - -WLAN驱动基于HDF框架和PLATFORM框架开发,不区分OS和芯片平台,为不同厂商的WLAN模组提供统一的驱动模型,各WLAN模组厂商根据如下指导适配WLAN驱动框架。 - -## 开发步骤 - -1. 通过wifi\_config.hcs文件,配置硬件参数:module\(不同feature\),芯片等。 -2. 解析配置文件, 生成全量配置的结构体对象。 -3. Module初始化,创建Module。 -4. 挂接chip,初始化chip。 -5. 总线初始化。 -6. 上层wpa业务挂接。 - ->![](public_sys-resources/icon-note.gif) **说明:** ->以上驱动框架适配步骤一部分已经提供(详细见开发实例),待开发人员实现的部分有:1、根据硬件,修改配置参数;2、适配挂接chip;3、测试自验证。 - diff --git "a/zh-cn/device-dev/driver/WLAN\345\274\200\345\217\221\346\246\202\350\277\260.md" "b/zh-cn/device-dev/driver/WLAN\345\274\200\345\217\221\346\246\202\350\277\260.md" deleted file mode 100755 index 869ee1da51..0000000000 --- "a/zh-cn/device-dev/driver/WLAN\345\274\200\345\217\221\346\246\202\350\277\260.md" +++ /dev/null @@ -1,229 +0,0 @@ -# WLAN开发概述 - -- [简介](#section23087361515) -- [WLAN驱动接口架构](#section1533192516212) -- [接口说明](#section87491484213) - -## 简介 - -WLAN是基于HDF(Hardware Driver Foundation)驱动框架开发的模块,该模块可实现跨操作系统迁移,自适应器件差异,模块化拼装编译等功能。各WLAN厂商驱动开发人员可根据WLAN模块提供的向下统一接口适配各自的驱动代码,实现如下能力:建立/关闭WLAN热点、扫描、关联WLAN热点等;对HDI层向上提供能力如下:设置MAC地址、设置发射功率、获取设备的MAC地址等。[WLAN模块框架图](#fig967034316227)如下: - -**图 1** WLAN框架 - - -![](figures/zh-cn_image_0000001055299108.png) - -## WLAN驱动接口架构 - -WLAN模块有三部分对外开放的API接口,如[下图2](#fig15016395217)所示: - -1. 对HDI层提供的能力接口。 - -2. 驱动直接调用WLAN模块能力接口。 - -3. 提供给各厂商实现的能力接口。 - -**图 2** WLAN模块开放能力分布图 - - -![](figures/接口分布图4.png) - -## 接口说明 - -WLAN驱动模块提供给驱动开发人员可直接调用的能力接口,主要功能有:创建/释放WifiModule、关联/取消关联、申请/释放NetBuf、lwip的pbuf和NetBuf的相互转换等。提供的部分接口说明如[表1](#table1521573319472)所示: - -**表 1** 可直接调用的接口 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    头文件

    -

    接口名称

    -

    功能描述

    -

    wifi_module.h

    -

    -

    struct WifiModule *WifiModuleCreate(const struct HdfConfigWifiModuleConfig *config);

    -

    基于HDF开发WLAN驱动时,创建一个WifiModule。

    -

    void WifiModuleDelete(struct WifiModule *module);

    -

    基于HDF开发WLAN驱动时,删除并释放WifiModule所有数据。

    -

    int32_t DelFeature(struct WifiModule *module, uint16_t featureType);

    -

    基于HDF开发WLAN驱动时,从WifiModule删除一个功能组件。

    -

    int32_t AddFeature(struct WifiModule *module, uint16_t featureType, struct WifiFeature *featureData);

    -

    基于HDF开发WLAN驱动时,注册一个功能组件到WifiModule。

    -

    wifi_mac80211_ops.h

    -

    int32_t (*startAp)(NetDevice *netDev);

    -

    启动AP。

    -

    int32_t (*stopAp)(NetDevice *netDev);

    -

    停止AP。

    -

    int32_t (*connect)(NetDevice *netDev, WifiConnectParams *param);

    -

    开始关联。

    -

    int32_t (*disconnect)(NetDevice *netDev, uint16_t reasonCode);

    -

    取消关联。

    -

    hdf_netbuf.h

    -

    static inline void NetBufQueueInit(struct NetBufQueue *q);

    -

    初始化NetBuf队列。

    -

    struct NetBuf *NetBufAlloc(uint32_t size);

    -

    申请NetBuf。

    -

    void NetBufFree(struct NetBuf *nb);

    -

    释放NetBuf。

    -

    struct NetBuf *Pbuf2NetBuf(const struct NetDevice *netdev, struct pbuf *lwipBuf);

    -

    lwip的pbuf转换为NetBuf。

    -

    struct pbuf *NetBuf2Pbuf(const struct NetBuf *nb);

    -

    NetBuf转换为lwip的pbuf。

    -
    - -同时WLAN驱动模块也提供了需要驱动开发人员实现的能力接口,主要功能有:初始化/注销NetDevice、打开/关闭NetDevice、获取NetDevice的状态等。提供的部分接口说明如[表2](#table74613501475)所示: - -**表 2** 需要开发人员实现的接口 - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    头文件

    -

    接口名称

    -

    功能描述

    -

    net_device.h

    -

    int32_t (*init)(struct NetDevice *netDev);

    -

    初始化NetDevice。

    -

    struct NetDevStats *(*getStats)(struct NetDevice *netDev);

    -

    获取NetDevice的状态。

    -

    int32_t (*setMacAddr)(struct NetDevice *netDev, void *addr);

    -

    设置Mac地址。

    -

    void (*deInit)(struct NetDevice *netDev);

    -

    注销NetDevice。

    -

    int32_t (*open)(struct NetDevice *netDev);

    -

    打开NetDevice。

    -

    int32_t (*stop)(struct NetDevice *netDev);

    -

    关闭NetDevice。

    -
    - -WLAN驱动模块对HDI层提供的能力接口,主要功能有:创建/销毁 IWiFi对象、设置MAC地址等。提供的部分接口说明如[表3](#table141076311618)所示: - -**表 3** HAL层对外接口 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    头文件

    -

    接口名称

    -

    功能描述

    -

    wifi_hal.h

    -

    -

    int32_t WifiConstruct(struct IWiFi **wifiInstance);

    -

    创建IWiFi对象,提供IWiFi基本能力。

    -

    int32_t WifiDestruct(struct IWiFi **wifiInstance);

    -

    销毁IWiFi对象。

    -

    int32_t (*start)(struct IWiFi *);

    -

    创建HAL和驱动之间的通道及获取驱动支持的网卡信息。

    -

    int32_t (*stop)(struct IWiFi *);

    -

    销毁通道。

    -

    wifi_hal_base_feature.h

    -

    int32_t (*getFeatureType)(const struct IWiFiBaseFeature *);

    -

    获取特性的类型。

    -

    int32_t (*setMacAddress)(const struct IWiFiBaseFeature *, unsigned char *, uint8_t);

    -

    设置MAC地址。

    -

    int32_t (*getDeviceMacAddress)(const struct IWiFiBaseFeature *, unsigned char *, uint8_t);

    -

    获取设备持久化的MAC地址。

    -

    int32_t (*setTxPower)(const struct IWiFiBaseFeature *, int32_t);

    -

    设置发射功率。

    -
    - diff --git a/zh-cn/device-dev/driver/drive-hdf-development.md b/zh-cn/device-dev/driver/drive-hdf-development.md new file mode 100644 index 0000000000..b01173490a --- /dev/null +++ b/zh-cn/device-dev/driver/drive-hdf-development.md @@ -0,0 +1,175 @@ +# 驱动开发 + +- [驱动模型介绍](#section157425168112) +- [驱动开发步骤](#section1969312275533) + +## 驱动模型介绍 + +HDF框架以组件化的驱动模型作为核心设计思路,为开发者提供更精细化的驱动管理,让驱动开发和部署更加规范。HDF框架将一类设备驱动放在同一个host里面,开发者也可以将驱动功能分层独立开发和部署,支持一个驱动多个node,HDF驱动模型如下图所示: + +**图 1** HDF驱动模型 + + +![](figure/zh-cn_image_0000001054564784.png) + +## 驱动开发步骤 + +基于HDF框架进行驱动的开发主要分为两个部分,驱动实现和驱动配置,详细开发流程如下所示: + +1. 驱动实现 + + 驱动实现包含驱动业务代码和驱动入口注册,具体写法如下: + + - 驱动业务代码 + + ``` + #include "hdf_device_desc.h" // HDF框架对驱动开放相关能力接口的头文件 + #include "hdf_log.h" // HDF 框架提供的日志接口头文件 + + #define HDF_LOG_TAG "sample_driver" // 打印日志所包含的标签,如果不定义则用默认定义的HDF_TAG标签 + + //驱动对外提供的服务能力,将相关的服务接口绑定到HDF框架 + int32_t HdfSampleDriverBind(struct HdfDeviceObject *deviceObject) + { + HDF_LOGD("Sample driver bind success"); + return 0; + } + + // 驱动自身业务初始的接口 + int32_t HdfSampleDriverInit(struct HdfDeviceObject *deviceObject) + { + HDF_LOGD("Sample driver Init success"); + return 0; + } + + // 驱动资源释放的接口 + void HdfSampleDriverRelease(struct HdfDeviceObject *deviceObject) + { + HDF_LOGD("Sample driver release success"); + return; + } + ``` + + - 驱动入口注册到HDF框架 + + ``` + // 定义驱动入口的对象,必须为HdfDriverEntry(在hdf_device_desc.h中定义)类型的全局变量 + struct HdfDriverEntry g_sampleDriverEntry = { + .moduleVersion = 1, + .moduleName = "sample_driver", + .Bind = HdfSampleDriverBind, + .Init = HdfSampleDriverInit, + .Release = HdfSampleDriverRelease, + }; + + // 调用HDF_INIT将驱动入口注册到HDF框架中,在加载驱动时HDF框架会先调用Bind函数,再调用Init函数加载该驱动,当Init调用异常时,HDF框架会调用Release释放驱动资源并退出。 + HDF_INIT(g_sampleDriverEntry); + ``` + + +2. 驱动编译 + - 驱动代码的编译必须要使用HDF框架提供的Makefile模板进行编译。 + + ``` + include $(LITEOSTOPDIR)/../../drivers/adapter/lite/khdf/lite.mk #导入hdf预定义内容,必需 + MODULE_NAME := #生成的结果文件 + LOCAL_INCLUDE := #本驱动的头文件目录 + LOCAL_SRCS := #本驱动的源代码文件 + LOCAL_CFLAGS := #自定义的编译选项 + include $(HDF_DRIVER) #导入模板makefile完成编译 + ``` + + - 编译结果文件链接到内核镜像,添加到vendor目录下的hdf\_vendor.mk里面,示例如下: + + ``` + LITEOS_BASELIB += -lxxx #链接生成的静态库 + LIB_SUBDIRS += #驱动代码Makefile的目录 + ``` + + +3. 驱动配置 + + HDF使用HCS作为配置描述源码,HCS详细介绍参考[配置管理](drive-hdf-manage.md)介绍。 + + 驱动配置包含两部分,HDF框架定义的驱动设备描述和驱动的私有配置信息,具体写法如下: + + - 驱动设备描述(必选) + + HDF框架加载驱动所需要的信息来源于HDF框架定义的驱动设备描述,因此基于HDF框架开发的驱动必须要在HDF框架定义的device\_info.hcs配置文件中添加对应的设备描述,驱动的设备描述填写如下所示: + + ``` + root { + device_info { + match_attr = "hdf_manager"; + template host { // host模板,继承该模板的节点(如下sample_host)如果使用模板中的默认值,则节点字段可以缺省 + hostName = ""; + priority = 100; + template device { + template deviceNode { + policy = 0; + priority = 100; + preload = 0; + permission = 0664; + moduleName = ""; + serviceName = ""; + deviceMatchAttr = ""; + } + } + } + sample_host :: host{ + hostName = "host0"; // host名称,host节点是用来存放某一类驱动的容器 + priority = 100; // host启动优先级(0-200),值越大优先级越低,建议默认配100,优先级相同则不保证host的加载顺序 + device_sample :: device { // sample设备节点 + device0 :: deviceNode { // sample驱动的DeviceNode节点 + policy = 1; // policy字段是驱动服务发布的策略,在驱动服务管理章节有详细介绍 + priority = 100; // 驱动启动优先级(0-200),值越大优先级越低,建议默认配100,优先级相同则不保证device的加载顺序 + preload = 0; // 驱动按需加载字段,在本章节最后的说明有详细介绍 + permission = 0664; // 驱动创建设备节点权限 + moduleName = "sample_driver"; // 驱动名称,该字段的值必须和驱动入口结构的moduleName值一致 + serviceName = "sample_service"; // 驱动对外发布服务的名称,必须唯一 + deviceMatchAttr = "sample_config"; // 驱动私有数据匹配的关键字,必须和驱动私有数据配置表中的match_attr值相等 + } + } + } + } + } + ``` + + - 驱动私有配置信息(可选) + + 如果驱动有私有配置,则可以添加一个驱动的配置文件,用来填写一些驱动的默认配置信息,HDF框架在加载驱动的时候,会将对应的配置信息获取并保存在HdfDeviceObject 中的property里面,通过Bind和Init(参考[驱动开发](#li35182436435))传递给驱动,驱动的配置信息示例如下: + + ``` + root { + SampleDriverConfig { + sample_version = 1; + sample_bus = "I2C_0"; + match_attr = "sample_config"; //该字段的值必须和device_info.hcs中的deviceMatchAttr值一致 + } + } + ``` + + 配置信息定义之后,需要将该配置文件添加到板级配置入口文件hdf.hcs(这一块可以通过OpenHarmony驱动子系统在DevEco集成驱动开发套件工具一键式配置,具体使用方法参考驱动开发套件中的介绍),示例如下: + + ``` + #include "device_info/device_info.hcs" + #include "sample/sample_config.hcs" + ``` + + + +>![](../public_sys-resources/icon-note.gif) **说明:** +>驱动加载方式支持按需加载和按序加载两种方式,具体使用方法如下: +>- 按需加载 +> ``` +> typedef enum { +> DEVICE_PRELOAD_ENABLE = 0, +> DEVICE_PRELOAD_ENABLE_STEP2, +> DEVICE_PRELOAD_DISABLE, +> DEVICE_PRELOAD_INVALID +> } DevicePreload; +> ``` +> 配置文件中preload 字段配成 0 (DEVICE\_PRELOAD\_ENABLE ),则系统启动过程中默认加载;配成1(DEVICE\_PRELOAD\_ENABLE\_STEP2),当系统支持快启的时候,则在系统系统完成之后再加载这一类驱动,否则和DEVICE\_PRELOAD\_ENABLE 含义相同;配成2(DEVICE\_PRELOAD\_DISABLE),则系统启动过程中默认不加载,支持后续动态加载,当用户态获取驱动服务(参考[消息机制](drive-hdf-news.md))时,如果驱动服务不存在时,HDF框架会尝试动态加载该驱动。 +>- 按序加载(需要驱动为默认加载) +> 配置文件中的priority(取值范围为整数0到200)是用来表示host和驱动的优先级,不同的host内的驱动,host的priority值越小,驱动加载优先级越高;同一个host内驱动的priority值越小,加载优先级越高。 + diff --git a/zh-cn/device-dev/driver/drive-hdf-manage.md b/zh-cn/device-dev/driver/drive-hdf-manage.md new file mode 100644 index 0000000000..86cc85d8c7 --- /dev/null +++ b/zh-cn/device-dev/driver/drive-hdf-manage.md @@ -0,0 +1,437 @@ +# 配置管理 + +- [配置概述](#section59914284576) +- [配置语法](#section533713333580) +- [关键字](#section1316625413586) +- [基本结构](#section173481622115918) +- [数据类型](#section96521601302) +- [预处理](#section8164295515) +- [注释](#section0338205819610) +- [引用修改](#section179799204716) +- [节点复制](#section382424014712) +- [删除](#section165211112586) +- [属性引用](#section192841514490) +- [模板](#section520134294) +- [配置生成](#section106152531919) +- [hc-gen介绍](#section8260625101012) + +## 配置概述 + +HCS\(**H**DF **C**onfiguration **S**ource\)是HDF驱动框架的配置描述源码,内容以Key-Value为主要形式。它实现了配置代码与驱动代码解耦,便于开发者进行配置管理。 + +HC-GEN**\(H**DF **C**onfiguration **G**enerator**\)**是HCS配置转换工具,可以将HDF配置文件转换为软件可读取的文件格式: + +- 在弱性能环境中,转换为配置树源码,驱动可直接调用C代码获取配置。 +- 在高性能环境中,转换为HCB\(**H**DF **C**onfiguration **B**inary\)二进制文件,驱动可使用HDF框架提供的配置解析接口获取配置。 + +以下是使用HCB模式的典型应用场景: + +**图 1** 配置使用流程图 + + +![](figure/zh-cn_image_0000001053405727.png) + +HCS经过HC-GEN编译生成HCB文件,HDF驱动框架中的HCS Parser模块会从HCB文件中重建配置树,HDF驱动模块使用HCS Parser提供的配置读取接口获取配置内容。 + +## 配置语法 + +HCS的语法介绍如下: + +## 关键字 + +HCS配置语法保留了以下关键字。 + +**表 1** HCS配置语法保留关键字 + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    关键字

    +

    用途

    +

    说明

    +

    root

    +

    配置根节点

    +

    -

    +

    include

    +

    引用其他HCS配置文件

    +

    -

    +

    delete

    +

    删除节点或属性

    +

    只能用于操作include导入的配置树

    +

    template

    +

    定义模板节点

    +

    -

    +

    match_attr

    +

    用于标记节点的匹配查找属性

    +

    解析配置时可以使用该属性的值查找到对应节点

    +
    + +## 基本结构 + +HCS主要分为属性\(Attribute\)和节点\(Node\)两种结构。 + +**属性** + +属性即最小的配置单元,是一个独立的配置项。语法如下: + +``` + attribute_name = value; +``` + +- attribute\_name 是**字母、数字、下划线**的组合且必须以字母或下划线开头,字母区分大小写。 + +- value的可用格式如下: + + - 数字常量,支持二进制、八进制、十进制、十六进制数,具体参考数据类型节。 + + - 字符串,内容使用双引号\(""\)引用。 + + - 节点引用。 + + +- attribute 必须以分号\(;\)结束且必须属于一个node。 + + +**节点** + +节点是一组属性的集合,语法如下: + +``` + node_name { + module = "sample"; + ... + } +``` + +- node\_name 是**字母、数字、下划线**的组合且必须以字母或下划线开头,字母区分大小写。 + +- 大括号后无需添加结束符“;”。 + +- root为保留关键字,用于声明配置表的根节点。每个配置表必须以root节点开始。 + +- root节点中必须包含module属性,其值应该为一个字符串,用于表征该配置所属模块。 + +- 节点中可以增加match\_attr属性,其值为一个全局唯一的字符串。在解析配置时可以调用查找接口以该属性的值查找到包含该属性的节点。 + +## 数据类型 + +在属性定义中使用自动数据类型,不显式指定类型,属性支持的数据类型如下: + +**整型** + +整型长度自动推断,根据实际数据长度给与最小空间占用的类型。 + +- 二进制,0b前缀,示例:0b1010。 + +- 八进制,0前缀,示例:0664。 +- 十进制 ,无前缀,且支持有符号与无符号,示例:1024,+1024均合法。负值在读取时注意使用有符号数读取接口。 + +- 十六进制,0x前缀,示例:0xff00、0xFF。 + + +**字符串** + +字符串使用双引号\(""\)表示。 + +**数组** + +数组元素支持整型、字符串,不支持混合类型。整型数组中uint32\_t uint64\_t混用会向上转型为uint64\_t 数组。整型数组与字符串数组示例如下: + +``` +attr_foo = [0x01, 0x02, 0x03, 0x04]; +attr_bar = ["hello", "world"]; +``` + +**bool类型** + +bool类型中**true**表示真,**false**表示假。 + +## 预处理 + +**include** + +用于导入其他HCS文件。语法示例如下: + +``` +#include "foo.hcs" +#include "../bar.hcs" +``` + +- 文件名必须使用双引号\(""\),不在同一目录使用相对路径引用。被include文件也必须是合法的HCS文件。 +- 多个include,如果存在相同的节点,后者覆盖前者,其余的节点依次展开。 + +## 注释 + +支持两种注释风格。 + +- 单行注释。 + + ``` + // comment + ``` + +- 多行注释。 + + ``` + /* + comment + */ + ``` + + >![](../public_sys-resources/icon-note.gif) **说明:** + >多行注释不支持嵌套。 + + +## 引用修改 + +引用修改可以实现修改另外任意一个节点的内容,语法为: + +``` + node :& source_node +``` + +上述语句表示node中的内容是对source\_node节点内容的修改。示例如下: + +``` +root { + module = "sample"; + foo { + foo_ :& root.bar{ + attr = "foo"; + } + foo1 :& foo2 { + attr = 0x2; + } + foo2 { + attr = 0x1; + } + } + + bar { + attr = "bar"; + } +} +``` + +最终生成配置树为: + +``` +root { + module = "sample"; + foo { + foo2 { + attr = 0x2; + } + } + bar { + attr = "foo"; + } +} +``` + +在以上示例中,可以看到foo.foo\_节点通过引用将bar.attr属性的值修改为了"foo",foo.foo1节点通过引用将foo.foo2.attr属性的值修改为了0x2。foo.foo\_以及foo.foo1节点表示对目标节点内容的修改,其自身并不会存在最终生成的配置树中。 + +- 引用同级node,可以直接使用node名称,否则被引用的节点必须使用绝对路径,节点间使用“.”分隔,root表示根节点,格式为root开始的节点路径序列,例如root.foo.bar即为一个合法的绝对路径。 +- 如果出现修改冲突(即多处修改同一个属性),编译器将提示warning,因为这种情况下只会生效某一个修改而导致最终结果不确定。 + +## 节点复制 + +节点复制可以实现在节点定义时从另一个节点先复制内容,用于定义内容相似的节点。语法为: + +``` + node : source_node +``` + +上述语句表示在定义"node"节点时将另一个节点"source\_node"的属性复制过来。示例如下: + +``` +root { + module = "sample"; + foo { + attr_0 = 0x0; + } + bar:foo { + attr_1 = 0x1; + } +} +``` + +上述代码的最终生成配置树为: + +``` +root { + module = "sample"; + foo { + attr_0 = 0x0; + } + bar { + attr_1 = 0x1; + attr_0 = 0x0; + } +} +``` + +在上述示例中,编译后bar节点即包含attr\_0属性也包含attr\_1属性,在bar中对attr\_0的修改不会影响到foo。 + +在foo和bar在同级node中可不指定foo的路径,否则需要使用绝对路径引用,参考[引用修改](#section179799204716)。 + +## 删除 + +要对include导入的base配置树中不需要的节点或属性进行删除,可以使用delete关键字。下面的举例中sample1.hcs通过include导入了sample2.hcs中的配置内容,并使用delete删除了sample2.hcs中的attribute2属性和foo\_2节点,示例如下: + +``` +// sample2.hcs +root { + attr_1 = 0x1; + attr_2 = 0x2; + foo_2 { + t = 0x1; + } +} + +// sample1.hcs +#include "sample2.hcs" +root { + attr_2 = delete; + foo_2 : delete { + } +} +``` + +上述代码在生成过程中将会删除root.foo\_2节点与attr\_2,最终生成配置树为: + +``` +root { + attr_1 = 0x1; +} +``` + +>![](../public_sys-resources/icon-note.gif) **说明:** +>在同一个HCS文件中不允许使用delete,建议直接删除不需要的属性。 + +## 属性引用 + +为了在解析配置时快速定位到关联的节点,可以把节点作为属性的右值,通过读取属性查找到对应节点。语法为: + +``` + attribute = &node; +``` + +上述语句表示attribute的值是一个节点node的引用,在解析时可以用这个attribute快速定位到node,便于关联和查询其他node。示例如下: + +``` +node1 { + attributes; +} + +node2 { + attr_1 = &node1; +} +``` + +## 模板 + +模板的用途在于生成严格一致的node结构,以便对同类型node进行遍历和管理。 + +使用template关键字定义模板node,子node通过双冒号“::”声明继承关系。子节点可以改写但不能新增和删除template中的属性,子节点中没有定义的属性将使用template中的定义作为默认值。示例如下: + +``` +root { + module = "sample"; + template foo { + attr_1 = 0x1; + attr_2 = 0x2; + } + + bar :: foo { + } + + bar_1 :: foo { + attr_1 = 0x2; + } +} +``` + +生成配置树如下: + +``` +root { + module = "sample"; + bar { + attr_1 = 0x1; + attr_2 = 0x2; + } + bar_1 { + attr_1 = 0x2; + attr_2 = 0x2; + } +} +``` + +在上述示例中,bar和bar\_1节点继承了foo节点,生成配置树节点结构与foo保持了完全一致,只是属性的值不同。 + +## 配置生成 + +hc-gen是配置生成的工具,可以对HCS配置语法进行检查并把HCS源文件转化成HCB二进制文件。 + +## hc-gen介绍 + +hc-gen参数说明: + +``` +Usage: hc-gen [Options] [File] +options: + -o output file name, default same as input + -a hcb align with four bytes + -b output binary output, default enable + -t output config in C language source file style + -i output binary hex dump in C language source file style + -p prefix of generated symbol name + -d decompile hcb to hcs + -V show verbose info + -v show version + -h show this help message +``` + +生成.c/.h 配置文件方法: + +``` +hc-gen -o [OutputCFileName] -t [SourceHcsFileName] +``` + +生成HCB 配置文件方法: + +``` +hc-gen -o [OutputHcbFileName] -b [SourceHcsFileName] +``` + +反编译HCB文件为HCS方法: + +``` +hc-gen -o [OutputHcsFileName] -d [SourceHcbFileName] +``` + diff --git a/zh-cn/device-dev/driver/drive-hdf-news.md b/zh-cn/device-dev/driver/drive-hdf-news.md new file mode 100644 index 0000000000..d57a99d58b --- /dev/null +++ b/zh-cn/device-dev/driver/drive-hdf-news.md @@ -0,0 +1,193 @@ +# 驱动消息机制管理 + +- [使用场景](#section33014541954) +- [接口说明](#section538852311616) +- [开发步骤](#section946912121153) + +## 使用场景 + +当用户态应用和内核态驱动需要交互时,可以使用HDF框架的消息机制来实现。 + +## 接口说明 + +消息机制的功能主要有以下两种: + +1. 用户态应用发送消息到驱动。 +2. 用户态应用接收驱动主动上报事件。 + +**表 1** 消息机制接口 + + + + + + + + + + + + + + + + + + + +

    方法

    +

    描述

    +

    struct HdfIoService *HdfIoServiceBind(const char *serviceName)

    +

    用户态获取驱动的服务,获取该服务之后通过服务中的Dispatch方法向驱动发送消息。

    +

    void HdfIoServiceRecycle(struct HdfIoService *service);

    +

    释放驱动服务。

    +

    int HdfDeviceRegisterEventListener(struct HdfIoService *target, struct HdfDevEventlistener *listener);

    +

    用户态程序注册接收驱动上报事件的操作方法。

    +

    int HdfDeviceSendEvent(struct HdfDeviceObject *deviceObject, uint32_t id, struct HdfSBuf *data);

    +

    驱动主动上报事件接口。

    +
    + +## 开发步骤 + +1. 将驱动配置信息中服务策略policy字段设置为2(SERVICE\_POLICY\_CAPACITY,参考[policy定义](drive-hdf-servicemanage.md))。 + + ``` + device_sample :: Device { + policy = 2; + ... + } + ``` + +2. 配置驱动信息中的服务设备节点权限(permission字段)是框架给驱动创建设备节点的权限,默认是0666,驱动开发者根据驱动的实际使用场景配置驱动设备节点的权限。 +3. 在服务实现过程中,实现服务基类成员IDeviceIoService中的Dispatch方法。 + + ``` + // Dispatch是用来处理用户态发下来的消息 + int32_t SampleDriverDispatch(struct HdfDeviceObject *device, int cmdCode, struct HdfSBuf *data, struct HdfSBuf *reply) + { + HDF_LOGE("sample driver lite A dispatch"); + return 0; + } + int32_t SampleDriverBind(struct HdfDeviceObject *device) + { + HDF_LOGE("test for lite os sample driver A Open!"); + if (device == NULL) { + HDF_LOGE("test for lite os sample driver A Open failed!"); + return -1; + } + static struct ISampleDriverService sampleDriverA = { + .ioService.Dispatch = SampleDriverDispatch, + .ServiceA = SampleDriverServiceA, + .ServiceB = SampleDriverServiceB, + }; + device->service = (struct IDeviceIoService *)(&sampleDriverA); + return 0; + } + ``` + +4. 驱动定义消息处理函数中的cmd类型。 + + ``` + #define SAMPLE_WRITE_READ 1 // 读写操作码1 + ``` + +5. 用户态获取服务接口并发送消息到驱动。 + + ``` + int SendMsg(const char *testMsg) + { + if (testMsg == NULL) { + HDF_LOGE("test msg is null"); + return -1; + } + struct HdfIoService *serv = HdfIoServiceBind("sample_driver"); + if (serv == NULL) { + HDF_LOGE("fail to get service"); + return -1; + } + struct HdfSBuf *data = HdfSBufObtainDefaultSize(); + if (data == NULL) { + HDF_LOGE("fail to obtain sbuf data"); + return -1; + } + struct HdfSBuf *reply = HdfSBufObtainDefaultSize(); + if (reply == NULL) { + HDF_LOGE("fail to obtain sbuf reply"); + ret = HDF_DEV_ERR_NO_MEMORY; + goto out; + } + if (!HdfSbufWriteString(data, testMsg)) { + HDF_LOGE("fail to write sbuf"); + ret = HDF_FAILURE; + goto out; + } + int ret = serv->dispatcher->Dispatch(&serv->object, SAMPLE_WRITE_READ, data, reply); + if (ret != HDF_SUCCESS) { + HDF_LOGE("fail to send service call"); + goto out; + } + out: + HdfSBufRecycle(data); + HdfSBufRecycle(reply); + HdfIoServiceRecycle(serv); + return ret; + } + ``` + +6. 用户态接收该驱动上报的消息。 + 1. 用户态编写驱动上报消息的处理函数。 + + ``` + static int OnDevEventReceived(void *priv, uint32_t id, struct HdfSBuf *data) + { + OsalTimespec time; + OsalGetTime(&time); + HDF_LOGE("%s received event at %llu.%llu", (char *)priv, time.sec, time.usec); + + const char *string = HdfSbufReadString(data); + if (string == NULL) { + HDF_LOGE("fail to read string in event data"); + return -1; + } + HDF_LOGE("%s: dev event received: %d %s", (char *)priv, id, string); + return 0; + } + ``` + + 2. 用户态注册接收驱动上报消息的操作方法。 + + ``` + int RegisterListen() + { + struct HdfIoService *serv = HdfIoServiceBind("sample_driver"); + if (serv == NULL) { + HDF_LOGE("fail to get service"); + return -1; + } + static struct HdfDevEventlistener listener = { + .callBack = OnDevEventReceived, + .priv ="Service0" + }; + if (HdfDeviceRegisterEventListener(serv, &listener) != 0) { + HDF_LOGE("fail to register event listener"); + return -1; + } + ...... + HdfDeviceUnregisterEventListener(serv, &listener); + HdfIoServiceRecycle(serv); + return 0; + } + ``` + + 3. 驱动上报事件。 + + ``` + int32_t SampleDriverDispatch(struct HdfDeviceObject *device, int cmdCode, struct HdfSBuf *data, struct HdfSBuf *reply) + { + ... // process api call here + return HdfDeviceSendEvent(deviceObject, cmdCode, data); + } + ``` + + + diff --git "a/zh-cn/device-dev/driver/HDF\345\274\200\345\217\221\346\246\202\350\277\260.md" b/zh-cn/device-dev/driver/drive-hdf-overview.md old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/driver/HDF\345\274\200\345\217\221\346\246\202\350\277\260.md" rename to zh-cn/device-dev/driver/drive-hdf-overview.md diff --git a/zh-cn/device-dev/driver/drive-hdf-sample.md b/zh-cn/device-dev/driver/drive-hdf-sample.md new file mode 100644 index 0000000000..0cc2f0686f --- /dev/null +++ b/zh-cn/device-dev/driver/drive-hdf-sample.md @@ -0,0 +1,238 @@ +# HDF开发实例 + +- [添加配置](#section27261067111) +- [编写驱动代码](#section177988005) +- [编写用户程序和驱动交互代码](#section6205173816412) + +下面基于HDF框架,提供一个完整的样例,包含配置文件的添加,驱动代码的实现以及用户态程序和驱动交互的流程。 + +## 添加配置 + +在HDF框架的配置文件(例如vendor/hisilicon/xxx/config/device\_info)中添加该驱动的配置信息,如下所示: + +``` +root { + device_info { + match_attr = "hdf_manager"; + template host { + hostName = ""; + priority = 100; + template device { + template deviceNode { + policy = 0; + priority = 100; + preload = 0; + permission = 0664; + moduleName = ""; + serviceName = ""; + deviceMatchAttr = ""; + } + } + } + sample_host :: host { + hostName = "sample_host"; + sample_device :: device { + device0 :: deviceNode { + policy = 2; + priority = 100; + preload = 1; + permission = 0664; + moduleName = "sample_driver"; + serviceName = "sample_service"; + } + } + } + } +} +``` + +## 编写驱动代码 + +基于HDF框架编写的sample驱动代码如下: + +``` +#include +#include +#include +#include "hdf_log.h" +#include "hdf_base.h" +#include "hdf_device_desc.h" + +#define HDF_LOG_TAG "sample_driver" + +#define SAMPLE_WRITE_READ 123 + +int32_t HdfSampleDriverDispatch( + struct HdfDeviceObject *deviceObject, int id, struct HdfSBuf *data, struct HdfSBuf *reply) +{ + HDF_LOGE("%s: received cmd %d", __func__, id); + if (id == SAMPLE_WRITE_READ) { + const char *readData = HdfSbufReadString(data); + if (readData != NULL) { + HDF_LOGE("%s: read data is: %s", __func__, readData); + } + if (!HdfSbufWriteInt32(reply, INT32_MAX)) { + HDF_LOGE("%s: reply int32 fail", __func__); + } + return HdfDeviceSendEvent(deviceObject, id, data); + } + return HDF_FAILURE; +} + +void HdfSampleDriverRelease(struct HdfDeviceObject *deviceObject) +{ + // release resources here + return; +} + +int HdfSampleDriverBind(struct HdfDeviceObject *deviceObject) +{ + if (deviceObject == NULL) { + return HDF_FAILURE; + } + static struct IDeviceIoService testService = { + .Dispatch = HdfSampleDriverDispatch, + }; + deviceObject->service = &testService; + return HDF_SUCCESS; +} + +int HdfSampleDriverInit(struct HdfDeviceObject *deviceObject) +{ + if (deviceObject == NULL) { + HDF_LOGE("%s::ptr is null!", __func__); + return HDF_FAILURE; + } + HDF_LOGE("Sample driver Init success"); + return HDF_SUCCESS; +} + +struct HdfDriverEntry g_sampleDriverEntry = { + .moduleVersion = 1, + .moduleName = "sample_driver", + .Bind = HdfSampleDriverBind, + .Init = HdfSampleDriverInit, + .Release = HdfSampleDriverRelease, +}; + +HDF_INIT(g_sampleDriverEntry); +``` + +## 编写用户程序和驱动交互代码 + +基于HDF框架编写的用户态程序和驱动交互的代码如下: + +``` +#include +#include +#include +#include +#include "hdf_log.h" +#include "hdf_sbuf.h" +#include "hdf_io_service_if.h" + +#define HDF_LOG_TAG "sample_test" +#define SAMPLE_SERVICE_NAME "sample_service" + +#define SAMPLE_WRITE_READ 123 + +int g_replyFlag = 0; + +static int OnDevEventReceived(void *priv, uint32_t id, struct HdfSBuf *data) +{ + const char *string = HdfSbufReadString(data); + if (string == NULL) { + HDF_LOGE("fail to read string in event data"); + g_replyFlag = 1; + return HDF_FAILURE; + } + HDF_LOGE("%s: dev event received: %u %s", (char *)priv, id, string); + g_replyFlag = 1; + return HDF_SUCCESS; +} + +static int SendEvent(struct HdfIoService *serv, char *eventData) +{ + int ret = 0; + struct HdfSBuf *data = HdfSBufObtainDefaultSize(); + if (data == NULL) { + HDF_LOGE("fail to obtain sbuf data"); + return 1; + } + + struct HdfSBuf *reply = HdfSBufObtainDefaultSize(); + if (reply == NULL) { + HDF_LOGE("fail to obtain sbuf reply"); + ret = HDF_DEV_ERR_NO_MEMORY; + goto out; + } + + if (!HdfSbufWriteString(data, eventData)) { + HDF_LOGE("fail to write sbuf"); + ret = HDF_FAILURE; + goto out; + } + + ret = serv->dispatcher->Dispatch(&serv->object, SAMPLE_WRITE_READ, data, reply); + if (ret != HDF_SUCCESS) { + HDF_LOGE("fail to send service call"); + goto out; + } + + int replyData = 0; + if (!HdfSbufReadInt32(reply, &replyData)) { + HDF_LOGE("fail to get service call reply"); + ret = HDF_ERR_INVALID_OBJECT; + goto out; + } + HDF_LOGE("Get reply is: %d", replyData); +out: + HdfSBufRecycle(data); + HdfSBufRecycle(reply); + return ret; +} + +int main() +{ + char *sendData = "default event info"; + struct HdfIoService *serv = HdfIoServiceBind(SAMPLE_SERVICE_NAME); + if (serv == NULL) { + HDF_LOGE("fail to get service %s", SAMPLE_SERVICE_NAME); + return HDF_FAILURE; + } + + static struct HdfDevEventlistener listener = { + .callBack = OnDevEventReceived, + .priv ="Service0" + }; + + if (HdfDeviceRegisterEventListener(serv, &listener) != HDF_SUCCESS) { + HDF_LOGE("fail to register event listener"); + return HDF_FAILURE; + } + if (SendEvent(serv, sendData)) { + HDF_LOGE("fail to send event"); + return HDF_FAILURE; + } + + while (g_replyFlag == 0) { + sleep(1); + } + + if (HdfDeviceUnregisterEventListener(serv, &listener)) { + HDF_LOGE("fail to unregister listener"); + return HDF_FAILURE; + } + + HdfIoServiceRecycle(serv); + return HDF_SUCCESS; +} +``` + +>![](../public_sys-resources/icon-note.gif) **说明:** +>用户态应用程序使用了HDF框架中的消息发送接口,因此在编译用户态程序的过程中需要依赖HDF框架对外提供的hdf\_core和osal的动态库,在gn编译文件中添加如下依赖项: +>deps = \[ +>"//drivers/adapter/lite/uhdf/manager:hdf\_core", +>"//drivers/adapter/lite/uhdf/posix:hdf\_posix\_osal", +>\] + diff --git "a/zh-cn/device-dev/driver/\351\251\261\345\212\250\346\234\215\345\212\241\347\256\241\347\220\206.md" b/zh-cn/device-dev/driver/drive-hdf-servicemanage.md old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/driver/\351\251\261\345\212\250\346\234\215\345\212\241\347\256\241\347\220\206.md" rename to zh-cn/device-dev/driver/drive-hdf-servicemanage.md diff --git a/zh-cn/device-dev/driver/drive-peripherals-external-des.md b/zh-cn/device-dev/driver/drive-peripherals-external-des.md new file mode 100644 index 0000000000..282d5ed454 --- /dev/null +++ b/zh-cn/device-dev/driver/drive-peripherals-external-des.md @@ -0,0 +1,622 @@ +# WLAN + +- [概述](#section729758162218) + - [WLAN驱动接口架构](#section178022416377) + - [接口说明](#section149681312202415) + +- [开发指导](#section15957746172412) + - [开发步骤](#section11776186132513) + +- [开发实例](#section1395253612512) + +## 概述 + +WLAN是基于HDF(Hardware Driver Foundation)驱动框架开发的模块,该模块可实现跨操作系统迁移,自适应器件差异,模块化拼装编译等功能。各WLAN厂商驱动开发人员可根据WLAN模块提供的向下统一接口适配各自的驱动代码,实现如下能力:建立/关闭WLAN热点、扫描、关联WLAN热点等;对HDI层向上提供能力如下:设置MAC地址、设置发射功率、获取设备的MAC地址等。[WLAN模块框架图](#fig967034316227)如下: + +**图 1** WLAN框架 + + +![](figure/zh-cn_image_0000001170383063.png) + +### WLAN驱动接口架构 + +WLAN模块有三部分对外开放的API接口,如[下图2](#fig15016395217)所示: + +1. 对HDI层提供的能力接口。 + +2. 驱动直接调用WLAN模块能力接口。 + +3. 提供给各厂商实现的能力接口。 + +**图 2** WLAN模块开放能力分布图 + + +![](figure/接口分布图4.png) + +### 接口说明 + +WLAN驱动模块提供给驱动开发人员可直接调用的能力接口,主要功能有:创建/释放WifiModule、关联/取消关联、申请/释放NetBuf、lwip的pbuf和NetBuf的相互转换等。提供的部分接口说明如[表1](#table1521573319472)所示: + +**表 1** 可直接调用的接口 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    头文件

    +

    接口名称

    +

    功能描述

    +

    wifi_module.h

    +

    +

    struct WifiModule *WifiModuleCreate(const struct HdfConfigWifiModuleConfig *config);

    +

    基于HDF开发WLAN驱动时,创建一个WifiModule。

    +

    void WifiModuleDelete(struct WifiModule *module);

    +

    基于HDF开发WLAN驱动时,删除并释放WifiModule所有数据。

    +

    int32_t DelFeature(struct WifiModule *module, uint16_t featureType);

    +

    基于HDF开发WLAN驱动时,从WifiModule删除一个功能组件。

    +

    int32_t AddFeature(struct WifiModule *module, uint16_t featureType, struct WifiFeature *featureData);

    +

    基于HDF开发WLAN驱动时,注册一个功能组件到WifiModule。

    +

    wifi_mac80211_ops.h

    +

    int32_t (*startAp)(NetDevice *netDev);

    +

    启动AP。

    +

    int32_t (*stopAp)(NetDevice *netDev);

    +

    停止AP。

    +

    int32_t (*connect)(NetDevice *netDev, WifiConnectParams *param);

    +

    开始关联。

    +

    int32_t (*disconnect)(NetDevice *netDev, uint16_t reasonCode);

    +

    取消关联。

    +

    hdf_netbuf.h

    +

    static inline void NetBufQueueInit(struct NetBufQueue *q);

    +

    初始化NetBuf队列。

    +

    struct NetBuf *NetBufAlloc(uint32_t size);

    +

    申请NetBuf。

    +

    void NetBufFree(struct NetBuf *nb);

    +

    释放NetBuf。

    +

    struct NetBuf *Pbuf2NetBuf(const struct NetDevice *netdev, struct pbuf *lwipBuf);

    +

    lwip的pbuf转换为NetBuf。

    +

    struct pbuf *NetBuf2Pbuf(const struct NetBuf *nb);

    +

    NetBuf转换为lwip的pbuf。

    +
    + +同时WLAN驱动模块也提供了需要驱动开发人员实现的能力接口,主要功能有:初始化/注销NetDevice、打开/关闭NetDevice、获取NetDevice的状态等。提供的部分接口说明如[表2](#table74613501475)所示: + +**表 2** 需要开发人员实现的接口 + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    头文件

    +

    接口名称

    +

    功能描述

    +

    net_device.h

    +

    int32_t (*init)(struct NetDevice *netDev);

    +

    初始化NetDevice。

    +

    struct NetDevStats *(*getStats)(struct NetDevice *netDev);

    +

    获取NetDevice的状态。

    +

    int32_t (*setMacAddr)(struct NetDevice *netDev, void *addr);

    +

    设置Mac地址。

    +

    void (*deInit)(struct NetDevice *netDev);

    +

    注销NetDevice。

    +

    int32_t (*open)(struct NetDevice *netDev);

    +

    打开NetDevice。

    +

    int32_t (*stop)(struct NetDevice *netDev);

    +

    关闭NetDevice。

    +
    + +WLAN驱动模块对HDI层提供的能力接口,主要功能有:创建/销毁 IWiFi对象、设置MAC地址等。提供的部分接口说明如[表3](#table141076311618)所示: + +**表 3** HAL层对外接口 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    头文件

    +

    接口名称

    +

    功能描述

    +

    wifi_hal.h

    +

    +

    int32_t WifiConstruct(struct IWiFi **wifiInstance);

    +

    创建IWiFi对象,提供IWiFi基本能力。

    +

    int32_t WifiDestruct(struct IWiFi **wifiInstance);

    +

    销毁IWiFi对象。

    +

    int32_t (*start)(struct IWiFi *);

    +

    创建HAL和驱动之间的通道及获取驱动支持的网卡信息。

    +

    int32_t (*stop)(struct IWiFi *);

    +

    销毁通道。

    +

    wifi_hal_base_feature.h

    +

    int32_t (*getFeatureType)(const struct IWiFiBaseFeature *);

    +

    获取特性的类型。

    +

    int32_t (*setMacAddress)(const struct IWiFiBaseFeature *, unsigned char *, uint8_t);

    +

    设置MAC地址。

    +

    int32_t (*getDeviceMacAddress)(const struct IWiFiBaseFeature *, unsigned char *, uint8_t);

    +

    获取设备持久化的MAC地址。

    +

    int32_t (*setTxPower)(const struct IWiFiBaseFeature *, int32_t);

    +

    设置发射功率。

    +
    + +## 开发指导 + +WLAN驱动基于HDF框架和PLATFORM框架开发,不区分OS和芯片平台,为不同厂商的WLAN模组提供统一的驱动模型,各WLAN模组厂商根据如下指导适配WLAN驱动框架。 + +### 开发步骤 + +1. 通过wifi\_config.hcs文件,配置硬件参数:module\(不同feature\),芯片等。 +2. 解析配置文件, 生成全量配置的结构体对象。 +3. Module初始化,创建Module。 +4. 挂接chip,初始化chip。 +5. 总线初始化。 +6. 上层wpa业务挂接。 + +>![](../public_sys-resources/icon-note.gif) **说明:** +>以上驱动框架适配步骤一部分已经提供(详细见开发实例),待开发人员实现的部分有:1、根据硬件,修改配置参数;2、适配挂接chip;3、测试自验证。 + +## 开发实例 + +本例程提供WLAN模块初始化过程的完整使用流程。示例如下(以hi3881WLAN芯片为例): + +1、根据硬件,修改配置参数。 + +``` +/* 根据硬件参数,通过wlan_platform.hcs配置相关参数,以下是WLAN平台配置的示例 */ +hisi :& deviceList { + device0 :: deviceInst { + deviceInstId = 0; + powers { + power0 { + powerSeqDelay = 0; /* 电源序列延时 */ + powerType = 1; /* 电源类型:0--总是打开;1--GPIO */ + gpioId = 1; /* GPIO管脚号 */ + activeLevel=1; /* 有效电平:0--低;1--高 */ + } + power1 { + powerSeqDelay = 0; /* 电源序列延时 */ + powerType = 0; /* 电源类型:0--总是打开;1--GPIO */ + } + } + reset { + resetType = 0; /* 复位类型:0--不管理;1--GPIO */ + gpioId = 2; /* GPIO管脚号 */ + activeLevel=1; /* 有效电平:0--低;1--高 */ + resetHoldTime = 30; /* 复位配置后的等待时间(ms) */ + } + bootUpTimeout = 30; /* 启动超时时间(ms) */ + bus { + busType = 0; /* 总线类型:0-sdio */ + busId = 2; /* 总线号 */ + funcNum = [1]; /* SDIO功能号 */ + timeout = 1000; /* 读/写数据的超时时间 */ + blockSize = 512; /* 读/写数据的块大小 */ + } + } +} +/* 每一块芯片添加配置文件wlan_chip_<芯片名>.hcs(如:wlan_chip_hi3881.hcs),配置相关参数。以下是hi3881的配置示例 */ +root { + wlan_config { + hi3881 :& chipList { + chipHi3881 :: chipInst { + match_attr = "hdf_wlan_chips_hi3881"; /* 配置匹配标识 */ + chipName = "hi3881"; /* WLAN芯片的名称 */ + sdio { + vendorId = 0x0296; /* 厂商Id */ + deviceId = [0x5347]; /* 设备Id */ + } + } + } + } +} +``` + +2、适配挂接WLAN芯片的初始化和去初始化、WLAN芯片驱动的初始化和去初始化 + +``` +/* WLAN初始化挂接流程 */ +#include "hdf_device_desc.h" +#include "hdf_wifi_product.h" +#include "hdf_log.h" +#include "osal_mem.h" +#include "hdf_wlan_chipdriver_manager.h" +#include "securec.h" +#include "wifi_module.h" +#include "hi_wifi_api.h" +#include "hi_types_base.h" + +#define HDF_LOG_TAG Hi3881Driver + +/* WLAN芯片的初始化和去初始化函数 */ +int32_t InitHi3881Chip(struct HdfWlanDevice *device); +int32_t DeinitHi3881Chip(struct HdfWlanDevice *device); +/* WLAN芯片驱动的初始化和去初始化函数 */ +int32_t Hi3881Deinit(struct HdfChipDriver* chipDriver, struct NetDevice *netDevice); +int32_t Hi3881Init(struct HdfChipDriver* chipDriver, struct NetDevice *netDevice); + +/* 初始化mac80211与芯片侧的函数挂接 */ +hi_void HiMac80211Init(struct HdfChipDriver *chipDriver); + +static const char* const HI3881_DRIVER_NAME = "hisi"; + +/* WLAN芯片驱动挂接以及mac80211与芯片侧的函数挂接 */ +static struct HdfChipDriver *BuildHi3881Driver(struct HdfWlanDevice *device, uint8_t ifIndex) +{ + struct HdfChipDriver *specificDriver = NULL; + if (device == NULL) { + HDF_LOGE("%s fail : channel is NULL", __func__); + return NULL; + } + (void)device; + (void)ifIndex; + specificDriver = (struct HdfChipDriver *)OsalMemCalloc(sizeof(struct HdfChipDriver)); + if (specificDriver == NULL) { + HDF_LOGE("%s fail: OsalMemCalloc fail!", __func__); + return NULL; + } + if (memset_s(specificDriver, sizeof(struct HdfChipDriver), 0, sizeof(struct HdfChipDriver)) != EOK) { + HDF_LOGE("%s fail: memset_s fail!", __func__); + OsalMemFree(specificDriver); + return NULL; + } + + if (strcpy_s(specificDriver->name, MAX_WIFI_COMPONENT_NAME_LEN, HI3881_DRIVER_NAME) != EOK) { + HDF_LOGE("%s fail : strcpy_s fail", __func__); + OsalMemFree(specificDriver); + return NULL; + } + specificDriver->init = Hi3881Init; + specificDriver->deinit = Hi3881Deinit; + + HiMac80211Init(specificDriver); + + return specificDriver; +} + +/* 释放WLAN芯片驱动 */ +static void ReleaseHi3881Driver(struct HdfChipDriver *chipDriver) +{ + if (chipDriver == NULL) { + return; + } + if (strcmp(chipDriver->name, HI3881_DRIVER_NAME) != 0) { + HDF_LOGE("%s:Not my driver!", __func__); + return; + } + OsalMemFree(chipDriver); +} + +static uint8_t GetHi3881GetMaxIFCount(struct HdfChipDriverFactory *factory) { + (void)factory; + return 1; +} + +/* WLAN芯片相关函数的注册 */ +static int32_t HDFWlanRegHisiDriverFactory(void) +{ + static struct HdfChipDriverFactory tmpFactory = { 0 }; + struct HdfChipDriverManager *driverMgr = NULL; + driverMgr = HdfWlanGetChipDriverMgr(); + if (driverMgr == NULL && driverMgr->RegChipDriver != NULL) { + HDF_LOGE("%s fail: driverMgr is NULL!", __func__); + return HDF_FAILURE; + } + tmpFactory.driverName = HI3881_DRIVER_NAME; + tmpFactory.GetMaxIFCount = GetHi3881GetMaxIFCount; + tmpFactory.InitChip = InitHi3881Chip; + tmpFactory.DeinitChip = DeinitHi3881Chip; + tmpFactory.Build = BuildHi3881Driver; + tmpFactory.Release = ReleaseHi3881Driver; + tmpFactory.ReleaseFactory = NULL; + if (driverMgr->RegChipDriver(&tmpFactory) != HDF_SUCCESS) { + HDF_LOGE("%s fail: driverMgr is NULL!", __func__); + return HDF_FAILURE; + } + + return HDF_SUCCESS; +} + +static int32_t HdfWlanHisiChipDriverInit(struct HdfDeviceObject *device) +{ + (void)device; + return HDFWlanRegHisiDriverFactory(); +} + +struct HdfDriverEntry g_hdfHisiChipEntry = { + .moduleVersion = 1, + .Init = HdfWlanHisiChipDriverInit, + .moduleName = "HDF_WLAN_CHIPS" +}; + +HDF_INIT(g_hdfHisiChipEntry); +``` + +``` +#include "hdf_wifi_product.h" +#include "hi_wifi_api.h" +#if (_PRE_OS_VERSION_LINUX == _PRE_OS_VERSION) +#include "oal_thread.h" +#include "osal_time.h" +#endif +#include "wifi_mac80211_ops.h" +#include "wal_cfg80211.h" +#include "net_adpater.h" +#include "hdf_wlan_utils.h" + +#define HDF_LOG_TAG Hi3881Driver + +/* WLAN芯片的初始化函数 */ +int32_t InitHi3881Chip(struct HdfWlanDevice *device) +{ + uint8_t maxPortCount = 1; + int32_t ret = HI_SUCCESS; + uint8_t maxRetryCount = 2; + if (device == NULL) { + HDF_LOGE("%s:NULL ptr!", __func__); + return HI_FAIL; + } + + do { + if (ret != HI_SUCCESS) { + if (device->reset != NULL && device->reset->Reset != NULL) { + device->reset->Reset(device->reset); + } + HDF_LOGE("%s:Retry init hi3881!last ret=%d", __func__, ret); + } + ret = hi_wifi_init(maxPortCount); + } while (ret != 0 && --maxRetryCount > 0); + + if (ret != 0) { + HDF_LOGE("%s:Init hi3881 driver failed!", __func__); + return ret; + } + return HI_SUCCESS; +} + +/* WLAN芯片的去初始化函数 */ +int32_t DeinitHi3881Chip(struct HdfWlanDevice *device) +{ + (void)device; + int32_t ret = hi_wifi_deinit(); + if (ret != 0) { + HDF_LOGE("%s:Deinit failed!ret=%d", __func__, ret); + } + return ret; +} + +/* WLAN芯片驱动的初始化函数 */ +int32_t Hi3881Init(struct HdfChipDriver *chipDriver, struct NetDevice *netDevice) +{ + HDF_LOGI("%s: start...", __func__); + hi_u16 mode = wal_get_vap_mode(); + int32_t ret; + nl80211_iftype_uint8 type; + (void)chipDriver; + + if (mode >= WAL_WIFI_MODE_BUTT) { + oam_error_log1(0, 0, "wal_init_drv_netdev:: invalid mode[%d]", mode); + return HI_FAIL; + } + + if (mode == WAL_WIFI_MODE_STA) { + type = NL80211_IFTYPE_STATION; + } else if (mode == WAL_WIFI_MODE_AP) { + type = NL80211_IFTYPE_AP; + } else { + oam_error_log1(0, 0, "wal_init_drv_netdev:: invalid mode[%d]", mode); + return HI_FAIL; + } + + ret = wal_init_drv_wlan_netdev(type, WAL_PHY_MODE_11N, netDevice); + if (ret != HI_SUCCESS) { + oam_error_log2(0, OAM_SF_ANY, "wal_init_drv_netdev %s failed.l_return:%d\n", netDevice->name, ret); + } + return ret; +} + +/* WLAN芯片驱动的去初始化函数 */ +int32_t Hi3881Deinit(struct HdfChipDriver *chipDriver, struct NetDevice *netDevice) +{ + (void)chipDriver; + int32_t ret = wal_deinit_drv_wlan_netdev(netDevice); + if (ret != HDF_SUCCESS) { + return ret; + } + return ReleasePlatformNetDevice(netDevice); +} +``` + +3、在芯片侧初始化过程中调用netdev的init和add接口进行初始化netdev,并挂接netdev的一些函数指针 + +``` +hi_s32 wal_init_drv_wlan_netdev(nl80211_iftype_uint8 type, wal_phy_mode mode, hi_char* ifname, hi_u32* len) +{ + oal_net_device_stru *netdev = HI_NULL; + + ...... + /* 初始化网络设备,获取对应的实例。*/ + netdev = NetDeviceInit(ifname, *len, LITE_OS); + oal_wireless_dev *wdev = (oal_wireless_dev *)oal_mem_alloc(OAL_MEM_POOL_ID_LOCAL, sizeof(oal_wireless_dev)); + ret = wal_init_netif(type, netdev, wdev); + + ...... + + return HI_SUCCESS; +} +/* 挂接netdev的一些函数指针,详细挂接函数{@link NetDeviceInterFace} */ +oal_net_device_ops_stru g_wal_net_dev_ops = +{ + .getStats = wal_netdev_get_stats, + .open = wal_netdev_open, + .stop = wal_netdev_stop, + .xmit = hmac_bridge_vap_xmit, + .ioctl = wal_net_device_ioctl, + .changeMtu = oal_net_device_change_mtu, + .init = oal_net_device_init, + .deInit = oal_net_free_netdev, +#if (defined(_PRE_WLAN_FEATURE_FLOWCTL) || defined(_PRE_WLAN_FEATURE_OFFLOAD_FLOWCTL)) + .selectQueue = wal_netdev_select_queue, +#endif + .setMacAddr = wal_netdev_set_mac_addr, +#if (_PRE_OS_VERSION_LITEOS == _PRE_OS_VERSION) + .netifNotify = HI_NULL, +#endif + .specialEtherTypeProcess = SpecialEtherTypeProcess, +}; + +hi_s32 wal_init_netif(nl80211_iftype_uint8 type, oal_net_device_stru *netdev, const oal_wireless_dev *wdev) +{ + /* 添加网络设备到协议栈 */ + hi_u32 ret = NetDeviceAdd(netdev, (Protocol80211IfType)type); + + ...... + + return HI_SUCCESS; +} +``` + +4、WifiMac80211Ops中的函数挂接实现。 + +``` +/* 挂接mac80211的一些函数指针 */ + +/* 驱动需要实现的MAC层基本能力的控制接口 */ +static struct HdfMac80211BaseOps g_baseOps = { + .SetMode = WalSetMode, + .AddKey = WalAddKey, + .DelKey = WalDelKey, + .SetDefaultKey = WalSetDefaultKey, + .GetDeviceMacAddr = WalGetDeviceMacAddr, + .SetMacAddr = WalSetMacAddr, + .SetTxPower = WalSetTxPower, + .GetValidFreqsWithBand = WalGetValidFreqsWithBand, + .GetHwCapability = WalGetHwCapability +}; + +/* 驱动需要实现的MAC层STA能力的控制接口 */ +static struct HdfMac80211STAOps g_staOps = { + .Connect = WalConnect, + .Disconnect = WalDisconnect, + .StartScan = WalStartScan, + .AbortScan = WalAbortScan, + .SetScanningMacAddress = WalSetScanningMacAddress, +}; + +/* 驱动需要实现的MAC层AP能力的控制接口 */ +static struct HdfMac80211APOps g_apOps = { + .ConfigAp = WalConfigAp, + .StartAp = WalStartAp, + .StopAp = WalStopAp, + .ConfigBeacon = WalChangeBeacon, + .DelStation = WalDelStation, + .SetCountryCode = WalSetCountryCode, + .GetAssociatedStasCount = WalGetAssociatedStasCount, + .GetAssociatedStasInfo = WalGetAssociatedStasInfo +}; + +/* 初始化mac80211与芯片侧的函数挂接 */ +hi_void HiMac80211Init(struct HdfChipDriver *chipDriver) +{ + if (chipDriver == NULL) { + oam_error_log(0, OAM_SF_ANY, "%s:input is NULL!", __func__); + return; + } + chipDriver->ops = &g_baseOps; + chipDriver->staOps = &g_staOps; + chipDriver->apOps = &g_apOps; +} +``` + diff --git a/zh-cn/device-dev/driver/drive-peripherals-lcd-des.md b/zh-cn/device-dev/driver/drive-peripherals-lcd-des.md new file mode 100644 index 0000000000..1e195e52db --- /dev/null +++ b/zh-cn/device-dev/driver/drive-peripherals-lcd-des.md @@ -0,0 +1,363 @@ +# LCD + +- [概述](#section141575391542) + - [接口说明](#section14711163785519) + +- [开发指导](#section12394223125615) + - [开发步骤](#section515923045814) + +- [开发实例](#section7441155155813) + +## 概述 + +LCD(Liquid Crystal Display)液晶显示驱动,对LCD进行上电,并通过接口初始化LCD内部寄存器,使LCD正常工作。Display驱动模型基于HDF( Hardware Driver Foundation)[驱动框架](drive-hdf-overview.md)开发,实现跨OS、跨平台,为LCD硬件提供上下电功能、发送初始化序列功能,使LCD进入正常的工作模式,显示芯片平台侧的图像数据,基于HDF驱动框架的Display驱动模型如[图1](#fig69138814229)。 + +**图 1** 基于HDF驱动框架的Display驱动模型 +![](figure/基于HDF驱动框架的Display驱动模型.png "基于HDF驱动框架的Display驱动模型") + +- **Display驱动模型介绍** + + Display驱动模型主要由平台驱动层、芯片平台适配层、LCD器件驱动层三部分组成。驱动模型基于HDF驱动框架开发,通过Platform层和OSAL层提供的接口,屏蔽内核形态的差异,使得器件驱动可以便利的迁移到不同OS及芯片平台。模型向上对接Display公共hal层,支撑HDI接口的实现,通过Display-HDI(Hardware Display Interface)对图形服务提供各类驱动能力接口。 + + (1)Display平台驱动层:通过HDF提供的IOService数据通道,与公共Hal层对接,集中接收并处理各类上层调用指令; + + (2)SOC平台驱动适配层:借助此SOC适配层,实现Display驱动和SOC侧驱动解耦,主要完成芯片平台相关的参数配置,并传递平台驱动层的调用到器件驱动层; + + (3)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接口") + + MIPI DSI接口是MIPI(移动行业处理器接口)联盟定义的显示接口,主要用于移动终端显示屏接口,接口数据传输遵循MIPI协议,MIPI DSI接口为数据接口,传输图像数据,通常情况下MIPI DSI接口的控制信息以MIPI包形式通过MIPI DSI接口发送到对端IC,不需要额外的外设接口。 + +- TTL接口 + + **图 3** TTL接口 + ![](figure/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驱动数据,驱动数据接口主要包括如下接口: + - LCD上下电 + + 根据LCD硬件连接,使用Platform接口层提供的GPIO操作接口操作对应LCD管脚,例如复位管脚、IOVCC管脚,上电时序参考LCD供应商提供的SPEC。 + + - 发送初始化序列 + + 根据LCD硬件接口,使用Platform接口层提供的I2C、SPI、MIPI等接口,下载LCD初始化序列,初始化参数序列可以参考LCD供应商提供的SPEC。 + + +4. 根据需求实现HDF框架其他接口,比如Release接口。 +5. 根据需求使用HDF框架可创建其他设备节点,用于业务逻辑或者调试功能。 + +## 开发实例 + +添加设备描述配置: + +``` +/* Display驱动相关的设备描述配置 */ +display :: host { + hostName = "display_host"; + /* Display平台驱动设备描述 */ + device_hdf_disp :: device { + device0 :: deviceNode { + policy = 2; + priority = 200; + permission = 0660; + moduleName = "HDF_DISP"; + serviceName = "hdf_disp"; + } + } + /* SOC适配层驱动设备描述 */ + device_hi35xx_disp :: device { + device0 :: deviceNode { + policy = 0; + priority = 199; + moduleName = "HI351XX_DISP"; + } + } + /* LCD器件驱动设备描述 */ + device_lcd :: device { + device0 :: deviceNode { + policy = 0; + priority = 100; + preload = 0; + moduleName = "LCD_Sample"; + } + device1 :: deviceNode { + policy = 0; + priority = 100; + preload = 2; + moduleName = "LCD_SampleXX"; + } + } +} +``` + +SOC适配层驱动,以Hi35xx系列芯片为例,需要在本层驱动中适配MIPI等和芯片平台相关的配置,示例如下: + +``` +static int32_t MipiDsiInit(struct PanelInfo *info) +{ + int32_t ret; + struct DevHandle *mipiHandle = NULL; + struct MipiCfg cfg; + + mipiHandle = MipiDsiOpen(0); + if (mipiHandle == NULL) { + HDF_LOGE("%s: MipiDsiOpen failure", __func__); + return HDF_FAILURE; + } + cfg.lane = info->mipi.lane; + cfg.mode = info->mipi.mode; + cfg.format = info->mipi.format; + cfg.burstMode = info->mipi.burstMode; + cfg.timing.xPixels = info->width; + cfg.timing.hsaPixels = info->hsw; + cfg.timing.hbpPixels = info->hbp; + cfg.timing.hlinePixels = info->width + info->hbp + info->hfp + info->hsw; + cfg.timing.vsaLines = info->vsw; + cfg.timing.vbpLines = info->vbp; + cfg.timing.vfpLines = info->vfp; + cfg.timing.ylines = info->height; + /* 0 : no care */ + cfg.timing.edpiCmdSize = 0; + cfg.pixelClk = CalcPixelClk(info); + cfg.phyDataRate = CalcDataRate(info); + /* config mipi device */ + ret = MipiDsiSetCfg(mipiHandle, &cfg); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s:MipiDsiSetCfg failure", __func__); + } + MipiDsiClose(mipiHandle); + HDF_LOGI("%s:pixelClk = %d, phyDataRate = %d\n", __func__, + cfg.pixelClk, cfg.phyDataRate); + return ret; +} +``` + +LCD器件驱动示例如下: + +``` +#define RESET_GPIO 5 +#define MIPI_DSI0 0 +#define BLK_PWM1 1 +#define PWM_MAX_PERIOD 100000 +/* backlight setting */ +#define MIN_LEVEL 0 +#define MAX_LEVEL 255 +#define DEFAULT_LEVEL 100 + +#define WIDTH 480 +#define HEIGHT 960 +#define HORIZONTAL_BACK_PORCH 20 +#define HORIZONTAL_FRONT_PORCH 20 +#define HORIZONTAL_SYNC_WIDTH 10 +#define VERTIACL_BACK_PORCH 14 +#define VERTIACL_FRONT_PORCH 16 +#define VERTIACL_SYNC_WIDTH 2 +#define FRAME_RATE 60 + +/* Panel Info结构体结构体 */ +struct PanelInfo { + uint32_t width; + uint32_t height; + uint32_t hbp; + uint32_t hfp; + uint32_t hsw; + uint32_t vbp; + uint32_t vfp; + uint32_t vsw; + uint32_t frameRate; + enum LcdIntfType intfType; + enum IntfSync intfSync; + struct MipiDsiDesc mipi; + struct BlkDesc blk; + struct PwmCfg pwm; +}; + +/* LCD屏的初始化序列 */ +static uint8_t g_payLoad0[] = { 0xF0, 0x5A, 0x5A }; +static uint8_t g_payLoad1[] = { 0xF1, 0xA5, 0xA5 }; +static uint8_t g_payLoad2[] = { 0xB3, 0x03, 0x03, 0x03, 0x07, 0x05, 0x0D, 0x0F, 0x11, 0x13, 0x09, 0x0B }; +static uint8_t g_payLoad3[] = { 0xB4, 0x03, 0x03, 0x03, 0x06, 0x04, 0x0C, 0x0E, 0x10, 0x12, 0x08, 0x0A }; +static uint8_t g_payLoad4[] = { 0xB0, 0x54, 0x32, 0x23, 0x45, 0x44, 0x44, 0x44, 0x44, 0x60, 0x00, 0x60, 0x1C }; +static uint8_t g_payLoad5[] = { 0xB1, 0x32, 0x84, 0x02, 0x87, 0x12, 0x00, 0x50, 0x1C }; +static uint8_t g_payLoad6[] = { 0xB2, 0x73, 0x09, 0x08 }; +static uint8_t g_payLoad7[] = { 0xB6, 0x5C, 0x5C, 0x05 }; +static uint8_t g_payLoad8[] = { 0xB8, 0x23, 0x41, 0x32, 0x30, 0x03 }; +static uint8_t g_payLoad9[] = { 0xBC, 0xD2, 0x0E, 0x63, 0x63, 0x5A, 0x32, 0x22, 0x14, 0x22, 0x03 }; +static uint8_t g_payLoad10[] = { 0xb7, 0x41 }; +static uint8_t g_payLoad11[] = { 0xC1, 0x0c, 0x10, 0x04, 0x0c, 0x10, 0x04 }; +static uint8_t g_payLoad12[] = { 0xC2, 0x10, 0xE0 }; +static uint8_t g_payLoad13[] = { 0xC3, 0x22, 0x11 }; +static uint8_t g_payLoad14[] = { 0xD0, 0x07, 0xFF }; +static uint8_t g_payLoad15[] = { 0xD2, 0x63, 0x0B, 0x08, 0x88 }; +static uint8_t g_payLoad16[] = { 0xC6, 0x08, 0x15, 0xFF, 0x10, 0x16, 0x80, 0x60 }; +static uint8_t g_payLoad17[] = { 0xc7, 0x04 }; +static uint8_t g_payLoad18[] = { + 0xC8, 0x7C, 0x50, 0x3B, 0x2C, 0x25, 0x16, 0x1C, 0x08, 0x27, 0x2B, 0x2F, 0x52, 0x43, 0x4C, 0x40, + 0x3D, 0x30, 0x1E, 0x06, 0x7C, 0x50, 0x3B, 0x2C, 0x25, 0x16, 0x1C, 0x08, 0x27, 0x2B, 0x2F, 0x52, + 0x43, 0x4C, 0x40, 0x3D, 0x30, 0x1E, 0x06 +}; +static uint8_t g_payLoad19[] = { 0x11 }; +static uint8_t g_payLoad20[] = { 0x29 }; + +struct DsiCmdDesc g_OnCmd[] = { + { 0x29, 0, sizeof(g_payLoad0), g_payLoad0 }, + { 0x29, 0, sizeof(g_payLoad1), g_payLoad1 }, + { 0x29, 0, sizeof(g_payLoad2), g_payLoad2 }, + { 0x29, 0, sizeof(g_payLoad3), g_payLoad3 }, + { 0x29, 0, sizeof(g_payLoad4), g_payLoad4 }, + { 0x29, 0, sizeof(g_payLoad5), g_payLoad5 }, + { 0x29, 0, sizeof(g_payLoad6), g_payLoad6 }, + { 0x29, 0, sizeof(g_payLoad7), g_payLoad7 }, + { 0x29, 0, sizeof(g_payLoad8), g_payLoad8 }, + { 0x29, 0, sizeof(g_payLoad9), g_payLoad9 }, + { 0x23, 0, sizeof(g_payLoad10), g_payLoad10 }, + { 0x29, 0, sizeof(g_payLoad11), g_payLoad11 }, + { 0x29, 0, sizeof(g_payLoad12), g_payLoad12 }, + { 0x29, 0, sizeof(g_payLoad13), g_payLoad13 }, + { 0x29, 0, sizeof(g_payLoad14), g_payLoad14 }, + { 0x29, 0, sizeof(g_payLoad15), g_payLoad15 }, + { 0x29, 0, sizeof(g_payLoad16), g_payLoad16 }, + { 0x23, 0, sizeof(g_payLoad17), g_payLoad17 }, + { 0x29, 1, sizeof(g_payLoad18), g_payLoad18 }, + { 0x05, 120, sizeof(g_payLoad19), g_payLoad19 }, + { 0x05, 120, sizeof(g_payLoad20), g_payLoad20 }, +}; +static DevHandle g_mipiHandle = NULL; +static DevHandle g_pwmHandle = NULL; + +/* 设置Reset Pin脚状态 */ +static int32_t LcdResetOn(void) +{ + int32_t ret; + ret = GpioSetDir(RESET_GPIO, GPIO_DIR_OUT); + if (ret != HDF_SUCCESS) { + HDF_LOGE("GpioSetDir failure, ret:%d", ret); + return HDF_FAILURE; + } + ret = GpioWrite(RESET_GPIO, GPIO_VAL_HIGH); + if (ret != HDF_SUCCESS) { + HDF_LOGE("GpioWrite failure, ret:%d", ret); + return HDF_FAILURE; + } + /* delay 20ms */ + OsalMSleep(20); + return HDF_SUCCESS; +} + +static int32_t SampleInit(void) +{ + /* 获取MIPI DSI设备操作句柄 */ + g_mipiHandle = MipiDsiOpen(MIPI_DSI0); + if (g_mipiHandle == NULL) { + HDF_LOGE("%s: MipiDsiOpen failure", __func__); + return HDF_FAILURE; + } + return HDF_SUCCESS; +} + +static int32_t SampleOn(void) +{ + int32_t ret; + /* LCD上电序列 */ + ret = LcdResetOn(); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: LcdResetOn failure", __func__); + return HDF_FAILURE; + } + if (g_mipiHandle == NULL) { + HDF_LOGE("%s: g_mipiHandle is null", __func__); + return HDF_FAILURE; + } + /* 使用mipi下发初始化序列 */ + int32_t count = sizeof(g_OnCmd) / sizeof(g_OnCmd[0]); + int32_t i; + for (i = 0; i < count; i++) { + ret = MipiDsiTx(g_mipiHandle, &(g_OnCmd[i])); + if (ret != HDF_SUCCESS) { + HDF_LOGE("MipiDsiTx failure"); + return HDF_FAILURE; + } + } + /* 将mipi切换到HS模式 */ + MipiDsiSetHsMode(g_mipiHandle); + return HDF_SUCCESS; +} + +/* PanelInfo结构体变量 */ +static struct PanelInfo g_panelInfo = { + .width = WIDTH, /* width */ + .height = HEIGHT, /* height */ + .hbp = HORIZONTAL_BACK_PORCH, /* horizontal back porch */ + .hfp = HORIZONTAL_FRONT_PORCH, /* horizontal front porch */ + .hsw = HORIZONTAL_SYNC_WIDTH, /* horizontal sync width */ + .vbp = VERTIACL_BACK_PORCH, /* vertiacl back porch */ + .vfp = VERTIACL_FRONT_PORCH, /* vertiacl front porch */ + .vsw = VERTIACL_SYNC_WIDTH, /* vertiacl sync width */ + .frameRate = FRAME_RATE, /* frame rate */ + .intfType = MIPI_DSI, /* panel interface type */ + .intfSync = OUTPUT_USER, /* output timming type */ + /* mipi config info */ + .mipi = { DSI_2_LANES, DSI_VIDEO_MODE, VIDEO_BURST_MODE, FORMAT_RGB_24_BIT }, + /* backlight config info */ + .blk = { BLK_PWM, MIN_LEVEL, MAX_LEVEL, DEFAULT_LEVEL }, + .pwm = { BLK_PWM1, PWM_MAX_PERIOD }, +}; + +/* 器件驱动需要适配的基础接口 */ +static struct PanelData g_panelData = { + .info = &g_panelInfo, + .init = SampleInit, + .on = SampleOn, + .off = SampleOff, + .setBacklight = SampleSetBacklight, +}; + +/* 器件驱动入口函数 */ +int32_t SampleEntryInit(struct HdfDeviceObject *object) +{ + HDF_LOGI("%s: enter", __func__); + if (object == NULL) { + HDF_LOGE("%s: param is null!", __func__); + return HDF_FAILURE; + } + /* 器件驱动接口注册,ops提供给平台驱动调用 */ + if (PanelDataRegister(&g_panelData) != HDF_SUCCESS) { + HDF_LOGE("%s: PanelDataRegister error!", __func__); + return HDF_FAILURE; + } + return HDF_SUCCESS; +} + +struct HdfDriverEntry g_sampleDevEntry = { + .moduleVersion = 1, + .moduleName = "LCD_SAMPLE", + .Init = SampleEntryInit, +}; + +HDF_INIT(g_sampleDevEntry); +``` + diff --git a/zh-cn/device-dev/driver/drive-peripherals-sensor-des.md b/zh-cn/device-dev/driver/drive-peripherals-sensor-des.md new file mode 100644 index 0000000000..b471e33124 --- /dev/null +++ b/zh-cn/device-dev/driver/drive-peripherals-sensor-des.md @@ -0,0 +1,929 @@ +# SENSOR + +- [概述](#section3634112111) + - [接口说明](#section188213414114) + +- [开发指导](#section1140943382) + - [开发步骤](#section7893102915819) + +- [开发实例](#section257750691) +- [测试指导](#section106021256121219) + +## 概述 + +Sensor(传感器)驱动模块为上层Sensor服务系统提供稳定的Sensor基础能力API,包括Sensor列表查询、Sensor启停、Sensor订阅及去订阅,Sensor参数配置等功能;基于HDF(**H**ardware **D**river **F**oundation)驱动框架开发的Sensor驱动模型,实现跨操作系统迁移,器件差异配置等功能。Sensor驱动模型如下图1所示: + +**图 1** Sensor驱动模型图 +![](figure/Sensor驱动模型图.png "Sensor驱动模型图") + +Sensor驱动模型对外开放的API接口能力如下: + +- 提供Sensor HDI(**H**ardware **D**river **I**nterface)能力接口,简化服务开发。 +- 提供Sensor驱动模型能力接口:依赖HDF驱动框架实现Sensor器件驱动的注册,加载,去注册,器件探测等能力,提供同一类型Sensor器件驱动归一接口, 寄存器配置解析操作接口,总线访问抽象接口,平台抽象接口。 +- 提供开发者实现的能力接口:依赖HDF驱动框架的HCS\(**H**DF **C**onfiguration **S**ource\)配置管理,根据同类型Sensor差异化配置,实现Sensor器件参数序列化配置和器件部分操作接口,简化Sensor器件驱动开发。 + +### 接口说明 + +Sensor驱动模型对HDI开放的API接口功能,参考表1。 + +**表 1** Sensor驱动模型对外API接口功能介绍 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    功能分类

    +

    接口名

    +

    功能描述

    +

    查询操作

    +

    int32_t GetAllSensors(struct SensorInformation **sensorInfo, int32_t *count)

    +

    获取系统中注册的所有传感器信息,一种类型传感器信息包括传感器名字、设备厂商、固件版本号、硬件版本号、传感器类型编号、传感器标识、最大量程、精度、功耗。

    +

    配置操作

    +

    int32_t Enable(int32_t sensorId)

    +

    使能一种传感器设备,只有数据订阅者使能传感器后,才能获取订阅的传感器数据。

    +

    int32_t Disable(int32_t sensorId)

    +

    去使能一种传感器设备。

    +

    int32_t SetBatch(iint32_t sensorId, int64_t samplingInterval, int64_t reportInterval)

    +

    设置一种传感器的数据采样间隔和数据上报间隔。

    +

    int32_t SetMode(int32_t sensorTypeId, SensorUser *user, int32_t mode)

    +

    设置一种传感器的工作模式,不同的工作模式,上报数据方式不同。

    +

    int32_t SetOption(int32_t sensorId, uint32_t option)

    +

    设置一种传感器量程,精度等可选配置。

    +

    数据订阅操作

    +

    int32_t Register(RecordDataCallback cb)

    +

    订阅者注册传感器数据回调函数,系统会将获取到的传感器数据上报给订阅者。

    +

    int32_t Unregister(void)

    +

    订阅者去注册传感器数据回调函数。

    +

    接口实例

    +

    const struct SensorInterface *NewSensorInterfaceInstance(void)

    +

    创建传感器接口实例。

    +

    int32_t FreeSensorInterfaceInstance(void)

    +

    释放传感器接口实例。

    +
    + +Sensor驱动模型对驱动开发者开放的功能接口,驱动开发者无需实现,直接使用,参考表2: + +**表 2** Sensor驱动模型对驱动开发者开放的功能接口列表 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    功能分类

    +

    接口名

    +

    功能描述

    +

    设备管理操作接口

    +

    int32_t AddSensorDevice(const struct SensorDeviceInfo *deviceInfo)

    +

    添加当前类型的传感器设备到传感器设备管理。

    +

    int32_t DeleteSensorDevice(int32_t sensorId)

    +

    删除传感器设备管理里指定的传感器设备。

    +

    int32_t ReportSensorEvent(const struct SensorReportEvent *events)

    +

    上报指定类型传感器的数据到用户侧。

    +

    Sensor抽象总线和平台操作接口

    +

    int32_t ReadSensor(struct SensorBusCfg *busCfg, uint16_t regAddr, uint8_t *data, uint16_t dataLen)

    +

    按照配置的总线方式,读取传感器寄存器配置数据。

    +

    int32_t WriteSensor(struct SensorBusCfg *busCfg, uint8_t *writeData, uint16_t len)

    +

    按照配置的总线方式,传感器配置数据写入寄存器。

    +

    int32_t CreateSensorThread(struct OsalThread *thread, OsalThreadEntry threadEntry, char *name, void *entryPara)

    +

    创建指定传感器的定时线程,用于传感器数据上报处理。

    +

    void DestroySensorThread(struct OsalThread *thread, uint8_t *status);

    +

    销毁传感器创建的定时线程。

    +

    通用配置操作接口

    +

    int32_t SetSensorRegCfgArray(struct SensorBusCfg *busCfg, const struct SensorRegCfgGroupNode *group);

    +

    根据传感器总线类型信息,下发寄存器分组配置。

    +

    配置解析操作接口

    +

    +

    int32_t GetSensorBaseConfigData(const struct DeviceResourceNode *node, struct SensorCfgData *config)

    +

    根据传感器设备HCS资源配置,获取传感器信息,总线配置信息,属性配置等基本配置信息,并初始化对应的基本配置数据结构体。

    +

    int32_t ParseSensorRegConfig(struct SensorCfgData *config)

    +

    根据传感器设备HCS资源配置,解析寄存器分组信息,并初始化配置数据结构体。

    +

    void ReleaseSensorAllRegConfig(struct SensorCfgData *config)

    +

    释放传感器配置数据结构体里分配的资源。

    +

    int32_t GetSensorBusHandle(struct SensorBusCfg *busCfg)

    +

    获取传感器总线句柄信息。

    +

    int32_t ReleaseSensorBusHandle(struct SensorBusCfg *busCfg)

    +

    释放传感器句柄信息。

    +
    + +Sensor驱动模型要求驱动开发者实现的接口功能,参考表3 + +**表 3** Sensor驱动模型要求驱动开发者实现的接口列表 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    功能分类

    +

    接口名

    +

    功能描述

    +

    基本功能操作

    +

    int32_t init(void)

    +

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

    +

    int32_t GetInfo(struct SensorBasicInfo *info)

    +

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

    +

    int32_t Enable(void)

    +

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

    +

    int32_t Disable(void)

    +

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

    +

    int32_t SetBatch(int64_t samplingInterval, int64_t reportInterval)

    +

    根据数据采样率和数据上报间隔,配置当前传感器设备的数据上报线程处理时间。

    +

    int32_t SetMode(int32_t mode)

    +

    配置当前传感器设备数据上报方式。

    +

    int32_t SetOption(uint32_t option)

    +

    根据可选配置,下发量程,精度等寄存器配置。

    +

    void ReadSensorData(void)

    +

    实现传感器的数据读取函数。

    +
    + +接口实现参考[SENSOR](#section257750691)章节。 + +## 开发指导 + +Sensor驱动是基于HDF框架、PLATFORM和OSAL基础接口进行开发,不区分操作系统和芯片平台,为不同Sensor器件提供统一的驱动模型。本篇开发指导以加速度计传感器为例,介绍传感器驱动开发。 + +### 开发步骤 + +1. 加速度计传感器驱动注册。HDF驱动框架会提供统一的驱动管理模型,通过加速计传感器模块配置信息,识别并加载对应模块驱动。 +2. 加速度计传感器驱动初始化和去初始化。HDF驱动框架通过init入口函数,依次启动传感器设备驱动加载和分配传感器设备数据配置资源。HDF驱动框架通过release函数,释放驱动加载的资源和配置。 +3. 加速度计传感器寄存器组配置解析。不同类型传感器需要在hcs里配置器件对应的HCS配置文件,然后再设备驱动启动过程中探测器件是否在位,然后加载对应的配置文件,生成配置的结构体对象。 +4. 加速度计传感器驱动操作接口实现。实现各个类型传感器归一化驱动接口,如init,GetInfo,Enable,Disable,SetBatch,SetMode,SetOption,ReadSensorData等函数,完成传感器驱动配置下发和数据上报功能。 + +>![](../public_sys-resources/icon-note.gif) **说明:** +>传感器驱动模型已经提供一部分能力集,包括驱动设备管理能力,抽象总线和平台操作接口能力,通用配置操作接口能力,配置解析操作接口能力,接口参考[表2](#table1156812588320)。需要开发人员实现部分有:1、传感器部分操作接口([表3](#table1083014911336));2、传感器HCS差异化数据配置;3、驱动基本功能验证。 + +## 开发实例 + +基于HDF驱动模型,加载启动加速度计传感器驱动,代码形式如下,具体原理可参考[HDF驱动开发指南](drive-hdf-development.md)。加速度传感器选择通讯接口方式为I2C,厂家选择博世BMI160加速度传感器。 + +1. 加速度计传感器驱动入口注册 + +- 加速度计传感器驱动入口函数实现 + +``` +/* 注册加速度计传感器入口数据结构体对象 */ +struct HdfDriverEntry g_sensorAccelDevEntry = { + .moduleVersion = 1, /* 加速度计传感器模块版本号 */ + .moduleName = "HDF_SENSOR_ACCEL", /* 加速度计传感器模块名,要与device_info.hcs文件里的加速度计moduleName字段值一样*/ + .Bind = BindAccelDriver, /* 加速度计传感器绑定函数 */ + .Init = InitAccelDriver, /* 加速度计传感器初始化函数 */ + .Release = ReleaseAccelDriver, /* 加速度计传感器资源释放函数 */ +}; + +/* 调用HDF_INIT将驱动入口注册到HDF框架中,在加载驱动时HDF框架会先调用Bind函数,再调用Init函数加载该驱动,当Init调用异常时,HDF框架会调用Release释放驱动资源并退出 */ +HDF_INIT(g_sensorAccelDevEntry); +``` + +- 加速度计传感器设备配置描述 + +加速度传感器模型使用HCS作为配置描述源码,HCS配置字段详细介绍参考[配置管理](drive-hdf-manage.md)介绍。 + +``` +/* 加速度计传感器设备HCS配置 */ +device_sensor_accel :: device { + device0 :: deviceNode { + policy = 1; /* policy字段是驱动服务发布的策略 */ + priority = 105; /* 驱动启动优先级(0-200),值越大优先级越低,建议默认配100,优先级相同则不保证device的加载顺序 */ + preload = 2; /* 驱动按需加载字段,0表示加载,2表示不加载 */ + permission = 0664; /* 驱动创建设备节点权限 */ + moduleName = "HDF_SENSOR_ACCEL"; /* 驱动名称,该字段的值必须和驱动入口结构的moduleName值一致 */ + serviceName = "sensor_accel"; /* 驱动对外发布服务的名称,必须唯一 */ + deviceMatchAttr = "hdf_sensor_accel_driver"; /* 驱动私有数据匹配的关键字,必须和驱动私有数据配置表中的match_attr值相等 */ + } +} +``` + +1. 加速度计传感器驱动初始化和去初始化 + +- 初始化入口函数init + +``` +/* 加速度计传感器驱动对外提供的服务绑定到HDF框架 */ +int32_t BindAccelDriver(struct HdfDeviceObject *device) +{ + CHECK_NULL_PTR_RETURN_VALUE(device, HDF_ERR_INVALID_PARAM); + + static struct IDeviceIoService service = { + .object = {0}, + .Dispatch = DispatchAccel, + }; + device->service = &service; + + return HDF_SUCCESS; +} +/*在探测到器件在位后,需要调用RegisterAccelChipOps注册差异化适配函数*/ +int32_t RegisterAccelChipOps(struct AccelOpsCall *ops) +{ + struct AccelDrvData *drvData = NULL; + + CHECK_NULL_PTR_RETURN_VALUE(ops, HDF_ERR_INVALID_PARAM); + + drvData = AccelGetDrvData(); + drvData->ops.Init = ops->Init; + drvData->ops.ReadData = ops->ReadData; + return HDF_SUCCESS; +} +/* 挂载加速度计传感器驱动归一化的接口函数 */ +static int32_t InitAccelOps(struct SensorDeviceInfo *deviceInfo) +{ + struct AccelDrvData *drvData = AccelGetDrvData(); + + (void)memset_s((void *)deviceInfo, sizeof(*deviceInfo), 0, sizeof(*deviceInfo)); + deviceInfo->ops.GetInfo = SetAccelInfo; + deviceInfo->ops.Enable = SetAccelEnable; + deviceInfo->ops.Disable = SetAccelDisable; + deviceInfo->ops.SetBatch = SetAccelBatch; + deviceInfo->ops.SetMode = SetAccelMode; + deviceInfo->ops.SetOption = SetAccelOption; + + if (memcpy_s(&deviceInfo->sensorInfo, sizeof(deviceInfo->sensorInfo), + &drvData->accelCfg->sensorInfo, sizeof(drvData->accelCfg->sensorInfo)) != EOK) { + HDF_LOGE("%s: copy sensor info failed", __func__); + return HDF_FAILURE; + } + /* 传感器类型标识可以在数据HCS配置文件里面配置,也可以在此处 */ + drvData->accelCfg->sensorInfo.sensorTypeId = SENSOR_TAG_ACCELEROMETER; + drvData->accelCfg->sensorInfo.sensorId = SENSOR_TAG_ACCELEROMETER; + + return HDF_SUCCESS; +} +/* 传感器寄存器初始化操作 */ +static int32_t InitAccelAfterConfig(void) +{ + struct SensorDeviceInfo deviceInfo; + + if (InitAccelConfig() != HDF_SUCCESS) { + HDF_LOGE("%s: init accel config failed", __func__); + return HDF_FAILURE; + } + + if (InitAccelOps(&deviceInfo) != HDF_SUCCESS) { + HDF_LOGE("%s: init accel ops failed", __func__); + return HDF_FAILURE; + } + + if (AddSensorDevice(&deviceInfo) != HDF_SUCCESS) { + HDF_LOGE("%s: add accel device failed", __func__); + return HDF_FAILURE; + } + + return HDF_SUCCESS; +} +/*通过器件探测函数,挂载器件差异化函数接口*/ +static int32_t DetectAccelChip(void) +{ + int32_t num; + int32_t ret; + int32_t loop; + struct AccelDrvData *drvData = AccelGetDrvData(); + CHECK_NULL_PTR_RETURN_VALUE(drvData->accelCfg, HDF_ERR_INVALID_PARAM); + + num = sizeof(g_accelDetectIfList) / sizeof(g_accelDetectIfList[0]); + for (loop = 0; loop < num; ++loop) { + if (g_accelDetectIfList[loop].DetectChip != NULL) { + ret = g_accelDetectIfList[loop].DetectChip(drvData->accelCfg); + if (ret == HDF_SUCCESS) { + drvData->detectFlag = true; + break; + } + } + } + + if (loop == num) { + HDF_LOGE("%s: detect accel device failed", __func__); + drvData->detectFlag = false; + return HDF_FAILURE; + } + return HDF_SUCCESS; +} +/* 加速度计传感器驱动初始化入口函数,主要功能为对传感器私有数据的结构体对象进行初始化,传感器HCS数据配置对象空间分配,传感器HCS数据配置初始化入口函数调用,传感器设备探测是否在位功能,传感器数据上报定时器创建,传感器归一化接口挂载,传感器设备注册功能 */ +int32_t InitAccelDriver(struct HdfDeviceObject *device) +{ + /* 获取传感器私有数据结构体对象 */ + struct AccelDrvData *drvData = AccelGetDrvData(); + + /* 同类型传感器不同厂家设备探测时,判断此类型传感器是否已经在位,若已经在位,无需再继续探测,直接返回 */ + if (drvData->detectFlag) { + HDF_LOGE("%s: accel sensor have detected", __func__); + return HDF_SUCCESS; + } + + CHECK_NULL_PTR_RETURN_VALUE(device, HDF_ERR_INVALID_PARAM); + /* 分配存放传感器数据配置的私有结构体数据对象,需要在驱动释放时释放分配的资源空间 */ + drvData->accelCfg = (struct SensorCfgData *)OsalMemCalloc(sizeof(*cfg)); + if (drvData->accelCfg == NULL) { + HDF_LOGE("%s: malloc sensor config data failed", __func__); + return HDF_FAILURE; + } + + drvData->accelCfg->regCfgGroup = &g_regCfgGroup[0]; + /* 初始化传感器配置数据主要是解析传感器通讯总线配置类型信息,传感器基本信息,传感器属性信息,传感器是否在位信息,寄存器分组信息 */ + if (GetSensorBaseConfigData(device->property, drvData->accelCfg) != HDF_SUCCESS) { + HDF_LOGE("%s: get sensor base config failed", __func__); + goto Base_CONFIG_EXIT; + } + + if (DetectAccelChip() != HDF_SUCCESS) { + HDF_LOGE("%s: accel sensor detect device no exist", __func__); + goto DETECT_CHIP_EXIT; + } + drvData->detectFlag = true; + if (ParseSensorRegConfig(drvData->accelCfg) != HDF_SUCCESS) { + HDF_LOGE("%s: detect sensor device failed", __func__); + goto REG_CONFIG_EXIT; + } + + if (InitAccelAfterConfig() != HDF_SUCCESS) { + HDF_LOGE("%s: init accel after config failed", __func__); + goto INIT_EXIT; + } + + HDF_LOGI("%s: init accel driver success", __func__); + return HDF_SUCCESS; + +INIT_EXIT: + DestroySensorThread(&drvData->thread, &drvData->threadStatus); + (void)DeleteSensorDevice(SENSOR_TAG_ACCELEROMETER); +REG_CONFIG_EXIT: + ReleaseSensorAllRegConfig(drvData->accelCfg); + (void)ReleaseSensorBusHandle(&drvData->accelCfg->busCfg); +DETECT_CHIP_EXIT: + drvData->detectFlag = false; +BASE_CONFIG_EXIT: + drvData->accelCfg->root = NULL; + drvData->accelCfg->regCfgGroup = NULL; + OsalMemFree(drvData->accelCfg); + drvData->accelCfg = NULL; + return HDF_FAILURE; +} + +/* 释放驱动初始化时分配的资源 */ +void ReleaseAccelDriver(struct HdfDeviceObject *device) +{ + (void)device; + struct AccelDrvData *drvData = NULL; + + drvData = AccelGetDrvData(); + (void)DestroySensorThread(&drvData->thread, &drvData->threadStatus); + (void)DeleteSensorDevice(SENSOR_TAG_ACCELEROMETER); + drvData->detectFlag = false; + + if (drvData->accelCfg != NULL) { + drvData->accelCfg->root = NULL; + drvData->accelCfg->regCfgGroup = NULL; + ReleaseSensorAllRegConfig(drvData->accelCfg); + (void)ReleaseSensorBusHandle(&drvData->accelCfg->busCfg); + OsalMemFree(drvData->accelCfg); + drvData->accelCfg = NULL; + } + + drvData->initStatus = false; +} +``` + +1. 加速度计传感器寄存器组配置信息 + +加速度计传感器数据配置只需要按照模板配置即可,基于模板配置的解析功能已经在**InitSensorConfigData**函数完成,只需初始化时调用即可。如果有新增配置项,需要同步修改此函数。 + +``` +加速度传感器数据配置模板(accel_config.hcs) +root { + sensorAccelConfig { + accelChipConfig { + /* 传感器设备信息模板 */ + template sensorInfo { + sensorName = "accelerometer"; /* 加速度计名字,字符最大长度16字节 */ + vendorName = "borsh_bmi160"; /* 传感器设备厂商,字符最大长度16字节 */ + firmwareVersion = "1.0"; /* 传感器固件版本号,默认1.0,字符最大长度16字节 */ + hardwareVersion = "1.0"; /* 传感器硬件版本号,默认1.0,字符最大长度16字节 */ + sensorTypeId = 1; /* 传感器类型编号,详见{@link SensorTypeTag} */ + sensorId = 1; /* 传感器的标识号,有传感器驱动开发者定义,推荐用{@link SensorTypeTag}枚举 */ + maxRange = 8; /* 传感器的最大量程,根据开发者需要配置 */ + precision = 0; /* 传感器的精度,与上报数据配合使用,上报数据结构体{@link SensorEvents } */ + power = 230; /* 传感器的功耗 */ + } + /* 传感器使用的总线类型和配置信息模板 */ + template sensorBusConfig { + busType = 0; /* 0:i2c 1:spi */ + busNum = 6; /* 芯片上分配给传感器的器件号 */ + busAddr = 0; /* 芯片上分配给传感器的地址 */ + regWidth = 1; /* 传感器寄存器地址宽度 */ + regBigEndian = 0; /* 传感器寄存器大小端 */ + } + /* 传感器设备属性模板 */ + template sensorAttr { + chipName = ""; /* 传感器芯片名字 */ + chipIdRegister = 0xf; /* 传感器在位检测寄存器地址 */ + chipIdValue = 0xd1; /* 校验传感器在位检测寄存器值 */ + } + } + } +} + +/* 根据不同器件硬件差异,修改模板配置,不修改的就会默认采用模板配置 */ +root { + sensorAccelConfig { + accel_bmi160_chip_config : accelChipConfig { + match_attr = "hdf_sensor_accel_driver"; /* 需要和加速度传感器设备配置match_attr字段保持一致 */ + accelInfo :: sensorInfo { + vendorName = "borsh_bmi160"; + sensorTypeId = 1; + sensorId = 1; + } + accelBusConfig :: sensorBusConfig { + busType = 0; /* i2c通讯方式 */ + busNum = 6; + busAddr = 0x68; + regWidth = 1; /* 1字节位宽 */ + } + accelAttr :: sensorAttr { + chipName = "bmi160"; + chipIdRegister = 0x00; + chipIdValue = 0xd1; + } + accelRegConfig { + /* regAddr: 寄存器地址 + value: 寄存器值 + mask: 寄存器值的掩码 + len: 寄存器值的数据长度(字节) + delay: 配置寄存器延时(ms) + opsType:操作类型 0-无 1-读 2-写 3-读并检查 4-位更新 + calType: 计算类型 0-无 1-写 2-取反 3-异或 4-左移 5-右移 + shiftNum: 移动位数 + debug: 调试开关,0-调试关闭 1-调试打开 + save: 保存数据开关,0-不保存数据 1-保存数据 + */ + /* 传感器寄存器操作分组,按照分组进行有序配置 */ + /* 寄存器地址, 寄存器值, 寄存器值的掩码, 寄存器值的数据长度, 配置寄存器延时, 操作类型, 计算类型, 移动位数, 调试开关, 保存开关 */ + /* 初始化寄存器组 */ + initSeqConfig = [ + 0x7e, 0xb6, 0xff, 1, 5, 2, 0, 0, 0, 0, + 0x7e, 0x10, 0xff, 1, 5, 2, 0, 0, 0, 0 + ]; + /* 使能寄存器组 */ + enableSeqConfig = [ + 0x7e, 0x11, 0xff, 1, 5, 2, 0, 0, 0, 0, + 0x41, 0x03, 0xff, 1, 0, 2, 0, 0, 0, 0, + 0x40, 0x08, 0xff, 1, 0, 2, 0, 0, 0, 0 + ]; + /* 去使能寄存器组 */ + disableSeqConfig = [ + 0x7e, 0x10, 0xff, 1, 5, 2, 0, 0, 0, 0 + ]; + } + } + } +} +``` + +1. 加速度计传感器驱动操作接口实现 + +开发者需要根据每种类型的传感器实现归一化接口。 + +``` +/* 不使用函数暂时置空 */ +static int32_t SetAccelInfo(struct SensorBasicInfo *info) +{ + (void)info; + + return HDF_ERR_NOT_SUPPORT; +} +/* 下发使能寄存器组的配置 */ +static int32_t SetAccelEnable(void) +{ + int32_t ret; + struct AccelDrvData *drvData = AccelGetDrvData(); + + CHECK_NULL_PTR_RETURN_VALUE(drvData->accelCfg, HDF_ERR_INVALID_PARAM); + ret = SetSensorRegCfgArray(&drvData->accelCfg->busCfg, drvData->accelCfg->regCfgGroup[SENSOR_ENABLE_GROUP]); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: accel sensor disable config failed", __func__); + return HDF_FAILURE; + } + + drvData->threadStatus = SENSOR_THREAD_RUNNING; + + return HDF_SUCCESS; +} +/* 下发去使能寄存器组的配置 */ +static int32_t SetAccelDisable(void) +{ + int32_t ret; + struct AccelDrvData *drvData = AccelGetDrvData(); + + CHECK_NULL_PTR_RETURN_VALUE(drvData->accelCfg, HDF_ERR_INVALID_PARAM); + + ret = SetSensorRegCfgArray(&drvData->accelCfg->busCfg, drvData->accelCfg->regCfgGroup[SENSOR_DISABLE_GROUP]); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: accel sensor disable config failed", __func__); + return HDF_FAILURE; + } + + drvData->threadStatus = SENSOR_THREAD_STOPPED; + + return HDF_SUCCESS; +} +/* 配置传感器采样率和数据上报间隔 */ +static int32_t SetAccelBatch(int64_t samplingInterval, int64_t interval) +{ + (void)interval; + + struct AccelDrvData *drvData = AccelGetDrvData(); + drvData->interval = samplingInterval; + + return HDF_SUCCESS; +} +/* 设置传感器工作模式,当前支持实时模式 */ +static int32_t SetAccelMode(int32_t mode) +{ + return (mode == SENSOR_WORK_MODE_REALTIME) ? HDF_SUCCESS : HDF_FAILURE; +} +/* 设置传感器可选配置 */ +static int32_t SetAccelOption(uint32_t option) +{ + (void)option; + return HDF_ERR_NOT_SUPPORT; +} +``` + +- 差异化处理接口 + + ``` + /* 器件探测时,如果探测成功,则注册差异化处理函数到accel驱动模型里 */ + int32_t DetectAccelBim160Chip(struct SensorCfgData *data) + { + int32_t ret; + struct AccelOpsCall ops; + CHECK_NULL_PTR_RETURN_VALUE(data, HDF_ERR_INVALID_PARAM); + + if (strcmp(ACCEL_CHIP_NAME_BMI160, data->sensorAttr.chipName) != 0) { + return HDF_SUCCESS; + } + ret = InitAccelPreConfig(); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: init BMI160 bus mux config", __func__); + return HDF_FAILURE; + } + if (DetectSensorDevice(data) != HDF_SUCCESS) { + return HDF_FAILURE; + } + + /* 差异化处理函数 */ + ops.Init = InitBmi160; + ops.ReadData = ReadBmi160Data; + ret = RegisterAccelChipOps(&ops); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: register BMI160 accel failed", __func__); + (void)ReleaseSensorBusHandle(&data->busCfg); + return HDF_FAILURE; + } + return HDF_SUCCESS; + } + /* 初始化处理函数 */ + static int32_t InitBmi160(struct SensorCfgData *data) + { + int32_t ret; + + CHECK_NULL_PTR_RETURN_VALUE(data, HDF_ERR_INVALID_PARAM); + ret = SetSensorRegCfgArray(&data->busCfg, data->regCfgGroup[SENSOR_INIT_GROUP]); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: bmi160 sensor init config failed", __func__); + return HDF_FAILURE; + } + return HDF_SUCCESS; + } + /* 数据处理函数 */ + int32_t ReadBmi160Data(struct SensorCfgData *data) + { + int32_t ret; + struct AccelData rawData = { 0, 0, 0 }; + int32_t tmp[ACCEL_AXIS_NUM]; + struct SensorReportEvent event; + + (void)memset_s(&event, sizeof(event), 0, sizeof(event)); + + ret = ReadBmi160RawData(data, &rawData, &event.timestamp); + if (ret != HDF_SUCCESS) { + return HDF_FAILURE; + } + + event.sensorId = SENSOR_TAG_ACCELEROMETER; + event.option = 0; + event.mode = SENSOR_WORK_MODE_REALTIME; + + rawData.x = rawData.x * BMI160_ACC_SENSITIVITY_2G; + rawData.y = rawData.y * BMI160_ACC_SENSITIVITY_2G; + rawData.z = rawData.z * BMI160_ACC_SENSITIVITY_2G; + + tmp[ACCEL_X_AXIS] = (rawData.x * SENSOR_1K_UNIT) / SENSOR_CONVERT_UNIT; + tmp[ACCEL_Y_AXIS] = (rawData.y * SENSOR_1K_UNIT) / SENSOR_CONVERT_UNIT; + tmp[ACCEL_Z_AXIS] = (rawData.z * SENSOR_1K_UNIT) / SENSOR_CONVERT_UNIT; + + event.dataLen = sizeof(tmp); + event.data = (uint8_t *)&tmp; + ret = ReportSensorEvent(&event); + return ret; + } + ``` + +- 数据处理函数 + +创建传感器定时器,按照配置的采样率定时采样,并上报给数据订阅者。 + +``` +/* 传感器定时工作线程 */ +static int32_t ReadAccelDataThreadWorker(void *arg) +{ + (void)arg; + int64_t interval; + struct AccelDrvData *drvData = AccelGetDrvData(); + + drvData->threadStatus = SENSOR_THREAD_START; + while (true) { + if (drvData->threadStatus == SENSOR_THREAD_RUNNING) { + if (drvData->ops.ReadData != NULL) { + (void)drvData->ops.ReadData(drvData->accelCfg); + } + interval = OsalDivS64(drvData->interval, (SENSOR_CONVERT_UNIT * SENSOR_CONVERT_UNIT)); + OsalMSleep(interval); + } else if (drvData->threadStatus == SENSOR_THREAD_DESTROY) { + break; + } else { + OsalMSleep(ACC_DEFAULT_SAMPLING_200_MS / SENSOR_CONVERT_UNIT / SENSOR_CONVERT_UNIT); + } + + if ((!drvData->initStatus) || (drvData->interval < 0) || drvData->threadStatus != SENSOR_THREAD_RUNNING) { + continue; + } + } + + return HDF_SUCCESS; +} +/* 创建传感器定时器和器件初始化 */ +static int32_t InitAccelConfig(void) +{ + int32_t ret; + struct AccelDrvData *drvData = AccelGetDrvData(); + + if (drvData->threadStatus != SENSOR_THREAD_NONE && drvData->threadStatus != SENSOR_THREAD_DESTROY) { + HDF_LOGE("%s: accel thread have created", __func__); + return HDF_SUCCESS; + } + + ret = CreateSensorThread(&drvData->thread, ReadAccelDataThreadWorker, "hdf_sensor_accel", drvData); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: accel create thread failed", __func__); + drvData->threadStatus = SENSOR_THREAD_NONE; + return HDF_FAILURE; + } + + CHECK_NULL_PTR_RETURN_VALUE(drvData->ops.Init, HDF_ERR_INVALID_PARAM); + + ret = drvData->ops.Init(drvData->accelCfg); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: accel create thread failed", __func__); + drvData->threadStatus = SENSOR_THREAD_NONE; + return HDF_FAILURE; + } + drvData->initStatus = true; + return HDF_SUCCESS; +} +``` + +- 主要的数据结构 + +``` +/* 传感器转换单位*/ +#define SENSOR_CONVERT_UNIT 1000 +#define SENSOR_1K_UNIT 1024 +/* 传感器2g对应灵敏度转换值 */ +#define BMI160_ACC_SENSITIVITY_2G 61 +/* 传感器数据采样寄存器地址 */ +#define BMI160_ACCEL_X_LSB_ADDR 0X12 +#define BMI160_ACCEL_X_MSB_ADDR 0X13 +#define BMI160_ACCEL_Y_LSB_ADDR 0X14 +#define BMI160_ACCEL_Y_MSB_ADDR 0X15 +#define BMI160_ACCEL_Z_LSB_ADDR 0X16 +#define BMI160_ACCEL_Z_MSB_ADDR 0X17 +/* 传感器数据维度 */ +enum AccelAxisNum { + ACCEL_X_AXIS = 0, + ACCEL_Y_AXIS = 1, + ACCEL_Z_AXIS = 2, + ACCEL_AXIS_NUM = 3, +}; +/* 传感器每个维度值 */ +struct AccelData { + int32_t x; + int32_t y; + int32_t z; +}; +/* 传感器私有数据结构体 */ +struct AccelDrvData { + bool detectFlag; + uint8_t threadStatus; + uint8_t initStatus; + int64_t interval; + struct SensorCfgData *accelCfg; + struct OsalThread thread; + struct AccelOpsCall ops; +}; +/* 差异化适配函数 */ +struct AccelOpsCall { + int32_t (*Init)(struct SensorCfgData *data); + int32_t (*ReadData)(struct SensorCfgData *data); +}; +``` + +## 测试指导 + +驱动开发完成后,在传感器单元测试里面开发自测试用例,验证驱动基本功能。测试环境采用开发者自测试平台。 + +``` +/* 标识是否上报传感器数据 */ +static int32_t g_sensorDataFlag = 0; +/* 保持获取的传感器接口实例地址 */ +static const struct SensorInterface *g_sensorDev = nullptr; + +/* 订阅者注册数据上报函数 */ +static int SensorTestDataCallback(struct SensorEvents *event) +{ + if (event == nullptr) { + return -1; + } + float *data = (float*)event->data; + printf("time [%lld] sensor id [%d] x-[%f] y-[%f] z-[%f]\n\r", event->timestamp, + event->sensorId, (*data), *(data + 1), *(data + g_axisZ)); + if (*data > 1e-5) { + g_sensorDataFlag = 1; + } + return 0; +} +/* 用例执行前,初始化传感器接口实例 */ +void HdfSensorTest::SetUpTestCase() +{ + g_sensorDev = NewSensorInterfaceInstance(); + if (g_sensorDev == nullptr) { + printf("test sensorHdi get Module instace failed\n\r"); + } +} +/* 用例资源释放 */ +void HdfSensorTest::TearDownTestCase() +{ + if (g_sensorDev != nullptr) { + FreeSensorInterfaceInstance(); + g_sensorDev = nullptr; + } +} +/* 传感器驱动测试验证 */ +HWTEST_F(HdfSensorTest,TestAccelDriver_001, TestSize.Level0) +{ + int32_t sensorInterval = 1000000000; /* 数据采样率单位纳秒 */ + int32_t pollTime = 5; /* 数据采样时间单位秒 */ + int32_t accelSensorId = 1; /* 加速度传感器类型标识为1 */ + int32_t count = 0; + int ret; + struct SensorInformation *sensorInfo = nullptr; + + ret = g_sensorDev->Register(SensorTestDataCallback) + EXPECT_EQ(SENSOR_NULL_PTR, ret); + + ret = g_sensorDev->GetAllSensors(&sensorInfo, &count); + EXPECT_EQ(0, ret); + if (sensorInfo == nullptr) { + EXPECT_NE(nullptr, sensorInfo); + return; + } + /* 打印获取的传感器列表 */ + for (int i = 0; i < count; i++) { + printf("get sensoriId[%d], info name[%s]\n\r", sensorInfo[i]->sensorId, sensorInfo[i]->sensorName); + } + ret = g_sensorDev->Enable(accelSensorId); + EXPECT_EQ(0, ret); + g_sensorDataFlag = 0; + + ret = g_sensorDev->SetBatch(accelSensorId, sensorInterval, pollTime); + EXPECT_EQ(0, ret); + /* 在时间pollTime内,观察输出打印数据 */ + OsalSleep(pollTime); + EXPECT_EQ(1, g_sensorDataFlag); + + ret = g_sensorDev->Disable(accelSensorId); + g_sensorDataFlag = 0; + EXPECT_EQ(0, ret); + + ret = g_sensorDev->Unregister(); + EXPECT_EQ(0, ret); +} +``` + diff --git a/zh-cn/device-dev/driver/drive-peripherals-touch-des.md b/zh-cn/device-dev/driver/drive-peripherals-touch-des.md new file mode 100644 index 0000000000..107b2ce618 --- /dev/null +++ b/zh-cn/device-dev/driver/drive-peripherals-touch-des.md @@ -0,0 +1,410 @@ +# TOUCHSCREEN + +- [概述](#section175431838101617) + - [接口说明](#section17667171301711) + +- [开发指导](#section65745222184) + - [开发步骤](#section865734181916) + +- [开发实例](#section263714411191) + - [设备描述配置](#section18249155619195) + - [板级配置及器件私有配置](#section3571192072014) + - [添加器件驱动](#section6356758162015) + + +## 概述 + +- **Touchscreen驱动主要任务** + + Touchscreen驱动用于驱动触摸屏使其正常工作,该驱动主要完成如下工作:对触摸屏驱动IC进行上电、配置硬件管脚并初始化其状态、注册中断、配置通信接口(I2C或SPI)、设定input相关配置、下载及更新固件等操作。 + + +- **Touchscreen驱动层次说明** + + 本节主要介绍基于input驱动模型开发touchscreen器件驱动,其整体的框架模型如[图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驱动模型") + +- **Input驱动模型介绍** + + Input驱动模型核心部分由设备管理层、公共驱动层、器件驱动层组成。器件产生的数据借助平台数据通道能力从内核传递到用户态,驱动模型通过配置文件适配不同器件及硬件平台,提高开发者的器件驱动开发效率。如下部分为模型各部分的说明: + + (1)input设备管理:为各类输入设备驱动提供input设备的注册、注销接口,同时统一管理input设备列表; + + (2)input平台驱动:指各类input设备的公共抽象驱动(例如触摸屏的公共驱动),负责对板级硬件进行初始化、硬件中断处理、向manager注册input设备等; + + (3)input器件驱动:指各器件厂家的差异化驱动,通过适配平台驱动预留的差异化接口,实现器件驱动开发量最小化; + + (4)input数据通道:提供一套通用的数据上报通道,各类别的input设备驱动均可用此通道上报input事件; + + (5)input配置解析:负责对input设备的板级配置及器件私有配置进行解析及管理。 + + +- **基于HDF驱动框架开发器件驱动的优势** + + 在HDF(Hardware Driver Foundation)[驱动管理框架](drive-hdf-development.md)的基础上,input驱动模型调用OSAL接口层和Platfom接口层提供的基础接口进行开发,包括bus通信接口、操作系统原生接口(memory、lock、thread、timer等)。由于OSAL接口和Platform接口屏蔽了芯片平台差异,所以基于input驱动模型实现的touchscreen驱动可以进行跨平台、跨OS迁移,以便逐步实现驱动的一次开发,多端部署。 + + +### 接口说明 + +Touchscreen器件的硬件接口相对简单,根据PIN脚的属性,可以简单分为如下三类: + +- 电源接口 +- IO控制接口 +- 通信接口 + +**图 2** Touchscreen器件常用管脚 +![](figure/Touchscreen器件常用管脚.png "Touchscreen器件常用管脚") + +如上图所示的三类接口,分别做简要说明如下: + +1. **电源接口** + - LDO\_1P8:1.8v数字电路 + - LDO\_3P3:3.3v模拟电路 + + 通常情况下,touchscreen驱动IC和LCD驱动IC是相互分离的,这种情况下,touchscreen驱动IC一般同时需要1.8v和3.3v两路供电。随着芯片演进,业内已有touchscreen驱动IC和LCD驱动IC集成在一颗IC中的芯片案例,对touchscreen而言,只需要关注1.8v供电即可,其内部需要的3.3v电源,会在驱动IC内部从LCD的VSP电源(典型值5.5V)中分出来。 + + +2. **IO控制接口** + - Reset:reset管脚,用于在系统休眠、唤醒时,由主机侧对驱动IC进行复位操作。 + - INT:中断管脚,需要在驱动初始化时,配置为输入上拉状态。在驱动IC检测到外部触摸信号后,通过操作中断管脚来触发中断,器件驱动则会在中断处理函数中进行报点数据读取等操作。 + +3. **通信接口** + - I2C:由于touchscreen的报点数据量相对较少,所以一般选用I2C方式传输数据。I2C的具体协议及对应操作接口,可以参考Platform接口层中的[“I2C”使用指南](drive-platform-i2c-des.md#section1695201514281)。 + - SPI:部分厂商,由于需要传递的数据不止报点坐标,而是需要获取基础容值,数据量较大,所以会选用SPI通信方式。SPI的具体协议及对应操作接口,可以参考Platform接口层中的[“SPI” 使用指南](drive-platform-spi-des.md#section71363452477)。 + + +## 开发指导 + +Input驱动模型是基于HDF框架、Platform接口和OSAL接口开发,不区分操作系统和芯片平台,为touchscreen等输入器件提供统一的驱动开发架构。 + +- 如下以touchscreen器件驱动为例,说明input驱动模型的完整加载流程: + + (1)设备描述配置:由开发者参考已有模板进行设备描述配置,包括驱动加载顺序、板级硬件信息、器件私有数据信息等。 + + (2)加载input设备管理驱动:input设备管理驱动由HDF驱动加载,完成设备manager的创建并对其初始化。 + + (3)加载平台驱动:平台驱动由HDF框架加载,主要完成板级配置解析及硬件初始化,并提供器件注册接口。 + + (4)加载器件驱动:器件驱动也由HDF框架加载,完成器件设备的实例化,包括器件私有配置解析和平台预留的差异化接口适配。 + + (5)器件设备向平台驱动注册:将实例化的器件设备向平台驱动注册,实现设备和驱动的绑定,并完成中断注册、上下电等器件初始化工作。 + + (6)input设备注册:在器件初始化完成后,实例化input设备,并将其注册到input manager进行管理。 + + +### 开发步骤 + +1. 设备描述配置 + + 目前Input驱动基于HDF驱动框架编写,驱动的加载启动由HDF驱动管理框架统一处理。首先需要在对应的配置文件中,将驱动信息注册进去,如是否加载、加载优先级,此后HDF驱动框架会逐一启动注册过的驱动模块。驱动的相关配置请参考[HDF驱动框架配置指导](drive-hdf-development.md#section1969312275533)。 + +2. 板级配置及Touchscreen器件私有配置 + + 配置对应的IO管脚功能,例如对单板上为touchscreen设计预留的I2C Pin脚,需设置对应的寄存器,使其选择I2C的通信功能。 + +3. 实现器件差异化适配接口 + + 根据硬件单板设计的通信接口,使用Platform接口层提供的管脚操作接口配置对应的复位管脚、中断管脚以及电源操作,对于GPIO的操作,可参考[GPIO操作接口指导](drive-platform-gpio-des.md#section259614242196) + + +## 开发实例 + +本实例提供touchscreen驱动开发示例,并简要对具体关键点进行开发说明。 + +### 设备描述配置 + +如下配置主要包含input驱动模型各模块层级信息,具体原理可参考[HDF驱动开发指南](drive-hdf-development.md),HDF框架依据该配置信息实现对Input模型各模块的依次加载等。 + +``` +input :: host { + hostName = "input_host"; + priority = 100; + device_input_manager :: device { + device0 :: deviceNode { + policy = 2; // 向外发布服务 + priority = 100; // 加载优先级,在input模块内,manager模块优先级应为最高 + preload = 0; // 加载该驱动 0:加载 1:不加载 + permission = 0660; + moduleName = "HDF_INPUT_MANAGER"; + serviceName = "input_dev_manager"; + deviceMatchAttr = ""; + } + } + device_hdf_touch :: device { + device0 :: deviceNode { + policy = 2; + priority = 120; + preload = 0; + permission = 0660; + moduleName = "HDF_TOUCH"; + serviceName = "event1"; + deviceMatchAttr = "touch_device1"; + } + } + + device_touch_chip :: device { + device0 :: deviceNode { + policy = 0; + priority = 130; + preload = 0; + permission = 0660; + moduleName = "HDF_TOUCH_SAMPLE"; + serviceName = "hdf_touch_sample_service"; + deviceMatchAttr = "zsj_sample_5p5"; + } + } +} +``` + +### 板级配置及器件私有配置 + +如下配置包含板级硬件配置及器件私有数据配置,实际业务开发时,可根据具体需求增删及修改如下配置文件信息。 + +``` +root { + input_config { + touchConfig { + touch0 { + boardConfig { + match_attr = "touch_device1"; + inputAttr { + inputType = 0; // 0代表触摸屏 + solutionX = 480; + solutionY = 960; + devName = "main_touch"; // 设备名称 + } + busConfig { + busType = 0; // 0代表I2C + busNum = 6; + clkGpio = 86; + dataGpio = 87; + i2cClkIomux = [0x114f0048, 0x403]; // i2c_clk对应pin的寄存器配置 + i2cDataIomux = [0x114f004c, 0x403]; // i2c_data对应pin的寄存器配置 + } + pinConfig { + rstGpio = 3; + intGpio = 4; + rstRegCfg = [0x112f0094, 0x400]; // reset对应pin的寄存器配置 + intRegCfg = [0x112f0098, 0x400]; // interrupt对应pin的寄存器配置 + } + powerConfig { + vccType = 2; // 1代表LDO、2代表GPIO、3代表PMIC + vccNum = 20; // GPIO号为20 + vccValue = 1800; // 电压幅值为1800mV + vciType = 1; + vciNum = 12; + vciValue = 3300; + } + featureConfig { + capacitanceTest = 0; + gestureMode = 0; + gloverMOde = 0; + coverMode = 0; + chargerMode = 0; + knuckleMode = 0; + } + } + chipConfig { + template touchChip { + match_attr = ""; + chipName = "sample"; + vendorName = "zsj"; + chipInfo = "AAAA11222"; // 1~4字符代表产品名,5~6字符代表IC型号,7~9字符代表模型型号 + busType = 0; + deviceAddr = 0x5D; + irqFlag = 2; // 1代表上升沿触发,2代表下降沿触发,4代表高电平触发,8代表低电平触发 + maxSpeed = 400; + chipVersion = 0; + powerSequence { + /* 上电时序的配置含义说明: + [类型, 状态, 方向 , 延时] + 0代表空,1代表vcc电源(1.8V),2代表VCI电源(3.3V),3代表复位管脚,4代表中断管脚 + 0代表下电或拉低,1代表上电或拉高,2代表无操作 + 0代表输入方向,1代表输出方向,2代表无操作 + 代表延时多少毫秒, 例如20代表延时20ms + */ + powerOnSeq = [4, 0, 1, 0, + 3, 0, 1, 10, + 3, 1, 2, 60, + 4, 2, 0, 0]; + suspendSeq = [3, 0, 2, 10]; + resumeSeq = [3, 1, 2, 10]; + powerOffSeq = [3, 0, 2, 10, + 1, 0, 2, 20]; + } + } + chip0 :: touchChip { + match_attr = "zsj_sample_5p5"; + chipInfo = "ZIDN45100"; + chipVersion = 0; + } + } + } + } + } +} +``` + +### 添加器件驱动 + +在器件驱动中,主要实现了平台预留的差异化接口,以器件数据获取及解析进行示例说明。具体开发过程,需要根据实际使用的单板及器件进行适配。 + +``` +/* 将从器件中读取到的报点数据解析为坐标 */ +static void ParsePointData(ChipDevice *device, FrameData *frame, uint8_t *buf, uint8_t pointNum) +{ + int32_t resX = device->driver->boardCfg->attr.resolutionX; + int32_t resY = device->driver->boardCfg->attr.resolutionY; + + for (int32_t i = 0; i < pointNum; i++) { + frame->fingers[i].y = (buf[GT_POINT_SIZE * i + GT_X_LOW] & ONE_BYTE_MASK) | + ((buf[GT_POINT_SIZE * i + GT_X_HIGH] & ONE_BYTE_MASK) << ONE_BYTE_OFFSET); + frame->fingers[i].x = (buf[GT_POINT_SIZE * i + GT_Y_LOW] & ONE_BYTE_MASK) | + ((buf[GT_POINT_SIZE * i + GT_Y_HIGH] & ONE_BYTE_MASK) << ONE_BYTE_OFFSET); + frame->fingers[i].valid = true; + } +} +/* 从器件中获取报点数据 */ +static int32_t ChipDataHandle(ChipDevice *device) +{ + int32_t ret; + uint8_t touchStatus = 0; + uint8_t pointNum; + uint8_t buf[GT_POINT_SIZE * MAX_SUPPORT_POINT] = {0}; + InputI2cClient *i2cClient = &device->driver->i2cClient; + uint8_t reg[GT_ADDR_LEN] = {0}; + FrameData *frame = &device->driver->frameData; + reg[0] = (GT_BUF_STATE_ADDR >> ONE_BYTE_OFFSET) & ONE_BYTE_MASK; + reg[1] = GT_BUF_STATE_ADDR & ONE_BYTE_MASK; + ret = InputI2cRead(i2cClient, reg, GT_ADDR_LEN, &touchStatus, 1); + if (ret < 0 || touchStatus == GT_EVENT_INVALID) { + return HDF_FAILURE; + } + OsalMutexLock(&device->driver->mutex); + (void)memset_s(frame, sizeof(FrameData), 0, sizeof(FrameData)); + if (touchStatus == GT_EVENT_UP) { + frame->realPointNum = 0; + frame->definedEvent = TOUCH_UP; + goto exit; + } + reg[0] = (GT_X_LOW_BYTE_BASE >> ONE_BYTE_OFFSET) & ONE_BYTE_MASK; + reg[1] = GT_X_LOW_BYTE_BASE & ONE_BYTE_MASK; + pointNum = touchStatus & GT_FINGER_NUM_MASK; + if (pointNum <= 0 || pointNum > MAX_SUPPORT_POINT) { + HDF_LOGE("%s: pointNum is invalid, %d", __func__, pointNum); + (void)ChipCleanBuffer(i2cClient); + OsalMutexUnlock(&device->driver->mutex); + return HDF_FAILURE; + } + frame->realPointNum = pointNum; + frame->definedEvent = TOUCH_DOWN; + /* 从寄存器中读取报点值 */ + (void)InputI2cRead(i2cClient, reg, GT_ADDR_LEN, buf, GT_POINT_SIZE * pointNum); + /* 解析报点值 */ + ParsePointData(device, frame, buf, pointNum); +exit: + OsalMutexUnlock(&device->driver->mutex); + if (ChipCleanBuffer(i2cClient) != HDF_SUCCESS) { + return HDF_FAILURE; + } + return HDF_SUCCESS; +} + +static struct TouchChipOps g_sampleChipOps = { + .Init = ChipInit, + .Detect = ChipDetect, + .Resume = ChipResume, + .Suspend = ChipSuspend, + .DataHandle = ChipDataHandle, +}; + +static TouchChipCfg *ChipConfigInstance(struct HdfDeviceObject *device) +{ + TouchChipCfg *chipCfg = (TouchChipCfg *)OsalMemAlloc(sizeof(TouchChipCfg)); + if (chipCfg == NULL) { + HDF_LOGE("%s: instance chip config failed", __func__); + return NULL; + } + (void)memset_s(chipCfg, sizeof(TouchChipCfg), 0, sizeof(TouchChipCfg)); + /* 解析器件私有配置 */ + if (ParseTouchChipConfig(device->property, chipCfg) != HDF_SUCCESS) { + HDF_LOGE("%s: parse chip config failed", __func__); + OsalMemFree(chipCfg); + chipCfg = NULL; + } + return chipCfg; +} + +static ChipDevice *ChipDeviceInstance(void) +{ + ChipDevice *chipDev = (ChipDevice *)OsalMemAlloc(sizeof(ChipDevice)); + if (chipDev == NULL) { + HDF_LOGE("%s: instance chip device failed", __func__); + return NULL; + } + (void)memset_s(chipDev, sizeof(ChipDevice), 0, sizeof(ChipDevice)); + return chipDev; +} + +static void FreeChipConfig(TouchChipCfg *config) +{ + if (config->pwrSeq.pwrOn.buf != NULL) { + OsalMemFree(config->pwrSeq.pwrOn.buf); + } + if (config->pwrSeq.pwrOff.buf != NULL) { + OsalMemFree(config->pwrSeq.pwrOff.buf); + } + OsalMemFree(config); +} + +static int32_t HdfSampleChipInit(struct HdfDeviceObject *device) +{ + TouchChipCfg *chipCfg = NULL; + ChipDevice *chipDev = NULL; + HDF_LOGE("%s: enter", __func__); + if (device == NULL) { + return HDF_ERR_INVALID_PARAM; + } + /* 器件私有配置解析 */ + chipCfg = ChipConfigInstance(device); + if (chipCfg == NULL) { + return HDF_ERR_MALLOC_FAIL; + } + /* 器件设备实例化 */ + chipDev = ChipDeviceInstance(); + if (chipDev == NULL) { + goto freeCfg; + } + chipDev->chipCfg = chipCfg; + chipDev->ops = &g_sampleChipOps; + chipDev->chipName = chipCfg->chipName; + chipDev->vendorName = chipCfg->vendorName; + + /* 器件设备注册到平台驱动 */ + if (RegisterChipDevice(chipDev) != HDF_SUCCESS) { + goto freeDev; + } + HDF_LOGI("%s: exit succ, chipName = %s", __func__, chipCfg->chipName); + return HDF_SUCCESS; + +freeDev: + OsalMemFree(chipDev); +freeCfg: + FreeChipConfig(chipCfg); + return HDF_FAILURE; +} + +struct HdfDriverEntry g_touchSampleChipEntry = { + .moduleVersion = 1, + .moduleName = "HDF_TOUCH_SAMPLE", + .Init = HdfSampleChipInit, +}; + +HDF_INIT(g_touchSampleChipEntry); +``` + diff --git a/zh-cn/device-dev/driver/drive-peripherals.md b/zh-cn/device-dev/driver/drive-peripherals.md new file mode 100644 index 0000000000..176fb421cd --- /dev/null +++ b/zh-cn/device-dev/driver/drive-peripherals.md @@ -0,0 +1,11 @@ +# 外设 + +- **[LCD](drive-peripherals-lcd-des.md)** + +- **[TOUCHSCREEN](drive-peripherals-touch-des.md)** + +- **[SENSOR](drive-peripherals-sensor-des.md)** + +- **[WLAN](drive-peripherals-external-des.md)** + + diff --git a/zh-cn/device-dev/driver/drive-platform-gpio-des.md b/zh-cn/device-dev/driver/drive-platform-gpio-des.md new file mode 100644 index 0000000000..d4e67c7a51 --- /dev/null +++ b/zh-cn/device-dev/driver/drive-platform-gpio-des.md @@ -0,0 +1,560 @@ +# GPIO + +- [概述](#section1635911016188) + - [接口说明](#section17715915181611) + +- [使用指导](#section259614242196) + - [使用流程](#section103477714216) + - [确定GPIO管脚号](#section370083272117) + - [使用API操作GPIO管脚](#section13604050132118) + +- [使用实例](#section25941262111) + +## 概述 + +GPIO(General-purpose input/output)即通用型输入输出。通常,GPIO控制器通过分组的方式管理所有GPIO管脚,每组GPIO有一个或多个寄存器与之关联,通过读写寄存器完成对GPIO管脚的操作。 + +GPIO接口定义了操作GPIO管脚的标准方法集合,包括: + +- 设置管脚方向: 方向可以是输入或者输出\(暂不支持高阻态\) + +- 读写管脚电平值: 电平值可以是低电平或高电平 +- 设置管脚中断服务函数:设置一个管脚的中断响应函数,以及中断触发方式 +- 使能和禁止管脚中断:禁止或使能管脚中断 + +### 接口说明 + +**表 1** GPIO驱动API接口功能介绍 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    功能分类

    +

    接口名

    +

    描述

    +

    GPIO读写

    +

    GpioRead

    +

    读管脚电平值

    +

    GpioWrite

    +

    写管脚电平值

    +

    GPIO配置

    +

    GpioSetDir

    +

    设置管脚方向

    +

    GpioGetDir

    +

    获取管脚方向

    +

    GPIO中断设置

    +

    GpioSetIrq

    +

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

    +

    GpioUnSetIrq

    +

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

    +

    GpioEnableIrq

    +

    使能管脚中断

    +

    GpioDisableIrq

    +

    禁止管脚中断

    +
    + +>![](../public_sys-resources/icon-note.gif) **说明:** +>本文涉及的所有接口,仅限内核态使用,不支持在用户态使用。 + +## 使用指导 + +### 使用流程 + +GPIO标准API通过GPIO管脚号来操作指定管脚,使用GPIO的一般流程如[图1](#fig1399416053717)所示。 + +**图 1** GPIO使用流程图 + + +![](figure/zh-cn_image_0000001170187071.png) + +### 确定GPIO管脚号 + +不同SOC芯片由于其GPIO控制器型号、参数、以及控制器驱动的不同,GPIO管脚号的换算方式不一样。 + +- Hi3516DV300 + + 控制器管理12组GPIO管脚,每组8个。 + + GPIO号 = GPIO组索引 \(0\~11\) \* 每组GPIO管脚数\(8\) + 组内偏移 + + 举例:GPIO10\_3的GPIO号 = 10 \* 8 + 3 = 83 + +- Hi3518EV300 + + 控制器管理10组GPIO管脚,每组10个。 + + GPIO号 = GPIO组索引 \(0\~9\) \* 每组GPIO管脚数\(10\) + 组内偏移 + + 举例:GPIO7\_3的GPIO管脚号 = 7 \* 10 + 3 = 73 + + +### 使用API操作GPIO管脚 + +- 设置GPIO管脚方向 + + 在进行GPIO管脚读写前,需要先通过如下函数设置GPIO管脚方向: + + int32\_t GpioSetDir\(uint16\_t gpio, uint16\_t dir\); + + **表 2** GpioSetDir参数和返回值描述 + + + + + + + + + + + + + + + + + + + + + +

    参数

    +

    参数描述

    +

    gpio

    +

    待设置的GPIO管脚号

    +

    dir

    +

    待设置的方向值

    +

    返回值

    +

    返回值描述

    +

    0

    +

    设置成功

    +

    负数

    +

    设置失败

    +
    + + +- 读写GPIO管脚 + + 如果要读取一个GPIO管脚电平,通过以下函数完成: + + int32\_t GpioRead\(uint16\_t gpio, uint16\_t \*val\); + + **表 3** GpioRead参数和返回值描述 + + + + + + + + + + + + + + + + + + + + + +

    参数

    +

    参数描述

    +

    gpio

    +

    待读取的GPIO管脚号

    +

    val

    +

    接收读取电平值的指针

    +

    返回值

    +

    返回值描述

    +

    0

    +

    读取成功

    +

    负数

    +

    读取失败

    +
    + + 如果要向GPIO管脚写入电平值,通过以下函数完成: + + int32\_t GpioWrite\(uint16\_t gpio, uint16\_t val\); + + **表 4** GpioWrite参数和返回值描述 + + + + + + + + + + + + + + + + + + + + + +

    参数

    +

    参数描述

    +

    gpio

    +

    待写入的GPIO管脚号

    +

    val

    +

    待写入的电平值

    +

    返回值

    +

    返回值描述

    +

    0

    +

    写入成功

    +

    负数

    +

    写入失败

    +
    + + 示例代码: + + ``` + int32_t ret; + uint16_t val; + /* 将3号GPIO管脚配置为输出 */ + ret = GpioSetDir(3, GPIO_DIR_OUT); + if (ret != 0) { + HDF_LOGE("GpioSerDir: failed, ret %d\n", ret); + return; + } + /* 向3号GPIO管脚写入低电平GPIO_VAL_LOW */ + ret = GpioWrite(3, GPIO_VAL_LOW); + if (ret != 0) { + HDF_LOGE("GpioWrite: failed, ret %d\n", ret); + return; + } + /* 将6号GPIO管脚配置为输入 */ + ret = GpioSetDir(6, GPIO_DIR_IN); + if (ret != 0) { + HDF_LOGE("GpioSetDir: failed, ret %d\n", ret); + return; + } + /* 读取6号GPIO管脚的电平值 */ + ret = GpioRead(6, &val); + ``` + + +- 设置GPIO中断 + + 如果要为一个GPIO管脚设置中断响应程序,使用如下函数: + + int32\_t GpioSetIrq\(uint16\_t gpio, uint16\_t mode, GpioIrqFunc func, void \*arg\); + + **表 5** GpioSetIrq参数和返回值描述 + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    参数

    +

    参数描述

    +

    gpio

    +

    GPIO管脚号

    +

    mode

    +

    中断触发模式

    +

    func

    +

    中断服务程序

    +

    arg

    +

    传递给中断服务程序的入参

    +

    返回值

    +

    返回值描述

    +

    0

    +

    设置成功

    +

    负数

    +

    设置失败

    +
    + + >![](../public_sys-resources/icon-caution.gif) **注意:** + >同一时间,只能为某个GPIO管脚设置一个中断服务函数,如果重复调用GpioSetIrq函数,则之前设置的中断服务函数会被取代。 + + 当不再需要响应中断服务函数时,使用如下函数取消中断设置: + + int32\_t GpioUnSetIrq\(uint16\_t gpio\); + + **表 6** GpioUnSetIrq参数和返回值描述 + + + + + + + + + + + + + + + + + + +

    参数

    +

    参数描述

    +

    gpio

    +

    GPIO管脚号

    +

    返回值

    +

    返回值描述

    +

    0

    +

    取消成功

    +

    负数

    +

    取消失败

    +
    + + 在中断服务程序设置完成后,还需要先通过如下函数使能GPIO管脚的中断: + + int32\_t GpioEnableIrq\(uint16\_t gpio\); + + **表 7** GpioEnableIrq参数和返回值描述 + + + + + + + + + + + + + + + + + + +

    参数

    +

    参数描述

    +

    gpio

    +

    GPIO管脚号

    +

    返回值

    +

    返回值描述

    +

    0

    +

    使能成功

    +

    负数

    +

    使能失败

    +
    + + >![](../public_sys-resources/icon-caution.gif) **注意:** + >必须通过此函数使能管脚中断,之前设置的中断服务函数才能被正确响应。 + + 如果要临时屏蔽此中断,可以通过如下函数禁止GPIO管脚中断: + + int32\_t GpioDisableIrq\(uint16\_t gpio\); + + **表 8** GpioDisableIrq参数和返回值描述 + + + + + + + + + + + + + + + + + + +

    参数

    +

    参数描述

    +

    gpio

    +

    GPIO管脚号

    +

    返回值

    +

    返回值描述

    +

    0

    +

    禁止成功

    +

    负数

    +

    禁止失败

    +
    + + 示例代码: + + ``` + /* 中断服务函数 + */ + int32_t MyCallBackFunc(uint16_t gpio, void *data) + { + HDF_LOGI("%s: gpio:%u interrupt service in! data=%p\n", __func__, gpio, data); + return 0; + } + + int32_t ret; + /* 设置中断服务程序为MyCallBackFunc,入参为NULL,中断触发模式为上升沿触发 */ + ret = GpioSetIrq(3, OSAL_IRQF_TRIGGER_RISING, MyCallBackFunc, NULL); + if (ret != 0) { + HDF_LOGE("GpioSetIrq: failed, ret %d\n", ret); + return; + } + + /* 使能3号GPIO管脚中断 */ + ret = GpioEnableIrq(3); + if (ret != 0) { + HDF_LOGE("GpioEnableIrq: failed, ret %d\n", ret); + return; + } + + /* 禁止3号GPIO管脚中断 */ + ret = GpioDisableIrq(3); + if (ret != 0) { + HDF_LOGE("GpioDisableIrq: failed, ret %d\n", ret); + return; + } + + /* 取消3号GPIO管脚中断服务程序 */ + ret = GpioUnSetIrq(3); + if (ret != 0) { + HDF_LOGE("GpioUnSetIrq: failed, ret %d\n", ret); + return; + } + ``` + + +## 使用实例 + +本实例程序中,我们将测试一个GPIO管脚的中断触发:为管脚设置中断服务函数,触发方式为边沿触发,然后通过交替写高低电平到管脚,产生电平波动,制造触发条件,观察中断服务函数的执行。 + +首先需要选取一个空闲的GPIO管脚,本例程基于Hi3516DV300某开发板,GPIO管脚选择GPIO10\_3,换算成GPIO号为83。 + +读者可以根据自己使用的开发板,参考其原理图,选择一个空闲的GPIO管脚即可。 + +``` +#include "gpio_if.h" +#include "hdf_log.h" +#include "osal_irq.h" +#include "osal_time.h" + +static uint32_t g_irqCnt; + +/* 中断服务函数*/ +static int32_t TestCaseGpioIrqHandler(uint16_t gpio, void *data) +{ + HDF_LOGE("%s: irq triggered! on gpio:%u, data=%p", __func__, gpio, data); + g_irqCnt++; /* 如果中断服务函数触发执行,则将全局中断计数加1 */ + return GpioDisableIrq(gpio); +} + +/* 测试用例函数 */ +static int32_t TestCaseGpioIrqEdge(void) +{ + int32_t ret; + uint16_t valRead; + uint16_t mode; + uint16_t gpio = 83; /* 待测试的GPIO管脚号 */ + uint32_t timeout; + + /* 将管脚方向设置为输出 */ + ret = GpioSetDir(gpio, GPIO_DIR_OUT); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: set dir fail! ret:%d\n", __func__, ret); + return ret; + } + + /* 先禁止该管脚中断 */ + ret = GpioDisableIrq(gpio); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: disable irq fail! ret:%d\n", __func__, ret); + return ret; + } + + /* 为管脚设置中断服务函数,触发模式为上升沿和下降沿共同触发 */ + mode = OSAL_IRQF_TRIGGER_RISING | OSAL_IRQF_TRIGGER_FALLING; + HDF_LOGE("%s: mode:%0x\n", __func__, mode); + ret = GpioSetIrq(gpio, mode, TestCaseGpioIrqHandler, NULL); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: set irq fail! ret:%d\n", __func__, ret); + return ret; + } + + /* 使能此管脚中断 */ + ret = GpioEnableIrq(gpio); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: enable irq fail! ret:%d\n", __func__, ret); + (void)GpioUnSetIrq(gpio); + return ret; + } + + g_irqCnt = 0; /* 清除全局计数器 */ + timeout = 0; /* 等待时间清零 */ + /* 等待此管脚中断服务函数触发,等待超时时间为1000毫秒 */ + while (g_irqCnt <= 0 && timeout < 1000) { + (void)GpioRead(gpio, &valRead); + (void)GpioWrite(gpio, (valRead == GPIO_VAL_LOW) ? GPIO_VAL_HIGH : GPIO_VAL_LOW); + HDF_LOGE("%s: wait irq timeout:%u\n", __func__, timeout); + OsalMDelay(200); /* wait for irq trigger */ + timeout += 200; + } + (void)GpioUnSetIrq(gpio); + return (g_irqCnt > 0) ? HDF_SUCCESS : HDF_FAILURE; +} +``` + diff --git a/zh-cn/device-dev/driver/drive-platform-i2c-des.md b/zh-cn/device-dev/driver/drive-platform-i2c-des.md new file mode 100644 index 0000000000..915c5f440e --- /dev/null +++ b/zh-cn/device-dev/driver/drive-platform-i2c-des.md @@ -0,0 +1,426 @@ +# I2C + +- [概述](#section5361140416) + - [接口说明](#section459052019177) + +- [使用指导](#section1695201514281) + - [使用流程](#section1338373417288) + - [打开I2C控制器](#section13751110132914) + - [进行I2C通信](#section9202183372916) + - [关闭I2C控制器](#section19481164133018) + +- [使用实例](#section5302202015300) + +## 概述 + +- I2C\(Inter Integrated Circuit\)总线是由Philips公司开发的一种简单、双向二线制同步串行总线。 +- I2C以主从方式工作,通常有一个主设备和一个或者多个从设备,主从设备通过SDA\(SerialData\)串行数据线以及SCL\(SerialClock\)串行时钟线两根线相连,如[图1 ](#fig1135561232714)所示。 + +- I2C数据的传输必须以一个起始信号作为开始条件,以一个结束信号作为传输的停止条件。数据传输以字节为单位,高位在前,逐个bit进行传输。 +- I2C总线上的每一个设备都可以作为主设备或者从设备,而且每一个设备都会对应一个唯一的地址,当主设备需要和某一个从设备通信时,通过广播的方式,将从设备地址写到总线上,如果某个从设备符合此地址,将会发出应答信号,建立传输。 + +- I2C接口定义了完成I2C传输的通用方法集合,包括: + + - I2C控制器管理: 打开或关闭I2C控制器 + - I2C消息传输:通过消息传输结构体数组进行自定义传输 + + **图 1** I2C物理连线示意图 + ![](figure/I2C物理连线示意图.png "I2C物理连线示意图") + + +### 接口说明 + +**表 1** I2C驱动API接口功能介绍 + + + + + + + + + + + + + + + + + + + +

    功能分类

    +

    接口名

    +

    描述

    +

    I2C控制器管理接口

    +

    I2cOpen

    +

    打开I2C控制器

    +

    I2cClose

    +

    关闭I2C控制器

    +

    I2c消息传输接口

    +

    I2cTransfer

    +

    自定义传输

    +
    + +>![](../public_sys-resources/icon-note.gif) **说明:** +>本文涉及的所有接口,仅限内核态使用,不支持在用户态使用。 + +## 使用指导 + +### 使用流程 + +使用I2C设备的一般流程如[图2](#fig166181128151112)所示。 + +**图 2** I2C设备使用流程图 + + +![](figure/zh-cn_image_0000001123509750.png) + +### 打开I2C控制器 + +在进行I2C通信前,首先要调用I2cOpen打开I2C控制器。 + +DevHandle I2cOpen\(int16\_t number\); + +**表 2** I2cOpen参数和返回值描述 + + + + + + + + + + + + + + + + + + + +

    参数

    +

    参数描述

    +

    number

    +

    I2C控制器号

    +

    返回值

    +

    返回值描述

    +

    NULL

    +

    打开I2C控制器失败

    +

    设备句柄

    +

    打开的I2C控制器设备句柄

    +
    + +假设系统中存在8个I2C控制器,编号从0到7,那么我们现在获取3号控制器 + +``` +DevHandle i2cHandle = NULL; /* I2C控制器句柄 / + +/* 打开I2C控制器 */ +i2cHandle = I2cOpen(3); +if (i2cHandle == NULL) { + HDF_LOGE("I2cOpen: failed\n"); + return; +} +``` + +### 进行I2C通信 + +消息传输 + +int32\_t I2cTransfer\(DevHandle handle, struct I2cMsg \*msgs, int16\_t count\); + +**表 3** I2cTransfer参数和返回值描述 + + + + + + + + + + + + + + + + + + + + + + + + + +

    参数

    +

    参数描述

    +

    handle

    +

    I2C控制器设备句柄

    +

    msgs

    +

    待传输数据的消息结构体数组

    +

    count

    +

    消息数组长度

    +

    返回值

    +

    返回值描述

    +

    正整数

    +

    成功传输的消息结构体数目

    +

    负数

    +

    执行失败

    +
    + +I2C传输消息类型为I2cMsg,每个传输消息结构体表示一次读或写,通过一个消息数组,可以执行若干次的读写组合操作。 + +``` +int32_t ret; +uint8_t wbuff[2] = { 0x12, 0x13 }; +uint8_t rbuff[2] = { 0 }; +struct I2cMsg msgs[2]; /* 自定义传输的消息结构体数组 */ +msgs[0].buf = wbuff; /* 写入的数据 */ +msgs[0].len = 2; /* 写入数据长度为2 */ +msgs[0].addr = 0x5A; /* 写入设备地址为0x5A */ +msgs[0].flags = 0; /* 传输标记为0,默认为写 */ +msgs[1].buf = rbuff; /* 要读取的数据 */ +msgs[1].len = 2; /* 读取数据长度为2 */ +msgs[1].addr = 0x5A; /* 读取设备地址为0x5A */ +msgs[1].flags = I2C_FLAG_READ /* I2C_FLAG_READ置位 */ +/* 进行一次自定义传输,传输的消息个数为2 */ +ret = I2cTransfer(i2cHandle, msgs, 2); +if (ret != 2) { + HDF_LOGE("I2cTransfer: failed, ret %d\n", ret); + return; +} +``` + +>![](../public_sys-resources/icon-caution.gif) **注意:** +>- I2cMsg结构体中的设备地址不包含读写标志位,读写信息由flags成员变量的读写控制位传递。 +>- 本函数不对消息结构体个数count做限制,其最大个数度由具体I2C控制器决定。 +>- 本函数也不对每个消息结构体中的数据长度做限制,同样由具体I2C控制器决定。 +>- 本函数可能会引起系统休眠,不允许在中断上下文调用 + +### 关闭I2C控制器 + +I2C通信完成之后,需要关闭I2C控制器,关闭函数如下所示: + +void I2cClose\(DevHandle handle\); + +**表 4** I2cClose参数和返回值描述 + + + + + + + + + + +

    参数

    +

    参数描述

    +

    handle

    +

    I2C控制器设备句柄

    +
    + +``` +I2cClose(i2cHandle); /* 关闭I2C控制器 */ +``` + +## 使用实例 + +本例程以操作开发板上的I2C设备为例,详细展示I2C接口的完整使用流程。 + +本例拟对Hi3516DV300某开发板上TouchPad设备进行简单的寄存器读写访问,基本硬件信息如下: + +- SOC:hi3516dv300。 + +- Touch IC:I2C地址为0x38, IC内部寄存器位宽为1字节。 + +- 原理图信息:TouchPad设备挂接在3号I2C控制器下;IC的复位管脚为3号GPIO。 + +本例程首先对Touch IC进行复位操作(开发板上电默认会给TouchIC供电,本例程不考虑供电),然后对其内部寄存器进行随机读写,测试I2C通路是否正常。 + +>![](../public_sys-resources/icon-note.gif) **说明:** +>本例程重点在于展示I2C设备访问流程,并验证I2C通路,所以对于设备寄存器读写值不做关注,读写寄存器导致的行为由设备自身决定。 + +示例如下: + +``` +#include "i2c_if.h" /* I2C标准接口头文件 */ +#include "gpio_if.h" /* GPIO标准接口头文件 */ +#include "hdf_log.h" /* 标准日志打印头文件 */ +#include "osal_io.h" /* 标准IO读写接口头文件 */ +#include "osal_time.h" /* 标准延迟&睡眠接口头文件 */ + +/* 定义一个表示TP设备的结构体,存储i2c及gpio相关硬件信息 */ +struct TpI2cDevice { + uint16_t rstGpio; /* 复位管脚 */ + uint16_t busId; /* I2C总线号 */ + uint16_t addr; /* I2C设备地址 */ + uint16_t regLen; /* 寄存器字节宽度 */ + DevHandle i2cHandle; /* I2C控制器句柄 */ +}; + +/* I2C管脚io配置,需要查阅SOC寄存器手册 */ +#define I2C3_DATA_REG_ADDR 0x112f008c /* 3号I2C控制器SDA管脚配置寄存器地址 */ +#define I2C3_CLK_REG_ADDR 0x112f0090 /* 3号I2C控制器SCL管脚配置寄存器地址 */ +#define I2C_REG_CFG 0x5f1 /* 3号I2C控制器SDA及SCL管脚配置值 */ + +static void TpSocIoCfg(void) +{ + /* 将3号I2C控制器对应两个管脚的IO功能设置为I2C */ + OSAL_WRITEL(I2C_REG_CFG, IO_DEVICE_ADDR(I2C3_DATA_REG_ADDR)); + OSAL_WRITEL(I2C_REG_CFG, IO_DEVICE_ADDR(I2C3_CLK_REG_ADDR)); +} + +/* 对TP的复位管脚进行初始化, 拉高维持20ms, 再拉底维持50ms,最后再拉高维持20ms, 完成复位动作 */ +static int32_t TestCaseGpioInit(struct TpI2cDevice *tpDevice) +{ + int32_t ret; + + /* 设置复位管脚方向为输出 */ + ret = GpioSetDir(tpDevice->rstGpio, GPIO_DIR_OUT); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: set rst dir fail!:%d", __func__, ret); + return ret; + } + + ret = GpioWrite(tpDevice->rstGpio, GPIO_VAL_HIGH); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: set rst hight fail!:%d", __func__, ret); + return ret; + } + OsalMSleep(20); + + ret = GpioWrite(tpDevice->rstGpio, GPIO_VAL_LOW); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: set rst low fail!:%d", __func__, ret); + return ret; + } + OsalMSleep(50); + + ret = GpioWrite(tpDevice->rstGpio, GPIO_VAL_HIGH); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: set rst high fail!:%d", __func__, ret); + return ret; + } + OsalMSleep(20); + + return HDF_SUCCESS; +} + +/* 基于I2cTransfer方法封装一个寄存器读写的辅助函数, 通过flag表示读或写 */ +static int TpI2cReadWrite(struct TpI2cDevice *tpDevice, unsigned int regAddr, + unsigned char *regData, unsigned int dataLen, uint8_t flag) +{ + int index = 0; + unsigned char regBuf[4] = {0}; + struct I2cMsg msgs[2] = {0}; + + /* 单双字节寄存器长度适配 */ + if (tpDevice->regLen == 1) { + regBuf[index++] = regAddr & 0xFF; + } else { + regBuf[index++] = (regAddr >> 8) & 0xFF; + regBuf[index++] = regAddr & 0xFF; + } + + /* 填充I2cMsg消息结构 */ + msgs[0].addr = tpDevice->addr; + msgs[0].flags = 0; /* 标记为0,表示写入 */ + msgs[0].len = tpDevice->regLen; + msgs[0].buf = regBuf; + + msgs[1].addr = tpDevice->addr; + msgs[1].flags = (flag == 1) ? I2C_FLAG_READ : 0; /* 添加读标记位,表示读取 */ + msgs[1].len = dataLen; + msgs[1].buf = regData; + + if (I2cTransfer(tpDevice->i2cHandle, msgs, 2) != 2) { + HDF_LOGE("%s: i2c read err", __func__); + return HDF_FAILURE; + } + return HDF_SUCCESS; +} + +/* TP寄存器读函数 */ +static inline int TpI2cReadReg(struct TpI2cDevice *tpDevice, unsigned int regAddr, + unsigned char *regData, unsigned int dataLen) +{ + return TpI2cReadWrite(tpDevice, regAddr, regData, dataLen, 1); +} + +/* TP寄存器写函数 */ +static inline int TpI2cWriteReg(struct TpI2cDevice *tpDevice, unsigned int regAddr, + unsigned char *regData, unsigned int dataLen) +{ + return TpI2cReadWrite(tpDevice, regAddr, regData, dataLen, 0); +} + +/* I2C例程总入口 */ +static int32_t TestCaseI2c(void) +{ + int32_t i; + int32_t ret; + unsigned char bufWrite[7] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xA, 0xB, 0xC }; + unsigned char bufRead[7] = {0}; + static struct TpI2cDevice tpDevice; + + /* IO管脚功能配置 */ + TpSocIoCfg(); + + /* TP设备信息初始化 */ + tpDevice.rstGpio = 3; + tpDevice.busId = 3; + tpDevice.addr = 0x38; + tpDevice.regLen = 1; + tpDevice.i2cHandle = NULL; + + /* GPIO管脚初始化 */ + ret = TestCaseGpioInit(&tpDevice); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: gpio init fail!:%d", __func__, ret); + return ret; + } + + /* 打开I2C控制器 */ + tpDevice.i2cHandle = I2cOpen(tpDevice.busId); + if (tpDevice.i2cHandle == NULL) { + HDF_LOGE("%s: Open I2c:%u fail!", __func__, tpDevice.busId); + return -1; + } + + /* 向TP-IC的0xD5寄存器连续写7字节数据 */ + ret = TpI2cWriteReg(&tpDevice, 0xD5, bufWrite, 7); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: tp i2c write reg fail!:%d", __func__, ret); + I2cClose(tpDevice.i2cHandle); + return -1; + } + OsalMSleep(10); + + /* 从TP-IC的0xDO寄存器连续读7字节数据 */ + ret = TpI2cReadReg(&tpDevice, 0xD5, bufRead, 7); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: tp i2c read reg fail!:%d", __func__, ret); + I2cClose(tpDevice.i2cHandle); + return -1; + } + + HDF_LOGE("%s: tp i2c write&read reg success!", __func__); + for (i = 0; i < 7; i++) { + HDF_LOGE("%s: bufRead[%d] = 0x%x", __func__, i, bufRead[i]); + } + + /* 访问完毕关闭I2C控制器 */ + I2cClose(tpDevice.i2cHandle); + return ret; +} +``` + diff --git a/zh-cn/device-dev/driver/drive-platform-mipidsi-des.md b/zh-cn/device-dev/driver/drive-platform-mipidsi-des.md new file mode 100644 index 0000000000..c7cf01ca02 --- /dev/null +++ b/zh-cn/device-dev/driver/drive-platform-mipidsi-des.md @@ -0,0 +1,554 @@ +# MIPI DSI + +- [概述](#section16806142183217) + - [接口说明](#section129611916132011) + +- [使用指导](#section037231715335) + - [使用流程](#section49299119344) + - [获取MIPI-DSI操作句柄](#section5126155683811) + - [MIPI-DSI相应配置](#section201164274344) + - [发送/回读控制指令](#section199401342173415) + - [释放MIPI-DSI操作句柄](#section161011610357) + +- [使用实例](#section17470126123520) + +## 概述 + +- DSI(Display Serial Interface)是由移动行业处理器接口联盟(Mobile Industry Processor Interface \(MIPI\) Alliance)制定的规范,旨在降低移动设备中显示控制器的成本。它以串行的方式发送像素数据或指令给外设\(通常是LCD或者类似的显示设备\),或从外设中读取状态信息或像素信息;它定义了主机、图像数据源和目标设备之间的串行总线和通信协议。 + +- MIPI-DSI具备高速模式和低速模式两种工作模式,全部数据通道都可以用于单向的高速传输,但只有第一个数据通道才可用于低速双向传输,从属端的状态信息、像素等是通过该数据通道返回。时钟通道专用于在高速传输数据的过程中传输同步时钟信号。 +- 图1显示了简化的DSI接口。从概念上看,符合DSI的接口与基于DBI-2和DPI-2标准的接口具有相同的功能。它向外围设备传输像素或命令数据,并且可以从外围设备读取状态或像素信息。主要区别在于,DSI对所有像素数据、命令和事件进行序列化,而在传统接口中,这些像素数据、命令和事件通常需要附加控制信号才能在并行数据总线上传输。 + + **图 1** DSI发送、接收接口 + ![](figure/DSI发送-接收接口.png "DSI发送-接收接口") + + +### 接口说明 + +**表 1** MIPI-DSI API接口功能介绍 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    功能分类

    +

    接口名

    +

    描述

    +

    设置/获取当前MIPI-DSI相关配置

    +

    MipiDsiSetCfg

    +

    设置MIPI-DSI相关配置

    +

    MipiDsiGetCfg

    +

    获取当前MIPI-DSI相关配置

    +

    获取/释放MIPI-DSI操作句柄

    +

    MipiDsiOpen

    +

    获取MIPI-DSI操作句柄

    +

    MipiDsiClose

    +

    释放MIPI-DSI操作句柄

    +

    设置MIPI-DSI进入Low power模式/High speed模式

    +

    MipiDsiSetLpMode

    +

    设置MIPI-DSI进入Low power模式

    +

    MipiDsiSetHsMode

    +

    设置MIPI-DSI进入High speed模式

    +

    MIPI-DSI发送/回读指令

    +

    MipiDsiTx

    +

    MIPI-DSI发送相应指令的接口

    +

    MipiDsiRx

    +

    MIPI-DSI按期望长度回读的接口

    +
    + +>![](../public_sys-resources/icon-note.gif) **说明:** +>本文涉及的所有接口,仅限内核态使用,不支持在用户态使用 + +## 使用指导 + +### 使用流程 + +使用MIPI-DSI的一般流程如[图2](#fig99821771782)所示。 + +**图 2** MIPI-DSI使用流程图 + + +![](figure/zh-cn_image_0000001123514210.png) + +### 获取MIPI-DSI操作句柄 + +在进行MIPI-DSI进行通信前,首先要调用MipiDsiOpen获取操作句柄,该函数会返回指定通道ID的操作句柄。 + +DevHandle MipiDsiOpen\(uint8\_t id\); + +**表 2** MipiDsiOpen的参数和返回值描述 + + + + + + + + + + + + + + + + + + + +

    参数

    +

    参数描述

    +

    id

    +

    MIPI DSI通道ID

    +

    返回值

    +

    返回值描述

    +

    NULL

    +

    获取失败

    +

    设备句柄

    +

    获取到指令通道的操作句柄, 类型为DevHandle

    +
    + +假设系统中的MIPI-DSI通道为0,获取该通道操作句柄的示例如下: + +``` +DevHandle mipiDsiHandle = NULL; /* 设备句柄 */ +chnId = 0; /* MIPI-DSI通道ID */ + +/* 获取操作句柄 */ +mipiDsiHandle = MipiDsiOpen(chnId); +if (mipiDsiHandle == NULL) { + HDF_LOGE("MipiDsiOpen: failed\n"); + return; +} +``` + +### MIPI-DSI相应配置 + +- 写入MIPI-DSI配置 + +int32\_t MipiDsiSetCfg\(DevHandle handle, struct MipiCfg \*cfg\); + +**表 3** MipiDsiSetCfg的参数和返回值描述 + + + + + + + + + + + + + + + + + + + + + + +

    参数

    +

    参数描述

    +

    handle

    +

    操作句柄

    +

    cfg

    +

    MIPI-DSI相应配置buf 指针

    +

    返回值

    +

    返回值描述

    +

    0

    +

    设置成功

    +

    负数

    +

    设置失败

    +
    + +``` +int32_t ret; +struct MipiCfg cfg = {0}; + +/* 当前对接的屏幕配置如下 */ +cfg.lane = DSI_4_LANES; +cfg.mode = DSI_CMD_MODE; +cfg.burstMode = VIDEO_NON_BURST_MODE_SYNC_EVENTS; +cfg.format = FORMAT_RGB_24_BIT; +cfg.pixelClk = 174; +cfg.phyDataRate = 384; +cfg.timingInfo.hsaPixels = 50; +cfg.timingInfo.hbpPixels = 55; +cfg.timingInfo.hlinePixels = 1200; +cfg.timingInfo.yResLines = 1800; +cfg.timingInfo.vbpLines = 33; +cfg.timingInfo.vsaLines = 76; +cfg.timingInfo.vfpLines = 120; +cfg.timingInfo.xResPixels = 1342; +/* 写入配置数据 */ +ret = MipiDsiSetCfg(g_handle, &cfg); +if (ret != 0) { + HDF_LOGE("%s: SetMipiCfg fail! ret=%d\n", __func__, ret); + return -1; +} +``` + +- 获取当前MIPI-DSI的配置 + +int32\_t MipiDsiGetCfg\(DevHandle handle, struct MipiCfg \*cfg\); + +**表 4** MipiDsiGetCfg的参数和返回值描述 + + + + + + + + + + + + + + + + + + + + + + +

    参数

    +

    参数描述

    +

    handle

    +

    操作句柄

    +

    cfg

    +

    MIPI-DSI相应配置buf 指针

    +

    返回值

    +

    返回值描述

    +

    0

    +

    获取成功

    +

    负数

    +

    获取失败

    +
    + +``` +int32_t ret; +struct MipiCfg cfg; +memset(&cfg, 0, sizeof(struct MipiCfg)); +ret = MipiDsiGetCfg(g_handle, &cfg); +if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: GetMipiCfg fail!\n", __func__); + return HDF_FAILURE; +} +``` + +### 发送/回读控制指令 + +- 发送指令 + +int32\_t MipiDsiTx\(PalHandle handle, struct DsiCmdDesc \*cmd\); + +**表 5** MipiDsiTx的参数和返回值描述 + + + + + + + + + + + + + + + + + + + + + + +

    参数

    +

    参数描述

    +

    handle

    +

    操作句柄

    +

    cmd

    +

    需要发送的指令数据指针

    +

    返回值

    +

    返回值描述

    +

    0

    +

    发送成功

    +

    负数

    +

    发送失败

    +
    + +``` +int32_t ret; +struct DsiCmdDesc *cmd = OsalMemCalloc(sizeof(struct DsiCmdDesc)); +if (cmd == NULL) { + return HDF_FAILURE; +} +cmd->dtype = DTYPE_DCS_WRITE; +cmd->dlen = 1; +cmd->payload = OsalMemCalloc(sizeof(uint8_t)); +if (cmd->payload == NULL) { + HdfFree(cmd); + return HDF_FAILURE; +} +*(cmd->payload) = DTYPE_GEN_LWRITE; +MipiDsiSetLpMode(mipiHandle); +ret = MipiDsiTx(mipiHandle, cmd); +MipiDsiSetHsMode(mipiHandle); +if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: PalMipiDsiTx fail! ret=%d\n", __func__, ret); + HdfFree(cmd->payload); + HdfFree(cmd); + return HDF_FAILURE; +} +HdfFree(cmd->payload); +HdfFree(cmd); +``` + +- 回读指令 + +int32\_t MipiDsiRx\(DevHandle handle, struct DsiCmdDesc \*cmd, uint32\_t readLen, uint8\_t \*out\); + +**表 6** MipiDsiRx的参数和返回值描述 + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    参数

    +

    参数描述

    +

    handle

    +

    操作句柄

    +

    cmd

    +

    需要回读的指令数据指针

    +

    readLen

    +

    期望回读的数据长度

    +

    out

    +

    回读的数据buf指针

    +

    返回值

    +

    返回值描述

    +

    0

    +

    获取成功

    +

    负数

    +

    获取失败

    +
    + +``` +int32_t ret; +uint8_t readVal = 0; + +struct DsiCmdDesc *cmdRead = OsalMemCalloc(sizeof(struct DsiCmdDesc)); +if (cmdRead == NULL) { + return HDF_FAILURE; +} +cmdRead->dtype = DTYPE_DCS_READ; +cmdRead->dlen = 1; +cmdRead->payload = OsalMemCalloc(sizeof(uint8_t)); +if (cmdRead->payload == NULL) { + HdfFree(cmdRead); + return HDF_FAILURE; +} +*(cmdRead->payload) = DDIC_REG_STATUS; +MipiDsiSetLpMode(g_handle); +ret = MipiDsiRx(g_handle, cmdRead, sizeof(readVal), &readVal); +MipiDsiSetHsMode(g_handle); +if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: MipiDsiRx fail! ret=%d\n", __func__, ret); + HdfFree(cmdRead->payload); + HdfFree(cmdRead); + return HDF_FAILURE; +} +HdfFree(cmdRead->payload); +HdfFree(cmdRead); +``` + +### 释放MIPI-DSI操作句柄 + +MIPI-DSI使用完成之后,需要释放操作句柄,释放句柄的函数如下所示: + +void MipiDsiClose\(DevHandle handle\); + +该函数会释放掉由MipiDsiOpen申请的资源。 + +**表 7** MipiDsiClose的参数和返回值描述 + + + + + + + + + + +

    参数

    +

    参数描述

    +

    handle

    +

    MIPI-DSI操作句柄

    +
    + +``` +MipiDsiClose(mipiHandle); /* 释放掉MIPI-DSI操作句柄 */ +``` + +## 使用实例 + +MIPI-DSI完整的使用示例如下所示: + +``` +#include "hdf.h" +#include "mipi_dsi_if.h" + +void PalMipiDsiTestSample(void) +{ + uint8_t chnId; + int32_t ret; + DevHandle handle = NULL; + + /* 设备通道编号 */ + chnId = 0; + /* 获取操作句柄 */ + handle = MipiDsiOpen(chnId); + if (handle == NULL) { + HDF_LOGE("MipiDsiOpen: failed!\n"); + return; + } + /* 配置相应参数 */ + struct MipiCfg cfg = {0}; + cfg.lane = DSI_4_LANES; + cfg.mode = DSI_CMD_MODE; + cfg.burstMode = VIDEO_NON_BURST_MODE_SYNC_EVENTS; + cfg.format = FORMAT_RGB_24_BIT; + cfg.pixelClk = 174; + cfg.phyDataRate = 384; + cfg.timingInfo.hsaPixels = 50; + cfg.timingInfo.hbpPixels = 55; + cfg.timingInfo.hlinePixels = 1200; + cfg.timingInfo.yResLines = 1800; + cfg.timingInfo.vbpLines = 33; + cfg.timingInfo.vsaLines = 76; + cfg.timingInfo.vfpLines = 120; + cfg.timingInfo.xResPixels = 1342; + /* 写入配置数据 */ + ret = MipiDsiSetCfg(g_handle, &cfg); + if (ret != 0) { + HDF_LOGE("%s: SetMipiCfg fail! ret=%d\n", __func__, ret); + return; + } + /* 发送PANEL初始化指令 */ + struct DsiCmdDesc *cmd = OsalMemCalloc(sizeof(struct DsiCmdDesc)); + if (cmd == NULL) { + return; + } + cmd->dtype = DTYPE_DCS_WRITE; + cmd->dlen = 1; + cmd->payload = OsalMemCalloc(sizeof(uint8_t)); + if (cmd->payload == NULL) { + HdfFree(cmd); + return; + } + *(cmd->payload) = DTYPE_GEN_LWRITE; + MipiDsiSetLpMode(mipiHandle); + ret = MipiDsiTx(mipiHandle, cmd); + MipiDsiSetHsMode(mipiHandle); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: MipiDsiTx fail! ret=%d\n", __func__, ret); + HdfFree(cmd->payload); + HdfFree(cmd); + return; + } + HdfFree(cmd->payload); + HdfFree(cmd); + /* 回读panel状态寄存器 */ + uint8_t readVal = 0; + struct DsiCmdDesc *cmdRead = OsalMemCalloc(sizeof(struct DsiCmdDesc)); + if (cmdRead == NULL) { + return; + } + cmdRead->dtype = DTYPE_DCS_READ; + cmdRead->dlen = 1; + cmdRead->payload = OsalMemCalloc(sizeof(uint8_t)); + if (cmdRead->payload == NULL) { + HdfFree(cmdRead); + return; + } + *(cmdRead->payload) = DDIC_REG_STATUS; + MipiDsiSetLpMode(g_handle); + ret = MipiDsiRx(g_handle, cmdRead, sizeof(readVal), &readVal); + MipiDsiSetHsMode(g_handle); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: MipiDsiRx fail! ret=%d\n", __func__, ret); + HdfFree(cmdRead->payload); + HdfFree(cmdRead); + return; + } + HdfFree(cmdRead->payload); + HdfFree(cmdRead); + /* 释放MIPI DSI设备句柄 */ + MipiDsiClose(handle); +} +``` + diff --git a/zh-cn/device-dev/driver/drive-platform-rtc-des.md b/zh-cn/device-dev/driver/drive-platform-rtc-des.md new file mode 100644 index 0000000000..fb55001feb --- /dev/null +++ b/zh-cn/device-dev/driver/drive-platform-rtc-des.md @@ -0,0 +1,944 @@ +# RTC + +- [概述](#section104842041574) + - [接口说明](#section3373340142215) + +- [使用指导](#section20636145604113) + - [使用流程](#section16919828134215) + - [创建RTC设备句柄](#section1131212144310) + - [销毁RTC设备句柄](#section10744117144314) + - [注册RTC定时报警回调函数](#section14839440184320) + - [操作RTC](#section161927578433) + +- [使用实例](#section1186111020456) + +## 概述 + +RTC\(real-time clock\)为操作系统中的实时时钟设备,为操作系统提供精准的实时时间和定时报警功能。当设备下电后,通过外置电池供电,RTC继续记录操作系统时间;设备上电后,RTC提供实时时钟给操作系统,确保断电后系统时间的连续性。 + +### 接口说明 + +**表 1** RTC设备API接口功能介绍 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    功能分类

    +

    接口名

    +

    描述

    +

    RTC句柄操作

    +

    RtcOpen

    +

    获取RTC设备驱动句柄

    +

    RtcClose

    +

    释放RTC设备驱动句柄

    +

    RTC时间操作接口

    +

    RtcReadTime

    +

    读RTC时间信息,包括年、月、星期、日、时、分、秒、毫秒

    +

    RtcWriteTime

    +

    写RTC时间信息,包括年、月、星期、日、时、分、秒、毫秒

    +

    RTC报警操作接口

    +

    RtcReadAlarm

    +

    读RTC报警时间信息

    +

    RtcWriteAlarm

    +

    写RTC报警时间信息

    +

    RtcRegisterAlarmCallback

    +

    注册报警超时回调函数

    +

    RtcAlarmInterruptEnable

    +

    使能/去使能RTC报警中断

    +

    RTC配置操作

    +

    RtcGetFreq

    +

    读RTC外接晶振频率

    +

    RtcSetFreq

    +

    配置RTC外接晶振频率

    +

    RtcReset

    +

    RTC复位

    +

    读写用户定义寄存器

    +

    RtcReadReg

    +

    读用户自定义寄存器

    +

    RtcWriteReg

    +

    写用户自定义寄存器

    +
    + +>![](../public_sys-resources/icon-note.gif) **说明:** +>本文涉及的所有接口,仅限内核态使用,不支持在用户态使用。 + +## 使用指导 + +### 使用流程 + +在操作系统启动过程中,驱动管理模块根据配置文件加载RTC驱动,RTC驱动会检测RTC器件并初始化驱动。 + +使用RTC设备的一般流程如[图1](#fig166181128151112)所示。 + +**图 1** RTC设备使用流程图 + + +![](figure/zh-cn_image_0000001123675706.png) + +### 创建RTC设备句柄 + +RTC驱动加载成功后,驱动开发者使用驱动框架提供的查询接口并调用RTC设备驱动接口。 + +>![](../public_sys-resources/icon-note.gif) **说明:** +>当前操作系统支持一个RTC设备。 + +DevHandle RtcOpen\(void\); + +**表 2** RtcOpen参数和返回值描述 + + + + + + + + + + + + + + + + + + +

    参数

    +

    参数描述

    +

    void

    +

    NA

    +

    返回值

    +

    返回值描述

    +

    handle

    +

    操作成功返回 指针类型

    +

    NULL

    +

    操作失败

    +
    + +``` +DevHandle handle = NULL; + +/* 获取RTC句柄 */ +handle = RtcOpen(); +if (handle == NULL) { + /* 错误处理 */ +} +``` + +### 销毁RTC设备句柄 + +销毁RTC设备句柄,系统释放对应的资源。 + +void RtcClose\(DevHandle handle\); + +**表 3** RtcClose参数描述 + + + + + + + + + +

    参数

    +

    参数描述

    +

    handle

    +

    RTC设备句柄

    +
    + +``` +/* 销毁RTC句柄 */ +RtcClose(handle); +``` + +### 注册RTC定时报警回调函数 + +系统启动后需要注册RTC定时报警回调函数,报警超时后触发回调函数。 + +int32\_t RtcRegisterAlarmCallback\(DevHandle handle, enum RtcAlarmIndex alarmIndex, RtcAlarmCallback cb\); + +**表 4** RtcRegisterAlarmCallback参数和返回值描述 + + + + + + + + + + + + + + + + + + + + + + + + + +

    参数

    +

    参数描述

    +

    handle

    +

    RTC设备句柄

    +

    alarmIndex

    +

    报警索引

    +

    cb

    +

    定时报警回调函数

    +

    返回值

    +

    返回值描述

    +

    0

    +

    操作成功

    +

    负数

    +

    操作失败

    +
    + +注册RTC\_ALARM\_INDEX\_A的定时报警处理函数, 示例如下: + +``` +/* 用户注册RTC定时报警回调函数的方法 */ +int32_t RtcAlarmACallback(enum RtcAlarmIndex alarmIndex) +{ + if (alarmIndex == RTC_ALARM_INDEX_A) { + /* 报警A的处理 */ + } else if (alarmIndex == RTC_ALARM_INDEX_B) { + /* 报警B的处理 */ + } else { + /* 错误处理 */ + } + return 0; +} +int32_t ret; +/* 注册报警A的定时回调函数 */ +ret = RtcRegisterAlarmCallback(handle, RTC_ALARM_INDEX_A, RtcAlarmACallback); +if (ret != 0) { + /* 错误处理 */ +} +``` + +### 操作RTC + +- 读取RTC时间。 + +系统从RTC读取时间信息,包括年、月、星期、日、时、分、秒、毫秒,则可以通过以下函数完成: + +int32\_t RtcReadTime\(DevHandle handle, struct RtcTime \*time\); + +**表 5** RtcReadTime参数和返回值描述 + + + + + + + + + + + + + + + + + + + + + +

    参数

    +

    参数描述

    +

    handle

    +

    RTC设备句柄

    +

    time

    +

    RTC读取时间信息,包括年、月、星期、日、时、分、秒、毫秒

    +

    返回值

    +

    返回值描述

    +

    0

    +

    操作成功

    +

    负数

    +

    操作失败

    +
    + +``` +int32_t ret; +struct RtcTime tm; + +/* 系统从RTC读取时间信息 */ +ret = RtcReadTime(handle, &tm); +if (ret != 0) { + /* 错误处理 */ +} +``` + +- 设置RTC时间 + +设置RTC时间,则可以通过以下函数完成: + +int32\_t RtcWriteTime\(DevHandle handle, struct RtcTime \*time\); + +**表 6** RtcWriteTime参数和返回值描述 + + + + + + + + + + + + + + + + + + + + + +

    参数

    +

    参数描述

    +

    handle

    +

    RTC设备句柄

    +

    time

    +

    写RTC时间信息,包括年、月、星期、日、时、分、秒、毫秒

    +

    返回值

    +

    返回值描述

    +

    0

    +

    操作成功

    +

    负数

    +

    操作失败

    +
    + +>![](../public_sys-resources/icon-note.gif) **说明:** +>RTC起始时间为UTC 1970/01/01 Thursday 00:00:00,年的最大取值按照用户器件手册要求计算配置,星期不用配置。 + +``` +int32_t ret; +struct RtcTime tm; + +/* 设置RTC时间为 UTC 2020/01/01 00:59:00 .000 */ +tm.year = 2020; +tm.month = 01; +tm.day = 01; +tm.hour= 00; +tm.minute = 59; +tm.second = 00; +tm.millisecond = 0; +/* 写RTC时间信息 */ +ret = RtcWriteTime(handle, &tm); +if (ret != 0) { + /* 错误处理 */ +} +``` + +- 读取RTC报警时间 + +如果需要读取定时报警时间,则可以通过以下函数完成: + +int32\_t RtcReadAlarm\(DevHandle handle, enum RtcAlarmIndex alarmIndex, struct RtcTime \*time\); + +**表 7** RtcReadAlarm参数和返回值描述 + + + + + + + + + + + + + + + + + + + + + + + + +

    参数

    +

    参数描述

    +

    handle

    +

    RTC设备句柄

    +

    alarmIndex

    +

    报警索引

    +

    time

    +

    RTC报警时间信息,包括年、月、星期、日、时、分、秒、毫秒

    +

    返回值

    +

    返回值描述

    +

    0

    +

    操作成功

    +

    负数

    +

    操作失败

    +
    + +``` +int32_t ret; +struct RtcTime alarmTime; + +/* 读RTC_ALARM_INDEX_A索引的RTC定时报警时间信息 */ +ret = RtcReadAlarm(handle, RTC_ALARM_INDEX_A, &alarmTime); +if (ret != 0) { + /* 错误处理 */ +} +``` + +- 设置RTC报警时间 + +根据报警索引设置RTC报警时间,通过以下函数完成: + +int32\_t RtcWriteAlarm\(DevHandle handle, enum RtcAlarmIndex alarmIndex, struct RtcTime \*time\); + +**表 8** RtcWriteAlarm参数和返回值描述 + + + + + + + + + + + + + + + + + + + + + + + + +

    参数

    +

    参数描述

    +

    handle

    +

    RTC设备句柄

    +

    alarmIndex

    +

    报警索引

    +

    time

    +

    RTC报警时间信息,包括年、月、星期、日、时、分、秒、毫秒

    +

    返回值

    +

    返回值描述

    +

    0

    +

    操作成功

    +

    负数

    +

    操作失败

    +
    + +>![](../public_sys-resources/icon-note.gif) **说明:** +>RTC起始时间为UTC 1970/01/01 Thursday 00:00:00,年的最大取值按照用户器件手册要求计算配置,星期不用配置。 + +``` +int32_t ret; +struct RtcTime alarmTime; + +/* 设置RTC报警时间为2020/01/01 00:59:59 .000 */ +alarmTime.year = 2020; +alarmTime.month = 01; +alarmTime.day = 01; +alarmTime.hour = 00; +alarmTime.minute = 59; +alarmTime.second = 59; +alarmTime.millisecond = 0; +/* 设置RTC_ALARM_INDEX_A索引的定时报警时间 */ +ret = RtcWriteAlarm(handle, RTC_ALARM_INDEX_A, &alarmTime); +if (ret != 0) { + /* 错误处理 */ +} +``` + +- 设置定时报警中断使能或去使能 + +在启动报警操作前,需要先设置报警中断使能,报警超时后会触发告警回调函数,可以通过以下函数完成: + +int32\_t RtcAlarmInterruptEnable\(DevHandle handle, enum RtcAlarmIndex alarmIndex, uint8\_t enable\); + +**表 9** RtcAlarmInterruptEnable参数和返回值描述 + + + + + + + + + + + + + + + + + + + + + + + + +

    参数

    +

    参数描述

    +

    handle

    +

    RTC设备句柄

    +

    alarmIndex

    +

    报警索引

    +

    enable

    +

    RTC报警中断配置,1:使能,0:去使能

    +

    返回值

    +

    返回值描述

    +

    0

    +

    操作成功

    +

    负数

    +

    操作失败

    +
    + +``` +int32_t ret; + +/* 设置RTC报警中断使能 */ +ret = RtcAlarmInterruptEnable(handle, RTC_ALARM_INDEX_A, 1); +if (ret != 0) { + /* 错误处理 */ +} +``` + +- 读取RTC外频 + +读取RTC外接晶体振荡频率,可以通过以下函数完成: + +int32\_t RtcGetFreq\(DevHandle handle, uint32\_t \*freq\); + +**表 10** RtcGetFreq参数和返回值描述 + + + + + + + + + + + + + + + + + + + + + +

    参数

    +

    参数描述

    +

    handle

    +

    RTC设备句柄

    +

    freq

    +

    RTC的外接晶体振荡频率,单位(HZ)

    +

    返回值

    +

    返回值描述

    +

    0

    +

    操作成功

    +

    负数

    +

    操作失败

    +
    + +``` +int32_t ret; +uint32_t freq = 0; + +/* 读取RTC外接晶体振荡频率 */ +ret = RtcGetFreq(handle, &freq); +if (ret != 0) { + /* 错误处理 */ +} +``` + +- 配置RTC外频 + +配置RTC外接晶体振荡频率,可以通过以下函数完成: + +int32\_t RtcSetFreq\(DevHandle handle, uint32\_t freq\); + +**表 11** RtcSetFreq参数和返回值描述 + + + + + + + + + + + + + + + + + + + + + +

    参数

    +

    参数描述

    +

    handle

    +

    RTC设备句柄

    +

    freq

    +

    RTC的外接晶体振荡频率,单位(HZ)

    +

    返回值

    +

    返回值描述

    +

    0

    +

    操作成功

    +

    负数

    +

    操作失败

    +
    + +``` +int32_t ret; +uint32_t freq = 32768; /* 32768 Hz */ + +/* 设置RTC外接晶体振荡频率,注意按照器件手册要求配置RTC外频 */ +ret = RtcSetFreq(handle, freq); +if (ret != 0) { + /* 错误处理 */ +} +``` + +- 复位RTC + +复位RTC,复位RTC后各配置寄存器恢复默认值,可以通过以下函数完成: + +int32\_t RtcReset\(DevHandle handle\); + +**表 12** RtcReset参数和返回值描述 + + + + + + + + + + + + + + + + + + +

    参数

    +

    参数描述

    +

    handle

    +

    RTC设备句柄

    +

    返回值

    +

    返回值描述

    +

    0

    +

    操作成功

    +

    负数

    +

    操作失败

    +
    + +``` +int32_t ret; + +/* 复位RTC,复位RTC后各配置寄存器恢复默认值 */ +ret = RtcReset(handle); +if (ret != 0) { + /* 错误处理 */ +} +``` + +- 读取RTC自定义寄存器配置 + +按照用户定义的寄存器索引,读取对应的寄存器配置,一个索引对应一字节的配置值,通过以下函数完成: + +int32\_t RtcReadReg\(DevHandle handle, uint8\_t usrDefIndex, uint8\_t \*value\); + +**表 13** RtcReadReg参数和返回值描述 + + + + + + + + + + + + + + + + + + + + + + + + +

    参数

    +

    参数描述

    +

    handle

    +

    RTC设备句柄

    +

    usrDefIndex

    +

    用户定义的寄存器对应索引

    +

    value

    +

    寄存器值

    +

    返回值

    +

    返回值描述

    +

    0

    +

    操作成功

    +

    负数

    +

    操作失败

    +
    + +``` +int32_t ret; +uint8_t usrDefIndex = 0; /* 定义0索引对应用户定义的第一个寄存器*/ +uint8_t value = 0; + +/* 按照用户定义的寄存器索引,读取对应的寄存器配置,一个索引对应一字节的配置值 */ +ret = RtcReadReg(handle, usrDefIndex, &value); +if (ret != 0) { + /* 错误处理 */ +} +``` + +- 设置RTC自定义寄存器配置 + +按照用户定义的寄存器索引,设置对应的寄存器配置,一个索引对应一字节的配置值,通过以下函数完成: + +int32\_t RtcWriteReg\(DevHandle handle, uint8\_t usrDefIndex, uint8\_t value\); + +**表 14** RtcWriteReg参数和返回值描述 + + + + + + + + + + + + + + + + + + + + + + + + +

    参数

    +

    参数描述

    +

    handle

    +

    RTC设备句柄

    +

    usrDefIndex

    +

    用户定义的寄存器对应索引

    +

    value

    +

    寄存器值

    +

    返回值

    +

    返回值描述

    +

    0

    +

    操作成功

    +

    负数

    +

    操作失败

    +
    + +``` +int32_t ret; +uint8_t usrDefIndex = 0; /* 定义0索引对应用户定义第一个寄存器*/ +uint8_t value = 0x10; + +/* 按照用户的定义的寄存器索引,设置对应的寄存器配置,一个索引对应一字节的配置值 */ +ret = RtcWriteReg(handle, usrDefIndex, value); +if (ret != 0) { + /* 错误处理 */ +} +``` + +## 使用实例 + +本实例提供RTC接口的完整使用流程: + +1. 系统启动,驱动管理模块会识别系统当前的RTC器件; +2. 驱动管理模块完成RTC设备的初始化和设备创建; +3. 用户通过不同API,对该RTC设备进行对应的操作; +4. 关闭RTC设备,释放设备资源。 + +示例如下: + +``` +#include "rtc_if.h" +int32_t RtcAlarmACallback(enum RtcAlarmIndex alarmIndex) +{ + if (alarmIndex == RTC_ALARM_INDEX_A) { + /* 报警A的处理 */ + printf("RTC Alarm A callback function\n\r"); + } else if (alarmIndex == RTC_ALARM_INDEX_B) { + /* 报警B的处理 */ + printf("RTC Alarm B callback function\n\r"); + } else { + /* 错误处理 */ + } + return 0; +} + +void RtcTestSample(void) +{ + int32_t ret; + struct RtcTime tm; + struct RtcTime alarmTime; + uint32_t freq; + DevHandle handle = NULL; + + /* 获取RTC设备句柄 */ + handle = RtcOpen(); + if (handle == NULL) { + /* 错误处理 */ + } + /* 注册报警A的定时回调函数 */ + ret = RtcRegisterAlarmCallback(handle, RTC_ALARM_INDEX_A, RtcAlarmACallback); + if (ret != 0) { + /* 错误处理 */ + } + /* 设置RTC外接晶体振荡频率,注意按照器件手册要求配置RTC外频 */ + freq = 32768; /* 32768 Hz */ + ret = RtcSetFreq(handle, freq); + if (ret != 0) { + /* 错误处理 */ + } + /* 设置RTC报警中断使能 */ + ret = RtcAlarmInterruptEnable(handle, RTC_ALARM_INDEX_A, 1); + if (ret != 0) { + /* 错误处理 */ + } + /* 设置RTC时间为2020/01/01 00:00:10 .990 */ + tm.year = 2020; + tm.month = 01; + tm.day = 01; + tm.hour= 0; + tm.minute = 0; + tm.second = 10; + tm.millisecond = 990; + /* 写RTC时间信息 */ + ret = RtcWriteTime(handle, &tm); + if (ret != 0) { + /* 错误处理 */ + } + /* 设置RTC报警时间为2020/01/01 00:00:30 .100 */ + alarmTime.year = 2020; + alarmTime.month = 01; + alarmTime.day = 01; + alarmTime.hour = 0; + alarmTime.minute = 0; + alarmTime.second = 30; + alarmTime.millisecond = 100; + /* 设置RTC_ALARM_INDEX_A索引定时报警时间信息, 定时时间到后会打印"RTC Alarm A callback function" */ + ret = RtcWriteAlarm(handle, RTC_ALARM_INDEX_A, &alarmTime); + if (ret != 0) { + /* 错误处理 */ + } + + /* 读取RTC实时时间 */ + ret = RtcReadTime(handle, &tm); + if (ret != 0) { + /* 错误处理 */ + } + sleep(5) + printf("RTC read time:\n\r"); + printf("year-month-date-weekday hour:minute:second .millisecond %04u-%02u-%02u-%u %02u:%02u:%02u .%03u", + tm.year, tm.month, tm.day, tm.weekday, tm.hour, tm.minute, tm.second, tm.millisecond); + /* 销毁RTC设备句柄 */ + RtcClose(handle); +} +``` + diff --git a/zh-cn/device-dev/driver/drive-platform-sdio-des.md b/zh-cn/device-dev/driver/drive-platform-sdio-des.md new file mode 100644 index 0000000000..1d85e6496e --- /dev/null +++ b/zh-cn/device-dev/driver/drive-platform-sdio-des.md @@ -0,0 +1,1068 @@ +# SDIO + +- [概述](#section1155271783811) + - [接口说明](#section08064247248) + +- [使用指导](#section1878939192515) + - [使用流程](#section1490685512255) + - [打开SDIO控制器](#section10782428132616) + - [独占HOST](#section11263172312715) + - [使能SDIO设备](#section17861486271) + - [注册SDIO中断](#section521213262286) + - [进行SDIO通信](#section85661522153420) + - [释放SDIO中断](#section1683449352) + - [去使能SDIO设备](#section15379324143611) + - [释放HOST](#section536018263713) + - [关闭SDIO控制器](#section4752739183716) + +- [使用实例](#section376910122382) + +## 概述 + +- SDIO是安全数字输入输出接口(Secure Digital Input and Output)的缩写,是从SD内存卡接口的基础上演化出来的一种外设接口。SDIO接口兼容以前的SD内存卡,并且可以连接支持SDIO接口的设备。 +- SDIO的应用比较广泛,目前,有许多手机都支持SDIO功能,并且很多SDIO外设也被开发出来,使得手机外接外设更加容易。常见的SDIO外设有WLAN、GPS、CAMERA、蓝牙等。 +- SDIO总线有两端,其中一端是主机端(HOST),另一端是设备端(DEVICE)。所有的通信都是由HOST端发出命令开始的,在DEVICE端只要能解析HOST的命令,就可以同HOST进行通信了。SDIO的HOST可以连接多个DEVICE,如下图所示: + + - CLK信号:HOST给DEVICE的时钟信号。 + - VDD信号:电源信号。 + - VSS信号:Ground信号。 + - D0-3信号:4条数据线,其中,DAT1信号线复用为中断线,在1BIT模式下DAT0用来传输数据,在4BIT模式下DAT0-DAT3用来传输数据。 + - CMD信号:用于HOST发送命令和DEVICE回复响应。 + + **图 1** SDIO的HOST-DEVICE连接示意图 + + + ![](figure/zh-cn_image_0000001054280608.png) + +- SDIO接口定义了操作SDIO的通用方法集合,包括打开/关闭SDIO控制器、独占/释放HOST、使能/去使能设备、申请/释放中断、读写、获取/设置公共信息等。 + +### 接口说明 + +**表 1** SDIO驱动API接口功能介绍 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    功能分类

    +

    接口名

    +

    描述

    +

    SDIO设备打开/关闭接口

    +

    SdioOpen

    +

    打开指定总线号的SDIO控制器

    +

    SdioClose

    +

    关闭SDIO控制器

    +

    SDIO读写接口

    +

    SdioReadBytes

    +

    从指定地址开始,增量读取指定长度的数据

    +

    SdioWriteBytes

    +

    从指定地址开始,增量写入指定长度的数据

    +

    SdioReadBytesFromFixedAddr

    +

    从固定地址读取指定长度的数据

    +

    SdioWriteBytesToFixedAddr

    +

    向固定地址写入指定长度的数据

    +

    SdioReadBytesFromFunc0

    +

    从SDIO function 0的指定地址空间读取指定长度的数据

    +

    SdioWriteBytesToFunc0

    +

    向SDIO function 0的指定地址空间写入指定长度的数据

    +

    SDIO设置块大小接口

    +

    SdioSetBlockSize

    +

    设置块的大小

    +

    SDIO获取/设置公共信息接口

    +

    SdioGetCommonInfo

    +

    获取公共信息

    +

    SdioSetCommonInfo

    +

    设置公共信息

    +

    SDIO刷新数据接口

    +

    SdioFlushData

    +

    刷新数据

    +

    SDIO独占/释放HOST接口

    +

    SdioClaimHost

    +

    独占Host

    +

    SdioReleaseHost

    +

    释放Host

    +

    SDIO使能/去使能功能设备接口

    +

    SdioEnableFunc

    +

    使能SDIO功能设备

    +

    SdioDisableFunc

    +

    去使能SDIO功能设备

    +

    SDIO申请/释放中断接口

    +

    SdioClaimIrq

    +

    申请中断

    +

    SdioReleaseIrq

    +

    释放中断

    +
    + +>![](../public_sys-resources/icon-note.gif) **说明:** +>本文涉及的所有接口,目前只支持在内核态使用,不支持在用户态使用。 + +## 使用指导 + +### 使用流程 + +使用SDIO的一般流程如[图2](#fig1343742311264)所示。 + +**图 2** SDIO使用流程图 + + +![](figure/zh-cn_image_0000001123540984.png) + +### 打开SDIO控制器 + +在使用SDIO进行通信前,首先要调用SdioOpen获取SDIO控制器的设备句柄,该函数会返回指定总线号的SDIO控制器的设备句柄。 + +DevHandle SdioOpen\(int16\_t mmcBusNum, struct SdioFunctionConfig \*config\); + +**表 2** SdioOpen函数的参数和返回值描述 + + + + + + + + + + + + + + + + + + + + + + +

    参数

    +

    参数描述

    +

    mmcBusNum

    +

    总线号

    +

    config

    +

    SDIO功能配置信息

    +

    返回值

    +

    返回值描述

    +

    NULL

    +

    获取SDIO控制器的设备句柄失败

    +

    设备句柄

    +

    SDIO控制器的设备句柄

    +
    + +打开SDIO控制器的示例如下: + +``` +DevHandle handle = NULL; +struct SdioFunctionConfig config; +config.funcNr = 1; +config.vendorId = 0x123; +config.deviceId = 0x456; +/* 打开总线号为1的SDIO控制器 */ +handle = SdioOpen(1, &config); +if (handle == NULL) { + HDF_LOGE("SdioOpen: failed!\n"); +} +``` + +### 独占HOST + +获取到SDIO控制器的设备句柄之后,需要先独占HOST才能进行SDIO后续的一系列操作,独占HOST函数如下所示: + +void SdioClaimHost\(DevHandle handle\); + +**表 3** SdioClaimHost函数的参数描述 + + + + + + + + + + +

    参数

    +

    参数描述

    +

    handle

    +

    SDIO控制器的设备句柄

    +
    + +独占HOST示例如下: + +``` +SdioClaimHost(handle); /* 独占HOST */ +``` + +### 使能SDIO设备 + +在访问寄存器之前,需要先使能SDIO设备,使能SDIO设备的函数如下所示: + +int32\_t SdioEnableFunc\(DevHandle handle\); + +**表 4** SdioEnableFunc函数的参数和返回值描述 + + + + + + + + + + + + + + + + + + + +

    参数

    +

    参数描述

    +

    handle

    +

    SDIO控制器的设备句柄

    +

    返回值

    +

    返回值描述

    +

    0

    +

    SDIO使能成功

    +

    负数

    +

    SDIO使能失败

    +
    + +使能SDIO设备的示例如下: + +``` +int32_t ret; +/* 使能SDIO设备 */ +ret = SdioEnableFunc(handle); +if (ret != 0) { + HDF_LOGE("SdioEnableFunc: failed, ret %d\n", ret); +} +``` + +### 注册SDIO中断 + +在通信之前,还需要注册SDIO中断,注册SDIO中断函数如下图所示: + +int32\_t SdioClaimIrq\(DevHandle handle, SdioIrqHandler \*handler\); + +**表 5** SdioClaimIrq函数的参数和返回值描述 + + + + + + + + + + + + + + + + + + + + + + +

    参数

    +

    参数描述

    +

    handle

    +

    SDIO控制器的设备句柄

    +

    handler

    +

    中断服务函数指针

    +

    返回值

    +

    返回值描述

    +

    0

    +

    注册中断成功

    +

    负数

    +

    注册中断失败

    +
    + +注册SDIO中的示例如下: + +``` +/* 中断服务函数需要根据各自平台的情况去实现 */ +static void SdioIrqFunc(void *data) +{ + if (data == NULL) { + HDF_LOGE("SdioIrqFunc: data is NULL.\n"); + return; + } + /* 需要开发者自行添加具体实现 */ +} + +int32_t ret; +/* 注册SDIO中断 */ +ret = SdioClaimIrq(handle, SdioIrqFunc); +if (ret != 0) { + HDF_LOGE("SdioClaimIrq: failed, ret %d\n", ret); +} +``` + +### 进行SDIO通信 + +- 向SDIO设备增量写入指定长度的数据 + +对应的接口函数如下所示: + +int32\_t SdioWriteBytes\(DevHandle handle, uint8\_t \*data, uint32\_t addr, uint32\_t size\); + +**表 6** SdioWriteBytes函数的参数和返回值描述 + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    参数

    +

    参数描述

    +

    handle

    +

    SDIO控制器的设备句柄

    +

    data

    +

    待写入数据的指针

    +

    addr

    +

    待写入数据的起始地址

    +

    size

    +

    待写入数据的长度

    +

    返回值

    +

    返回值描述

    +

    0

    +

    SDIO写数据成功

    +

    负数

    +

    SDIO写数据失败

    +
    + +向SDIO设备增量写入指定长度的数据的示例如下: + +``` +int32_t ret; +uint8_t wbuff[] = {1,2,3,4,5}; +uint32_t addr = 0x100 + 0x09; +/* 向SDIO设备起始地址0x109,增量写入5个字节的数据 */ +ret = SdioWriteBytes(handle, wbuff, addr, sizeof(wbuff) / sizeof(wbuff[0])); +if (ret != 0) { + HDF_LOGE("SdioWriteBytes: failed, ret %d\n", ret); +} +``` + +- 从SDIO设备增量读取指定长度的数据 + +对应的接口函数如下所示: + +int32\_t SdioReadBytes\(DevHandle handle, uint8\_t \*data, uint32\_t addr, uint32\_t size\); + +**表 7** SdioReadBytes函数的参数和返回值描述 + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    参数

    +

    参数描述

    +

    handle

    +

    SDIO控制器的设备句柄

    +

    data

    +

    接收读取数据的指针

    +

    addr

    +

    待读取数据的起始地址

    +

    size

    +

    待读取数据的长度

    +

    返回值

    +

    返回值描述

    +

    0

    +

    SDIO读数据成功

    +

    负数

    +

    SDIO读数据失败

    +
    + +从SDIO设备增量读取指定长度的数据的示例如下: + +``` +int32_t ret; +uint8_t rbuff[5] = {0}; +uint32_t addr = 0x100 + 0x09; +/* 从SDIO设备起始地址0x109,增量读取5个字节的数据 */ +ret = SdioReadBytes(handle, rbuff, addr, 5); +if (ret != 0) { + HDF_LOGE("SdioReadBytes: failed, ret %d\n", ret); +} +``` + +- 向SDIO设备的固定地址写入指定长度的数据 + + 对应的接口函数如下所示: + + int32\_t SdioWriteBytesToFixedAddr\(DevHandle handle, uint8\_t \*data, uint32\_t addr, uint32\_t size, uint32\_t scatterLen\); + + **表 8** SdioWriteBytesToFixedAddr函数的参数和返回值描述 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    参数

    +

    参数描述

    +

    handle

    +

    SDIO控制器的设备句柄

    +

    data

    +

    待写入数据的指针

    +

    addr

    +

    待写入数据的固定地址

    +

    size

    +

    待写入数据的长度

    +

    scatterLen

    +

    集散表的长度。如果该字段不为0,则data为集散表类型。

    +

    返回值

    +

    返回值描述

    +

    0

    +

    SDIO写数据成功

    +

    负数

    +

    SDIO写数据失败

    +
    + + 向SDIO设备的固定地址写入指定长度的数据的示例如下: + + ``` + int32_t ret; + uint8_t wbuff[] = {1,2,3,4,5}; + uint32_t addr = 0x100 + 0x09; + /* 向SDIO设备固定地址0x109写入5个字节的数据 */ + ret = SdioWriteBytesToFixedAddr(handle, wbuff, addr, sizeof(wbuff) / sizeof(wbuff[0]), 0); + if (ret != 0) { + HDF_LOGE("SdioWriteBytesToFixedAddr: failed, ret %d\n", ret); + } + ``` + +- 从SDIO设备的固定地址读取指定长度的数据 + + 对应的接口函数如下所示: + + int32\_t SdioReadBytesFromFixedAddr\(DevHandle handle, uint8\_t \*data, uint32\_t addr, uint32\_t size, uint32\_t scatterLen\); + + **表 9** SdioReadBytesFromFixedAddr函数的参数和返回值描述 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    参数

    +

    参数描述

    +

    handle

    +

    SDIO控制器的设备句柄

    +

    data

    +

    接收读取数据的指针

    +

    addr

    +

    待读取数据的起始地址

    +

    size

    +

    待读取数据的长度

    +

    scatterLen

    +

    集散表的长度。如果该字段不为0,则data为集散表类型。

    +

    返回值

    +

    返回值描述

    +

    0

    +

    SDIO读数据成功

    +

    负数

    +

    SDIO读数据失败

    +
    + + 从SDIO设备的固定地址读取指定长度的数据的示例如下: + + ``` + int32_t ret; + uint8_t rbuff[5] = {0}; + uint32_t addr = 0x100 + 0x09; + /* 从SDIO设备固定地址0x109中读取5个字节的数据 */ + ret = SdioReadBytesFromFixedAddr(handle, rbuff, addr, 5, 0); + if (ret != 0) { + HDF_LOGE("SdioReadBytesFromFixedAddr: failed, ret %d\n", ret); + } + ``` + + +- 向SDIO function 0的指定地址空间写入指定长度的数据 + +当前只支持写入一个字节的数据,对应的接口函数如下所示: + +int32\_t SdioWriteBytesToFunc0\(DevHandle handle, uint8\_t \*data, uint32\_t addr, uint32\_t size\); + +**表 10** SdioWriteBytesToFunc0函数的参数和返回值描述 + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    参数

    +

    参数描述

    +

    handle

    +

    SDIO控制器的设备句柄

    +

    data

    +

    待写入数据的指针

    +

    addr

    +

    待写入数据的起始地址

    +

    size

    +

    待写入数据的长度

    +

    返回值

    +

    返回值描述

    +

    0

    +

    SDIO写数据成功

    +

    负数

    +

    SDIO写数据失败

    +
    + +向SDIO function 0的指定地址空间写入指定长度的数据的示例如下: + +``` +int32_t ret; +uint8_t wbuff = 1; +/* 向SDIO function 0地址0x2中写入1字节的数据 */ +ret = SdioWriteBytesToFunc0(handle, &wbuff, 0x2, 1); +if (ret != 0) { + HDF_LOGE("SdioWriteBytesToFunc0: failed, ret %d\n", ret); +} +``` + +- 从SDIO function 0的指定地址空间读取指定长度的数据 + +当前只支持读取一个字节的数据,对应的接口函数如下所示: + +int32\_t SdioReadBytesFromFunc0\(DevHandle handle, uint8\_t \*data, uint32\_t addr, uint32\_t size\); + +**表 11** SdioReadBytesFromFunc0函数的参数和返回值描述 + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    参数

    +

    参数描述

    +

    handle

    +

    SDIO控制器的设备句柄

    +

    data

    +

    接收读取数据的指针

    +

    addr

    +

    待读取数据的起始地址

    +

    size

    +

    待读取数据的长度

    +

    返回值

    +

    返回值描述

    +

    0

    +

    SDIO读数据成功

    +

    负数

    +

    SDIO读数据失败

    +
    + +从SDIO function 0的指定地址空间读取指定长度的数据的示例如下: + +``` +int32_t ret; +uint8_t rbuff; +/* 从SDIO function 0设备地址0x2中读取1字节的数据 */ +ret = SdioReadBytesFromFunc0(handle, &rbuff, 0x2, 1); +if (ret != 0) { + HDF_LOGE("SdioReadBytesFromFunc0: failed, ret %d\n", ret); +} +``` + +### 释放SDIO中断 + +通信完成之后,需要释放SDIO中断,函数如下所示: + +int32\_t SdioReleaseIrq\(DevHandle handle\); + +**表 12** SdioReleaseIrq函数的参数和返回值描述 + + + + + + + + + + + + + + + + + + + +

    参数

    +

    参数描述

    +

    handle

    +

    SDIO控制器的设备句柄

    +

    返回值

    +

    返回值描述

    +

    0

    +

    释放SDIO中断成功

    +

    负数

    +

    释放SDIO中断失败

    +
    + +释放SDIO中断的示例如下: + +``` +int32_t ret; +/* 释放SDIO中断 */ +ret = SdioReleaseIrq(handle); +if (ret != 0) { + HDF_LOGE("SdioReleaseIrq: failed, ret %d\n", ret); +} +``` + +### 去使能SDIO设备 + +通信完成之后,还需要去使能SDIO设备,函数如下所示: + +int32\_t SdioDisableFunc\(DevHandle handle\); + +**表 13** SdioDisableFunc函数的参数和返回值描述 + + + + + + + + + + + + + + + + + + + +

    参数

    +

    参数描述

    +

    handle

    +

    SDIO控制器的设备句柄

    +

    返回值

    +

    返回值描述

    +

    0

    +

    去使能SDIO设备成功

    +

    负数

    +

    去使能SDIO设备失败

    +
    + +去使能SDIO设备的示例如下: + +``` +int32_t ret; +/* 去使能SDIO设备 */ +ret = SdioDisableFunc(handle); +if (ret != 0) { + HDF_LOGE("SdioDisableFunc: failed, ret %d\n", ret); +} +``` + +### 释放HOST + +通信完成之后,还需要释放去HOST,函数如下所示: + +void SdioReleaseHost\(DevHandle handle\); + +**表 14** SdioReleaseHost函数的参数描述 + + + + + + + + + + +

    参数

    +

    参数描述

    +

    handle

    +

    SDIO控制器的设备句柄

    +
    + +释放HOST的示例如下: + +``` +SdioReleaseHost(handle); /* 释放HOST */ +``` + +### 关闭SDIO控制器 + +SDIO通信完成之后,最后需要关闭SDIO控制器,函数如下所示: + +void SdioClose\(DevHandle handle\); + +该函数会释放掉申请的资源。 + +**表 15** SdioClose函数的参数描述 + + + + + + + + + + +

    参数

    +

    参数描述

    +

    handle

    +

    SDIO控制器的设备句柄

    +
    + +关闭SDIO控制器的示例如下: + +``` +SdioClose(handle); /* 关闭SDIO控制器 */ +``` + +## 使用实例 + +SDIO设备完整的使用示例如下所示,首先打开总线号为1的SDIO控制器,然后独占HOST、使能设备、注册中断,接着进行SDIO通信(读写等),通信完成之后,释放中断、去使能设备、释放HOST,最后关闭SDIO控制器。 + +``` +#include "hdf_log.h" +#include "sdio_if.h" + +#define TEST_FUNC_NUM 1 /* 本测试用例中,使用编号为1的I/O function */ +#define TEST_FBR_BASE_ADDR 0x100 /* 编号为1的I/O function的FBR基地址 */ +#define TEST_ADDR_OFFSET 9 /* 本测试用例中,需要读写的寄存器的地址偏移 */ +#define TEST_DATA_LEN 3 /* 本测试用例中,读写数据的长度 */ +#define TEST_BLOCKSIZE 2 /* 本测试用例中,数据块的大小,单位字节 */ + +/* 中断服务函数,需要根据各自平台的情况去实现 */ +static void SdioIrqFunc(void *data) +{ + if (data == NULL) { + HDF_LOGE("SdioIrqFunc: data is NULL.\n"); + return; + } + /* 需要开发者自行添加具体的实现 */ +} + +void SdioTestSample(void) +{ + int32_t ret; + DevHandle handle = NULL; + uint8_t data[TEST_DATA_LEN] = {0}; + struct SdioFunctionConfig config = {1, 0x123, 0x456}; + uint8_t val; + uint32_t addr; + + /* 打开总线号为1的SDIO设备 */ + handle = SdioOpen(1, &config); + if (handle == NULL) { + HDF_LOGE("SdioOpen: failed!\n"); + return; + } + /* 独占HOST */ + SdioClaimHost(handle); + /* 使能SDIO设备 */ + ret = SdioEnableFunc(handle); + if (ret != 0) { + HDF_LOGE("SdioEnableFunc: failed, ret %d\n", ret); + goto ENABLE_ERR; + } + /* 注册中断 */ + ret = SdioClaimIrq(handle, SdioIrqFunc); + if (ret != 0) { + HDF_LOGE("SdioClaimIrq: failed, ret %d\n", ret); + goto CLAIM_IRQ_ERR; + } + /* 设置块大小为2字节 */ + ret = SdioSetBlockSize(handle, TEST_BLOCKSIZE); + if (ret != 0) { + HDF_LOGE("SdioSetBlockSize: failed, ret %d\n", ret); + goto COMM_ERR; + } + /* 从SDIO设备增量地址读取3字节的数据 */ + addr = TEST_FBR_BASE_ADDR * TEST_FUNC_NUM + TEST_ADDR_OFFSET; + ret = SdioReadBytes(handle, data, addr, TEST_DATA_LEN); + if (ret != 0) { + HDF_LOGE("SdioReadBytes: failed, ret %d\n", ret); + goto COMM_ERR; + } + /* 向SDIO设备增量地址写入3字节的数据 */ + ret = SdioWriteBytes(handle, data, addr, TEST_DATA_LEN); + if (ret != 0) { + HDF_LOGE("SdioWriteBytes: failed, ret %d\n", ret); + goto COMM_ERR; + } + /* 从SDIO设备读取1字节的数据 */ + ret = SdioReadBytes(handle, &val, addr, 1); + if (ret != 0) { + HDF_LOGE("SdioReadBytes: failed, ret %d\n", ret); + goto COMM_ERR; + } + /* 向SDIO设备写入1字节的数据 */ + ret = SdioWriteBytes(handle, &val, addr, 1); + if (ret != 0) { + HDF_LOGE("SdioWriteBytes: failed, ret %d\n", ret); + goto COMM_ERR; + } + /* 从SDIO设备固定地址读取3字节的数据 */ + ret = SdioReadBytesFromFixedAddr(handle, data, addr, TEST_DATA_LEN, 0); + if (ret != 0) { + HDF_LOGE("SdioReadBytesFromFixedAddr: failed, ret %d\n", ret); + goto COMM_ERR; + } + /* 向SDIO设备固定地址写入1字节的数据 */ + ret = SdioWriteBytesToFixedAddr(handle, data, addr, 1, 0); + if (ret != 0) { + HDF_LOGE("SdioWriteBytesToFixedAddr: failed, ret %d\n", ret); + goto COMM_ERR; + } + /* 从SDIO function 0读取1字节的数据 */ + addr = 0x02; + ret = SdioReadBytesFromFunc0(handle, &val, addr, 1); + if (ret != 0) { + HDF_LOGE("SdioReadBytesFromFunc0: failed, ret %d\n", ret); + goto COMM_ERR; + } + /* 向SDIO function 0写入1字节的数据 */ + ret = SdioWriteBytesToFunc0(handle, &val, addr, 1); + if (ret != 0) { + HDF_LOGE("SdioWriteBytesToFunc0: failed, ret %d\n", ret); + goto COMM_ERR; + } +COMM_ERR: + /* 释放中断 */ + ret = SdioReleaseIrq(handle); + if (ret != 0) { + HDF_LOGE("SdioReleaseIrq: failed, ret %d\n", ret); + } +CLAIM_IRQ_ERR: + /* 去使能SDIO设备 */ + ret = SdioDisableFunc(handle); + if (ret != 0) { + HDF_LOGE("SdioDisableFunc: failed, ret %d\n", ret); + } +ENABLE_ERR: + /* 释放HOST */ + SdioReleaseHost(handle); + /* 关闭SDIO设备 */ + SdioClose(handle); +} +``` + diff --git a/zh-cn/device-dev/driver/drive-platform-spi-des.md b/zh-cn/device-dev/driver/drive-platform-spi-des.md new file mode 100644 index 0000000000..47581f9a40 --- /dev/null +++ b/zh-cn/device-dev/driver/drive-platform-spi-des.md @@ -0,0 +1,566 @@ +# SPI + +- [概述](#section193356154511) + - [接口说明](#section232141411476) + +- [使用指导](#section71363452477) + - [使用流程](#section32846814820) + - [获取SPI设备句柄](#section1927265711481) + - [获取SPI设备属性](#section541133418493) + - [配置SPI设备属性](#section7870106145010) + - [进行SPI通信](#section13324155195013) + - [销毁SPI设备句柄](#section19661632135117) + +- [使用实例](#section06541058155120) + +## 概述 + +- SPI是串行外设接口(Serial Peripheral Interface)的缩写,是一种高速的,全双工,同步的通信总线。 +- SPI是由Motorola公司开发,用于在主设备和从设备之间进行通信,常用于与闪存、实时时钟、传感器以及模数转换器等进行通信。 +- SPI以主从方式工作,通常有一个主设备和一个或者多个从设备。主设备和从设备之间一般用4根线相连,它们分别是: + - SCLK – 时钟信号,由主设备产生; + - MOSI – 主设备数据输出,从设备数据输入; + - MISO – 主设备数据输入,从设备数据输出; + - CS – 片选,从设备使能信号,由主设备控制。 + + +- 一个主设备和两个从设备的连接示意图如[图1](#fig15227181812587)所示,Device A和Device B共享主设备的SCLK、MISO和MOSI三根引脚,Device A的片选CS0连接主设备的CS0,Device B的片选CS1连接主设备的CS1。 + +**图 1** SPI主从设备连接示意图。 + + +![](figure/zh-cn_image_0000001123742254.png) + +- SPI通信通常由主设备发起,通过以下步骤完成一次通信: + +1. 通过CS选中要通信的从设备,在任意时刻,一个主设备上最多只能有一个从设备被选中。 +2. 通过SCLK给选中的从设备提供时钟信号。 +3. 基于SCLK时钟信号,主设备数据通过MOSI发送给从设备,同时通过MISO接收从设备发送的数据,完成通信。 + +- 根据SCLK时钟信号的CPOL(Clock Polarity,时钟极性)和CPHA(Clock Phase,时钟相位)的不同组合,SPI有以下四种工作模式: + - CPOL=0,CPHA=0 时钟信号idle状态为低电平,第一个时钟边沿采样数据。 + - CPOL=0,CPHA=1 时钟信号idle状态为低电平,第二个时钟边沿采样数据。 + - CPOL=1,CPHA=0 时钟信号idle状态为高电平,第一个时钟边沿采样数据。 + - CPOL=1,CPHA=1 时钟信号idle状态为高电平,第二个时钟边沿采样数据。 + + +- SPI接口定义了操作SPI设备的通用方法集合,包括: + - SPI设备句柄获取和释放。 + - SPI读写: 从SPI设备读取或写入指定长度数据。 + - SPI自定义传输:通过消息传输结构体执行任意读写组合过程。 + - SPI设备配置:获取和设置SPI设备属性。 + + +>![](../public_sys-resources/icon-note.gif) **说明:** +>当前只支持主机模式,不支持从机模式。 + +### 接口说明 + +**表 1** SPI驱动API接口功能介绍 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    功能分类

    +

    接口名

    +

    描述

    +

    SPI设备句柄获取释放接口

    +

    SpiOpen

    +

    获取SPI设备句柄

    +

    SpiClose

    +

    释放SPI设备句柄

    +

    SPI读写接口

    +

    SpiRead

    +

    读取指定长度的数据

    +

    SpiWrite

    +

    写入指定长度的数据

    +

    SpiTransfer

    +

    SPI数据传输接口

    +

    SPI设备配置接口

    +

    +

    SpiSetCfg

    +

    根据指定参数,配置SPI设备

    +

    SpiGetCfg

    +

    获取SPI设备配置参数

    +
    + +>![](../public_sys-resources/icon-note.gif) **说明:** +>本文涉及的所有接口,仅限内核态使用,不支持在用户态使用。 + +## 使用指导 + +### 使用流程 + +使用SPI的一般流程如[图2](#fig23885455594)所示。 + +**图 2** SPI使用流程图 + + +![](figure/zh-cn_image_0000001123703482.png) + +### 获取SPI设备句柄 + +在使用SPI进行通信时,首先要调用SpiOpen获取SPI设备句柄,该函数会返回指定总线号和片选号的SPI设备句柄。 + +DevHandle SpiOpen\(const struct SpiDevInfo \*info\); + +**表 2** SpiOpen参数和返回值描述 + + + + + + + + + + + + + + + + + + +

    参数

    +

    参数描述

    +

    info

    +

    SPI设备描述符

    +

    返回值

    +

    返回值描述

    +

    NULL

    +

    获取SPI设备句柄失败

    +

    设备句柄

    +

    对应的SPI设备句柄

    +
    + +假设系统中的SPI设备总线号为0,片选号为0,获取该SPI设备句柄的示例如下: + +``` +struct SpiDevInfo spiDevinfo; /* SPI设备描述符 */ +DevHandle spiHandle = NULL; /* SPI设备句柄 */ +spiDevinfo.busNum = 0; /* SPI设备总线号 */ +spiDevinfo.csNum = 0; /* SPI设备片选号 */ + +/* 获取SPI设备句柄 */ +spiHandle = SpiOpen(&spiDevinfo); +if (spiHandle == NULL) { + HDF_LOGE("SpiOpen: failed\n"); + return; +} +``` + +### 获取SPI设备属性 + +在获取到SPI设备句柄之后,需要配置SPI设备属性。配置SPI设备属性之前,可以先获取SPI设备属性,获取SPI设备属性的函数如下所示: + +int32\_t SpiGetCfg\(DevHandle handle, struct SpiCfg \*cfg\); + +**表 3** SpiGetCfg参数和返回值描述 + + + + + + + + + + + + + + + + + + + + + +

    参数

    +

    参数描述

    +

    handle

    +

    SPI设备句柄

    +

    cfg

    +

    SPI设备配置参数

    +

    返回值

    +

    返回值描述

    +

    0

    +

    获取配置成功

    +

    负数

    +

    获取配置失败

    +
    + +``` +int32_t ret; +struct SpiCfg cfg = {0}; /* SPI配置信息*/ +ret = SpiGetCfg(spiHandle, &cfg); /* 配置SPI设备属性 */ +if (ret != 0) { + HDF_LOGE("SpiGetCfg: failed, ret %d\n", ret); +} +``` + +### 配置SPI设备属性 + +在获取到SPI设备句柄之后,需要配置SPI设备属性,配置SPI设备属性的函数如下所示: + +int32\_t SpiSetCfg\(DevHandle handle, struct SpiCfg \*cfg\); + +**表 4** SpiSetCfg参数和返回值描述 + + + + + + + + + + + + + + + + + + + + + +

    参数

    +

    参数描述

    +

    handle

    +

    SPI设备句柄

    +

    cfg

    +

    SPI设备配置参数

    +

    返回值

    +

    返回值描述

    +

    0

    +

    配置成功

    +

    负数

    +

    配置失败

    +
    + +``` +int32_t ret; +struct SpiCfg cfg = {0}; /* SPI配置信息*/ +cfg.mode = SPI_MODE_LOOP; /* 以回环模式进行通信 */ +cfg.transferMode = PAL_SPI_POLLING_TRANSFER; /* 以轮询的方式进行通信 */ +cfg.maxSpeedHz = 115200; /* 最大传输频率 */ +cfg.bitsPerWord = 8; /* 读写位宽为8个比特 */ +ret = SpiSetCfg(spiHandle, &cfg); /* 配置SPI设备属性 */ +if (ret != 0) { + HDF_LOGE("SpiSetCfg: failed, ret %d\n", ret); +} +``` + +### 进行SPI通信 + +- 向SPI设备写入指定长度的数据 + +如果只向SPI设备写一次数据,则可以通过以下函数完成: + +int32\_t SpiWrite\(DevHandle handle, uint8\_t \*buf, uint32\_t len\); + +**表 5** SpiWrite参数和返回值描述 + + + + + + + + + + + + + + + + + + + + + + + + +

    参数

    +

    参数描述

    +

    handle

    +

    SPI设备句柄

    +

    buf

    +

    待写入数据的指针

    +

    len

    +

    待写入的数据长度

    +

    返回值

    +

    返回值描述

    +

    0

    +

    写入成功

    +

    负数

    +

    写入失败

    +
    + +``` +int32_t ret; +uint8_t wbuff[4] = {0x12, 0x34, 0x56, 0x78}; +/* 向SPI设备写入指定长度的数据 */ +ret = SpiWrite(spiHandle, wbuff, 4); +if (ret != 0) { + HDF_LOGE("SpiWrite: failed, ret %d\n", ret); +} +``` + +- 从SPI设备读取指定长度的数据 + +如果只读取一次数据,则可以通过以下函数完成: + +int32\_t SpiRead\(DevHandle handle, uint8\_t \*buf, uint32\_t len\); + +**表 6** SpiRead参数和返回值描述 + + + + + + + + + + + + + + + + + + + + + + + + +

    参数

    +

    参数描述

    +

    handle

    +

    SPI设备句柄

    +

    buf

    +

    待读取数据的指针

    +

    len

    +

    待读取的数据长度

    +

    返回值

    +

    返回值描述

    +

    0

    +

    读取成功

    +

    负数

    +

    读取失败

    +
    + +``` +int32_t ret; +uint8_t rbuff[4] = {0}; +/* 从SPI设备读取指定长度的数据 */ +ret = SpiRead(spiHandle, rbuff, 4); +if (ret != 0) { + HDF_LOGE("SpiRead: failed, ret %d\n", ret); +} +``` + +- 自定义传输 + +如果需要发起一次自定义传输,则可以通过以下函数完成: + +int32\_t SpiTransfer\(DevHandle handle, struct SpiMsg \*msgs, uint32\_t count\); + +**表 7** SpiTransfer参数和返回值描述 + + + + + + + + + + + + + + + + + + + + + + + + +

    参数

    +

    参数描述

    +

    handle

    +

    SPI设备句柄

    +

    msgs

    +

    待传输数据的数组

    +

    count

    +

    msgs数组长度

    +

    返回值

    +

    返回值描述

    +

    0

    +

    执行成功

    +

    负数

    +

    执行失败

    +
    + +``` +int32_t ret; +uint8_t wbuff[1] = {0x12}; +uint8_t rbuff[1] = {0}; +struct SpiMsg msg; /* 自定义传输的消息*/ +msg.wbuf = wbuff; /* 写入的数据 */ +msg.rbuf = rbuff; /* 读取的数据 */ +msg.len = 1; /* 读取、写入数据的长度都是1 */ +msg.csChange = 1; /* 进行下一次传输前关闭片选 */ +msg.delayUs = 0; /* 进行下一次传输前不进行延时 */ +msg.speed = 115200; /* 本次传输的速度 */ +/* 进行一次自定义传输,传输的msg个数为1 */ +ret = SpiTransfer(spiHandle, &msg, 1); +if (ret != 0) { + HDF_LOGE("SpiTransfer: failed, ret %d\n", ret); +} +``` + +### 销毁SPI设备句柄 + +SPI通信完成之后,需要销毁SPI设备句柄,销毁SPI设备句柄的函数如下所示: + +void SpiClose\(DevHandle handle\); + +该函数会释放掉申请的资源。 + +**表 8** SpiClose参数描述 + + + + + + + + + +

    参数

    +

    参数描述

    +

    handle

    +

    SPI设备句柄

    +
    + +``` +SpiClose(spiHandle); /* 销毁SPI设备句柄 */ +``` + +## 使用实例 + +SPI设备完整的使用示例如下所示,首先获取SPI设备句柄,然后配置SPI设备属性,接着调用读写接口进行数据传输,最后销毁SPI设备句柄。 + +``` +#include "hdf_log.h" +#include "spi_if.h" + +void SpiTestSample(void) +{ + int32_t ret; + struct SpiCfg cfg; /* SPI配置信息 */ + struct SpiDevInfo spiDevinfo; /* SPI设备描述符 */ + DevHandle spiHandle = NULL; /* SPI设备句柄 */ + struct SpiMsg msg; /* 自定义传输的消息 */ + uint8_t rbuff[4] = { 0 }; + uint8_t wbuff[4] = { 0x12, 0x34, 0x56, 0x78 }; + uint8_t wbuff2[4] = { 0xa1, 0xb2, 0xc3, 0xd4 }; + + spiDevinfo.busNum = 0; /* SPI设备总线号 */ + spiDevinfo.csNum = 0; /* SPI设备片选号 */ + spiHandle = SpiOpen(&spiDevinfo); /* 根据spiDevinfo获取SPI设备句柄 */ + if (spiHandle == NULL) { + HDF_LOGE("SpiOpen: failed\n"); + return; + } + /* 获取SPI设备属性 */ + ret = SpiGetCfg(spiHandle, &cfg); + if (ret != 0) { + HDF_LOGE("SpiGetCfg: failed, ret %d\n", ret); + goto err; + } + cfg.maxSpeedHz = 115200; /* 将最大时钟频率改为115200 */ + cfg.bitsPerWord = 8; /* 传输位宽改为8比特 */ + /* 配置SPI设备属性 */ + ret = SpiSetCfg(spiHandle, &cfg); + if (ret != 0) { + HDF_LOGE("SpiSetCfg: failed, ret %d\n", ret); + goto err; + } + /* 向SPI设备写入指定长度的数据 */ + ret = SpiWrite(spiHandle, wbuff, 4); + if (ret != 0) { + HDF_LOGE("SpiWrite: failed, ret %d\n", ret); + goto err; + } + /* 从SPI设备读取指定长度的数据 */ + ret = SpiRead(spiHandle, rbuff, 4); + if (ret != 0) { + HDF_LOGE("SpiRead: failed, ret %d\n", ret); + goto err; + } + msg.wbuf = wbuff2; /* 写入的数据 */ + msg.rbuf = rbuff; /* 读取的数据 */ + msg.len = 4; /* 读取写入数据的长度为4 */ + msg.csChange = 1; /* 进行下一次传输前关闭片选 */ + msg.delayUs = 0; /* 进行下一次传输前不进行延时 */ + msg.speed = 115200; /* 本次传输的速度 */ + /* 进行一次自定义传输,传输的msg个数为1 */ + ret = SpiTransfer(spiHandle, &msg, 1); + if (ret != 0) { + HDF_LOGE("SpiTransfer: failed, ret %d\n", ret); + goto err; + } +err: + /* 销毁SPI设备句柄 */ + SpiClose(spiHandle); +} +``` + diff --git a/zh-cn/device-dev/driver/drive-platform-uart-des.md b/zh-cn/device-dev/driver/drive-platform-uart-des.md new file mode 100644 index 0000000000..182cad984a --- /dev/null +++ b/zh-cn/device-dev/driver/drive-platform-uart-des.md @@ -0,0 +1,682 @@ +# UART + +- [概述](#section833012453535) + - [接口说明](#section1680292311549) + +- [使用指导](#section12779050105412) + - [使用流程](#section1858116395510) + - [获取UART设备句柄](#section124512065617) + - [UART设置波特率](#section86881004579) + - [UART获取波特率](#section897032965712) + - [UART设置设备属性](#section129141884588) + - [UART获取设备属性](#section18689637165812) + - [设置UART传输模式](#section72713435918) + - [向UART设备写入指定长度的数据](#section128001736155919) + - [从UART设备中读取指定长度的数据](#section92851601604) + - [销毁UART设备句柄](#section1477410521406) + +- [使用实例](#section35404241311) + +## 概述 + +- UART是通用异步收发传输器(Universal Asynchronous Receiver/Transmitter)的缩写,是通用串行数据总线,用于异步通信。该总线双向通信,可以实现全双工传输。 +- UART应用比较广泛,常用于输出打印信息,也可以外接各种模块,如GPS、蓝牙等。 +- 两个UART设备的连接示意图如下,UART与其他模块一般用2线(图1)或4线(图2)相连,它们分别是: + - TX:发送数据端,和对端的RX相连; + - RX:接收数据端,和对端的TX相连; + - RTS:发送请求信号,用于指示本设备是否准备好,可接受数据,和对端CTS相连; + - CTS:允许发送信号,用于判断是否可以向对端发送数据,和对端RTS相连; + + **图 1** 2线UART设备连接示意图 + + + ![](figure/zh-cn_image_0000001170262141.png) + + **图 2** 4线UART设备连接示意图 + + + ![](figure/zh-cn_image_0000001123582482.png) + + +- UART通信之前,收发双方需要约定好一些参数:波特率、数据格式(起始位、数据位、校验位、停止位)等。通信过程中,UART通过TX发送给对端数据,通过RX接收对端发送的数据。当UART接收缓存达到预定的门限值时,RTS变为不可发送数据,对端的CTS检测到不可发送数据,则停止发送数据。 +- UART接口定义了操作UART端口的通用方法集合,包括获取、释放设备句柄、读写数据、获取和设置波特率、获取和设置设备属性。 + +### 接口说明 + +**表 1** UART驱动API接口功能介绍 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    功能分类

    +

    接口名

    +

    描述

    +

    UART获取/释放设备句柄

    +

    +

    UartOpen

    +

    UART获取设备句柄

    +

    UartClose

    +

    UART释放设备句柄

    +

    UART读写接口

    +

    +

    UartRead

    +

    从UART设备中读取指定长度的数据

    +

    UartWrite

    +

    向UART设备中写入指定长度的数据

    +

    UART获取/设置波特率接口

    +

    UartGetBaud

    +

    UART获取波特率

    +

    UartSetBaud

    +

    UART设置波特率

    +

    UART获取/设置设备属性

    +

    +

    UartGetAttribute

    +

    UART获取设备属性

    +

    UartSetAttribute

    +

    UART设置设备属性

    +

    UART设置传输模式

    +

    UartSetTransMode

    +

    UART设置传输模式

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

    参数

    +

    参数描述

    +

    port

    +

    UART设备号

    +

    返回值

    +

    返回值描述

    +

    NULL

    +

    获取UART设备句柄失败

    +

    设备句柄

    +

    UART设备句柄

    +
    + +假设系统中的UART端口号为3,获取该UART设备句柄的示例如下: + +``` +DevHandle handle = NULL; /* UART设备句柄 */ +uint32_t port = 3; /* UART设备端口号 */ +handle = UartOpen(port); +if (handle == NULL) { + HDF_LOGE("UartOpen: failed!\n"); + return; +} +``` + +### UART设置波特率 + +在通信之前,需要设置UART的波特率,设置波特率的函数如下所示: + +int32\_t UartSetBaud\(DevHandle handle, uint32\_t baudRate\); + +**表 3** UartSetBaud参数和返回值描述 + + + + + + + + + + + + + + + + + + + + + + +

    参数

    +

    参数描述

    +

    handle

    +

    UART设备句柄

    +

    baudRate

    +

    待设置的波特率值

    +

    返回值

    +

    返回值描述

    +

    0

    +

    UART设置波特率成功

    +

    负数

    +

    UART设置波特率失败

    +
    + +假设需要设置的UART波特率为9600,设置波特率的实例如下: + +``` +int32_t ret; +/* 设置UART波特率 */ +ret = UartSetBaud(handle, 9600); +if (ret != 0) { + HDF_LOGE("UartSetBaud: failed, ret %d\n", ret); +} +``` + +### UART获取波特率 + +设置UART的波特率后,可以通过获取波特率接口来查看UART当前的波特率,获取波特率的函数如下所示: + +int32\_t UartGetBaud\(DevHandle handle, uint32\_t \*baudRate\); + +**表 4** UartGetBaud参数和返回值描述 + + + + + + + + + + + + + + + + + + + + + + +

    参数

    +

    参数描述

    +

    handle

    +

    UART设备句柄

    +

    baudRate

    +

    接收波特率值的指针

    +

    返回值

    +

    返回值描述

    +

    0

    +

    UART获取波特率成功

    +

    负数

    +

    UART获取波特率失败

    +
    + +获取波特率的实例如下: + +``` +int32_t ret; +uint32_t baudRate; +/* 获取UART波特率 */ +ret = UartGetBaud(handle, &baudRate); +if (ret != 0) { + HDF_LOGE("UartGetBaud: failed, ret %d\n", ret); +} +``` + +### UART设置设备属性 + +在通信之前,需要设置UART的设备属性,设置设备属性的函数如下图所示: + +int32\_t UartSetAttribute\(DevHandle handle, struct UartAttribute \*attribute\); + +**表 5** UartSetAttribute参数和返回值描述 + + + + + + + + + + + + + + + + + + + + + + +

    参数

    +

    参数描述

    +

    handle

    +

    UART设备句柄

    +

    attribute

    +

    待设置的设备属性

    +

    返回值

    +

    返回值描述

    +

    0

    +

    UART设置设备属性成功

    +

    负数

    +

    UART设置设备属性失败

    +
    + +设置UART的设备属性的实例如下: + +``` +int32_t ret; +struct UartAttribute attribute; +attribute.dataBits = UART_ATTR_DATABIT_7; /* UART传输数据位宽,一次传输7个bit */ +attribute.parity = UART_ATTR_PARITY_NONE; /* UART传输数据无校检 */ +attribute.stopBits = UART_ATTR_STOPBIT_1; /* UART传输数据停止位为1位 */ +attribute.rts = UART_ATTR_RTS_DIS; /* UART禁用RTS */ +attribute.cts = UART_ATTR_CTS_DIS; /* UART禁用CTS */ +attribute.fifoRxEn = UART_ATTR_RX_FIFO_EN; /* UART使能RX FIFO */ +attribute.fifoTxEn = UART_ATTR_TX_FIFO_EN; /* UART使能TX FIFO */ +/* 设置UART设备属性 */ +ret = UartSetAttribute(handle, &attribute); +if (ret != 0) { + HDF_LOGE("UartSetAttribute: failed, ret %d\n", ret); +} +``` + +### UART获取设备属性 + +设置UART的设备属性后,可以通过获取设备属性接口来查看UART当前的设备属性,获取设备属性的函数如下图所示: + +int32\_t UartGetAttribute\(DevHandle handle, struct UartAttribute \*attribute\); + +**表 6** UartGetAttribute参数和返回值描述 + + + + + + + + + + + + + + + + + + + + + + +

    参数

    +

    参数描述

    +

    handle

    +

    UART设备句柄

    +

    attribute

    +

    接收UART设备属性的指针

    +

    返回值

    +

    返回值描述

    +

    0

    +

    UART获取设备属性成功

    +

    负数

    +

    UART获取设备属性失败

    +
    + +获取UART的设备属性的实例如下: + +``` +int32_t ret; +struct UartAttribute attribute; +/* 获取UART设备属性 */ +ret = UartGetAttribute(handle, &attribute); +if (ret != 0) { + HDF_LOGE("UartGetAttribute: failed, ret %d\n", ret); +} +``` + +### 设置UART传输模式 + +在通信之前,需要设置UART的传输模式,设置传输模式的函数如下图所示: + +int32\_t UartSetTransMode\(DevHandle handle, enum UartTransMode mode\); + +**表 7** UartSetTransMode参数和返回值描述 + + + + + + + + + + + + + + + + + + + + + + +

    参数

    +

    参数描述

    +

    handle

    +

    UART设备句柄

    +

    mode

    +

    待设置的传输模式,

    +

    返回值

    +

    返回值描述

    +

    0

    +

    UART设置传输模式成功

    +

    负数

    +

    UART设置传输模式失败

    +
    + +假设需要设置的UART传输模式为UART\_MODE\_RD\_BLOCK,设置传输模式的实例如下: + +``` +int32_t ret; +/* 设置UART传输模式 */ +ret = UartSetTransMode(handle, UART_MODE_RD_BLOCK); +if (ret != 0) { + HDF_LOGE("UartSetTransMode: failed, ret %d\n", ret); +} +``` + +### 向UART设备写入指定长度的数据 + +对应的接口函数如下所示: + +int32\_t UartWrite\(DevHandle handle, uint8\_t \*data, uint32\_t size\); + +**表 8** UartWrite参数和返回值描述 + + + + + + + + + + + + + + + + + + + + + + + + + +

    参数

    +

    参数描述

    +

    handle

    +

    UART设备句柄

    +

    data

    +

    待写入数据的指针

    +

    size

    +

    待写入数据的长度

    +

    返回值

    +

    返回值描述

    +

    0

    +

    UART写数据成功

    +

    负数

    +

    UART写数据失败

    +
    + +写入指定长度数据的实例如下: + +``` +int32_t ret; +uint8_t wbuff[5] = {1, 2, 3, 4, 5}; +/* 向UART设备写入指定长度的数据 */ +ret = UartWrite(handle, wbuff, 5); +if (ret != 0) { + HDF_LOGE("UartWrite: failed, ret %d\n", ret); +} +``` + +### 从UART设备中读取指定长度的数据 + +对应的接口函数如下所示: + +int32\_t UartRead\(DevHandle handle, uint8\_t \*data, uint32\_t size\); + +**表 9** UartRead参数和返回值描述 + + + + + + + + + + + + + + + + + + + + + + + + + +

    参数

    +

    参数描述

    +

    handle

    +

    UART设备句柄

    +

    data

    +

    接收读取数据的指针

    +

    size

    +

    待读取数据的长度

    +

    返回值

    +

    返回值描述

    +

    非负数

    +

    UART读取到的数据长度

    +

    负数

    +

    UART读取数据失败

    +
    + +读取指定长度数据的实例如下: + +``` +int32_t ret; +uint8_t rbuff[5] = {0}; +/* 从UART设备读取指定长度的数据 */ +ret = UartRead(handle, rbuff, 5); +if (ret < 0) { + HDF_LOGE("UartRead: failed, ret %d\n", ret); +} +``` + +>![](../public_sys-resources/icon-caution.gif) **注意:** +>UART返回值为非负值,表示UART读取成功。若返回值等于0,表示UART无有效数据可以读取。若返回值大于0,表示实际读取到的数据长度,该长度小于或等于传入的参数size的大小,并且不超过当前正在使用的UART控制器规定的最大单次读取数据长度的值。 + +### 销毁UART设备句柄 + +UART通信完成之后,需要销毁UART设备句柄,函数如下所示: + +void UartClose\(DevHandle handle\); + +该函数会释放申请的资源。 + +**表 10** UartClose参数和返回值描述 + + + + + + + + + + +

    参数

    +

    参数描述

    +

    handle

    +

    UART设备句柄

    +
    + +销毁UART设备句柄的实例如下: + +``` +UartClose(handle); /* 销毁UART设备句柄 * +``` + +## 使用实例 + +UART设备完整的使用示例如下所示,首先获取UART设备句柄,接着设置波特率、设备属性和传输模式,之后进行UART通信,最后销毁UART设备句柄。 + +``` +#include "hdf_log.h" +#include "uart_if.h" + +void UartTestSample(void) +{ + int32_t ret; + uint32_t port; + DevHandle handle = NULL; + uint8_t wbuff[5] = { 1, 2, 3, 4, 5 }; + uint8_t rbuff[5] = { 0 }; + struct UartAttribute attribute; + attribute.dataBits = UART_ATTR_DATABIT_7; /* UART传输数据位宽,一次传输7个bit */ + attribute.parity = UART_ATTR_PARITY_NONE; /* UART传输数据无校检 */ + attribute.stopBits = UART_ATTR_STOPBIT_1; /* UART传输数据停止位为1位 */ + attribute.rts = UART_ATTR_RTS_DIS; /* UART禁用RTS */ + attribute.cts = UART_ATTR_CTS_DIS; /* UART禁用CTS */ + attribute.fifoRxEn = UART_ATTR_RX_FIFO_EN; /* UART使能RX FIFO */ + attribute.fifoTxEn = UART_ATTR_TX_FIFO_EN; /* UART使能TX FIFO */ + /* UART设备端口号,要填写实际平台上的端口号 */ + port = 1; + /* 获取UART设备句柄 */ + handle = UartOpen(port); + if (handle == NULL) { + HDF_LOGE("UartOpen: failed!\n"); + return; + } + /* 设置UART波特率为9600 */ + ret = UartSetBaud(handle, 9600); + if (ret != 0) { + HDF_LOGE("UartSetBaud: failed, ret %d\n", ret); + goto _ERR; + } + /* 设置UART设备属性 */ + ret = UartSetAttribute(handle, &attribute); + if (ret != 0) { + HDF_LOGE("UartSetAttribute: failed, ret %d\n", ret); + goto _ERR; + } + /* 设置UART传输模式为非阻塞模式 */ + ret = UartSetTransMode(handle, UART_MODE_RD_NONBLOCK); + if (ret != 0) { + HDF_LOGE("UartSetTransMode: failed, ret %d\n", ret); + goto _ERR; + } + /* 向UART设备写入5字节的数据 */ + ret = UartWrite(handle, wbuff, 5); + if (ret != 0) { + HDF_LOGE("UartWrite: failed, ret %d\n", ret); + goto _ERR; + } + /* 从UART设备读取5字节的数据 */ + ret = UartRead(handle, rbuff, 5); + if (ret < 0) { + HDF_LOGE("UartRead: failed, ret %d\n", ret); + goto _ERR; + } +_ERR: + /* 销毁UART设备句柄 */ + UartClose(handle); +} +``` + diff --git a/zh-cn/device-dev/driver/drive-platform-watchdog-des.md b/zh-cn/device-dev/driver/drive-platform-watchdog-des.md new file mode 100644 index 0000000000..b6eba28de3 --- /dev/null +++ b/zh-cn/device-dev/driver/drive-platform-watchdog-des.md @@ -0,0 +1,557 @@ +# WATCHDOG + +- [概述](#section14918241977) + - [接口说明](#section20177131219818) + +- [使用指导](#section10103184312813) + - [使用流程](#section10181195910815) + - [打开看门狗设备](#section66089201107) + - [获取看门狗状态](#section786624341011) + - [设置超时时间](#section182386137111) + - [获取超时时间](#section1883310371114) + - [启动看门狗](#section82501405123) + - [喂狗](#section3547530101211) + - [停止看门狗](#section944595841217) + - [关闭看门狗设备](#section96561824121311) + +- [使用实例](#section1724514523135) + +## 概述 + +看门狗(watchdog),又叫看门狗计时器(watchdog timer),是一种硬件的计时设备,当系统的主程序发生某些错误时,导致未及时清除看门狗计时器的计时值,这时看门狗计时器就会对系统发出复位信号,使系统从悬停状态恢复到正常运作状态。 + +### 接口说明 + +**表 1** 看门狗 API接口功能介绍 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    功能分类

    +

    接口名

    +

    描述

    +

    打开/关闭看门狗

    +

    WatchdogOpen

    +

    打开看门狗设备

    +

    WatchdogClose

    +

    关闭看门狗设备

    +

    启动/停止看门狗

    +

    WatchdogStart

    +

    启动看门狗

    +

    WatchdogStop

    +

    停止看门狗

    +

    设置/获取超时时间

    +

    WatchdogSetTimeout

    +

    设置看门狗超时时间

    +

    WatchdogGetTimeout

    +

    获取看门狗超时时间

    +

    获取看门狗状态

    +

    WatchdogGetStatus

    +

    获取看门狗状态

    +

    清除看门狗定时器

    +

    WatchdogFeed

    +

    清除看门狗定时器(喂狗)

    +
    + +>![](../public_sys-resources/icon-note.gif) **说明:** +>本文涉及看门狗的所有接口,仅限内核态使用,不支持在用户态使用。 + +## 使用指导 + +### 使用流程 + +使用看门狗的一般流程如[图1](#fig19134125410189)所示。 + +**图 1** 看门狗使用流程图 + + +![](figure/zh-cn_image_0000001170229891.png) + +### 打开看门狗设备 + +在操作看门狗之前,需要使用WatchdogOpen打开一个看门狗设备,一个系统可能有多个看门狗,通过ID号来打开指定的看门狗设备: + +int32\_t WatchdogOpen\(int16\_t wdtId\); + +**表 2** WatchdogOpen参数和返回值描述 + + + + + + + + + + + + + + + + + + + +

    参数

    +

    参数描述

    +

    wdtId

    +

    看门狗设备号

    +

    返回值

    +

    返回值描述

    +

    NULL

    +

    打开失败

    +

    DevHandle类型指针

    +

    看门狗设备句柄

    +
    + +``` +DevHandle handle = NULL; +handle = WatchdogOpen(0); /* 打开0号看门狗设备 */ +if (handle == NULL) { + HDF_LOGE("WatchdogOpen: failed, ret %d\n", ret); + return; +} +``` + +### 获取看门狗状态 + +int32\_t WatchdogGetStatus\(DevHandle handle, int32\_t \*status\); + +**表 3** WatchdogGetStatus参数和返回值描述 + + + + + + + + + + + + + + + + + + + + + + +

    参数

    +

    参数描述

    +

    handle

    +

    看门狗设备句柄

    +

    status

    +

    获取到的启动状态指针

    +

    返回值

    +

    返回值描述

    +

    0

    +

    获取成功

    +

    负数

    +

    获取失败

    +
    + +``` +int32_t ret; +int32_t status; +/* 获取Watchdog启动状态 */ +ret = WatchdogGetStatus(handle, &status); +if (ret != 0) { + HDF_LOGE("WatchdogGetStatus: failed, ret %d\n", ret); + return; +} +``` + +### 设置超时时间 + +int32\_t WatchdogSetTimeout\(PalHandle \*handle, uint32\_t seconds\); + +**表 4** WatchdogSetTimeout参数和返回值描述 + + + + + + + + + + + + + + + + + + + + + + +

    参数

    +

    参数描述

    +

    handle

    +

    看门狗设备句柄

    +

    seconds

    +

    超时时间,单位为秒

    +

    返回值

    +

    返回值描述

    +

    0

    +

    设置成功

    +

    负数

    +

    设置失败

    +
    + +``` +int32_t ret; +uint32_t timeOut = 60; +/* 设置超时时间,单位:秒 */ +ret = WatchdogSetTimeout(handle, timeOut); +if (ret != 0) { + HDF_LOGE("WatchdogSetTimeout: failed, ret %d\n", ret); + return; +} +``` + +### 获取超时时间 + +int32\_t WatchdogGetTimeout\(PalHandle \*handle, uint32\_t \*seconds\); + +**表 5** WatchdogGetTimeout参数和返回值描述 + + + + + + + + + + + + + + + + + + + + + + +

    参数

    +

    参数描述

    +

    handle

    +

    看门狗设备句柄

    +

    seconds

    +

    接收超时时间的指针,单位为秒

    +

    返回值

    +

    返回值描述

    +

    0

    +

    获取成功

    +

    负数

    +

    获取失败

    +
    + +``` +int32_t ret; +uint32_t timeOut; +/* 获取超时时间,单位:秒 */ +ret = WatchdogGetTimeout(handle, &timeOut); +if (ret != 0) { + HDF_LOGE("WatchdogGetTimeout: failed, ret %d\n", ret); + return; +} +``` + +### 启动看门狗 + +int32\_t WatchdogStart\(DevHandle handle\); + +**表 6** WatchdogStart参数和返回值描述 + + + + + + + + + + + + + + + + + + + +

    参数

    +

    参数描述

    +

    handle

    +

    看门狗设备句柄

    +

    返回值

    +

    返回值描述

    +

    0

    +

    启动成功

    +

    负数

    +

    启动失败

    +
    + +``` +int32_t ret; +/* 启动看门狗 */ +ret = WatchdogStart(handle); +if (ret != 0) { + HDF_LOGE("WatchdogStart: failed, ret %d\n", ret); + return; +} +``` + +### 喂狗 + +int32\_t WatchdogFeed\(DevHandle handle\); + +**表 7** WatchdogFeed参数和返回值描述 + + + + + + + + + + + + + + + + + + + +

    参数

    +

    参数描述

    +

    handle

    +

    看门狗设备句柄

    +

    返回值

    +

    返回值描述

    +

    0

    +

    喂狗成功

    +

    负数

    +

    喂狗失败

    +
    + +``` +int32_t ret; +/* 喂狗 */ +ret = WatchdogFeed(handle); +if (ret != 0) { + HDF_LOGE("WatchdogFeed: failed, ret %d\n", ret); + return; +} +``` + +### 停止看门狗 + +int32\_t WatchdogStop\(DevHandle handle\); + +**表 8** WatchdogStop参数和返回值描述 + + + + + + + + + + + + + + + + + + + +

    参数

    +

    参数描述

    +

    handle

    +

    看门狗设备句柄

    +

    返回值

    +

    返回值描述

    +

    0

    +

    停止成功

    +

    负数

    +

    停止失败

    +
    + +``` +int32_t ret; +/* 停止看门狗 */ +ret = WatchdogStop(handle); +if (ret != 0) { + HDF_LOGE("WatchdogStop: failed, ret %d\n", ret); + return; +} +``` + +### 关闭看门狗设备 + +当操作完毕时,使用WatchdogClose关闭打开的设备句柄: + +void WatchdogClose\(DevHandle handle\); + +**表 9** WatchdogClose参数和返回值描述 + + + + + + + + + + +

    参数

    +

    参数描述

    +

    handle

    +

    看门狗设备句柄

    +
    + +``` +/* 关闭看门狗 */ +ret = WatchdogClose(handle); +``` + +## 使用实例 + +本例程提供看门狗的完整使用流程。 + +在本例程中,我们打开一个看门狗设备,设置超时时间并启动计时: + +- 首先定期喂狗,即按时清除看门狗定时器,确保系统不会因定时器超时而复位。 +- 接着再停止喂狗,观察定时器到期后系统是否发生复位行为。 + +示例如下: + +``` +#include "watchdog_if.h" +#include "hdf_log.h" +#include "osal_irq.h" +#include "osal_time.h" + +#define WATCHDOG_TEST_TIMEOUT 2 +#define WATCHDOG_TEST_FEED_TIME 6 + +static int32_t TestCaseWatchdog(void) +{ + int32_t i; + int32_t ret; + uint32_t timeout; + DevHandle handle = NULL; + + /* 打开0号看门狗设备 */ + handle = WatchdogOpen(0); + if (handle == NULL) { + HDF_LOGE("Open watchdog fail!"); + return -1; + } + + /* 设置超时时间 */ + ret = WatchdogSetTimeout(handle, WATCHDOG_TEST_TIMEOUT); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: set timeout fail! ret:%d\n", __func__, ret); + WatchdogClose(handle); + return ret; + } + + /* 回读设置的超时时间值 */ + ret = WatchdogGetTimeout(handle, &timeout); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: get timeout fail! ret:%d\n", __func__, ret); + WatchdogClose(handle); + return ret; + } + HDF_LOGI("%s: read timeout back:%u\n", __func__, timeout); + + /* 启动看门狗,开始计时 */ + ret = WatchdogStart(handle); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: satrt fail! ret:%d\n", __func__, ret); + WatchdogClose(handle); + return ret; + } + + /* 每隔1S喂狗一次 */ + for (i = 0; i < WATCHDOG_TEST_FEED_TIME; i++) { + HDF_LOGE("%s: feeding watchdog %d times... \n", __func__, i); + ret = WatchdogFeed(handle); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: feed dog fail! ret:%d\n", __func__, ret); + WatchdogClose(handle); + return ret; + } + OsalSleep(1); + } + /* 由于喂狗间隔小于超时时间,系统不会发生复位,此日志可以正常打印 */ + HDF_LOGE("%s: no reset ... feeding test OK!!!\n", __func__); + + /* 接下来持续不喂狗,使得看门狗计时器超时 */ + for (i = 0; i < WATCHDOG_TEST_FEED_TIME; i++) { + HDF_LOGE("%s: watiting dog buck %d times... \n", __func__, i); + OsalSleep(1); + } + + /* 当不喂狗时间到达之前设定的超时时间的时候,系统会发生复位,理论上观察不到此日志的打印 */ + HDF_LOGE("%s: dog has't buck!!! \n", __func__, i); + WatchdogClose(handle); + return -1; +} +``` + diff --git a/zh-cn/device-dev/driver/drive-platform.md b/zh-cn/device-dev/driver/drive-platform.md new file mode 100644 index 0000000000..6fd91defa4 --- /dev/null +++ b/zh-cn/device-dev/driver/drive-platform.md @@ -0,0 +1,19 @@ +# 平台驱动 + +- **[GPIO](drive-platform-gpio-des.md)** + +- **[I2C](drive-platform-i2c-des.md)** + +- **[RTC](drive-platform-rtc-des.md)** + +- **[SDIO](drive-platform-sdio-des.md)** + +- **[SPI](drive-platform-spi-des.md)** + +- **[UART](drive-platform-uart-des.md)** + +- **[WATCHDOG](drive-platform-watchdog-des.md)** + +- **[MIPI DSI](drive-platform-mipidsi-des.md)** + + diff --git a/zh-cn/device-dev/driver/drive.md b/zh-cn/device-dev/driver/drive.md new file mode 100644 index 0000000000..0e8e677c95 --- /dev/null +++ b/zh-cn/device-dev/driver/drive.md @@ -0,0 +1,19 @@ +# 驱动使用指南 + +- **[HDF开发概述](drive-hdf-overview.md)** + +- **[驱动开发](drive-hdf-development.md)** + +- **[驱动服务管理](drive-hdf-servicemanage.md)** + +- **[驱动消息机制管理](drive-hdf-news.md)** + +- **[配置管理](drive-hdf-manage.md)** + +- **[HDF开发实例](drive-hdf-sample.md)** + +- **[平台驱动](drive-platform.md)** + +- **[外设](drive-peripherals.md)** + + diff --git "a/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" "b/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" old mode 100755 new mode 100644 similarity index 100% rename from "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" rename to "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" diff --git "a/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" "b/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" old mode 100755 new mode 100644 similarity index 100% rename from "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" rename to "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" diff --git "a/zh-cn/device-dev/driver/figures/MIPI-DSI\346\216\245\345\217\243.png" "b/zh-cn/device-dev/driver/figure/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/figures/MIPI-DSI\346\216\245\345\217\243.png" rename to "zh-cn/device-dev/driver/figure/MIPI-DSI\346\216\245\345\217\243.png" diff --git "a/zh-cn/device-dev/driver/figures/Sensor\351\251\261\345\212\250\346\250\241\345\236\213\345\233\276.png" "b/zh-cn/device-dev/driver/figure/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/figures/Sensor\351\251\261\345\212\250\346\250\241\345\236\213\345\233\276.png" rename to "zh-cn/device-dev/driver/figure/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/figures/TTL\346\216\245\345\217\243.png" "b/zh-cn/device-dev/driver/figure/TTL\346\216\245\345\217\243.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/driver/figures/TTL\346\216\245\345\217\243.png" rename to "zh-cn/device-dev/driver/figure/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/figure/Touchscreen\345\231\250\344\273\266\345\270\270\347\224\250\347\256\241\350\204\232.png" old mode 100755 new mode 100644 similarity index 100% rename from "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" rename to "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" diff --git a/zh-cn/device-dev/driver/figures/zh-cn_image_0000001053405727.png b/zh-cn/device-dev/driver/figure/zh-cn_image_0000001053405727.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/driver/figures/zh-cn_image_0000001053405727.png rename to zh-cn/device-dev/driver/figure/zh-cn_image_0000001053405727.png diff --git a/zh-cn/device-dev/driver/figures/zh-cn_image_0000001054280608.png b/zh-cn/device-dev/driver/figure/zh-cn_image_0000001054280608.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/driver/figures/zh-cn_image_0000001054280608.png rename to zh-cn/device-dev/driver/figure/zh-cn_image_0000001054280608.png diff --git a/zh-cn/device-dev/driver/figures/zh-cn_image_0000001054564784.png b/zh-cn/device-dev/driver/figure/zh-cn_image_0000001054564784.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/driver/figures/zh-cn_image_0000001054564784.png rename to zh-cn/device-dev/driver/figure/zh-cn_image_0000001054564784.png diff --git a/zh-cn/device-dev/driver/figures/zh-cn_image_0000001057902344.png b/zh-cn/device-dev/driver/figure/zh-cn_image_0000001123509750.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/driver/figures/zh-cn_image_0000001057902344.png rename to zh-cn/device-dev/driver/figure/zh-cn_image_0000001123509750.png diff --git a/zh-cn/device-dev/driver/figures/zh-cn_image_0000001072553354.png b/zh-cn/device-dev/driver/figure/zh-cn_image_0000001123514210.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/driver/figures/zh-cn_image_0000001072553354.png rename to zh-cn/device-dev/driver/figure/zh-cn_image_0000001123514210.png diff --git a/zh-cn/device-dev/driver/figures/zh-cn_image_0000001054440624.png b/zh-cn/device-dev/driver/figure/zh-cn_image_0000001123540984.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/driver/figures/zh-cn_image_0000001054440624.png rename to zh-cn/device-dev/driver/figure/zh-cn_image_0000001123540984.png diff --git a/zh-cn/device-dev/driver/figures/zh-cn_image_0000001054007499.png b/zh-cn/device-dev/driver/figure/zh-cn_image_0000001123582482.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/driver/figures/zh-cn_image_0000001054007499.png rename to zh-cn/device-dev/driver/figure/zh-cn_image_0000001123582482.png diff --git a/zh-cn/device-dev/driver/figures/zh-cn_image_0000001054728498.png b/zh-cn/device-dev/driver/figure/zh-cn_image_0000001123675706.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/driver/figures/zh-cn_image_0000001054728498.png rename to zh-cn/device-dev/driver/figure/zh-cn_image_0000001123675706.png diff --git a/zh-cn/device-dev/driver/figures/zh-cn_image_0000001054726248.png b/zh-cn/device-dev/driver/figure/zh-cn_image_0000001123703482.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/driver/figures/zh-cn_image_0000001054726248.png rename to zh-cn/device-dev/driver/figure/zh-cn_image_0000001123703482.png diff --git a/zh-cn/device-dev/driver/figures/zh-cn_image_0000001054142582.png b/zh-cn/device-dev/driver/figure/zh-cn_image_0000001123742254.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/driver/figures/zh-cn_image_0000001054142582.png rename to zh-cn/device-dev/driver/figure/zh-cn_image_0000001123742254.png diff --git a/zh-cn/device-dev/driver/figures/zh-cn_image_0000001057342245.png b/zh-cn/device-dev/driver/figure/zh-cn_image_0000001170187071.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/driver/figures/zh-cn_image_0000001057342245.png rename to zh-cn/device-dev/driver/figure/zh-cn_image_0000001170187071.png diff --git a/zh-cn/device-dev/driver/figures/zh-cn_image_0000001054006983.png b/zh-cn/device-dev/driver/figure/zh-cn_image_0000001170227689.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/driver/figures/zh-cn_image_0000001054006983.png rename to zh-cn/device-dev/driver/figure/zh-cn_image_0000001170227689.png diff --git a/zh-cn/device-dev/driver/figures/zh-cn_image_0000001057622716.png b/zh-cn/device-dev/driver/figure/zh-cn_image_0000001170229891.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/driver/figures/zh-cn_image_0000001057622716.png rename to zh-cn/device-dev/driver/figure/zh-cn_image_0000001170229891.png diff --git a/zh-cn/device-dev/driver/figures/zh-cn_image_0000001053926237.png b/zh-cn/device-dev/driver/figure/zh-cn_image_0000001170262141.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/driver/figures/zh-cn_image_0000001053926237.png rename to zh-cn/device-dev/driver/figure/zh-cn_image_0000001170262141.png diff --git a/zh-cn/device-dev/driver/figures/zh-cn_image_0000001055299108.png b/zh-cn/device-dev/driver/figure/zh-cn_image_0000001170383063.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/driver/figures/zh-cn_image_0000001055299108.png rename to zh-cn/device-dev/driver/figure/zh-cn_image_0000001170383063.png diff --git "a/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" "b/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" old mode 100755 new mode 100644 similarity index 100% rename from "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" rename to "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" diff --git "a/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" "b/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" old mode 100755 new mode 100644 similarity index 100% rename from "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" rename to "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" diff --git "a/zh-cn/device-dev/driver/figures/\346\216\245\345\217\243\345\210\206\345\270\203\345\233\2764.png" "b/zh-cn/device-dev/driver/figure/\346\216\245\345\217\243\345\210\206\345\270\203\345\233\2764.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/driver/figures/\346\216\245\345\217\243\345\210\206\345\270\203\345\233\2764.png" rename to "zh-cn/device-dev/driver/figure/\346\216\245\345\217\243\345\210\206\345\270\203\345\233\2764.png" diff --git a/zh-cn/device-dev/driver/public_sys-resources/icon-caution.gif b/zh-cn/device-dev/driver/public_sys-resources/icon-caution.gif deleted file mode 100755 index 6e90d7cfc2193e39e10bb58c38d01a23f045d571..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 580 zcmV-K0=xZ3Nk%w1VIu$?0Hp~4{QBgqmQ+MG9K51r{QB&)np^||1PlfQ%(86!{`~yv zv{XhUWKt}AZaiE{EOcHp{O-j3`t;<+eEiycJT4p@77X;(jQsMfB$R?oG%6hQ z+MMLZbQBH@)Vg&1^3?qHb(5!%>3r0+`eq=&V&E}0Dypi0000000000 z00000A^8LW000R9EC2ui03!e$000L5z=Uu}ED8YtqjJd<+B}(9bIOb$3-31_h|V>=0A{ z1Hh0#H30>fNT})^fRU_83uewx9oRr{f{Sx1Ml`t)EQ zGkHZ67&~y{W5Jpq4H_WfuLxp*3<7O}GEl;1ESe36fLNs=B0&LQM1Buf(R)qg(BRd`t1OPjI1m_q4 diff --git a/zh-cn/device-dev/driver/public_sys-resources/icon-danger.gif b/zh-cn/device-dev/driver/public_sys-resources/icon-danger.gif deleted file mode 100755 index 6e90d7cfc2193e39e10bb58c38d01a23f045d571..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 580 zcmV-K0=xZ3Nk%w1VIu$?0Hp~4{QBgqmQ+MG9K51r{QB&)np^||1PlfQ%(86!{`~yv zv{XhUWKt}AZaiE{EOcHp{O-j3`t;<+eEiycJT4p@77X;(jQsMfB$R?oG%6hQ z+MMLZbQBH@)Vg&1^3?qHb(5!%>3r0+`eq=&V&E}0Dypi0000000000 z00000A^8LW000R9EC2ui03!e$000L5z=Uu}ED8YtqjJd<+B}(9bIOb$3-31_h|V>=0A{ z1Hh0#H30>fNT})^fRU_83uewx9oRr{f{Sx1Ml`t)EQ zGkHZ67&~y{W5Jpq4H_WfuLxp*3<7O}GEl;1ESe36fLNs=B0&LQM1Buf(R)qg(BRd`t1OPjI1m_q4 diff --git a/zh-cn/device-dev/driver/public_sys-resources/icon-note.gif b/zh-cn/device-dev/driver/public_sys-resources/icon-note.gif deleted file mode 100755 index 6314297e45c1de184204098efd4814d6dc8b1cda..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 394 zcmZ?wbhEHblx7fPSjxcg=ii?@_wH=jwxy=7CMGH-B`L+l$wfv=#>UF#$gv|VY%C^b zCQFtrnKN(Bo_%|sJbO}7RAORe!otL&qo<>yq_Sq+8Xqqo5h0P3w3Lvb5E(g{p01vl zxR@)KuDH0l^z`+-dH3eaw=XqSH7aTIx{kzVBN;X&hha0dQSgWuiw0NWUvMRmkD|> diff --git a/zh-cn/device-dev/driver/public_sys-resources/icon-notice.gif b/zh-cn/device-dev/driver/public_sys-resources/icon-notice.gif deleted file mode 100755 index 86024f61b691400bea99e5b1f506d9d9aef36e27..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 406 zcmV;H0crk6Nk%w1VIu$@0J8u9|NsB@_xJDb@8;&_*4Ea}&d#;9wWXz{jEszHYim+c zQaU<1At50E0000000000A^8Le000gEEC2ui03!e%000R7038S%NU)&51O^i-Tu6`s z0)`MFE@;3YqD6xSC^kTNu_J>91{PH8XfZ(p1pp2-SU@u3#{mEUC}_}tg3+I#{z}{Ok@D_ZUDg- zt0stin4;pC8M{WLSlRH*1pzqEw1}3oOskyNN?j;7HD{BBZ*OEcv4HK!6Bk6beR+04 z&8}k>SkTusVTDmkyOz#5fCA$JTPGJVQvr3uZ?QzzPQFvD0rGf_PdrcF`pMs}p^BcF zKtKTd`0wipR%nKN&Wj+V}pX;WC3SdJV!a_8Qi zE7z`U*|Y^H0^}fB$R?oG%6hQ z+MMLZbQBH@)Vg&1^3?qHb(5!%>3r0+`eq=&V&E}0Dypi0000000000 z00000A^8LW000R9EC2ui03!e$000L5z=Uu}ED8YtqjJd<+B}(9bIOb$3-31_h|V>=0A{ z1Hh0#H30>fNT})^fRU_83uewx9oRr{f{Sx1Ml`t)EQ zGkHZ67&~y{W5Jpq4H_WfuLxp*3<7O}GEl;1ESe36fLNs=B0&LQM1Buf(R)qg(BRd`t1OPjI1m_q4 diff --git "a/zh-cn/device-dev/driver/\344\274\240\346\204\237\345\231\250\351\251\261\345\212\250\345\274\200\345\217\221\345\256\236\344\276\213.md" "b/zh-cn/device-dev/driver/\344\274\240\346\204\237\345\231\250\351\251\261\345\212\250\345\274\200\345\217\221\345\256\236\344\276\213.md" deleted file mode 100755 index 2222c0fde7..0000000000 --- "a/zh-cn/device-dev/driver/\344\274\240\346\204\237\345\231\250\351\251\261\345\212\250\345\274\200\345\217\221\345\256\236\344\276\213.md" +++ /dev/null @@ -1,583 +0,0 @@ -# 传感器驱动开发实例 - -基于HDF驱动模型,加载启动加速度计传感器驱动,代码形式如下,具体原理可参考[HDF驱动开发指南](驱动开发.md)。加速度传感器选择通讯接口方式为I2C,厂家选择博世BMI160加速度传感器。 - -1. 加速度计传感器驱动入口注册 - -- 加速度计传感器驱动入口函数实现 - -``` -/* 注册加速度计传感器入口数据结构体对象 */ -struct HdfDriverEntry g_sensorAccelDevEntry = { - .moduleVersion = 1, /* 加速度计传感器模块版本号 */ - .moduleName = "HDF_SENSOR_ACCEL", /* 加速度计传感器模块名,要与device_info.hcs文件里的加速度计moduleName字段值一样*/ - .Bind = BindAccelDriver, /* 加速度计传感器绑定函数 */ - .Init = InitAccelDriver, /* 加速度计传感器初始化函数 */ - .Release = ReleaseAccelDriver, /* 加速度计传感器资源释放函数 */ -}; - -/* 调用HDF_INIT将驱动入口注册到HDF框架中,在加载驱动时HDF框架会先调用Bind函数,再调用Init函数加载该驱动,当Init调用异常时,HDF框架会调用Release释放驱动资源并退出 */ -HDF_INIT(g_sensorAccelDevEntry); -``` - -- 加速度计传感器设备配置描述 - -加速度传感器模型使用HCS作为配置描述源码,HCS配置字段详细介绍参考[配置管理](配置管理.md)介绍。 - -``` -/* 加速度计传感器设备HCS配置 */ -device_sensor_accel :: device { - device0 :: deviceNode { - policy = 1; /* policy字段是驱动服务发布的策略 */ - priority = 105; /* 驱动启动优先级(0-200),值越大优先级越低,建议默认配100,优先级相同则不保证device的加载顺序 */ - preload = 2; /* 驱动按需加载字段,0表示加载,2表示不加载 */ - permission = 0664; /* 驱动创建设备节点权限 */ - moduleName = "HDF_SENSOR_ACCEL"; /* 驱动名称,该字段的值必须和驱动入口结构的moduleName值一致 */ - serviceName = "sensor_accel"; /* 驱动对外发布服务的名称,必须唯一 */ - deviceMatchAttr = "hdf_sensor_accel_driver"; /* 驱动私有数据匹配的关键字,必须和驱动私有数据配置表中的match_attr值相等 */ - } -} -``` - -1. 加速度计传感器驱动初始化和去初始化 - -- 初始化入口函数init - -``` -/* 加速度计传感器驱动对外提供的服务绑定到HDF框架 */ -int32_t BindAccelDriver(struct HdfDeviceObject *device) -{ - CHECK_NULL_PTR_RETURN_VALUE(device, HDF_ERR_INVALID_PARAM); - - static struct IDeviceIoService service = { - .object = {0}, - .Dispatch = DispatchAccel, - }; - device->service = &service; - - return HDF_SUCCESS; -} -/*在探测到器件在位后,需要调用RegisterAccelChipOps注册差异化适配函数*/ -int32_t RegisterAccelChipOps(struct AccelOpsCall *ops) -{ - struct AccelDrvData *drvData = NULL; - - CHECK_NULL_PTR_RETURN_VALUE(ops, HDF_ERR_INVALID_PARAM); - - drvData = AccelGetDrvData(); - drvData->ops.Init = ops->Init; - drvData->ops.ReadData = ops->ReadData; - return HDF_SUCCESS; -} -/* 挂载加速度计传感器驱动归一化的接口函数 */ -static int32_t InitAccelOps(struct SensorDeviceInfo *deviceInfo) -{ - struct AccelDrvData *drvData = AccelGetDrvData(); - - (void)memset_s((void *)deviceInfo, sizeof(*deviceInfo), 0, sizeof(*deviceInfo)); - deviceInfo->ops.GetInfo = SetAccelInfo; - deviceInfo->ops.Enable = SetAccelEnable; - deviceInfo->ops.Disable = SetAccelDisable; - deviceInfo->ops.SetBatch = SetAccelBatch; - deviceInfo->ops.SetMode = SetAccelMode; - deviceInfo->ops.SetOption = SetAccelOption; - - if (memcpy_s(&deviceInfo->sensorInfo, sizeof(deviceInfo->sensorInfo), - &drvData->accelCfg->sensorInfo, sizeof(drvData->accelCfg->sensorInfo)) != EOK) { - HDF_LOGE("%s: copy sensor info failed", __func__); - return HDF_FAILURE; - } - /* 传感器类型标识可以在数据HCS配置文件里面配置,也可以在此处 */ - drvData->accelCfg->sensorInfo.sensorTypeId = SENSOR_TAG_ACCELEROMETER; - drvData->accelCfg->sensorInfo.sensorId = SENSOR_TAG_ACCELEROMETER; - - return HDF_SUCCESS; -} -/* 传感器寄存器初始化操作 */ -static int32_t InitAccelAfterConfig(void) -{ - struct SensorDeviceInfo deviceInfo; - - if (InitAccelConfig() != HDF_SUCCESS) { - HDF_LOGE("%s: init accel config failed", __func__); - return HDF_FAILURE; - } - - if (InitAccelOps(&deviceInfo) != HDF_SUCCESS) { - HDF_LOGE("%s: init accel ops failed", __func__); - return HDF_FAILURE; - } - - if (AddSensorDevice(&deviceInfo) != HDF_SUCCESS) { - HDF_LOGE("%s: add accel device failed", __func__); - return HDF_FAILURE; - } - - return HDF_SUCCESS; -} -/*通过器件探测函数,挂载器件差异化函数接口*/ -static int32_t DetectAccelChip(void) -{ - int32_t num; - int32_t ret; - int32_t loop; - struct AccelDrvData *drvData = AccelGetDrvData(); - CHECK_NULL_PTR_RETURN_VALUE(drvData->accelCfg, HDF_ERR_INVALID_PARAM); - - num = sizeof(g_accelDetectIfList) / sizeof(g_accelDetectIfList[0]); - for (loop = 0; loop < num; ++loop) { - if (g_accelDetectIfList[loop].DetectChip != NULL) { - ret = g_accelDetectIfList[loop].DetectChip(drvData->accelCfg); - if (ret == HDF_SUCCESS) { - drvData->detectFlag = true; - break; - } - } - } - - if (loop == num) { - HDF_LOGE("%s: detect accel device failed", __func__); - drvData->detectFlag = false; - return HDF_FAILURE; - } - return HDF_SUCCESS; -} -/* 加速度计传感器驱动初始化入口函数,主要功能为对传感器私有数据的结构体对象进行初始化,传感器HCS数据配置对象空间分配,传感器HCS数据配置初始化入口函数调用,传感器设备探测是否在位功能,传感器数据上报定时器创建,传感器归一化接口挂载,传感器设备注册功能 */ -int32_t InitAccelDriver(struct HdfDeviceObject *device) -{ - /* 获取传感器私有数据结构体对象 */ - struct AccelDrvData *drvData = AccelGetDrvData(); - - /* 同类型传感器不同厂家设备探测时,判断此类型传感器是否已经在位,若已经在位,无需再继续探测,直接返回 */ - if (drvData->detectFlag) { - HDF_LOGE("%s: accel sensor have detected", __func__); - return HDF_SUCCESS; - } - - CHECK_NULL_PTR_RETURN_VALUE(device, HDF_ERR_INVALID_PARAM); - /* 分配存放传感器数据配置的私有结构体数据对象,需要在驱动释放时释放分配的资源空间 */ - drvData->accelCfg = (struct SensorCfgData *)OsalMemCalloc(sizeof(*cfg)); - if (drvData->accelCfg == NULL) { - HDF_LOGE("%s: malloc sensor config data failed", __func__); - return HDF_FAILURE; - } - - drvData->accelCfg->regCfgGroup = &g_regCfgGroup[0]; - /* 初始化传感器配置数据主要是解析传感器通讯总线配置类型信息,传感器基本信息,传感器属性信息,传感器是否在位信息,寄存器分组信息 */ - if (GetSensorBaseConfigData(device->property, drvData->accelCfg) != HDF_SUCCESS) { - HDF_LOGE("%s: get sensor base config failed", __func__); - goto Base_CONFIG_EXIT; - } - - if (DetectAccelChip() != HDF_SUCCESS) { - HDF_LOGE("%s: accel sensor detect device no exist", __func__); - goto DETECT_CHIP_EXIT; - } - drvData->detectFlag = true; - if (ParseSensorRegConfig(drvData->accelCfg) != HDF_SUCCESS) { - HDF_LOGE("%s: detect sensor device failed", __func__); - goto REG_CONFIG_EXIT; - } - - if (InitAccelAfterConfig() != HDF_SUCCESS) { - HDF_LOGE("%s: init accel after config failed", __func__); - goto INIT_EXIT; - } - - HDF_LOGI("%s: init accel driver success", __func__); - return HDF_SUCCESS; - -INIT_EXIT: - DestroySensorThread(&drvData->thread, &drvData->threadStatus); - (void)DeleteSensorDevice(SENSOR_TAG_ACCELEROMETER); -REG_CONFIG_EXIT: - ReleaseSensorAllRegConfig(drvData->accelCfg); - (void)ReleaseSensorBusHandle(&drvData->accelCfg->busCfg); -DETECT_CHIP_EXIT: - drvData->detectFlag = false; -BASE_CONFIG_EXIT: - drvData->accelCfg->root = NULL; - drvData->accelCfg->regCfgGroup = NULL; - OsalMemFree(drvData->accelCfg); - drvData->accelCfg = NULL; - return HDF_FAILURE; -} - -/* 释放驱动初始化时分配的资源 */ -void ReleaseAccelDriver(struct HdfDeviceObject *device) -{ - (void)device; - struct AccelDrvData *drvData = NULL; - - drvData = AccelGetDrvData(); - (void)DestroySensorThread(&drvData->thread, &drvData->threadStatus); - (void)DeleteSensorDevice(SENSOR_TAG_ACCELEROMETER); - drvData->detectFlag = false; - - if (drvData->accelCfg != NULL) { - drvData->accelCfg->root = NULL; - drvData->accelCfg->regCfgGroup = NULL; - ReleaseSensorAllRegConfig(drvData->accelCfg); - (void)ReleaseSensorBusHandle(&drvData->accelCfg->busCfg); - OsalMemFree(drvData->accelCfg); - drvData->accelCfg = NULL; - } - - drvData->initStatus = false; -} -``` - -1. 加速度计传感器寄存器组配置信息 - -加速度计传感器数据配置只需要按照模板配置即可,基于模板配置的解析功能已经在**InitSensorConfigData**函数完成,只需初始化时调用即可。如果有新增配置项,需要同步修改此函数。 - -``` -加速度传感器数据配置模板(accel_config.hcs) -root { - sensorAccelConfig { - accelChipConfig { - /* 传感器设备信息模板 */ - template sensorInfo { - sensorName = "accelerometer"; /* 加速度计名字,字符最大长度16字节 */ - vendorName = "borsh_bmi160"; /* 传感器设备厂商,字符最大长度16字节 */ - firmwareVersion = "1.0"; /* 传感器固件版本号,默认1.0,字符最大长度16字节 */ - hardwareVersion = "1.0"; /* 传感器硬件版本号,默认1.0,字符最大长度16字节 */ - sensorTypeId = 1; /* 传感器类型编号,详见{@link SensorTypeTag} */ - sensorId = 1; /* 传感器的标识号,有传感器驱动开发者定义,推荐用{@link SensorTypeTag}枚举 */ - maxRange = 8; /* 传感器的最大量程,根据开发者需要配置 */ - precision = 0; /* 传感器的精度,与上报数据配合使用,上报数据结构体{@link SensorEvents } */ - power = 230; /* 传感器的功耗 */ - } - /* 传感器使用的总线类型和配置信息模板 */ - template sensorBusConfig { - busType = 0; /* 0:i2c 1:spi */ - busNum = 6; /* 芯片上分配给传感器的器件号 */ - busAddr = 0; /* 芯片上分配给传感器的地址 */ - regWidth = 1; /* 传感器寄存器地址宽度 */ - regBigEndian = 0; /* 传感器寄存器大小端 */ - } - /* 传感器设备属性模板 */ - template sensorAttr { - chipName = ""; /* 传感器芯片名字 */ - chipIdRegister = 0xf; /* 传感器在位检测寄存器地址 */ - chipIdValue = 0xd1; /* 校验传感器在位检测寄存器值 */ - } - } - } -} - -/* 根据不同器件硬件差异,修改模板配置,不修改的就会默认采用模板配置 */ -root { - sensorAccelConfig { - accel_bmi160_chip_config : accelChipConfig { - match_attr = "hdf_sensor_accel_driver"; /* 需要和加速度传感器设备配置match_attr字段保持一致 */ - accelInfo :: sensorInfo { - vendorName = "borsh_bmi160"; - sensorTypeId = 1; - sensorId = 1; - } - accelBusConfig :: sensorBusConfig { - busType = 0; /* i2c通讯方式 */ - busNum = 6; - busAddr = 0x68; - regWidth = 1; /* 1字节位宽 */ - } - accelAttr :: sensorAttr { - chipName = "bmi160"; - chipIdRegister = 0x00; - chipIdValue = 0xd1; - } - accelRegConfig { - /* regAddr: 寄存器地址 - value: 寄存器值 - mask: 寄存器值的掩码 - len: 寄存器值的数据长度(字节) - delay: 配置寄存器延时(ms) - opsType:操作类型 0-无 1-读 2-写 3-读并检查 4-位更新 - calType: 计算类型 0-无 1-写 2-取反 3-异或 4-左移 5-右移 - shiftNum: 移动位数 - debug: 调试开关,0-调试关闭 1-调试打开 - save: 保存数据开关,0-不保存数据 1-保存数据 - */ - /* 传感器寄存器操作分组,按照分组进行有序配置 */ - /* 寄存器地址, 寄存器值, 寄存器值的掩码, 寄存器值的数据长度, 配置寄存器延时, 操作类型, 计算类型, 移动位数, 调试开关, 保存开关 */ - /* 初始化寄存器组 */ - initSeqConfig = [ - 0x7e, 0xb6, 0xff, 1, 5, 2, 0, 0, 0, 0, - 0x7e, 0x10, 0xff, 1, 5, 2, 0, 0, 0, 0 - ]; - /* 使能寄存器组 */ - enableSeqConfig = [ - 0x7e, 0x11, 0xff, 1, 5, 2, 0, 0, 0, 0, - 0x41, 0x03, 0xff, 1, 0, 2, 0, 0, 0, 0, - 0x40, 0x08, 0xff, 1, 0, 2, 0, 0, 0, 0 - ]; - /* 去使能寄存器组 */ - disableSeqConfig = [ - 0x7e, 0x10, 0xff, 1, 5, 2, 0, 0, 0, 0 - ]; - } - } - } -} -``` - -1. 加速度计传感器驱动操作接口实现 - -开发者需要根据每种类型的传感器实现归一化接口。 - -``` -/* 不使用函数暂时置空 */ -static int32_t SetAccelInfo(struct SensorBasicInfo *info) -{ - (void)info; - - return HDF_ERR_NOT_SUPPORT; -} -/* 下发使能寄存器组的配置 */ -static int32_t SetAccelEnable(void) -{ - int32_t ret; - struct AccelDrvData *drvData = AccelGetDrvData(); - - CHECK_NULL_PTR_RETURN_VALUE(drvData->accelCfg, HDF_ERR_INVALID_PARAM); - ret = SetSensorRegCfgArray(&drvData->accelCfg->busCfg, drvData->accelCfg->regCfgGroup[SENSOR_ENABLE_GROUP]); - if (ret != HDF_SUCCESS) { - HDF_LOGE("%s: accel sensor disable config failed", __func__); - return HDF_FAILURE; - } - - drvData->threadStatus = SENSOR_THREAD_RUNNING; - - return HDF_SUCCESS; -} -/* 下发去使能寄存器组的配置 */ -static int32_t SetAccelDisable(void) -{ - int32_t ret; - struct AccelDrvData *drvData = AccelGetDrvData(); - - CHECK_NULL_PTR_RETURN_VALUE(drvData->accelCfg, HDF_ERR_INVALID_PARAM); - - ret = SetSensorRegCfgArray(&drvData->accelCfg->busCfg, drvData->accelCfg->regCfgGroup[SENSOR_DISABLE_GROUP]); - if (ret != HDF_SUCCESS) { - HDF_LOGE("%s: accel sensor disable config failed", __func__); - return HDF_FAILURE; - } - - drvData->threadStatus = SENSOR_THREAD_STOPPED; - - return HDF_SUCCESS; -} -/* 配置传感器采样率和数据上报间隔 */ -static int32_t SetAccelBatch(int64_t samplingInterval, int64_t interval) -{ - (void)interval; - - struct AccelDrvData *drvData = AccelGetDrvData(); - drvData->interval = samplingInterval; - - return HDF_SUCCESS; -} -/* 设置传感器工作模式,当前支持实时模式 */ -static int32_t SetAccelMode(int32_t mode) -{ - return (mode == SENSOR_WORK_MODE_REALTIME) ? HDF_SUCCESS : HDF_FAILURE; -} -/* 设置传感器可选配置 */ -static int32_t SetAccelOption(uint32_t option) -{ - (void)option; - return HDF_ERR_NOT_SUPPORT; -} -``` - -- 差异化处理接口 - - ``` - /* 器件探测时,如果探测成功,则注册差异化处理函数到accel驱动模型里 */ - int32_t DetectAccelBim160Chip(struct SensorCfgData *data) - { - int32_t ret; - struct AccelOpsCall ops; - CHECK_NULL_PTR_RETURN_VALUE(data, HDF_ERR_INVALID_PARAM); - - if (strcmp(ACCEL_CHIP_NAME_BMI160, data->sensorAttr.chipName) != 0) { - return HDF_SUCCESS; - } - ret = InitAccelPreConfig(); - if (ret != HDF_SUCCESS) { - HDF_LOGE("%s: init BMI160 bus mux config", __func__); - return HDF_FAILURE; - } - if (DetectSensorDevice(data) != HDF_SUCCESS) { - return HDF_FAILURE; - } - - /* 差异化处理函数 */ - ops.Init = InitBmi160; - ops.ReadData = ReadBmi160Data; - ret = RegisterAccelChipOps(&ops); - if (ret != HDF_SUCCESS) { - HDF_LOGE("%s: register BMI160 accel failed", __func__); - (void)ReleaseSensorBusHandle(&data->busCfg); - return HDF_FAILURE; - } - return HDF_SUCCESS; - } - /* 初始化处理函数 */ - static int32_t InitBmi160(struct SensorCfgData *data) - { - int32_t ret; - - CHECK_NULL_PTR_RETURN_VALUE(data, HDF_ERR_INVALID_PARAM); - ret = SetSensorRegCfgArray(&data->busCfg, data->regCfgGroup[SENSOR_INIT_GROUP]); - if (ret != HDF_SUCCESS) { - HDF_LOGE("%s: bmi160 sensor init config failed", __func__); - return HDF_FAILURE; - } - return HDF_SUCCESS; - } - /* 数据处理函数 */ - int32_t ReadBmi160Data(struct SensorCfgData *data) - { - int32_t ret; - struct AccelData rawData = { 0, 0, 0 }; - int32_t tmp[ACCEL_AXIS_NUM]; - struct SensorReportEvent event; - - (void)memset_s(&event, sizeof(event), 0, sizeof(event)); - - ret = ReadBmi160RawData(data, &rawData, &event.timestamp); - if (ret != HDF_SUCCESS) { - return HDF_FAILURE; - } - - event.sensorId = SENSOR_TAG_ACCELEROMETER; - event.option = 0; - event.mode = SENSOR_WORK_MODE_REALTIME; - - rawData.x = rawData.x * BMI160_ACC_SENSITIVITY_2G; - rawData.y = rawData.y * BMI160_ACC_SENSITIVITY_2G; - rawData.z = rawData.z * BMI160_ACC_SENSITIVITY_2G; - - tmp[ACCEL_X_AXIS] = (rawData.x * SENSOR_1K_UNIT) / SENSOR_CONVERT_UNIT; - tmp[ACCEL_Y_AXIS] = (rawData.y * SENSOR_1K_UNIT) / SENSOR_CONVERT_UNIT; - tmp[ACCEL_Z_AXIS] = (rawData.z * SENSOR_1K_UNIT) / SENSOR_CONVERT_UNIT; - - event.dataLen = sizeof(tmp); - event.data = (uint8_t *)&tmp; - ret = ReportSensorEvent(&event); - return ret; - } - ``` - -- 数据处理函数 - -创建传感器定时器,按照配置的采样率定时采样,并上报给数据订阅者。 - -``` -/* 传感器定时工作线程 */ -static int32_t ReadAccelDataThreadWorker(void *arg) -{ - (void)arg; - int64_t interval; - struct AccelDrvData *drvData = AccelGetDrvData(); - - drvData->threadStatus = SENSOR_THREAD_START; - while (true) { - if (drvData->threadStatus == SENSOR_THREAD_RUNNING) { - if (drvData->ops.ReadData != NULL) { - (void)drvData->ops.ReadData(drvData->accelCfg); - } - interval = OsalDivS64(drvData->interval, (SENSOR_CONVERT_UNIT * SENSOR_CONVERT_UNIT)); - OsalMSleep(interval); - } else if (drvData->threadStatus == SENSOR_THREAD_DESTROY) { - break; - } else { - OsalMSleep(ACC_DEFAULT_SAMPLING_200_MS / SENSOR_CONVERT_UNIT / SENSOR_CONVERT_UNIT); - } - - if ((!drvData->initStatus) || (drvData->interval < 0) || drvData->threadStatus != SENSOR_THREAD_RUNNING) { - continue; - } - } - - return HDF_SUCCESS; -} -/* 创建传感器定时器和器件初始化 */ -static int32_t InitAccelConfig(void) -{ - int32_t ret; - struct AccelDrvData *drvData = AccelGetDrvData(); - - if (drvData->threadStatus != SENSOR_THREAD_NONE && drvData->threadStatus != SENSOR_THREAD_DESTROY) { - HDF_LOGE("%s: accel thread have created", __func__); - return HDF_SUCCESS; - } - - ret = CreateSensorThread(&drvData->thread, ReadAccelDataThreadWorker, "hdf_sensor_accel", drvData); - if (ret != HDF_SUCCESS) { - HDF_LOGE("%s: accel create thread failed", __func__); - drvData->threadStatus = SENSOR_THREAD_NONE; - return HDF_FAILURE; - } - - CHECK_NULL_PTR_RETURN_VALUE(drvData->ops.Init, HDF_ERR_INVALID_PARAM); - - ret = drvData->ops.Init(drvData->accelCfg); - if (ret != HDF_SUCCESS) { - HDF_LOGE("%s: accel create thread failed", __func__); - drvData->threadStatus = SENSOR_THREAD_NONE; - return HDF_FAILURE; - } - drvData->initStatus = true; - return HDF_SUCCESS; -} -``` - -- 主要的数据结构 - -``` -/* 传感器转换单位*/ -#define SENSOR_CONVERT_UNIT 1000 -#define SENSOR_1K_UNIT 1024 -/* 传感器2g对应灵敏度转换值 */ -#define BMI160_ACC_SENSITIVITY_2G 61 -/* 传感器数据采样寄存器地址 */ -#define BMI160_ACCEL_X_LSB_ADDR 0X12 -#define BMI160_ACCEL_X_MSB_ADDR 0X13 -#define BMI160_ACCEL_Y_LSB_ADDR 0X14 -#define BMI160_ACCEL_Y_MSB_ADDR 0X15 -#define BMI160_ACCEL_Z_LSB_ADDR 0X16 -#define BMI160_ACCEL_Z_MSB_ADDR 0X17 -/* 传感器数据维度 */ -enum AccelAxisNum { - ACCEL_X_AXIS = 0, - ACCEL_Y_AXIS = 1, - ACCEL_Z_AXIS = 2, - ACCEL_AXIS_NUM = 3, -}; -/* 传感器每个维度值 */ -struct AccelData { - int32_t x; - int32_t y; - int32_t z; -}; -/* 传感器私有数据结构体 */ -struct AccelDrvData { - bool detectFlag; - uint8_t threadStatus; - uint8_t initStatus; - int64_t interval; - struct SensorCfgData *accelCfg; - struct OsalThread thread; - struct AccelOpsCall ops; -}; -/* 差异化适配函数 */ -struct AccelOpsCall { - int32_t (*Init)(struct SensorCfgData *data); - int32_t (*ReadData)(struct SensorCfgData *data); -}; -``` - diff --git "a/zh-cn/device-dev/driver/\344\274\240\346\204\237\345\231\250\351\251\261\345\212\250\345\274\200\345\217\221\346\214\207\345\257\274.md" "b/zh-cn/device-dev/driver/\344\274\240\346\204\237\345\231\250\351\251\261\345\212\250\345\274\200\345\217\221\346\214\207\345\257\274.md" deleted file mode 100755 index a544f96506..0000000000 --- "a/zh-cn/device-dev/driver/\344\274\240\346\204\237\345\231\250\351\251\261\345\212\250\345\274\200\345\217\221\346\214\207\345\257\274.md" +++ /dev/null @@ -1,16 +0,0 @@ -# 传感器驱动开发指导 - -- [开发步骤](#section18816105182315) - -Sensor驱动是基于HDF框架、PLATFORM和OSAL基础接口进行开发,不区分操作系统和芯片平台,为不同Sensor器件提供统一的驱动模型。本篇开发指导以加速度计传感器为例,介绍传感器驱动开发。 - -## 开发步骤 - -1. 加速度计传感器驱动注册。HDF驱动框架会提供统一的驱动管理模型,通过加速计传感器模块配置信息,识别并加载对应模块驱动。 -2. 加速度计传感器驱动初始化和去初始化。HDF驱动框架通过init入口函数,依次启动传感器设备驱动加载和分配传感器设备数据配置资源。HDF驱动框架通过release函数,释放驱动加载的资源和配置。 -3. 加速度计传感器寄存器组配置解析。不同类型传感器需要在hcs里配置器件对应的HCS配置文件,然后再设备驱动启动过程中探测器件是否在位,然后加载对应的配置文件,生成配置的结构体对象。 -4. 加速度计传感器驱动操作接口实现。实现各个类型传感器归一化驱动接口,如init,GetInfo,Enable,Disable,SetBatch,SetMode,SetOption,ReadSensorData等函数,完成传感器驱动配置下发和数据上报功能。 - ->![](public_sys-resources/icon-note.gif) **说明:** ->传感器驱动模型已经提供一部分能力集,包括驱动设备管理能力,抽象总线和平台操作接口能力,通用配置操作接口能力,配置解析操作接口能力,接口参考[表2](传感器驱动开发概述.md#table1156812588320)。需要开发人员实现部分有:1、传感器部分操作接口([表3](传感器驱动开发概述.md#table1083014911336));2、传感器HCS差异化数据配置;3、驱动基本功能验证。 - diff --git "a/zh-cn/device-dev/driver/\344\274\240\346\204\237\345\231\250\351\251\261\345\212\250\345\274\200\345\217\221\346\246\202\350\277\260.md" "b/zh-cn/device-dev/driver/\344\274\240\346\204\237\345\231\250\351\251\261\345\212\250\345\274\200\345\217\221\346\246\202\350\277\260.md" deleted file mode 100755 index 6319a9086c..0000000000 --- "a/zh-cn/device-dev/driver/\344\274\240\346\204\237\345\231\250\351\251\261\345\212\250\345\274\200\345\217\221\346\246\202\350\277\260.md" +++ /dev/null @@ -1,244 +0,0 @@ -# 传感器驱动开发概述 - -- [简介](#section667413271505) -- [接口说明](#section7255104114110) - -## 简介 - -Sensor(传感器)驱动模块为上层Sensor服务系统提供稳定的Sensor基础能力API,包括Sensor列表查询、Sensor启停、Sensor订阅及去订阅,Sensor参数配置等功能;基于HDF(**H**ardware **D**river **F**oundation)驱动框架开发的Sensor驱动模型,实现跨操作系统迁移,器件差异配置等功能。Sensor驱动模型如下图1所示: - -**图 1** Sensor驱动模型图 -![](figures/Sensor驱动模型图.png "Sensor驱动模型图") - -Sensor驱动模型对外开放的API接口能力如下: - -- 提供Sensor HDI(**H**ardware **D**river **I**nterface)能力接口,简化服务开发。 -- 提供Sensor驱动模型能力接口:依赖HDF驱动框架实现Sensor器件驱动的注册,加载,去注册,器件探测等能力,提供同一类型Sensor器件驱动归一接口, 寄存器配置解析操作接口,总线访问抽象接口,平台抽象接口。 -- 提供开发者实现的能力接口:依赖HDF驱动框架的HCS\(**H**DF **C**onfiguration **S**ource\)配置管理,根据同类型Sensor差异化配置,实现Sensor器件参数序列化配置和器件部分操作接口,简化Sensor器件驱动开发。 - -## 接口说明 - -Sensor驱动模型对HDI开放的API接口功能,参考表1。 - -**表 1** Sensor驱动模型对外API接口功能介绍 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    功能分类

    -

    接口名

    -

    功能描述

    -

    查询操作

    -

    int32_t GetAllSensors(struct SensorInformation **sensorInfo, int32_t *count)

    -

    获取系统中注册的所有传感器信息,一种类型传感器信息包括传感器名字、设备厂商、固件版本号、硬件版本号、传感器类型编号、传感器标识、最大量程、精度、功耗。

    -

    配置操作

    -

    int32_t Enable(int32_t sensorId)

    -

    使能一种传感器设备,只有数据订阅者使能传感器后,才能获取订阅的传感器数据。

    -

    int32_t Disable(int32_t sensorId)

    -

    去使能一种传感器设备。

    -

    int32_t SetBatch(iint32_t sensorId, int64_t samplingInterval, int64_t reportInterval)

    -

    设置一种传感器的数据采样间隔和数据上报间隔。

    -

    int32_t SetMode(int32_t sensorTypeId, SensorUser *user, int32_t mode)

    -

    设置一种传感器的工作模式,不同的工作模式,上报数据方式不同。

    -

    int32_t SetOption(int32_t sensorId, uint32_t option)

    -

    设置一种传感器量程,精度等可选配置。

    -

    数据订阅操作

    -

    int32_t Register(RecordDataCallback cb)

    -

    订阅者注册传感器数据回调函数,系统会将获取到的传感器数据上报给订阅者。

    -

    int32_t Unregister(void)

    -

    订阅者去注册传感器数据回调函数。

    -

    接口实例

    -

    const struct SensorInterface *NewSensorInterfaceInstance(void)

    -

    创建传感器接口实例。

    -

    int32_t FreeSensorInterfaceInstance(void)

    -

    释放传感器接口实例。

    -
    - -Sensor驱动模型对驱动开发者开放的功能接口,驱动开发者无需实现,直接使用,参考表2: - -**表 2** Sensor驱动模型对驱动开发者开放的功能接口列表 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    功能分类

    -

    接口名

    -

    功能描述

    -

    设备管理操作接口

    -

    int32_t AddSensorDevice(const struct SensorDeviceInfo *deviceInfo)

    -

    添加当前类型的传感器设备到传感器设备管理。

    -

    int32_t DeleteSensorDevice(int32_t sensorId)

    -

    删除传感器设备管理里指定的传感器设备。

    -

    int32_t ReportSensorEvent(const struct SensorReportEvent *events)

    -

    上报指定类型传感器的数据到用户侧。

    -

    Sensor抽象总线和平台操作接口

    -

    int32_t ReadSensor(struct SensorBusCfg *busCfg, uint16_t regAddr, uint8_t *data, uint16_t dataLen)

    -

    按照配置的总线方式,读取传感器寄存器配置数据。

    -

    int32_t WriteSensor(struct SensorBusCfg *busCfg, uint8_t *writeData, uint16_t len)

    -

    按照配置的总线方式,传感器配置数据写入寄存器。

    -

    int32_t CreateSensorThread(struct OsalThread *thread, OsalThreadEntry threadEntry, char *name, void *entryPara)

    -

    创建指定传感器的定时线程,用于传感器数据上报处理。

    -

    void DestroySensorThread(struct OsalThread *thread, uint8_t *status);

    -

    销毁传感器创建的定时线程。

    -

    通用配置操作接口

    -

    int32_t SetSensorRegCfgArray(struct SensorBusCfg *busCfg, const struct SensorRegCfgGroupNode *group);

    -

    根据传感器总线类型信息,下发寄存器分组配置。

    -

    配置解析操作接口

    -

    -

    int32_t GetSensorBaseConfigData(const struct DeviceResourceNode *node, struct SensorCfgData *config)

    -

    根据传感器设备HCS资源配置,获取传感器信息,总线配置信息,属性配置等基本配置信息,并初始化对应的基本配置数据结构体。

    -

    int32_t ParseSensorRegConfig(struct SensorCfgData *config)

    -

    根据传感器设备HCS资源配置,解析寄存器分组信息,并初始化配置数据结构体。

    -

    void ReleaseSensorAllRegConfig(struct SensorCfgData *config)

    -

    释放传感器配置数据结构体里分配的资源。

    -

    int32_t GetSensorBusHandle(struct SensorBusCfg *busCfg)

    -

    获取传感器总线句柄信息。

    -

    int32_t ReleaseSensorBusHandle(struct SensorBusCfg *busCfg)

    -

    释放传感器句柄信息。

    -
    - -Sensor驱动模型要求驱动开发者实现的接口功能,参考表3 - -**表 3** Sensor驱动模型要求驱动开发者实现的接口列表 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    功能分类

    -

    接口名

    -

    功能描述

    -

    基本功能操作

    -

    int32_t init(void)

    -

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

    -

    int32_t GetInfo(struct SensorBasicInfo *info)

    -

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

    -

    int32_t Enable(void)

    -

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

    -

    int32_t Disable(void)

    -

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

    -

    int32_t SetBatch(int64_t samplingInterval, int64_t reportInterval)

    -

    根据数据采样率和数据上报间隔,配置当前传感器设备的数据上报线程处理时间。

    -

    int32_t SetMode(int32_t mode)

    -

    配置当前传感器设备数据上报方式。

    -

    int32_t SetOption(uint32_t option)

    -

    根据可选配置,下发量程,精度等寄存器配置。

    -

    void ReadSensorData(void)

    -

    实现传感器的数据读取函数。

    -
    - -接口实现参考[SENSOR](传感器驱动开发实例.md)章节。 - diff --git "a/zh-cn/device-dev/driver/\344\274\240\346\204\237\345\231\250\351\251\261\345\212\250\346\265\213\350\257\225\346\214\207\345\257\274.md" "b/zh-cn/device-dev/driver/\344\274\240\346\204\237\345\231\250\351\251\261\345\212\250\346\265\213\350\257\225\346\214\207\345\257\274.md" deleted file mode 100755 index 7bf5125160..0000000000 --- "a/zh-cn/device-dev/driver/\344\274\240\346\204\237\345\231\250\351\251\261\345\212\250\346\265\213\350\257\225\346\214\207\345\257\274.md" +++ /dev/null @@ -1,82 +0,0 @@ -# 传感器驱动测试指导 - -驱动开发完成后,在传感器单元测试里面开发自测试用例,验证驱动基本功能。测试环境采用开发者自测试平台。 - -``` -/* 标识是否上报传感器数据 */ -static int32_t g_sensorDataFlag = 0; -/* 保持获取的传感器接口实例地址 */ -static const struct SensorInterface *g_sensorDev = nullptr; - -/* 订阅者注册数据上报函数 */ -static int SensorTestDataCallback(struct SensorEvents *event) -{ - if (event == nullptr) { - return -1; - } - float *data = (float*)event->data; - printf("time [%lld] sensor id [%d] x-[%f] y-[%f] z-[%f]\n\r", event->timestamp, - event->sensorId, (*data), *(data + 1), *(data + g_axisZ)); - if (*data > 1e-5) { - g_sensorDataFlag = 1; - } - return 0; -} -/* 用例执行前,初始化传感器接口实例 */ -void HdfSensorTest::SetUpTestCase() -{ - g_sensorDev = NewSensorInterfaceInstance(); - if (g_sensorDev == nullptr) { - printf("test sensorHdi get Module instace failed\n\r"); - } -} -/* 用例资源释放 */ -void HdfSensorTest::TearDownTestCase() -{ - if (g_sensorDev != nullptr) { - FreeSensorInterfaceInstance(); - g_sensorDev = nullptr; - } -} -/* 传感器驱动测试验证 */ -HWTEST_F(HdfSensorTest,TestAccelDriver_001, TestSize.Level0) -{ - int32_t sensorInterval = 1000000000; /* 数据采样率单位纳秒 */ - int32_t pollTime = 5; /* 数据采样时间单位秒 */ - int32_t accelSensorId = 1; /* 加速度传感器类型标识为1 */ - int32_t count = 0; - int ret; - struct SensorInformation *sensorInfo = nullptr; - - ret = g_sensorDev->Register(SensorTestDataCallback) - EXPECT_EQ(SENSOR_NULL_PTR, ret); - - ret = g_sensorDev->GetAllSensors(&sensorInfo, &count); - EXPECT_EQ(0, ret); - if (sensorInfo == nullptr) { - EXPECT_NE(nullptr, sensorInfo); - return; - } - /* 打印获取的传感器列表 */ - for (int i = 0; i < count; i++) { - printf("get sensoriId[%d], info name[%s]\n\r", sensorInfo[i]->sensorId, sensorInfo[i]->sensorName); - } - ret = g_sensorDev->Enable(accelSensorId); - EXPECT_EQ(0, ret); - g_sensorDataFlag = 0; - - ret = g_sensorDev->SetBatch(accelSensorId, sensorInterval, pollTime); - EXPECT_EQ(0, ret); - /* 在时间pollTime内,观察输出打印数据 */ - OsalSleep(pollTime); - EXPECT_EQ(1, g_sensorDataFlag); - - ret = g_sensorDev->Disable(accelSensorId); - g_sensorDataFlag = 0; - EXPECT_EQ(0, ret); - - ret = g_sensorDev->Unregister(); - EXPECT_EQ(0, ret); -} -``` - diff --git "a/zh-cn/device-dev/driver/\345\244\226\350\256\276.md" "b/zh-cn/device-dev/driver/\345\244\226\350\256\276.md" deleted file mode 100755 index 26824613db..0000000000 --- "a/zh-cn/device-dev/driver/\345\244\226\350\256\276.md" +++ /dev/null @@ -1,11 +0,0 @@ -# 外设 - -- **[LCD](LCD.md)** - -- **[TOUCHSCREEN](TOUCHSCREEN.md)** - -- **[SENSOR](SENSOR.md)** - -- **[WLAN](WLAN.md)** - - diff --git "a/zh-cn/device-dev/driver/\347\234\213\351\227\250\347\213\227\344\275\277\347\224\250\345\256\236\344\276\213.md" "b/zh-cn/device-dev/driver/\347\234\213\351\227\250\347\213\227\344\275\277\347\224\250\345\256\236\344\276\213.md" deleted file mode 100755 index b8d64e53b7..0000000000 --- "a/zh-cn/device-dev/driver/\347\234\213\351\227\250\347\213\227\344\275\277\347\224\250\345\256\236\344\276\213.md" +++ /dev/null @@ -1,86 +0,0 @@ -# 看门狗使用实例 - -本例程提供看门狗的完整使用流程。 - -在本例程中,我们打开一个看门狗设备,设置超时时间并启动计时: - -- 首先定期喂狗,即按时清除看门狗定时器,确保系统不会因定时器超时而复位。 -- 接着再停止喂狗,观察定时器到期后系统是否发生复位行为。 - -示例如下: - -``` -#include "watchdog_if.h" -#include "hdf_log.h" -#include "osal_irq.h" -#include "osal_time.h" - -#define WATCHDOG_TEST_TIMEOUT 2 -#define WATCHDOG_TEST_FEED_TIME 6 - -static int32_t TestCaseWatchdog(void) -{ - int32_t i; - int32_t ret; - uint32_t timeout; - DevHandle handle = NULL; - - /* 打开0号看门狗设备 */ - handle = WatchdogOpen(0); - if (handle == NULL) { - HDF_LOGE("Open watchdog fail!"); - return -1; - } - - /* 设置超时时间 */ - ret = WatchdogSetTimeout(handle, WATCHDOG_TEST_TIMEOUT); - if (ret != HDF_SUCCESS) { - HDF_LOGE("%s: set timeout fail! ret:%d\n", __func__, ret); - WatchdogClose(handle); - return ret; - } - - /* 回读设置的超时时间值 */ - ret = WatchdogGetTimeout(handle, &timeout); - if (ret != HDF_SUCCESS) { - HDF_LOGE("%s: get timeout fail! ret:%d\n", __func__, ret); - WatchdogClose(handle); - return ret; - } - HDF_LOGI("%s: read timeout back:%u\n", __func__, timeout); - - /* 启动看门狗,开始计时 */ - ret = WatchdogStart(handle); - if (ret != HDF_SUCCESS) { - HDF_LOGE("%s: satrt fail! ret:%d\n", __func__, ret); - WatchdogClose(handle); - return ret; - } - - /* 每隔1S喂狗一次 */ - for (i = 0; i < WATCHDOG_TEST_FEED_TIME; i++) { - HDF_LOGE("%s: feeding watchdog %d times... \n", __func__, i); - ret = WatchdogFeed(handle); - if (ret != HDF_SUCCESS) { - HDF_LOGE("%s: feed dog fail! ret:%d\n", __func__, ret); - WatchdogClose(handle); - return ret; - } - OsalSleep(1); - } - /* 由于喂狗间隔小于超时时间,系统不会发生复位,此日志可以正常打印 */ - HDF_LOGE("%s: no reset ... feeding test OK!!!\n", __func__); - - /* 接下来持续不喂狗,使得看门狗计时器超时 */ - for (i = 0; i < WATCHDOG_TEST_FEED_TIME; i++) { - HDF_LOGE("%s: watiting dog buck %d times... \n", __func__, i); - OsalSleep(1); - } - - /* 当不喂狗时间到达之前设定的超时时间的时候,系统会发生复位,理论上观察不到此日志的打印 */ - HDF_LOGE("%s: dog has't buck!!! \n", __func__, i); - WatchdogClose(handle); - return -1; -} -``` - diff --git "a/zh-cn/device-dev/driver/\347\234\213\351\227\250\347\213\227\344\275\277\347\224\250\346\214\207\345\257\274.md" "b/zh-cn/device-dev/driver/\347\234\213\351\227\250\347\213\227\344\275\277\347\224\250\346\214\207\345\257\274.md" deleted file mode 100755 index b8fd5753d4..0000000000 --- "a/zh-cn/device-dev/driver/\347\234\213\351\227\250\347\213\227\344\275\277\347\224\250\346\214\207\345\257\274.md" +++ /dev/null @@ -1,391 +0,0 @@ -# 看门狗使用指导 - -- [使用流程](#section0719414187) -- [打开看门狗设备](#section198171379261) -- [获取看门狗状态](#section206592910275) -- [设置超时时间](#section19605128182714) -- [获取超时时间](#section11111516208) -- [启动看门狗](#section141174192814) -- [喂狗](#section179101435113910) -- [停止看门狗](#section15282123192816) -- [关闭看门狗设备](#section7857850173411) - -## 使用流程 - -使用看门狗的一般流程如[图1](#fig19134125410189)所示。 - -**图 1** 看门狗使用流程图 - - -![](figures/zh-cn_image_0000001057622716.png) - -## 打开看门狗设备 - -在操作看门狗之前,需要使用WatchdogOpen打开一个看门狗设备,一个系统可能有多个看门狗,通过ID号来打开指定的看门狗设备: - -int32\_t WatchdogOpen\(int16\_t wdtId\); - -**表 1** WatchdogOpen参数和返回值描述 - - - - - - - - - - - - - - - - - - - -

    参数

    -

    参数描述

    -

    wdtId

    -

    看门狗设备号

    -

    返回值

    -

    返回值描述

    -

    NULL

    -

    打开失败

    -

    DevHandle类型指针

    -

    看门狗设备句柄

    -
    - -``` -DevHandle handle = NULL; -handle = WatchdogOpen(0); /* 打开0号看门狗设备 */ -if (handle == NULL) { - HDF_LOGE("WatchdogOpen: failed, ret %d\n", ret); - return; -} -``` - -## 获取看门狗状态 - -int32\_t WatchdogGetStatus\(DevHandle handle, int32\_t \*status\); - -**表 2** WatchdogGetStatus参数和返回值描述 - - - - - - - - - - - - - - - - - - - - - - -

    参数

    -

    参数描述

    -

    handle

    -

    看门狗设备句柄

    -

    status

    -

    获取到的启动状态指针

    -

    返回值

    -

    返回值描述

    -

    0

    -

    获取成功

    -

    负数

    -

    获取失败

    -
    - -``` -int32_t ret; -int32_t status; -/* 获取Watchdog启动状态 */ -ret = WatchdogGetStatus(handle, &status); -if (ret != 0) { - HDF_LOGE("WatchdogGetStatus: failed, ret %d\n", ret); - return; -} -``` - -## 设置超时时间 - -int32\_t WatchdogSetTimeout\(PalHandle \*handle, uint32\_t seconds\); - -**表 3** WatchdogSetTimeout参数和返回值描述 - - - - - - - - - - - - - - - - - - - - - - -

    参数

    -

    参数描述

    -

    handle

    -

    看门狗设备句柄

    -

    seconds

    -

    超时时间,单位为秒

    -

    返回值

    -

    返回值描述

    -

    0

    -

    设置成功

    -

    负数

    -

    设置失败

    -
    - -``` -int32_t ret; -uint32_t timeOut = 60; -/* 设置超时时间,单位:秒 */ -ret = WatchdogSetTimeout(handle, timeOut); -if (ret != 0) { - HDF_LOGE("WatchdogSetTimeout: failed, ret %d\n", ret); - return; -} -``` - -## 获取超时时间 - -int32\_t WatchdogGetTimeout\(PalHandle \*handle, uint32\_t \*seconds\); - -**表 4** WatchdogGetTimeout参数和返回值描述 - - - - - - - - - - - - - - - - - - - - - - -

    参数

    -

    参数描述

    -

    handle

    -

    看门狗设备句柄

    -

    seconds

    -

    接收超时时间的指针,单位为秒

    -

    返回值

    -

    返回值描述

    -

    0

    -

    获取成功

    -

    负数

    -

    获取失败

    -
    - -``` -int32_t ret; -uint32_t timeOut; -/* 获取超时时间,单位:秒 */ -ret = WatchdogGetTimeout(handle, &timeOut); -if (ret != 0) { - HDF_LOGE("WatchdogGetTimeout: failed, ret %d\n", ret); - return; -} -``` - -## 启动看门狗 - -int32\_t WatchdogStart\(DevHandle handle\); - -**表 5** WatchdogStart参数和返回值描述 - - - - - - - - - - - - - - - - - - - -

    参数

    -

    参数描述

    -

    handle

    -

    看门狗设备句柄

    -

    返回值

    -

    返回值描述

    -

    0

    -

    启动成功

    -

    负数

    -

    启动失败

    -
    - -``` -int32_t ret; -/* 启动看门狗 */ -ret = WatchdogStart(handle); -if (ret != 0) { - HDF_LOGE("WatchdogStart: failed, ret %d\n", ret); - return; -} -``` - -## 喂狗 - -int32\_t WatchdogFeed\(DevHandle handle\); - -**表 6** WatchdogFeed参数和返回值描述 - - - - - - - - - - - - - - - - - - - -

    参数

    -

    参数描述

    -

    handle

    -

    看门狗设备句柄

    -

    返回值

    -

    返回值描述

    -

    0

    -

    喂狗成功

    -

    负数

    -

    喂狗失败

    -
    - -``` -int32_t ret; -/* 喂狗 */ -ret = WatchdogFeed(handle); -if (ret != 0) { - HDF_LOGE("WatchdogFeed: failed, ret %d\n", ret); - return; -} -``` - -## 停止看门狗 - -int32\_t WatchdogStop\(DevHandle handle\); - -**表 7** WatchdogStop参数和返回值描述 - - - - - - - - - - - - - - - - - - - -

    参数

    -

    参数描述

    -

    handle

    -

    看门狗设备句柄

    -

    返回值

    -

    返回值描述

    -

    0

    -

    停止成功

    -

    负数

    -

    停止失败

    -
    - -``` -int32_t ret; -/* 停止看门狗 */ -ret = WatchdogStop(handle); -if (ret != 0) { - HDF_LOGE("WatchdogStop: failed, ret %d\n", ret); - return; -} - -``` - -## 关闭看门狗设备 - -当操作完毕时,使用WatchdogClose关闭打开的设备句柄: - -void WatchdogClose\(DevHandle handle\); - -**表 8** WatchdogClose参数和返回值描述 - - - - - - - - - - -

    参数

    -

    参数描述

    -

    handle

    -

    看门狗设备句柄

    -
    - -``` -/* 关闭看门狗 */ -ret = WatchdogClose(handle); -``` - diff --git "a/zh-cn/device-dev/driver/\347\234\213\351\227\250\347\213\227\346\246\202\350\277\260.md" "b/zh-cn/device-dev/driver/\347\234\213\351\227\250\347\213\227\346\246\202\350\277\260.md" deleted file mode 100755 index 467e21ba08..0000000000 --- "a/zh-cn/device-dev/driver/\347\234\213\351\227\250\347\213\227\346\246\202\350\277\260.md" +++ /dev/null @@ -1,78 +0,0 @@ -# 看门狗概述 - -- [简介](#section3579126111816) -- [接口说明](#section17429111981812) - -## 简介 - -看门狗(watchdog),又叫看门狗计时器(watchdog timer),是一种硬件的计时设备,当系统的主程序发生某些错误时,导致未及时清除看门狗计时器的计时值,这时看门狗计时器就会对系统发出复位信号,使系统从悬停状态恢复到正常运作状态。 - -## 接口说明 - -**表 1** 看门狗 API接口功能介绍 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    功能分类

    -

    接口名

    -

    描述

    -

    打开/关闭看门狗

    -

    WatchdogOpen

    -

    打开看门狗设备

    -

    WatchdogClose

    -

    关闭看门狗设备

    -

    启动/停止看门狗

    -

    WatchdogStart

    -

    启动看门狗

    -

    WatchdogStop

    -

    停止看门狗

    -

    设置/获取超时时间

    -

    WatchdogSetTimeout

    -

    设置看门狗超时时间

    -

    WatchdogGetTimeout

    -

    获取看门狗超时时间

    -

    获取看门狗状态

    -

    WatchdogGetStatus

    -

    获取看门狗状态

    -

    清除看门狗定时器

    -

    WatchdogFeed

    -

    清除看门狗定时器(喂狗)

    -
    - ->![](public_sys-resources/icon-note.gif) **说明:** ->本文涉及看门狗的所有接口,仅限内核态使用,不支持在用户态使用。 - diff --git "a/zh-cn/device-dev/driver/\351\205\215\347\275\256\347\256\241\347\220\206.md" "b/zh-cn/device-dev/driver/\351\205\215\347\275\256\347\256\241\347\220\206.md" deleted file mode 100755 index 3fd2a0701a..0000000000 --- "a/zh-cn/device-dev/driver/\351\205\215\347\275\256\347\256\241\347\220\206.md" +++ /dev/null @@ -1,437 +0,0 @@ -# 配置管理 - -- [配置概述](#section59914284576) -- [配置语法](#section533713333580) -- [关键字](#section1316625413586) -- [基本结构](#section173481622115918) -- [数据类型](#section96521601302) -- [预处理](#section8164295515) -- [注释](#section0338205819610) -- [引用修改](#section179799204716) -- [节点复制](#section382424014712) -- [删除](#section165211112586) -- [属性引用](#section192841514490) -- [模板](#section520134294) -- [配置生成](#section106152531919) -- [hc-gen介绍](#section8260625101012) - -## 配置概述 - -HCS\(**H**DF **C**onfiguration **S**ource\)是HDF驱动框架的配置描述源码,内容以Key-Value为主要形式。它实现了配置代码与驱动代码解耦,便于开发者进行配置管理。 - -HC-GEN**\(H**DF **C**onfiguration **G**enerator**\)**是HCS配置转换工具,可以将HDF配置文件转换为软件可读取的文件格式: - -- 在弱性能环境中,转换为配置树源码,驱动可直接调用C代码获取配置。 -- 在高性能环境中,转换为HCB\(**H**DF **C**onfiguration **B**inary\)二进制文件,驱动可使用HDF框架提供的配置解析接口获取配置。 - -以下是使用HCB模式的典型应用场景: - -**图 1** 配置使用流程图 - - -![](figures/zh-cn_image_0000001053405727.png) - -HCS经过HC-GEN编译生成HCB文件,HDF驱动框架中的HCS Parser模块会从HCB文件中重建配置树,HDF驱动模块使用HCS Parser提供的配置读取接口获取配置内容。 - -## 配置语法 - -HCS的语法介绍如下: - -## 关键字 - -HCS配置语法保留了以下关键字。 - -**表 1** HCS配置语法保留关键字 - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    关键字

    -

    用途

    -

    说明

    -

    root

    -

    配置根节点

    -

    -

    -

    include

    -

    引用其他HCS配置文件

    -

    -

    -

    delete

    -

    删除节点或属性

    -

    只能用于操作include导入的配置树

    -

    template

    -

    定义模板节点

    -

    -

    -

    match_attr

    -

    用于标记节点的匹配查找属性

    -

    解析配置时可以使用该属性的值查找到对应节点

    -
    - -## 基本结构 - -HCS主要分为属性\(Attribute\)和节点\(Node\)两种结构。 - -**属性** - -属性即最小的配置单元,是一个独立的配置项。语法如下: - -``` - attribute_name = value; -``` - -- attribute\_name 是**字母、数字、下划线**的组合且必须以字母或下划线开头,字母区分大小写。 - -- value的可用格式如下: - - - 数字常量,支持二进制、八进制、十进制、十六进制数,具体参考数据类型节。 - - - 字符串,内容使用双引号\(""\)引用。 - - - 节点引用。 - - -- attribute 必须以分号\(;\)结束且必须属于一个node。 - - -**节点** - -节点是一组属性的集合,语法如下: - -``` - node_name { - module = "sample"; - ... - } -``` - -- node\_name 是**字母、数字、下划线**的组合且必须以字母或下划线开头,字母区分大小写。 - -- 大括号后无需添加结束符“;”。 - -- root为保留关键字,用于声明配置表的根节点。每个配置表必须以root节点开始。 - -- root节点中必须包含module属性,其值应该为一个字符串,用于表征该配置所属模块。 - -- 节点中可以增加match\_attr属性,其值为一个全局唯一的字符串。在解析配置时可以调用查找接口以该属性的值查找到包含该属性的节点。 - -## 数据类型 - -在属性定义中使用自动数据类型,不显式指定类型,属性支持的数据类型如下: - -**整型** - -整型长度自动推断,根据实际数据长度给与最小空间占用的类型。 - -- 二进制,0b前缀,示例:0b1010。 - -- 八进制,0前缀,示例:0664。 -- 十进制 ,无前缀,且支持有符号与无符号,示例:1024,+1024均合法。负值在读取时注意使用有符号数读取接口。 - -- 十六进制,0x前缀,示例:0xff00、0xFF。 - - -**字符串** - -字符串使用双引号\(""\)表示。 - -**数组** - -数组元素支持整型、字符串,不支持混合类型。整型数组中uint32\_t uint64\_t混用会向上转型为uint64\_t 数组。整型数组与字符串数组示例如下: - -``` -attr_foo = [0x01, 0x02, 0x03, 0x04]; -attr_bar = ["hello", "world"]; -``` - -**bool类型** - -bool类型中**true**表示真,**false**表示假。 - -## 预处理 - -**include** - -用于导入其他HCS文件。语法示例如下: - -``` -#include "foo.hcs" -#include "../bar.hcs" -``` - -- 文件名必须使用双引号\(""\),不在同一目录使用相对路径引用。被include文件也必须是合法的HCS文件。 -- 多个include,如果存在相同的节点,后者覆盖前者,其余的节点依次展开。 - -## 注释 - -支持两种注释风格。 - -- 单行注释。 - - ``` - // comment - ``` - -- 多行注释。 - - ``` - /* - comment - */ - ``` - - >![](public_sys-resources/icon-note.gif) **说明:** - >多行注释不支持嵌套。 - - -## 引用修改 - -引用修改可以实现修改另外任意一个节点的内容,语法为: - -``` - node :& source_node -``` - -上述语句表示node中的内容是对source\_node节点内容的修改。示例如下: - -``` -root { - module = "sample"; - foo { - foo_ :& root.bar{ - attr = "foo"; - } - foo1 :& foo2 { - attr = 0x2; - } - foo2 { - attr = 0x1; - } - } - - bar { - attr = "bar"; - } -} -``` - -最终生成配置树为: - -``` -root { - module = "sample"; - foo { - foo2 { - attr = 0x2; - } - } - bar { - attr = "foo"; - } -} -``` - -在以上示例中,可以看到foo.foo\_节点通过引用将bar.attr属性的值修改为了"foo",foo.foo1节点通过引用将foo.foo2.attr属性的值修改为了0x2。foo.foo\_以及foo.foo1节点表示对目标节点内容的修改,其自身并不会存在最终生成的配置树中。 - -- 引用同级node,可以直接使用node名称,否则被引用的节点必须使用绝对路径,节点间使用“.”分隔,root表示根节点,格式为root开始的节点路径序列,例如root.foo.bar即为一个合法的绝对路径。 -- 如果出现修改冲突(即多处修改同一个属性),编译器将提示warning,因为这种情况下只会生效某一个修改而导致最终结果不确定。 - -## 节点复制 - -节点复制可以实现在节点定义时从另一个节点先复制内容,用于定义内容相似的节点。语法为: - -``` - node : source_node -``` - -上述语句表示在定义"node"节点时将另一个节点"source\_node"的属性复制过来。示例如下: - -``` -root { - module = "sample"; - foo { - attr_0 = 0x0; - } - bar:foo { - attr_1 = 0x1; - } -} -``` - -上述代码的最终生成配置树为: - -``` -root { - module = "sample"; - foo { - attr_0 = 0x0; - } - bar { - attr_1 = 0x1; - attr_0 = 0x0; - } -} -``` - -在上述示例中,编译后bar节点即包含attr\_0属性也包含attr\_1属性,在bar中对attr\_0的修改不会影响到foo。 - -在foo和bar在同级node中可不指定foo的路径,否则需要使用绝对路径引用,参考[引用修改](#section179799204716)。 - -## 删除 - -要对include导入的base配置树中不需要的节点或属性进行删除,可以使用delete关键字。下面的举例中sample1.hcs通过include导入了sample2.hcs中的配置内容,并使用delete删除了sample2.hcs中的attribute2属性和foo\_2节点,示例如下: - -``` -// sample2.hcs -root { - attr_1 = 0x1; - attr_2 = 0x2; - foo_2 { - t = 0x1; - } -} - -// sample1.hcs -#include "sample2.hcs" -root { - attr_2 = delete; - foo_2 : delete { - } -} -``` - -上述代码在生成过程中将会删除root.foo\_2节点与attr\_2,最终生成配置树为: - -``` -root { - attr_1 = 0x1; -} -``` - ->![](public_sys-resources/icon-note.gif) **说明:** ->在同一个HCS文件中不允许使用delete,建议直接删除不需要的属性。 - -## 属性引用 - -为了在解析配置时快速定位到关联的节点,可以把节点作为属性的右值,通过读取属性查找到对应节点。语法为: - -``` - attribute = &node; -``` - -上述语句表示attribute的值是一个节点node的引用,在解析时可以用这个attribute快速定位到node,便于关联和查询其他node。示例如下: - -``` -node1 { - attributes; -} - -node2 { - attr_1 = &node1; -} -``` - -## 模板 - -模板的用途在于生成严格一致的node结构,以便对同类型node进行遍历和管理。 - -使用template关键字定义模板node,子node通过双冒号“::”声明继承关系。子节点可以改写但不能新增和删除template中的属性,子节点中没有定义的属性将使用template中的定义作为默认值。示例如下: - -``` -root { - module = "sample"; - template foo { - attr_1 = 0x1; - attr_2 = 0x2; - } - - bar :: foo { - } - - bar_1 :: foo { - attr_1 = 0x2; - } -} -``` - -生成配置树如下: - -``` -root { - module = "sample"; - bar { - attr_1 = 0x1; - attr_2 = 0x2; - } - bar_1 { - attr_1 = 0x2; - attr_2 = 0x2; - } -} -``` - -在上述示例中,bar和bar\_1节点继承了foo节点,生成配置树节点结构与foo保持了完全一致,只是属性的值不同。 - -## 配置生成 - -hc-gen是配置生成的工具,可以对HCS配置语法进行检查并把HCS源文件转化成HCB二进制文件。 - -## hc-gen介绍 - -hc-gen参数说明: - -``` -Usage: hc-gen [Options] [File] -options: - -o output file name, default same as input - -a hcb align with four bytes - -b output binary output, default enable - -t output config in C language source file style - -i output binary hex dump in C language source file style - -p prefix of generated symbol name - -d decompile hcb to hcs - -V show verbose info - -v show version - -h show this help message -``` - -生成.c/.h 配置文件方法: - -``` -hc-gen -o [OutputCFileName] -t [SourceHcsFileName] -``` - -生成HCB 配置文件方法: - -``` -hc-gen -o [OutputHcbFileName] -b [SourceHcsFileName] -``` - -反编译HCB文件为HCS方法: - -``` -hc-gen -o [OutputHcsFileName] -d [SourceHcbFileName] -``` - diff --git "a/zh-cn/device-dev/driver/\351\251\261\345\212\250\345\271\263\345\217\260.md" "b/zh-cn/device-dev/driver/\351\251\261\345\212\250\345\271\263\345\217\260.md" deleted file mode 100755 index 7d5a5437f7..0000000000 --- "a/zh-cn/device-dev/driver/\351\251\261\345\212\250\345\271\263\345\217\260.md" +++ /dev/null @@ -1,19 +0,0 @@ -# 驱动平台 - -- **[GPIO](GPIO.md)** - -- **[I2C](I2C.md)** - -- **[RTC](RTC.md)** - -- **[SDIO](SDIO.md)** - -- **[SPI](SPI.md)** - -- **[UART](UART.md)** - -- **[WATCHDOG](WATCHDOG.md)** - -- **[MIPI DSI](MIPI-DSI.md)** - - diff --git "a/zh-cn/device-dev/driver/\351\251\261\345\212\250\345\274\200\345\217\221.md" "b/zh-cn/device-dev/driver/\351\251\261\345\212\250\345\274\200\345\217\221.md" deleted file mode 100755 index e35139db59..0000000000 --- "a/zh-cn/device-dev/driver/\351\251\261\345\212\250\345\274\200\345\217\221.md" +++ /dev/null @@ -1,175 +0,0 @@ -# 驱动开发 - -- [驱动模型介绍](#section157425168112) -- [驱动开发步骤](#section1969312275533) - -## 驱动模型介绍 - -HDF框架以组件化的驱动模型作为核心设计思路,为开发者提供更精细化的驱动管理,让驱动开发和部署更加规范。HDF框架将一类设备驱动放在同一个host里面,开发者也可以将驱动功能分层独立开发和部署,支持一个驱动多个node,HDF框架管理驱动模型如下图所示: - -**图 1** HDF框架管理驱动模型 - - -![](figures/zh-cn_image_0000001054564784.png) - -## 驱动开发步骤 - -基于HDF框架进行驱动的开发主要分为两个部分,驱动实现和驱动配置,详细开发流程如下所示: - -1. 驱动实现 - - 驱动实现包含驱动业务代码和驱动入口注册,具体写法如下: - - - 驱动业务代码 - - ``` - #include "hdf_device_desc.h" // HDF框架对驱动开放相关能力接口的头文件 - #include "hdf_log.h" // HDF 框架提供的日志接口头文件 - - #define HDF_LOG_TAG "sample_driver" // 打印日志所包含的标签,如果不定义则用默认定义的HDF_TAG标签 - - //驱动对外提供的服务能力,将相关的服务接口绑定到HDF框架 - int32_t HdfSampleDriverBind(struct HdfDeviceObject *deviceObject) - { - HDF_LOGD("Sample driver bind success"); - return 0; - } - - // 驱动自身业务初始的接口 - int32_t HdfSampleDriverInit(struct HdfDeviceObject *deviceObject) - { - HDF_LOGD("Sample driver Init success"); - return 0; - } - - // 驱动资源释放的接口 - void HdfSampleDriverRelease(struct HdfDeviceObject *deviceObject) - { - HDF_LOGD("Sample driver release success"); - return; - } - ``` - - - 驱动入口注册到HDF框架 - - ``` - // 定义驱动入口的对象,必须为HdfDriverEntry(在hdf_device_desc.h中定义)类型的全局变量 - struct HdfDriverEntry g_sampleDriverEntry = { - .moduleVersion = 1, - .moduleName = "sample_driver", - .Bind = HdfSampleDriverBind, - .Init = HdfSampleDriverInit, - .Release = HdfSampleDriverRelease, - }; - - // 调用HDF_INIT将驱动入口注册到HDF框架中,在加载驱动时HDF框架会先调用Bind函数,再调用Init函数加载该驱动,当Init调用异常时,HDF框架会调用Release释放驱动资源并退出。 - HDF_INIT(g_sampleDriverEntry); - ``` - - -2. 驱动编译 - - 驱动代码的编译必须要使用HDF框架提供的Makefile模板进行编译。 - - ``` - include $(LITEOSTOPDIR)/../../drivers/adapter/lite/khdf/lite.mk #导入hdf预定义内容,必需 - MODULE_NAME := #生成的结果文件 - LOCAL_INCLUDE := #本驱动的头文件目录 - LOCAL_SRCS := #本驱动的源代码文件 - LOCAL_CFLAGS := #自定义的编译选项 - include $(HDF_DRIVER) #导入模板makefile完成编译 - ``` - - - 编译结果文件链接到内核镜像,添加到vendor目录下的hdf\_vendor.mk里面,示例如下: - - ``` - LITEOS_BASELIB += -lxxx #链接生成的静态库 - LIB_SUBDIRS += #驱动代码Makefile的目录 - ``` - - -3. 驱动配置 - - HDF使用HCS作为配置描述源码,HCS详细介绍参考[配置管理](配置管理.md)介绍。 - - 驱动配置包含两部分,HDF框架定义的驱动设备描述和驱动的私有配置信息,具体写法如下: - - - 驱动设备描述(必选) - - HDF框架加载驱动所需要的信息来源于HDF框架定义的驱动设备描述,因此基于HDF框架开发的驱动必须要在HDF框架定义的device\_info.hcs配置文件中添加对应的设备描述,驱动的设备描述填写如下所示: - - ``` - root { - device_info { - match_attr = "hdf_manager"; - template host { // host模板,继承该模板的节点(如下sample_host)如果使用模板中的默认值,则节点字段可以缺省 - hostName = ""; - priority = 100; - template device { - template deviceNode { - policy = 0; - priority = 100; - preload = 0; - permission = 0664; - moduleName = ""; - serviceName = ""; - deviceMatchAttr = ""; - } - } - } - sample_host :: host{ - hostName = "host0"; // host名称,host节点是用来存放某一类驱动的容器 - priority = 100; // host启动优先级(0-200),值越大优先级越低,建议默认配100,优先级相同则不保证host的加载顺序 - device_sample :: device { // sample设备节点 - device0 :: deviceNode { // sample驱动的DeviceNode节点 - policy = 1; // policy字段是驱动服务发布的策略,在驱动服务管理章节有详细介绍 - priority = 100; // 驱动启动优先级(0-200),值越大优先级越低,建议默认配100,优先级相同则不保证device的加载顺序 - preload = 0; // 驱动按需加载字段,在本章节最后的说明有详细介绍 - permission = 0664; // 驱动创建设备节点权限 - moduleName = "sample_driver"; // 驱动名称,该字段的值必须和驱动入口结构的moduleName值一致 - serviceName = "sample_service"; // 驱动对外发布服务的名称,必须唯一 - deviceMatchAttr = "sample_config"; // 驱动私有数据匹配的关键字,必须和驱动私有数据配置表中的match_attr值相等 - } - } - } - } - } - ``` - - - 驱动私有配置信息(可选) - - 如果驱动有私有配置,则可以添加一个驱动的配置文件,用来填写一些驱动的默认配置信息,HDF框架在加载驱动的时候,会将对应的配置信息获取并保存在HdfDeviceObject 中的property里面,通过Bind和Init(参考[驱动开发](#li35182436435))传递给驱动,驱动的配置信息示例如下: - - ``` - root { - SampleDriverConfig { - sample_version = 1; - sample_bus = "I2C_0"; - match_attr = "sample_config"; //该字段的值必须和device_info.hcs中的deviceMatchAttr值一致 - } - } - ``` - - 配置信息定义之后,需要将该配置文件添加到板级配置入口文件hdf.hcs(这一块可以通过OpenHarmony驱动子系统在DevEco集成驱动开发套件工具一键式配置,具体使用方法参考驱动开发套件中的介绍),示例如下: - - ``` - #include "device_info/device_info.hcs" - #include "sample/sample_config.hcs" - ``` - - - ->![](public_sys-resources/icon-note.gif) **说明:** ->驱动加载方式支持按需加载和按序加载两种方式,具体使用方法如下: ->- 按需加载 -> ``` -> typedef enum { -> DEVICE_PRELOAD_ENABLE = 0, -> DEVICE_PRELOAD_ENABLE_STEP2, -> DEVICE_PRELOAD_DISABLE, -> DEVICE_PRELOAD_INVALID -> } DevicePreload; -> ``` -> 配置文件中preload 字段配成 0 (DEVICE\_PRELOAD\_ENABLE ),则系统启动过程中默认加载;配成1(DEVICE\_PRELOAD\_ENABLE\_STEP2),当系统支持快启的时候,则在系统系统完成之后再加载这一类驱动,否则和DEVICE\_PRELOAD\_ENABLE 含义相同;配成2(DEVICE\_PRELOAD\_DISABLE),则系统启动过程中默认不加载,支持后续动态加载,当用户态获取驱动服务(参考[消息机制](驱动消息机制管理.md))时,如果驱动服务不存在时,HDF框架会尝试动态加载该驱动。 ->- 按序加载(需要驱动为默认加载) -> 配置文件中的priority(取值范围为整数0到200)是用来表示host和驱动的优先级,不同的host内的驱动,host的priority值越小,驱动加载优先级越高;同一个host内驱动的priority值越小,加载优先级越高。 - diff --git "a/zh-cn/device-dev/driver/\351\251\261\345\212\250\346\266\210\346\201\257\346\234\272\345\210\266\347\256\241\347\220\206.md" "b/zh-cn/device-dev/driver/\351\251\261\345\212\250\346\266\210\346\201\257\346\234\272\345\210\266\347\256\241\347\220\206.md" deleted file mode 100755 index ac271c2f1e..0000000000 --- "a/zh-cn/device-dev/driver/\351\251\261\345\212\250\346\266\210\346\201\257\346\234\272\345\210\266\347\256\241\347\220\206.md" +++ /dev/null @@ -1,193 +0,0 @@ -# 驱动消息机制管理 - -- [使用场景](#section33014541954) -- [接口说明](#section538852311616) -- [开发步骤](#section946912121153) - -## 使用场景 - -当用户态应用和内核态驱动需要交互时,可以使用HDF框架的消息机制来实现。 - -## 接口说明 - -消息机制的功能主要有以下两种: - -1. 用户态应用发送消息到驱动。 -2. 用户态应用接收驱动主动上报事件。 - -**表 1** 消息机制接口 - - - - - - - - - - - - - - - - - - - -

    方法

    -

    描述

    -

    struct HdfIoService *HdfIoServiceBind(const char *serviceName)

    -

    用户态获取驱动的服务,获取该服务之后通过服务中的Dispatch方法向驱动发送消息。

    -

    void HdfIoServiceRecycle(struct HdfIoService *service);

    -

    释放驱动服务。

    -

    int HdfDeviceRegisterEventListener(struct HdfIoService *target, struct HdfDevEventlistener *listener);

    -

    用户态程序注册接收驱动上报事件的操作方法。

    -

    int HdfDeviceSendEvent(struct HdfDeviceObject *deviceObject, uint32_t id, struct HdfSBuf *data);

    -

    驱动主动上报事件接口。

    -
    - -## 开发步骤 - -1. 将驱动配置信息中服务策略policy字段设置为2(SERVICE\_POLICY\_CAPACITY,参考[policy定义](驱动服务管理.md))。 - - ``` - device_sample :: Device { - policy = 2; - ... - } - ``` - -2. 配置驱动信息中的服务设备节点权限(permission字段)是框架给驱动创建设备节点的权限,默认是0666,驱动开发者根据驱动的实际使用场景配置驱动设备节点的权限。 -3. 在服务实现过程中,实现服务基类成员IDeviceIoService中的Dispatch方法。 - - ``` - // Dispatch是用来处理用户态发下来的消息 - int32_t SampleDriverDispatch(struct HdfDeviceObject *device, int cmdCode, struct HdfSBuf *data, struct HdfSBuf *reply) - { - HDF_LOGE("sample driver lite A dispatch"); - return 0; - } - int32_t SampleDriverBind(struct HdfDeviceObject *device) - { - HDF_LOGE("test for lite os sample driver A Open!"); - if (device == NULL) { - HDF_LOGE("test for lite os sample driver A Open failed!"); - return -1; - } - static struct ISampleDriverService sampleDriverA = { - .ioService.Dispatch = SampleDriverDispatch, - .ServiceA = SampleDriverServiceA, - .ServiceB = SampleDriverServiceB, - }; - device->service = (struct IDeviceIoService *)(&sampleDriverA); - return 0; - } - ``` - -4. 驱动定义消息处理函数中的cmd类型。 - - ``` - #define SAMPLE_WRITE_READ 1 // 读写操作码1 - ``` - -5. 用户态获取服务接口并发送消息到驱动。 - - ``` - int SendMsg(const char *testMsg) - { - if (testMsg == NULL) { - HDF_LOGE("test msg is null"); - return -1; - } - struct HdfIoService *serv = HdfIoServiceBind("sample_driver"); - if (serv == NULL) { - HDF_LOGE("fail to get service"); - return -1; - } - struct HdfSBuf *data = HdfSBufObtainDefaultSize(); - if (data == NULL) { - HDF_LOGE("fail to obtain sbuf data"); - return -1; - } - struct HdfSBuf *reply = HdfSBufObtainDefaultSize(); - if (reply == NULL) { - HDF_LOGE("fail to obtain sbuf reply"); - ret = HDF_DEV_ERR_NO_MEMORY; - goto out; - } - if (!HdfSbufWriteString(data, testMsg)) { - HDF_LOGE("fail to write sbuf"); - ret = HDF_FAILURE; - goto out; - } - int ret = serv->dispatcher->Dispatch(&serv->object, SAMPLE_WRITE_READ, data, reply); - if (ret != HDF_SUCCESS) { - HDF_LOGE("fail to send service call"); - goto out; - } - out: - HdfSBufRecycle(data); - HdfSBufRecycle(reply); - HdfIoServiceRecycle(serv); - return ret; - } - ``` - -6. 用户态接收该驱动上报的消息。 - 1. 用户态编写驱动上报消息的处理函数。 - - ``` - static int OnDevEventReceived(void *priv, uint32_t id, struct HdfSBuf *data) - { - OsalTimespec time; - OsalGetTime(&time); - HDF_LOGE("%s received event at %llu.%llu", (char *)priv, time.sec, time.usec); - - const char *string = HdfSbufReadString(data); - if (string == NULL) { - HDF_LOGE("fail to read string in event data"); - return -1; - } - HDF_LOGE("%s: dev event received: %d %s", (char *)priv, id, string); - return 0; - } - ``` - - 2. 用户态注册接收驱动上报消息的操作方法。 - - ``` - int RegisterListen() - { - struct HdfIoService *serv = HdfIoServiceBind("sample_driver"); - if (serv == NULL) { - HDF_LOGE("fail to get service"); - return -1; - } - static struct HdfDevEventlistener listener = { - .callBack = OnDevEventReceived, - .priv ="Service0" - }; - if (HdfDeviceRegisterEventListener(serv, &listener) != 0) { - HDF_LOGE("fail to register event listener"); - return -1; - } - ...... - HdfDeviceUnregisterEventListener(serv, &listener); - HdfIoServiceRecycle(serv); - return 0; - } - ``` - - 3. 驱动上报事件。 - - ``` - int32_t SampleDriverDispatch(struct HdfDeviceObject *device, int cmdCode, struct HdfSBuf *data, struct HdfSBuf *reply) - { - ... // process api call here - return HdfDeviceSendEvent(deviceObject, cmdCode, data); - } - ``` - - - diff --git "a/zh-cn/device-dev/get-code/Docker\347\274\226\350\257\221\347\216\257\345\242\203.md" "b/zh-cn/device-dev/get-code/Docker\347\274\226\350\257\221\347\216\257\345\242\203.md" deleted file mode 100644 index c15f1861f1..0000000000 --- "a/zh-cn/device-dev/get-code/Docker\347\274\226\350\257\221\347\216\257\345\242\203.md" +++ /dev/null @@ -1,313 +0,0 @@ -# Docker编译环境 - -- [Docker环境介绍](#section107932281315) -- [环境准备](#section7337134183512) -- [独立Docker环境](#section2858536103611) - - [搭建Docker环境-轻量系统类设备(参考内存≥128KB)和小型系统类设备(参考内存≥1MB)](#section319412277287) - - [编译源码-轻量系统类设备(参考内存≥128KB)和小型系统类设备(参考内存≥1MB)](#section631485163615) - - [搭建Docker环境-标准系统类设备(参考内存≥128MB)](#section13585262391) - - [编译源码-标准系统类设备(参考内存≥128MB)](#section193711513406) - -- [基于HPM的Docker环境](#section485713518337) - - [搭建Docker环境](#section3295842510) - - [获取及编译源码](#section69141039143518) - - -## Docker环境介绍 - -OpenHarmony为开发者提供了两种Docker环境,以帮助开发者快速完成复杂的开发环境准备工作。两种Docker环境及适用场景如下: - -- 独立Docker环境:适用于直接基于Ubuntu、Windows操作系统平台进行版本编译的场景。 -- 基于HPM的Docker环境:适用于使用HPM工具进行发行版编译的场景。 - -**表 1** Docker镜像介绍 - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    Docker环境

    -

    系统类型

    -

    运行平台

    -

    Docker镜像仓库

    -

    标签

    -

    独立 Docker环境

    -

    轻量和小型系统

    -

    Ubuntu/Windows

    -

    swr.cn-south-1.myhuaweicloud.com/openharmony-docker/openharmony-docker

    -

    0.0.5

    -

    标准系统

    -

    Ubuntu

    -

    swr.cn-south-1.myhuaweicloud.com/openharmony-docker/openharmony-docker-standard

    -

    0.0.1

    -

    HPM Docker环境

    -

    轻量和小型系统

    -

    Ubuntu/Windows

    -

    swr.cn-south-1.myhuaweicloud.com/openharmony-docker/openharmony-docker

    -

    0.0.3

    -
    - -## 环境准备 - -在使用docker环境前需要先完成以下操作: - -1. 安装Docker,Docker安装请参考[官方指导](https://docs.docker.com/engine/install/)。 -2. 获取OpenHarmony源码,请参考[获取源码](源码获取.md)。 - - >![](public_sys-resources/icon-note.gif) **说明:** - >HPM Docker环境无需单独获取源码。 - - -## 独立Docker环境 - -OpenHarmony的Docker镜像托管在[HuaweiCloud SWR](https://console.huaweicloud.com/swr/?region=cn-south-1#/app/warehouse/warehouseMangeDetail/goldensir/openharmony-docker/openharmony-docker?type=ownImage)上。开发者可以通过该镜像在很大程度上简化编译前的环境配置。下文将介绍具体使用步骤。 - -### 搭建Docker环境-轻量系统类设备(参考内存≥128KB)和小型系统类设备(参考内存≥1MB) - -**方式一:从HuaweiCloud SWR上直接获取Docker镜像进行构建:** - -1. 获取Docker镜像。 - - ``` - docker pull swr.cn-south-1.myhuaweicloud.com/openharmony-docker/openharmony-docker:0.0.5 - ``` - -2. 进入OpenHarmony代码根目录执行如下命令,从而进入Docker构建环境。 - - ubuntu下执行: - - ``` - docker run -it -v $(pwd):/home/openharmony swr.cn-south-1.myhuaweicloud.com/openharmony-docker/openharmony-docker:0.0.5 - ``` - - windows下执行(假设源码目录为D:\\OpenHarmony): - - ``` - docker run -it -v D:\OpenHarmony:/home/openharmony swr.cn-south-1.myhuaweicloud.com/openharmony-docker/openharmony-docker:0.0.5 - ``` - - -**方式二:通过Dockerfile 构建本地Docker镜像进行构建** - -1. 获取Dockerfile脚本文件,用来构建本地Docker镜像。 - - ``` - git clone https://gitee.com/openharmony/docs.git - ``` - -2. 进入Dockerfile代码目录路径执行Docker镜像构建命令。 - - ``` - cd docs/docker - ./build.sh - ``` - -3. 进入OpenHarmony代码根目录执行如下命令,从而进入Docker构建环境。 - - ubuntu下执行: - - ``` - docker run -it -v $(pwd):/home/openharmony swr.cn-south-1.myhuaweicloud.com/openharmony-docker/openharmony-docker:0.0.5 - ``` - - windows下执行(假设源码目录为D:\\OpenHarmony): - - ``` - docker run -it -v D:\OpenHarmony:/home/openharmony swr.cn-south-1.myhuaweicloud.com/openharmony-docker/openharmony-docker:0.0.5 - ``` - - -### 编译源码-轻量系统类设备(参考内存≥128KB)和小型系统类设备(参考内存≥1MB) - -通过如下编译脚本启动轻量系统类设备(参考内存≥128KB)和小型系统类设备(参考内存≥1MB)的编译。下文以Hi3516平台为例说明具体编译步骤。 - -设置编译路径,选择当前路径。 - -``` -hb set - . -``` - -**图 1** 设置编译界面 - - -![](figures/zh-cn_image_0000001101413884.png) - ->![](public_sys-resources/icon-note.gif) **说明:** ->当前开发板平台和编译界面的对应关系如下: ->- Hi3861:wifiiot\_hispark\_pegasus@hisilicon ->- Hi3516:ipcamera\_hispark\_taurus@hisilicon ->- Hi3518:ipcamera\_hispark\_aries@hisilicon - -1. 选择ipcamera\_hispark\_taurus@hisilicon并回车。 -2. 执行编译。 - - ``` - hb build -f - ``` - -3. 查看编译结果。 - - 编译结果文件生成在out/hispark\_taurus/ipcamera\_hispark\_taurus目录下。 - - -### 搭建Docker环境-标准系统类设备(参考内存≥128MB) - -**方式一:从HuaweiCloud SWR上直接获取Docker镜像进行构建:** - -1. 获取Docker镜像。 - - ``` - docker pull swr.cn-south-1.myhuaweicloud.com/openharmony-docker/openharmony-docker-standard:0.0.1 - ``` - -2. 进入OpenHarmony代码根目录执行如下命令,从而进入Docker构建环境。 - - ``` - docker run -it -v $(pwd):/home/openharmony swr.cn-south-1.myhuaweicloud.com/openharmony-docker/openharmony-docker-standard:0.0.1 - ``` - - -**方式二:通过Dockerfile 构建本地Docker镜像进行构建** - -1. 获取Dockerfile脚本文件,用来构建本地Docker镜像。 - - ``` - git clone https://gitee.com/openharmony/docs.git - ``` - -2. 进入Dockerfile代码目录路径执行Docker镜像构建命令。 - - ``` - cd docs/docker/standard - ./build.sh - ``` - -3. 进入OpenHarmony代码根目录执行如下命令,从而进入Docker构建环境。 - - ``` - docker run -it -v $(pwd):/home/openharmony openharmony-docker-standard:0.0.1 - ``` - - -### 编译源码-标准系统类设备(参考内存≥128MB) - -1. 在源码的根目录执行预处理脚本。 - - ``` - ../scripts/prepare.sh - ``` - -2. 通过如下编译脚本启动标准系统类设备(参考内存≥128MB)的编译。 - - ``` - ./build.sh --product-name {product_name} - ``` - - \{product\_name\}为当前版本支持的平台。比如:Hi3516DV300等。 - - 编译所生成的文件都归档在out/ohos-arm-release/目录下,结果镜像输出在 out/ohos-arm-release/packages/phone/images/ 目录下。 - - ->![](public_sys-resources/icon-note.gif) **说明:** ->退出Docker执行exit命令即可。 - -## 基于HPM的Docker环境 - -docker\_dist是一个[HPM](https://hpm.harmonyos.com/)系统中的模板组件,能够帮助用户快速初始化HPM工程,利用docker镜像来快速编译OpenHarmony发行版,在很大程度上简化了编译前的环境配置。开发者在配置好Ubuntu和[hpm-cli](https://device.harmonyos.com/cn/docs/develop/bundles/oem_bundle_guide_prepare-0000001050129846)开发环境后,可以通过以下步骤来使用我们提供的Docker环境。 - -### 搭建Docker环境 - -1. 初始化安装模板。在任意工作目录中执行以下命令。 - - ``` - hpm init -t @ohos/docker_dist - ``` - -2. 修改publishAs。 - - 因为获取到的是模板类型的包,要把包的类型改为需要的类型。 在当前目录下打开bundle.json文件,把"publishAs"字段的值由"template"改为"distribution"。 - - -### 获取及编译源码 - -执行编译。自动安装docker只能在Ubuntu环境下执行,如果其他环境,需要用户自行安装docker,然后拉取镜像,执行编译。 - -- **自动安装docker(Ubuntu环境)** - - 以下命令可以帮助用户自动安装docker, 拉取镜像,并且在容器中开始运行对应解决方案的拉取和编译。 - - **方式一:** - - 命令后接参数指定解决方案,格式如下: - - ``` - hpm run docker solution={product} - ``` - - \{product\}为需编译的解决方案,如:@ohos/hispark\_taurus、@ohos/hispark\_aries、@ohos/hispark\_pegasus。 - - **方式二:** - - 设置环境变量来选择解决方案,再执行编译命令。 - - 1. 选择解决方案。 - - ``` - export solution={product} - ``` - - \{product\}为需编译的解决方案,如:@ohos/hispark\_taurus、@ohos/hispark\_aries、@ohos/hispark\_pegasus。 - - 2. 获取源码及执行编译。 - - ``` - hpm run docker - ``` - - - 以上两种方式以@ohos/hispark\_taurus为例,执行成功结果如下: - - ``` - ...... - ohos ipcamera_hispark_taurus build success! - @ohos/hispark_taurus: distribution building completed. - ``` - - -- **自行安装docker(非Ubuntu环境)** - - 自行安装docker相关操作如下: - - ``` - # 拉取镜像 - docker pull swr.cn-south-1.myhuaweicloud.com/openharmony-docker/openharmony-docker:0.0.3# linux环境下的编译 - hpm run distWithDocker solution={product} - # windows下的编译,需要配置gitbash - hpm config set shellPath "gitbash路径" - hpm run distWithDocker solution={product} - ``` - - diff --git a/zh-cn/device-dev/get-code/IDE.md b/zh-cn/device-dev/get-code/IDE.md deleted file mode 100644 index 144b67418b..0000000000 --- a/zh-cn/device-dev/get-code/IDE.md +++ /dev/null @@ -1,17 +0,0 @@ -# IDE - -- [获取设备开发工具(HUAWEI DevEco Device Tool)](#section2452141120244) -- [获取应用开发工具(HUAWEI DevEco Studio)](#section0904101019258) - -## 获取设备开发工具(HUAWEI DevEco Device Tool) - -HUAWEI DevEco Device Tool是OpenHarmony面向智能设备开发者提供的一站式集成开发环境,支持OpenHarmony的组件按需定制,支持代码编辑、编译、烧录、调试等功能,支持C/C++语言,以插件的形式部署在Visual Studio Code上。具体可参见[获取工具](https://device.harmonyos.com/cn/ide)和[工具使用指南](https://device.harmonyos.com/cn/docs/ide/user-guides/service_introduction-0000001050166905)**。** - -Huawei DevEco Device Tool支持 OpenHarmony设备开发的演进路标如下: - -![](figures/3.png) - -## 获取应用开发工具(HUAWEI DevEco Studio) - -HUAWEI DevEco Studio(以下简称DevEco Studio)是面向华为终端全场景多设备的一站式集成开发环境(IDE),为开发者提供工程模板创建、开发、编译、调试、发布等E2E的OpenHarmony应用开发服务。通过使用DevEco Studio,开发者可以更高效的开发具备OpenHarmony分布式能力的应用,进而提升创新效率。具体可参见[获取工具](https://developer.harmonyos.com/cn/develop/deveco-studio)和[工具使用指南](https://developer.harmonyos.com/cn/docs/documentation/doc-guides/tools_overview-0000001053582387)。 - diff --git a/zh-cn/device-dev/get-code/Readme-CN.md b/zh-cn/device-dev/get-code/Readme-CN.md index a2dbbc91bb..82da2d561e 100755 --- a/zh-cn/device-dev/get-code/Readme-CN.md +++ b/zh-cn/device-dev/get-code/Readme-CN.md @@ -1,7 +1,9 @@ # 获取源码 -- [源码获取](源码获取.md) -- [获取工具](获取工具.md) - - [Docker编译环境](Docker编译环境.md) - - [IDE](IDE.md) +- [获取源码](sourcecode.md) + - [源码获取](sourcecode-acquire.md) + +- [获取工具](gettools.md) + - [Docker编译环境](gettools-acquire.md) + - [IDE](gettools-ide.md) diff --git a/zh-cn/device-dev/get-code/figures/3.png b/zh-cn/device-dev/get-code/figure/3-20.png similarity index 100% rename from zh-cn/device-dev/get-code/figures/3.png rename to zh-cn/device-dev/get-code/figure/3-20.png diff --git a/zh-cn/device-dev/get-code/figures/zh-cn_image_0000001101413884.png b/zh-cn/device-dev/get-code/figure/zh-cn_image_0000001101413884.png similarity index 100% rename from zh-cn/device-dev/get-code/figures/zh-cn_image_0000001101413884.png rename to zh-cn/device-dev/get-code/figure/zh-cn_image_0000001101413884.png diff --git a/zh-cn/device-dev/get-code/figures/zh-cn_image_0000001119755646.png b/zh-cn/device-dev/get-code/figure/zh-cn_image_0000001119755646.png similarity index 100% rename from zh-cn/device-dev/get-code/figures/zh-cn_image_0000001119755646.png rename to zh-cn/device-dev/get-code/figure/zh-cn_image_0000001119755646.png diff --git a/zh-cn/device-dev/get-code/figures/zh-cn_image_0000001119915556.png b/zh-cn/device-dev/get-code/figure/zh-cn_image_0000001119915556.png similarity index 100% rename from zh-cn/device-dev/get-code/figures/zh-cn_image_0000001119915556.png rename to zh-cn/device-dev/get-code/figure/zh-cn_image_0000001119915556.png diff --git a/zh-cn/device-dev/get-code/figures/zh-cn_image_0000001166715379.png b/zh-cn/device-dev/get-code/figure/zh-cn_image_0000001166715379.png similarity index 100% rename from zh-cn/device-dev/get-code/figures/zh-cn_image_0000001166715379.png rename to zh-cn/device-dev/get-code/figure/zh-cn_image_0000001166715379.png diff --git a/zh-cn/device-dev/get-code/gettools-acquire.md b/zh-cn/device-dev/get-code/gettools-acquire.md new file mode 100644 index 0000000000..942635e189 --- /dev/null +++ b/zh-cn/device-dev/get-code/gettools-acquire.md @@ -0,0 +1,313 @@ +# Docker编译环境 + +- [Docker环境介绍](#section107932281315) +- [环境准备](#section7337134183512) +- [独立Docker环境](#section2858536103611) + - [搭建Docker环境-轻量系统类设备(参考内存≥128KB)和小型系统类设备(参考内存≥1MB)](#section319412277287) + - [编译源码-轻量系统类设备(参考内存≥128KB)和小型系统类设备(参考内存≥1MB)](#section631485163615) + - [搭建Docker环境-标准系统类设备(参考内存≥128MB)](#section13585262391) + - [编译源码-标准系统类设备(参考内存≥128MB)](#section193711513406) + +- [基于HPM的Docker环境](#section485713518337) + - [搭建Docker环境](#section3295842510) + - [获取及编译源码](#section69141039143518) + + +## Docker环境介绍 + +OpenHarmony为开发者提供了两种Docker环境,以帮助开发者快速完成复杂的开发环境准备工作。两种Docker环境及适用场景如下: + +- 独立Docker环境:适用于直接基于Ubuntu、Windows操作系统平台进行版本编译的场景。 +- 基于HPM的Docker环境:适用于使用HPM工具进行发行版编译的场景。 + +**表 1** Docker镜像介绍 + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    Docker环境

    +

    系统类型

    +

    运行平台

    +

    Docker镜像仓库

    +

    标签

    +

    独立 Docker环境

    +

    轻量和小型系统

    +

    Ubuntu/Windows

    +

    swr.cn-south-1.myhuaweicloud.com/openharmony-docker/openharmony-docker

    +

    0.0.5

    +

    标准系统

    +

    Ubuntu

    +

    swr.cn-south-1.myhuaweicloud.com/openharmony-docker/openharmony-docker-standard

    +

    0.0.1

    +

    HPM Docker环境

    +

    轻量和小型系统

    +

    Ubuntu/Windows

    +

    swr.cn-south-1.myhuaweicloud.com/openharmony-docker/openharmony-docker

    +

    0.0.3

    +
    + +## 环境准备 + +在使用docker环境前需要先完成以下操作: + +1. 安装Docker,Docker安装请参考[官方指导](https://docs.docker.com/engine/install/)。 +2. 获取OpenHarmony源码,请参考[获取源码](sourcecode-acquire.md)。 + + >![](../public_sys-resources/icon-note.gif) **说明:** + >HPM Docker环境无需单独获取源码。 + + +## 独立Docker环境 + +OpenHarmony的Docker镜像托管在[HuaweiCloud SWR](https://console.huaweicloud.com/swr/?region=cn-south-1#/app/warehouse/warehouseMangeDetail/goldensir/openharmony-docker/openharmony-docker?type=ownImage)上。开发者可以通过该镜像在很大程度上简化编译前的环境配置。下文将介绍具体使用步骤。 + +### 搭建Docker环境-轻量系统类设备(参考内存≥128KB)和小型系统类设备(参考内存≥1MB) + +**方式一:从HuaweiCloud SWR上直接获取Docker镜像进行构建:** + +1. 获取Docker镜像。 + + ``` + docker pull swr.cn-south-1.myhuaweicloud.com/openharmony-docker/openharmony-docker:0.0.5 + ``` + +2. 进入OpenHarmony代码根目录执行如下命令,从而进入Docker构建环境。 + + ubuntu下执行: + + ``` + docker run -it -v $(pwd):/home/openharmony swr.cn-south-1.myhuaweicloud.com/openharmony-docker/openharmony-docker:0.0.5 + ``` + + windows下执行(假设源码目录为D:\\OpenHarmony): + + ``` + docker run -it -v D:\OpenHarmony:/home/openharmony swr.cn-south-1.myhuaweicloud.com/openharmony-docker/openharmony-docker:0.0.5 + ``` + + +**方式二:通过Dockerfile 构建本地Docker镜像进行构建** + +1. 获取Dockerfile脚本文件,用来构建本地Docker镜像。 + + ``` + git clone https://gitee.com/openharmony/docs.git + ``` + +2. 进入Dockerfile代码目录路径执行Docker镜像构建命令。 + + ``` + cd docs/docker + ./build.sh + ``` + +3. 进入OpenHarmony代码根目录执行如下命令,从而进入Docker构建环境。 + + ubuntu下执行: + + ``` + docker run -it -v $(pwd):/home/openharmony swr.cn-south-1.myhuaweicloud.com/openharmony-docker/openharmony-docker:0.0.5 + ``` + + windows下执行(假设源码目录为D:\\OpenHarmony): + + ``` + docker run -it -v D:\OpenHarmony:/home/openharmony swr.cn-south-1.myhuaweicloud.com/openharmony-docker/openharmony-docker:0.0.5 + ``` + + +### 编译源码-轻量系统类设备(参考内存≥128KB)和小型系统类设备(参考内存≥1MB) + +通过如下编译脚本启动轻量系统类设备(参考内存≥128KB)和小型系统类设备(参考内存≥1MB)的编译。下文以Hi3516平台为例说明具体编译步骤。 + +设置编译路径,选择当前路径。 + +``` +hb set + . +``` + +**图 1** 设置编译界面 + + +![](figure/zh-cn_image_0000001101413884.png) + +>![](../public_sys-resources/icon-note.gif) **说明:** +>当前开发板平台和编译界面的对应关系如下: +>- Hi3861:wifiiot\_hispark\_pegasus@hisilicon +>- Hi3516:ipcamera\_hispark\_taurus@hisilicon +>- Hi3518:ipcamera\_hispark\_aries@hisilicon + +1. 选择ipcamera\_hispark\_taurus@hisilicon并回车。 +2. 执行编译。 + + ``` + hb build -f + ``` + +3. 查看编译结果。 + + 编译结果文件生成在out/hispark\_taurus/ipcamera\_hispark\_taurus目录下。 + + +### 搭建Docker环境-标准系统类设备(参考内存≥128MB) + +**方式一:从HuaweiCloud SWR上直接获取Docker镜像进行构建:** + +1. 获取Docker镜像。 + + ``` + docker pull swr.cn-south-1.myhuaweicloud.com/openharmony-docker/openharmony-docker-standard:0.0.1 + ``` + +2. 进入OpenHarmony代码根目录执行如下命令,从而进入Docker构建环境。 + + ``` + docker run -it -v $(pwd):/home/openharmony swr.cn-south-1.myhuaweicloud.com/openharmony-docker/openharmony-docker-standard:0.0.1 + ``` + + +**方式二:通过Dockerfile 构建本地Docker镜像进行构建** + +1. 获取Dockerfile脚本文件,用来构建本地Docker镜像。 + + ``` + git clone https://gitee.com/openharmony/docs.git + ``` + +2. 进入Dockerfile代码目录路径执行Docker镜像构建命令。 + + ``` + cd docs/docker/standard + ./build.sh + ``` + +3. 进入OpenHarmony代码根目录执行如下命令,从而进入Docker构建环境。 + + ``` + docker run -it -v $(pwd):/home/openharmony openharmony-docker-standard:0.0.1 + ``` + + +### 编译源码-标准系统类设备(参考内存≥128MB) + +1. 在源码的根目录执行预处理脚本。 + + ``` + ../scripts/prepare.sh + ``` + +2. 通过如下编译脚本启动标准系统类设备(参考内存≥128MB)的编译。 + + ``` + ./build.sh --product-name {product_name} + ``` + + \{product\_name\}为当前版本支持的平台。比如:Hi3516DV300等。 + + 编译所生成的文件都归档在out/ohos-arm-release/目录下,结果镜像输出在 out/ohos-arm-release/packages/phone/images/ 目录下。 + + +>![](../public_sys-resources/icon-note.gif) **说明:** +>退出Docker执行exit命令即可。 + +## 基于HPM的Docker环境 + +docker\_dist是一个[HPM](https://hpm.harmonyos.com/)系统中的模板组件,能够帮助用户快速初始化HPM工程,利用docker镜像来快速编译OpenHarmony发行版,在很大程度上简化了编译前的环境配置。开发者在配置好Ubuntu和[hpm-cli](../bundles/bundles-guide-prepare.md)开发环境后,可以通过以下步骤来使用我们提供的Docker环境。 + +### 搭建Docker环境 + +1. 初始化安装模板。在任意工作目录中执行以下命令。 + + ``` + hpm init -t @ohos/docker_dist + ``` + +2. 修改publishAs。 + + 因为获取到的是模板类型的包,要把包的类型改为需要的类型。 在当前目录下打开bundle.json文件,把"publishAs"字段的值由"template"改为"distribution"。 + + +### 获取及编译源码 + +执行编译。自动安装docker只能在Ubuntu环境下执行,如果其他环境,需要用户自行安装docker,然后拉取镜像,执行编译。 + +- **自动安装docker(Ubuntu环境)** + + 以下命令可以帮助用户自动安装docker, 拉取镜像,并且在容器中开始运行对应解决方案的拉取和编译。 + + **方式一:** + + 命令后接参数指定解决方案,格式如下: + + ``` + hpm run docker solution={product} + ``` + + \{product\}为需编译的解决方案,如:@ohos/hispark\_taurus、@ohos/hispark\_aries、@ohos/hispark\_pegasus。 + + **方式二:** + + 设置环境变量来选择解决方案,再执行编译命令。 + + 1. 选择解决方案。 + + ``` + export solution={product} + ``` + + \{product\}为需编译的解决方案,如:@ohos/hispark\_taurus、@ohos/hispark\_aries、@ohos/hispark\_pegasus。 + + 2. 获取源码及执行编译。 + + ``` + hpm run docker + ``` + + + 以上两种方式以@ohos/hispark\_taurus为例,执行成功结果如下: + + ``` + ...... + ohos ipcamera_hispark_taurus build success! + @ohos/hispark_taurus: distribution building completed. + ``` + + +- **自行安装docker(非Ubuntu环境)** + + 自行安装docker相关操作如下: + + ``` + # 拉取镜像 + docker pull swr.cn-south-1.myhuaweicloud.com/openharmony-docker/openharmony-docker:0.0.3# linux环境下的编译 + hpm run distWithDocker solution={product} + # windows下的编译,需要配置gitbash + hpm config set shellPath "gitbash路径" + hpm run distWithDocker solution={product} + ``` + + diff --git a/zh-cn/device-dev/get-code/gettools-ide.md b/zh-cn/device-dev/get-code/gettools-ide.md new file mode 100644 index 0000000000..8217ddc122 --- /dev/null +++ b/zh-cn/device-dev/get-code/gettools-ide.md @@ -0,0 +1,17 @@ +# IDE + +- [获取设备开发工具(HUAWEI DevEco Device Tool)](#section2452141120244) +- [获取应用开发工具(HUAWEI DevEco Studio)](#section0904101019258) + +## 获取设备开发工具(HUAWEI DevEco Device Tool) + +HUAWEI DevEco Device Tool是OpenHarmony面向智能设备开发者提供的一站式集成开发环境,支持OpenHarmony的组件按需定制,支持代码编辑、编译、烧录、调试等功能,支持C/C++语言,以插件的形式部署在Visual Studio Code上。具体可参见[获取工具](https://device.harmonyos.com/cn/ide)和[工具使用指南](https://device.harmonyos.com/cn/docs/ide/user-guides/service_introduction-0000001050166905)**。** + +Huawei DevEco Device Tool支持 OpenHarmony设备开发的演进路标如下: + +![](figure/3-20.png) + +## 获取应用开发工具(HUAWEI DevEco Studio) + +HUAWEI DevEco Studio(以下简称DevEco Studio)是面向华为终端全场景多设备的一站式集成开发环境(IDE),为开发者提供工程模板创建、开发、编译、调试、发布等E2E的OpenHarmony应用开发服务。通过使用DevEco Studio,开发者可以更高效的开发具备OpenHarmony分布式能力的应用,进而提升创新效率。具体可参见[获取工具](https://developer.harmonyos.com/cn/develop/deveco-studio)和[工具使用指南](https://developer.harmonyos.com/cn/docs/documentation/doc-guides/tools_overview-0000001053582387)。 + diff --git a/zh-cn/device-dev/get-code/gettools.md b/zh-cn/device-dev/get-code/gettools.md new file mode 100644 index 0000000000..4e35772567 --- /dev/null +++ b/zh-cn/device-dev/get-code/gettools.md @@ -0,0 +1,7 @@ +# 获取工具 + +- **[Docker编译环境](gettools-acquire.md)** + +- **[IDE](gettools-ide.md)** + + diff --git a/zh-cn/device-dev/get-code/public_sys-resources/icon-caution.gif b/zh-cn/device-dev/get-code/public_sys-resources/icon-caution.gif deleted file mode 100755 index 6e90d7cfc2193e39e10bb58c38d01a23f045d571..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 580 zcmV-K0=xZ3Nk%w1VIu$?0Hp~4{QBgqmQ+MG9K51r{QB&)np^||1PlfQ%(86!{`~yv zv{XhUWKt}AZaiE{EOcHp{O-j3`t;<+eEiycJT4p@77X;(jQsMfB$R?oG%6hQ z+MMLZbQBH@)Vg&1^3?qHb(5!%>3r0+`eq=&V&E}0Dypi0000000000 z00000A^8LW000R9EC2ui03!e$000L5z=Uu}ED8YtqjJd<+B}(9bIOb$3-31_h|V>=0A{ z1Hh0#H30>fNT})^fRU_83uewx9oRr{f{Sx1Ml`t)EQ zGkHZ67&~y{W5Jpq4H_WfuLxp*3<7O}GEl;1ESe36fLNs=B0&LQM1Buf(R)qg(BRd`t1OPjI1m_q4 diff --git a/zh-cn/device-dev/get-code/public_sys-resources/icon-danger.gif b/zh-cn/device-dev/get-code/public_sys-resources/icon-danger.gif deleted file mode 100755 index 6e90d7cfc2193e39e10bb58c38d01a23f045d571..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 580 zcmV-K0=xZ3Nk%w1VIu$?0Hp~4{QBgqmQ+MG9K51r{QB&)np^||1PlfQ%(86!{`~yv zv{XhUWKt}AZaiE{EOcHp{O-j3`t;<+eEiycJT4p@77X;(jQsMfB$R?oG%6hQ z+MMLZbQBH@)Vg&1^3?qHb(5!%>3r0+`eq=&V&E}0Dypi0000000000 z00000A^8LW000R9EC2ui03!e$000L5z=Uu}ED8YtqjJd<+B}(9bIOb$3-31_h|V>=0A{ z1Hh0#H30>fNT})^fRU_83uewx9oRr{f{Sx1Ml`t)EQ zGkHZ67&~y{W5Jpq4H_WfuLxp*3<7O}GEl;1ESe36fLNs=B0&LQM1Buf(R)qg(BRd`t1OPjI1m_q4 diff --git a/zh-cn/device-dev/get-code/public_sys-resources/icon-note.gif b/zh-cn/device-dev/get-code/public_sys-resources/icon-note.gif deleted file mode 100755 index 6314297e45c1de184204098efd4814d6dc8b1cda..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 394 zcmZ?wbhEHblx7fPSjxcg=ii?@_wH=jwxy=7CMGH-B`L+l$wfv=#>UF#$gv|VY%C^b zCQFtrnKN(Bo_%|sJbO}7RAORe!otL&qo<>yq_Sq+8Xqqo5h0P3w3Lvb5E(g{p01vl zxR@)KuDH0l^z`+-dH3eaw=XqSH7aTIx{kzVBN;X&hha0dQSgWuiw0NWUvMRmkD|> diff --git a/zh-cn/device-dev/get-code/public_sys-resources/icon-notice.gif b/zh-cn/device-dev/get-code/public_sys-resources/icon-notice.gif deleted file mode 100755 index 86024f61b691400bea99e5b1f506d9d9aef36e27..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 406 zcmV;H0crk6Nk%w1VIu$@0J8u9|NsB@_xJDb@8;&_*4Ea}&d#;9wWXz{jEszHYim+c zQaU<1At50E0000000000A^8Le000gEEC2ui03!e%000R7038S%NU)&51O^i-Tu6`s z0)`MFE@;3YqD6xSC^kTNu_J>91{PH8XfZ(p1pp2-SU@u3#{mEUC}_}tg3+I#{z}{Ok@D_ZUDg- zt0stin4;pC8M{WLSlRH*1pzqEw1}3oOskyNN?j;7HD{BBZ*OEcv4HK!6Bk6beR+04 z&8}k>SkTusVTDmkyOz#5fCA$JTPGJVQvr3uZ?QzzPQFvD0rGf_PdrcF`pMs}p^BcF zKtKTd`0wipR%nKN&Wj+V}pX;WC3SdJV!a_8Qi zE7z`U*|Y^H0^}fB$R?oG%6hQ z+MMLZbQBH@)Vg&1^3?qHb(5!%>3r0+`eq=&V&E}0Dypi0000000000 z00000A^8LW000R9EC2ui03!e$000L5z=Uu}ED8YtqjJd<+B}(9bIOb$3-31_h|V>=0A{ z1Hh0#H30>fNT})^fRU_83uewx9oRr{f{Sx1Ml`t)EQ zGkHZ67&~y{W5Jpq4H_WfuLxp*3<7O}GEl;1ESe36fLNs=B0&LQM1Buf(R)qg(BRd`t1OPjI1m_q4 diff --git a/zh-cn/device-dev/get-code/sourcecode-acquire.md b/zh-cn/device-dev/get-code/sourcecode-acquire.md new file mode 100644 index 0000000000..de62e5dd99 --- /dev/null +++ b/zh-cn/device-dev/get-code/sourcecode-acquire.md @@ -0,0 +1,426 @@ +# 源码获取 + +- [OpenHarmony介绍](#section6370143622110) +- [源码获取概述](#section12763342204) +- [获取方式1:从代码仓库获取](#section537312010229) + - [适用场景](#section10881513459) + - [前提条件](#section102871547153314) + - [操作步骤](#section429012478331) + +- [获取方式2:从HPM获取](#section463013147412) + - [适用场景](#section26661067443) + - [前提条件](#section17544943123315) + - [操作步骤](#section954619433333) + +- [获取方式3:从镜像站点获取](#section1186691118430) +- [源码目录简介](#section1072115612811) + +## OpenHarmony介绍 + +OpenHarmony是由开放原子开源基金会(OpenAtom Foundation)孵化及运营的开源项目,目标是面向全场景、全连接、全智能时代,搭建一个智能终端设备操作系统的框架和平台,促进万物互联产业的繁荣发展。 + +开源代码仓库地址:[https://openharmony.gitee.com](https://openharmony.gitee.com) + +>![](../public_sys-resources/icon-note.gif) **说明:** +>当前的OpenHarmony源代码仅支持在Linux环境下编译。 + +## 源码获取概述 + +本文档将介绍如何获取OpenHarmony源码并说明OpenHarmony的源码目录结构。OpenHarmony的代码以[组件](../bundles/bundles-standard-rules.md)的形式开放,开发者可以通过如下其中一种方式获取: + +- **获取方式1**:从代码仓库获取。通过repo或git工具从代码仓库中下载,此方式可获取最新代码。 +- **获取方式2**:通过HPM包管理器获取。在[HPM](https://hpm.harmonyos.com)网站,查找满足需求的开源发行版,直接下载(或者定制后下载),再通过hpm-cli命令工具将所需的组件及工具链下载、安装到本地。 +- **获取方式3**:从镜像站点下载归档后的发行版压缩文件。如果要获取旧版本的源码,也可通过此方式获取,此方式下载速度较快。 + +## 获取方式1:从代码仓库获取 + +### 适用场景 + +- 基于OpenHarmony的稳定分支建立自己的基线,分发下游客户。 + +- 已经完成自身软件与OpenHarmony的对接,需要进行OpenHarmony官方认证。 + +- 芯片/模组/app通过OpenHarmony官方认证后,贡献代码到OpenHarmony社区。 + +- 修复OpenHarmony的问题。 + +- 学习OpenHarmony的源码。 + + +### 前提条件 + +1. 注册码云gitee账号。 +2. 注册码云SSH公钥,请参考[码云帮助中心](https://gitee.com/help/articles/4191)。 +3. 安装[git客户端](http://git-scm.com/book/zh/v2/%E8%B5%B7%E6%AD%A5-%E5%AE%89%E8%A3%85-Git)和[git-lfs](https://gitee.com/vcs-all-in-one/git-lfs?_from=gitee_search#downloading))并配置用户信息。 + + ``` + git config --global user.name "yourname" + git config --global user.email "your-email-address" + git config --global credential.helper store + ``` + +4. 安装码云repo工具,可以执行如下命令。 + + ``` + curl -s https://gitee.com/oschina/repo/raw/fork_flow/repo-py3 > /usr/local/bin/repo #如果没有权限,可下载至其他目录,并将其配置到环境变量中 + chmod a+x /usr/local/bin/repo + pip3 install -i https://repo.huaweicloud.com/repository/pypi/simple requests + ``` + + +### 操作步骤 + +**获取轻量/小型/标准系统(2.0 Canary)源码** + +>![](../public_sys-resources/icon-note.gif) **说明:** +>主干代码为开发分支,开发者可通过主干代码获取最新特性。release分支代码相对比较稳定,开发者可基于release分支代码进行商用功能开发。 + +- **OpenHarmony主干代码获取** + + 方式一(推荐):通过repo + ssh 下载(需注册公钥,请参考[码云帮助中心](https://gitee.com/help/articles/4191))。 + + ``` + repo init -u git@gitee.com:openharmony/manifest.git -b master --no-repo-verify + repo sync -c + repo forall -c 'git lfs pull' + ``` + + 方式二:通过repo + https 下载。 + + ``` + repo init -u https://gitee.com/openharmony/manifest.git -b master --no-repo-verify + repo sync -c + repo forall -c 'git lfs pull' + ``` + + +- **OpenHarmony release 分支最新代码获取** + + >![](../public_sys-resources/icon-note.gif) **说明:** + >当前通过release分支只能获取轻量和小型系统源码。 + + 通过repo下载。 + + ``` + repo init -u https://gitee.com/openharmony/manifest.git -b OpenHarmony_1.0.1_release --no-repo-verify + repo sync -c + repo forall -c 'git lfs pull' + ``` + +- OpenHarmony其他版本源码获取方式请参考版本[Release-Notes](https://gitee.com/openharmony/docs/blob/master/zh-cn/release-notes/OpenHarmony-Release-Notes.md)。 + +## 获取方式2:从HPM获取 + +### 适用场景 + +对于刚接触OpenHarmony的新用户,希望能够参考一些示例解决方案从而进行快速开发。可以在[HPM](https://hpm.harmonyos.com)网站获取下载开源发行版,也可以在开源发行版的基础上定制(添加或删除组件)。然后通过包管理器命令行工具(hpm-cli)将需要的组件及相关的编译工具链全部下载、安装到本地。 + +### 前提条件 + +先要在本地安装Node.js和hpm命令行工具,安装步骤如下: + +1. 安装Node.js。 + + 官网下载并在本地安装Node.js. + + 推荐安装 [Node.js](https://nodejs.org/) 12.x \(包含 npm 6.14.4\)或更高版本 \(推荐 12.13.0+\)。 + +2. 通过Node.js自带的npm安装hpm命令行工具。 + + 打开CMD,执行以下命令: + + ``` + npm install -g @ohos/hpm-cli + ``` + +3. 安装完成后执行如下命令,显示hpm版本,即安装成功。 + + ``` + hpm -V 或 hpm --version + ``` + +4. 如果升级hpm的版本,请执行如下命令: + + ``` + npm update -g @ohos/hpm-cli + ``` + + +### 操作步骤 + +1. 查找发行版。 + 1. 打开包管理页面[HPM](https://hpm.harmonyOS.com),设定搜索的对象为“发行版“,如下图所示。 + 2. 在搜索框输入关键字搜索,如“摄像头”。 + 3. 结果中显示与关键字匹配的发行版,可以进一步根据组件类别等过滤条件(如:适配的开发板,内核)精确筛选。 + 4. 查找合适的发行版,点击查看发行版的详情介绍。 + + **图 1** 包管理 + + + ![](figure/zh-cn_image_0000001119915556.png) + + +2. 了解发行版详情。 + + 1. 仔细阅读发行版的说明信息,以了解使用场景、特性、组件构成、使用方法以及如何进行定制化,如下图所示。 + 2. 点击「直接下载」,将发行版下载到本地。 + 3. 点击「定制组件」,将对发行版包含的组件进行定制(添加/删除)。 + + **图 2** 发行版示例 + + + ![](figure/zh-cn_image_0000001119755646.png) + +3. 定制组件。 + 1. 进入发行版的定制页面,如下图所示。 + 2. 通过关闭开关移除可选组件,或者通过“添加组件”增加新的组件。 + 3. 在右边填写您的项目基本信息,包括名称、版本、描述等信息。 + 4. 点击“下载“,系统会根据您的选择,生成相应的OpenHarmony代码结构文件\(如my\_cust\_dist.zip\),保存至本地文件。 + + **图 3** 组件定制 + + + ![](figure/zh-cn_image_0000001166715379.png) + + +4. 下载安装组件。 + 1. 解压下载的压缩文件,用命令行工具CMD(Linux下的Shell终端) + 2. 在解压后的文件目录下执行hpm install指令 + 3. 下载的组件存在工程目录下的ohos\_bundles文件夹中(部分组件安装后会将源码复制到指定目录下)。 + + +## 获取方式3:从镜像站点获取 + +为了获得更好的下载性能,您可以选择从以下站点的镜像库获取源码或者对应的解决方案。 + +>![](../public_sys-resources/icon-note.gif) **说明:** +>- 本部分只提供OpenHarmony Master最新版本和LTS最新版本的源码获取方式, 其他版本源码获取方式以及具体版本信息请参考[Release-Notes](https://gitee.com/openharmony/docs/blob/master/zh-cn/release-notes/OpenHarmony-Release-Notes.md) +>- 当前Master 1.0版本已经不再维护。 + +**表 1** 源码获取路径 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    LTS版本源码

    +

    版本信息

    +

    下载站点

    +

    SHA256校验码

    +

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

    +

    1.1.1

    +

    站点

    +

    SHA256 校验码

    +

    Hi3861解决方案(二进制)

    +

    1.1.1

    +

    站点

    +

    SHA256 校验码

    +

    Hi3518解决方案(二进制)

    +

    1.1.1

    +

    站点

    +

    SHA256 校验码

    +

    Hi3516解决方案(二进制)

    +

    1.1.1

    +

    站点

    +

    SHA256 校验码

    +

    RELEASE-NOTES

    +

    1.1.1

    +

    站点

    +

    -

    +

    Master版本源码

    +

    版本信息

    +

    下载站点

    +

    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(不再维护)

    +

    站点

    +

    -

    +

    编译工具链

    +

    版本信息

    +

    下载站点

    +

    SHA256校验码

    +

    编译工具链获取清单

    +

    -

    +

    站点

    +

    -

    +
    + +## 源码目录简介 + +下表是OpenHarmony源码的目录及简单说明: + +**表 2** 源码目录 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    目录名

    +

    描述

    +

    applications

    +

    应用程序样例,包括camera等

    +

    base

    +

    基础软件服务子系统集&硬件服务子系统集

    +

    build

    +

    组件化编译、构建和配置脚本

    +

    docs

    +

    说明文档

    +

    domains

    +

    增强软件服务子系统集

    +

    drivers

    +

    驱动子系统

    +

    foundation

    +

    系统基础能力子系统集

    +

    kernel

    +

    内核子系统

    +

    prebuilts

    +

    编译器及工具链子系统

    +

    test

    +

    测试子系统

    +

    third_party

    +

    开源第三方组件

    +

    utils

    +

    常用的工具集

    +

    vendor

    +

    厂商提供的软件

    +

    build.py

    +

    编译脚本文件

    +
    + diff --git a/zh-cn/device-dev/get-code/sourcecode.md b/zh-cn/device-dev/get-code/sourcecode.md new file mode 100644 index 0000000000..c5803f640f --- /dev/null +++ b/zh-cn/device-dev/get-code/sourcecode.md @@ -0,0 +1,5 @@ +# 获取源码 + +- **[源码获取](sourcecode-acquire.md)** + + diff --git "a/zh-cn/device-dev/get-code/\346\272\220\347\240\201\350\216\267\345\217\226.md" "b/zh-cn/device-dev/get-code/\346\272\220\347\240\201\350\216\267\345\217\226.md" deleted file mode 100755 index 3b2c0526b4..0000000000 --- "a/zh-cn/device-dev/get-code/\346\272\220\347\240\201\350\216\267\345\217\226.md" +++ /dev/null @@ -1,426 +0,0 @@ -# 源码获取 - -- [OpenHarmony介绍](#section6370143622110) -- [源码获取概述](#section12763342204) -- [获取方式1:从代码仓库获取](#section537312010229) - - [适用场景](#section10881513459) - - [前提条件](#section102871547153314) - - [操作步骤](#section429012478331) - -- [获取方式2:从HPM获取](#section463013147412) - - [适用场景](#section26661067443) - - [前提条件](#section17544943123315) - - [操作步骤](#section954619433333) - -- [获取方式3:从镜像站点获取](#section1186691118430) -- [源码目录简介](#section1072115612811) - -## OpenHarmony介绍 - -OpenHarmony是由开放原子开源基金会(OpenAtom Foundation)孵化及运营的开源项目,目标是面向全场景、全连接、全智能时代,搭建一个智能终端设备操作系统的框架和平台,促进万物互联产业的繁荣发展。 - -开源代码仓库地址:[https://openharmony.gitee.com](https://openharmony.gitee.com) - ->![](public_sys-resources/icon-note.gif) **说明:** ->当前的OpenHarmony源代码仅支持在Linux环境下编译。 - -## 源码获取概述 - -本文档将介绍如何获取OpenHarmony源码并说明OpenHarmony的源码目录结构。OpenHarmony的代码以[组件](../bundles/概述.md)的形式开放,开发者可以通过如下其中一种方式获取: - -- **获取方式1**:从代码仓库获取。通过repo或git工具从代码仓库中下载,此方式可获取最新代码。 -- **获取方式2**:通过HPM包管理器获取。在[HPM](https://hpm.harmonyos.com)网站,查找满足需求的开源发行版,直接下载(或者定制后下载),再通过hpm-cli命令工具将所需的组件及工具链下载、安装到本地。 -- **获取方式3**:从镜像站点下载归档后的发行版压缩文件。如果要获取旧版本的源码,也可通过此方式获取,此方式下载速度较快。 - -## 获取方式1:从代码仓库获取 - -### 适用场景 - -- 基于OpenHarmony的稳定分支建立自己的基线,分发下游客户。 - -- 已经完成自身软件与OpenHarmony的对接,需要进行OpenHarmony官方认证。 - -- 芯片/模组/app通过OpenHarmony官方认证后,贡献代码到OpenHarmony社区。 - -- 修复OpenHarmony的问题。 - -- 学习OpenHarmony的源码。 - - -### 前提条件 - -1. 注册码云gitee账号。 -2. 注册码云SSH公钥,请参考[码云帮助中心](https://gitee.com/help/articles/4191)。 -3. 安装[git客户端](http://git-scm.com/book/zh/v2/%E8%B5%B7%E6%AD%A5-%E5%AE%89%E8%A3%85-Git)和[git-lfs](https://gitee.com/vcs-all-in-one/git-lfs?_from=gitee_search#downloading)并配置用户信息。 - - ``` - git config --global user.name "yourname" - git config --global user.email "your-email-address" - git config --global credential.helper store - ``` - -4. 安装码云repo工具,可以执行如下命令。 - - ``` - curl -s https://gitee.com/oschina/repo/raw/fork_flow/repo-py3 > /usr/local/bin/repo #如果没有权限,可下载至其他目录,并将其配置到环境变量中 - chmod a+x /usr/local/bin/repo - pip3 install -i https://repo.huaweicloud.com/repository/pypi/simple requests - ``` - - -### 操作步骤 - -**获取轻量/小型/标准系统(2.0 Canary)源码** - ->![](public_sys-resources/icon-note.gif) **说明:** ->主干代码为开发分支,开发者可通过主干代码获取最新特性。release分支代码相对比较稳定,开发者可基于release分支代码进行商用功能开发。 - -- **OpenHarmony主干代码获取** - - 方式一(推荐):通过repo + ssh 下载(需注册公钥,请参考[码云帮助中心](https://gitee.com/help/articles/4191))。 - - ``` - repo init -u git@gitee.com:openharmony/manifest.git -b master --no-repo-verify - repo sync -c - repo forall -c 'git lfs pull' - ``` - - 方式二:通过repo + https 下载。 - - ``` - repo init -u https://gitee.com/openharmony/manifest.git -b master --no-repo-verify - repo sync -c - repo forall -c 'git lfs pull' - ``` - - -- **OpenHarmony release 分支最新代码获取** - - >![](public_sys-resources/icon-note.gif) **说明:** - >当前通过release分支只能获取轻量和小型系统源码。 - - 通过repo下载。 - - ``` - repo init -u https://gitee.com/openharmony/manifest.git -b OpenHarmony_1.0.1_release --no-repo-verify - repo sync -c - repo forall -c 'git lfs pull' - ``` - -- **OpenHarmony** 其他版本源码获取方式请参考版本[Release-Notes](https://gitee.com/openharmony/docs/blob/master/zh-cn/release-notes/OpenHarmony-Release-Notes.md)。 - -## 获取方式2:从HPM获取 - -### 适用场景 - -对于刚接触OpenHarmony的新用户,希望能够参考一些示例解决方案从而进行快速开发。可以在[HPM](https://hpm.harmonyos.com)网站获取下载开源发行版,也可以在开源发行版的基础上定制(添加或删除组件)。然后通过包管理器命令行工具(hpm-cli)将需要的组件及相关的编译工具链全部下载、安装到本地。 - -### 前提条件 - -先要在本地安装Node.js和hpm命令行工具,安装步骤如下: - -1. 安装Node.js。 - - 官网下载并在本地安装Node.js. - - 推荐安装 [Node.js](https://nodejs.org/) 12.x \(包含 npm 6.14.4\)或更高版本 \(推荐 12.13.0+\)。 - -2. 通过Node.js自带的npm安装hpm命令行工具。 - - 打开CMD,执行以下命令: - - ``` - npm install -g @ohos/hpm-cli - ``` - -3. 安装完成后执行如下命令,显示hpm版本,即安装成功。 - - ``` - hpm -V 或 hpm --version - ``` - -4. 如果升级hpm的版本,请执行如下命令: - - ``` - npm update -g @ohos/hpm-cli - ``` - - -### 操作步骤 - -1. 查找发行版。 - 1. 打开包管理页面[HPM](https://hpm.harmonyOS.com),设定搜索的对象为“发行版“,如下图所示。 - 2. 在搜索框输入关键字搜索,如“摄像头”。 - 3. 结果中显示与关键字匹配的发行版,可以进一步根据组件类别等过滤条件(如:适配的开发板,内核)精确筛选。 - 4. 查找合适的发行版,点击查看发行版的详情介绍。 - - **图 1** 包管理 - - - ![](figures/zh-cn_image_0000001119915556.png) - - -2. 了解发行版详情。 - - 1. 仔细阅读发行版的说明信息,以了解使用场景、特性、组件构成、使用方法以及如何进行定制化,如下图所示。 - 2. 点击「直接下载」,将发行版下载到本地。 - 3. 点击「定制组件」,将对发行版包含的组件进行定制(添加/删除)。 - - **图 2** 发行版示例 - - - ![](figures/zh-cn_image_0000001119755646.png) - -3. 定制组件。 - 1. 进入发行版的定制页面,如下图所示。 - 2. 通过关闭开关移除可选组件,或者通过“添加组件”增加新的组件。 - 3. 在右边填写您的项目基本信息,包括名称、版本、描述等信息。 - 4. 点击“下载“,系统会根据您的选择,生成相应的OpenHarmony代码结构文件\(如my\_cust\_dist.zip\),保存至本地文件。 - - **图 3** 组件定制 - - - ![](figures/zh-cn_image_0000001166715379.png) - - -4. 下载安装组件。 - 1. 解压下载的压缩文件,用命令行工具CMD(Linux下的Shell终端) - 2. 在解压后的文件目录下执行hpm install指令 - 3. 下载的组件存在工程目录下的ohos\_bundles文件夹中(部分组件安装后会将源码复制到指定目录下)。 - - -## 获取方式3:从镜像站点获取 - -为了获得更好的下载性能,您可以选择从以下站点的镜像库获取源码或者对应的解决方案。 - ->![](public_sys-resources/icon-note.gif) **说明:** ->- 本部分只提供**OpenHarmony** Master最新版本和LTS最新版本的源码获取方式, 其他版本源码获取方式以及具体版本信息请参考[Release-Notes](https://gitee.com/openharmony/docs/blob/master/zh-cn/release-notes/OpenHarmony-Release-Notes.md) ->- 当前Master 1.0版本已经不再维护。 - -**表 1** 源码获取路径 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    LTS版本源码

    -

    版本信息

    -

    下载站点

    -

    SHA256校验码

    -

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

    -

    1.1.1

    -

    站点

    -

    SHA256 校验码

    -

    Hi3861解决方案(二进制)

    -

    1.1.1

    -

    站点

    -

    SHA256 校验码

    -

    Hi3518解决方案(二进制)

    -

    1.1.1

    -

    站点

    -

    SHA256 校验码

    -

    Hi3516解决方案(二进制)

    -

    1.1.1

    -

    站点

    -

    SHA256 校验码

    -

    RELEASE-NOTES

    -

    1.1.1

    -

    站点

    -

    -

    -

    Master版本源码

    -

    版本信息

    -

    下载站点

    -

    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(不再维护)

    -

    站点

    -

    -

    -

    编译工具链

    -

    版本信息

    -

    下载站点

    -

    SHA256校验码

    -

    编译工具链获取清单

    -

    -

    -

    站点

    -

    -

    -
    - -## 源码目录简介 - -下表是OpenHarmony源码的目录及简单说明: - -**表 2** 源码目录 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    目录名

    -

    描述

    -

    applications

    -

    应用程序样例,包括camera等

    -

    base

    -

    基础软件服务子系统集&硬件服务子系统集

    -

    build

    -

    组件化编译、构建和配置脚本

    -

    docs

    -

    说明文档

    -

    domains

    -

    增强软件服务子系统集

    -

    drivers

    -

    驱动子系统

    -

    foundation

    -

    系统基础能力子系统集

    -

    kernel

    -

    内核子系统

    -

    prebuilts

    -

    编译器及工具链子系统

    -

    test

    -

    测试子系统

    -

    third_party

    -

    开源第三方组件

    -

    utils

    -

    常用的工具集

    -

    vendor

    -

    厂商提供的软件

    -

    build.py

    -

    编译脚本文件

    -
    - diff --git "a/zh-cn/device-dev/get-code/\350\216\267\345\217\226\345\267\245\345\205\267.md" "b/zh-cn/device-dev/get-code/\350\216\267\345\217\226\345\267\245\345\205\267.md" deleted file mode 100755 index eeb55c7156..0000000000 --- "a/zh-cn/device-dev/get-code/\350\216\267\345\217\226\345\267\245\345\205\267.md" +++ /dev/null @@ -1,7 +0,0 @@ -# 获取工具 - -- **[Docker编译环境](Docker编译环境.md)** - -- **[IDE](IDE.md)** - - diff --git a/zh-cn/device-dev/glossary/Readme-CN.md b/zh-cn/device-dev/glossary/Readme-CN.md index 1e55e64c53..e69d48c937 100755 --- a/zh-cn/device-dev/glossary/Readme-CN.md +++ b/zh-cn/device-dev/glossary/Readme-CN.md @@ -1,4 +1,4 @@ -# glossary +# 术语 -- [术语](术语.md) +- [术语](glossary.md) diff --git "a/zh-cn/device-dev/glossary/\346\234\257\350\257\255.md" b/zh-cn/device-dev/glossary/glossary.md old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/glossary/\346\234\257\350\257\255.md" rename to zh-cn/device-dev/glossary/glossary.md diff --git a/zh-cn/device-dev/glossary/public_sys-resources/icon-caution.gif b/zh-cn/device-dev/glossary/public_sys-resources/icon-caution.gif deleted file mode 100755 index 6e90d7cfc2193e39e10bb58c38d01a23f045d571..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 580 zcmV-K0=xZ3Nk%w1VIu$?0Hp~4{QBgqmQ+MG9K51r{QB&)np^||1PlfQ%(86!{`~yv zv{XhUWKt}AZaiE{EOcHp{O-j3`t;<+eEiycJT4p@77X;(jQsMfB$R?oG%6hQ z+MMLZbQBH@)Vg&1^3?qHb(5!%>3r0+`eq=&V&E}0Dypi0000000000 z00000A^8LW000R9EC2ui03!e$000L5z=Uu}ED8YtqjJd<+B}(9bIOb$3-31_h|V>=0A{ z1Hh0#H30>fNT})^fRU_83uewx9oRr{f{Sx1Ml`t)EQ zGkHZ67&~y{W5Jpq4H_WfuLxp*3<7O}GEl;1ESe36fLNs=B0&LQM1Buf(R)qg(BRd`t1OPjI1m_q4 diff --git a/zh-cn/device-dev/glossary/public_sys-resources/icon-danger.gif b/zh-cn/device-dev/glossary/public_sys-resources/icon-danger.gif deleted file mode 100755 index 6e90d7cfc2193e39e10bb58c38d01a23f045d571..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 580 zcmV-K0=xZ3Nk%w1VIu$?0Hp~4{QBgqmQ+MG9K51r{QB&)np^||1PlfQ%(86!{`~yv zv{XhUWKt}AZaiE{EOcHp{O-j3`t;<+eEiycJT4p@77X;(jQsMfB$R?oG%6hQ z+MMLZbQBH@)Vg&1^3?qHb(5!%>3r0+`eq=&V&E}0Dypi0000000000 z00000A^8LW000R9EC2ui03!e$000L5z=Uu}ED8YtqjJd<+B}(9bIOb$3-31_h|V>=0A{ z1Hh0#H30>fNT})^fRU_83uewx9oRr{f{Sx1Ml`t)EQ zGkHZ67&~y{W5Jpq4H_WfuLxp*3<7O}GEl;1ESe36fLNs=B0&LQM1Buf(R)qg(BRd`t1OPjI1m_q4 diff --git a/zh-cn/device-dev/glossary/public_sys-resources/icon-note.gif b/zh-cn/device-dev/glossary/public_sys-resources/icon-note.gif deleted file mode 100755 index 6314297e45c1de184204098efd4814d6dc8b1cda..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 394 zcmZ?wbhEHblx7fPSjxcg=ii?@_wH=jwxy=7CMGH-B`L+l$wfv=#>UF#$gv|VY%C^b zCQFtrnKN(Bo_%|sJbO}7RAORe!otL&qo<>yq_Sq+8Xqqo5h0P3w3Lvb5E(g{p01vl zxR@)KuDH0l^z`+-dH3eaw=XqSH7aTIx{kzVBN;X&hha0dQSgWuiw0NWUvMRmkD|> diff --git a/zh-cn/device-dev/glossary/public_sys-resources/icon-notice.gif b/zh-cn/device-dev/glossary/public_sys-resources/icon-notice.gif deleted file mode 100755 index 86024f61b691400bea99e5b1f506d9d9aef36e27..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 406 zcmV;H0crk6Nk%w1VIu$@0J8u9|NsB@_xJDb@8;&_*4Ea}&d#;9wWXz{jEszHYim+c zQaU<1At50E0000000000A^8Le000gEEC2ui03!e%000R7038S%NU)&51O^i-Tu6`s z0)`MFE@;3YqD6xSC^kTNu_J>91{PH8XfZ(p1pp2-SU@u3#{mEUC}_}tg3+I#{z}{Ok@D_ZUDg- zt0stin4;pC8M{WLSlRH*1pzqEw1}3oOskyNN?j;7HD{BBZ*OEcv4HK!6Bk6beR+04 z&8}k>SkTusVTDmkyOz#5fCA$JTPGJVQvr3uZ?QzzPQFvD0rGf_PdrcF`pMs}p^BcF zKtKTd`0wipR%nKN&Wj+V}pX;WC3SdJV!a_8Qi zE7z`U*|Y^H0^}fB$R?oG%6hQ z+MMLZbQBH@)Vg&1^3?qHb(5!%>3r0+`eq=&V&E}0Dypi0000000000 z00000A^8LW000R9EC2ui03!e$000L5z=Uu}ED8YtqjJd<+B}(9bIOb$3-31_h|V>=0A{ z1Hh0#H30>fNT})^fRU_83uewx9oRr{f{Sx1Ml`t)EQ zGkHZ67&~y{W5Jpq4H_WfuLxp*3<7O}GEl;1ESe36fLNs=B0&LQM1Buf(R)qg(BRd`t1OPjI1m_q4 diff --git "a/zh-cn/device-dev/guide/Input\346\250\241\345\236\213\345\267\245\344\275\234\346\265\201\347\250\213\350\247\243\346\236\220.md" "b/zh-cn/device-dev/guide/Input\346\250\241\345\236\213\345\267\245\344\275\234\346\265\201\347\250\213\350\247\243\346\236\220.md" deleted file mode 100644 index 90604006df..0000000000 --- "a/zh-cn/device-dev/guide/Input\346\250\241\345\236\213\345\267\245\344\275\234\346\265\201\347\250\213\350\247\243\346\236\220.md" +++ /dev/null @@ -1,18 +0,0 @@ -# Input模型工作流程解析 - -为了让开发者更清晰的了解Input模型工作流程,本节将对input模型加载的关键流程代码进行说明。 - ->![](public_sys-resources/icon-notice.gif) **须知:** ->本章节为Input模型工作流程说明,开发者无需进行开发。 - -- **[私有配置信息解析](私有配置信息解析.md)** - -- **[管理驱动层初始化及注册驱动至HDF框架](管理驱动层初始化及注册驱动至HDF框架.md)** - -- **[公共驱动层初始化及注册驱动至HDF框架](公共驱动层初始化及注册驱动至HDF框架.md)** - -- **[器件驱动层初始化及注册驱动至HDF框架](器件驱动层初始化及注册驱动至HDF框架.md)** - -- **[具体调用逻辑串联函数](具体调用逻辑串联函数.md)** - - diff --git "a/zh-cn/device-dev/guide/Input\346\250\241\345\236\213\347\256\200\344\273\213.md" "b/zh-cn/device-dev/guide/Input\346\250\241\345\236\213\347\256\200\344\273\213.md" deleted file mode 100644 index 2ad3264215..0000000000 --- "a/zh-cn/device-dev/guide/Input\346\250\241\345\236\213\347\256\200\344\273\213.md" +++ /dev/null @@ -1,12 +0,0 @@ -# Input模型简介 - -Input驱动模型核心部分由设备管理层、公共驱动层、器件驱动层组成。其中: - -- 设备管理层:主要为各类输入设备驱动提供input设备的注册、注销接口,同时统一管理input设备列表; -- 公共驱动层:负责对板级硬件进行初始化、硬件中断处理、向manager注册input设备等; -- 器件驱动层:通过适配平台驱动预留的差异化接口,实现器件驱动开发量最小化; - -此外,Input模型预先实现了数据通道以及设备配置信息解析等函数。 - -关于Input模型的详细介绍请参考《[Touchscreen开发概述](../driver/Touchscreen开发概述.md)》。 - diff --git "a/zh-cn/device-dev/guide/LED\345\244\226\350\256\276\346\216\247\345\210\266.md" "b/zh-cn/device-dev/guide/LED\345\244\226\350\256\276\346\216\247\345\210\266.md" deleted file mode 100755 index fc94423bf4..0000000000 --- "a/zh-cn/device-dev/guide/LED\345\244\226\350\256\276\346\216\247\345\210\266.md" +++ /dev/null @@ -1,9 +0,0 @@ -# LED外设控制 - -- **[概述](概述.md)** - -- **[开发](开发.md)** - -- **[验证](验证.md)** - - diff --git a/zh-cn/device-dev/guide/Readme-CN.md b/zh-cn/device-dev/guide/Readme-CN.md index 6afa218aca..b447b4990a 100755 --- a/zh-cn/device-dev/guide/Readme-CN.md +++ b/zh-cn/device-dev/guide/Readme-CN.md @@ -1,74 +1,39 @@ -# 开发示例 +# 设备开发指南 + +- [WLAN连接类产品](device-wifi.md) + - [LED外设控制](device-wifi-led-outcontrol.md) + - [集成三方SDK](device-wifi-sdk.md) + +- [无屏摄像头类产品](device-iotcamera.md) + - [概述](device-iotcamera-control-overview.md) + - [示例开发](device-iotcamera-control-demo.md) + - [拍照开发指导](device-iotcamera-control-demo-photodevguide.md) + - [录像开发指导](device-iotcamera-control-demo-videodevguide.md) + + - [应用实例](device-iotcamera-control-example.md) + +- [带屏摄像头类产品](device-camera.md) + - [屏幕和摄像头控制](device-camera-control.md) + - [概述](device-camera-control-overview.md) + - [示例开发](device-camera-control-demo.md) + - [拍照开发指导](device-camera-control-demo-photoguide.md) + - [录像开发指导](device-camera-control-demo-videoguide.md) + - [预览开发指导](device-camera-control-demo-previewguide.md) + + - [应用实例](device-camera-control-example.md) + + - [视觉应用开发](device-camera-visual.md) + - [概述](device-camera-visual-overview.md) + - [开发准备](device-camera-visual-prepare.md) + - [添加页面](device-camera-visual-addpage.md) + - [开发首页](device-camera-visual-first-page.md) + - [开发详情页](device-camera-visual-details.md) + - [调试打包](device-camera-visual-debug.md) + - [真机运行](device-camera-visual-run.md) + - [常见问题](device-camera-visual-faqs.md) + +- [时钟应用开发指导](device-clock-guide.md) +- [平台驱动开发示例](device-drive-demo.md) +- [外设驱动开发示例](device-outerdrive-demo.md) -- [WLAN连接类产品](WLAN连接类产品.md) - - [LED外设控制](LED外设控制.md) - - [概述](概述.md) - - [开发](开发.md) - - [验证](验证.md) - - - [集成三方SDK](集成三方SDK.md) - -- [无屏摄像头类产品](无屏摄像头类产品.md) - - [摄像头控制](摄像头控制.md) - - [概述](概述-0.md) - - [示例开发](示例开发.md) - - [拍照开发指导](拍照开发指导.md) - - [录像开发指导](录像开发指导.md) - - - [应用实例](应用实例.md) - -- [带屏摄像头类产品](带屏摄像头类产品.md) - - [屏幕和摄像头控制](屏幕和摄像头控制.md) - - [概述](概述-1.md) - - [示例开发](示例开发-2.md) - - [拍照开发指导](拍照开发指导-3.md) - - [录像开发指导](录像开发指导-4.md) - - [预览开发指导](预览开发指导.md) - - - [应用实例](应用实例-5.md) - - - [视觉应用开发](视觉应用开发.md) - - [概述](概述-6.md) - - [开发准备](开发准备.md) - - [添加页面](添加页面.md) - - [开发首页](开发首页.md) - - [开发详情页](开发详情页.md) - - [调试打包](调试打包.md) - - [真机运行](真机运行.md) - - [常见问题](常见问题.md) - -- [时钟应用开发示例](时钟应用开发示例.md) - - [概述](概述-7.md) - - [开发准备](开发准备-8.md) - - [开发步骤](开发步骤.md) - - [签名打包](签名打包.md) - - [真机运行](真机运行-9.md) - -- [平台驱动开发示例](平台驱动开发示例.md) - - [概述](概述-10.md) - - [环境准备](环境准备.md) - - [开发](开发-11.md) - - [编译及烧录](编译及烧录.md) - -- [外设驱动开发示例](外设驱动开发示例.md) - - [概述](概述-12.md) - - [硬件资源介绍](硬件资源介绍.md) - - [Input模型简介](Input模型简介.md) - - - [环境搭建](环境搭建.md) - - [TouchScreen器件驱动开发](TouchScreen器件驱动开发.md) - - [配置设备描述信息](配置设备描述信息.md) - - [配置Touchscreen器件信息](配置Touchscreen器件信息.md) - - [适配器件私有驱动](适配器件私有驱动.md) - - - [编译及烧录](编译及烧录-13.md) - - [调试验证](调试验证.md) - - [开机日志分析](开机日志分析.md) - - - [Input模型工作流程解析](Input模型工作流程解析.md) - - [私有配置信息解析](私有配置信息解析.md) - - [管理驱动层初始化及注册驱动至HDF框架](管理驱动层初始化及注册驱动至HDF框架.md) - - [公共驱动层初始化及注册驱动至HDF框架](公共驱动层初始化及注册驱动至HDF框架.md) - - [器件驱动层初始化及注册驱动至HDF框架](器件驱动层初始化及注册驱动至HDF框架.md) - - [具体调用逻辑串联函数](具体调用逻辑串联函数.md) diff --git "a/zh-cn/device-dev/guide/TouchScreen\345\231\250\344\273\266\351\251\261\345\212\250\345\274\200\345\217\221.md" "b/zh-cn/device-dev/guide/TouchScreen\345\231\250\344\273\266\351\251\261\345\212\250\345\274\200\345\217\221.md" deleted file mode 100644 index ef2d3835fa..0000000000 --- "a/zh-cn/device-dev/guide/TouchScreen\345\231\250\344\273\266\351\251\261\345\212\250\345\274\200\345\217\221.md" +++ /dev/null @@ -1,17 +0,0 @@ -# TouchScreen器件驱动开发 - -基于Input模型适配一款触摸屏IC需要完成的工作有: - -1.配置设备描述信息。驱动注册到HDF框架所需要的设备驱动描述信息,如驱动是否加载以及加载次序等; - -2.配置器件私有信息、平台硬件信息。器件私有信息包括上下电时序等,平台硬件信息包括器件连接主板的GPIO端口信息等。 - -3.适配器件私有驱动。 Input模型对Input设备开发流程进行了抽象,开发者只需要适配器件驱动层,无需改动管理驱动层以及公共驱动层。 - -- **[配置设备描述信息](配置设备描述信息.md)** - -- **[配置Touchscreen器件信息](配置Touchscreen器件信息.md)** - -- **[适配器件私有驱动](适配器件私有驱动.md)** - - diff --git "a/zh-cn/device-dev/guide/WLAN\350\277\236\346\216\245\347\261\273\344\272\247\345\223\201.md" "b/zh-cn/device-dev/guide/WLAN\350\277\236\346\216\245\347\261\273\344\272\247\345\223\201.md" deleted file mode 100755 index 08afdfcafc..0000000000 --- "a/zh-cn/device-dev/guide/WLAN\350\277\236\346\216\245\347\261\273\344\272\247\345\223\201.md" +++ /dev/null @@ -1,7 +0,0 @@ -# WLAN连接类产品 - -- **[LED外设控制](LED外设控制.md)** - -- **[集成三方SDK](集成三方SDK.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 new file mode 100644 index 0000000000..0cae9c359b --- /dev/null +++ b/zh-cn/device-dev/guide/device-camera-control-demo-photoguide.md @@ -0,0 +1,396 @@ +# 拍照开发指导 + +- [使用场景](#zh-cn_topic_0000001052170554_section1963312376119) +- [接口说明](#zh-cn_topic_0000001052170554_section56549532016) +- [约束与限制](#zh-cn_topic_0000001052170554_section1165911177314) +- [开发步骤](#zh-cn_topic_0000001052170554_section138543918214) + +## 使用场景 + +使用Camera产生图片帧(拍照)。 + +## 接口说明 + +**表 1** API列表 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    类名

    +

    接口名

    +

    描述

    +

    CameraKit

    +

    int32_t GetCameraIds(std::list<string> cameraList)

    +

    获取cameraId列表

    +

    CameraKit

    +

    CameraAbility& GetCameraAbility(string cameraId)

    +

    获取指定camera的能力

    +

    CameraKit

    +

    void RegisterCameraDeviceCallback(CameraDeviceCallback* callback, EventHandler* handler)

    +

    注册camera设备状态回调

    +

    CameraKit

    +

    void UnregisterCameraDeviceCallback(CameraDeviceCallback* callback)

    +

    去注册camera设备状态回调

    +

    CameraKit

    +

    void CreateCamera(string cameraId, CameraStateCallback* callback, EventHandler* handler)

    +

    创建camera实例

    +

    Camera

    +

    string GetCameraId()

    +

    获取cameraID

    +

    Camera

    +

    CameraConfig& GetCameraConfig()

    +

    获取camera配置信息

    +

    Camera

    +

    FrameConfig& GetFrameConfig(int32_t type)

    +

    获取捕获帧类型

    +

    Camera

    +

    void Configure(CameraConfig& config)

    +

    配置camera

    +

    Camera

    +

    void Release()

    +

    释放camera

    +

    Camera

    +

    int TriggerLoopingCapture(FrameConfig& frameConfig)

    +

    开始循环帧捕获

    +

    Camera

    +

    void StopLoopingCapture()

    +

    停止循环帧捕获

    +

    Camera

    +

    int32_t TriggerSingleCapture(FrameConfig& frameConfig)

    +

    抓图

    +

    CameraConfig

    +

    void SetFrameStateCallback(FrameStateCallback* callback, EventHandler* handler);

    +

    设置帧状态回调

    +

    CameraConfig

    +

    static CameraConfig* CreateCameraConfig()

    +

    创建camera配置信息实例

    +

    CameraAbility

    +

    std::list<Size> GetSupportedSizes(int format)

    +

    根据类型获取支持输出图像尺寸大小

    +

    CameraAbility

    +

    std::list<T> GetParameterRange(uint32_t key)

    +

    获取支持的参数范围

    +

    CameraDevice

    +

    CameraDeviceCallback()

    +

    camera设备回调类构造函数

    +

    CameraDevice

    +

    void OnCameraStatus​(std::string cameraId, int32_t status)

    +

    camera设备状态变化时的回调

    +

    CameraStateCallback

    +

    CameraStateCallback​()

    +

    camera状态回调类构造函数

    +

    CameraStateCallback

    +

    void OnConfigured​(Camera& camera)

    +

    camera配置成功回调

    +

    CameraStateCallback

    +

    void OnConfigureFailed​(Camera& camera,int32_t errorCode)

    +

    camera配置失败回调

    +

    CameraStateCallback

    +

    void OnCreated​(Camera& camera)

    +

    camera创建成功回调

    +

    CameraStateCallback

    +

    void OnCreateFailed​(std::string cameraId,int32_t errorCode)

    +

    camera创建失败回调

    +

    CameraStateCallback

    +

    void OnReleased​(Camera& camera)

    +

    camera释放回调

    +

    FrameStateCallback

    +

    FrameStateCallback​()

    +

    帧状态回调类构造函数

    +

    FrameStateCallback

    +

    void OnFrameFinished(Camera& camera, FrameConfig& frameConfig, FrameResult& frameResult)

    +

    拍照帧完成回调

    +

    FrameStateCallback

    +

    void OnFrameError​(Camera& camera, FrameConfig& frameConfig, int32_t errorCode, FrameResult& frameResult)

    +

    拍照帧异常回调

    +

    FrameConfig

    +

    int32_t GetFrameConfigType()

    +

    获取帧配置类型

    +

    FrameConfig

    +

    std::list<OHOS::Surface> GetSurfaces()

    +

    获取帧配置的surface

    +

    FrameConfig

    +

    void AddSurface(OHOS::AGP::UISurface& surface);

    +

    添加surface

    +

    FrameConfig

    +

    void RemoveSurface(OHOS::AGP::UISurface& surface);

    +

    删除surface

    +
    + +## 约束与限制 + +无。 + +## 开发步骤 + +1. 实现设备状态回调的派生类,用户在设备状态发生变更(如新插入相机设备/相机掉线)时,自定义操作。 + + ``` + class SampleCameraDeviceCallback : public CameraDeviceCallback { + void OnCameraStatus(std::string cameraId, int32_t status) override + { + //do something when camera is available/unavailable + } + }; + ``` + +2. 实现帧事件回调的派生类,这里在拿到帧数据以后将其转存为文件。 + + ``` + static void SampleSaveCapture(const char *p, uint32_t size) + { + cout << "Start saving picture" << endl; + struct timeval tv; + gettimeofday(&tv, NULL); + struct tm *ltm = localtime(&tv.tv_sec); + if (ltm != nullptr) { + ostringstream ss("Capture_"); + ss << "Capture" << ltm->tm_hour << "-" << ltm->tm_min << "-" << ltm->tm_sec << ".jpg"; + + ofstream pic("/sdcard/" + ss.str(), ofstream::out | ofstream::trunc); + cout << "write " << size << " bytes" << endl; + pic.write(p, size); + cout << "Saving picture end" << endl; + } + } + + class TestFrameStateCallback : public FrameStateCallback { + void OnFrameFinished(Camera &camera, FrameConfig &fc, FrameResult &result) override + { + cout << "Receive frame complete inform." << endl; + if (fc.GetFrameConfigType() == FRAME_CONFIG_CAPTURE) { + cout << "Capture frame received." << endl; + list surfaceList = fc.GetSurfaces(); + for (Surface *surface : surfaceList) { + SurfaceBuffer *buffer = surface->AcquireBuffer(); + if (buffer != nullptr) { + char *virtAddr = static_cast(buffer->GetVirAddr()); + if (virtAddr != nullptr) { + SampleSaveCapture(virtAddr, buffer->GetSize()); + } + surface->ReleaseBuffer(buffer); + } + delete surface; + } + delete &fc; + } + } + }; + ``` + +3. 实现相机状态回调的派生类,当相机状态发生变化(配置成功/失败,创建成功/失败\)时,自定义操作。 + + ``` + class SampleCameraStateMng : public CameraStateCallback { + public: + SampleCameraStateMng() = delete; + SampleCameraStateMng(EventHandler &eventHdlr) : eventHdlr_(eventHdlr) {} + ~SampleCameraStateMng() + { + if (recordFd_ != -1) { + close(recordFd_); + } + } + void OnCreated(Camera &c) override + { + cout << "Sample recv OnCreate camera." << endl; + auto config = CameraConfig::CreateCameraConfig(); + config->SetFrameStateCallback(&fsCb_, &eventHdlr_); + c.Configure(*config); + cam_ = &c; + } + void OnCreateFailed(const std::string cameraId, int32_t errorCode) override {} + void OnReleased(Camera &c) override {} + }; + ``` + +4. 创建CameraKit,用于创建和获取camera信息。 + + ``` + CameraKit *camKit = CameraKit::GetInstance(); + list camList = camKit->GetCameraIds(); + string camId; + for (auto &cam : camList) { + cout << "camera name:" << cam << endl; + const CameraAbility *ability = camKit->GetCameraAbility(cam); + /* find camera which fits user's ability */ + list sizeList = ability->GetSupportedSizes(0); + if (find(sizeList.begin(), sizeList.end(), CAM_PIC_1080P) != sizeList.end()) { + camId = cam; + break; + } + } + ``` + +5. 创建Camera实例。 + + ``` + EventHandler eventHdlr; // Create a thread to handle callback events + SampleCameraStateMng CamStateMng(eventHdlr); + + 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需要设计同步机制。 + + ``` + void OnCreated(Camera &c) override + { + cout << "Sample recv OnCreate camera." << endl; + auto config = CameraConfig::CreateCameraConfig(); + config->SetFrameStateCallback(&fsCb_, &eventHdlr_); + c.Configure(*config); + cam_ = &c; + } + + void Capture() + { + if (cam_ == nullptr) { + cout << "Camera is not ready." << endl; + return; + } + FrameConfig *fc = new FrameConfig(FRAME_CONFIG_CAPTURE); + Surface *surface = Surface::CreateSurface(); + if (surface == nullptr) { + delete fc; + return; + } + surface->SetWidthAndHeight(1920, 1080); /* 1920:width,1080:height */ + fc->AddSurface(*surface); + cam_->TriggerSingleCapture(*fc); + } + ``` + + diff --git "a/zh-cn/device-dev/guide/\351\242\204\350\247\210\345\274\200\345\217\221\346\214\207\345\257\274.md" b/zh-cn/device-dev/guide/device-camera-control-demo-previewguide.md old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/guide/\351\242\204\350\247\210\345\274\200\345\217\221\346\214\207\345\257\274.md" rename to zh-cn/device-dev/guide/device-camera-control-demo-previewguide.md diff --git "a/zh-cn/device-dev/guide/\345\275\225\345\203\217\345\274\200\345\217\221\346\214\207\345\257\274-4.md" b/zh-cn/device-dev/guide/device-camera-control-demo-videoguide.md old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/guide/\345\275\225\345\203\217\345\274\200\345\217\221\346\214\207\345\257\274-4.md" rename to zh-cn/device-dev/guide/device-camera-control-demo-videoguide.md diff --git a/zh-cn/device-dev/guide/device-camera-control-demo.md b/zh-cn/device-dev/guide/device-camera-control-demo.md new file mode 100644 index 0000000000..3d42880861 --- /dev/null +++ b/zh-cn/device-dev/guide/device-camera-control-demo.md @@ -0,0 +1,9 @@ +# 示例开发 + +- **[拍照开发指导](device-camera-control-demo-photoguide.md)** + +- **[录像开发指导](device-camera-control-demo-videoguide.md)** + +- **[预览开发指导](device-camera-control-demo-previewguide.md)** + + diff --git a/zh-cn/device-dev/guide/device-camera-control-example.md b/zh-cn/device-dev/guide/device-camera-control-example.md new file mode 100644 index 0000000000..a092908acd --- /dev/null +++ b/zh-cn/device-dev/guide/device-camera-control-example.md @@ -0,0 +1,63 @@ +# 应用实例 + +本示例将运行源码中的camera示例代码,通过本示例可以实现对开发板拍照、录像及预览功能的控制。 + +- 本示例源码路径为“applications/sample/camera/media/camera\_sample.cpp”。 +- 在运行本示例前需先完成编译烧录、运行镜像等步骤,相关操作请参考[Hi3516快速入门](../quick-start/quickstart-lite-introduction-hi3516.md#section26131214194212)。 + + >![](../public_sys-resources/icon-note.gif) **说明:** + >开发板启动后默认会加载launcher应用,应用的图形界面默认显示在媒体图层上方,会影响camera\_sample的演示结果,因此需要在编译或是打包时去掉launcher应用。 + >**修改方法:**将“build/lite/components/applications.json”中camera\_sample\_app组件的targets中"//applications/sample/camera/launcher:launcher\_hap"整行注释或删除。 + +- 本示例编译结果路径为“out/hi3516dv300/ipcamera\_hi3516dv300\_liteos/dev\_tools/bin”,为让文件能在单板中执行,可将示例文件通过读卡器复制至TF卡中,或者修改camera\_sample的编译脚本将结果文件复制至rootfs.img中。 + + 修改源码路径“applications/sample/camera/media/BUILD.gn”中第一处的output\_dir。 + + - 修改前:output\_dir = "$root\_out\_dir/dev\_ools" + - 修改后:output\_dir = "$root\_out\_dir/" + + 重新执行源码仓编译并烧写入单板后,可在单板bin目录下找到camera\_sample文件。 + + >![](../public_sys-resources/icon-notice.gif) **须知:** + >实例运行拍照和录像功能需要插入TF卡\(最大容量支持128GB\),系统启动后自动将TF卡挂载至/sdcard目录,如果在启动后插入则需要手动挂载。查看拍照和录像内容可将TF卡中内容复制到电脑中进行查看,预览功能无需TF卡。 + +- 接下来可通过以下步骤运行示例: + +1. 通过cd命令进入可执行程序的末端路径,启动camera\_sample,执行命令如下图。 + + **图 1** 启动示例 + ![](figure/启动示例.png "启动示例") + + 运行后的控制命令如串口打印所示,按s键停止当前操作(包括录像和预览),按q键退出示例程序。 + +2. 按1进行拍照,拍照的文件格式为jpg,存储在/sdcard,文件名Capture\* + + **图 2** 输入拍照指令后串口打印日志 + ![](figure/输入拍照指令后串口打印日志.png "输入拍照指令后串口打印日志") + + 若想查看保存文件,可在退出程序后进入文件系统查看,退出后重新进入请回到步骤1。 + + **图 3** 查看文件图 + ![](figure/查看文件图.png "查看文件图") + +3. 按2进行录像,录像的文件格式为mp4,存储在/sdcard,文件名Record\*,按s键停止 + + **图 4** 输入录像指令后串口打印日志 + ![](figure/输入录像指令后串口打印日志.png "输入录像指令后串口打印日志") + +4. 按3进行预览,预览图像直接送至显示屏,按s键停止。 + + **图 5** 输入预览指令后串口打印日志 + ![](figure/输入预览指令后串口打印日志.png "输入预览指令后串口打印日志") + + 预览效果如下 + + **图 6** 预览效果 + ![](figure/预览效果.jpg "预览效果") + +5. 按q键退出 + + **图 7** 输出退出指令后串口打印日志 + ![](figure/输出退出指令后串口打印日志.png "输出退出指令后串口打印日志") + + diff --git a/zh-cn/device-dev/guide/device-camera-control-overview.md b/zh-cn/device-dev/guide/device-camera-control-overview.md new file mode 100644 index 0000000000..0bf698b535 --- /dev/null +++ b/zh-cn/device-dev/guide/device-camera-control-overview.md @@ -0,0 +1,10 @@ +# 概述 + +本文档将介绍如何基于IoT Camera开发板(Hi3516DV300),利用其摄像头和屏幕,完成拍照、录像和视频预览功能。 + +通过本文档,开发者能够对OpenHarmony的摄像控制有更深入的了解,可参照本例尝试完成“智能猫眼”、“智能后视镜”、“智能带屏音箱”等设备的开发。 + +若开发者想先查看示例效果,请进入[应用实例](device-camera-control-example.md)。如需自定义应用行为,可参考下节“示例开发”对示例代码进行修改。 + +相机应用开发的基本概念请参考:[相机开发概述](../subsystems/subsys-multimedia-camera-overview.md)。 + diff --git a/zh-cn/device-dev/guide/device-camera-control.md b/zh-cn/device-dev/guide/device-camera-control.md new file mode 100644 index 0000000000..a3e406a2e3 --- /dev/null +++ b/zh-cn/device-dev/guide/device-camera-control.md @@ -0,0 +1,9 @@ +# 屏幕和摄像头控制 + +- **[概述](device-camera-control-overview.md)** + +- **[示例开发](device-camera-control-demo.md)** + +- **[应用实例](device-camera-control-example.md)** + + diff --git a/zh-cn/device-dev/guide/device-camera-visual-addpage.md b/zh-cn/device-dev/guide/device-camera-visual-addpage.md new file mode 100644 index 0000000000..3929ffbf6a --- /dev/null +++ b/zh-cn/device-dev/guide/device-camera-visual-addpage.md @@ -0,0 +1,34 @@ +# 添加页面 + +- [创建首页面](#section16935511143715) +- [创建详情页](#section122131729173819) + +## 创建首页面 + +空气质量监测App包含两个界面(Page),工程创建完成后会生成一个名为index的Page,可以作为首页。工程目录如下图所示: + +**图 1** 工程目录 +![](figure/工程目录.png "工程目录") + +## 创建详情页 + +新增一个Page,作为详情页,具体步骤如下: + +1. pages目录右键 ,弹出的菜单中选择New、JS Page。 + + **图 2** 添加页面 + ![](figure/添加页面.png "添加页面") + +2. 输入Page名称。 + + **图 3** 输入页面名称 + ![](figure/输入页面名称.png "输入页面名称") + +3. 确认创建结果。 + + 详情页创建完成后应用工程目录如下图所示,每个Page包括三个文件:布局文件hml、样式文件css、业务逻辑代码js。 + + **图 4** 完整工程目录 + ![](figure/完整工程目录.png "完整工程目录") + + diff --git a/zh-cn/device-dev/guide/device-camera-visual-debug.md b/zh-cn/device-dev/guide/device-camera-visual-debug.md new file mode 100644 index 0000000000..30505bcb3e --- /dev/null +++ b/zh-cn/device-dev/guide/device-camera-visual-debug.md @@ -0,0 +1,4 @@ +# 调试打包 + +代码编写完成后,可以进行调试和打包;应用调试及打包方法可以参考[《DevEco Studio使用指南》](https://developer.harmonyos.com/cn/docs/documentation/doc-guides/tools_overview-0000001053582387)的[应用调测](https://developer.harmonyos.com/cn/docs/documentation/doc-guides/ide_debug_device-0000001053822404)和[编译构建](https://developer.harmonyos.com/cn/docs/documentation/doc-guides/build_overview-0000001055075201)章节。IPCamera应用暂时不支持签名模式,所以需要将应用发布为未签名的应用安装包。 + diff --git "a/zh-cn/device-dev/guide/\345\274\200\345\217\221\350\257\246\346\203\205\351\241\265.md" b/zh-cn/device-dev/guide/device-camera-visual-details.md old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/guide/\345\274\200\345\217\221\350\257\246\346\203\205\351\241\265.md" rename to zh-cn/device-dev/guide/device-camera-visual-details.md diff --git "a/zh-cn/device-dev/guide/\345\270\270\350\247\201\351\227\256\351\242\230.md" b/zh-cn/device-dev/guide/device-camera-visual-faqs.md old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/guide/\345\270\270\350\247\201\351\227\256\351\242\230.md" rename to zh-cn/device-dev/guide/device-camera-visual-faqs.md diff --git a/zh-cn/device-dev/guide/device-camera-visual-first-page.md b/zh-cn/device-dev/guide/device-camera-visual-first-page.md new file mode 100644 index 0000000000..354097ab25 --- /dev/null +++ b/zh-cn/device-dev/guide/device-camera-visual-first-page.md @@ -0,0 +1,581 @@ +# 开发首页 + +应用首页主要展示城市的空气质量概况。首页总共有两屏(可以根据需求设置多屏),每屏显示一个城市的空气质量信息:主要包括AQI指数、城市名称、污染物指数、更新时间和信息来源等数据。 + +从第一章节中的[显示效果图](device-camera-visual-overview.md#fig18250512195914)分析可知,首页由三部分组成: + +- 标题栏:位于页面正上方,位置固定,包括应用退出按钮和页面标题。 +- 信息栏:主要展示城市的空气信息指标等内容;该页面根据用户需求可设置多屏,且能循环滑动。 +- 页面位置指示器:主要功能是标识当前页面,位置固定在页面底部的中间。 + +综上,我们可搭建一个纵向三行排列的弹性页面布局来实现首页的功能。 + +1. 在hml文件中添加一个根节点div,注意每个hml文件中有且只能有一个根节点,代码如下: + + ``` +
    +
    + ``` + + class="container"表示组件使用的样式,container是index.css文件中的一个样式类,代码如下: + + ``` + .container { + flex-direction: column; + height: 480px; + width: 960px; + } + ``` + + 在这个样式类中,我们分别设置了根组件div的高度和宽度(注意在应用的开发过程中,除部分组件(text)外必须显式指定组件的高度和宽度,否则可能无法显示)、并将flex-direction属性设置为column,该属性表示div的子组件是垂直方向从上到下排列;这样就可以实现本节开头所说的纵向三行排列的弹性页面布局。 + +2. 实现标题栏:标题栏包括一个退出按钮和一个标题,两个控件是横向排列;首先添加一个div,并设置flex-direction的属性为row,表示子组件是水平方向从左往右排列;然后依次添加一个image和text组件,代码如下: + + ``` +
    +
    + + + 空气质量 + +
    +
    + ``` + + 设置组件的高度、边距、颜色等属性。 + + ``` + .header { + width: 960px; + height: 72px; + } + .back { + width: 36px; + height: 36px; + margin-left: 39px; + margin-top: 23px; + } + .title { + width: 296px; + height: 40px; + margin-top: 20px; + margin-left: 21px; + color: #e6e6e6; + } + ``` + + onclick="exitApp" 设置了div组件的click事件,当在标题栏上触发点击事件时,就会执行函数exitApp,该函数位于index.js文件中,代码如下: + + ``` + exitApp() { + console.log('start exit'); + app.terminate(); + console.log('end exit'); + } + ``` + + app.terminate\(\)函数实现了程序退出功能;在使用该函数前,需要引入app模块,在js文件的最上方写如下代码: + + ``` + import app from '@system.app' + ``` + + 代码编写完成后,在模拟器中运行项目,显示效果如下图所示: + + **图 1** 标题栏效果 + ![](figure/标题栏效果.png "标题栏效果") + +3. 实现城市空气质量信息的多屏左右滑动,需要使用“swiper”组件。 + + 在根节点中添加一个子节点swiper,代码片段如下: + + ``` +
    +
    + + + 空气质量 + +
    + + +
    + ``` + + - class="swiper"设置了组件的高度和宽度,代码如下: + + ``` + .swiper { + height: 385px; + width: 960px; + } + ``` + + + - index="\{\{swiperPage\}\}" duration="500" onchange="swiperChange" 这些代码用来设置组件的属性和事件。其中,duration="500" 表示设置swiper的页面滑动的动画时长为500ms。 + - index="\{\{swiperPage\}\}"设置了swiper子组件索引值,\{\{swiperPage\}\}这种写法表示index的值是和js代码中的swiperPage变量动态绑定的,index的值会随着swiperPage变动而改变。 + - onchange="swiperChange" 设置了swiper组件的change事件和函数swiperChange绑定,对应的js代码如下: + + ``` + //引入router模块,用户页面跳转 + import router from'@system.router' + import app from '@system.app' + + export default { + //定义参数 + data: { + //默认是第一页 + swiperPage: 0 + }, + onInit () { + }, + exitApp(){ + console.log('start exit'); + app.terminate(); + console.log('end exit'); + }, + //swiper滑动回调事件,保存当前swiper的index值,每次滑动都会将index值保存在swiperPage变量中 + swiperChange (e) { + this.swiperPage = e.index; + } + } + ``` + + +4. 设置一个城市的空气质量信息为一屏,在一屏内,要展示多种信息,分别使用不同的控件进行展示。 + + 在swiper中添加两个子组件stack(绝对布局),每个stack组件内分别添加text、image、progress等组件来显示对应的信息 ,页面结构如下: + + ``` + + + + ------空气质量 + ------城市名称 + -----进度条 + -------云朵图片 + --------AQI数值 + AQI------AQI +
    --------空气指标详细信息 +
    +
    --------更新时间和网站等信息 +
    +
    + + + + + + + + +
    +
    +
    + ``` + + 代码编写完成后,模拟器运行效果如下: + + **图 2** 标题栏和信息栏效果 + ![](figure/标题栏和信息栏效果.png "标题栏和信息栏效果") + +5. 添加页面位置指示器:由于当前swiper不支持设置indicator,需要开发者自己来实现该效果。在根节点中添加一个子组件div,并设置相应样式;然后在该div中添加两个子组件div,设置两个div的border-radius,并在swiper滑动事件中动态改变对应div的背景色来实现该效果。 + + ``` +
    +
    +
    +
    + ``` + + **图 3** 页面位置指示器效果图 + ![](figure/页面位置指示器效果图.png "页面位置指示器效果图") + +6. 所有组件设置样式、动画效果和数据动态绑定,完整代码如下所示: + + - **index.hml文件** + + ``` +
    +
    + + + 空气质量 + +
    + + + {{airData[0].airQuality}} + + {{airData[0].location}} + + + + {{airData[0].detailData}} + + + AQI + +
    +
    + + CO + + + 100 + +
    +
    + + NO2 + + + 90 + +
    +
    + + PM10 + + + 120 + +
    +
    + + PM2.5 + + + 40 + +
    +
    + + SO2 + + + 150 + +
    + +
    + +
    + + {{airData[1].airQuality}} + + {{airData[1].location}} + + + + {{airData[1].detailData}} + + + AQI + +
    +
    + + CO + + + 10 + +
    +
    + + NO2 + + + 50 + +
    +
    + + PM10 + + + 60 + +
    +
    + + PM2.5 + + + 40 + +
    +
    + + SO2 + + + 150 + +
    + +
    + +
    +
    +
    +
    +
    +
    +
    + ``` + + - **index.css文件** + + css文件中定义了许多class,每个class用于定义组件的位置、大小、字体、颜色、背景色等信息。同时,每一个子组件都叠加在父组件中,父组件的样式会影响子组件的呈现。 + + ``` + .aqi-value { + text-align: center; + font-size: 65px; + color: #f0ffff; + width: 156px; + height: 92px; + top: 134px; + left: 210px; + } + .aqi { + text-align: center; + color: #a2c4a2; + width: 156px; + height: 45px; + top: 90px; + left: 210px; + } + .airquality { + top: 222px; + text-align: center; + width: 156px; + height: 45px; + left: 210px; + } + .image { + top: 285px; + left: 274px; + width: 32px; + height: 32px; + } + .location-text { + text-align: center; + color: #ffffff; + width: 200px; + height: 52px; + font-size: 40px; + left: 380px; + top: 16px; + } + .container { + flex-direction: column; + height: 480px; + width: 960px; + } + .circle-progress { + center-x: 128px; + center-y: 128px; + radius: 128px; + startAngle: 198; + totalAngle: 320; + strokeWidth: 24px; + width: 256px; + height: 256px; + left: 160px; + top: 58px; + } + .detail { + width: 256px; + height: 265px; + left: 544px; + top: 58px; + flex-direction: column; + } + .text-wrapper { + width: 256px; + height: 35px; + margin-top: 6px; + } + .gas-name { + width: 128px; + height: 35px; + text-align: left; + } + .gas-value { + width: 128px; + height: 35px; + text-align: right; + } + .btn { + width: 180px; + height: 50px; + margin-top: 6px; + margin-left: 38px; + background-color: #1a1a1a; + color: #1085CE; + } + .footer { + top: 326px; + width: 960px; + height: 28px; + } + .header { + width: 960px; + height: 72px; + } + .back { + width: 36px; + height: 36px; + margin-left: 39px; + margin-top: 23px; + } + .title { + width: 296px; + height: 40px; + margin-top: 20px; + margin-left: 21px; + color: #e6e6e6; + } + .swiper { + height: 385px; + width: 960px; + } + .images { + width: 60px; + height: 15px; + margin-left: 450px; + } + .update-time { + width: 480px; + height: 28px; + font-size: 20px; + color: #A9A9A9; + text-align: right; + } + .info-source { + width: 450px; + height: 28px; + font-size: 20px; + color: #A9A9A9; + text-align: left; + margin-left: 24px; + } + .circle-div { + width: 12px; + height: 12px; + border-radius: 6px; + } + ``` + + - **index.js:** + + js文件主要用于实现App应用的逻辑交互。在本页面js文件中,需要实现如下功能:根据数值动态改变文字、进度条颜色、页面跳转。 + + ``` + //导入router和app模块 + import router from '@system.router' + import app from '@system.app' + + export default { + data: { + //页面绑定数据 + textColor1: '#00ff00', + textColor2: '#00ff00', + bgColor1: '#669966', + bgColor2: '#669966', + swiperPage: 0, + percent1: 40, + percent2: 90, + iconUncheckedColor: '#262626', + iconcheckedColor: '#ffffff', + iconcheckedBR: '6px', + src1: 'common/cloud_green.png', + src2: 'common/cloud_green.png', + airData: [{ + location: '东莞', + airQuality: '良', + detailData: 40 + }, { + location: '深圳', + airQuality: '差', + detailData: 90 + }] + }, + onInit () { + //根据数值的不同,设置不同的字体、背景颜色和图片 + if(this.airData[0].detailData > 100){ + this.src1 = 'common/cloud_red.png'; + this.textColor1 = '#ff0000'; + this.bgColor1 = '#9d7462'; + } else if(50 < this.airData[0].detailData && this.airData[0].detailData <= 100){ + this.src1 = 'common/cloud_yellow.png'; + this.textColor1 = '#ecf19a'; + this.bgColor1 = '#9d9d62'; + } + if(this.airData[1].detailData > 100){ + this.src2 = 'common/cloud_red.png'; + this.textColor2 = '#ff0000'; + this.bgColor2 = '#9d7462'; + } else if(50 < this.airData[1].detailData && this.airData[1].detailData <= 100){ + this.src2 = 'common/cloud_yellow.png'; + this.textColor2 = '#ecf19a'; + this.bgColor2 = '#9d9d62'; + } + if(this.selectedCityIndex){ + this.swiperPage = this.selectedCityIndex; + if(this.swiperPage == 0){ + this.iconcheckedColor = '#ffffff'; + this.iconUncheckedColor = '#262626'; + }else{ + this.iconcheckedColor = '#262626'; + this.iconUncheckedColor = '#ffffff'; + } + } + }, + //跳转到详情页面 + openDetail () { + router.replace({ + uri: 'pages/detail/detail', + params: {selectedCityIndex:this.swiperPage} + }); + }, + //退出应用 + exitApp(){ + console.log('start exit'); + app.terminate(); + console.log('end exit'); + }, + //页面滑动事件,滑动时改变最新的标识 + swiperChange (e) { + this.swiperPage = e.index; + if(e.index == 0){ + this.iconcheckedColor = '#ffffff'; + this.iconUncheckedColor = '#262626'; + }else{ + this.iconcheckedColor = '#262626'; + this.iconUncheckedColor = '#ffffff'; + } + } + } + ``` + + diff --git a/zh-cn/device-dev/guide/device-camera-visual-overview.md b/zh-cn/device-dev/guide/device-camera-visual-overview.md new file mode 100644 index 0000000000..a7e9895e2d --- /dev/null +++ b/zh-cn/device-dev/guide/device-camera-visual-overview.md @@ -0,0 +1,15 @@ +# 概述 + +- [效果展示](#section3997224182313) + +本文将介绍如何快速搭建基于OpenHarmony系统的行车记录仪(Hi3516DV300开发板)应用开发环境,并基于一个简易的APP示例逐步展示应用的创建、开发、调试和安装等流程。接下来本文以空气质量监测(AirQuality)App为例进行说明。 + +## 效果展示 + +空气质量监测App是一款展示城市空气质量信息的应用,有两个页面组成:首页和详情页,在DevEco Studio模拟器中的显示效果如下图所示: + +**图 1** 空气质量监测 App显示效果图 + + +![](figure/Video_2020-07-25_173141.gif) + diff --git a/zh-cn/device-dev/guide/device-camera-visual-prepare.md b/zh-cn/device-dev/guide/device-camera-visual-prepare.md new file mode 100644 index 0000000000..55ed7451c0 --- /dev/null +++ b/zh-cn/device-dev/guide/device-camera-visual-prepare.md @@ -0,0 +1,27 @@ +# 开发准备 + +- [准备开发环境](#section1912530122716) +- [创建项目](#section1456035192720) + +## 准备开发环境 + +首先需要下载和配置DevEco Studio,具体操作请参考[《DevEco Studio使用指南》](https://developer.harmonyos.com/cn/docs/documentation/doc-guides/software_install-0000001053582415)。 + +## 创建项目 + +1. 通过如下两种方式,打开工程创建向导界面。 + - 如果当前未打开任何工程,可以在DevEco Studio的欢迎页,选择**Create HarmonyOS Project**开始创建一个新工程。 + - 如果已经打开了工程,可以在菜单栏选择**File \> New \> New Project**来创建一个新工程。 + +2. 选择“Smart Vision”下的“Empty Feature Ability”模板。 + + ![](figure/zh-cn_image_0000001082434703.png) + +3. 点击**Next**,进入到工程配置阶段,需要根据向导配置工程的基本信息。 + - **Project Name**:工程的名称,可以自定义。 + - **Package Name**:软件包名称,默认情况下,应用ID也会使用该名称,应用发布时,应用ID需要唯一。 + - **Save Location**:工程文件本地存储路径,存储路径中不能包含中文字符和空格。 + - **Compatible API Version**:兼容的SDK版本。 + +4. 点击**Finish**,工具会自动生成示例代码和相关资源,等待工程创建完成。 + diff --git a/zh-cn/device-dev/guide/device-camera-visual-run.md b/zh-cn/device-dev/guide/device-camera-visual-run.md new file mode 100644 index 0000000000..3e7c3f1d16 --- /dev/null +++ b/zh-cn/device-dev/guide/device-camera-visual-run.md @@ -0,0 +1,29 @@ +# 真机运行 + +应用编译打包后即可安装到开发板。安装应用前需要先完成[DevEco Device Tool的安装配置](https://device.harmonyos.com/cn/docs/ide/user-guides/service_introduction-0000001050166905),然后将OpenHarmony烧录到开发板并运行。编译烧录、运行镜像的基本操作请参考快速入门手册:[Hi3516快速入门](../quick-start/quickstart-lite-introduction-hi3516.md#section26131214194212)。完成镜像运行,系统正常启动后,执行如下步骤安装或卸载三方应用。 + +1. 将IDE编译的未签名应用安装包和安装工具(镜像文件生成目录中的dev\_tools)放在sdcard中,将sdcard插入开发板卡槽。 +2. 应用安装默认要校验签名,需要执行以下命令,关闭签名校验。 + + ``` + ./sdcard/dev_tools/bin/bm set -s disable + ``` + +3. 执行以下命令,安装应用。 + + ``` + ./sdcard/dev_tools/bin/bm install -p /sdcard/airquality.hap + ``` + + 其中dev\_tools目录中是安装工具,airquality.hap为应用安装包,此处替换为实际工程的安装包名称。 + +4. 应用安装完成后,可点击桌面应用图标启动应用,进行操作。 + + **图 1** 桌面 + ![](figure/桌面.png "桌面") + +5. 卸载应用(可选)。 + + 长按桌面应用图标,在弹出的菜单中点击“卸载”按钮即可卸载应用。 + + diff --git a/zh-cn/device-dev/guide/device-camera-visual.md b/zh-cn/device-dev/guide/device-camera-visual.md new file mode 100644 index 0000000000..ca4e46538b --- /dev/null +++ b/zh-cn/device-dev/guide/device-camera-visual.md @@ -0,0 +1,19 @@ +# 视觉应用开发 + +- **[概述](device-camera-visual-overview.md)** + +- **[开发准备](device-camera-visual-prepare.md)** + +- **[添加页面](device-camera-visual-addpage.md)** + +- **[开发首页](device-camera-visual-first-page.md)** + +- **[开发详情页](device-camera-visual-details.md)** + +- **[调试打包](device-camera-visual-debug.md)** + +- **[真机运行](device-camera-visual-run.md)** + +- **[常见问题](device-camera-visual-faqs.md)** + + diff --git a/zh-cn/device-dev/guide/device-camera.md b/zh-cn/device-dev/guide/device-camera.md new file mode 100644 index 0000000000..7239a00d3a --- /dev/null +++ b/zh-cn/device-dev/guide/device-camera.md @@ -0,0 +1,7 @@ +# 带屏摄像头类产品 + +- **[屏幕和摄像头控制](device-camera-control.md)** + +- **[视觉应用开发](device-camera-visual.md)** + + diff --git a/zh-cn/device-dev/guide/device-clock-guide.md b/zh-cn/device-dev/guide/device-clock-guide.md new file mode 100644 index 0000000000..a615280a6e --- /dev/null +++ b/zh-cn/device-dev/guide/device-clock-guide.md @@ -0,0 +1,332 @@ +# 时钟应用开发指导 + +- [概述](#section11522349121115) +- [开发准备](#section6592121861218) +- [开发步骤](#section19901741111312) +- [签名打包](#section10601181101516) +- [真机运行](#section092721731511) +- [常见问题](#section1122413460153) + - [hdc\_std连接不到设备](#section1922725151614) + - [hdc\_std运行不了](#section15657547131615) + + +## 概述 + +本文将介绍如何快速搭建基于OpenHarmony标准系统(Hi3516DV300开发板)的应用开发环境,并基于一个时钟APP示例逐步展示应用的创建、开发、调试和安装等流程。示例代码可以通过[本链接](https://gitee.com/openharmony/app_samples/tree/master/common/Clock)获取。 + +时钟App是一款显示实时时间的应用,显示效果如下图所示: + +**图 1** 时钟应用显示效果图 + + +![](figure/Clock.png) + +## 开发准备 + +首先需要下载和配置DevEco Studio,具体操作请参考[DevEco Studio 使用指南](../../application-dev/quick-start/DevEco-Studio(OpenHarmony)使用指南.md)。 + +## 开发步骤 + +应用的功能是通过表盘和数字显示实时时间。 + +从[显示效果图](device-clock-guide.md#fig7763172132019)分析可知,页面由两个部分组成: + +- 表盘栏:主要展示一个动态的钟表,且钟表指针能准确转动。 +- 数字时间栏:主要以数字形式显示当前时间。 + +综上,我们可搭建一个纵向两行排列的弹性页面布局来实现界面的功能。具体开发步骤如下: + +1. 在hml文件中添加一个根节点div,注意每个hml文件中有且只能有一个根节点,代码如下: + + ``` +
    +
    + ``` + + class="container"表示组件使用的样式,container是index.css文件中的一个样式类,代码如下: + + ``` + .container { + flex-direction: column; + justify-content: center; + align-items: center; + width: 100%; + height: 100%; + } + ``` + + 在这个样式类中,我们分别设置了根组件div的高度和宽度(注意在应用的开发过程中,除部分组件(text)外必须显式指定组件的高度和宽度,否则可能无法显示)、并将flex-direction属性设置为column,该属性表示div的子组件是垂直方向从上到下排列;这样就可以实现本节开头所说的纵向两行排列的弹性页面布局。 + +2. 实现时钟转动,需要使用“stack”组件。“stack”组件的功能是堆叠容器,子组件按照顺序依次入栈,后一个子组件覆盖前一个子组件。 + + 在根组件下添加一个stack容器,代码片段如下: + + ``` +
    + + + + + + +
    + ``` + + style="transform : rotate\(\{\{ second \* 6 \}\}deg\) 这类代码用来设置组件的旋转事件。其中transform是设置动画平移/旋转/缩放的属性,rotate是旋转动画属性,支持设置x轴和y轴两个维度的选中参数。 + + 在css文件中设置"stack"组件样式的高度、宽度、位置等属性,代码如下: + + ``` + .stack { + flex-direction: column; + justify-content: center; + align-items: center; + width: 100%; + height: 50%; + } + ``` + + 在css文件中设置"clock-bg"组件样式的高度、宽度等属性,代码如下: + + ``` + .clock-bg { + width: 80%; + height: 80%; + object-fit: scale-down; + } + ``` + + 在css文件中设置"clock-hand"组件为时针、分针和秒针的高度、宽度等属性,代码如下: + + ``` + .clock-hand { + width: 25%; + height: 65%; + object-fit: contain; + } + ``` + + index.js中会有一个定时器实时刷新时分秒变量,从而触发时间界面自动更新。对应的js代码如下: + + ``` + export default { + timer: undefined, + //定义参数 + data: { + hour: 0, //定义小时 + minute: 0, //定义分钟 + second: 0 //定义秒 + }, + onInit () { + this.updateTime(); + this.timer = setInterval(this.updateTime, 1000)//设置1s的定时器 + }, + updateTime: function () { + var nowTime = new Date() + this.hour = nowTime.getHours() + this.minute = nowTime.getMinutes() + this.second = nowTime.getSeconds() + if (this.hour < 10) { + this.hour = '0' + this.hour + } + if (this.minute < 10) { + this.minute = '0' + this.minute + } + if (this.second < 10) { + this.second = '0' + this.second + } + }, + } + ``` + +3. 显示数字时间,在钟表下面以数字形式显示当前时间。在根布局内末尾加上text组件,页面结构如下: + + ``` + {{ hour }}:{{ minute }}:{{ second }} + ``` + + class="digit-clock"设置了组件的高度和宽度以及字体大小,其代码如下: + + ``` + .digit-clock { + font-size: 58px; + width: 100%; + margin-top: 0px; + text-align: center; + } + ``` + +4. 所有组件设置样式、动画效果和数据动态绑定,完整代码如下所示: + - **index.hml文件** + + ``` +
    + + + + + + + {{ hour }}:{{ minute }}:{{ second }} +
    + ``` + + + - **index.css文件** + + ``` + .container { + flex-direction: column; + justify-content: center; + align-items: center; + width: 100%; + height: 100%; + } + + .stack { + flex-direction: column; + justify-content: center; + align-items: center; + width: 100%; + height: 50%; + } + + .digit-clock { + font-size: 58px; + width: 100%; + margin-top: 0px; + text-align: center; + } + + .clock-bg { + width: 80%; + height: 80%; + object-fit: scale-down; + } + + .clock-hand { + width: 25%; + height: 65%; + object-fit: contain; + } + ``` + + + - **index.js:** + + js文件主要用于实现App应用的逻辑交互。在本页面js文件中,需要实现如下功能:定时获取系统时间。 + + ``` + export default { + timer: undefined, + data: { + hour: 0, + minute: 0, + second: 0 + }, + onInit() { + this.updateTime() + this.timer = setInterval(this.updateTime, 1000) + }, + updateTime: function () { + var nowTime = new Date() + this.hour = nowTime.getHours() + this.minute = nowTime.getMinutes() + this.second = nowTime.getSeconds() + if (this.hour < 10) { + this.hour = '0' + this.hour + } + if (this.minute < 10) { + this.minute = '0' + this.minute + } + if (this.second < 10) { + this.second = '0' + this.second + } + }, + onDestroy() { + clearInterval(this.timer); + } + } + ``` + + + +## 签名打包 + +代码编写完成后,在真机设备上运行应用,需要先对应用进行签名,然后再进行打包,具体操作请参考[签名打包指导](../../application-dev/quick-start/配置OpenHarmony应用签名信息.md)。 + +## 真机运行 + +应用签名打包后即可安装到开发板。安装应用前需要先完成[DevEco Device Tool的安装配置](https://device.harmonyos.com/cn/docs/ide/user-guides/service_introduction-0000001050166905),然后将OpenHarmony系统烧录到开发板并运行。编译烧录、运行镜像的基本操作请参考快速入门手册:[标准系统Hi3516快速入门](../quick-start/quickstart-standard.md)。完成镜像运行,系统正常启动后,执行如下步骤安装或卸载应用。 + +1. 从开发者工具代码仓路径中获取hdc客户端。 + + ``` + developtools/hdc_standard/prebuilt/windows/hdc_std.exe + ``` + + 修改名称为hdc.exe,并将工具路径加入系统环境path变量中。 + +2. 启动cmd命令窗口,执行以下命令,推送hap应用包到设备目录下并安装。 + + ``` + hdc smode + hdc target mount + hdc file send clock.hap /data/clock.hap + hdc shell chmod 666 /data/clock.hap + hdc shell bm install -p /data/clock.hap + ``` + +3. 启动应用。执行以下命令,其中ohos.samples.clock为应用包名,MainAbility为应用启动的Ability。 + + ``` + hdc shell aa start -d 123 -a ohos.samples.clock.MainAbility -b ohos.samples.clock + ``` + +4. 卸载应用(可选)。执行以下命令,其中ohos.samples.clock为应用包名。 + + ``` + hdc shell bm uninstall -n ohos.samples.clock + ``` + + +## 常见问题 + +### hdc\_std连接不到设备 + +- **现象描述** + + 执行 "hdc\_std list targets"命令后结果为:\[Empty\] + +- **可能原因和解决方法** + 1. 设备没有被识别: + + 在设备管理器中查看是否有hdc设备,在通用串行总线设备中会有“HDC Device”信息。如果没有,hdc无法连接。此时需要插拔设备,或者烧写最新的镜像。 + + 2. hdc\_std工作异常: + + 可以执行"hdc kill"或者"hdc start -r"杀掉hdc服务或者重启hdc服务,然后再执行hdc list targets查看是否已经可以获取设备信息。 + + 3. hdc\_std与设备不匹配: + + 如果设备烧写的是最新镜像,hdc\_std也需要使用最新版本。由于hdc\_std会持续更新,请从开源仓developtools\_hdc\_standard中获取,具体位置在该开源仓的prebuilt目录。 + + + +### hdc\_std运行不了 + +- **现象描述** + + 点击hdc\_std.exe文件无法运行。 + +- **可能原因和解决方法** + + hdc\_std.exe不需要安装,直接放到磁盘上就能使用,也可以添加到环境变量中。通过打开cmd执行hdc\_std命令直接使用。 + + diff --git a/zh-cn/device-dev/guide/device-drive-demo.md b/zh-cn/device-dev/guide/device-drive-demo.md new file mode 100644 index 0000000000..bb103f846c --- /dev/null +++ b/zh-cn/device-dev/guide/device-drive-demo.md @@ -0,0 +1,453 @@ +# 平台驱动开发示例 + +- [概述](#section194201316174215) +- [环境准备](#section6926133918422) +- [开发](#section65801539470) + - [文件说明](#section0708184454414) + - [实例化驱动入口](#section85325864412) + - [设置相关参数](#section8155172019453) + - [添加控制器](#section1335374114452) + +- [编译及烧录](#section164824754712) + +## 概述 + +本文档将以I2C驱动为例,介绍如何基于HDF驱动框架完成平台驱动开发。 + +>![](../public_sys-resources/icon-caution.gif) **注意:** +>本例仅作为平台驱动开发示例参考,开发者不可直接用于商用集成。 + +HDF驱动框架为常用外围设备提供了标准的驱动框架,驱动开发者只需将驱动适配至HDF驱动框架,即可通过HDF驱动框架提供的接口操作外围设备。 + +本文以I2C为例。其时序流程如[图1](#fig148041484161)所示。 + +**图 1** I2C时序流程图 + + +![](figure/zh-cn_image_0000001169991055.png) + +- User Business:用户业务驱动。 +- i2cManagerEntry:I2C管理器入口,注册I2cManager到HDF驱动框架。 +- I2cManager:I2C管理器,管理I2C控制器。 +- I2cCntlr:I2C控制器。 +- i2cDriverEntry:I2C控制器入口,注册I2cCntlr到HDF驱动框架。 + +## 环境准备 + +环境准备具体操作请参考[标准系统基础环境搭建](../quick-start/quickstart-standard.md)。 + +>![](../public_sys-resources/icon-notice.gif) **须知:** +>本示例针对OpenHarmony轻量系统、小型系统、标准系统都适用,本文以标准系统为例。其他系统的开发者可参考对应系统的指导文档进行环境搭建。 + +## 开发 + +### 文件说明 + +本例中涉及的文件及路径如下表: + +**表 1** 文件说明 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    说明

    +

    文件路径

    +

    操作

    +

    示例文件

    +

    /drivers/adapter/khdf/linux/platform/i2c/i2c_sample.c

    +

    新增文件

    +

    设备服务文件

    +

    /drivers/adapter/khdf/linux/hcs/device_info/device_info.hcs

    +

    +

    追加内容

    +

    +

    配置参数文件

    +

    /drivers/adapter/khdf/linux/hcs/platform/i2c_config.hcs

    +

    编译文件

    +

    /drivers/adapter/khdf/linux/platform/i2c/Makefile

    +

    依赖头文件

    +

    /drivers/framework/include/core/hdf_device_desc.h

    +

    作为头文件引用

    +

    +

    核心层头文件

    +

    /drivers/framework/support/platform/include/i2c_core.h

    +

    HCS配置入口文件

    +

    /drivers/adapter/khdf/linux/hcs/hdf.hcs

    +

    HCS配置文件总入口

    +
    + +>![](../public_sys-resources/icon-caution.gif) **注意:** +>本例程涉及的文件路径均作为演示,驱动开发者应根据实际情况确定具体的源文件存放位置。 + +### 实例化驱动入口 + +实例化一个HdfDriverEntry 对象作为驱动入口。驱动入口必须为HdfDriverEntry(在hdf\_device\_desc.h中定义)类型的全局变量,且moduleName要和device\_info.hcs中保持一致。在加载驱动时HDF框架会先调用Bind函数,再调用Init函数加载该驱动,当Init调用异常时,HDF框架会调用Release释放驱动资源并退出。 + +I2C驱动中没有实现Bind方法,因为I2C控制器由manager管理,而在manager中已经实现了Bind方法,因此I2C驱动中无需再绑定服务。 + +实例化驱动入口的示例代码如下: + +``` +/* 定义驱动入口的对象,必须为HdfDriverEntry(在hdf_device_desc.h中定义)类型的全局变量 */ +struct HdfDriverEntry g_sampleI2cDriverEntry = { + .moduleVersion = 1, + .Init = SampleI2cInit, + .Release = SampleI2cRelease, + .moduleName = "demo_i2c_driver", +}; +/* 调用HDF_INIT将驱动入口注册到HDF框架中 */ +HDF_INIT(g_sampleI2cDriverEntry); +``` + +### 设置相关参数 + +通过配置device\_info.hcs,并从HCS获取并解析设备的配置参数以确保驱动能够正确加载。 + +1. 添加设备服务节点(必选)。 + + 编辑device\_info.hcs,在device\_i2c :: device下添加驱动设备服务节点,示例如下: + + ``` + root { + device_info { + match_attr = "hdf_manager"; + device_i2c :: device { // i2c设备节点 + device2 :: deviceNode { // i2c驱动的DeviceNode节点 + policy = 0; // policy字段是驱动服务发布的策略 + priority = 55; // 驱动启动优先级 + permission = 0644; // 驱动创建设备节点权限 + moduleName = "demo_i2c_driver"; // 驱动名称,该字段的值必须和驱动入口结构的moduleName值一致 + serviceName = "DEMO_I2C_DRIVER"; // 驱动对外发布服务的名称,必须唯一 + deviceMatchAttr = "demo_i2c_config"; // 驱动私有数据匹配的关键字,必须和驱动私有数据配置表中的 + // match_attr值相等 + } + } + } + } + + ``` + + >![](../public_sys-resources/icon-notice.gif) **须知:** + >配置文件中的priority(取值范围为整数0到200)是用来表示host和驱动的优先级,不同的host内的驱动,host的priority值越小,驱动加载优先级越高;同一个host内驱动的priority值越小,加载优先级越高,驱动的priority值相同则不保证加载顺序。 + +2. 添加配置参数(可选)。 + + 有时驱动可能会需要私有配置信息,以确保寄存器的配置可以满足不同产品的需求。如需要私有配置信息,则可以添加一个驱动的配置文件,用来存放一些驱动的默认配置信息,HDF框架在加载驱动的时候,会将对应的配置信息获取并保存在HdfDeviceObject 中的property里面,通过Bind和Init(参考[驱动开发](../driver/drive-hdf-development.md))传递给驱动。驱动开发者可新建配置文件,并在板级驱动hdf.hcs中引用新建的配置文件,本例中直接在原有的配置文件i2c\_config.hcs内添加配置参数。 + + 本例中编辑i2c\_config.hcs,添加配置参数: + + ``` + root { + platform { + i2c_config_demo { + match_attr = "demo_i2c_config"; // 该字段的值必须和device_info.hcs中的deviceMatchAttr值一致 + + template i2c_controller { // 参数模板 + bus = 0; + reg_pbase = 0x120b0000; + reg_size = 0xd1; + } + + controller_demo_0 :: i2c_controller { // 两个I2C示例控制器 + bus = 8; + } + controller_demo_1 :: i2c_controller { + bus = 9; + } + } + } + } + ``` + + match\_attr字段必须与device\_info.hcs中的deviceMatch\_Attr保持一致,在此文件中配置驱动需要的参数,通过match\_attr可匹配至对应的驱动,该驱动即可在Bind或Init中调用DeviceResourceGetIfaceInstance\(\)函数获取这些配置参数。 + + 若配置文件为新文件,则需要在板级配置入口文件hdf.hcs中引用该配置文件,例如: + + ``` + #include "device_info/device_info.hcs" + #include "i2c/i2c_config.hcs" + ``` + + 由于本例中在原有的i2c\_config.hcs内添加配置参数,没有新建配置文件,因此无需再将i2c\_config.hcs添加至板级配置入口文件中。 + +3. 驱动从HCS获取配置参数。 + + 在本例中,驱动需要通过HCS获取寄存器物理基地址、寄存器大小、总线号等参数,从而对控制器进行正确配置。 + + ``` + /* 从HCS获取配置参数 */ + static int32_t SampleI2cReadDrs(struct SampleI2cCntlr *sampleCntlr, const struct DeviceResourceNode *node) + { + int32_t ret; + struct DeviceResourceIface *drsOps = NULL; + + drsOps = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE); + if (drsOps == NULL || drsOps->GetUint32 == NULL) { // 确保GetUint32方法可用 + HDF_LOGE("%s: invalid drs ops fail!", __func__); + return HDF_FAILURE; + } + + ret = drsOps->GetUint32(node, "reg_pbase", &sampleCntlr->regBasePhy, 0); // 从HCS读取物理基地址reg_pbase + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: read regBase fail!", __func__); + return ret; + } + + ret = drsOps->GetUint16(node, "reg_size", &sampleCntlr->regSize, 0); // 从HCS读取寄存器大小reg_size + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: read regsize fail!", __func__); + return ret; + } + + ret = drsOps->GetUint16(node, "bus", (uint16_t *)&sampleCntlr->bus, 0); // 从HCS读取总线号bus + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: read bus fail!", __func__); + return ret; + } + + return HDF_SUCCESS; + } + ``` + + +### 添加控制器 + +初始化控制器硬件,并调用核心层接口完成向核心层添加、删除设备,以及钩子函数的实现等。 + +1. 定义结构体,实现钩子函数并赋值至函数指针。 + + I2cMethod结构体在i2c\_core.h中定义,其中通过函数指针的方式定义了I2C需要实现的方法,transfer方法为用于传输的钩子函数,在驱动中需要做具体实现并对函数指针赋值。 + + 示例代码如下: + + ``` + /* 自定义设备结构体,继承父类I2cCntlr */ + struct SampleI2cCntlr { + struct I2cCntlr cntlr; + OsalSpinlock spin; + volatile unsigned char *regBase; + uint16_t regSize; + int16_t bus; + uint32_t regBasePhy; + }; + + /* 消息结构体,继承父类I2cMsg */ + struct SampleTransferData { + struct I2cMsg *msgs; + int16_t index; + int16_t count; + }; + /* 钩子函数实现 */ + static int32_t SampleI2cTransfer(struct I2cCntlr *cntlr, struct I2cMsg *msgs, int16_t count) + { + int32_t ret = HDF_SUCCESS; + struct SampleI2cCntlr *sampleCntlr = NULL; + struct SampleTransferData td; + + if (cntlr == NULL || cntlr->priv == NULL) { + HDF_LOGE("SampleI2cTransfer: cntlr lor sampleCntlr is null!"); + return HDF_ERR_INVALID_OBJECT; + } + sampleCntlr = (struct SampleI2cCntlr *)cntlr; + + if (msgs == NULL || count <= 0) { + HDF_LOGE("SampleI2cTransfer: err parms! count:%d", count); + return HDF_ERR_INVALID_PARAM; + } + td.msgs = msgs; + td.count = count; + td.index = 0; + + HDF_LOGE("Successfully transmitted!"); // 表示此处传输成功 + + td.index = count; // 经过处理,最后实际发送msg个数等于count,返回已发送个数,此句代替已省略的处理过程 + return (td.index > 0) ? td.index : ret; + } + /* 钩子函数赋值 */ + static struct I2cMethod g_method = { + .transfer = SampleI2cTransfer, + }; + ``` + +2. 编写驱动初始化函数。 + + 本例中使用SampleI2cInit作为驱动初始化函数的函数名(函数名称可由驱动开发者确定),该函数需要在驱动入口结构体中赋值给Init,以供HDF驱动框架调用从而达到初始化驱动的目的。该函数中需要对从HCS获取的配置参数进行解析,并按照这些参数创建控制器。示例如下: + + ``` + /* 解析参数,申请内存并创建控制器 */ + static int32_t SampleI2cParseAndInit(struct HdfDeviceObject *device, const struct DeviceResourceNode *node) + { + int32_t ret; + struct SampleI2cCntlr *sampleCntlr = NULL; + (void)device; + + sampleCntlr = (struct SampleI2cCntlr *)OsalMemCalloc(sizeof(*sampleCntlr)); + if (sampleCntlr == NULL) { + HDF_LOGE("%s: malloc sampleCntlr fail!", __func__); + return HDF_ERR_MALLOC_FAIL; + } + + ret = SampleI2cReadDrs(sampleCntlr, node); // 从HCS获取配置参数 + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: read drs fail! ret:%d", __func__, ret); + goto __ERR__; + } + + sampleCntlr->regBase = OsalIoRemap(sampleCntlr->regBasePhy, sampleCntlr->regSize); + if (sampleCntlr->regBase == NULL) { + HDF_LOGE("%s: ioremap regBase fail!", __func__); + ret = HDF_ERR_IO; + goto __ERR__; + } + + HDF_LOGE("The controller has been initialized!"); // 表示此处省略的控制器初始化操作已经成功 + + sampleCntlr->cntlr.priv = (void *)node; + sampleCntlr->cntlr.busId = sampleCntlr->bus; + sampleCntlr->cntlr.ops = &g_method; + (void)OsalSpinInit(&sampleCntlr->spin); // 初始化自旋锁 + ret = I2cCntlrAdd(&sampleCntlr->cntlr); // 向核心层添加控制器 + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: add i2c controller fail:%d!", __func__, ret); + goto __ERR__; + } + + return HDF_SUCCESS; + __ERR__: // 错误处理 + if (sampleCntlr != NULL) { + if (sampleCntlr->regBase != NULL) { + OsalIoUnmap((void *)sampleCntlr->regBase); // 取消地址映射 + sampleCntlr->regBase = NULL; + } + OsalMemFree(sampleCntlr); // 释放内存 + sampleCntlr = NULL; + } + return ret; + } + /* 驱动入口初始化函数 */ + static int32_t SampleI2cInit(struct HdfDeviceObject *device) + { + int32_t ret; + const struct DeviceResourceNode *childNode = NULL; + + HDF_LOGE("%s: Enter", __func__); + if (device == NULL || device->property == NULL) { + HDF_LOGE("%s: device or property is NULL", __func__); + return HDF_ERR_INVALID_OBJECT; + } + + ret = HDF_SUCCESS; + DEV_RES_NODE_FOR_EACH_CHILD_NODE(device->property, childNode) { + ret = SampleI2cParseAndInit(device, childNode); // 调用解析参数和创建控制器的函数 + if (ret != HDF_SUCCESS) { + break; + } + } + return ret; + } + ``` + +3. 编写驱动释放函数。 + + 本例中使用SampleI2cRelease作为驱动释放函数的函数名(函数名称可由驱动开发者确定),该函数需要在驱动入口结构体中赋值给Release,当HDF框架调用Init函数初始化驱动失败时,将调用Release释放驱动资源。该函数中需包含释放内存和删除控制器等操作。示例如下: + + ``` + /* 删除控制器函数 */ + static void SampleI2cRemoveByNode(const struct DeviceResourceNode *node) + { + int32_t ret; + int16_t bus; + struct I2cCntlr *cntlr = NULL; + struct SampleI2cCntlr *sampleCntlr = NULL; + struct DeviceResourceIface *drsOps = NULL; + + drsOps = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE); + if (drsOps == NULL || drsOps->GetUint32 == NULL) { + HDF_LOGE("%s: invalid drs ops fail!", __func__); + return; + } + + ret = drsOps->GetUint16(node, "bus", (uint16_t *)&bus, 0); // 从HCS获取I2C总线号 + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: read bus fail!", __func__); + return; + } + + cntlr = I2cCntlrGet(bus); + if (cntlr != NULL && cntlr->priv == node) { // 根据I2C总线号删除控制器 + I2cCntlrPut(cntlr); + I2cCntlrRemove(cntlr); + sampleCntlr = (struct SampleI2cCntlr *)cntlr; + OsalIoUnmap((void *)sampleCntlr->regBase); + OsalMemFree(sampleCntlr); + } + return; + } + /* 释放资源 */ + static void SampleI2cRelease(struct HdfDeviceObject *device) + { + const struct DeviceResourceNode *childNode = NULL; + + HDF_LOGI("%s: enter", __func__); + + if (device == NULL || device->property == NULL) { + HDF_LOGE("%s: device or property is NULL", __func__); + return; + } + + DEV_RES_NODE_FOR_EACH_CHILD_NODE(device->property, childNode) { + SampleI2cRemoveByNode(childNode); // 调用删除控制器函数 + } + } + ``` + + +## 编译及烧录 + +1. 编辑Makefile,添加源文件: + + ``` + include drivers/hdf/khdf/platform/platform.mk + + obj-y += $(HDF_PLATFORM_FRAMEWORKS_ROOT)/src/i2c_core.o \ + $(HDF_PLATFORM_FRAMEWORKS_ROOT)/src/i2c_if.o \ + ./i2c_adapter.o \ + ./i2c_sample.o + ``` + + "./i2c\_sample.o"为本示例中在Makefile中追加的内容。 + +2. 编译及烧录。 + + 具体操作请参考[标准系统快速入门编译及烧录章节](../quick-start/quickstart-standard.md)。 + + 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 new file mode 100644 index 0000000000..31edc27814 --- /dev/null +++ b/zh-cn/device-dev/guide/device-iotcamera-control-demo-photodevguide.md @@ -0,0 +1,396 @@ +# 拍照开发指导 + +- [使用场景](#zh-cn_topic_0000001052170554_section1963312376119) +- [接口说明](#zh-cn_topic_0000001052170554_section56549532016) +- [约束与限制](#zh-cn_topic_0000001052170554_section1165911177314) +- [开发步骤](#zh-cn_topic_0000001052170554_section138543918214) + +## 使用场景 + +使用Camera产生图片帧(拍照)。 + +## 接口说明 + +**表 1** API列表 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    类名

    +

    接口名

    +

    描述

    +

    CameraKit

    +

    int32_t GetCameraIds(std::list<string> cameraList)

    +

    获取cameraId列表

    +

    CameraKit

    +

    CameraAbility& GetCameraAbility(string cameraId)

    +

    获取指定camera的能力

    +

    CameraKit

    +

    void RegisterCameraDeviceCallback(CameraDeviceCallback* callback, EventHandler* handler)

    +

    注册camera设备状态回调

    +

    CameraKit

    +

    void UnregisterCameraDeviceCallback(CameraDeviceCallback* callback)

    +

    去注册camera设备状态回调

    +

    CameraKit

    +

    void CreateCamera(string cameraId, CameraStateCallback* callback, EventHandler* handler)

    +

    创建camera实例

    +

    Camera

    +

    string GetCameraId()

    +

    获取cameraID

    +

    Camera

    +

    CameraConfig& GetCameraConfig()

    +

    获取camera配置信息

    +

    Camera

    +

    FrameConfig& GetFrameConfig(int32_t type)

    +

    获取捕获帧类型

    +

    Camera

    +

    void Configure(CameraConfig& config)

    +

    配置camera

    +

    Camera

    +

    void Release()

    +

    释放camera

    +

    Camera

    +

    int TriggerLoopingCapture(FrameConfig& frameConfig)

    +

    开始循环帧捕获

    +

    Camera

    +

    void StopLoopingCapture()

    +

    停止循环帧捕获

    +

    Camera

    +

    int32_t TriggerSingleCapture(FrameConfig& frameConfig)

    +

    抓图

    +

    CameraConfig

    +

    void SetFrameStateCallback(FrameStateCallback* callback, EventHandler* handler);

    +

    设置帧状态回调

    +

    CameraConfig

    +

    static CameraConfig* CreateCameraConfig()

    +

    创建camera配置信息实例

    +

    CameraAbility

    +

    std::list<Size> GetSupportedSizes(int format)

    +

    根据类型获取支持输出图像尺寸大小

    +

    CameraAbility

    +

    std::list<T> GetParameterRange(uint32_t key)

    +

    获取支持的参数范围

    +

    CameraDevice

    +

    CameraDeviceCallback()

    +

    camera设备回调类构造函数

    +

    CameraDevice

    +

    void OnCameraStatus​(std::string cameraId, int32_t status)

    +

    camera设备状态变化时的回调

    +

    CameraStateCallback

    +

    CameraStateCallback​()

    +

    camera状态回调类构造函数

    +

    CameraStateCallback

    +

    void OnConfigured​(Camera& camera)

    +

    camera配置成功回调

    +

    CameraStateCallback

    +

    void OnConfigureFailed​(Camera& camera,int32_t errorCode)

    +

    camera配置失败回调

    +

    CameraStateCallback

    +

    void OnCreated​(Camera& camera)

    +

    camera创建成功回调

    +

    CameraStateCallback

    +

    void OnCreateFailed​(std::string cameraId,int32_t errorCode)

    +

    camera创建失败回调

    +

    CameraStateCallback

    +

    void OnReleased​(Camera& camera)

    +

    camera释放回调

    +

    FrameStateCallback

    +

    FrameStateCallback​()

    +

    帧状态回调类构造函数

    +

    FrameStateCallback

    +

    void OnFrameFinished(Camera& camera, FrameConfig& frameConfig, FrameResult& frameResult)

    +

    拍照帧完成回调

    +

    FrameStateCallback

    +

    void OnFrameError​(Camera& camera, FrameConfig& frameConfig, int32_t errorCode, FrameResult& frameResult)

    +

    拍照帧异常回调

    +

    FrameConfig

    +

    int32_t GetFrameConfigType()

    +

    获取帧配置类型

    +

    FrameConfig

    +

    std::list<OHOS::Surface> GetSurfaces()

    +

    获取帧配置的surface

    +

    FrameConfig

    +

    void AddSurface(OHOS::AGP::UISurface& surface);

    +

    添加surface

    +

    FrameConfig

    +

    void RemoveSurface(OHOS::AGP::UISurface& surface);

    +

    删除surface

    +
    + +## 约束与限制 + +无。 + +## 开发步骤 + +1. 实现设备状态回调的派生类,用户在设备状态发生变更(如新插入相机设备/相机掉线)时,自定义操作。 + + ``` + class SampleCameraDeviceCallback : public CameraDeviceCallback { + void OnCameraStatus(std::string cameraId, int32_t status) override + { + //do something when camera is available/unavailable + } + }; + ``` + +2. 实现帧事件回调的派生类,这里在拿到帧数据以后将其转存为文件。 + + ``` + static void SampleSaveCapture(const char *p, uint32_t size) + { + cout << "Start saving picture" << endl; + struct timeval tv; + gettimeofday(&tv, NULL); + struct tm *ltm = localtime(&tv.tv_sec); + if (ltm != nullptr) { + ostringstream ss("Capture_"); + ss << "Capture" << ltm->tm_hour << "-" << ltm->tm_min << "-" << ltm->tm_sec << ".jpg"; + + ofstream pic("/sdcard/" + ss.str(), ofstream::out | ofstream::trunc); + cout << "write " << size << " bytes" << endl; + pic.write(p, size); + cout << "Saving picture end" << endl; + } + } + + class TestFrameStateCallback : public FrameStateCallback { + void OnFrameFinished(Camera &camera, FrameConfig &fc, FrameResult &result) override + { + cout << "Receive frame complete inform." << endl; + if (fc.GetFrameConfigType() == FRAME_CONFIG_CAPTURE) { + cout << "Capture frame received." << endl; + list surfaceList = fc.GetSurfaces(); + for (Surface *surface : surfaceList) { + SurfaceBuffer *buffer = surface->AcquireBuffer(); + if (buffer != nullptr) { + char *virtAddr = static_cast(buffer->GetVirAddr()); + if (virtAddr != nullptr) { + SampleSaveCapture(virtAddr, buffer->GetSize()); + } + surface->ReleaseBuffer(buffer); + } + delete surface; + } + delete &fc; + } + } + }; + ``` + +3. 实现相机状态回调的派生类,当相机状态发生变化(配置成功/失败,创建成功/失败\)时,自定义操作。 + + ``` + class SampleCameraStateMng : public CameraStateCallback { + public: + SampleCameraStateMng() = delete; + SampleCameraStateMng(EventHandler &eventHdlr) : eventHdlr_(eventHdlr) {} + ~SampleCameraStateMng() + { + if (recordFd_ != -1) { + close(recordFd_); + } + } + void OnCreated(Camera &c) override + { + cout << "Sample recv OnCreate camera." << endl; + auto config = CameraConfig::CreateCameraConfig(); + config->SetFrameStateCallback(&fsCb_, &eventHdlr_); + c.Configure(*config); + cam_ = &c; + } + void OnCreateFailed(const std::string cameraId, int32_t errorCode) override {} + void OnReleased(Camera &c) override {} + }; + ``` + +4. 创建CameraKit,用于创建和获取camera信息。 + + ``` + CameraKit *camKit = CameraKit::GetInstance(); + list camList = camKit->GetCameraIds(); + string camId; + for (auto &cam : camList) { + cout << "camera name:" << cam << endl; + const CameraAbility *ability = camKit->GetCameraAbility(cam); + /* find camera which fits user's ability */ + list sizeList = ability->GetSupportedSizes(0); + if (find(sizeList.begin(), sizeList.end(), CAM_PIC_1080P) != sizeList.end()) { + camId = cam; + break; + } + } + ``` + +5. 创建Camera实例。 + + ``` + EventHandler eventHdlr; // Create a thread to handle callback events + SampleCameraStateMng CamStateMng(eventHdlr); + + 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需要设计同步机制。 + + ``` + void OnCreated(Camera &c) override + { + cout << "Sample recv OnCreate camera." << endl; + auto config = CameraConfig::CreateCameraConfig(); + config->SetFrameStateCallback(&fsCb_, &eventHdlr_); + c.Configure(*config); + cam_ = &c; + } + + void Capture() + { + if (cam_ == nullptr) { + cout << "Camera is not ready." << endl; + return; + } + FrameConfig *fc = new FrameConfig(FRAME_CONFIG_CAPTURE); + Surface *surface = Surface::CreateSurface(); + if (surface == nullptr) { + delete fc; + return; + } + surface->SetWidthAndHeight(1920, 1080); /* 1920:width,1080:height */ + fc->AddSurface(*surface); + cam_->TriggerSingleCapture(*fc); + } + ``` + + diff --git "a/zh-cn/device-dev/guide/\345\275\225\345\203\217\345\274\200\345\217\221\346\214\207\345\257\274.md" b/zh-cn/device-dev/guide/device-iotcamera-control-demo-videodevguide.md old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/guide/\345\275\225\345\203\217\345\274\200\345\217\221\346\214\207\345\257\274.md" rename to zh-cn/device-dev/guide/device-iotcamera-control-demo-videodevguide.md diff --git a/zh-cn/device-dev/guide/device-iotcamera-control-demo.md b/zh-cn/device-dev/guide/device-iotcamera-control-demo.md new file mode 100644 index 0000000000..26be96c626 --- /dev/null +++ b/zh-cn/device-dev/guide/device-iotcamera-control-demo.md @@ -0,0 +1,7 @@ +# 示例开发 + +- **[拍照开发指导](device-iotcamera-control-demo-photodevguide.md)** + +- **[录像开发指导](device-iotcamera-control-demo-videodevguide.md)** + + diff --git a/zh-cn/device-dev/guide/device-iotcamera-control-example.md b/zh-cn/device-dev/guide/device-iotcamera-control-example.md new file mode 100644 index 0000000000..8f7e480ded --- /dev/null +++ b/zh-cn/device-dev/guide/device-iotcamera-control-example.md @@ -0,0 +1,45 @@ +# 应用实例 + +- 开发板介绍、编译烧录、运行镜像等操作请参考[Hi3518快速入门](../quick-start/quickstart-lite-introduction-hi3518.md#section14815247616),编译结果包含示例,结果文件为out/ipcamera\_hi3518ev300/dev\_tools/bin/camera\_sample,可将文件通过读卡器复制至TF卡中,或者修改camera\_sample的编译脚本将结果文件复制至rootfs.img中。 + + 修改applications/sample/camera/media/BUILD.gn中的output\_dir。 + + - 修改前:output\_dir = "$root\_out\_dir/dev\_tools" + - 修改后:output\_dir = "$root\_out\_dir/" + + 重新执行源码仓编译并烧写入单板后,可在单板bin目录下找到camera\_sample文件。 + +- 相机示例代码为applications/sample/camera/media/camera\_sample.cpp。 + + >![](../public_sys-resources/icon-notice.gif) **须知:** + >实例运行拍照和录像功能需要插入TF卡\(最大容量支持128GB\),系统启动后时自动将TF卡挂载至/sdcard目录,如果在启动后插入则需要手动挂载。查看拍照和录像内容可将TF卡中内容复制到电脑中进行查看,预览功能无需TF卡。 + + +1. 通过cd命令进入可执行程序的末端路径,启动camera\_sample,执行命令如下图。 + + **图 1** 启动示例 + ![](figure/启动示例.png "启动示例") + + 运行后的控制命令如串口打印所示,按s键停止当前操作(包括录像和预览),按q键退出示例程序。 + +2. 按1进行拍照,拍照的文件格式为jpg,存储在/sdcard,文件名Capture\* + + **图 2** 输入拍照指令后串口打印日志 + ![](figure/输入拍照指令后串口打印日志.png "输入拍照指令后串口打印日志") + + 若想查看保存文件,可在退出程序后进入文件系统查看,退出后重新进入请回到步骤1。 + + **图 3** 查看文件图 + ![](figure/查看文件图.png "查看文件图") + +3. 按2进行录像,录像的文件格式为mp4,存储在/sdcard,文件名Record\*,按s键停止 + + **图 4** 输入录像指令后串口打印日志 + ![](figure/输入录像指令后串口打印日志.png "输入录像指令后串口打印日志") + +4. 按q键退出 + + **图 5** 输出退出指令后串口打印日志 + ![](figure/输出退出指令后串口打印日志.png "输出退出指令后串口打印日志") + + diff --git a/zh-cn/device-dev/guide/device-iotcamera-control-overview.md b/zh-cn/device-dev/guide/device-iotcamera-control-overview.md new file mode 100644 index 0000000000..03fef3f55e --- /dev/null +++ b/zh-cn/device-dev/guide/device-iotcamera-control-overview.md @@ -0,0 +1,10 @@ +# 概述 + +本文档将介绍如何基于IoT Camera开发板,利用开发套件中自带的摄像头,完成拍照、录像功能。 + +开发者可通过执行示例应用,对开发板的外设控制有了更深入了解后,可使用开发板完成摄像头等设备。 + +若开发者想先查看示例效果,请进入[应用实例](device-iotcamera-control-example.md)。如需自定义应用行为,可参考下节“示例开发”对示例代码进行修改。 + +相机开发基本概念可参考:[相机开发概述](../subsystems/subsys-multimedia-camera-overview.md)。 + diff --git a/zh-cn/device-dev/guide/device-iotcamera-control.md b/zh-cn/device-dev/guide/device-iotcamera-control.md new file mode 100644 index 0000000000..776d324bf5 --- /dev/null +++ b/zh-cn/device-dev/guide/device-iotcamera-control.md @@ -0,0 +1,9 @@ +# 摄像头控制 + +- **[概述](device-iotcamera-control-overview.md)** + +- **[示例开发](device-iotcamera-control-demo.md)** + +- **[应用实例](device-iotcamera-control-example.md)** + + diff --git a/zh-cn/device-dev/guide/device-iotcamera.md b/zh-cn/device-dev/guide/device-iotcamera.md new file mode 100644 index 0000000000..4823d57830 --- /dev/null +++ b/zh-cn/device-dev/guide/device-iotcamera.md @@ -0,0 +1,5 @@ +# 无屏摄像头类产品 + +- **[摄像头控制](device-iotcamera-control.md)** + + diff --git a/zh-cn/device-dev/guide/device-outerdrive-demo.md b/zh-cn/device-dev/guide/device-outerdrive-demo.md new file mode 100644 index 0000000000..afeffb7863 --- /dev/null +++ b/zh-cn/device-dev/guide/device-outerdrive-demo.md @@ -0,0 +1,483 @@ +# 外设驱动开发示例 + +- [概述](#section86753818426) + - [硬件资源简介](#section123071189431) + - [Input模型简介](#section53684425430) + +- [环境搭建](#section661075474418) +- [TouchScreen器件驱动开发](#section15233162984520) + - [配置设备描述信息](#section16761205604515) + - [配置Touchscreen器件信息](#section156331030144617) + - [适配器件私有驱动](#section17127331595) + +- [编译及烧录](#section16465031164711) +- [调试验证](#section62577313482) +- [Input模型工作流程解析](#section1578569154917) + - [私有配置信息解析](#section1310113815495) + - [管理驱动层初始化及注册驱动至HDF框架](#section614512119500) + - [公共驱动层初始化及注册驱动至HDF框架](#section16194201755019) + - [器件驱动层初始化及注册驱动至HDF框架](#section1090743312505) + - [具体调用逻辑串联函数](#section81801147529) + + +## 概述 + +本文档将介绍如何基于Hi3516DV300开发板完成基于HDF\_Input模型的触摸屏器件驱动开发,从而使开发者快速入门,进行基于的外设驱动开发。 + +### 硬件资源简介 + +Hi3516DV300开发板套件所提供的触摸屏器件IC为GT911,该器件采用标准I2C与主机通信,通过6pin软排线与主板连接。6pin分布以及实物连接图如下图所示: + +![](figure/绘图1.png) + +### Input模型简介 + +Input驱动模型核心部分由设备管理层、公共驱动层、器件驱动层组成。其中: + +- 设备管理层:主要为各类输入设备驱动提供input设备的注册、注销接口,同时统一管理input设备列表; +- 公共驱动层:负责对板级硬件进行初始化、硬件中断处理、向manager注册input设备等; +- 器件驱动层:通过适配平台驱动预留的差异化接口,实现器件驱动开发量最小化; + +此外,Input模型预先实现了数据通道以及设备配置信息解析等函数。 + +关于Input模型的详细介绍请参考《[Touchscreen开发概述](../driver/drive-peripherals-touch-des.md#section175431838101617)》。 + +## 环境搭建 + +环境准备具体操作请参考[标准系统基础环境搭建](../quick-start/quickstart-standard.md)。 + +>![](../public_sys-resources/icon-notice.gif) **须知:** +>本示例针对OpenHarmony轻量系统、小型系统、标准系统都适用,本文以标准系统为例。其他系统的开发者可参考对应系统的指导文档进行环境搭建。 + +## TouchScreen器件驱动开发 + +基于Input模型适配一款触摸屏IC需要完成的具体工作见下。 + +### 配置设备描述信息 + +驱动注册到HDF框架所需要的设备驱动描述信息,如驱动是否加载以及加载次序等。 + +配置文件路径:./drivers/adapter/khdf/linux/hcs/device\_info/device\_info.hcs + +device\_info.hcs中的信息主要提供给HDF框架使用,包含了Input模型各层驱动注册到HDF框架所必需的信息,开发者无特殊场景需求无需改动。各驱动层私有配置信息通过“deviceMatchAttr”字段与input\_config.hcs中的“match\_attr”相关内容进行匹配。 + +配置文件中与input模块相关的内容如下所示,相关字段的详细含义可以参考《[驱动配置](../driver/drive-hdf-development.md)》: + +``` +input :: host { + hostName = "input_host"; + priority = 100; + device_input_manager :: device { // Input管理层设备描述信息 + device0 :: deviceNode { + policy = 2; // 向内核用户态均发布服务 + priority = 100; // input管理层驱动优先级默认为100 + preload = 0; // 加载该驱动 + permission = 0660; // 驱动创建设备节点权限 + moduleName = "HDF_INPUT_MANAGER"; // 与驱动入口的moduleName匹配 + serviceName = "hdf_input_host"; // HDF框架生成的节点名 + deviceMatchAttr = ""; // manager目前不需要私有配置,因此为空 + } + } + + device_hdf_touch :: device { // Input公共驱动层设备描述信息 + device0 :: deviceNode { + policy = 2; // 向内核用户态均发布服务 + priority = 120; // input公共驱动优先级默认为120 + preload = 0; // 加载该驱动 + permission = 0660; // 驱动创建设备节点权限 + moduleName = "HDF_TOUCH"; // 与驱动入口的moduleName匹配 + serviceName = "hdf_input_event1"; // HDF框架生成的节点名 + deviceMatchAttr = "touch_device1"; // 与私有配置信息中的“match_attr”字段保持一致 + } + } + + device_touch_chip :: device { // Input器件驱动层信息 + device0 :: deviceNode { + policy = 0; // 向内核用户态均不发布服务 + priority = 130; // input器件驱动优先级默认为130 + preload = 0; // 加载该驱动 + permission = 0660; // 驱动创建设备节点权限 + moduleName = "HDF_TOUCH_GT911"; // 与驱动入口的moduleName匹配 + serviceName = "hdf_touch_gt911_service";// HDF框架生成的节点名 + deviceMatchAttr = "zsj_gt911_5p5"; //与私有配置信息中的“match_attr”字段保持一致 + } + } + } +``` + +该配置文件中需要重点关注的字段有: + +“priority”决定驱动加载顺序; + +“preload”决定驱动是否加载; + +“moduleName ”需要与驱动注册入口处的“moduleName ”字段保持一致; + +“serviceName ”HDF框架依据该字段创建节点名; + +“deviceMatchAttr ”需要与私有配置信息中的“match\_attr”字段保持一致。 + +通过配置设备描述信息,使得HDF框架通过moduleName与注册至驱动入口的代码相匹配,保证了驱动的正常加载,通过priority字段保证了各驱动的加载顺序。 + +### 配置Touchscreen器件信息 + +器件私有信息包括上下电时序等,平台硬件信息包括器件连接主板的GPIO端口信息等。 + +配置文件路径:./drivers/adapter/khdf/linux/hcs/input/input\_config.hcs + +input\_config.hcs中的信息由驱动代码进行读取解析,主要由公共驱动层的私有配置信息及器件驱动层的私有配置信息组成。文件中的配置包含板级硬件信息及器件私有配置信息,实际业务开发时,可根据具体需求增删及修改对应内容。 + +``` +root { + input_config { + touchConfig { + touch0 { // 第一款触摸屏 + boardConfig { // 板级硬件信息 + match_attr = "touch_device1"; // 与设备描述配置信息中公共驱动层私有配置信息的“match_attr”字段保持一致 + inputAttr { + /* 0:touch 1:key 2:keyboard 3:mouse 4:button 5:crown 6:encoder */ + inputType = 0; // input类型为touch + solutionX = 480; // 分辨率X信息 + solutionY = 960; // 分辨率Y信息 + devName = "main_touch"; // 设备名称 + } + busConfig { + /* 0:i2c 1:spi */ + busType = 0; // GT911采用I2C通信 + busNum = 6; // 与主机芯片第6路I2C通信 + clkGpio = 86; // 主机芯片SCL管脚 + dataGpio = 87; // 主机芯片SDA管脚 + i2cClkIomux = [0x114f0048, 0x403]; // SCL管脚配置信息 + i2cDataIomux = [0x114f004c, 0x403]; // SDA管脚配置信息 + } + pinConfig { + rstGpio = 3; // 复位管脚连接主机芯片的3号管脚 + intGpio = 4; // 中断管脚连接主机芯片的4号管脚 + rstRegCfg = [0x112f0094, 0x400]; // 复位管脚配置信息 + intRegCfg = [0x112f0098, 0x400]; // 中断管脚配置信息 + } + powerConfig { + /* 0:unused 1:ldo 2:gpio 3:pmic */ + vccType = 2; // GPIO供电 + vccNum = 20; // gpio20 + vccValue = 1800; // 电压幅值为1800mV + vciType = 1; // LDO供电 + vciNum = 12; // ldo12 + vciValue = 3300; // 电压幅值为3300mV + } + + featureConfig { + capacitanceTest = 0; // 容值测试 + gestureMode = 0; // 手势模式 + gloverMode = 0; // 手套模式 + coverMode = 0; // 皮套模式 + chargerMode = 0; // 充电模式 + knuckleMode = 0; // 指关节模式 + } + } + chipConfig { // 器件私有信息配置 + template touchChip { // 模板 + match_attr = ""; + chipName = "gt911"; // 触摸屏IC型号 + vendorName = "zsj"; // 供应商 + chipInfo = "AAAA11222"; // 1~4字符代表产品名,5~6字符代表IC型号,7~9字符代表模型型号 + busType = 0; // 0代表I2C,1代表SPI + deviceAddr = 0x5D; // 器件IC通信地址 + irqFlag = 2; // 1代表上升沿触发,2代表下降沿触发,4代表高电平触发,8代表低电平触发 + maxSpeed = 400; // 最大通信速率为400Hz + chipVersion = 0; // 触摸屏IC版本号 + powerSequence { + /* 上电时序的配置含义说明: + [类型, 状态, 方向 , 延时] + 0代表空,1代表vcc电源(1.8V),2代表VCI电源(3.3V),3代表复位管脚,4代表中断管脚 + 0代表下电或拉低,1代表上电或拉高,2代表无操作 + 0代表输入方向,1代表输出方向,2代表无操作 + 代表延时多少毫秒, 例如20代表延时20ms + */ + powerOnSeq = [4, 0, 1, 0, // 中断管脚配置为输出,且进行拉低 + 3, 0, 1, 10, // 复位管脚配置为输出,且进行拉低,延时10ms + 3, 1, 2, 60, // 复位管脚无操作,且进行拉高,延时60ms + 4, 2, 0, 0]; // 中断管脚配置为输入 + suspendSeq = [3, 0, 2, 10]; // 复位管脚无操作,且进行拉低,延时10ms + resumeSeq = [3, 1, 2, 10]; // 复位管脚无操作,且进行拉高,延时10ms + powerOffSeq = [3, 0, 2, 10, // 复位管脚无操作,且进行拉低,延时10ms + 1, 0, 2, 20]; // 电源正极管脚无操作,且进行拉低,延时20ms + } + } + + chip0 :: touchChip { + match_attr = "zsj_gt911_5p5"; // 与设备描述配置信息中器件私有配置信息的“match_attr”字段保持一致 + chipInfo = "ZIDN45100"; // 产品名+模组编号+芯片编号的组合信息 用于给用户态区分当前器件 + chipVersion = 0; // IC型号的版本 + } + } + } + } + } +} +``` + +示例中“touchConfig”包含了“touch0”,"touch0"包含了“boardConfig”与“chipConfig”;“boardConfig”字段包含了Hi3516DV300板级硬件信息,“chipConfig”包含了触摸屏器件的私有信息,如果需要替换触摸屏器件,重新配置“chipConfig”对应的字段信息即可。同时产品可以配置多款触摸屏,示例中用“touch0”代表了套件中默认的触摸屏的硬件接口以及器件的配置信息,如产品需要配置副屏,可在与“touch0”并列的位置配置“touch1”的信息。 + +### 适配器件私有驱动 + +Input模型对Input设备开发流程进行了抽象,开发者只需要适配器件驱动层,无需改动管理驱动层以及公共驱动层。 + +Input模型由三层驱动组成,开发者适配一款全新触摸屏驱动只需要适配器件驱动层即可,重点实现差异化接口,本小节以代码示例的形式展示开发者需要重点完成的工作。 + +1. 触摸屏器件差异化接口适配 + + 示例代码路径:./drivers/framework/model/input/driver/touchscreen/touch\_gt911.c + + ``` + static struct TouchChipOps g_gt911ChipOps = { // 器件IC接口 + .Init = ChipInit, // 初始化 + .Detect = ChipDetect, // 器件检测 + .Resume = ChipResume, // 唤醒 + .Suspend = ChipSuspend, // 休眠 + .DataHandle = ChipDataHandle, // 器件数据读取 + .UpdateFirmware = UpdateFirmware, // 固件升级 + }; + + /* 不同触摸屏厂家使用的IC不一样,对应的寄存器操作也不一样,因此器件驱动层代码重点适配差异化接口部分,如下示例代码展示了GT911的数据解析*/ + + static int32_t ChipDataHandle(ChipDevice *device) + { + ... + /* GT911获取坐标之前需先读取状态寄存器 */ + reg[0] = (GT_BUF_STATE_ADDR >> ONE_BYTE_OFFSET) & ONE_BYTE_MASK; + reg[1] = GT_BUF_STATE_ADDR & ONE_BYTE_MASK; + ret = InputI2cRead(i2cClient, reg, GT_ADDR_LEN, &touchStatus, 1); + if (ret < 0 || touchStatus == GT_EVENT_INVALID) { + return HDF_FAILURE; + } + ... + /* 根据状态寄存器的值读取数据寄存器数据 */ + reg[0] = (GT_X_LOW_BYTE_BASE >> ONE_BYTE_OFFSET) & ONE_BYTE_MASK; + reg[1] = GT_X_LOW_BYTE_BASE & ONE_BYTE_MASK; + pointNum = touchStatus & GT_FINGER_NUM_MASK; + if (pointNum == 0 || pointNum > MAX_SUPPORT_POINT) { + HDF_LOGE("%s: pointNum is invalid, %u", __func__, pointNum); + (void)ChipCleanBuffer(i2cClient); + OsalMutexUnlock(&device->driver->mutex); + return HDF_FAILURE; + } + frame->realPointNum = pointNum; + frame->definedEvent = TOUCH_DOWN; + (void)InputI2cRead(i2cClient, reg, GT_ADDR_LEN, buf, GT_POINT_SIZE * pointNum); + /* 对获取的数据进行解析 */ + ParsePointData(device, frame, buf, pointNum); + ... + } + static void ParsePointData(ChipDevice *device, FrameData *frame, uint8_t *buf, uint8_t pointNum) + { + ... + /* 每个坐标值由两个字节组成,对获取的单字节数据进行拼接得到最终的坐标值 */ + for (i = 0; i < pointNum; i++) { + frame->fingers[i].trackId = buf[GT_POINT_SIZE * i + GT_TRACK_ID]; + frame->fingers[i].y = (buf[GT_POINT_SIZE * i + GT_X_LOW] & ONE_BYTE_MASK) | + ((buf[GT_POINT_SIZE * i + GT_X_HIGH] & ONE_BYTE_MASK) << ONE_BYTE_OFFSET); + frame->fingers[i].x = (buf[GT_POINT_SIZE * i + GT_Y_LOW] & ONE_BYTE_MASK) | + ((buf[GT_POINT_SIZE * i + GT_Y_HIGH] & ONE_BYTE_MASK) << ONE_BYTE_OFFSET); + /* 对解析出来的坐标值进行打印 */ + HDF_LOGD("%s: x = %d, y = %d", __func__, frame->fingers[i].x, frame->fingers[i].y); + } + } + ``` + +2. 器件层驱动初始化及注册驱动至HDF框架 + + 示例代码路径:./drivers/framework/model/input/driver/touchscreen/touch\_gt911.c + + ``` + static int32_t HdfGoodixChipInit(struct HdfDeviceObject *device) + { + ... + /* 器件配置结构体内存申请、配置信息解析及挂载 */ + chipCfg = ChipConfigInstance(device); + ... + /* 器件实例化 */ + chipDev = ChipDeviceInstance(); + ... + /* 器件信息挂载及器件私有操作挂载 */ + chipDev->chipCfg = chipCfg; + chipDev->ops = &g_gt911ChipOps; + ... + /* 注册器件驱动至平台驱动 */ + RegisterChipDevice(chipDev); + ... + } + struct HdfDriverEntry g_touchGoodixChipEntry = { + .moduleVersion = 1, + .moduleName = "HDF_TOUCH_GT911", // 该moduleName与device_info.hcs文件中器件驱动层的moduleName信息相匹配 + .Init = HdfGoodixChipInit, // 器件驱动初始化函数 + }; + HDF_INIT(g_touchGoodixChipEntry); // 注册器件驱动至HDF框架 + ``` + + 器件私有驱动层主要实现了各器件厂商差异较大的部分,如器件休眠唤醒、数据解析以及固件升级等。 + + 至此,基于HDF框架及Input模型的触摸屏驱动适配完成。 + + +## 编译及烧录 + +1. 编辑Makefile文件,添加本示例中的内容: + + 文件路径:./drivers/adapter/khdf/linux/model/input/Makefile + + 添加内容如下: + + ``` + obj-$(CONFIG_DRIVERS_HDF_TP_5P5_GT911) += \ + $(INPUT_ROOT_DIR)/touchscreen/touch_gt911.o + ``` + + 其中touch\_gt911.o为本示例中追加的内容。 + +2. 具体编译及烧录操作请参考[标准系统快速入门编译及烧录章节](../nottoctopics/zh-cn_topic_0000001135402541.md#section375234715135)。 + +## 调试验证 + +如下所示为开机启动日志部分截取 + +``` +[I/HDF_INPUT_DRV] HdfInputManagerInit: enter // 管理驱动层初始化 +[I/HDF_INPUT_DRV] HdfInputManagerInit: exit succ // 初始化成功 +[I/osal_cdev] add cdev hdf_input_host success +[I/HDF_LOG_TAG] HdfTouchDriverProbe: enter // 公共驱动层初始化 +[I/HDF_LOG_TAG] HdfTouchDriverProbe: main_touch exit succ // 初始化成功 +[I/osal_cdev] add cdev hdf_input_event1 success +[I/HDF_INPUT_DRV] HdfGoodixChipInit: enter // 器件驱动层初始化 +[I/HDF_INPUT_DRV] ChipDetect: IC FW version is 0x1060 +[I/HDF_INPUT_DRV] Product_ID: 911_1060, x_sol = 960, y_sol = 480 +[I/HDF_LOG_TAG] ChipDriverInit: chipDetect succ, ret = 0 +[I/HDF_LOG_TAG] InputDeviceInstance: inputDev->devName = main_touch +[I/HDF_INPUT_DRV] HdfGoodixChipInit: exit succ, chipName = gt911 // 初始化成功 +``` + +## Input模型工作流程解析 + +为了让开发者更清晰的了解Input模型工作流程,本节将对input模型加载的关键流程代码进行说明。 + +>![](../public_sys-resources/icon-notice.gif) **须知:** +>本章节为Input模型工作流程说明,开发者无需进行开发。 + +### 私有配置信息解析 + +示例代码路径:./drivers/framework/model/input/driver/input\_config\_parser.c + +根据OSAL提供的配置解析函数,可以将hcs文件中各字段含义进行解析,具体请参考input\_config\_parser.c中各函数的实现。如果提供的模板不能满足需求,在hcs文件中添加相应信息后,需要根据添加的字段开发相应的解析函数。 + +``` +static int32_t ParseAttr(struct DeviceResourceIface *parser, const struct DeviceResourceNode *attrNode, BoardAttrCfg *attr) +{ + int32_t ret; + ret = parser->GetUint8(attrNode, "inputType", &attr->devType, 0); // 获取inputType字段信息,保存在BoardAttrCfg结构体中 + CHECK_PARSER_RET(ret, "GetUint8"); + ... + return HDF_SUCCESS; +} +``` + +### 管理驱动层初始化及注册驱动至HDF框架 + +示例代码路径:./drivers/framework/model/input/driver/hdf\_input\_device\_manager.c + +``` +static int32_t HdfInputManagerInit(struct HdfDeviceObject *device) +{ + /* 分配内存给manager,manager中将存放所有input设备 */ + g_inputManager = InputManagerInstance(); + ... +} +struct HdfDriverEntry g_hdfInputEntry = { + .moduleVersion = 1, + .moduleName = "HDF_INPUT_MANAGER", + .Bind = HdfInputManagerBind, + .Init = HdfInputManagerInit, + .Release = HdfInputManagerRelease, +}; + +HDF_INIT(g_hdfInputEntry); //驱动注册入口 +``` + +### 公共驱动层初始化及注册驱动至HDF框架 + +示例代码路径:./drivers/framework/model/input/driver/hdf\_touch.c + +``` +static int32_t HdfTouchDriverProbe(struct HdfDeviceObject *device) +{ + ... + /* 板级信息结构体内存申请及hcs配置信息解析 */ + boardCfg = BoardConfigInstance(device); + ... + /* 公共驱动结构体内存申请 */ + touchDriver = TouchDriverInstance(); + ... + /* 依据解析出的板级信息进行公共资源初始化,如IIC初始化 */ + ret = TouchDriverInit(touchDriver, boardCfg); + if (ret == HDF_SUCCESS) { + ... + /* 添加驱动至公共驱动层驱动管理链表,当设备与驱动进行绑定时使用该链表进行查询 */ + AddTouchDriver(touchDriver); + ... + } + ... +} +struct HdfDriverEntry g_hdfTouchEntry = { + .moduleVersion = 1, + .moduleName = "HDF_TOUCH", + .Bind = HdfTouchDriverBind, + .Init = HdfTouchDriverProbe, + .Release = HdfTouchDriverRelease, +}; + +HDF_INIT(g_hdfTouchEntry); //驱动注册入口 +``` + +### 器件驱动层初始化及注册驱动至HDF框架 + +具体请参考[适配器件私有驱动](#section17127331595)器件层驱动初始化及注册驱动至HDF框架部分。 + +### 具体调用逻辑串联函数 + +Input模型管理层驱动init函数初始化了设备管理链表,公共驱动层初始化函数完成了相关结构体的内存申请。器件驱动相关信息通过RegisterChipDevice函数对公共驱动层相关结构体进行信息填充,同时完成了相关硬件信息的初始化(如中断注册等),绑定设备与驱动组成inputDev通过RegisterInputDevice函数向驱动管理层进行注册,在RegisterInputDevice函数中主要实现了将inputDev向设备管理链表的添加等功能。如下所示为两个函数的实现部分: + +``` +//函数具体实现代码位置 :./drivers/framework/model/input/driver/hdf_touch.c +int32_t RegisterChipDevice(ChipDevice *chipDev) +{ + ... + /* 绑定设备与驱动,从而通过InputDeviceInstance函数创建inputDev */ + DeviceBindDriver(chipDev); + ... + /* 主要包含器件中断注册及中断处理函数,中断处理函数中有数据上报用户态的数据通道 */ + ChipDriverInit(chipDev); + ... + /* 申请内存实例化InputDev */ + inputDev = InputDeviceInstance(chipDev); + ... + /* 将InputDev设备注册至input驱动管理层 */ + RegisterInputDevice(inputDev); + ... +} + +//函数具体实现代码位置 :./drivers/framework/model/input/driver/hdf_input_device_manager.c +int32_t RegisterInputDevice(InputDevice *inputDev) +{ + ... + /* 申请ID,该ID对于不同input设备唯一 */ + ret = AllocDeviceID(inputDev); + ... + /* 该函数包含了对hid类设备的特殊处理,对于触摸屏驱动,该函数无实质操作; */ + CreateDeviceNode(inputDev); + /* 内核态数据传送至用户态需使用IOService能力,需要申请buffer */ + AllocPackageBuffer(inputDev); + /* 将input设备添加进设备全局管理链表 */ + AddInputDevice(inputDev); + ... +} +``` + diff --git a/zh-cn/device-dev/guide/device-wifi-led-outcontrol.md b/zh-cn/device-dev/guide/device-wifi-led-outcontrol.md new file mode 100644 index 0000000000..2d4970fa19 --- /dev/null +++ b/zh-cn/device-dev/guide/device-wifi-led-outcontrol.md @@ -0,0 +1,110 @@ +# LED外设控制 + +- [概述](#section14639174516337) +- [开发](#section13857170163412) +- [验证](#section1949121910344) + +## 概述 + +OpenHarmony WLAN模组基于Hi3861平台提供了丰富的外设操作能力,包含I2C、I2S、ADC、UART、SPI、SDIO、GPIO、PWM、FLASH等。本文介绍如何通过调用OpenHarmony的NDK接口,实现对GPIO控制,达到LED闪烁的效果。其他的IOT外设控制,开发者可根据API指导文档完成,此处不逐一介绍。 + +## 开发 + +1. 请先完成[《Hi3861快速入门》](../quick-start/quickstart-lite-introduction-hi3861.md#section19352114194115)。 + + LED控制参考示例存放于applications/sample/wifi-iot/app/iothardware/led\_example.c文件中。 + +2. 实现IOT外设控制,首先需要通过查阅原理图明确接线关系。经过查阅,hispark pegasus的LED与芯片的9号管脚相连。 + + ``` + #define LED_TEST_GPIO 9 + ``` + + >![](../public_sys-resources/icon-note.gif) **说明:** + >开发板原理图,请开发者联系Hi3861购买渠道客服获取。 + +3. 使用GPIO前,需要完成GPIO管脚初始化,明确管脚用途,并创建任务,使LED周期性亮灭,达到闪烁的效果。 + + ``` + static void LedExampleEntry(void) + { + osThreadAttr_t attr; + + /* 管脚初始化 */ + IoTGpioInit(LED_TEST_GPIO); + /* 配置9号管脚为输出方向 */ + IoTGpioSetDir(LED_TEST_GPIO, IOT_GPIO_DIR_OUT); + + attr.name = "LedTask"; + attr.attr_bits = 0U; + attr.cb_mem = NULL; + attr.cb_size = 0U; + attr.stack_mem = NULL; + attr.stack_size = LED_TASK_STACK_SIZE; + attr.priority = LED_TASK_PRIO; + + /* 启动任务 */ + if (osThreadNew((osThreadFunc_t)LedTask, NULL, &attr) == NULL) { + printf("[LedExample] Failed to create LedTask!\n"); + } + } + ``` + +4. 在循环任务中通过周期性亮灭形式实现LED闪烁。 + + ``` + static void *LedTask(const char *arg) + { + (void)arg; + while (1) { + switch (g_ledState) { + case LED_ON: + IoTGpioSetOutputVal(LED_TEST_GPIO, 1); + usleep(LED_INTERVAL_TIME_US); + break; + case LED_OFF: + IoTGpioSetOutputVal(LED_TEST_GPIO, 0); + usleep(LED_INTERVAL_TIME_US); + break; + case LED_SPARK: + IoTGpioSetOutputVal(LED_TEST_GPIO, 0); + usleep(LED_INTERVAL_TIME_US); + IoTGpioSetOutputVal(LED_TEST_GPIO, 1); + usleep(LED_INTERVAL_TIME_US); + break; + default: + usleep(LED_INTERVAL_TIME_US); + break; + } + } + return NULL; + } + ``` + +5. 在代码最下方,使用OpenHarmony启动恢复模块接口SYS\_RUN\(\)启动业务。(SYS\_RUN定义在ohos\_init.h文件中) + + ``` + SYS_RUN(LedExampleEntry); + ``` + +6. 修改applications/sample/wifi-iot/app/BUILD.gn文件,使led\_example.c参与编译。 + + ``` + import("//build/lite/config/component/lite_component.gni") + lite_component("app") { + features = [ + "iothardware:led_example" + ] + } + ``` + + +## 验证 + +编译过程请参考《[Hi3861快速入门-源码编译](../quick-start/quickstart-lite-steps-board3861-connection.md#section191121332125319)》,烧录过程请参考《[Hi3861快速入门-镜像烧录](../quick-start/quickstart-lite-steps-board3861-connection.md#section19458165166)》。 + +完成以上两步后,按下RST键复位模组,可发现LED在周期性闪烁,与预期相符,验证完毕。 + +**图 1** LED闪烁图 +![](figure/LED闪烁图.gif "LED闪烁图") + diff --git a/zh-cn/device-dev/guide/device-wifi-sdk.md b/zh-cn/device-dev/guide/device-wifi-sdk.md new file mode 100644 index 0000000000..8106f68cd6 --- /dev/null +++ b/zh-cn/device-dev/guide/device-wifi-sdk.md @@ -0,0 +1,325 @@ +# 集成三方SDK + +- [规划目录结构](#section1736472718351) +- [构建业务libs](#section442815485351) +- [编写适配代码](#section3984721113613) +- [代码编写](#section830417531286) +- [脚本编写](#section13500201173710) +- [编写业务代码](#section8754114803918) +- [运行](#section7737749184012) +- [结束](#section153301392411) + +OpenHarmony致力于打造一套更加开放完善的IoT生态系统,为此OpenHarmony规划了一组目录,用于将各厂商的SDK集成到OpenHarmony中。本文档基于Hi3861开发板,向平台开发者介绍将SDK集成到OpenHarmony的方法。 + +## 规划目录结构 + +三方SDK通常由静态库和适配代码构成。SDK的业务逻辑通过硬件模组工具链编译得到静态库libs,每款模组都有其对应的libs。SDK的南向API与OpenHarmony 的API存在使用差异,该差异可通过adapter适配代码屏蔽,不同模组可共用一套adapter。 + +基于以上特征,在OpenHarmony目录结构中,可以对三方SDK目录做如下划分。 + +- 适配代码adapter,放置到domains/iot/link/ 目录下,与模组解耦。 +- 业务库libs,放置到device/hisilicon/hispark\_pegasus/sdk\_liteos/3rd\_sdk/ 目录下,与模组绑定。 + +平台开发者在适配前,务必先依次完成以下步骤,下面以demolink SDK举例,进行介绍。 + +1. 创建厂商目录,domains/iot/link/demolink/、device/hisilicon/hispark\_pegasus/sdk\_liteos/3rd\_sdk/demolink/ ,用于厂商隔离。 +2. 创建domains/iot/link/demolink/BUILD.gn ,用于构建适配代码。 +3. 创建device/hisilicon/hispark\_pegasus/sdk\_liteos/3rd\_sdk/demolink/libs/ 目录,用于存放业务库libs。 + +``` +. +├── domains +│ └── iot +│ └── link +│ ├── demolink +│ │ └── BUILD.gn +│ ├── libbuild +│ │ └── BUILD.gn +│ └── BUILD.gn +└── device + └── hisilicon + └── hispark_pegasus + └── sdk_liteos + └── 3rd_sdk + └── demolink + └── libs +``` + +## 构建业务libs + +平台SDK业务一般以静态库的形式提供,平台厂商在获取到OpenHarmony代码后,需要根据对应的硬件模组vendor,编译业务libs,并将编译结果放置在device/hisilicon/hispark\_pegasus/sdk\_liteos/3rd\_sdk/demolink/libs/ 目录下。下面介绍业务libs的构建方法。 + +OpenHarmony已规划用于编译业务libs的目录domains/iot/link/libbuild/ ,该目录中包含domains/iot/link/libbuild/BUILD.gn和domains/iot/link/BUILD.gn文件,目录结构如下。 + +``` +. +└── domains + └── iot + └── link + ├── demolink + │ └── BUILD.gn + ├── libbuild + │ └── BUILD.gn + └── BUILD.gn +``` + +平台开发者在构建libs前,务必先完成如下步骤。 + +1. 在domains/iot/link/libbuild/ 目录下放置业务源码文件,包括.c和.h文件。 + + ``` + . + └── domains + └── iot + └── link + ├── demolink + │ ├── demosdk_adapter.c + │ ├── demosdk_adapter.h + │ └── BUILD.gn + ├── libbuild + │ ├── demosdk.c + │ ├── demosdk.h + │ └── BUILD.gn + └── BUILD.gn + ``` + +2. 适配domains/iot/link/libbuild/BUILD.gn,在编译完成后还原该文件。 + + 在BUILD.gn中,sources为需要参与构建的源文件,include\_dirs为依赖的头文件路径,构建的目标结果是生成静态库libdemosdk.a。 + + ``` + static_library("demosdk") { + sources = [ + "demosdk.c" + ] + include_dirs = [ + "//domains/iot/link/libbuild", + "//domains/iot/link/demolink" + ] + } + ``` + +3. 适配domains/iot/link/BUILD.gn,在编译完成后还原该文件。 + + 此BUILD.gn文件用于指定构建条目,需要在features中填入所有需参与编译的静态库条目,使domains/iot/link/libbuild/BUILD.gn参与到构建中来。 + + ``` + import("//build/lite/config/subsystem/lite_subsystem.gni") + import("//build/lite/config/component/lite_component.gni") + lite_subsystem("iot") { + subsystem_components = [ + ":link" + ] + } + lite_component("link") { + features = [ + "libbuild:demosdk" + ] + } + ``` + + +完成以上3点后,需在代码根目录下执行命令“hb build -T //domains/iot/link:iot”,等待执行完成,检查out/hispark\_pegasus/wifiiot\_hispark\_pegasus/libs/目录下是否生成了目标库文件。 + +![](figure/zh-cn_image_0000001078563230.png) + +将库文件拷贝到device/hisilicon/hispark\_pegasus/sdk\_liteos/3rd\_sdk/demolink/libs/ 目录下,并将domains/iot/link/libbuild/ 目录中的.c和.h文件清除。 + +## 编写适配代码 + +## 代码编写 + +平台SDK中使用的API通常与OpenHarmony API存在差异,无法直接使用,需要一层适配代码adapter进行中间转换。本节以domains/iot/link/demolink/demosdk\_adapter.c中的任务创建接口DemoSdkCreateTask举例,向开发者演示如何在OpenHarmony上编写适配代码。 + +1. 查看待适配接口DemoSdkCreateTask的描述、参数、返回值。 + + ``` + struct TaskPara { + char *name; + void *(*func)(char* arg); + void *arg; + unsigned char prio; + unsigned int size; + }; + + /* + * IoT OS 创建线程接口 + * 返回值: 返回0 成功, 其他 失败 + */ + int DemoSdkCreateTask(unsigned int *handle, const struct TaskPara *para); + ``` + +2. 查看OpenHarmony API接口文档,选取一个功能类似的接口,并比对参数及用法上的差异。例如本文选取osThreadNew ,通过和DemoSdkCreateTask接口比对,可以发现两接口依赖的参数基本一致,只是参数所归属的结构体不同。 + + ``` + typedef struct { + const char *name; ///< name of the thread + uint32_t attr_bits; ///< attribute bits + void *cb_mem; ///< memory for control block + uint32_t cb_size; ///< size of provided memory for control block + void *stack_mem; ///< memory for stack + uint32_t stack_size; ///< size of stack + osPriority_t priority; ///< initial thread priority (default: osPriorityNormal) + TZ_ModuleId_t tz_module; ///< TrustZone module identifier + uint32_t reserved; ///< reserved (must be 0) + } osThreadAttr_t; + + /// Create a thread and add it to Active Threads. + /// \param[in] func thread function. + /// \param[in] argument pointer that is passed to the thread function as start argument. + /// \param[in] attr thread attributes; NULL: default values. + /// \return thread ID for reference by other functions or NULL in case of error. + osThreadId_t osThreadNew (osThreadFunc_t func, void *argument, const osThreadAttr_t *attr); + ``` + +3. 完成代码差异转换。 + + ``` + int DemoSdkCreateTask(unsigned int *handle, const struct TaskPara *para) + { + osThreadAttr_t attr = {0}; + osThreadId_t threadId; + if (handle == 0 || para == 0) { + return DEMOSDK_ERR; + } + if (para->func == 0) { + return DEMOSDK_ERR; + } + if (para->name == 0) { + return DEMOSDK_ERR; + } + attr.name = para->name; + attr.priority = para->prio; + attr.stack_size = para->size; + threadId = osThreadNew((osThreadFunc_t)para->func, para->arg, &attr); + if (threadId == 0) { + printf("osThreadNew fail\n"); + return DEMOSDK_ERR; + } + *(unsigned int *)handle = (unsigned int)threadId; + return DEMOSDK_OK; + } + ``` + + +## 脚本编写 + +开发者在完成代码适配后,还需要在adapter同级目录下新建BUILD.gn文件。该文件可在整包构建时,将适配代码编译成静态库,并链接到bin包中去。在domains/iot/link/demolink/BUILD.gn中,sources中为需要参与构建的源文件,include\_dirs中为依赖的头文件路径,构建目标结果是生产静态库libdemolinkadapter.a。 + +``` +import("//build/lite/config/component/lite_component.gni") +static_library("demolinkadapter") { + sources = [ + "demosdk_adapter.c" + ] + include_dirs = [ + "//kernel/liteos-m/kal/cmsis", + "//domains/iot/link/demolink" + ] +} +``` + +修改domains/iot/link/BUILD.gn文件,使domain/iot/hilink/BUILD.gn参与到构建系统中。 + +``` +import("//build/lite/config/subsystem/lite_subsystem.gni") +import("//build/lite/config/component/lite_component.gni") +lite_subsystem("iot") { + subsystem_components = [ + ":link" + ] +} +lite_component("link") { + features = [ + "demolink:demolinkadapter" + ] +} +``` + +## 编写业务代码 + +业务libs库和适配代码准备就绪后,还需要编写业务入口函数,调起三方SDK的业务入口。 + +下面以demolink举例,介绍如何在applications/sample/wifi-iot/app/路径下编写代码,调起demosdk的入口函数。 + +1. 目录创建 + + 开发者编写业务时,务必先在applications/sample/wifi-iot/app/ 路径下新建一个目录(或一套目录结构),用于存放业务源码文件。 + + 例如:在app下新增业务目录demolink,并在其中创建业务入口代码helloworld.c和编译构建文件BUILD.gn,如下。 + + ``` + . + └── applications + └── sample + └── wifi-iot + └── app + │── demolink + │ │── helloworld.c + │ └── BUILD.gn + └── BUILD.gn + ``` + +2. 编写业务代码。 + + 在helloworld.c文件中编写业务入口函数DemoSdkMain,并调起demolink的业务DemoSdkEntry,最后通过SYS\_RUN\(\)调用入口函数完成业务启动。 + + ``` + #include "hos_init.h" + #include "demosdk.h" + + void DemoSdkMain(void) + { + DemoSdkEntry(); + } + + SYS_RUN(DemoSdkMain); + ``` + +3. 编写构建脚本 + + 新增applications/sample/wifi-iot/app/demolink/BUILD.gn文件,指定源码和头文件路径,编译输出静态库文件libexample\_demolink.a。 + + ``` + static_library("example_demolink") { + sources = [ + "helloworld.c" + ] + include_dirs = [ + "//utils/native/lite/include", + "//domains/iot/link/libbuild" + ] + } + ``` + + 修改applications/sample/wifi-iot/app/BUILD.gn,使demolink参与编译。 + + ``` + import("//build/lite/config/component/lite_component.gni") + lite_component("app") { + features = [ + "demolink:example_demolink" + ] + } + ``` + + +## 运行 + +在代码根目录下,执行命令“hb build”编译输出版本包。最后启动运行,运行结果如图所示,与demolink预期相符。 + +``` +ready to OS start +sdk ver:Hi3861V100R001C00SPC024 2020-08-05 16:30:00 +formatting spiffs... +FileSystem mount ok. +wifi init success! +it is demosdk entry. +it is demo biz: hello world. +it is demo biz: hello world. +``` + +## 结束 + +至此,三方SDK集成已介绍完毕。 + diff --git a/zh-cn/device-dev/guide/device-wifi.md b/zh-cn/device-dev/guide/device-wifi.md new file mode 100644 index 0000000000..3f85bc6f6c --- /dev/null +++ b/zh-cn/device-dev/guide/device-wifi.md @@ -0,0 +1,7 @@ +# WLAN连接类产品 + +- **[LED外设控制](device-wifi-led-outcontrol.md)** + +- **[集成三方SDK](device-wifi-sdk.md)** + + diff --git a/zh-cn/device-dev/guide/device.md b/zh-cn/device-dev/guide/device.md new file mode 100644 index 0000000000..2c7d789c20 --- /dev/null +++ b/zh-cn/device-dev/guide/device.md @@ -0,0 +1,15 @@ +# 设备开发指南 + +- **[WLAN连接类产品](device-wifi.md)** + +- **[无屏摄像头类产品](device-iotcamera.md)** + +- **[带屏摄像头类产品](device-camera.md)** + +- **[时钟应用开发指导](device-clock-guide.md)** + +- **[平台驱动开发示例](device-drive-demo.md)** + +- **[外设驱动开发示例](device-outerdrive-demo.md)** + + diff --git a/zh-cn/device-dev/guide/figures/Clock.png b/zh-cn/device-dev/guide/figure/Clock.png similarity index 100% rename from zh-cn/device-dev/guide/figures/Clock.png rename to zh-cn/device-dev/guide/figure/Clock.png diff --git "a/zh-cn/device-dev/guide/figures/LED\351\227\252\347\203\201\345\233\276.gif" "b/zh-cn/device-dev/guide/figure/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/figures/LED\351\227\252\347\203\201\345\233\276.gif" rename to "zh-cn/device-dev/guide/figure/LED\351\227\252\347\203\201\345\233\276.gif" diff --git a/zh-cn/device-dev/guide/figures/Video_2020-07-25_173141.gif b/zh-cn/device-dev/guide/figure/Video_2020-07-25_173141.gif old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/guide/figures/Video_2020-07-25_173141.gif rename to zh-cn/device-dev/guide/figure/Video_2020-07-25_173141.gif diff --git a/zh-cn/device-dev/guide/figures/zh-cn_image_0000001078563230.png b/zh-cn/device-dev/guide/figure/zh-cn_image_0000001078563230.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/guide/figures/zh-cn_image_0000001078563230.png rename to zh-cn/device-dev/guide/figure/zh-cn_image_0000001078563230.png diff --git a/zh-cn/device-dev/guide/figures/zh-cn_image_0000001082434703.png b/zh-cn/device-dev/guide/figure/zh-cn_image_0000001082434703.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/guide/figures/zh-cn_image_0000001082434703.png rename to zh-cn/device-dev/guide/figure/zh-cn_image_0000001082434703.png diff --git a/zh-cn/device-dev/guide/figures/zh-cn_image_0000001161922745.png b/zh-cn/device-dev/guide/figure/zh-cn_image_0000001169991055.png similarity index 100% rename from zh-cn/device-dev/guide/figures/zh-cn_image_0000001161922745.png rename to zh-cn/device-dev/guide/figure/zh-cn_image_0000001169991055.png diff --git "a/zh-cn/device-dev/guide/figures/\345\220\257\345\212\250\347\244\272\344\276\213.png" "b/zh-cn/device-dev/guide/figure/\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/figures/\345\220\257\345\212\250\347\244\272\344\276\213.png" rename to "zh-cn/device-dev/guide/figure/\345\220\257\345\212\250\347\244\272\344\276\213.png" diff --git "a/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" "b/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" old mode 100755 new mode 100644 similarity index 100% rename from "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" rename to "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" diff --git "a/zh-cn/device-dev/guide/figures/\345\267\245\347\250\213\347\233\256\345\275\225.png" "b/zh-cn/device-dev/guide/figure/\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/figures/\345\267\245\347\250\213\347\233\256\345\275\225.png" rename to "zh-cn/device-dev/guide/figure/\345\267\245\347\250\213\347\233\256\345\275\225.png" diff --git "a/zh-cn/device-dev/guide/figures/\346\237\245\347\234\213\346\226\207\344\273\266\345\233\276.png" "b/zh-cn/device-dev/guide/figure/\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/figures/\346\237\245\347\234\213\346\226\207\344\273\266\345\233\276.png" rename to "zh-cn/device-dev/guide/figure/\346\237\245\347\234\213\346\226\207\344\273\266\345\233\276.png" diff --git "a/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" "b/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" old mode 100755 new mode 100644 similarity index 100% rename from "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" rename to "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" diff --git "a/zh-cn/device-dev/guide/figures/\346\240\207\351\242\230\346\240\217\346\225\210\346\236\234.png" "b/zh-cn/device-dev/guide/figure/\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/figures/\346\240\207\351\242\230\346\240\217\346\225\210\346\236\234.png" rename to "zh-cn/device-dev/guide/figure/\346\240\207\351\242\230\346\240\217\346\225\210\346\236\234.png" diff --git "a/zh-cn/device-dev/guide/figures/\346\241\214\351\235\242.png" "b/zh-cn/device-dev/guide/figure/\346\241\214\351\235\242.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/guide/figures/\346\241\214\351\235\242.png" rename to "zh-cn/device-dev/guide/figure/\346\241\214\351\235\242.png" diff --git "a/zh-cn/device-dev/guide/figures/\346\267\273\345\212\240\351\241\265\351\235\242.png" "b/zh-cn/device-dev/guide/figure/\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/figures/\346\267\273\345\212\240\351\241\265\351\235\242.png" rename to "zh-cn/device-dev/guide/figure/\346\267\273\345\212\240\351\241\265\351\235\242.png" diff --git "a/zh-cn/device-dev/guide/figures/\347\273\230\345\233\2761.png" "b/zh-cn/device-dev/guide/figure/\347\273\230\345\233\2761.png" similarity index 100% rename from "zh-cn/device-dev/guide/figures/\347\273\230\345\233\2761.png" rename to "zh-cn/device-dev/guide/figure/\347\273\230\345\233\2761.png" diff --git "a/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" "b/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" old mode 100755 new mode 100644 similarity index 100% rename from "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" rename to "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" diff --git "a/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" "b/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" old mode 100755 new mode 100644 similarity index 100% rename from "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" rename to "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" diff --git "a/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" "b/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" old mode 100755 new mode 100644 similarity index 100% rename from "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" rename to "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" diff --git "a/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" "b/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" old mode 100755 new mode 100644 similarity index 100% rename from "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" rename to "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" diff --git "a/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" "b/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" old mode 100755 new mode 100644 similarity index 100% rename from "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" rename to "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" diff --git "a/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" "b/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" old mode 100755 new mode 100644 similarity index 100% rename from "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" rename to "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" diff --git "a/zh-cn/device-dev/guide/figures/\351\242\204\350\247\210\346\225\210\346\236\234.jpg" "b/zh-cn/device-dev/guide/figure/\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/figures/\351\242\204\350\247\210\346\225\210\346\236\234.jpg" rename to "zh-cn/device-dev/guide/figure/\351\242\204\350\247\210\346\225\210\346\236\234.jpg" diff --git a/zh-cn/device-dev/guide/public_sys-resources/icon-caution.gif b/zh-cn/device-dev/guide/public_sys-resources/icon-caution.gif deleted file mode 100755 index 6e90d7cfc2193e39e10bb58c38d01a23f045d571..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 580 zcmV-K0=xZ3Nk%w1VIu$?0Hp~4{QBgqmQ+MG9K51r{QB&)np^||1PlfQ%(86!{`~yv zv{XhUWKt}AZaiE{EOcHp{O-j3`t;<+eEiycJT4p@77X;(jQsMfB$R?oG%6hQ z+MMLZbQBH@)Vg&1^3?qHb(5!%>3r0+`eq=&V&E}0Dypi0000000000 z00000A^8LW000R9EC2ui03!e$000L5z=Uu}ED8YtqjJd<+B}(9bIOb$3-31_h|V>=0A{ z1Hh0#H30>fNT})^fRU_83uewx9oRr{f{Sx1Ml`t)EQ zGkHZ67&~y{W5Jpq4H_WfuLxp*3<7O}GEl;1ESe36fLNs=B0&LQM1Buf(R)qg(BRd`t1OPjI1m_q4 diff --git a/zh-cn/device-dev/guide/public_sys-resources/icon-danger.gif b/zh-cn/device-dev/guide/public_sys-resources/icon-danger.gif deleted file mode 100755 index 6e90d7cfc2193e39e10bb58c38d01a23f045d571..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 580 zcmV-K0=xZ3Nk%w1VIu$?0Hp~4{QBgqmQ+MG9K51r{QB&)np^||1PlfQ%(86!{`~yv zv{XhUWKt}AZaiE{EOcHp{O-j3`t;<+eEiycJT4p@77X;(jQsMfB$R?oG%6hQ z+MMLZbQBH@)Vg&1^3?qHb(5!%>3r0+`eq=&V&E}0Dypi0000000000 z00000A^8LW000R9EC2ui03!e$000L5z=Uu}ED8YtqjJd<+B}(9bIOb$3-31_h|V>=0A{ z1Hh0#H30>fNT})^fRU_83uewx9oRr{f{Sx1Ml`t)EQ zGkHZ67&~y{W5Jpq4H_WfuLxp*3<7O}GEl;1ESe36fLNs=B0&LQM1Buf(R)qg(BRd`t1OPjI1m_q4 diff --git a/zh-cn/device-dev/guide/public_sys-resources/icon-note.gif b/zh-cn/device-dev/guide/public_sys-resources/icon-note.gif deleted file mode 100755 index 6314297e45c1de184204098efd4814d6dc8b1cda..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 394 zcmZ?wbhEHblx7fPSjxcg=ii?@_wH=jwxy=7CMGH-B`L+l$wfv=#>UF#$gv|VY%C^b zCQFtrnKN(Bo_%|sJbO}7RAORe!otL&qo<>yq_Sq+8Xqqo5h0P3w3Lvb5E(g{p01vl zxR@)KuDH0l^z`+-dH3eaw=XqSH7aTIx{kzVBN;X&hha0dQSgWuiw0NWUvMRmkD|> diff --git a/zh-cn/device-dev/guide/public_sys-resources/icon-notice.gif b/zh-cn/device-dev/guide/public_sys-resources/icon-notice.gif deleted file mode 100755 index 86024f61b691400bea99e5b1f506d9d9aef36e27..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 406 zcmV;H0crk6Nk%w1VIu$@0J8u9|NsB@_xJDb@8;&_*4Ea}&d#;9wWXz{jEszHYim+c zQaU<1At50E0000000000A^8Le000gEEC2ui03!e%000R7038S%NU)&51O^i-Tu6`s z0)`MFE@;3YqD6xSC^kTNu_J>91{PH8XfZ(p1pp2-SU@u3#{mEUC}_}tg3+I#{z}{Ok@D_ZUDg- zt0stin4;pC8M{WLSlRH*1pzqEw1}3oOskyNN?j;7HD{BBZ*OEcv4HK!6Bk6beR+04 z&8}k>SkTusVTDmkyOz#5fCA$JTPGJVQvr3uZ?QzzPQFvD0rGf_PdrcF`pMs}p^BcF zKtKTd`0wipR%nKN&Wj+V}pX;WC3SdJV!a_8Qi zE7z`U*|Y^H0^}fB$R?oG%6hQ z+MMLZbQBH@)Vg&1^3?qHb(5!%>3r0+`eq=&V&E}0Dypi0000000000 z00000A^8LW000R9EC2ui03!e$000L5z=Uu}ED8YtqjJd<+B}(9bIOb$3-31_h|V>=0A{ z1Hh0#H30>fNT})^fRU_83uewx9oRr{f{Sx1Ml`t)EQ zGkHZ67&~y{W5Jpq4H_WfuLxp*3<7O}GEl;1ESe36fLNs=B0&LQM1Buf(R)qg(BRd`t1OPjI1m_q4 diff --git "a/zh-cn/device-dev/guide/\345\205\254\345\205\261\351\251\261\345\212\250\345\261\202\345\210\235\345\247\213\345\214\226\345\217\212\346\263\250\345\206\214\351\251\261\345\212\250\350\207\263HDF\346\241\206\346\236\266.md" "b/zh-cn/device-dev/guide/\345\205\254\345\205\261\351\251\261\345\212\250\345\261\202\345\210\235\345\247\213\345\214\226\345\217\212\346\263\250\345\206\214\351\251\261\345\212\250\350\207\263HDF\346\241\206\346\236\266.md" deleted file mode 100644 index 31de19a1b1..0000000000 --- "a/zh-cn/device-dev/guide/\345\205\254\345\205\261\351\251\261\345\212\250\345\261\202\345\210\235\345\247\213\345\214\226\345\217\212\346\263\250\345\206\214\351\251\261\345\212\250\350\207\263HDF\346\241\206\346\236\266.md" +++ /dev/null @@ -1,35 +0,0 @@ -# 公共驱动层初始化及注册驱动至HDF框架 - -示例代码路径:./drivers/framework/model/input/driver/hdf\_touch.c - -``` -static int32_t HdfTouchDriverProbe(struct HdfDeviceObject *device) -{ - ... - /* 板级信息结构体内存申请及hcs配置信息解析 */ - boardCfg = BoardConfigInstance(device); - ... - /* 公共驱动结构体内存申请 */ - touchDriver = TouchDriverInstance(); - ... - /* 依据解析出的板级信息进行公共资源初始化,如IIC初始化 */ - ret = TouchDriverInit(touchDriver, boardCfg); - if (ret == HDF_SUCCESS) { - ... - /* 添加驱动至公共驱动层驱动管理链表,当设备与驱动进行绑定时使用该链表进行查询 */ - AddTouchDriver(touchDriver); - ... - } - ... -} -struct HdfDriverEntry g_hdfTouchEntry = { - .moduleVersion = 1, - .moduleName = "HDF_TOUCH", - .Bind = HdfTouchDriverBind, - .Init = HdfTouchDriverProbe, - .Release = HdfTouchDriverRelease, -}; - -HDF_INIT(g_hdfTouchEntry); //驱动注册入口 -``` - diff --git "a/zh-cn/device-dev/guide/\345\205\267\344\275\223\350\260\203\347\224\250\351\200\273\350\276\221\344\270\262\350\201\224\345\207\275\346\225\260.md" "b/zh-cn/device-dev/guide/\345\205\267\344\275\223\350\260\203\347\224\250\351\200\273\350\276\221\344\270\262\350\201\224\345\207\275\346\225\260.md" deleted file mode 100644 index 9fc526d210..0000000000 --- "a/zh-cn/device-dev/guide/\345\205\267\344\275\223\350\260\203\347\224\250\351\200\273\350\276\221\344\270\262\350\201\224\345\207\275\346\225\260.md" +++ /dev/null @@ -1,40 +0,0 @@ -# 具体调用逻辑串联函数 - -Input模型管理层驱动init函数初始化了设备管理链表,公共驱动层初始化函数完成了相关结构体的内存申请。器件驱动相关信息通过RegisterChipDevice函数对公共驱动层相关结构体进行信息填充,同时完成了相关硬件信息的初始化(如中断注册等),绑定设备与驱动组成inputDev通过RegisterInputDevice函数向驱动管理层进行注册,在RegisterInputDevice函数中主要实现了将inputDev向设备管理链表的添加等功能。如下所示为两个函数的实现部分: - -``` -//函数具体实现代码位置 :./drivers/framework/model/input/driver/hdf_touch.c -int32_t RegisterChipDevice(ChipDevice *chipDev) -{ - ... - /* 绑定设备与驱动,从而通过InputDeviceInstance函数创建inputDev */ - DeviceBindDriver(chipDev); - ... - /* 主要包含器件中断注册及中断处理函数,中断处理函数中有数据上报用户态的数据通道 */ - ChipDriverInit(chipDev); - ... - /* 申请内存实例化InputDev */ - inputDev = InputDeviceInstance(chipDev); - ... - /* 将InputDev设备注册至input驱动管理层 */ - RegisterInputDevice(inputDev); - ... -} - -//函数具体实现代码位置 :./drivers/framework/model/input/driver/hdf_input_device_manager.c -int32_t RegisterInputDevice(InputDevice *inputDev) -{ - ... - /* 申请ID,该ID对于不同input设备唯一 */ - ret = AllocDeviceID(inputDev); - ... - /* 该函数包含了对hid类设备的特殊处理,对于触摸屏驱动,该函数无实质操作; */ - CreateDeviceNode(inputDev); - /* 内核态数据传送至用户态需使用IOService能力,需要申请buffer */ - AllocPackageBuffer(inputDev); - /* 将input设备添加进设备全局管理链表 */ - AddInputDevice(inputDev); - ... -} -``` - diff --git "a/zh-cn/device-dev/guide/\345\231\250\344\273\266\351\251\261\345\212\250\345\261\202\345\210\235\345\247\213\345\214\226\345\217\212\346\263\250\345\206\214\351\251\261\345\212\250\350\207\263HDF\346\241\206\346\236\266.md" "b/zh-cn/device-dev/guide/\345\231\250\344\273\266\351\251\261\345\212\250\345\261\202\345\210\235\345\247\213\345\214\226\345\217\212\346\263\250\345\206\214\351\251\261\345\212\250\350\207\263HDF\346\241\206\346\236\266.md" deleted file mode 100644 index 4cfddfa469..0000000000 --- "a/zh-cn/device-dev/guide/\345\231\250\344\273\266\351\251\261\345\212\250\345\261\202\345\210\235\345\247\213\345\214\226\345\217\212\346\263\250\345\206\214\351\251\261\345\212\250\350\207\263HDF\346\241\206\346\236\266.md" +++ /dev/null @@ -1,4 +0,0 @@ -# 器件驱动层初始化及注册驱动至HDF框架 - -具体请参考[3.3章节](适配器件私有驱动.md)器件层驱动初始化及注册驱动至HDF框架部分。 - diff --git "a/zh-cn/device-dev/guide/\345\244\226\350\256\276\351\251\261\345\212\250\345\274\200\345\217\221\347\244\272\344\276\213.md" "b/zh-cn/device-dev/guide/\345\244\226\350\256\276\351\251\261\345\212\250\345\274\200\345\217\221\347\244\272\344\276\213.md" deleted file mode 100644 index 8b08382712..0000000000 --- "a/zh-cn/device-dev/guide/\345\244\226\350\256\276\351\251\261\345\212\250\345\274\200\345\217\221\347\244\272\344\276\213.md" +++ /dev/null @@ -1,15 +0,0 @@ -# 外设驱动开发示例 - -- **[概述](概述-12.md)** - -- **[环境搭建](环境搭建.md)** - -- **[TouchScreen器件驱动开发](TouchScreen器件驱动开发.md)** - -- **[编译及烧录](编译及烧录-13.md)** - -- **[调试验证](调试验证.md)** - -- **[Input模型工作流程解析](Input模型工作流程解析.md)** - - diff --git "a/zh-cn/device-dev/guide/\345\261\217\345\271\225\345\222\214\346\221\204\345\203\217\345\244\264\346\216\247\345\210\266.md" "b/zh-cn/device-dev/guide/\345\261\217\345\271\225\345\222\214\346\221\204\345\203\217\345\244\264\346\216\247\345\210\266.md" deleted file mode 100755 index 7fed33d8a7..0000000000 --- "a/zh-cn/device-dev/guide/\345\261\217\345\271\225\345\222\214\346\221\204\345\203\217\345\244\264\346\216\247\345\210\266.md" +++ /dev/null @@ -1,9 +0,0 @@ -# 屏幕和摄像头控制 - -- **[概述](概述-1.md)** - -- **[示例开发](示例开发-2.md)** - -- **[应用实例](应用实例-5.md)** - - diff --git "a/zh-cn/device-dev/guide/\345\270\246\345\261\217\346\221\204\345\203\217\345\244\264\347\261\273\344\272\247\345\223\201.md" "b/zh-cn/device-dev/guide/\345\270\246\345\261\217\346\221\204\345\203\217\345\244\264\347\261\273\344\272\247\345\223\201.md" deleted file mode 100755 index 0dacd47e00..0000000000 --- "a/zh-cn/device-dev/guide/\345\270\246\345\261\217\346\221\204\345\203\217\345\244\264\347\261\273\344\272\247\345\223\201.md" +++ /dev/null @@ -1,7 +0,0 @@ -# 带屏摄像头类产品 - -- **[屏幕和摄像头控制](屏幕和摄像头控制.md)** - -- **[视觉应用开发](视觉应用开发.md)** - - diff --git "a/zh-cn/device-dev/guide/\345\270\270\350\247\201\351\227\256\351\242\230-10.md" "b/zh-cn/device-dev/guide/\345\270\270\350\247\201\351\227\256\351\242\230-10.md" deleted file mode 100644 index 24be547245..0000000000 --- "a/zh-cn/device-dev/guide/\345\270\270\350\247\201\351\227\256\351\242\230-10.md" +++ /dev/null @@ -1,39 +0,0 @@ -# 常见问题 - -- [hdc\_std连接不到设备](#section1221016541119) -- [hdc\_std运行不了](#section219185710311) - -## hdc\_std连接不到设备 - -- **现象描述** - - 执行 "hdc\_std list targets"命令后结果为:\[Empty\] - -- **可能原因和解决方法** - 1. 设备没有被识别: - - 在设备管理器中查看是否有hdc设备,在通用串行总线设备中会有“HDC Device”信息。如果没有,hdc无法连接。此时需要插拔设备,或者烧写最新的镜像。 - - 2. hdc\_std工作异常: - - 可以执行"hdc kill"或者"hdc start -r"杀掉hdc服务或者重启hdc服务,然后再执行hdc list targets查看是否已经可以获取设备信息。 - - 如果一直获取不到设备信息,请在任务管理器中查询是否有adb进程,该进程可能会对hdc产生干扰,可以将其杀掉后重复执行上面的步骤。 - - 3. hdc\_std与设备不匹配: - - 如果设备烧写的是最新镜像,hdc\_std也需要使用最新版本。由于hdc\_std会持续更新,请从开源仓developtools\_hdc\_standard中获取,具体位置在该开源仓的prebuilt目录。 - - - -## hdc\_std运行不了 - -- **现象描述** - - 点击hdc\_std.exe文件无法运行。 - -- **可能原因和解决方法** - - hdc\_std.exe不需要安装,直接放到磁盘上就能使用,也可以添加到环境变量中。通过打开cmd执行hdc\_std命令直接使用。 - - diff --git "a/zh-cn/device-dev/guide/\345\271\263\345\217\260\351\251\261\345\212\250\345\274\200\345\217\221\347\244\272\344\276\213.md" "b/zh-cn/device-dev/guide/\345\271\263\345\217\260\351\251\261\345\212\250\345\274\200\345\217\221\347\244\272\344\276\213.md" deleted file mode 100644 index 5dc1dd07b5..0000000000 --- "a/zh-cn/device-dev/guide/\345\271\263\345\217\260\351\251\261\345\212\250\345\274\200\345\217\221\347\244\272\344\276\213.md" +++ /dev/null @@ -1,11 +0,0 @@ -# 平台驱动开发示例 - -- **[概述](概述-10.md)** - -- **[环境准备](环境准备.md)** - -- **[开发](开发-11.md)** - -- **[编译及烧录](编译及烧录.md)** - - diff --git "a/zh-cn/device-dev/guide/\345\272\224\347\224\250\345\256\236\344\276\213-5.md" "b/zh-cn/device-dev/guide/\345\272\224\347\224\250\345\256\236\344\276\213-5.md" deleted file mode 100755 index a5da7138f9..0000000000 --- "a/zh-cn/device-dev/guide/\345\272\224\347\224\250\345\256\236\344\276\213-5.md" +++ /dev/null @@ -1,63 +0,0 @@ -# 应用实例 - -本示例将运行源码中的camera示例代码,通过本示例可以实现对开发板拍照、录像及预览功能的控制。 - -- 本示例源码路径为“applications/sample/camera/media/camera\_sample.cpp”。 -- 在运行本示例前需先完成编译烧录、运行镜像等步骤,相关操作请参考[Hi3516快速入门](../quick-start/Hi3516开发板介绍.md) - - >![](public_sys-resources/icon-note.gif) **说明:** - >开发板启动后默认会加载launcher应用,应用的图形界面默认显示在媒体图层上方,会影响camera\_sample的演示结果,因此需要在编译或是打包时去掉launcher应用。 - >**修改方法:**将“build/lite/components/applications.json”中camera\_sample\_app组件的targets中"//applications/sample/camera/launcher:launcher\_hap"整行注释或删除。 - -- 本示例编译结果路径为“out/hi3516dv300/ipcamera\_hi3516dv300\_liteos/dev\_tools/bin”,为让文件能在单板中执行,可将示例文件通过读卡器复制至TF卡中,或者修改camera\_sample的编译脚本将结果文件复制至rootfs.img中。 - - 修改源码路径“applications/sample/camera/media/BUILD.gn”中第一处的output\_dir。 - - - 修改前:output\_dir = "$root\_out\_dir/dev\_ools" - - 修改后:output\_dir = "$root\_out\_dir/" - - 重新执行源码仓编译并烧写入单板后,可在单板bin目录下找到camera\_sample文件。 - - >![](public_sys-resources/icon-notice.gif) **须知:** - >实例运行拍照和录像功能需要插入TF卡\(最大容量支持128GB\),系统启动后自动将TF卡挂载至/sdcard目录,如果在启动后插入则需要手动挂载。查看拍照和录像内容可将TF卡中内容复制到电脑中进行查看,预览功能无需TF卡。 - -- 接下来可通过以下步骤运行示例: - -1. 通过cd命令进入可执行程序的末端路径,启动camera\_sample,执行命令如下图。 - - **图 1** 启动示例 - ![](figures/启动示例.png "启动示例") - - 运行后的控制命令如串口打印所示,按s键停止当前操作(包括录像和预览),按q键退出示例程序。 - -2. 按1进行拍照,拍照的文件格式为jpg,存储在/sdcard,文件名Capture\* - - **图 2** 输入拍照指令后串口打印日志 - ![](figures/输入拍照指令后串口打印日志.png "输入拍照指令后串口打印日志") - - 若想查看保存文件,可在退出程序后进入文件系统查看,退出后重新进入请回到步骤1。 - - **图 3** 查看文件图 - ![](figures/查看文件图.png "查看文件图") - -3. 按2进行录像,录像的文件格式为mp4,存储在/sdcard,文件名Record\*,按s键停止 - - **图 4** 输入录像指令后串口打印日志 - ![](figures/输入录像指令后串口打印日志.png "输入录像指令后串口打印日志") - -4. 按3进行预览,预览图像直接送至显示屏,按s键停止。 - - **图 5** 输入预览指令后串口打印日志 - ![](figures/输入预览指令后串口打印日志.png "输入预览指令后串口打印日志") - - 预览效果如下 - - **图 6** 预览效果 - ![](figures/预览效果.jpg "预览效果") - -5. 按q键退出 - - **图 7** 输出退出指令后串口打印日志 - ![](figures/输出退出指令后串口打印日志.png "输出退出指令后串口打印日志") - - diff --git "a/zh-cn/device-dev/guide/\345\272\224\347\224\250\345\256\236\344\276\213.md" "b/zh-cn/device-dev/guide/\345\272\224\347\224\250\345\256\236\344\276\213.md" deleted file mode 100755 index 21cb165165..0000000000 --- "a/zh-cn/device-dev/guide/\345\272\224\347\224\250\345\256\236\344\276\213.md" +++ /dev/null @@ -1,45 +0,0 @@ -# 应用实例 - -- 开发板介绍、编译烧录、运行镜像等操作请参考[Hi3518快速入门](../quick-start/Hi3518开发板介绍.md),编译结果包含示例,结果文件为out/ipcamera\_hi3518ev300/dev\_tools/bin/camera\_sample,可将文件通过读卡器复制至TF卡中,或者修改camera\_sample的编译脚本将结果文件复制至rootfs.img中。 - - 修改applications/sample/camera/media/BUILD.gn中的output\_dir。 - - - 修改前:output\_dir = "$root\_out\_dir/dev\_tools" - - 修改后:output\_dir = "$root\_out\_d_i_r/" - - 重新执行源码仓编译并烧写入单板后,可在单板bin目录下找到camera\_sample文件。 - -- 相机示例代码为applications/sample/camera/media/camera\_sample.cpp。 - - >![](public_sys-resources/icon-notice.gif) **须知:** - >实例运行拍照和录像功能需要插入TF卡\(最大容量支持128GB\),系统启动后时自动将TF卡挂载至/sdcard目录,如果在启动后插入则需要手动挂载。查看拍照和录像内容可将TF卡中内容复制到电脑中进行查看,预览功能无需TF卡。 - - -1. 通过cd命令进入可执行程序的末端路径,启动camera\_sample,执行命令如下图。 - - **图 1** 启动示例 - ![](figures/启动示例.png "启动示例") - - 运行后的控制命令如串口打印所示,按s键停止当前操作(包括录像和预览),按q键退出示例程序。 - -2. 按1进行拍照,拍照的文件格式为jpg,存储在/sdcard,文件名Capture\* - - **图 2** 输入拍照指令后串口打印日志 - ![](figures/输入拍照指令后串口打印日志.png "输入拍照指令后串口打印日志") - - 若想查看保存文件,可在退出程序后进入文件系统查看,退出后重新进入请回到步骤1。 - - **图 3** 查看文件图 - ![](figures/查看文件图.png "查看文件图") - -3. 按2进行录像,录像的文件格式为mp4,存储在/sdcard,文件名Record\*,按s键停止 - - **图 4** 输入录像指令后串口打印日志 - ![](figures/输入录像指令后串口打印日志.png "输入录像指令后串口打印日志") - -4. 按q键退出 - - **图 5** 输出退出指令后串口打印日志 - ![](figures/输出退出指令后串口打印日志.png "输出退出指令后串口打印日志") - - diff --git "a/zh-cn/device-dev/guide/\345\274\200\345\217\221-11.md" "b/zh-cn/device-dev/guide/\345\274\200\345\217\221-11.md" deleted file mode 100644 index a7dedada78..0000000000 --- "a/zh-cn/device-dev/guide/\345\274\200\345\217\221-11.md" +++ /dev/null @@ -1,396 +0,0 @@ -# 开发 - -- [实例化驱动入口](#section6586911816) -- [设置相关参数](#section114323217503) -- [添加控制器](#section115187812516) - -平台驱动开发包含以下几步: - -1. 实例化驱动入口: 实例化一个HdfDriverEntry 对象作为驱动入口。 -2. 设置相关参数:通过配置device\_info.hcs,并从HCS获取并解析设备的配置参数以确保驱动能够正确加载。 -3. 添加控制器:初始化控制器硬件,并调用核心层接口完成向核心层添加、删除设备,以及钩子函数的实现等。 - -本例中涉及的文件及路径如下表: - -**表 1** 文件说明 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    说明

    -

    文件路径

    -

    操作

    -

    示例文件

    -

    /drivers/adapter/khdf/linux/platform/i2c/i2c_sample.c

    -

    新增文件

    -

    设备服务文件

    -

    /drivers/adapter/khdf/linux/hcs/device_info/device_info.hcs

    -

    -

    追加内容

    -

    -

    配置参数文件

    -

    /drivers/adapter/khdf/linux/hcs/platform/i2c_config.hcs

    -

    编译文件

    -

    /drivers/adapter/khdf/linux/platform/i2c/Makefile

    -

    依赖头文件

    -

    /drivers/framework/include/core/hdf_device_desc.h

    -

    作为头文件引用

    -

    -

    核心层头文件

    -

    /drivers/framework/support/platform/include/i2c_core.h

    -

    HCS配置入口文件

    -

    /drivers/adapter/khdf/linux/hcs/hdf.hcs

    -

    HCS配置文件总入口

    -
    - ->![](public_sys-resources/icon-caution.gif) **注意:** ->本例程涉及的文件路径均作为演示,驱动开发者应根据实际情况确定具体的源文件存放位置。 - -## 实例化驱动入口 - -驱动入口必须为HdfDriverEntry(在hdf\_device\_desc.h中定义)类型的全局变量,且moduleName要和device\_info.hcs中保持一致。在加载驱动时HDF框架会先调用Bind函数,再调用Init函数加载该驱动,当Init调用异常时,HDF框架会调用Release释放驱动资源并退出。 - -I2C驱动中没有实现Bind方法,因为I2C控制器由manager管理,而在manager中已经实现了Bind方法,因此I2C驱动中无需再绑定服务。 - -实例化驱动入口的示例代码如下: - -``` -/* 定义驱动入口的对象,必须为HdfDriverEntry(在hdf_device_desc.h中定义)类型的全局变量 */ -struct HdfDriverEntry g_sampleI2cDriverEntry = { - .moduleVersion = 1, - .Init = SampleI2cInit, - .Release = SampleI2cRelease, - .moduleName = "demo_i2c_driver", -}; -/* 调用HDF_INIT将驱动入口注册到HDF框架中 */ -HDF_INIT(g_sampleI2cDriverEntry); -``` - -## 设置相关参数 - -1. 添加设备服务节点(必选)。 - - 编辑device\_info.hcs,在device\_i2c :: device下添加驱动设备服务节点,示例如下: - - ``` - root { - device_info { - match_attr = "hdf_manager"; - device_i2c :: device { // i2c设备节点 - device2 :: deviceNode { // i2c驱动的DeviceNode节点 - policy = 0; // policy字段是驱动服务发布的策略 - priority = 55; // 驱动启动优先级 - permission = 0644; // 驱动创建设备节点权限 - moduleName = "demo_i2c_driver"; // 驱动名称,该字段的值必须和驱动入口结构的moduleName值一致 - serviceName = "DEMO_I2C_DRIVER"; // 驱动对外发布服务的名称,必须唯一 - deviceMatchAttr = "demo_i2c_config"; // 驱动私有数据匹配的关键字,必须和驱动私有数据配置表中的 - // match_attr值相等 - } - } - } - } - - ``` - - >![](public_sys-resources/icon-notice.gif) **须知:** - >配置文件中的priority(取值范围为整数0到200)是用来表示host和驱动的优先级,不同的host内的驱动,host的priority值越小,驱动加载优先级越高;同一个host内驱动的priority值越小,加载优先级越高,驱动的priority值相同则不保证加载顺序。 - -2. 添加配置参数(可选)。 - - 有时驱动可能会需要私有配置信息,以确保寄存器的配置可以满足不同产品的需求。如需要私有配置信息,则可以添加一个驱动的配置文件,用来存放一些驱动的默认配置信息,HDF框架在加载驱动的时候,会将对应的配置信息获取并保存在HdfDeviceObject 中的property里面,通过Bind和Init(参考[驱动开发](../driver/驱动开发.md))传递给驱动。驱动开发者可新建配置文件,并在板级驱动hdf.hcs中引用新建的配置文件,本例中直接在原有的配置文件i2c\_config.hcs内添加配置参数。 - - 本例中编辑i2c\_config.hcs,添加配置参数: - - ``` - root { - platform { - i2c_config_demo { - match_attr = "demo_i2c_config"; // 该字段的值必须和device_info.hcs中的deviceMatchAttr值一致 - - template i2c_controller { // 参数模板 - bus = 0; - reg_pbase = 0x120b0000; - reg_size = 0xd1; - } - - controller_demo_0 :: i2c_controller { // 两个I2C示例控制器 - bus = 8; - } - controller_demo_1 :: i2c_controller { - bus = 9; - } - } - } - } - ``` - - match\_attr字段必须与device\_info.hcs中的deviceMatch\_Attr保持一致,在此文件中配置驱动需要的参数,通过match\_attr可匹配至对应的驱动,该驱动即可在Bind或Init中调用DeviceResourceGetIfaceInstance\(\)函数获取这些配置参数。 - - 若配置文件为新文件,则需要在板级配置入口文件hdf.hcs中引用该配置文件,例如: - - ``` - #include "device_info/device_info.hcs" - #include "i2c/i2c_config.hcs" - ``` - - 由于本例中在原有的i2c\_config.hcs内添加配置参数,没有新建配置文件,因此无需再将i2c\_config.hcs添加至板级配置入口文件中。 - -3. 驱动从HCS获取配置参数。 - - 在本例中,驱动需要通过HCS获取寄存器物理基地址、寄存器大小、总线号等参数,从而对控制器进行正确配置。 - - ``` - /* 从HCS获取配置参数 */ - static int32_t SampleI2cReadDrs(struct SampleI2cCntlr *sampleCntlr, const struct DeviceResourceNode *node) - { - int32_t ret; - struct DeviceResourceIface *drsOps = NULL; - - drsOps = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE); - if (drsOps == NULL || drsOps->GetUint32 == NULL) { // 确保GetUint32方法可用 - HDF_LOGE("%s: invalid drs ops fail!", __func__); - return HDF_FAILURE; - } - - ret = drsOps->GetUint32(node, "reg_pbase", &sampleCntlr->regBasePhy, 0); // 从HCS读取物理基地址reg_pbase - if (ret != HDF_SUCCESS) { - HDF_LOGE("%s: read regBase fail!", __func__); - return ret; - } - - ret = drsOps->GetUint16(node, "reg_size", &sampleCntlr->regSize, 0); // 从HCS读取寄存器大小reg_size - if (ret != HDF_SUCCESS) { - HDF_LOGE("%s: read regsize fail!", __func__); - return ret; - } - - ret = drsOps->GetUint16(node, "bus", (uint16_t *)&sampleCntlr->bus, 0); // 从HCS读取总线号bus - if (ret != HDF_SUCCESS) { - HDF_LOGE("%s: read bus fail!", __func__); - return ret; - } - - return HDF_SUCCESS; - } - ``` - - -## 添加控制器 - -1. 定义结构体,实现钩子函数并赋值至函数指针。 - - I2cMethod结构体在i2c\_core.h中定义,其中通过函数指针的方式定义了I2C需要实现的方法,transfer方法为用于传输的钩子函数,在驱动中需要做具体实现并对函数指针赋值。 - - 示例代码如下: - - ``` - /* 自定义设备结构体,继承父类I2cCntlr */ - struct SampleI2cCntlr { - struct I2cCntlr cntlr; - OsalSpinlock spin; - volatile unsigned char *regBase; - uint16_t regSize; - int16_t bus; - uint32_t regBasePhy; - }; - - /* 消息结构体,继承父类I2cMsg */ - struct SampleTransferData { - struct I2cMsg *msgs; - int16_t index; - int16_t count; - }; - /* 钩子函数实现 */ - static int32_t SampleI2cTransfer(struct I2cCntlr *cntlr, struct I2cMsg *msgs, int16_t count) - { - int32_t ret = HDF_SUCCESS; - struct SampleI2cCntlr *sampleCntlr = NULL; - struct SampleTransferData td; - - if (cntlr == NULL || cntlr->priv == NULL) { - HDF_LOGE("SampleI2cTransfer: cntlr lor sampleCntlr is null!"); - return HDF_ERR_INVALID_OBJECT; - } - sampleCntlr = (struct SampleI2cCntlr *)cntlr; - - if (msgs == NULL || count <= 0) { - HDF_LOGE("SampleI2cTransfer: err parms! count:%d", count); - return HDF_ERR_INVALID_PARAM; - } - td.msgs = msgs; - td.count = count; - td.index = 0; - - HDF_LOGE("Successfully transmitted!"); // 表示此处传输成功 - - td.index = count; // 经过处理,最后实际发送msg个数等于count,返回已发送个数,此句代替已省略的处理过程 - return (td.index > 0) ? td.index : ret; - } - /* 钩子函数赋值 */ - static struct I2cMethod g_method = { - .transfer = SampleI2cTransfer, - }; - ``` - -2. 编写驱动初始化函数。 - - 本例中使用SampleI2cInit作为驱动初始化函数的函数名(函数名称可由驱动开发者确定),该函数需要在驱动入口结构体中赋值给Init,以供HDF驱动框架调用从而达到初始化驱动的目的。该函数中需要对从HCS获取的配置参数进行解析,并按照这些参数创建控制器。示例如下: - - ``` - /* 解析参数,申请内存并创建控制器 */ - static int32_t SampleI2cParseAndInit(struct HdfDeviceObject *device, const struct DeviceResourceNode *node) - { - int32_t ret; - struct SampleI2cCntlr *sampleCntlr = NULL; - (void)device; - - sampleCntlr = (struct SampleI2cCntlr *)OsalMemCalloc(sizeof(*sampleCntlr)); - if (sampleCntlr == NULL) { - HDF_LOGE("%s: malloc sampleCntlr fail!", __func__); - return HDF_ERR_MALLOC_FAIL; - } - - ret = SampleI2cReadDrs(sampleCntlr, node); // 从HCS获取配置参数 - if (ret != HDF_SUCCESS) { - HDF_LOGE("%s: read drs fail! ret:%d", __func__, ret); - goto __ERR__; - } - - sampleCntlr->regBase = OsalIoRemap(sampleCntlr->regBasePhy, sampleCntlr->regSize); - if (sampleCntlr->regBase == NULL) { - HDF_LOGE("%s: ioremap regBase fail!", __func__); - ret = HDF_ERR_IO; - goto __ERR__; - } - - HDF_LOGE("The controller has been initialized!"); // 表示此处省略的控制器初始化操作已经成功 - - sampleCntlr->cntlr.priv = (void *)node; - sampleCntlr->cntlr.busId = sampleCntlr->bus; - sampleCntlr->cntlr.ops = &g_method; - (void)OsalSpinInit(&sampleCntlr->spin); // 初始化自旋锁 - ret = I2cCntlrAdd(&sampleCntlr->cntlr); // 向核心层添加控制器 - if (ret != HDF_SUCCESS) { - HDF_LOGE("%s: add i2c controller fail:%d!", __func__, ret); - goto __ERR__; - } - - return HDF_SUCCESS; - __ERR__: // 错误处理 - if (sampleCntlr != NULL) { - if (sampleCntlr->regBase != NULL) { - OsalIoUnmap((void *)sampleCntlr->regBase); // 取消地址映射 - sampleCntlr->regBase = NULL; - } - OsalMemFree(sampleCntlr); // 释放内存 - sampleCntlr = NULL; - } - return ret; - } - /* 驱动入口初始化函数 */ - static int32_t SampleI2cInit(struct HdfDeviceObject *device) - { - int32_t ret; - const struct DeviceResourceNode *childNode = NULL; - - HDF_LOGE("%s: Enter", __func__); - if (device == NULL || device->property == NULL) { - HDF_LOGE("%s: device or property is NULL", __func__); - return HDF_ERR_INVALID_OBJECT; - } - - ret = HDF_SUCCESS; - DEV_RES_NODE_FOR_EACH_CHILD_NODE(device->property, childNode) { - ret = SampleI2cParseAndInit(device, childNode); // 调用解析参数和创建控制器的函数 - if (ret != HDF_SUCCESS) { - break; - } - } - return ret; - } - ``` - -3. 编写驱动释放函数。 - - 本例中使用SampleI2cRelease作为驱动释放函数的函数名(函数名称可由驱动开发者确定),该函数需要在驱动入口结构体中赋值给Release,当HDF框架调用Init函数初始化驱动失败时,将调用Release释放驱动资源。该函数中需包含释放内存和删除控制器等操作。示例如下: - - ``` - /* 删除控制器函数 */ - static void SampleI2cRemoveByNode(const struct DeviceResourceNode *node) - { - int32_t ret; - int16_t bus; - struct I2cCntlr *cntlr = NULL; - struct SampleI2cCntlr *sampleCntlr = NULL; - struct DeviceResourceIface *drsOps = NULL; - - drsOps = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE); - if (drsOps == NULL || drsOps->GetUint32 == NULL) { - HDF_LOGE("%s: invalid drs ops fail!", __func__); - return; - } - - ret = drsOps->GetUint16(node, "bus", (uint16_t *)&bus, 0); // 从HCS获取I2C总线号 - if (ret != HDF_SUCCESS) { - HDF_LOGE("%s: read bus fail!", __func__); - return; - } - - cntlr = I2cCntlrGet(bus); - if (cntlr != NULL && cntlr->priv == node) { // 根据I2C总线号删除控制器 - I2cCntlrPut(cntlr); - I2cCntlrRemove(cntlr); - sampleCntlr = (struct SampleI2cCntlr *)cntlr; - OsalIoUnmap((void *)sampleCntlr->regBase); - OsalMemFree(sampleCntlr); - } - return; - } - /* 释放资源 */ - static void SampleI2cRelease(struct HdfDeviceObject *device) - { - const struct DeviceResourceNode *childNode = NULL; - - HDF_LOGI("%s: enter", __func__); - - if (device == NULL || device->property == NULL) { - HDF_LOGE("%s: device or property is NULL", __func__); - return; - } - - DEV_RES_NODE_FOR_EACH_CHILD_NODE(device->property, childNode) { - SampleI2cRemoveByNode(childNode); // 调用删除控制器函数 - } - } - ``` - - diff --git "a/zh-cn/device-dev/guide/\345\274\200\345\217\221.md" "b/zh-cn/device-dev/guide/\345\274\200\345\217\221.md" deleted file mode 100755 index 18b3247aef..0000000000 --- "a/zh-cn/device-dev/guide/\345\274\200\345\217\221.md" +++ /dev/null @@ -1,91 +0,0 @@ -# 开发 - -1. 请先完成[《Hi3861快速入门》](../quick-start/Hi3861开发板介绍.md)。 - - LED控制参考示例存放于applications/sample/wifi-iot/app/iothardware/led\_example.c文件中。 - -2. 实现IOT外设控制,首先需要通过查阅原理图明确接线关系。经过查阅,hispark pegasus的LED与芯片的9号管脚相连。 - - ``` - #define LED_TEST_GPIO 9 - ``` - - >![](public_sys-resources/icon-note.gif) **说明:** - >开发板原理图,请开发者联系Hi3861购买渠道客服获取。 - -3. 使用GPIO前,需要完成GPIO管脚初始化,明确管脚用途,并创建任务,使LED周期性亮灭,达到闪烁的效果。 - - ``` - static void LedExampleEntry(void) - { - osThreadAttr_t attr; - - /* 管脚初始化 */ - IoTGpioInit(LED_TEST_GPIO); - /* 配置9号管脚为输出方向 */ - IoTGpioSetDir(LED_TEST_GPIO, IOT_GPIO_DIR_OUT); - - attr.name = "LedTask"; - attr.attr_bits = 0U; - attr.cb_mem = NULL; - attr.cb_size = 0U; - attr.stack_mem = NULL; - attr.stack_size = LED_TASK_STACK_SIZE; - attr.priority = LED_TASK_PRIO; - - /* 启动任务 */ - if (osThreadNew((osThreadFunc_t)LedTask, NULL, &attr) == NULL) { - printf("[LedExample] Falied to create LedTask!\n"); - } - } - ``` - -4. 在循环任务中通过周期性亮灭形式实现LED闪烁。 - - ``` - static void *LedTask(const char *arg) - { - (void)arg; - while (1) { - switch (g_ledState) { - case LED_ON: - IoTGpioSetOutputVal(LED_TEST_GPIO, 1); - usleep(LED_INTERVAL_TIME_US); - break; - case LED_OFF: - IoTGpioSetOutputVal(LED_TEST_GPIO, 0); - usleep(LED_INTERVAL_TIME_US); - break; - case LED_SPARK: - IoTGpioSetOutputVal(LED_TEST_GPIO, 0); - usleep(LED_INTERVAL_TIME_US); - IoTGpioSetOutputVal(LED_TEST_GPIO, 1); - usleep(LED_INTERVAL_TIME_US); - break; - default: - usleep(LED_INTERVAL_TIME_US); - break; - } - } - return NULL; - } - ``` - -5. 在代码最下方,使用OpenHarmony启动恢复模块接口SYS\_RUN\(\)启动业务。(SYS\_RUN定义在ohos\_init.h文件中) - - ``` - SYS_RUN(LedExampleEntry); - ``` - -6. 修改applications/sample/wifi-iot/app/BUILD.gn文件,使led\_example.c参与编译。 - - ``` - import("//build/lite/config/component/lite_component.gni") - lite_component("app") { - features = [ - "iothardware:led_example" - ] - } - ``` - - diff --git "a/zh-cn/device-dev/guide/\345\274\200\345\217\221\345\207\206\345\244\207-8.md" "b/zh-cn/device-dev/guide/\345\274\200\345\217\221\345\207\206\345\244\207-8.md" deleted file mode 100755 index 52eed11deb..0000000000 --- "a/zh-cn/device-dev/guide/\345\274\200\345\217\221\345\207\206\345\244\207-8.md" +++ /dev/null @@ -1,8 +0,0 @@ -# 开发准备 - -- [准备开发环境和创建工程](#section1912530122716) - -## 准备开发环境和创建工程 - -首先需要下载和配置DevEco Studio,具体操作请参考[DevEco Studio 使用指南](../../application-dev/quick-start/DevEco-Studio(OpenHarmony)使用指南.md)。 - diff --git "a/zh-cn/device-dev/guide/\345\274\200\345\217\221\345\207\206\345\244\207.md" "b/zh-cn/device-dev/guide/\345\274\200\345\217\221\345\207\206\345\244\207.md" deleted file mode 100755 index f24d68a539..0000000000 --- "a/zh-cn/device-dev/guide/\345\274\200\345\217\221\345\207\206\345\244\207.md" +++ /dev/null @@ -1,27 +0,0 @@ -# 开发准备 - -- [准备开发环境](#section1912530122716) -- [创建项目](#section1456035192720) - -## 准备开发环境 - -首先需要下载和配置DevEco Studio,具体操作请参考[《DevEco Studio使用指南》](https://developer.harmonyos.com/cn/docs/documentation/doc-guides/software_install-0000001053582415)。 - -## 创建项目 - -1. 通过如下两种方式,打开工程创建向导界面。 - - 如果当前未打开任何工程,可以在DevEco Studio的欢迎页,选择**Create HarmonyOS Project**开始创建一个新工程。 - - 如果已经打开了工程,可以在菜单栏选择**File \> New \> New Project**来创建一个新工程。 - -2. 选择“Smart Vision”下的“Empty Feature Ability”模板。 - - ![](figures/zh-cn_image_0000001082434703.png) - -3. 点击**Next**,进入到工程配置阶段,需要根据向导配置工程的基本信息。 - - **Project Name**:工程的名称,可以自定义。 - - **Package Name**:软件包名称,默认情况下,应用ID也会使用该名称,应用发布时,应用ID需要唯一。 - - **Save Location**:工程文件本地存储路径,存储路径中不能包含中文字符和空格。 - - **Compatible API Version**:兼容的SDK版本。 - -4. 点击**Finish**,工具会自动生成示例代码和相关资源,等待工程创建完成。 - diff --git "a/zh-cn/device-dev/guide/\345\274\200\345\217\221\346\255\245\351\252\244.md" "b/zh-cn/device-dev/guide/\345\274\200\345\217\221\346\255\245\351\252\244.md" deleted file mode 100644 index ae738663fd..0000000000 --- "a/zh-cn/device-dev/guide/\345\274\200\345\217\221\346\255\245\351\252\244.md" +++ /dev/null @@ -1,230 +0,0 @@ -# 开发步骤 - -应用的功能是通过表盘和数字显示实时时间。 - -从第一章节中的[显示效果图](概述-7.md#fig7763172132019)分析可知,页面由两个部分组成: - -- 表盘栏:主要展示一个动态的钟表,且钟表指针能准确转动。 -- 数字时间栏:主要以数字形式显示当前时间。 - -综上,我们可搭建一个纵向两行排列的弹性页面布局来实现界面的功能。具体开发步骤如下: - -1. 在hml文件中添加一个根节点div,注意每个hml文件中有且只能有一个根节点,代码如下: - - ``` -
    -
    - ``` - - class="container"表示组件使用的样式,container是index.css文件中的一个样式类,代码如下: - - ``` - .container { - flex-direction: column; - justify-content: center; - align-items: center; - width: 100%; - height: 100%; - } - ``` - - 在这个样式类中,我们分别设置了根组件div的高度和宽度(注意在应用的开发过程中,除部分组件(text)外必须显式指定组件的高度和宽度,否则可能无法显示)、并将flex-direction属性设置为column,该属性表示div的子组件是垂直方向从上到下排列;这样就可以实现本节开头所说的纵向两行排列的弹性页面布局。 - -2. 实现时钟转动,需要使用“stack”组件。“stack”组件的功能是堆叠容器,子组件按照顺序依次入栈,后一个子组件覆盖前一个子组件。 - - 在根组件下添加一个stack容器,代码片段如下: - - ``` -
    - - - - - - -
    - ``` - - style="transform : rotate\(\{\{ second \* 6 \}\}deg\) 这类代码用来设置组件的旋转事件。其中transform是设置动画平移/旋转/缩放的属性,rotate是旋转动画属性,支持设置x轴和y轴两个维度的选中参数。 - - 在css文件中设置"stack"组件样式的高度、宽度、位置等属性,代码如下: - - ``` - .stack { - flex-direction: column; - justify-content: center; - align-items: center; - width: 100%; - height: 50%; - } - ``` - - 在css文件中设置"clock-bg"组件样式的高度、宽度等属性,代码如下: - - ``` - .clock-bg { - width: 80%; - height: 80%; - object-fit: scale-down; - } - ``` - - 在css文件中设置"clock-hand"组件为时针、分针和秒针的高度、宽度等属性,代码如下: - - ``` - .clock-hand { - width: 25%; - height: 65%; - object-fit: contain; - } - ``` - - index.js中会有一个定时器实时刷新时分秒变量,从而触发时间界面自动更新。对应的js代码如下: - - ``` - export default { - timer: undefined, - //定义参数 - data: { - hour: 0, //定义小时 - minute: 0, //定义分钟 - second: 0 //定义秒 - }, - onInit () { - this.updateTime(); - this.timer = setInterval(this.updateTime, 1000)//设置1s的定时器 - }, - updateTime: function () { - var nowTime = new Date() - this.hour = nowTime.getHours() - this.minute = nowTime.getMinutes() - this.second = nowTime.getSeconds() - if (this.hour < 10) { - this.hour = '0' + this.hour - } - if (this.minute < 10) { - this.minute = '0' + this.minute - } - if (this.second < 10) { - this.second = '0' + this.second - } - }, - } - ``` - -3. 显示数字时间,在钟表下面以数字形式显示当前时间。在根布局内末尾加上text组件,页面结构如下: - - ``` - {{ hour }}:{{ minute }}:{{ second }} - ``` - - class="digit-clock"设置了组件的高度和宽度以及字体大小,其代码如下: - - ``` - .digit-clock { - font-size: 58px; - width: 100%; - margin-top: 0px; - text-align: center; - } - ``` - -4. 所有组件设置样式、动画效果和数据动态绑定,完整代码如下所示: - - - **index.hml文件** - - ``` -
    - - - - - - - {{ hour }}:{{ minute }}:{{ second }} -
    - ``` - - - **index.css文件** - - ``` - .container { - flex-direction: column; - justify-content: center; - align-items: center; - width: 100%; - height: 100%; - } - - .stack { - flex-direction: column; - justify-content: center; - align-items: center; - width: 100%; - height: 50%; - } - - .digit-clock { - font-size: 58px; - width: 100%; - margin-top: 0px; - text-align: center; - } - - .clock-bg { - width: 80%; - height: 80%; - object-fit: scale-down; - } - - .clock-hand { - width: 25%; - height: 65%; - object-fit: contain; - } - ``` - - - **index.js:** - - js文件主要用于实现App应用的逻辑交互。在本页面js文件中,需要实现如下功能:定时获取系统时间。 - - ``` - export default { - timer: undefined, - data: { - hour: 0, - minute: 0, - second: 0 - }, - onInit() { - this.updateTime() - this.timer = setInterval(this.updateTime, 1000) - }, - updateTime: function () { - var nowTime = new Date() - this.hour = nowTime.getHours() - this.minute = nowTime.getMinutes() - this.second = nowTime.getSeconds() - if (this.hour < 10) { - this.hour = '0' + this.hour - } - if (this.minute < 10) { - this.minute = '0' + this.minute - } - if (this.second < 10) { - this.second = '0' + this.second - } - }, - onDestroy() { - clearInterval(this.timer); - } - } - ``` - - diff --git "a/zh-cn/device-dev/guide/\345\274\200\345\217\221\351\246\226\351\241\265.md" "b/zh-cn/device-dev/guide/\345\274\200\345\217\221\351\246\226\351\241\265.md" deleted file mode 100755 index c80d70f94f..0000000000 --- "a/zh-cn/device-dev/guide/\345\274\200\345\217\221\351\246\226\351\241\265.md" +++ /dev/null @@ -1,581 +0,0 @@ -# 开发首页 - -应用首页主要展示城市的空气质量概况。首页总共有两屏(可以根据需求设置多屏),每屏显示一个城市的空气质量信息:主要包括AQI指数、城市名称、污染物指数、更新时间和信息来源等数据。 - -从第一章节中的[显示效果图](概述-6.md#fig18250512195914)分析可知,首页由三部分组成: - -- 标题栏:位于页面正上方,位置固定,包括应用退出按钮和页面标题。 -- 信息栏:主要展示城市的空气信息指标等内容;该页面根据用户需求可设置多屏,且能循环滑动。 -- 页面位置指示器:主要功能是标识当前页面,位置固定在页面底部的中间。 - -综上,我们可搭建一个纵向三行排列的弹性页面布局来实现首页的功能。 - -1. 在hml文件中添加一个根节点div,注意每个hml文件中有且只能有一个根节点,代码如下: - - ``` -
    -
    - ``` - - class="container"表示组件使用的样式,container是index.css文件中的一个样式类,代码如下: - - ``` - .container { - flex-direction: column; - height: 480px; - width: 960px; - } - ``` - - 在这个样式类中,我们分别设置了根组件div的高度和宽度(注意在应用的开发过程中,除部分组件(text)外必须显式指定组件的高度和宽度,否则可能无法显示)、并将flex-direction属性设置为column,该属性表示div的子组件是垂直方向从上到下排列;这样就可以实现本节开头所说的纵向三行排列的弹性页面布局。 - -2. 实现标题栏:标题栏包括一个退出按钮和一个标题,两个控件是横向排列;首先添加一个div,并设置flex-direction的属性为row,表示子组件是水平方向从左往右排列;然后依次添加一个image和text组件,代码如下: - - ``` -
    -
    - - - 空气质量 - -
    -
    - ``` - - 设置组件的高度、边距、颜色等属性。 - - ``` - .header { - width: 960px; - height: 72px; - } - .back { - width: 36px; - height: 36px; - margin-left: 39px; - margin-top: 23px; - } - .title { - width: 296px; - height: 40px; - margin-top: 20px; - margin-left: 21px; - color: #e6e6e6; - } - ``` - - onclick="exitApp" 设置了div组件的click事件,当在标题栏上触发点击事件时,就会执行函数exitApp,该函数位于index.js文件中,代码如下: - - ``` - exitApp() { - console.log('start exit'); - app.terminate(); - console.log('end exit'); - } - ``` - - app.terminate\(\)函数实现了程序退出功能;在使用该函数前,需要引入app模块,在js文件的最上方写如下代码: - - ``` - import app from '@system.app' - ``` - - 代码编写完成后,在模拟器中运行项目,显示效果如下图所示: - - **图 1** 标题栏效果 - ![](figures/标题栏效果.png "标题栏效果") - -3. 实现城市空气质量信息的多屏左右滑动,需要使用“swiper”组件。 - - 在根节点中添加一个子节点swiper,代码片段如下: - - ``` -
    -
    - - - 空气质量 - -
    - - -
    - ``` - - - class="swiper"设置了组件的高度和宽度,代码如下: - - ``` - .swiper { - height: 385px; - width: 960px; - } - ``` - - - - index="\{\{swiperPage\}\}" duration="500" onchange="swiperChange" 这些代码用来设置组件的属性和事件。其中,duration="500" 表示设置swiper的页面滑动的动画时长为500ms。 - - index="\{\{swiperPage\}\}"设置了swiper子组件索引值,\{\{swiperPage\}\}这种写法表示index的值是和js代码中的swiperPage变量动态绑定的,index的值会随着swiperPage变动而改变。 - - onchange="swiperChange" 设置了swiper组件的change事件和函数swiperChange绑定,对应的js代码如下: - - ``` - //引入router模块,用户页面跳转 - import router from'@system.router' - import app from '@system.app' - - export default { - //定义参数 - data: { - //默认是第一页 - swiperPage: 0 - }, - onInit () { - }, - exitApp(){ - console.log('start exit'); - app.terminate(); - console.log('end exit'); - }, - //swiper滑动回调事件,保存当前swiper的index值,每次滑动都会将index值保存在swiperPage变量中 - swiperChange (e) { - this.swiperPage = e.index; - } - } - ``` - - -4. 设置一个城市的空气质量信息为一屏,在一屏内,要展示多种信息,分别使用不同的控件进行展示。 - - 在swiper中添加两个子组件stack(绝对布局),每个stack组件内分别添加text、image、progress等组件来显示对应的信息 ,页面结构如下: - - ``` - - - - ------空气质量 - ------城市名称 - -----进度条 - -------云朵图片 - --------AQI数值 - AQI------AQI -
    --------空气指标详细信息 -
    -
    --------更新时间和网站等信息 -
    -
    - - - - - - - - -
    -
    -
    - ``` - - 代码编写完成后,模拟器运行效果如下: - - **图 2** 标题栏和信息栏效果 - ![](figures/标题栏和信息栏效果.png "标题栏和信息栏效果") - -5. 添加页面位置指示器:由于当前swiper不支持设置indicator,需要开发者自己来实现该效果。在根节点中添加一个子组件div,并设置相应样式;然后在该div中添加两个子组件div,设置两个div的border-radius,并在swiper滑动事件中动态改变对应div的背景色来实现该效果。 - - ``` -
    -
    -
    -
    - ``` - - **图 3** 页面位置指示器效果图 - ![](figures/页面位置指示器效果图.png "页面位置指示器效果图") - -6. 所有组件设置样式、动画效果和数据动态绑定,完整代码如下所示: - - - **index.hml文件** - - ``` -
    -
    - - - 空气质量 - -
    - - - {{airData[0].airQuality}} - - {{airData[0].location}} - - - - {{airData[0].detailData}} - - - AQI - -
    -
    - - CO - - - 100 - -
    -
    - - NO2 - - - 90 - -
    -
    - - PM10 - - - 120 - -
    -
    - - PM2.5 - - - 40 - -
    -
    - - SO2 - - - 150 - -
    - -
    - -
    - - {{airData[1].airQuality}} - - {{airData[1].location}} - - - - {{airData[1].detailData}} - - - AQI - -
    -
    - - CO - - - 10 - -
    -
    - - NO2 - - - 50 - -
    -
    - - PM10 - - - 60 - -
    -
    - - PM2.5 - - - 40 - -
    -
    - - SO2 - - - 150 - -
    - -
    - -
    -
    -
    -
    -
    -
    -
    - ``` - - - **index.css文件** - - css文件中定义了许多class,每个class用于定义组件的位置、大小、字体、颜色、背景色等信息。同时,每一个子组件都叠加在父组件中,父组件的样式会影响子组件的呈现。 - - ``` - .aqi-value { - text-align: center; - font-size: 65px; - color: #f0ffff; - width: 156px; - height: 92px; - top: 134px; - left: 210px; - } - .aqi { - text-align: center; - color: #a2c4a2; - width: 156px; - height: 45px; - top: 90px; - left: 210px; - } - .airquality { - top: 222px; - text-align: center; - width: 156px; - height: 45px; - left: 210px; - } - .image { - top: 285px; - left: 274px; - width: 32px; - height: 32px; - } - .location-text { - text-align: center; - color: #ffffff; - width: 200px; - height: 52px; - font-size: 40px; - left: 380px; - top: 16px; - } - .container { - flex-direction: column; - height: 480px; - width: 960px; - } - .circle-progress { - center-x: 128px; - center-y: 128px; - radius: 128px; - startAngle: 198; - totalAngle: 320; - strokeWidth: 24px; - width: 256px; - height: 256px; - left: 160px; - top: 58px; - } - .detail { - width: 256px; - height: 265px; - left: 544px; - top: 58px; - flex-direction: column; - } - .text-wrapper { - width: 256px; - height: 35px; - margin-top: 6px; - } - .gas-name { - width: 128px; - height: 35px; - text-align: left; - } - .gas-value { - width: 128px; - height: 35px; - text-align: right; - } - .btn { - width: 180px; - height: 50px; - margin-top: 6px; - margin-left: 38px; - background-color: #1a1a1a; - color: #1085CE; - } - .footer { - top: 326px; - width: 960px; - height: 28px; - } - .header { - width: 960px; - height: 72px; - } - .back { - width: 36px; - height: 36px; - margin-left: 39px; - margin-top: 23px; - } - .title { - width: 296px; - height: 40px; - margin-top: 20px; - margin-left: 21px; - color: #e6e6e6; - } - .swiper { - height: 385px; - width: 960px; - } - .images { - width: 60px; - height: 15px; - margin-left: 450px; - } - .update-time { - width: 480px; - height: 28px; - font-size: 20px; - color: #A9A9A9; - text-align: right; - } - .info-source { - width: 450px; - height: 28px; - font-size: 20px; - color: #A9A9A9; - text-align: left; - margin-left: 24px; - } - .circle-div { - width: 12px; - height: 12px; - border-radius: 6px; - } - ``` - - - **index.js:** - - js文件主要用于实现App应用的逻辑交互。在本页面js文件中,需要实现如下功能:根据数值动态改变文字、进度条颜色、页面跳转。 - - ``` - //导入router和app模块 - import router from '@system.router' - import app from '@system.app' - - export default { - data: { - //页面绑定数据 - textColor1: '#00ff00', - textColor2: '#00ff00', - bgColor1: '#669966', - bgColor2: '#669966', - swiperPage: 0, - percent1: 40, - percent2: 90, - iconUncheckedColor: '#262626', - iconcheckedColor: '#ffffff', - iconcheckedBR: '6px', - src1: 'common/cloud_green.png', - src2: 'common/cloud_green.png', - airData: [{ - location: '东莞', - airQuality: '良', - detailData: 40 - }, { - location: '深圳', - airQuality: '差', - detailData: 90 - }] - }, - onInit () { - //根据数值的不同,设置不同的字体、背景颜色和图片 - if(this.airData[0].detailData > 100){ - this.src1 = 'common/cloud_red.png'; - this.textColor1 = '#ff0000'; - this.bgColor1 = '#9d7462'; - } else if(50 < this.airData[0].detailData && this.airData[0].detailData <= 100){ - this.src1 = 'common/cloud_yellow.png'; - this.textColor1 = '#ecf19a'; - this.bgColor1 = '#9d9d62'; - } - if(this.airData[1].detailData > 100){ - this.src2 = 'common/cloud_red.png'; - this.textColor2 = '#ff0000'; - this.bgColor2 = '#9d7462'; - } else if(50 < this.airData[1].detailData && this.airData[1].detailData <= 100){ - this.src2 = 'common/cloud_yellow.png'; - this.textColor2 = '#ecf19a'; - this.bgColor2 = '#9d9d62'; - } - if(this.selectedCityIndex){ - this.swiperPage = this.selectedCityIndex; - if(this.swiperPage == 0){ - this.iconcheckedColor = '#ffffff'; - this.iconUncheckedColor = '#262626'; - }else{ - this.iconcheckedColor = '#262626'; - this.iconUncheckedColor = '#ffffff'; - } - } - }, - //跳转到详情页面 - openDetail () { - router.replace({ - uri: 'pages/detail/detail', - params: {selectedCityIndex:this.swiperPage} - }); - }, - //退出应用 - exitApp(){ - console.log('start exit'); - app.terminate(); - console.log('end exit'); - }, - //页面滑动事件,滑动时改变最新的标识 - swiperChange (e) { - this.swiperPage = e.index; - if(e.index == 0){ - this.iconcheckedColor = '#ffffff'; - this.iconUncheckedColor = '#262626'; - }else{ - this.iconcheckedColor = '#262626'; - this.iconUncheckedColor = '#ffffff'; - } - } - } - ``` - - diff --git "a/zh-cn/device-dev/guide/\345\274\200\346\234\272\346\227\245\345\277\227\345\210\206\346\236\220.md" "b/zh-cn/device-dev/guide/\345\274\200\346\234\272\346\227\245\345\277\227\345\210\206\346\236\220.md" deleted file mode 100644 index 469d6a3566..0000000000 --- "a/zh-cn/device-dev/guide/\345\274\200\346\234\272\346\227\245\345\277\227\345\210\206\346\236\220.md" +++ /dev/null @@ -1,19 +0,0 @@ -# 开机日志分析 - -如下所示为开机启动日志部分截取 - -``` -[I/HDF_INPUT_DRV] HdfInputManagerInit: enter // 管理驱动层初始化 -[I/HDF_INPUT_DRV] HdfInputManagerInit: exit succ // 初始化成功 -[I/osal_cdev] add cdev hdf_input_host success -[I/HDF_LOG_TAG] HdfTouchDriverProbe: enter // 公共驱动层初始化 -[I/HDF_LOG_TAG] HdfTouchDriverProbe: main_touch exit succ // 初始化成功 -[I/osal_cdev] add cdev hdf_input_event1 success -[I/HDF_INPUT_DRV] HdfGoodixChipInit: enter // 器件驱动层初始化 -[I/HDF_INPUT_DRV] ChipDetect: IC FW version is 0x1060 -[I/HDF_INPUT_DRV] Product_ID: 911_1060, x_sol = 960, y_sol = 480 -[I/HDF_LOG_TAG] ChipDriverInit: chipDetect succ, ret = 0 -[I/HDF_LOG_TAG] InputDeviceInstance: inputDev->devName = main_touch -[I/HDF_INPUT_DRV] HdfGoodixChipInit: exit succ, chipName = gt911 // 初始化成功 -``` - diff --git "a/zh-cn/device-dev/guide/\346\213\215\347\205\247\345\274\200\345\217\221\346\214\207\345\257\274-3.md" "b/zh-cn/device-dev/guide/\346\213\215\347\205\247\345\274\200\345\217\221\346\214\207\345\257\274-3.md" deleted file mode 100755 index 83e445c0ed..0000000000 --- "a/zh-cn/device-dev/guide/\346\213\215\347\205\247\345\274\200\345\217\221\346\214\207\345\257\274-3.md" +++ /dev/null @@ -1,395 +0,0 @@ -# 拍照开发指导 - -- [使用场景](#zh-cn_topic_0000001052170554_section1963312376119) -- [接口说明](#zh-cn_topic_0000001052170554_section56549532016) -- [约束与限制](#zh-cn_topic_0000001052170554_section1165911177314) -- [开发步骤](#zh-cn_topic_0000001052170554_section138543918214) - -## 使用场景 - -使用Camera产生图片帧(拍照)。 - -## 接口说明 - -**表 1** API列表 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    类名

    -

    接口名

    -

    描述

    -

    CameraKit

    -

    int32_t GetCameraIds(std::list<string> cameraList)

    -

    获取cameraId列表

    -

    CameraKit

    -

    CameraAbility& GetCameraAbility(string cameraId)

    -

    获取指定camera的能力

    -

    CameraKit

    -

    void RegisterCameraDeviceCallback(CameraDeviceCallback* callback, EventHandler* handler)

    -

    注册camera设备状态回调

    -

    CameraKit

    -

    void UnregisterCameraDeviceCallback(CameraDeviceCallback* callback)

    -

    去注册camera设备状态回调

    -

    CameraKit

    -

    void CreateCamera(string cameraId, CameraStateCallback* callback, EventHandler* handler)

    -

    创建camera实例

    -

    Camera

    -

    string GetCameraId()

    -

    获取cameraID

    -

    Camera

    -

    CameraConfig& GetCameraConfig()

    -

    获取camera配置信息

    -

    Camera

    -

    FrameConfig& GetFrameConfig(int32_t type)

    -

    获取捕获帧类型

    -

    Camera

    -

    void Configure(CameraConfig& config)

    -

    配置camera

    -

    Camera

    -

    void Release()

    -

    释放camera

    -

    Camera

    -

    int TriggerLoopingCapture(FrameConfig& frameConfig)

    -

    开始循环帧捕获

    -

    Camera

    -

    void StopLoopingCapture()

    -

    停止循环帧捕获

    -

    Camera

    -

    int32_t TriggerSingleCapture(FrameConfig& frameConfig)

    -

    抓图

    -

    CameraConfig

    -

    void SetFrameStateCallback(FrameStateCallback* callback, EventHandler* handler);

    -

    设置帧状态回调

    -

    CameraConfig

    -

    static CameraConfig* CreateCameraConfig()

    -

    创建camera配置信息实例

    -

    CameraAbility

    -

    std::list<Size> GetSupportedSizes(int format)

    -

    根据类型获取支持输出图像尺寸大小

    -

    CameraAbility

    -

    std::list<T> GetParameterRange(uint32_t key)

    -

    获取支持的参数范围

    -

    CameraDevice

    -

    CameraDeviceCallback()

    -

    camera设备回调类构造函数

    -

    CameraDevice

    -

    void OnCameraStatus​(std::string cameraId, int32_t status)

    -

    camera设备状态变化时的回调

    -

    CameraStateCallback

    -

    CameraStateCallback​()

    -

    camera状态回调类构造函数

    -

    CameraStateCallback

    -

    void OnConfigured​(Camera& camera)

    -

    camera配置成功回调

    -

    CameraStateCallback

    -

    void OnConfigureFailed​(Camera& camera,int32_t errorCode)

    -

    camera配置失败回调

    -

    CameraStateCallback

    -

    void OnCreated​(Camera& camera)

    -

    camera创建成功回调

    -

    CameraStateCallback

    -

    void OnCreateFailed​(std::string cameraId,int32_t errorCode)

    -

    camera创建失败回调

    -

    CameraStateCallback

    -

    void OnReleased​(Camera& camera)

    -

    camera释放回调

    -

    FrameStateCallback

    -

    FrameStateCallback​()

    -

    帧状态回调类构造函数

    -

    FrameStateCallback

    -

    void OnFrameFinished(Camera& camera, FrameConfig& frameConfig, FrameResult& frameResult)

    -

    拍照帧完成回调

    -

    FrameStateCallback

    -

    void OnFrameError​(Camera& camera, FrameConfig& frameConfig, int32_t errorCode, FrameResult& frameResult)

    -

    拍照帧异常回调

    -

    FrameConfig

    -

    int32_t GetFrameConfigType()

    -

    获取帧配置类型

    -

    FrameConfig

    -

    std::list<OHOS::Surface> GetSurfaces()

    -

    获取帧配置的surface

    -

    FrameConfig

    -

    void AddSurface(OHOS::AGP::UISurface& surface);

    -

    添加surface

    -

    FrameConfig

    -

    void RemoveSurface(OHOS::AGP::UISurface& surface);

    -

    删除surface

    -
    - -## 约束与限制 - -无。 - -## 开发步骤 - -1. 实现设备状态回调的派生类,用户在设备状态发生变更(如新插入相机设备/相机掉线)时,自定义操作。 - - ``` - class SampleCameraDeviceCallback : public CameraDeviceCallback { - void OnCameraStatus(std::string cameraId, int32_t status) override - { - //do something when camera is available/unavailable - } - }; - ``` - -2. 实现帧事件回调的派生类,这里在拿到帧数据以后将其转存为文件。 - - ``` - static void SampleSaveCapture(const char *p, uint32_t size) - { - cout << "Start saving picture" << endl; - struct timeval tv; - gettimeofday(&tv, NULL); - struct tm *ltm = localtime(&tv.tv_sec); - if (ltm != nullptr) { - ostringstream ss("Capture_"); - ss << "Capture" << ltm->tm_hour << "-" << ltm->tm_min << "-" << ltm->tm_sec << ".jpg"; - - ofstream pic("/sdcard/" + ss.str(), ofstream::out | ofstream::trunc); - cout << "write " << size << " bytes" << endl; - pic.write(p, size); - cout << "Saving picture end" << endl; - } - } - - class TestFrameStateCallback : public FrameStateCallback { - void OnFrameFinished(Camera &camera, FrameConfig &fc, FrameResult &result) override - { - cout << "Receive frame complete inform." << endl; - if (fc.GetFrameConfigType() == FRAME_CONFIG_CAPTURE) { - cout << "Capture frame received." << endl; - list surfaceList = fc.GetSurfaces(); - for (Surface *surface : surfaceList) { - SurfaceBuffer *buffer = surface->AcquireBuffer(); - if (buffer != nullptr) { - char *virtAddr = static_cast(buffer->GetVirAddr()); - if (virtAddr != nullptr) { - SampleSaveCapture(virtAddr, buffer->GetSize()); - } - surface->ReleaseBuffer(buffer); - } - delete surface; - } - delete &fc; - } - } - }; - ``` - -3. 实现相机状态回调的派生类,当相机状态发生变化(配置成功/失败,创建成功/失败\)时,自定义操作。 - - ``` - class SampleCameraStateMng : public CameraStateCallback { - public: - SampleCameraStateMng() = delete; - SampleCameraStateMng(EventHandler &eventHdlr) : eventHdlr_(eventHdlr) {} - ~SampleCameraStateMng() - { - if (recordFd_ != -1) { - close(recordFd_); - } - } - void OnCreated(Camera &c) override - { - cout << "Sample recv OnCreate camera." << endl; - auto config = CameraConfig::CreateCameraConfig(); - config->SetFrameStateCallback(&fsCb_, &eventHdlr_); - c.Configure(*config); - cam_ = &c; - } - void OnCreateFailed(const std::string cameraId, int32_t errorCode) override {} - void OnReleased(Camera &c) override {} - }; - ``` - -4. 创建CameraKit,用于创建和获取camera信息。 - - ``` - CameraKit *camKit = CameraKit::GetInstance(); - list camList = camKit->GetCameraIds(); - string camId; - for (auto &cam : camList) { - cout << "camera name:" << cam << endl; - const CameraAbility *ability = camKit->GetCameraAbility(cam); - /* find camera which fits user's ability */ - list sizeList = ability->GetSupportedSizes(0); - if (find(sizeList.begin(), sizeList.end(), CAM_PIC_1080P) != sizeList.end()) { - camId = cam; - break; - } - } - ``` - -5. 创建Camera实例。 - - ``` - EventHandler eventHdlr; // Create a thread to handle callback events - SampleCameraStateMng CamStateMng(eventHdlr); - - 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需要设计同步机制。 - - ``` - void OnCreated(Camera &c) override - { - cout << "Sample recv OnCreate camera." << endl; - auto config = CameraConfig::CreateCameraConfig(); - config->SetFrameStateCallback(&fsCb_, &eventHdlr_); - c.Configure(*config); - cam_ = &c; - } - - void Capture() - { - if (cam_ == nullptr) { - cout << "Camera is not ready." << endl; - return; - } - FrameConfig *fc = new FrameConfig(FRAME_CONFIG_CAPTURE); - Surface *surface = Surface::CreateSurface(); - if (surface == nullptr) { - delete fc; - } - surface->SetWidthAndHeight(1920, 1080); /* 1920:width,1080:height */ - fc->AddSurface(*surface); - cam_->TriggerSingleCapture(*fc); - } - ``` - - diff --git "a/zh-cn/device-dev/guide/\346\213\215\347\205\247\345\274\200\345\217\221\346\214\207\345\257\274.md" "b/zh-cn/device-dev/guide/\346\213\215\347\205\247\345\274\200\345\217\221\346\214\207\345\257\274.md" deleted file mode 100755 index e59c365a5c..0000000000 --- "a/zh-cn/device-dev/guide/\346\213\215\347\205\247\345\274\200\345\217\221\346\214\207\345\257\274.md" +++ /dev/null @@ -1,395 +0,0 @@ -# 拍照开发指导 - -- [使用场景](#zh-cn_topic_0000001052170554_section1963312376119) -- [接口说明](#zh-cn_topic_0000001052170554_section56549532016) -- [约束与限制](#zh-cn_topic_0000001052170554_section1165911177314) -- [开发步骤](#zh-cn_topic_0000001052170554_section138543918214) - -## 使用场景 - -使用Camera产生图片帧(拍照)。 - -## 接口说明 - -**表 1** API列表 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    类名

    -

    接口名

    -

    描述

    -

    CameraKit

    -

    int32_t GetCameraIds(std::list<string> cameraList)

    -

    获取cameraId列表

    -

    CameraKit

    -

    CameraAbility& GetCameraAbility(string cameraId)

    -

    获取指定camera的能力

    -

    CameraKit

    -

    void RegisterCameraDeviceCallback(CameraDeviceCallback* callback, EventHandler* handler)

    -

    注册camera设备状态回调

    -

    CameraKit

    -

    void UnregisterCameraDeviceCallback(CameraDeviceCallback* callback)

    -

    去注册camera设备状态回调

    -

    CameraKit

    -

    void CreateCamera(string cameraId, CameraStateCallback* callback, EventHandler* handler)

    -

    创建camera实例

    -

    Camera

    -

    string GetCameraId()

    -

    获取cameraID

    -

    Camera

    -

    CameraConfig& GetCameraConfig()

    -

    获取camera配置信息

    -

    Camera

    -

    FrameConfig& GetFrameConfig(int32_t type)

    -

    获取捕获帧类型

    -

    Camera

    -

    void Configure(CameraConfig& config)

    -

    配置camera

    -

    Camera

    -

    void Release()

    -

    释放camera

    -

    Camera

    -

    int TriggerLoopingCapture(FrameConfig& frameConfig)

    -

    开始循环帧捕获

    -

    Camera

    -

    void StopLoopingCapture()

    -

    停止循环帧捕获

    -

    Camera

    -

    int32_t TriggerSingleCapture(FrameConfig& frameConfig)

    -

    抓图

    -

    CameraConfig

    -

    void SetFrameStateCallback(FrameStateCallback* callback, EventHandler* handler);

    -

    设置帧状态回调

    -

    CameraConfig

    -

    static CameraConfig* CreateCameraConfig()

    -

    创建camera配置信息实例

    -

    CameraAbility

    -

    std::list<Size> GetSupportedSizes(int format)

    -

    根据类型获取支持输出图像尺寸大小

    -

    CameraAbility

    -

    std::list<T> GetParameterRange(uint32_t key)

    -

    获取支持的参数范围

    -

    CameraDevice

    -

    CameraDeviceCallback()

    -

    camera设备回调类构造函数

    -

    CameraDevice

    -

    void OnCameraStatus​(std::string cameraId, int32_t status)

    -

    camera设备状态变化时的回调

    -

    CameraStateCallback

    -

    CameraStateCallback​()

    -

    camera状态回调类构造函数

    -

    CameraStateCallback

    -

    void OnConfigured​(Camera& camera)

    -

    camera配置成功回调

    -

    CameraStateCallback

    -

    void OnConfigureFailed​(Camera& camera,int32_t errorCode)

    -

    camera配置失败回调

    -

    CameraStateCallback

    -

    void OnCreated​(Camera& camera)

    -

    camera创建成功回调

    -

    CameraStateCallback

    -

    void OnCreateFailed​(std::string cameraId,int32_t errorCode)

    -

    camera创建失败回调

    -

    CameraStateCallback

    -

    void OnReleased​(Camera& camera)

    -

    camera释放回调

    -

    FrameStateCallback

    -

    FrameStateCallback​()

    -

    帧状态回调类构造函数

    -

    FrameStateCallback

    -

    void OnFrameFinished(Camera& camera, FrameConfig& frameConfig, FrameResult& frameResult)

    -

    拍照帧完成回调

    -

    FrameStateCallback

    -

    void OnFrameError​(Camera& camera, FrameConfig& frameConfig, int32_t errorCode, FrameResult& frameResult)

    -

    拍照帧异常回调

    -

    FrameConfig

    -

    int32_t GetFrameConfigType()

    -

    获取帧配置类型

    -

    FrameConfig

    -

    std::list<OHOS::Surface> GetSurfaces()

    -

    获取帧配置的surface

    -

    FrameConfig

    -

    void AddSurface(OHOS::AGP::UISurface& surface);

    -

    添加surface

    -

    FrameConfig

    -

    void RemoveSurface(OHOS::AGP::UISurface& surface);

    -

    删除surface

    -
    - -## 约束与限制 - -无。 - -## 开发步骤 - -1. 实现设备状态回调的派生类,用户在设备状态发生变更(如新插入相机设备/相机掉线)时,自定义操作。 - - ``` - class SampleCameraDeviceCallback : public CameraDeviceCallback { - void OnCameraStatus(std::string cameraId, int32_t status) override - { - //do something when camera is available/unavailable - } - }; - ``` - -2. 实现帧事件回调的派生类,这里在拿到帧数据以后将其转存为文件。 - - ``` - static void SampleSaveCapture(const char *p, uint32_t size) - { - cout << "Start saving picture" << endl; - struct timeval tv; - gettimeofday(&tv, NULL); - struct tm *ltm = localtime(&tv.tv_sec); - if (ltm != nullptr) { - ostringstream ss("Capture_"); - ss << "Capture" << ltm->tm_hour << "-" << ltm->tm_min << "-" << ltm->tm_sec << ".jpg"; - - ofstream pic("/sdcard/" + ss.str(), ofstream::out | ofstream::trunc); - cout << "write " << size << " bytes" << endl; - pic.write(p, size); - cout << "Saving picture end" << endl; - } - } - - class TestFrameStateCallback : public FrameStateCallback { - void OnFrameFinished(Camera &camera, FrameConfig &fc, FrameResult &result) override - { - cout << "Receive frame complete inform." << endl; - if (fc.GetFrameConfigType() == FRAME_CONFIG_CAPTURE) { - cout << "Capture frame received." << endl; - list surfaceList = fc.GetSurfaces(); - for (Surface *surface : surfaceList) { - SurfaceBuffer *buffer = surface->AcquireBuffer(); - if (buffer != nullptr) { - char *virtAddr = static_cast(buffer->GetVirAddr()); - if (virtAddr != nullptr) { - SampleSaveCapture(virtAddr, buffer->GetSize()); - } - surface->ReleaseBuffer(buffer); - } - delete surface; - } - delete &fc; - } - } - }; - ``` - -3. 实现相机状态回调的派生类,当相机状态发生变化(配置成功/失败,创建成功/失败\)时,自定义操作。 - - ``` - class SampleCameraStateMng : public CameraStateCallback { - public: - SampleCameraStateMng() = delete; - SampleCameraStateMng(EventHandler &eventHdlr) : eventHdlr_(eventHdlr) {} - ~SampleCameraStateMng() - { - if (recordFd_ != -1) { - close(recordFd_); - } - } - void OnCreated(Camera &c) override - { - cout << "Sample recv OnCreate camera." << endl; - auto config = CameraConfig::CreateCameraConfig(); - config->SetFrameStateCallback(&fsCb_, &eventHdlr_); - c.Configure(*config); - cam_ = &c; - } - void OnCreateFailed(const std::string cameraId, int32_t errorCode) override {} - void OnReleased(Camera &c) override {} - }; - ``` - -4. 创建CameraKit,用于创建和获取camera信息。 - - ``` - CameraKit *camKit = CameraKit::GetInstance(); - list camList = camKit->GetCameraIds(); - string camId; - for (auto &cam : camList) { - cout << "camera name:" << cam << endl; - const CameraAbility *ability = camKit->GetCameraAbility(cam); - /* find camera which fits user's ability */ - list sizeList = ability->GetSupportedSizes(0); - if (find(sizeList.begin(), sizeList.end(), CAM_PIC_1080P) != sizeList.end()) { - camId = cam; - break; - } - } - ``` - -5. 创建Camera实例。 - - ``` - EventHandler eventHdlr; // Create a thread to handle callback events - SampleCameraStateMng CamStateMng(eventHdlr); - - 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需要设计同步机制。 - - ``` - void OnCreated(Camera &c) override - { - cout << "Sample recv OnCreate camera." << endl; - auto config = CameraConfig::CreateCameraConfig(); - config->SetFrameStateCallback(&fsCb_, &eventHdlr_); - c.Configure(*config); - cam_ = &c; - } - - void Capture() - { - if (cam_ == nullptr) { - cout << "Camera is not ready." << endl; - return; - } - FrameConfig *fc = new FrameConfig(FRAME_CONFIG_CAPTURE); - Surface *surface = Surface::CreateSurface(); - if (surface == nullptr) { - delete fc; - } - surface->SetWidthAndHeight(1920, 1080); /* 1920:width,1080:height */ - fc->AddSurface(*surface); - cam_->TriggerSingleCapture(*fc); - } - ``` - - diff --git "a/zh-cn/device-dev/guide/\346\221\204\345\203\217\345\244\264\346\216\247\345\210\266.md" "b/zh-cn/device-dev/guide/\346\221\204\345\203\217\345\244\264\346\216\247\345\210\266.md" deleted file mode 100755 index 65f7df7980..0000000000 --- "a/zh-cn/device-dev/guide/\346\221\204\345\203\217\345\244\264\346\216\247\345\210\266.md" +++ /dev/null @@ -1,9 +0,0 @@ -# 摄像头控制 - -- **[概述](概述-0.md)** - -- **[示例开发](示例开发.md)** - -- **[应用实例](应用实例.md)** - - diff --git "a/zh-cn/device-dev/guide/\346\227\240\345\261\217\346\221\204\345\203\217\345\244\264\347\261\273\344\272\247\345\223\201.md" "b/zh-cn/device-dev/guide/\346\227\240\345\261\217\346\221\204\345\203\217\345\244\264\347\261\273\344\272\247\345\223\201.md" deleted file mode 100755 index 7d723b1bfd..0000000000 --- "a/zh-cn/device-dev/guide/\346\227\240\345\261\217\346\221\204\345\203\217\345\244\264\347\261\273\344\272\247\345\223\201.md" +++ /dev/null @@ -1,5 +0,0 @@ -# 无屏摄像头类产品 - -- **[摄像头控制](摄像头控制.md)** - - diff --git "a/zh-cn/device-dev/guide/\346\227\266\351\222\237\345\272\224\347\224\250\345\274\200\345\217\221\347\244\272\344\276\213.md" "b/zh-cn/device-dev/guide/\346\227\266\351\222\237\345\272\224\347\224\250\345\274\200\345\217\221\347\244\272\344\276\213.md" deleted file mode 100644 index 3cbff6960f..0000000000 --- "a/zh-cn/device-dev/guide/\346\227\266\351\222\237\345\272\224\347\224\250\345\274\200\345\217\221\347\244\272\344\276\213.md" +++ /dev/null @@ -1,15 +0,0 @@ -# 时钟应用开发示例 - -- **[概述](概述-7.md)** - -- **[开发准备](开发准备-8.md)** - -- **[开发步骤](开发步骤.md)** - -- **[签名打包](签名打包.md)** - -- **[真机运行](真机运行-9.md)** - -- **[常见问题](常见问题-10.md)** - - diff --git "a/zh-cn/device-dev/guide/\346\246\202\350\277\260-0.md" "b/zh-cn/device-dev/guide/\346\246\202\350\277\260-0.md" deleted file mode 100755 index e3d5da250e..0000000000 --- "a/zh-cn/device-dev/guide/\346\246\202\350\277\260-0.md" +++ /dev/null @@ -1,10 +0,0 @@ -# 概述 - -本文档将介绍如何基于IoT Camera开发板,利用开发套件中自带的摄像头,完成拍照、录像功能。 - -开发者可通过执行示例应用,对开发板的外设控制有了更深入了解后,可使用开发板完成摄像头等设备。 - -若开发者想先查看示例效果,请进入[应用实例](应用实例.md)。如需自定义应用行为,可参考下节“示例开发”对示例代码进行修改。 - -相机开发基本概念可参考:[相机开发概述](../subsystems/相机开发概述.md)。 - diff --git "a/zh-cn/device-dev/guide/\346\246\202\350\277\260-1.md" "b/zh-cn/device-dev/guide/\346\246\202\350\277\260-1.md" deleted file mode 100755 index f265cdb276..0000000000 --- "a/zh-cn/device-dev/guide/\346\246\202\350\277\260-1.md" +++ /dev/null @@ -1,10 +0,0 @@ -# 概述 - -本文档将介绍如何基于IoT Camera开发板(Hi3516DV300),利用其摄像头和屏幕,完成拍照、录像和视频预览功能。 - -通过本文档,开发者能够对OpenHarmony的摄像控制有更深入的了解,可参照本例尝试完成“智能猫眼”、“智能后视镜”、“智能带屏音箱”等设备的开发。 - -若开发者想先查看示例效果,请进入[应用实例](应用实例-5.md)。如需自定义应用行为,可参考下节“示例开发”对示例代码进行修改。 - -相机应用开发的基本概念请参考:[相机开发概述](../subsystems/相机开发概述.md)。 - diff --git "a/zh-cn/device-dev/guide/\346\246\202\350\277\260-10.md" "b/zh-cn/device-dev/guide/\346\246\202\350\277\260-10.md" deleted file mode 100644 index 16734e3f17..0000000000 --- "a/zh-cn/device-dev/guide/\346\246\202\350\277\260-10.md" +++ /dev/null @@ -1,26 +0,0 @@ -# 概述 - -- [场景介绍](#section191543223549) - -本文档将以I2C驱动为例,介绍如何基于HDF驱动框架完成平台驱动开发。 - ->![](public_sys-resources/icon-caution.gif) **注意:** ->本例仅作为平台驱动开发示例参考,开发者不可直接用于商用集成。 - -## 场景介绍 - -HDF驱动框架为常用外围设备提供了标准的驱动框架,驱动开发者只需将驱动适配至HDF驱动框架,即可通过HDF驱动框架提供的接口操作外围设备。 - -本文以I2C为例。其时序流程如[图1](#fig148041484161)所示。 - -**图 1** I2C时序流程图 - - -![](figures/zh-cn_image_0000001161922745.png) - -- User Business:用户业务驱动。 -- i2cManagerEntry:I2C管理器入口,注册I2cManager到HDF驱动框架。 -- I2cManager:I2C管理器,管理I2C控制器。 -- I2cCntlr:I2C控制器。 -- i2cDriverEntry:I2C控制器入口,注册I2cCntlr到HDF驱动框架。 - diff --git "a/zh-cn/device-dev/guide/\346\246\202\350\277\260-12.md" "b/zh-cn/device-dev/guide/\346\246\202\350\277\260-12.md" deleted file mode 100644 index 0606b801b5..0000000000 --- "a/zh-cn/device-dev/guide/\346\246\202\350\277\260-12.md" +++ /dev/null @@ -1,9 +0,0 @@ -# 概述 - -本文档将介绍如何基于Hi3516DV300开发板完成基于HDF\_Input模型的触摸屏器件驱动开发,从而使开发者快速入门,进行基于的外设驱动开发。 - -- **[硬件资源介绍](硬件资源介绍.md)** - -- **[Input模型简介](Input模型简介.md)** - - diff --git "a/zh-cn/device-dev/guide/\346\246\202\350\277\260-6.md" "b/zh-cn/device-dev/guide/\346\246\202\350\277\260-6.md" deleted file mode 100755 index 7f8de10aa7..0000000000 --- "a/zh-cn/device-dev/guide/\346\246\202\350\277\260-6.md" +++ /dev/null @@ -1,15 +0,0 @@ -# 概述 - -- [效果展示](#section3997224182313) - -本文将介绍如何快速搭建基于OpenHarmony系统的行车记录仪(Hi3516DV300开发板)应用开发环境,并基于一个简易的APP示例逐步展示应用的创建、开发、调试和安装等流程。接下来本文以空气质量监测(AirQuality)App为例进行说明。 - -## 效果展示 - -空气质量监测App是一款展示城市空气质量信息的应用,有两个页面组成:首页和详情页,在DevEco Studio模拟器中的显示效果如下图所示: - -**图 1** 空气质量监测 App显示效果图 - - -![](figures/Video_2020-07-25_173141.gif) - diff --git "a/zh-cn/device-dev/guide/\346\246\202\350\277\260-7.md" "b/zh-cn/device-dev/guide/\346\246\202\350\277\260-7.md" deleted file mode 100755 index e032aa00bc..0000000000 --- "a/zh-cn/device-dev/guide/\346\246\202\350\277\260-7.md" +++ /dev/null @@ -1,15 +0,0 @@ -# 概述 - -- [效果展示](#section3997224182313) - -本文将介绍如何快速搭建基于OpenHarmony标准系统(Hi3516DV300开发板)的应用开发环境,并基于一个时钟APP示例逐步展示应用的创建、开发、调试和安装等流程。示例代码可以通过[本链接](https://gitee.com/openharmony/app_samples/tree/master/common/Clock)获取。 - -## 效果展示 - -时钟App是一款显示实时时间的应用,显示效果如下图所示: - -**图 1** 时钟应用显示效果图 - - -![](figures/Clock.png) - diff --git "a/zh-cn/device-dev/guide/\346\246\202\350\277\260.md" "b/zh-cn/device-dev/guide/\346\246\202\350\277\260.md" deleted file mode 100755 index 875da92ed1..0000000000 --- "a/zh-cn/device-dev/guide/\346\246\202\350\277\260.md" +++ /dev/null @@ -1,4 +0,0 @@ -# 概述 - -OpenHarmony WLAN模组基于Hi3861平台提供了丰富的外设操作能力,包含I2C、I2S、ADC、UART、SPI、SDIO、GPIO、PWM、FLASH等。本文介绍如何通过调用OpenHarmony的NDK接口,实现对GPIO控制,达到LED闪烁的效果。其他的IOT外设控制,开发者可根据API指导文档完成,此处不逐一介绍。 - diff --git "a/zh-cn/device-dev/guide/\346\267\273\345\212\240\351\241\265\351\235\242.md" "b/zh-cn/device-dev/guide/\346\267\273\345\212\240\351\241\265\351\235\242.md" deleted file mode 100755 index 8733bfb1e6..0000000000 --- "a/zh-cn/device-dev/guide/\346\267\273\345\212\240\351\241\265\351\235\242.md" +++ /dev/null @@ -1,34 +0,0 @@ -# 添加页面 - -- [创建首页面](#section16935511143715) -- [创建详情页](#section122131729173819) - -## 创建首页面 - -空气质量监测App包含两个界面(Page),工程创建完成后会生成一个名为index的Page,可以作为首页。工程目录如下图所示: - -**图 1** 工程目录 -![](figures/工程目录.png "工程目录") - -## 创建详情页 - -新增一个Page,作为详情页,具体步骤如下: - -1. pages目录右键 ,弹出的菜单中选择New、JS Page。 - - **图 2** 添加页面 - ![](figures/添加页面.png "添加页面") - -2. 输入Page名称。 - - **图 3** 输入页面名称 - ![](figures/输入页面名称.png "输入页面名称") - -3. 确认创建结果。 - - 详情页创建完成后应用工程目录如下图所示,每个Page包括三个文件:布局文件hml、样式文件css、业务逻辑代码js。 - - **图 4** 完整工程目录 - ![](figures/完整工程目录.png "完整工程目录") - - diff --git "a/zh-cn/device-dev/guide/\347\216\257\345\242\203\345\207\206\345\244\207.md" "b/zh-cn/device-dev/guide/\347\216\257\345\242\203\345\207\206\345\244\207.md" deleted file mode 100644 index c6ae1a1842..0000000000 --- "a/zh-cn/device-dev/guide/\347\216\257\345\242\203\345\207\206\345\244\207.md" +++ /dev/null @@ -1,7 +0,0 @@ -# 环境准备 - -环境准备具体操作请参考[标准系统基础环境搭建](../quick-start/标准系统入门.md)。 - ->![](public_sys-resources/icon-notice.gif) **须知:** ->本示例针对OpenHarmony轻量系统、小型系统、标准系统都适用,本文以标准系统为例。其他系统的开发者可参考对应系统的指导文档进行环境搭建。 - diff --git "a/zh-cn/device-dev/guide/\347\216\257\345\242\203\346\220\255\345\273\272.md" "b/zh-cn/device-dev/guide/\347\216\257\345\242\203\346\220\255\345\273\272.md" deleted file mode 100644 index 381ddaa88c..0000000000 --- "a/zh-cn/device-dev/guide/\347\216\257\345\242\203\346\220\255\345\273\272.md" +++ /dev/null @@ -1,7 +0,0 @@ -# 环境搭建 - -环境准备具体操作请参考[标准系统基础环境搭建](../quick-start/标准系统入门.md)。 - ->![](public_sys-resources/icon-notice.gif) **须知:** ->本示例针对OpenHarmony轻量系统、小型系统、标准系统都适用,本文以标准系统为例。其他系统的开发者可参考对应系统的指导文档进行环境搭建。 - diff --git "a/zh-cn/device-dev/guide/\347\234\237\346\234\272\350\277\220\350\241\214-9.md" "b/zh-cn/device-dev/guide/\347\234\237\346\234\272\350\277\220\350\241\214-9.md" deleted file mode 100644 index 30bb3b0801..0000000000 --- "a/zh-cn/device-dev/guide/\347\234\237\346\234\272\350\277\220\350\241\214-9.md" +++ /dev/null @@ -1,35 +0,0 @@ -# 真机运行 - -应用签名打包后即可安装到开发板。安装应用前需要先完成[DevEco Device Tool的安装配置](https://device.harmonyos.com/cn/docs/ide/user-guides/service_introduction-0000001050166905),然后将OpenHarmony系统烧录到开发板并运行。编译烧录、运行镜像的基本操作请参考快速入门手册:[标准系统Hi3516快速入门](../quick-start/标准系统入门.md)。完成镜像运行,系统正常启动后,执行如下步骤安装或卸载应用。 - -1. 从开发者工具代码仓路径中获取hdc客户端。 - - ``` - developtools/hdc_standard/prebuilt/windows/hdc_std.exe - ``` - - 修改名称为hdc.exe,并将工具路径加入系统环境path变量中。 - -2. 启动cmd命令窗口,执行以下命令,推送hap应用包到设备目录下并安装。 - - ``` - hdc smode - hdc target mount - hdc file send clock.hap /data/clock.hap - hdc shell chmod 666 /data/clock.hap - hdc shell bm install -p /data/clock.hap - ``` - -3. 启动应用。执行以下命令,其中ohos.samples.clock为应用包名,MainAbility为应用启动的Ability。 - - ``` - hdc shell aa start -d 123 -a ohos.samples.clock.MainAbility -b ohos.samples.clock - ``` - -4. 卸载应用(可选)。执行以下命令,其中ohos.samples.clock为应用包名。 - - ``` - hdc shell bm uninstall -n ohos.samples.clock - ``` - - diff --git "a/zh-cn/device-dev/guide/\347\234\237\346\234\272\350\277\220\350\241\214.md" "b/zh-cn/device-dev/guide/\347\234\237\346\234\272\350\277\220\350\241\214.md" deleted file mode 100755 index 973019fcce..0000000000 --- "a/zh-cn/device-dev/guide/\347\234\237\346\234\272\350\277\220\350\241\214.md" +++ /dev/null @@ -1,29 +0,0 @@ -# 真机运行 - -应用编译打包后即可安装到开发板。安装应用前需要先完成[DevEco Device Tool的安装配置](https://device.harmonyos.com/cn/docs/ide/user-guides/tool_install-0000001050164976),然后将OpenHarmony烧录到开发板并运行。编译烧录、运行镜像的基本操作请参考快速入门手册:[Hi3516快速入门](../quick-start/Hi3516开发板介绍.md)。完成镜像运行,系统正常启动后,执行如下步骤安装或卸载三方应用。 - -1. 将IDE编译的未签名应用安装包和安装工具(镜像文件生成目录中的dev\_tools)放在sdcard中,将sdcard插入开发板卡槽。 -2. 应用安装默认要校验签名,需要执行以下命令,关闭签名校验。 - - ``` - ./sdcard/dev_tools/bin/bm set -s disable - ``` - -3. 执行以下命令,安装应用。 - - ``` - ./sdcard/dev_tools/bin/bm install -p /sdcard/airquality.hap - ``` - - 其中dev\_tools目录中是安装工具,airquality.hap为应用安装包,此处替换为实际工程的安装包名称。 - -4. 应用安装完成后,可点击桌面应用图标启动应用,进行操作。 - - **图 1** 桌面 - ![](figures/桌面.png "桌面") - -5. 卸载应用(可选)。 - - 长按桌面应用图标,在弹出的菜单中点击“卸载”按钮即可卸载应用。 - - diff --git "a/zh-cn/device-dev/guide/\347\241\254\344\273\266\350\265\204\346\272\220\344\273\213\347\273\215.md" "b/zh-cn/device-dev/guide/\347\241\254\344\273\266\350\265\204\346\272\220\344\273\213\347\273\215.md" deleted file mode 100644 index 18b33bd5af..0000000000 --- "a/zh-cn/device-dev/guide/\347\241\254\344\273\266\350\265\204\346\272\220\344\273\213\347\273\215.md" +++ /dev/null @@ -1,6 +0,0 @@ -# 硬件资源介绍 - -Hi3516DV300开发板套件所提供的触摸屏器件IC为GT911,该器件采用标准I2C与主机通信,通过6pin软排线与主板连接。6pin分布以及实物连接图如下图所示: - -![](figures/绘图1.png) - diff --git "a/zh-cn/device-dev/guide/\347\244\272\344\276\213\345\274\200\345\217\221-2.md" "b/zh-cn/device-dev/guide/\347\244\272\344\276\213\345\274\200\345\217\221-2.md" deleted file mode 100755 index eb01bec406..0000000000 --- "a/zh-cn/device-dev/guide/\347\244\272\344\276\213\345\274\200\345\217\221-2.md" +++ /dev/null @@ -1,9 +0,0 @@ -# 示例开发 - -- **[拍照开发指导](拍照开发指导-3.md)** - -- **[录像开发指导](录像开发指导-4.md)** - -- **[预览开发指导](预览开发指导.md)** - - diff --git "a/zh-cn/device-dev/guide/\347\244\272\344\276\213\345\274\200\345\217\221.md" "b/zh-cn/device-dev/guide/\347\244\272\344\276\213\345\274\200\345\217\221.md" deleted file mode 100755 index e8128ecaac..0000000000 --- "a/zh-cn/device-dev/guide/\347\244\272\344\276\213\345\274\200\345\217\221.md" +++ /dev/null @@ -1,7 +0,0 @@ -# 示例开发 - -- **[拍照开发指导](拍照开发指导.md)** - -- **[录像开发指导](录像开发指导.md)** - - diff --git "a/zh-cn/device-dev/guide/\347\247\201\346\234\211\351\205\215\347\275\256\344\277\241\346\201\257\350\247\243\346\236\220.md" "b/zh-cn/device-dev/guide/\347\247\201\346\234\211\351\205\215\347\275\256\344\277\241\346\201\257\350\247\243\346\236\220.md" deleted file mode 100644 index a472a6dfdf..0000000000 --- "a/zh-cn/device-dev/guide/\347\247\201\346\234\211\351\205\215\347\275\256\344\277\241\346\201\257\350\247\243\346\236\220.md" +++ /dev/null @@ -1,17 +0,0 @@ -# 私有配置信息解析 - -示例代码路径:./drivers/framework/model/input/driver/input\_config\_parser.c - -根据OSAL提供的配置解析函数,可以将hcs文件中各字段含义进行解析,具体请参考input\_config\_parser.c中各函数的实现。如果提供的模板不能满足需求,在hcs文件中添加相应信息后,需要根据添加的字段开发相应的解析函数。 - -``` -static int32_t ParseAttr(struct DeviceResourceIface *parser, const struct DeviceResourceNode *attrNode, BoardAttrCfg *attr) -{ - int32_t ret; - ret = parser->GetUint8(attrNode, "inputType", &attr->devType, 0); // 获取inputType字段信息,保存在BoardAttrCfg结构体中 - CHECK_PARSER_RET(ret, "GetUint8"); - ... - return HDF_SUCCESS; -} -``` - diff --git "a/zh-cn/device-dev/guide/\347\255\276\345\220\215\346\211\223\345\214\205.md" "b/zh-cn/device-dev/guide/\347\255\276\345\220\215\346\211\223\345\214\205.md" deleted file mode 100644 index a6fd6f9655..0000000000 --- "a/zh-cn/device-dev/guide/\347\255\276\345\220\215\346\211\223\345\214\205.md" +++ /dev/null @@ -1,4 +0,0 @@ -# 签名打包 - -代码编写完成后,在真机设备上运行应用,需要先对应用进行签名,然后再进行打包,具体操作请参考[签名打包指导](../../application-dev/quick-start/配置OpenHarmony应用签名信息.md)。 - diff --git "a/zh-cn/device-dev/guide/\347\256\241\347\220\206\351\251\261\345\212\250\345\261\202\345\210\235\345\247\213\345\214\226\345\217\212\346\263\250\345\206\214\351\251\261\345\212\250\350\207\263HDF\346\241\206\346\236\266.md" "b/zh-cn/device-dev/guide/\347\256\241\347\220\206\351\251\261\345\212\250\345\261\202\345\210\235\345\247\213\345\214\226\345\217\212\346\263\250\345\206\214\351\251\261\345\212\250\350\207\263HDF\346\241\206\346\236\266.md" deleted file mode 100644 index 73b05bf0b0..0000000000 --- "a/zh-cn/device-dev/guide/\347\256\241\347\220\206\351\251\261\345\212\250\345\261\202\345\210\235\345\247\213\345\214\226\345\217\212\346\263\250\345\206\214\351\251\261\345\212\250\350\207\263HDF\346\241\206\346\236\266.md" +++ /dev/null @@ -1,22 +0,0 @@ -# 管理驱动层初始化及注册驱动至HDF框架 - -示例代码路径:./drivers/framework/model/input/driver/hdf\_input\_device\_manager.c - -``` -static int32_t HdfInputManagerInit(struct HdfDeviceObject *device) -{ - /* 分配内存给manager,manager中将存放所有input设备 */ - g_inputManager = InputManagerInstance(); - ... -} -struct HdfDriverEntry g_hdfInputEntry = { - .moduleVersion = 1, - .moduleName = "HDF_INPUT_MANAGER", - .Bind = HdfInputManagerBind, - .Init = HdfInputManagerInit, - .Release = HdfInputManagerRelease, -}; - -HDF_INIT(g_hdfInputEntry); //驱动注册入口 -``` - diff --git "a/zh-cn/device-dev/guide/\347\274\226\350\257\221\345\217\212\347\203\247\345\275\225-13.md" "b/zh-cn/device-dev/guide/\347\274\226\350\257\221\345\217\212\347\203\247\345\275\225-13.md" deleted file mode 100644 index 587404009f..0000000000 --- "a/zh-cn/device-dev/guide/\347\274\226\350\257\221\345\217\212\347\203\247\345\275\225-13.md" +++ /dev/null @@ -1,17 +0,0 @@ -# 编译及烧录 - -1. 编辑Makefile文件,添加本示例中的内容: - - 文件路径:./drivers/adapter/khdf/linux/model/input/Makefile - - 添加内容如下: - - ``` - obj-$(CONFIG_DRIVERS_HDF_TP_5P5_GT911) += \ - $(INPUT_ROOT_DIR)/touchscreen/touch_gt911.o - ``` - - 其中touch\_gt911.o为本示例中追加的内容。 - -2. 具体编译及烧录操作请参考[标准系统快速入门编译及烧录章节](../quick-start/标准系统入门.md)。 - diff --git "a/zh-cn/device-dev/guide/\347\274\226\350\257\221\345\217\212\347\203\247\345\275\225.md" "b/zh-cn/device-dev/guide/\347\274\226\350\257\221\345\217\212\347\203\247\345\275\225.md" deleted file mode 100644 index 92d839390d..0000000000 --- "a/zh-cn/device-dev/guide/\347\274\226\350\257\221\345\217\212\347\203\247\345\275\225.md" +++ /dev/null @@ -1,20 +0,0 @@ -# 编译及烧录 - -1. 编辑Makefile,添加源文件: - - ``` - include drivers/hdf/khdf/platform/platform.mk - - obj-y += $(HDF_PLATFORM_FRAMEWORKS_ROOT)/src/i2c_core.o \ - $(HDF_PLATFORM_FRAMEWORKS_ROOT)/src/i2c_if.o \ - ./i2c_adapter.o \ - ./i2c_sample.o - ``` - - "./i2c\_sample.o"为本示例中在Makefile中追加的内容。 - -2. 编译及烧录。 - - 具体操作请参考[标准系统快速入门编译及烧录章节](../quick-start/标准系统入门.md)。 - - diff --git "a/zh-cn/device-dev/guide/\350\247\206\350\247\211\345\272\224\347\224\250\345\274\200\345\217\221.md" "b/zh-cn/device-dev/guide/\350\247\206\350\247\211\345\272\224\347\224\250\345\274\200\345\217\221.md" deleted file mode 100755 index b4a8975ab2..0000000000 --- "a/zh-cn/device-dev/guide/\350\247\206\350\247\211\345\272\224\347\224\250\345\274\200\345\217\221.md" +++ /dev/null @@ -1,19 +0,0 @@ -# 视觉应用开发 - -- **[概述](概述-6.md)** - -- **[开发准备](开发准备.md)** - -- **[添加页面](添加页面.md)** - -- **[开发首页](开发首页.md)** - -- **[开发详情页](开发详情页.md)** - -- **[调试打包](调试打包.md)** - -- **[真机运行](真机运行.md)** - -- **[常见问题](常见问题.md)** - - diff --git "a/zh-cn/device-dev/guide/\350\260\203\350\257\225\346\211\223\345\214\205.md" "b/zh-cn/device-dev/guide/\350\260\203\350\257\225\346\211\223\345\214\205.md" deleted file mode 100755 index 5015bd5755..0000000000 --- "a/zh-cn/device-dev/guide/\350\260\203\350\257\225\346\211\223\345\214\205.md" +++ /dev/null @@ -1,4 +0,0 @@ -# 调试打包 - -代码编写完成后,可以进行调试和打包;应用调试及打包方法可以参考[《DevEco Studio使用指南》](https://developer.harmonyos.com/cn/docs/documentation/doc-guides/tools_overview-0000001053582387)的[应用调测](https://developer.harmonyos.com/cn/docs/documentation/doc-guides/debug_overview-0000001053822404)和[编译构建](https://developer.harmonyos.com/cn/docs/documentation/doc-guides/build_overview-0000001055075201)章节。IPCamera应用暂时不支持签名模式,所以需要将应用发布为未签名的应用安装包。 - diff --git "a/zh-cn/device-dev/guide/\350\260\203\350\257\225\351\252\214\350\257\201.md" "b/zh-cn/device-dev/guide/\350\260\203\350\257\225\351\252\214\350\257\201.md" deleted file mode 100644 index f339b20a63..0000000000 --- "a/zh-cn/device-dev/guide/\350\260\203\350\257\225\351\252\214\350\257\201.md" +++ /dev/null @@ -1,5 +0,0 @@ -# 调试验证 - -- **[开机日志分析](开机日志分析.md)** - - diff --git "a/zh-cn/device-dev/guide/\351\200\202\351\205\215\345\231\250\344\273\266\347\247\201\346\234\211\351\251\261\345\212\250.md" "b/zh-cn/device-dev/guide/\351\200\202\351\205\215\345\231\250\344\273\266\347\247\201\346\234\211\351\251\261\345\212\250.md" deleted file mode 100644 index b719de9bac..0000000000 --- "a/zh-cn/device-dev/guide/\351\200\202\351\205\215\345\231\250\344\273\266\347\247\201\346\234\211\351\251\261\345\212\250.md" +++ /dev/null @@ -1,99 +0,0 @@ -# 适配器件私有驱动 - -Input模型由三层驱动组成,开发者适配一款全新触摸屏驱动只需要适配器件驱动层即可,重点实现差异化接口,本小节以代码示例的形式展示开发者需要重点完成的工作。 - -1. 触摸屏器件差异化接口适配 - - 示例代码路径:./drivers/framework/model/input/driver/touchscreen/touch\_gt911.c - - ``` - static struct TouchChipOps g_gt911ChipOps = { // 器件IC接口 - .Init = ChipInit, // 初始化 - .Detect = ChipDetect, // 器件检测 - .Resume = ChipResume, // 唤醒 - .Suspend = ChipSuspend, // 休眠 - .DataHandle = ChipDataHandle, // 器件数据读取 - .UpdateFirmware = UpdateFirmware, // 固件升级 - }; - - /* 不同触摸屏厂家使用的IC不一样,对应的寄存器操作也不一样,因此器件驱动层代码重点适配差异化接口部分,如下示例代码展示了GT911的数据解析*/ - - static int32_t ChipDataHandle(ChipDevice *device) - { - ... - /* GT911获取坐标之前需先读取状态寄存器 */ - reg[0] = (GT_BUF_STATE_ADDR >> ONE_BYTE_OFFSET) & ONE_BYTE_MASK; - reg[1] = GT_BUF_STATE_ADDR & ONE_BYTE_MASK; - ret = InputI2cRead(i2cClient, reg, GT_ADDR_LEN, &touchStatus, 1); - if (ret < 0 || touchStatus == GT_EVENT_INVALID) { - return HDF_FAILURE; - } - ... - /* 根据状态寄存器的值读取数据寄存器数据 */ - reg[0] = (GT_X_LOW_BYTE_BASE >> ONE_BYTE_OFFSET) & ONE_BYTE_MASK; - reg[1] = GT_X_LOW_BYTE_BASE & ONE_BYTE_MASK; - pointNum = touchStatus & GT_FINGER_NUM_MASK; - if (pointNum == 0 || pointNum > MAX_SUPPORT_POINT) { - HDF_LOGE("%s: pointNum is invalid, %u", __func__, pointNum); - (void)ChipCleanBuffer(i2cClient); - OsalMutexUnlock(&device->driver->mutex); - return HDF_FAILURE; - } - frame->realPointNum = pointNum; - frame->definedEvent = TOUCH_DOWN; - (void)InputI2cRead(i2cClient, reg, GT_ADDR_LEN, buf, GT_POINT_SIZE * pointNum); - /* 对获取的数据进行解析 */ - ParsePointData(device, frame, buf, pointNum); - ... - } - static void ParsePointData(ChipDevice *device, FrameData *frame, uint8_t *buf, uint8_t pointNum) - { - ... - /* 每个坐标值由两个字节组成,对获取的单字节数据进行拼接得到最终的坐标值 */ - for (i = 0; i < pointNum; i++) { - frame->fingers[i].trackId = buf[GT_POINT_SIZE * i + GT_TRACK_ID]; - frame->fingers[i].y = (buf[GT_POINT_SIZE * i + GT_X_LOW] & ONE_BYTE_MASK) | - ((buf[GT_POINT_SIZE * i + GT_X_HIGH] & ONE_BYTE_MASK) << ONE_BYTE_OFFSET); - frame->fingers[i].x = (buf[GT_POINT_SIZE * i + GT_Y_LOW] & ONE_BYTE_MASK) | - ((buf[GT_POINT_SIZE * i + GT_Y_HIGH] & ONE_BYTE_MASK) << ONE_BYTE_OFFSET); - /* 对解析出来的坐标值进行打印 */ - HDF_LOGD("%s: x = %d, y = %d", __func__, frame->fingers[i].x, frame->fingers[i].y); - } - } - ``` - -2. 器件层驱动初始化及注册驱动至HDF框架 - - 示例代码路径:./drivers/framework/model/input/driver/touchscreen/touch\_gt911.c - - ``` - static int32_t HdfGoodixChipInit(struct HdfDeviceObject *device) - { - ... - /* 器件配置结构体内存申请、配置信息解析及挂载 */ - chipCfg = ChipConfigInstance(device); - ... - /* 器件实例化 */ - chipDev = ChipDeviceInstance(); - ... - /* 器件信息挂载及器件私有操作挂载 */ - chipDev->chipCfg = chipCfg; - chipDev->ops = &g_gt911ChipOps; - ... - /* 注册器件驱动至平台驱动 */ - RegisterChipDevice(chipDev); - ... - } - struct HdfDriverEntry g_touchGoodixChipEntry = { - .moduleVersion = 1, - .moduleName = "HDF_TOUCH_GT911", // 该moduleName与device_info.hcs文件中器件驱动层的moduleName信息相匹配 - .Init = HdfGoodixChipInit, // 器件驱动初始化函数 - }; - HDF_INIT(g_touchGoodixChipEntry); // 注册器件驱动至HDF框架 - ``` - - 器件私有驱动层主要实现了各器件厂商差异较大的部分,如器件休眠唤醒、数据解析以及固件升级等。 - - 至此,基于HDF框架及Input模型的触摸屏驱动适配完成。 - - diff --git "a/zh-cn/device-dev/guide/\351\205\215\347\275\256Touchscreen\345\231\250\344\273\266\344\277\241\346\201\257.md" "b/zh-cn/device-dev/guide/\351\205\215\347\275\256Touchscreen\345\231\250\344\273\266\344\277\241\346\201\257.md" deleted file mode 100644 index a563814582..0000000000 --- "a/zh-cn/device-dev/guide/\351\205\215\347\275\256Touchscreen\345\231\250\344\273\266\344\277\241\346\201\257.md" +++ /dev/null @@ -1,98 +0,0 @@ -# 配置Touchscreen器件信息 - -配置文件路径:./drivers/adapter/khdf/linux/hcs/input/input\_config.hcs - -input\_config.hcs中的信息由驱动代码进行读取解析,主要由公共驱动层的私有配置信息及器件驱动层的私有配置信息组成。文件中的配置包含板级硬件信息及器件私有配置信息,实际业务开发时,可根据具体需求增删及修改对应内容。 - -``` -root { - input_config { - touchConfig { - touch0 { // 第一款触摸屏 - boardConfig { // 板级硬件信息 - match_attr = "touch_device1"; // 与设备描述配置信息中公共驱动层私有配置信息的“match_attr”字段保持一致 - inputAttr { - /* 0:touch 1:key 2:keyboard 3:mouse 4:button 5:crown 6:encoder */ - inputType = 0; // input类型为touch - solutionX = 480; // 分辨率X信息 - solutionY = 960; // 分辨率Y信息 - devName = "main_touch"; // 设备名称 - } - busConfig { - /* 0:i2c 1:spi */ - busType = 0; // GT911采用I2C通信 - busNum = 6; // 与主机芯片第6路I2C通信 - clkGpio = 86; // 主机芯片SCL管脚 - dataGpio = 87; // 主机芯片SDA管脚 - i2cClkIomux = [0x114f0048, 0x403]; // SCL管脚配置信息 - i2cDataIomux = [0x114f004c, 0x403]; // SDA管脚配置信息 - } - pinConfig { - rstGpio = 3; // 复位管脚连接主机芯片的3号管脚 - intGpio = 4; // 中断管脚连接主机芯片的4号管脚 - rstRegCfg = [0x112f0094, 0x400]; // 复位管脚配置信息 - intRegCfg = [0x112f0098, 0x400]; // 中断管脚配置信息 - } - powerConfig { - /* 0:unused 1:ldo 2:gpio 3:pmic */ - vccType = 2; // GPIO供电 - vccNum = 20; // gpio20 - vccValue = 1800; // 电压幅值为1800mV - vciType = 1; // LDO供电 - vciNum = 12; // ldo12 - vciValue = 3300; // 电压幅值为3300mV - } - - featureConfig { - capacitanceTest = 0; // 容值测试 - gestureMode = 0; // 手势模式 - gloverMode = 0; // 手套模式 - coverMode = 0; // 皮套模式 - chargerMode = 0; // 充电模式 - knuckleMode = 0; // 指关节模式 - } - } - chipConfig { // 器件私有信息配置 - template touchChip { // 模板 - match_attr = ""; - chipName = "gt911"; // 触摸屏IC型号 - vendorName = "zsj"; // 供应商 - chipInfo = "AAAA11222"; // 1~4字符代表产品名,5~6字符代表IC型号,7~9字符代表模型型号 - busType = 0; // 0代表I2C,1代表SPI - deviceAddr = 0x5D; // 器件IC通信地址 - irqFlag = 2; // 1代表上升沿触发,2代表下降沿触发,4代表高电平触发,8代表低电平触发 - maxSpeed = 400; // 最大通信速率为400Hz - chipVersion = 0; // 触摸屏IC版本号 - powerSequence { - /* 上电时序的配置含义说明: - [类型, 状态, 方向 , 延时] - 0代表空,1代表vcc电源(1.8V),2代表VCI电源(3.3V),3代表复位管脚,4代表中断管脚 - 0代表下电或拉低,1代表上电或拉高,2代表无操作 - 0代表输入方向,1代表输出方向,2代表无操作 - 代表延时多少毫秒, 例如20代表延时20ms - */ - powerOnSeq = [4, 0, 1, 0, // 中断管脚配置为输出,且进行拉低 - 3, 0, 1, 10, // 复位管脚配置为输出,且进行拉低,延时10ms - 3, 1, 2, 60, // 复位管脚无操作,且进行拉高,延时60ms - 4, 2, 0, 0]; // 中断管脚配置为输入 - suspendSeq = [3, 0, 2, 10]; // 复位管脚无操作,且进行拉低,延时10ms - resumeSeq = [3, 1, 2, 10]; // 复位管脚无操作,且进行拉高,延时10ms - powerOffSeq = [3, 0, 2, 10, // 复位管脚无操作,且进行拉低,延时10ms - 1, 0, 2, 20]; // 电源正极管脚无操作,且进行拉低,延时20ms - } - } - - chip0 :: touchChip { - match_attr = "zsj_gt911_5p5"; // 与设备描述配置信息中器件私有配置信息的“match_attr”字段保持一致 - chipInfo = "ZIDN45100"; // 产品名+模组编号+芯片编号的组合信息 用于给用户态区分当前器件 - chipVersion = 0; // IC型号的版本 - } - } - } - } - } -} -``` - -示例中“touchConfig”包含了“touch0”,"touch0"包含了“boardConfig”与“chipConfig”;“boardConfig”字段包含了Hi3516DV300板级硬件信息,“chipConfig”包含了触摸屏器件的私有信息,如果需要替换触摸屏器件,重新配置“chipConfig”对应的字段信息即可。同时产品可以配置多款触摸屏,示例中用“touch0”代表了套件中默认的触摸屏的硬件接口以及器件的配置信息,如产品需要配置副屏,可在与“touch0”并列的位置配置“touch1”的信息。 - diff --git "a/zh-cn/device-dev/guide/\351\205\215\347\275\256\350\256\276\345\244\207\346\217\217\350\277\260\344\277\241\346\201\257.md" "b/zh-cn/device-dev/guide/\351\205\215\347\275\256\350\256\276\345\244\207\346\217\217\350\277\260\344\277\241\346\201\257.md" deleted file mode 100644 index 4183826a4f..0000000000 --- "a/zh-cn/device-dev/guide/\351\205\215\347\275\256\350\256\276\345\244\207\346\217\217\350\277\260\344\277\241\346\201\257.md" +++ /dev/null @@ -1,64 +0,0 @@ -# 配置设备描述信息 - -配置文件路径:./drivers/adapter/khdf/linux/hcs/device\_info/device\_info.hcs - -device\_info.hcs中的信息主要提供给HDF框架使用,包含了Input模型各层驱动注册到HDF框架所必需的信息,开发者无特殊场景需求无需改动。各驱动层私有配置信息通过“deviceMatchAttr”字段与input\_config.hcs中的“match\_attr”相关内容进行匹配。 - -配置文件中与input模块相关的内容如下所示,相关字段的详细含义可以参考《[驱动配置](../driver/驱动开发.md)》: - -``` -input :: host { - hostName = "input_host"; - priority = 100; - device_input_manager :: device { // Input管理层设备描述信息 - device0 :: deviceNode { - policy = 2; // 向内核用户态均发布服务 - priority = 100; // input管理层驱动优先级默认为100 - preload = 0; // 加载该驱动 - permission = 0660; // 驱动创建设备节点权限 - moduleName = "HDF_INPUT_MANAGER"; // 与驱动入口的moduleName匹配 - serviceName = "hdf_input_host"; // HDF框架生成的节点名 - deviceMatchAttr = ""; // manager目前不需要私有配置,因此为空 - } - } - - device_hdf_touch :: device { // Input公共驱动层设备描述信息 - device0 :: deviceNode { - policy = 2; // 向内核用户态均发布服务 - priority = 120; // input公共驱动优先级默认为120 - preload = 0; // 加载该驱动 - permission = 0660; // 驱动创建设备节点权限 - moduleName = "HDF_TOUCH"; // 与驱动入口的moduleName匹配 - serviceName = "hdf_input_event1"; // HDF框架生成的节点名 - deviceMatchAttr = "touch_device1"; // 与私有配置信息中的“match_attr”字段保持一致 - } - } - - device_touch_chip :: device { // Input器件驱动层信息 - device0 :: deviceNode { - policy = 0; // 向内核用户态均不发布服务 - priority = 130; // input器件驱动优先级默认为130 - preload = 0; // 加载该驱动 - permission = 0660; // 驱动创建设备节点权限 - moduleName = "HDF_TOUCH_GT911"; // 与驱动入口的moduleName匹配 - serviceName = "hdf_touch_gt911_service";// HDF框架生成的节点名 - deviceMatchAttr = "zsj_gt911_5p5"; //与私有配置信息中的“match_attr”字段保持一致 - } - } - } -``` - -该配置文件中需要重点关注的字段有: - -“priority”决定驱动加载顺序; - -“preload”决定驱动是否加载; - -“moduleName ”需要与驱动注册入口处的“moduleName ”字段保持一致; - -“serviceName ”HDF框架依据该字段创建节点名; - -“deviceMatchAttr ”需要与私有配置信息中的“match\_attr”字段保持一致。 - -通过配置设备描述信息,使得HDF框架通过moduleName与注册至驱动入口的代码相匹配,保证了驱动的正常加载,通过priority字段保证了各驱动的加载顺序。 - diff --git "a/zh-cn/device-dev/guide/\351\233\206\346\210\220\344\270\211\346\226\271SDK.md" "b/zh-cn/device-dev/guide/\351\233\206\346\210\220\344\270\211\346\226\271SDK.md" deleted file mode 100755 index 355c2b275b..0000000000 --- "a/zh-cn/device-dev/guide/\351\233\206\346\210\220\344\270\211\346\226\271SDK.md" +++ /dev/null @@ -1,325 +0,0 @@ -# 集成三方SDK - -- [规划目录结构](#section1736472718351) -- [构建业务libs](#section442815485351) -- [编写适配代码](#section3984721113613) -- [代码编写](#section830417531286) -- [脚本编写](#section13500201173710) -- [编写业务代码](#section8754114803918) -- [运行](#section7737749184012) -- [结束](#section153301392411) - -OpenHarmony致力于打造一套更加开放完善的IoT生态系统,为此OpenHarmony规划了一组目录,用于将各厂商的SDK集成到OpenHarmony中。本文档基于Hi3861开发板,向平台开发者介绍将SDK集成到OpenHarmony的方法。 - -## 规划目录结构 - -三方SDK通常由静态库和适配代码构成。SDK的业务逻辑通过硬件模组工具链编译得到静态库libs,每款模组都有其对应的libs。SDK的南向API与OpenHarmony 的API存在使用差异,该差异可通过adapter适配代码屏蔽,不同模组可共用一套adapter。 - -基于以上特征,在OpenHarmony目录结构中,可以对三方SDK目录做如下划分。 - -- 适配代码adapter,放置到domains/iot/link/ 目录下,与模组解耦。 -- 业务库libs,放置到device/hisilicon/hispark\_pegasus/sdk\_liteos/3rd\_sdk/ 目录下,与模组绑定。 - -平台开发者在适配前,务必先依次完成以下步骤,下面以demolink SDK举例,进行介绍。 - -1. 创建厂商目录,domains/iot/link/demolink/、device/hisilicon/hispark\_pegasus/sdk\_liteos/3rd\_sdk/demolink/ ,用于厂商隔离。 -2. 创建domains/iot/link/demolink/BUILD.gn ,用于构建适配代码。 -3. 创建device/hisilicon/hispark\_pegasus/sdk\_liteos/3rd\_sdk/demolink/libs/ 目录,用于存放业务库libs。 - -``` -. -├── domains -│ └── iot -│ └── link -│ ├── demolink -│ │ └── BUILD.gn -│ ├── libbuild -│ │ └── BUILD.gn -│ └── BUILD.gn -└── device - └── hisilicon - └── hispark_pegasus - └── sdk_liteos - └── 3rd_sdk - └── demolink - └── libs -``` - -## 构建业务libs - -平台SDK业务一般以静态库的形式提供,平台厂商在获取到OpenHarmony代码后,需要根据对应的硬件模组vendor,编译业务libs,并将编译结果放置在device/hisilicon/hispark\_pegasus/sdk\_liteos/3rd\_sdk/demolink/libs/ 目录下。下面介绍业务libs的构建方法。 - -OpenHarmony已规划用于编译业务libs的目录domains/iot/link/libbuild/ ,该目录中包含domains/iot/link/libbuild/BUILD.gn和domains/iot/link/BUILD.gn文件,目录结构如下。 - -``` -. -└── domains - └── iot - └── link - ├── demolink - │ └── BUILD.gn - ├── libbuild - │ └── BUILD.gn - └── BUILD.gn -``` - -平台开发者在构建libs前,务必先完成如下步骤。 - -1. 在domains/iot/link/libbuild/ 目录下放置业务源码文件,包括.c和.h文件。 - - ``` - . - └── domains - └── iot - └── link - ├── demolink - │ ├── demosdk_adapter.c - │ ├── demosdk_adapter.h - │ └── BUILD.gn - ├── libbuild - │ ├── demosdk.c - │ ├── demosdk.h - │ └── BUILD.gn - └── BUILD.gn - ``` - -2. 适配domains/iot/link/libbuild/BUILD.gn,在编译完成后还原该文件。 - - 在BUILD.gn中,sources为需要参与构建的源文件,include\_dirs为依赖的头文件路径,构建的目标结果是生成静态库libdemosdk.a。 - - ``` - static_library("demosdk") { - sources = [ - "demosdk.c" - ] - include_dirs = [ - "//domains/iot/link/libbuild", - "//domains/iot/link/demolink" - ] - } - ``` - -3. 适配domains/iot/link/BUILD.gn,在编译完成后还原该文件。 - - 此BUILD.gn文件用于指定构建条目,需要在features中填入所有需参与编译的静态库条目,使domains/iot/link/libbuild/BUILD.gn参与到构建中来。 - - ``` - import("//build/lite/config/subsystem/lite_subsystem.gni") - import("//build/lite/config/component/lite_component.gni") - lite_subsystem("iot") { - subsystem_components = [ - ":link" - ] - } - lite_component("link") { - features = [ - "libbuild:demosdk" - ] - } - ``` - - -完成以上3点后,需在代码根目录下执行命令“hb build -T //domains/iot/link:iot”,等待执行完成,检查out/hispark\_pegasus/wifiiot\_hispark\_pegasus/libs/目录下是否生成了目标库文件。 - -![](figures/zh-cn_image_0000001078563230.png) - -将库文件拷贝到device/hisilicon/hispark\_pegasus/sdk\_liteos/3rd\_sdk/demolink/libs/ 目录下,并将domains/iot/link/libbuild/ 目录中的.c和.h文件清除。 - -## 编写适配代码 - -## 代码编写 - -平台SDK中使用的API通常与OpenHarmony API存在差异,无法直接使用,需要一层适配代码adapter进行中间转换。本节以domains/iot/link/demolink/demosdk\_adapter.c中的任务创建接口DemoSdkCreateTask举例,向开发者演示如何在OpenHarmony上编写适配代码。 - -1. 查看待适配接口DemoSdkCreateTask的描述、参数、返回值。 - - ``` - struct TaskPara { - char *name; - void *(*func)(char* arg); - void *arg; - unsigned char prio; - unsigned int size; - }; - - /* - * IoT OS 创建线程接口 - * 返回值: 返回0 成功, 其他 失败 - */ - int DemoSdkCreateTask(unsigned int *handle, const struct TaskPara *para); - ``` - -2. 查看OpenHarmony API接口文档,选取一个功能类似的接口,并比对参数及用法上的差异。例如本文选取osThreadNew ,通过和DemoSdkCreateTask接口比对,可以发现两接口依赖的参数基本一致,只是参数所归属的结构体不同。 - - ``` - typedef struct { - const char *name; ///< name of the thread - uint32_t attr_bits; ///< attribute bits - void *cb_mem; ///< memory for control block - uint32_t cb_size; ///< size of provided memory for control block - void *stack_mem; ///< memory for stack - uint32_t stack_size; ///< size of stack - osPriority_t priority; ///< initial thread priority (default: osPriorityNormal) - TZ_ModuleId_t tz_module; ///< TrustZone module identifier - uint32_t reserved; ///< reserved (must be 0) - } osThreadAttr_t; - - /// Create a thread and add it to Active Threads. - /// \param[in] func thread function. - /// \param[in] argument pointer that is passed to the thread function as start argument. - /// \param[in] attr thread attributes; NULL: default values. - /// \return thread ID for reference by other functions or NULL in case of error. - osThreadId_t osThreadNew (osThreadFunc_t func, void *argument, const osThreadAttr_t *attr); - ``` - -3. 完成代码差异转换。 - - ``` - int DemoSdkCreateTask(unsigned int *handle, const struct TaskPara *para) - { - osThreadAttr_t attr = {0}; - osThreadId_t threadId; - if (handle == 0 || para == 0) { - return DEMOSDK_ERR; - } - if (para->func == 0) { - return DEMOSDK_ERR; - } - if (para->name == 0) { - return DEMOSDK_ERR; - } - attr.name = para->name; - attr.priority = para->prio; - attr.stack_size = para->size; - threadId = osThreadNew((osThreadFunc_t)para->func, para->arg, &attr); - if (threadId == 0) { - printf("osThreadNew fail\n"); - return DEMOSDK_ERR; - } - *(unsigned int *)handle = (unsigned int)threadId; - return DEMOSDK_OK; - } - ``` - - -## 脚本编写 - -开发者在完成代码适配后,还需要在adapter同级目录下新建BUILD.gn文件。该文件可在整包构建时,将适配代码编译成静态库,并链接到bin包中去。在domains/iot/link/demolink/BUILD.gn中,sources中为需要参与构建的源文件,include\_dirs中为依赖的头文件路径,构建目标结果是生产静态库libdemolinkadapter.a。 - -``` -import("//build/lite/config/component/lite_component.gni") -static_library("demolinkadapter") { - sources = [ - "demosdk_adapter.c" - ] - include_dirs = [ - "//kernel/liteos-m/kal/cmsis", - "//domains/iot/link/demolink" - ] -} -``` - -修改domains/iot/link/BUILD.gn文件,使domain/iot/hilink/BUILD.gn参与到构建系统中。 - -``` -import("//build/lite/config/subsystem/lite_subsystem.gni") -import("//build/lite/config/component/lite_component.gni") -lite_subsystem("iot") { - subsystem_components = [ - ":link" - ] -} -lite_component("link") { - features = [ - "demolink:demolinkadapter" - ] -} -``` - -## 编写业务代码 - -业务libs库和适配代码准备就绪后,还需要编写业务入口函数,调起三方SDK的业务入口。 - -下面以demolink举例,介绍如何在applications/sample/wifi-iot/app/路径下编写代码,调起demosdk的入口函数。 - -1. 目录创建 - - 开发者编写业务时,务必先在applications/sample/wifi-iot/app/ 路径下新建一个目录(或一套目录结构),用于存放业务源码文件。 - - 例如:在app下新增业务目录demolink,并在其中创建业务入口代码helloworld.c和编译构建文件BUILD.gn,如下。 - - ``` - . - └── applications - └── sample - └── wifi-iot - └── app - │── demolink - │ │── helloworld.c - │ └── BUILD.gn - └── BUILD.gn - ``` - -2. 编写业务代码。 - - 在helloworld.c文件中编写业务入口函数DemoSdkMain,并调起demolink的业务DemoSdkEntry,最后通过SYS\_RUN\(\)调用入口函数完成业务启动。 - - ``` - #include "hos_init.h" - #include "demosdk.h" - - void DemoSdkMain(void) - { - DemoSdkEntry(); - } - - SYS_RUN(DemoSdkMain); - ``` - -3. 编写构建脚本 - - 新增applications/sample/wifi-iot/app/demolink/BUILD.gn文件,指定源码和头文件路径,编译输出静态库文件libexample\_demolink.a。 - - ``` - static_library("example_demolink") { - sources = [ - "helloworld.c" - ] - include_dirs = [ - "//utils/native/lite/include", - "//domains/iot/link/libbuild" - ] - } - ``` - - 修改applications/sample/wifi-iot/app/BUILD.gn,使demolink参与编译。 - - ``` - import("//build/lite/config/component/lite_component.gni") - lite_component("app") { - features = [ - "demolink:example_demolink" - ] - } - ``` - - -## 运行 - -在代码根目录下,执行命令“hb build”编译输出版本包。最后启动运行,运行结果如图所示,与demolink预期相符。 - -``` -ready to OS start -sdk ver:Hi3861V100R001C00SPC024 2020-08-05 16:30:00 -formatting spiffs... -FileSystem mount ok. -wifi init success! -it is demosdk entry. -it is demo biz: hello world. -it is demo biz: hello world. -``` - -## 结束 - -至此,三方SDK集成已介绍完毕。 - diff --git "a/zh-cn/device-dev/guide/\351\252\214\350\257\201.md" "b/zh-cn/device-dev/guide/\351\252\214\350\257\201.md" deleted file mode 100755 index e9be36acdf..0000000000 --- "a/zh-cn/device-dev/guide/\351\252\214\350\257\201.md" +++ /dev/null @@ -1,9 +0,0 @@ -# 验证 - -编译过程请参考《[Hi3861快速入门-源码编译](../quick-start/运行Hello-World.md)》,烧录过程请参考《[Hi3861快速入门-镜像烧录](../quick-start/WLAN联网.md)》。 - -完成以上两步后,按下RST键复位模组,可发现LED在周期性闪烁,与预期相符,验证完毕。 - -**图 1** LED闪烁图 -![](figures/LED闪烁图.gif "LED闪烁图") - diff --git "a/zh-cn/device-dev/kernel-contribution/OpenHarmony\345\206\205\346\240\270\346\226\207\346\241\243\345\205\261\345\273\272ToDo-List.md" "b/zh-cn/device-dev/kernel-contribution/OpenHarmony\345\206\205\346\240\270\346\226\207\346\241\243\345\205\261\345\273\272ToDo-List.md" deleted file mode 100644 index ce1082a69f..0000000000 --- "a/zh-cn/device-dev/kernel-contribution/OpenHarmony\345\206\205\346\240\270\346\226\207\346\241\243\345\205\261\345\273\272ToDo-List.md" +++ /dev/null @@ -1,245 +0,0 @@ -# OpenHarmony文档共建计划--内核文档共建 - - - -| 2021-06-28-2021-07-30 | 2021-07-05 | 2021-07-05-2021-07-30 | 2021-08-01-2021-08-31 | -| --------------------------------- | -------------------------------- | -------------------------- | --------------------- | -| **任务招募** | **线上会议** | **文档共建** | **结项发布** | -| ToDo List、文档模板、共建手册大纲 | 文档共建介绍、写作规范、常见操作 | 小组周进展跟踪、导师辅导制 | 发布共建后内核文档 | - -- [如何参与](#section_register) -- [文档共建范围](#section_outline_summary) -- [文档大纲及认领明细](section_outline_detail) - -## 共建活动ToDoList - -OpenHarmony文档共建活动是由OpenHarmony社区举办,旨在进一步丰富和完善现有文档,提升文档体验**,**更好地服务于广大开发者。本次文档共建活动有共建移植文档、内核文档、Qemu仿真文档。详情请参考共建手册大纲:《基于Qemu运行OpenHarmony》、 《小型系统三方芯片移植指南》、《OpenHarmony内核开发指南》。 - -即日起开发者可自主选择并认领感兴趣的任务,获得社区资深**技术导师**和**文档导师**的指导。根据项目的难易程度和完成情况,参与者还将获得"**OpenHarmony 文档共建贡献者** " 荣誉及周边纪念品。 - -1. **活动时间:** 2021-06-28~2021-07-30 - -2. **招募对象:** - - - 技术写作者 - - - 文档验证/审核者 - - - 小组组织人员 - -3. **招募要求:** -- 熟悉嵌入式、物联网等OS开发相关知识 - -- 有扎实的C语言编程经验 - -- 有较强的文字写作能力、逻辑思维能力 - -4. **参与方式:** - - - Gitee社区内认领任务反馈 - - 开发者加入内核文档共建招募活动微信群 -5. 共建激励规则 - -**卓越贡献奖** - -- **奖励对象:**审核通过&内容被采纳的contributor。 - -- **奖励礼品:**OpenHarmonyT恤、帽子等周边纪念品。 - - - -## 如何参与 -- 方式1 [Issue回帖](https://gitee.com/openharmony/docs/issues/I3Y9MU?from=project-issue) -- 方式2 微信交流群报名 -- 方式3 邮件反馈 @neeen @rtos_yuan ,邮件主题:OpenHarmony轻内核文档共建报名 -3种方式均可报名,建议同时提供邮箱,方便后续发送线上会议交流通知。 - - -## 文档共建范围 - -### 1、基于Qemu运行OpenHarmony---招募内容写作 - -- 背景 - - - 对于想体验OpenHarmony的开发者,手头不一定有现成的开发板,基于Qemu可以降低入门体验门槛。 - - - 已经支持Qemu,但是没有对应的文档, 快速入门只有3861、3516、3518等板子。 - -- 文档计划 - - LiteOS-A、LiteOS-M Qemu使用教程第一时间上社区,社区化运作文档,降低社区开发者体验OpenHarmony开发的门槛。 - -- **访问[《基于Qemu运行OpenHarmony 文档大纲》](#section_qemu_outline_detail)。** - -### 2、小型系统三方芯片移植指南---招募内容体验&验证 - -社区支持的开发板有限,三方芯片、开发板移植需要更丰富的开发板场景案例。 -- 文档计划 - - - 鼓励开发者完善移植文档,支持社区开发者移植支持更多的开发板、支持手头的开发板能运行起来。 - - 鼓励移植经验文档回馈社区。 - -- **访问[《小型系统三方芯片移植指南 文档大纲》](#porting_tutorial_outline_detail)。** - -### 3、小型系统内核开发指南(LiteOS-A核)---招募内容体验&验证 - -- 文档计划 - - - 优化后内核文档初稿完成,鼓励开发者体验新内容,验证内容。 - - 社区化文档运作,鼓励社区开发者参与文档的优化编写,文档问题反馈。 - -- **访问[《OpenHarmony 内核开发指南(LiteOS-A核) 文档大纲》](#kernel_a_tutorial_outline_detail)。** - - - - -## 文档大纲及认领明细 - -✨**文档大纲用于维护文档的组成章节、章节意图,编写责任人,及PR合入状态**。 - -✨**使用对号[✔]表示文档的完成状态,第一个对号表示文档开发完成,第二个对号表示文档开发完成**。 - -### 一、基于Qemu运行OpenHarmony 文档大纲 - -#### 1 Qemu简介 [@rtos_yuan](https://gitee.com/rtos_yuan) [✔] [@mgy917](https://gitee.com/mgy917) [✔] - - - -#### 2 开发环境准备 [@mgy917](https://gitee.com/mgy917) [✔] [@rtos_yuan](https://gitee.com/rtos_yuan) [✔] - -- 2.1 OpenHarmony开发环境准备 - - - 环境搭建 - - 获取OpenHarmony源码 - -- 2.2 Qemu软件安装 - - 开发者根据需求,选择运行LiteOS-A、LiteOS-M的Qemu软件。 - - - Qemu软件编译安装 - - Qemu-Virt软件 - - Qemu-Riscv32软件 [@zhushengle](https://gitee.com/zhushengle) [✔] - - - -#### 3 Qemu工程源码介绍 [@waitForContributor](https://gitee.com/openharmony/docs/issues)[ ?] - -* 3.1 Qemu工程源码介绍 - -#### 4 编译运行LiteOS-A Qemu Virt工程 [@waitForContributor](https://gitee.com/openharmony/docs/issues)[ ?] - -- 4.1 编译构建LiteOS-A -- 4.2 运行镜像 - - 准备Flash镜像 - - 配置主机网桥 - - 运行程序 - -#### 5 编译运行LiteOS-M Qemu Riscv工程 [@waitForContributor](https://gitee.com/openharmony/docs/issues)[ ?] - -- 4.1 编译构建LiteOS-M -- 4.2 运行程序 - -### 二、小型系统三方芯片移植指南 ---招募内容体验&验证 - -#### 1 移植准备 [@arvinzzz](https://gitee.com/arvinzzz) [✔] [@rtos_yuan](https://gitee.com/rtos_yuan) [✔] - - - -##### 1.1 移植须知 - -##### 1.2 编译构建 - -#### 2 内核移植 [@waitForContributor](https://gitee.com/openharmony/docs/issues)[ ?] - -- 2.1 LiteOS-A内核 - - - - - 2.1.1 移植概述 - - 2.1.2 内核基础适配 - - 2.1.3 内核移植验证 - -- 2.2 Linux内核 - - - -#### 3 板级移植 [@waitForContributor](https://gitee.com/openharmony/docs/issues)[ ?] - - - -### 三、小型系统内核开发指南(LiteOS-A核)---招募内容体验&验证 - -#### 1 认识LiteOS-A内核 [@kkup180](https://gitee.com/kkup180) [✔] [@mgy917](https://gitee.com/mgy917) [✔] - - - -- 1.1 简介 -- 1.2 内核架构 -- 1.3 CPU体系架构支持 - -#### 2 基础内核 [@waitForContributor](https://gitee.com/openharmony/docs/issues)[ ?] - - - -- 2.1 中断及异常处理 -- 2.2 进程管理 -- 2.3 线程管理 -- 2.4 调度 -- 2.5 内存管理 - - 2.5.1 堆内存管理 - - 2.5.2 虚拟内存管理 - - 2.5.3 物理内存管理 - - 2.5.4 虚实映射 -- 2.6 IPC - - 2.6.1 事件 - - 2.6.2 信号量 - - 2.6.3 互斥锁 - - 2.6.4 消息队列 - - 2.6.5 读写锁 - - 2.6.6 futex - - 2.6.7 信号 -- 2.7 系统调用 -- 2.8 时间管理 -- 2.9 软件定时器 -- 2.10 原子操作 -#### 3 扩展组件 [@waitForContributor](https://gitee.com/openharmony/docs/issues)[ ?] - - - -- 3.1 ELF内核加载器 -- 3.2 VDSO -- 3.3 LiteIPC -- 3.4 CPUP -- 3.5 C++支持 -#### 4 文件系统 [@waitForContributor](https://gitee.com/openharmony/docs/issues)[ ?] - - - -- 4.1 vfs - -- 4.2 支持的文件系统 - - 4.2.1 FAT - - 4.2.2 jffs2 - - 4.2.3 nfs - - 4.2.4 ramfs - - 4.2.5 procfs -- 4.3 适配新的文件系统 -#### 5 内核启动 [@waitForContributor](https://gitee.com/openharmony/docs/issues)[ ?] -- 5.1 运行机制 -#### 6 用户态启动 [@waitForContributor](https://gitee.com/openharmony/docs/issues)[ ?] -- 6.1 用户态根进程启动 -- 6.2 用户态程序运行 -#### 7 调测 [@waitForContributor](https://gitee.com/openharmony/docs/issues)[ ?] - - - -- 7.1 内存调测 -- 7.2 Trace -- 7.3 魔法键 -- 7.4 Dying gasp -- 7.5 常见问题定位方法 -#### 8 附录 [@rtos_yuan](https://gitee.com/rtos_yuan) [✔] [@harylee](https://gitee.com/harylee)[✔] -- 8.1 基本数据结构 - - 8.1.1 双向链表 - - 8.1.2 位操作 - diff --git "a/zh-cn/device-dev/kernel-contribution/template/\345\270\270\350\247\201\351\227\256\351\242\230.md" "b/zh-cn/device-dev/kernel-contribution/template/\345\270\270\350\247\201\351\227\256\351\242\230.md" deleted file mode 100644 index 976524f98b..0000000000 --- "a/zh-cn/device-dev/kernel-contribution/template/\345\270\270\350\247\201\351\227\256\351\242\230.md" +++ /dev/null @@ -1,51 +0,0 @@ -# 常见问题 - -** *【写作要求】*** - - -*可选。描述开发过程遇到的各类问题以及解决方案,以提高开发效率。* - - -- * 如果无常见问题,删除此章节。* - -- * 如果有常见问题,建议单独章节,后续具备扩展性。* - -- * 如果有常见问题,问题少于1屏且未来扩充可能性不大,可放在“开发指导”。* - - -*具体写作要求见下,完成写作后,请逐项自检下。* - - -| 要求项 | 内容要求 | 是否满足 | -| -------- | -------- | -------- | -| **N1** | **整体要求** | | -| N1.1 | 问题是否对外呈现(考虑重要性、出现概率等),请在部门内部CCB达成一致。 | | -| N1.2 | 每个问题描述里一般只问一个问题,避免多个问题合在一个问题描述。 | | -| N1.3 | 如果问题比较多,可以对问题进行分类。 | | -| **N2** | **单个问题要求** | | -| N2.1 | 标题:1句话描述问题场景、现象。 | | -| N2.2 | 现象描述:以用户视角黑盒描述问题出现的场景、现象、条件、概率等。描述问题现象清晰,没有歧义。 | | -| N2.3 | 可能原因:明确问题根本的原因。 | | -| N2.4 | 处理步骤-1:明确处理问题的步骤,step by step操作,具体要求同“开发步骤”部分。 | | -| N2.5 | 处理步骤-2:答复必须是严谨、明确的解决方法,口径与产品宣传一致,不能是参考建议这类含糊的回答。 | | -| N2.6 | 处理步骤-3:如果问题与能力版本有关联性的,需要明确。 | | - - -## 1.XX问题(简单问题) - -XXX - - -## 2.XX问题(复杂问题) - -**现象描述** - -XXX - -**可能原因** - -XXX - -**解决办法** - -XXX diff --git "a/zh-cn/device-dev/kernel-contribution/template/\345\274\200\345\217\221\345\256\236\344\276\213.md" "b/zh-cn/device-dev/kernel-contribution/template/\345\274\200\345\217\221\345\256\236\344\276\213.md" deleted file mode 100644 index 54133ebda8..0000000000 --- "a/zh-cn/device-dev/kernel-contribution/template/\345\274\200\345\217\221\345\256\236\344\276\213.md" +++ /dev/null @@ -1,49 +0,0 @@ -# 开发实例 - -** *【写作要求】*** - - -*必选。描述开发完成后,基于一个任务整体做代码段的描述。* - - -- * 标题名称不变。如果“开发指导”是多场景,标题名称可以调整为拍照开发实例、预览开发指导等。* - -- * 标题可合并。如果产品链接到示例代码或内容少于1屏,可合并到“开发指导”,整本统一。* - - -*具体写作要求见下,完成写作后,请逐项自检下。* - - -| 要求项 | 内容要求 | 是否满足 | -| -------- | -------- | -------- | -| M1.1 | 有任务的场景介绍,且和代码端内容呼应。 | | -| M1.2 | 代码段顺利指导完成操作,无缺失。 | | -| M1.3 | 代码涉及开发者拷贝的命令,必须用可编辑的报文呈现,避免截图(DOCS插入Screen)。 | | -| M1.4 | 代码中关键段用蓝色(RGB:0.0.255)突出显示,关键步骤要有注释说明。 | | -| M1.5 | 代码显示符合代码缩进要求。 | | - - -**【写作样例---节选】** - - -SDIO设备完整的使用示例如下所示,首先打开总线号为1的SDIO控制器,然后独占HOST、使能设备、注册中断,接着进行SDIO通信(读写等),通信完成之后,释放中断、去使能设备、释放HOST,最后关闭SDIO控制器。 -``` -#include "hdf_log.h" -#include "sdio_if.h" - -#define TEST_FUNC_NUM 1 /* 本测试用例中,使用编号为1的I/O function */ -#define TEST_FBR_BASE_ADDR 0x100 /* 编号为1的I/O function的FBR基地址 */ -#define TEST_ADDR_OFFSET 9 /* 本测试用例中,需要读写的寄存器的地址偏移 */ -#define TEST_DATA_LEN 3 /* 本测试用例中,读写数据的长度 */ -#define TEST_BLOCKSIZE 2 /* 本测试用例中,数据块的大小,单位字节 */ - -/* 中断服务函数,需要根据各自平台的情况去实现 */ -static void SdioIrqFunc(void *data) -{ - if (data == NULL) { - HDF_LOGE("SdioIrqFunc: data is NULL.\n"); - return; - } - /* 需要开发者自行添加具体的实现 */ -} -``` diff --git "a/zh-cn/device-dev/kernel-contribution/template/\345\274\200\345\217\221\346\214\207\345\257\274.md" "b/zh-cn/device-dev/kernel-contribution/template/\345\274\200\345\217\221\346\214\207\345\257\274.md" deleted file mode 100644 index 2b4b6a3a93..0000000000 --- "a/zh-cn/device-dev/kernel-contribution/template/\345\274\200\345\217\221\346\214\207\345\257\274.md" +++ /dev/null @@ -1,128 +0,0 @@ -# 开发指导 - -** *【写作要求】*** - - -*必选。* *描述各个场景下,开发者如何完成开发任务。* *可根据多场景任务增加章节。写作要求见下,完成写作后,请逐项自检。* - - -| 要求项 | 内容要求 | 是否满足 | -| -------- | -------- | -------- | -| H.1.1 | 如果有多个场景,请写起多个“开发指导”章节,如音频播放开发指导、音量管理开发指导、短音播放开发指导。 | | -| H.1.2 | 标题尽量使用“动词+名词”的句式表述任务操作。 | | - - -## 场景介绍 - -** *【写作要求】*** - -*必选。* *描述在什么情景下解决什么问题,最终达到什么样的效果。*应用SCQA描述方法: - -- S:situation(情景),由大家都熟悉的的情景,事实引入。 - -- C:complication(冲突),但是实际情况往往和我们的要求有冲突。 - -- Q:question(疑问),怎么办? - -- A:answer(回答),我们的解决方案是 … - -*写作要求见下,完成写作后,请逐项自检。* - -| 要求项 | 内容要求 | 是否满足 | -| -------- | -------- | -------- | -| I.1.1 | 背景原因、什么时候在哪、做了什么操作、最终解决什么问题或操作效果都明确。 | | - -**【写作样例】** - -音频播放的主要工作是将音频数据转码为可听见的音频模拟信号并通过输出设备进行播放,同时对播放任务进行管理。 - - -## 接口说明 - -** *【写作要求】*** - -*必选。* *描述本开发指导相关的接口有哪些,旨在要开发者在开发前有大体了解,提升开发效率。* *写作要求见下,完成写作后,请逐项自检。* - -| 要求项 | 内容要求 | 是否满足 | -| -------- | -------- | -------- | -| J.1.1 | 不在本开发任务的接口无需提供。 | | -| J.1.2 | 如果接口太多,超过10个,可以提供主要的接口 | | - -**【写作样例】** - -音频播放开放能力如下:AudioRenderer类,具体的API详见接口文档。 - -**表1** 音频播放API接口功能介绍 - -| 接口名 | 描述 | -| -------- | -------- | -| AudioRenderer(AudioRendererInfo audioRendererInfo, PlayMode pm) throws IllegalArgumentException | 构造函数,设置播放相关音频参数和播放模式,使用默认播放设备 | -| AudioRenderer(AudioRendererInfo audioRendererInfo, PlayMode pm, AudioDeviceDescriptor outputDevice) throws IllegalArgumentException | 构造函数,设置播放相关音频参数、播放模式和播放设备 | -| boolean play() | 播放音频流 | -| boolean write(byte[] data, int offset, int size) | 将音频数据以byte流写入音频接收器以进行播放 | - - -## 开发步骤 - -** *【写作要求】*** - - * 必选。描述* *开发的整体过程,便于开发者快速完成开发。* * 具体 写作要求见下,完成写作后,请逐项自检下。* -| 要求项 | 内容要求 | 是否满足 | -| -------- | -------- | -------- | -| **K.1** | **如何写好步骤** | | -| K.1.1 | 步骤完整:提供必须的步骤,顺利指导完成操作,无缺失。 | | -| K.1.2 | 脉络清楚:文档逻辑清晰、合理。文档前面的概述、准备、操作围绕一条线描述,不能章节断裂或前后矛盾的现象。 | | -| K.1.3 | 任务句式:标题或句子尽量使用“动词+名词”的句式表述动作。 | | -| K.1.4 | 预防提前:操作过程中的限制、易错的、有潜在风险的,要提前描述,使用DOCS平台的“插入> 说明 > 须知”描述。 | | -| K.1.5 | 步骤清晰-1:无论步骤简单或复杂,都需要写步骤目的,即为什么做。 | | -| K.1.6 | 步骤清晰-2:明确在什么环境下,使用什么工具,做什么操作,怎么做该操作。 | | -| K.1.7 | 步骤具体:如果操作可选,要明确可选条件。 | | -| K.1.8 | 在开发步骤执行完成后,及时明确操作正确的标准。 | | -| **K.2** | **如何写好代码段** | | -| K.2.1 | 代码涉及开发者拷贝的命令,必须用可编辑的报文呈现,避免截图(DOCS插入Screen)。 | | -| K.2.2 | 代码中关键段用蓝色(RGB:0.0.255)突出显示,关键步骤要有注释说明。 | | -| K.2.3 | 代码显示符合代码缩进要求。 | | -| K.2.4 | 步骤涉及接口调用,清晰给出接口及其使用说明或示例代码,代码来源于具体实例。 | | - -**【写作样例】** - -1. 构造音频流参数的数据结构AudioStreamInfo,推荐使用AudioStreamInfo.Builder类来构造,模板如下,模板中设置的均为AudioStreamInfo.Builder类的默认值,根据音频流的具体规格来设置具体参数。 - ``` - AudioStreamInfo audioStreamInfo = new AudioStreamInfo.Builder().sampleRate( AudioStreamInfo.SAMPLE_RATE_UNSPECIFIED) .audioStreamFlag(AudioStreamInfo.AudioStreamFlag.AUDIO_STREAM_FLAG_NONE) .encodingFormat(AudioStreamInfo.EncodingFormat.ENCODING_INVALID) .channelMask(AudioStreamInfo.ChannelMask.CHANNEL_INVALID) .streamUsage(AudioStreamInfo.StreamUsage.STREAM_USAGE_UNKNOWN) .build(); - ``` - - 以真实的播放pcm流为例: - ``` - AudioStreamInfo audioStreamInfo = new AudioStreamInfo.Builder().sampleRate(44100)//44.1kHz .audioStreamFlag(AudioStreamInfo.AudioStreamFlag.AUDIO_STREAM_FLAG_MAY_DUCK)//混音 .encodingFormat(AudioStreamInfo.EncodingFormat.ENCODING_PCM_16BIT)//16-bit PCM .channelMask(AudioStreamInfo.ChannelMask.CHANNEL_OUT_STEREO)//双声道 .streamUsage(AudioStreamInfo.StreamUsage.STREAM_USAGE_MEDIA)//媒体类音频 .build(); - ``` - -2. 使用步骤1创建的音频流构建音频播放的参数结构AudioRendererInfo,推荐使用AudioRendererInfo.Builder类来构造,模板如下,模板中设置的均为AudioRendererInfo.Builder类的默认值,根据音频播放的具体规格来设置具体参数。 - ``` - AudioRendererInfo audioRendererInfo = new AudioRendererInfo.Builder().audioStreamInfo(audioStreamInfo) .audioStreamOutputFlag(AudioRendererInfo.AudioStreamOutputFlag.AUDIO_STREAM_OUTPUT_FLAG_NONE) .bufferSizeInBytes(0) .distributedDeviceId("") .isOffload(false) .sessionID(AudioRendererInfo.SESSION_ID_UNSPECIFIED) .build(); - ``` - - 以真实的播放pcm流为例: - ``` - AudioRendererInfo audioRendererInfo = new AudioRendererInfo.Builder().audioStreamInfo(audioStreamInfo) .audioStreamOutputFlag(AudioRendererInfo.AudioStreamOutputFlag.AUDIO_STREAM_OUTPUT_FLAG_DIRECT_PCM)//pcm格式的输出流 .bufferSizeInBytes(100) .distributedDeviceId("E54***5E8")//使用分布式设备E54***5E8播放 .isOffload(false)//false表示分段传输buffer并播放,true表示整个音频流一次性传输到HAL层播放 .build(); - ``` - -3. 根据要播放音频流指定PlayMode,不同的PlayMode在写数据时存在差异,详情见步骤7,其余播放流程是无区别的。并通过构造函数获取AudioRenderer类的实例化对象。 - .... - -4. 播放任务结束后,调用AudioRenderer实例化对象的release()释放资源。 - - -## 调测验证(可选) - -** *【写作要求】*** - -*可选。* *描述开发完成后,进行调测验证,确保最终操作成功。* *操作步骤要求同“开发指导”,其他具体写作要求见下,完成写作后,请逐项自检下。* - -| 要求项 | 内容要求 | 是否满足 | -| -------- | -------- | -------- | -| L1.1 | 仅进行最后的业务调测,每个小任务的操作结果,在开发步骤执行完成后,及时验证操作结果。 | | -| L1.2 | 明确开发成功标准。 | | - -**【写作样例---节选】** - -![1624266401415](C:\Users\LWX104~1\AppData\Local\Temp\1624266401415.png) diff --git "a/zh-cn/device-dev/kernel-contribution/template/\346\220\255\345\273\272\347\216\257\345\242\203.md" "b/zh-cn/device-dev/kernel-contribution/template/\346\220\255\345\273\272\347\216\257\345\242\203.md" deleted file mode 100644 index 743adf6abc..0000000000 --- "a/zh-cn/device-dev/kernel-contribution/template/\346\220\255\345\273\272\347\216\257\345\242\203.md" +++ /dev/null @@ -1,82 +0,0 @@ -# 搭建环境 - -** *【写作要求】*** - - -*条件必选。* *如果在快速入门里已提供此部分,此章节可以不提供。明确如何搭建开发环境(如开发工具、编译工具)*。 - - -## 环境要求 - -** *【写作要求】*** - -*必选。* *明确开发环境所需要的软硬件配置,* *旨在要用户提前准备环境。*如果软硬件内容比较多,可以再增加子标题。写作要求见下,完成写作后,请逐项自检。 - -| 要求项 | 内容要求 | 是否满足 | -| -------- | -------- | -------- | -| E.1.1 | 分别明确开发的软硬环境和手机的开发环境,下载路径。 | | -| E1.2 | 明确具体的版本号。 | | - - -**【写作样例】** - - -**表1** 环境要求 - -| 项目 | PC | 手机 | -| -------- | -------- | -------- | -| 硬件 | - 内存:8G及以上
    - 硬盘:100G及以上
    - 分辨率:1280\*800 | 处理器不低于kirin 980的华为手机 | -| 软件 | 操作系统:Windows10 64位  或 Mac 10。 | 系统软件版本不低于EMUI_10.0.0 | - - -## 安装环境 - -** *【写作要求】*** - -必选。描述安装环境的具体步骤,如果内容比较多,可以区分安装环境章节,如:安装编译基础环境、安装编译工具环境、安装gcc_riscv32(WLAN模组类编译工具链)。 - -写作要求见下,完成写作后,请逐项自检。 - -| 要求项 | 内容要求 | 是否满足 | -| -------- | -------- | -------- | -| **F.1** | **如何写好步骤** | | -| F.1.1 | 步骤完整:提供必须的步骤,顺利指导完成操作,无缺失。 | | -| F.1.2 | 脉络清楚:文档逻辑清晰、合理。文档前面的概述、准备、操作围绕一条线描述,不能章节断裂或前后矛盾的现象。 | | -| F.1.3 | 任务句式:标题或句子尽量使用“动词+名词”的句式表述动作。 | | -| F.1.4 | 预防提前:操作过程中的限制、易错的、有潜在风险的,要提前描述,使用DOCS平台的“插入> 说明 > 须知”描述。 | | -| F.1.5 | 步骤清晰-1:无论步骤简单或复杂,都需要写步骤目的,即为什么做。 | | -| F.1.6 | 步骤清晰-2:明确在什么环境下,使用什么工具,做什么操作,怎么做该操作。 | | -| F.1.7 | 步骤具体:如果操作可选,要明确可选条件。 | | -| F.1.8 | 在开发步骤执行完成后,及时明确操作正确的标准。 | | -| **F.2** | **如何写好代码段** | | -| F.2.1 | 代码涉及开发者拷贝的命令,必须用可编辑的报文呈现,避免截图(DOCS插入Screen)。 | | -| F.2.2 | 代码中关键段用蓝色(RGB:0.0.255)突出显示,关键步骤要有注释说明。 | | -| F.2.3 | 代码显示符合代码缩进要求。 | | -| F.2.4 | 步骤涉及接口调用,清晰给出接口及其使用说明或示例代码,代码来源于具体实例。 | | - -**【写作样例】** - -1. 双击下载的exe文件,进入DevEco Studio安装向导。 - -2. 配置DevEco Studio安装路径,点击Next。 - -3. 配置DevEco Studio安装选项,点击Next。 - - Create Desktop Shortcut:配置是否创建桌面快捷方式,根据操作系统位数进行选择。 - - Update PATH variable:配置是否将启动器路径添加到环境变量PATH中,需要从命令行启动DevEco Studio时,需要勾选Add launchers dir to the PATH。 - - Update context menu:配置是否将DevEco Studio功能添加至上下文菜单。勾选后,右键上下文菜单将出现“Open Folder as Project”选项。 - -4. 配置桌面快捷方式的开始菜单文件夹,点击Install。 - -5. 等待DevEco Studio安装完成后,点击Finish。 - - -## 检验环境是否搭建成功 - -** *【写作要求】*** - -*必选。* *环境搭建完成后,需要明确给出环境搭建是否成功的检验标准*。 - -| 要求项 | 内容要求 | 是否满足 | -| -------- | -------- | -------- | -| G.1.1 | 仅进行最后的结果验证,每个小任务的操作结果,在开发步骤执行完成后,及时验证操作结果。 | | -| G1.2 | 明确搭建成功的标准。 | | diff --git "a/zh-cn/device-dev/kernel-contribution/template/\346\246\202\350\277\260.md" "b/zh-cn/device-dev/kernel-contribution/template/\346\246\202\350\277\260.md" deleted file mode 100644 index c3ab6dfa23..0000000000 --- "a/zh-cn/device-dev/kernel-contribution/template/\346\246\202\350\277\260.md" +++ /dev/null @@ -1,169 +0,0 @@ -# 概述 - -* **【开发指南总体** **写作要求】*** - - -* 适用于鸿蒙南北向子系统开发、应用侧的设备开发、南向开发指南。* - - -* 章节调整:本模板知识点内容结构可以根据产品内容多少微调,具体操作方式见下。* - - -| 章节 | 可选/必选说明 | 备注 | -| -------- | -------- | -------- | -| 概述 | 必选,标题名称不变 | - | -| 搭建环境 | 可选,如果快速入门已有,可不用提供,否则需提供。 | - | -| 开发指导 | 必选,可根据多场景任务增加章节。 | 拍照开发指导
    预览开发指导
    录像开发指导 | -| 开发实例 | 必选。
    - 标题名称可自定义。如果“开发指导”是多场景,标题名称可以调整为拍照开发实例、预览开发实例等。
    - 标题可合并。如果产品链接到示例代码或内容少于1屏,可合并到“开发指导”,整本统一。 | - | -| 常见问题 | 可选,标题不变。
    - 如果无常见问题,删除此章节。
    - 如果有常见问题,建议单独章节,后续具备扩展性。
    - 如果有常见问题,问题少于1屏,未来扩充可能行不大,可放在“开发指导”。 | - | -| 参考 | 可选,根据实际需要补充。 | - | - - - * 整体写作要求见下,完成写作后,请逐项自检。* -| 要求项 | 内容要求 | 是否满足 | -| -------- | -------- | -------- | -| **A.1** | **用语要求** | | -| A.1.1 | 行文风格:文档在官方网站发布,用语正式,避免口语化。 | | -| A.1.2 | 合规要求:不能使用Android特有概念等存在合规和法务风险的词汇。敏感词汇包含但不限于:Android、Google、EMUI、Activity、AOSP、provider、binder、APK、Dalvik、AVD、ADT、DDMS、adb、AAPT、AndroidManifest、NDK、ART、dex、ANR、Cursor、Blacklist、Whitelist、Master、Slave、L0、L1、轻鸿蒙、富鸿蒙等。 | | -| A.1.3 | 内容简洁:内容采用信息必备、最小化原则,旨在指导开发者在尽量短的时间完成操作。 | | -| A.1.4 | 内容正确:文档的代码、需要设置的参数等需要跟产品实际情况实时保持一致。 | | -| A.1.5 | 用语准确:应当确切,不能出现多义性的描述。 | | -| A.1.6 | 用语一致:同一叫法,全文保持一致,术语与术语库保持一致,正文中缩略语首次出现要给出全称。 | | -| A.1.7 | 用语具体:如表示数量或程度时,避免用笼统的“多”“少”“大”,建议用具体数字表示。 | | -| **A.2** | **格式要求** | | -| A.2.1 | 标点符号正确、句尾有符号结尾。 | | -| A.2.2 | 内容尽量用项目列表或分类的方式清晰呈现。不要有单个项目列表;不要有多余空行。 | | -| A.2.3 | 英文字母和中文字之间不要有空格。 | | -| A.2.4 | 链接必须有效,具体,可直接跳转或下载。 | | -| A.2.5 | 如果是内容的辅助说明,请使用“说明”式样;如果提前申明事项,,请使用“须知”式样。To D的资料不用“注意”格式。 | | -| **A.3** | **表格** | | -| A.3.1 | 表格有表注,表头风格一致,采用名词或名词词组形式。 | | -| A.3.2 | 表格有表头,至少为2行2列,避免出现单行或单列表。 | | -| A.3.3 | 表格无内容用“_”,不出现空白的单元格。 | | -| **A.4** | **图形** | | -| A.4.2 | 符合华为调性,避免互联网化,避免涉及宗教信仰类截图。 | | -| A.4.3 | 图文并茂,行文应力求简明,如有可能,配以适当的图,表。 | | -| A.4.4 | 图形有图注(不可直接粘贴图形),图注风格一致,采用名词或名词词组形式。 | | -| A.4.5 | 图形应清晰可辩识,信息表达完整,易于阅读。如流程图不可缺少“开始”和“结束”。 | | -| A.4.6 | 图形逻辑清晰,图文配合使用,切忌图文分离。 | | -| A.4.7 | 图片的高度建议在640px左右,宽度不超过820px,一般为.png格式,图片的大小建议不超过150k。 | | -| A.4.8 | 图形建议尽量不要用文字,中文图用中文,英文图用英文。 | | - - -## 基本概念 - -*【 **写作要求】*** - -*必选,描述本开发任务相关的基本概念,帮助开发者更好的理解开发任务。* *写作要求见下,完成写作后,请逐项自检。* - -| 要求项 | 内容要求 | 是否满足 | -| -------- | -------- | -------- | -| B.1.1 | 业界通用的概念不用再此赘述。 | | -| B.1.2 | 注意使用业界通用术语来表达,不用华为研发内部语言。 | | -| B.1.3 | 基本概念要黑盒描述,不用体现具体细节。 | | - - -【写作样例】 - - -鸿蒙系统音频模块支持音频业务的开发,提供音频相关的功能,主要包括音频播放、音频采集、音量管理和短音播放等。 - - -在进行应用的开发前,开发者应了解以下基本概念: - - -- 采样 - 采样就是把模拟信号数字化的过程,所有的模拟信号都需要通过采样转换为可以用0101来表示的数字信号。 - -- 采样率 - 采样率为每秒从连续信号中提取并组成离散信号的采样次数,单位用赫兹(Hz)来表示。通常人耳能听到频率范围大约在20Hz~20kHz之间的声音。常用的音频采样频率有:8kHz、11.025kHz、22.05kHz、16kHz、37.8kHz、44.1kHz、48kHz、96kHz、192kHz等。 - -- 声道 - 声道是指声音在录制或播放时在不同空间位置采集或回放的相互独立的音频信号,所以声道数也就是声音录制时的音源数量或回放时相应的扬声器数量。 - -- 音频帧 - 音频数据是流式的,本身没有明确的一帧帧的概念,在实际的应用中,为了音频算法处理/传输的方便,一般约定俗成取2.5ms~60ms为单位的数据量为一帧音频。这个时间被称之为“采样时间”,其长度没有特别的标准,它是根据编解码器和具体应用的需求来决定的。 - - -## 运作机制 - -*【 **写作要求】*** - -*可选。如果机制比较简单,通过前面基本概念就可以说清楚,此章节可以不用提供,删除标题即可。* - -*描述实现原理介绍机制,如关键步骤相关接口调用时机和触发时机,帮助开发者了解该功能的基本运作原理,以便更好的理解开发任务和定位问题。* - -* 写作要求见下,完成写作后,请逐项自检。* - -| 要求项 | 内容要求 | 是否满足 | -| -------- | -------- | -------- | -| C.1.1 | 仅描述开发任务相关的原理。 | | -| C.1.2 | 尽量图文配合,一般使用时序图、流程图等形式。文字描述与图形描述匹配。 | | -| C.1.3 | 原理要黑盒描述,注意不要泄密。 | | - -【写作样例-1】 - -- 信号量初始化,为配置的N个信号量申请内存(N值可以由用户自行配置,受内存限制),并把所有的信号量初始化成未使用,并加入到未使用链表中供系统使用。 - -- 信号量创建,从未使用的信号量链表中获取一个信号量资源,并设定初值。 - -- 信号量申请,若其计数器值大于0,则直接减1返回成功。否则任务阻塞,等待其它任务释放该信号量,等待的超时时间可设定。当任务被一个信号量阻塞时,将该任务挂到信号量等待任务队列的队尾。 - -- 信号量释放,若没有任务等待该信号量,则直接将计数器加1返回。否则唤醒该信号量等待任务队列上的第一个任务。 - -- 信号量删除,将正在使用的信号量置为未使用信号量,并挂回到未使用链表。 - -- 信号量允许多个任务在同一时刻访问同一资源,但会限制同一时刻访问此资源的最大任务数目。访问同一资源的任务数达到该资源的最大数量时,会阻塞其他试图获取该资源的任务,直到有任务释放该信号量。 - ![1624266502700](C:\Users\LWX104~1\AppData\Local\Temp\1624266502700.png) - - 【写作样例-2】 - - **互斥锁运作原理** - - 多任务环境下会存在多个任务访问同一公共资源的场景,而有些公共资源是非共享的,需要任务进行独占式处理。互斥锁怎样来避免这种冲突呢? - - 用互斥锁处理非共享资源的同步访问时,如果有任务访问该资源,则互斥锁为加锁状态。此时其他任务如果想访问这个公共资源则会被阻塞,直到互斥锁被持有该锁的任务释放后,其他任务才能重新访问该公共资源,此时互斥锁再次上锁,如此确保同一时刻只有一个任务正在访问这个公共资源,保证了公共资源操作的完整性。 - - **图2** 互斥锁运作示意图 - ![1624266485662](C:\Users\LWX104~1\AppData\Local\Temp\1624266485662.png) - - -## 约束与限制 - -* **【写作要求】*** - -*必选。* *描述本开发任务过程中* *的约束条件,以及此操作约束带来相应的负面影响,包括但不限于如下几方面:* - -* **功能限制:*** - -- * 功能使用范围(明确不支持的场景)。* - -- *规格限制。* - -* **操作限制** **:*** - -- * 已知问题的操作。* - -- * 潜在风险的操作(如引起性能降低)。* - -- * 引起性能降低的操作*。 - -* 写作要求见下,完成写作后,请逐项自检。* - -| 要求项 | 内容要求 | 是否满足 | -| -------- | -------- | -------- | -| D.1.1 | 明确功能限制或操作限制。 | | -| D.1.2 | 约束对指导任务开发有影响或体验有感知,否则不用体现。 | | -| D.1.3 | 容易出错的操作在步骤里描述,不在此体现。 | | - -**【写作样例】** - -**互斥锁的约束与限制:** - -- 两个任务不能对同一把互斥锁加锁。如果某任务对已被持有的互斥锁加锁,则该任务会被挂起,直到持有该锁的任务对互斥锁解锁,才能执行对这把互斥锁的加锁操作。 - -- 互斥锁不能在中断服务程序中使用。 - -- Huawei LiteOS作为实时操作系统需要保证任务调度的实时性,尽量避免任务的长时间阻塞,因此在获得互斥锁之后,应该尽快释放互斥锁。 - -- 持有互斥锁的过程中,不得再调用LOS_TaskPriSet等接口更改持有互斥锁任务的优先级。 diff --git "a/zh-cn/device-dev/kernel/C++\346\224\257\346\214\201.md" "b/zh-cn/device-dev/kernel/C++\346\224\257\346\214\201.md" deleted file mode 100644 index 8608037257..0000000000 --- "a/zh-cn/device-dev/kernel/C++\346\224\257\346\214\201.md" +++ /dev/null @@ -1,86 +0,0 @@ -# C++支持 - -- [基本概念](#section11374125415814) - - [运行机制](#section125251720195) - -- [开发指导](#section166302407911) - - [接口说明](#section1881825119919) - - [开发流程](#section76371145108) - - [编程实例](#section994427141111) - - -## 基本概念 - -C++作为目前使用最广泛的编程语言之一,支持类、封装、重载等特性,是在C语言基础上开发的一种面向对象的编程语言。 - -### 运行机制 - -C++代码的识别主要由编译器支持,系统主要对全局对象进行构造函数调用,进行初始化操作。 - -## 开发指导 - -### 接口说明 - -**表 1** C++支持接口 - - - - - - - - - - - - -

    功能分类

    -

    接口名

    -

    描述

    -

    使用C++特性的前置条件

    -

    LOS_CppSystemInit

    -

    C++构造函数初始化

    -
    - -### 开发流程 - -使用C++特性之前,需要调用函数LOS\_CppSystemInit,实现C++构造函数初始化,其中被初始化的构造函数存在init\_array这个段中,段区间通过变量\_\_init\_array\_start\_\_、\_\_init\_array\_end\_\_传递。 - -**表 2** 参数说明 - - - - - - - - - - - - - -

    参数

    -

    参数说明

    -

    __init_array_start__

    -

    init_array段起始位置

    -

    __init_array_end__

    -

    init_array段结束位置

    -
    - ->![](public_sys-resources/icon-note.gif) **说明:** ->调用该函数时,一定要在c++业务前。另外部分与系统资源强相关的类或接口,如std::thread,std::mutex等,在三方编译器使用的c库非musl c时,存在兼容性问题,不建议使用。 - -### 编程实例 - -``` -void app_init(void) -{ -...... -/* 启动阶段C++初始化 */ -LOS_CppSystemInit((UINTPTR)&__init_array_start__, (UINTPTR)&__init_array_end__); -/* C++业务 */ -...... -} -``` - diff --git "a/zh-cn/device-dev/kernel/CMSIS\346\224\257\346\214\201.md" "b/zh-cn/device-dev/kernel/CMSIS\346\224\257\346\214\201.md" deleted file mode 100644 index 4f64bc6b8c..0000000000 --- "a/zh-cn/device-dev/kernel/CMSIS\346\224\257\346\214\201.md" +++ /dev/null @@ -1,487 +0,0 @@ -# CMSIS支持 - -- [基本概念](#section131091144111615) -- [开发指导](#section57653573161) - - [接口说明](#section1795910417173) - - [开发流程](#section48301225131720) - - [编程实例](#section524434761713) - - -## 基本概念 - -[CMSIS](https://developer.arm.com/tools-and-software/embedded/cmsis)是Cortex Microcontroller Software Interface Standard(Cortex微控制器软件接口标准)的缩写,是对于那些基于ARM Cortex处理器的微控制器独立于供应商的硬件抽象层。它包含多个组件层,其中之一是RTOS层,该层定义了一套通用及标准化的RTOS API接口,减少了应用开发者对特定RTOS的依赖,方便用户软件的移植重用。该套API有2个版本,分别为版本1(CMSIS-RTOS v1)和版本2(CMSIS-RTOS v2),OpenHarmony LiteOS-M仅提供其版本2的实现。 - -## 开发指导 - -### 接口说明 - -CMSIS-RTOS v2提供下面几种功能,接口详细信息可以查看API参考。 - -**表 1** CMSIS-RTOS v2接口 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    功能分类

    -

    接口名

    -

    描述

    -

    内核信息与控制

    -

    osKernelGetInfo

    -

    获取RTOS内核信息。

    -

    osKernelGetState

    -

    获取当前的RTOS内核状态。

    -

    osKernelGetSysTimerCount

    -

    获取RTOS内核系统计时器计数。

    -

    osKernelGetSysTimerFreq

    -

    获取RTOS内核系统计时器频率。

    -

    osKernelInitialize

    -

    初始化RTOS内核。

    -

    osKernelLock

    -

    锁定RTOS内核调度程序。

    -

    osKernelUnlock

    -

    解锁RTOS内核调度程序。

    -

    osKernelRestoreLock

    -

    恢复RTOS内核调度程序锁定状态。

    -

    osKernelResume

    -

    恢复RTOS内核调度程序。(暂未实现)

    -

    osKernelStart

    -

    启动RTOS内核调度程序。

    -

    osKernelSuspend

    -

    挂起RTOS内核调度程序。(暂未实现)

    -

    osKernelGetTickCount

    -

    获取RTOS内核滴答计数。

    -

    osKernelGetTickFreq

    -

    获取RTOS内核滴答频率。

    -

    线程管理

    -

    osThreadDetach

    -

    分离线程(线程终止时可以回收线程存储)。(暂未实现)

    -

    osThreadEnumerate

    -

    枚举活动线程。(暂未实现)

    -

    osThreadExit

    -

    终止当前正在运行的线程的执行。

    -

    osThreadGetCount

    -

    获取活动线程的数量。

    -

    osThreadGetId

    -

    返回当前正在运行的线程的线程ID。

    -

    osThreadGetName

    -

    获取线程的名称。

    -

    osThreadGetPriority

    -

    获取线程的当前优先级。

    -

    osThreadGetStackSize

    -

    获取线程的堆栈大小。

    -

    osThreadGetStackSpace

    -

    根据执行期间的堆栈水印记录获取线程的可用堆栈空间。

    -

    osThreadGetState

    -

    获取线程的当前线程状态。

    -

    osThreadJoin

    -

    等待指定线程终止。(暂未实现)

    -

    osThreadNew

    -

    创建一个线程并将其添加到活动线程中。

    -

    osThreadResume

    -

    恢复线程的执行。

    -

    osThreadSetPriority

    -

    更改线程的优先级。

    -

    osThreadSuspend

    -

    暂停执行线程。

    -

    osThreadTerminate

    -

    终止线程的执行。

    -

    osThreadYield

    -

    将控制权传递给处于就绪状态的下一个线程。

    -

    线程标志

    -

    osThreadFlagsSet

    -

    设置线程的指定线程标志。(暂未实现)

    -

    osThreadFlagsClear

    -

    清除当前正在运行的线程的指定线程标志。(暂未实现)

    -

    osThreadFlagsGet

    -

    获取当前正在运行的线程的当前线程标志。(暂未实现)

    -

    osThreadFlagsWait

    -

    等待当前正在运行的线程的一个或多个线程标志发出信号。(暂未实现)

    -

    事件标志

    -

    osEventFlagsGetName

    -

    获取事件标志对象的名称。(暂未实现)

    -

    osEventFlagsNew

    -

    创建并初始化事件标志对象。

    -

    osEventFlagsDelete

    -

    删除事件标志对象。

    -

    osEventFlagsSet

    -

    设置指定的事件标志。

    -

    osEventFlagsClear

    -

    清除指定的事件标志。

    -

    osEventFlagsGet

    -

    获取当前事件标志。

    -

    osEventFlagsWait

    -

    等待一个或多个事件标志被发出信号。

    -

    通用等待函数

    -

    osDelay

    -

    等待超时(时间延迟)。

    -

    osDelayUntil

    -

    等到指定时间。

    -

    计时器管理

    -

    osTimerDelete

    -

    删除计时器。

    -

    osTimerGetName

    -

    获取计时器的名称。(暂未实现)

    -

    osTimerIsRunning

    -

    检查计时器是否正在运行。

    -

    osTimerNew

    -

    创建和初始化计时器。

    -

    osTimerStart

    -

    启动或重新启动计时器。

    -

    osTimerStop

    -

    停止计时器。

    -

    互斥管理

    -

    osMutexAcquire

    -

    获取互斥或超时(如果已锁定)。

    -

    osMutexDelete

    -

    删除互斥对象。

    -

    osMutexGetName

    -

    获取互斥对象的名称。(暂未实现)

    -

    osMutexGetOwner

    -

    获取拥有互斥对象的线程。

    -

    osMutexNew

    -

    创建并初始化Mutex对象。

    -

    osMutexRelease

    -

    释放由osMutexAcquire获取的Mutex。

    -

    信号量

    -

    osSemaphoreAcquire

    -

    获取信号量令牌或超时(如果没有可用的令牌)。

    -

    osSemaphoreDelete

    -

    删除一个信号量对象。

    -

    osSemaphoreGetCount

    -

    获取当前信号量令牌计数。

    -

    osSemaphoreGetName

    -

    获取信号量对象的名称。(暂未实现)

    -

    osSemaphoreNew

    -

    创建并初始化一个信号量对象。

    -

    osSemaphoreRelease

    -

    释放信号量令牌,直到初始最大计数。

    -

    内存池

    -

    osMemoryPoolAlloc

    -

    从内存池分配一个内存块。

    -

    osMemoryPoolDelete

    -

    删除内存池对象。

    -

    osMemoryPoolFree

    -

    将分配的内存块返回到内存池。

    -

    osMemoryPoolGetBlockSize

    -

    获取内存池中的内存块大小。

    -

    osMemoryPoolGetCapacity

    -

    获取内存池中最大的内存块数。

    -

    osMemoryPoolGetCount

    -

    获取内存池中使用的内存块数。

    -

    osMemoryPoolGetName

    -

    获取内存池对象的名称。

    -

    osMemoryPoolGetSpace

    -

    获取内存池中可用的内存块数。

    -

    osMemoryPoolNew

    -

    创建并初始化一个内存池对象。

    -

    消息队列

    -

    osMessageQueueDelete

    -

    删除消息队列对象。

    -

    osMessageQueueGet

    -

    从队列获取消息,或者如果队列为空,则从超时获取消息。

    -

    osMessageQueueGetCapacity

    -

    获取消息队列中的最大消息数。

    -

    osMessageQueueGetCount

    -

    获取消息队列中排队的消息数。

    -

    osMessageQueueGetMsgSize

    -

    获取内存池中的最大消息大小。

    -

    osMessageQueueGetName

    -

    获取消息队列对象的名称。(暂未实现)

    -

    osMessageQueueGetSpace

    -

    获取消息队列中消息的可用插槽数。

    -

    osMessageQueueNew

    -

    创建和初始化消息队列对象。

    -

    osMessageQueuePut

    -

    如果队列已满,则将消息放入队列或超时。

    -

    osMessageQueueReset

    -

    将消息队列重置为初始空状态。(暂未实现)

    -
    - -### 开发流程 - -CMSIS-RTOS2组件可以作为库或源代码提供(下图显示了库)。通过添加CMSIS-RTOS2组件(通常是一些配置文件),可以将基于CMSIS的应用程序扩展为具有RTOS功能。只需包含cmsis\_os2.h头文件就可以访问RTOS API函数,这使用户应用程序能够处理RTOS内核相关事件,而在更换内核时无需重新编译源代码。 - -静态对象分配需要访问RTOS对象控制块定义。特定于实现的头文件(下图中的os\_xx .h)提供对此类控制块定义的访问。对于OpenHarmony LiteOS-M内核,由文件名以los\_开头的头文件提供,这些文件包含OpenHarmony LiteOS-M内核的这些定义。 - -![](figures/zh-cn_image_0000001121429646.png) - -### 编程实例 - -``` -#include ... -#include "cmsis_os2.h" - -/*---------------------------------------------------------------------------- - * 应用程序主线程 - *---------------------------------------------------------------------------*/ -void app_main (void *argument) { - // ... - for (;;) {} -} - -int main (void) { - // 系统初始化 - MySystemInit(); - // ... - - osKernelInitialize(); // 初始化CMSIS-RTOS - osThreadNew(app_main, NULL, NULL); // 创建应用程序主线程 - osKernelStart(); // 开始执行线程 - for (;;) {} -} -``` - diff --git a/zh-cn/device-dev/kernel/FAT-20.md b/zh-cn/device-dev/kernel/FAT-20.md deleted file mode 100644 index 7b8620cb01..0000000000 --- a/zh-cn/device-dev/kernel/FAT-20.md +++ /dev/null @@ -1,176 +0,0 @@ -# FAT - -- [基本概念](#section1772629121418) -- [开发指导](#section1149072811148) - - [驱动适配](#section19174939191414) - - [开发流程](#section131211626151513) - - [编程实例](#section206071303163) - - [实例描述](#section45337345313) - - [示例代码](#section119813171539) - - [结果验证](#section7987101232311) - - -## 基本概念 - -FAT文件系统是File Allocation Table(文件配置表)的简称,主要包括DBR区、FAT区、DATA区三个区域。其中,FAT区各个表项记录存储设备中对应簇的信息,包括簇是否被使用、文件下一个簇的编号、是否文件结尾等。FAT文件系统有FAT12、FAT16、FAT32等多种格式,其中,12、16、32表示对应格式中FAT表项的字节数。FAT文件系统支持多种介质,特别在可移动存储介质(U盘、SD卡、移动硬盘等)上广泛使用,使嵌入式设备和Windows、Linux等桌面系统保持很好的兼容性,方便用户管理操作文件。 - -OpenHarmony内核支持FAT12、FAT16与FAT32三种格式的FAT文件系统,具有代码量小、资源占用小、可裁切、支持多种物理介质等特性,并且与Windows、Linux等系统保持兼容,支持多设备、多分区识别等功能。OpenHarmony内核支持硬盘多分区,可以在主分区以及逻辑分区上创建FAT文件系统。 - -## 开发指导 - -### 驱动适配 - -FAT文件系统的使用需要底层MMC相关驱动的支持。在一个带MMC存储设备的板子上运行FATFS,需要: - -1、适配板端EMMC驱动,实现disk\_status、disk\_initialize、disk\_read、disk\_write、disk\_ioctl接口; - -2、新增fs\_config.h文件,配置FS\_MAX\_SS(存储设备最大sector大小)、FF\_VOLUME\_STRS(分区名)等信息,例如: - -``` -#define FF_VOLUME_STRS "system", "inner", "update", "user" -#define FS_MAX_SS 512 -#define FAT_MAX_OPEN_FILES 50 -``` - -### 开发流程 - ->![](public_sys-resources/icon-note.gif) **说明:** ->- FATFS文件与目录操作: -> - 单个文件大小不超过4G。 -> - 支持同时打开的文件数最大为FAT\_MAX\_OPEN\_FILES,文件夹数最大为FAT\_MAX\_OPEN\_DIRS。 -> - 暂不支持根目录管理,文件/目录名均以分区名开头,例如“user/testfile”就是在“user”分区下名为“testfile”的文件或目录。 -> - 若需要同时多次打开同一文件,必须全部使用只读方式(O\_RDONLY)。以可写方式(O\_RDWR、O\_WRONLY等)只能打开一次。 -> - 读写指针未分离,例如以O\_APPEND(追加写)方式打开文件后,读指针也在文件尾,从头读文件前需要用户手动置位。 -> - 暂不支持文件与目录的权限管理。 -> - stat及fstat接口暂不支持查询修改时间、创建时间和最后访问时间。微软FAT协议不支持1980年以前的时间。 ->- FATFS分区挂载与卸载: -> - 支持以只读属性挂载分区。当mount函数的入参为MS\_RDONLY时,所有的带有写入的接口,如write、mkdir、unlink,以及非O\_RDONLY属性的open,将均被拒绝。 -> - mount支持通过MS\_REMOUNT标记修改已挂载分区的权限。 -> - 在umount操作前,需确保所有目录及文件全部关闭。 -> - umount2支持通过MNT\_FORCE参数强制关闭所有文件与文件夹并umount,但可能造成数据丢失,请谨慎使用。 ->- FATFS支持重新划分存储设备分区、格式化分区,对应接口为fatfs\_fdisk与fatfs\_format: -> - 在fatfs\_format操作之前,若需要格式化的分区已挂载,需确保分区中的所有目录及文件全部关闭,并且分区umount。 -> - 在fatfs\_fdisk操作前,需要该设备中的所有分区均已umount。 -> - fatfs\_fdisk与fatfs\_format会造成设备数据丢失,请谨慎使用。 - -### 编程实例 - -### 实例描述 - -本实例实现以下功能: - -1. 创建目录“user/test” -2. 在“user/test”目录下创建文件“file.txt” -3. 在文件起始位置写入“Hello OpenHarmony!” -4. 将文件内容刷入设备中 -5. 设置偏移到文件起始位置 -6. 读取文件内容 -7. 关闭文件 -8. 删除文件 -9. 删除目录 - -### 示例代码 - -前提条件: - -- 系统已将MMC设备分区挂载到user目录 - -代码实现如下: - -``` -#include -#include -#include "sys/stat.h" -#include "fcntl.h" -#include "unistd.h" - -#define LOS_OK 0 -#define LOS_NOK -1 - -int FatfsTest(void) -{ - int ret; - int fd = -1; - ssize_t len; - off_t off; - char dirName[20] = "user/test"; - char fileName[20] = "user/test/file.txt"; - char writeBuf[20] = "Hello OpenHarmony!"; - char readBuf[20] = {0}; - - /* 创建目录“user/test” */ - ret = mkdir(dirName, 0777); - if (ret != LOS_OK) { - printf("mkdir failed.\n"); - return LOS_NOK; - } - - /* 创建可读写文件"user/test/file.txt" */ - fd = open(fileName, O_RDWR | O_CREAT, 0777); - if (fd < 0) { - printf("open file failed.\n"); - return LOS_NOK; - } - - /* 将writeBuf中的内容写入文件 */ - len = write(fd, writeBuf, strlen(writeBuf)); - if (len != strlen(writeBuf)) { - printf("write file failed.\n"); - return LOS_NOK; - } - - /* 将文件内容刷入存储设备中 */ - ret = fsync(fd); - if (ret != LOS_OK) { - printf("fsync failed.\n"); - return LOS_NOK; - } - - /* 将读写指针偏移至文件头 */ - off = lseek(fd, 0, SEEK_SET); - if (off != 0) { - printf("lseek failed.\n"); - return LOS_NOK; - } - - /* 将文件内容读出至readBuf中,读取长度为readBuf大小 */ - len = read(fd, readBuf, sizeof(readBuf)); - if (len != strlen(writeBuf)) { - printf("read file failed.\n"); - return LOS_NOK; - } - printf("%s\n", readBuf); - - /* 关闭文件 */ - ret = close(fd); - if (ret != LOS_OK) { - printf("close failed.\n"); - return LOS_NOK; - } - - /* 删除文件"user/test/file.txt" */ - ret = unlink(fileName); - if (ret != LOS_OK) { - printf("unlink failed.\n"); - return LOS_NOK; - } - - /* 删除目录“user/test” */ - ret = rmdir(dirName); - if (ret != LOS_OK) { - printf("rmdir failed.\n"); - return LOS_NOK; - } - - return LOS_OK; -} -``` - -### 结果验证 - -编译运行得到的结果为: - -``` -Hello OpenHarmony! -``` - diff --git a/zh-cn/device-dev/kernel/IPC.md b/zh-cn/device-dev/kernel/IPC.md deleted file mode 100644 index 14c3d35d89..0000000000 --- a/zh-cn/device-dev/kernel/IPC.md +++ /dev/null @@ -1,11 +0,0 @@ -# IPC - -- **[事件](事件.md)** - -- **[互斥锁](互斥锁.md)** - -- **[消息队列](消息队列.md)** - -- **[信号量](信号量.md)** - - diff --git "a/zh-cn/device-dev/kernel/Linux\345\206\205\346\240\270\347\274\226\350\257\221\344\270\216\346\236\204\345\273\272\346\214\207\345\257\274.md" "b/zh-cn/device-dev/kernel/Linux\345\206\205\346\240\270\347\274\226\350\257\221\344\270\216\346\236\204\345\273\272\346\214\207\345\257\274.md" deleted file mode 100755 index 1dec4cb144..0000000000 --- "a/zh-cn/device-dev/kernel/Linux\345\206\205\346\240\270\347\274\226\350\257\221\344\270\216\346\236\204\345\273\272\346\214\207\345\257\274.md" +++ /dev/null @@ -1,47 +0,0 @@ -# Linux内核编译与构建指导 - -- [开发示例1](#section19369206113115) - - [场景1:版本级编译原生方式](#section1025111193220) - - [场景2:单独编译修改后的内核](#section17446652173211) - - -## 开发示例1 - -以hi3516dv300开源开发板+ubuntu x86主机开发环境为例。 - -### 场景1:版本级编译原生方式 - -使用工程的全量编译命令,编译生成uImage内核镜像 - -``` -./build.sh --product-name Hi3516DV300 # 编译hi3516dv300的uImage内核镜像 -``` - -### 场景2:单独编译修改后的内核 - -1. 准备工作 - - 1. 按[开发板Patch使用指导](OpenHarmony开发板Patch使用指导.md)打入所需补丁。 - 2. 准备编译环境,可以使用开源arm clang/gcc编译器。 - - 进入工程主目录配置环境变量: - - ``` - export PATH=`pwd`/prebuilts/clang/host/linux-x86/clang-r353983c/bin:`pwd`/prebuilts/gcc/linux-x86/arm/gcc-linaro-7.5.0-arm-linux-gnueabi/bin/:$PATH # 配置编译环境 - MAKE_OPTIONES="ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- CC=clang HOSTCC=clang" # 使用工程项目自带的clang环境 - ``` - -2. 修改内核代码或内核config (OpenHarmony提供对应平台的defconfig供参考)。 -3. 创建编译目录及生成内核.config。 - - ``` - make ${MAKE_OPTIONES} hi3516dv300_emmc_smp_hos_l2_defconfig # 使用自带的默认config 构建内核 - ``` - -4. 编译生成对应的内核Image。 - - ``` - make ${MAKE_OPTIONES} -j32 uImage # 编译uImage内核镜像 - ``` - - diff --git a/zh-cn/device-dev/kernel/LittleFS.md b/zh-cn/device-dev/kernel/LittleFS.md deleted file mode 100644 index 1f8ad2cec8..0000000000 --- a/zh-cn/device-dev/kernel/LittleFS.md +++ /dev/null @@ -1,7 +0,0 @@ -# LittleFS - -- **[基本概念](基本概念-21.md)** - -- **[开发指导](开发指导-22.md)** - - diff --git a/zh-cn/device-dev/kernel/NFS.md b/zh-cn/device-dev/kernel/NFS.md deleted file mode 100755 index d319329c44..0000000000 --- a/zh-cn/device-dev/kernel/NFS.md +++ /dev/null @@ -1,163 +0,0 @@ -# NFS - -- [概述](#section18322139164413) -- [注意事项](#section532912331467) -- [开发指导](#section166873374711) - -## 概述 - -NFS是Network File System(网络文件系统)的缩写。它最大的功能是可以通过网络,让不同的机器、不同的操作系统彼此分享其他用户的文件。因此,用户可以简单地将它看做是一个文件系统服务,在一定程度上相当于Windows环境下的共享文件夹。 - -NFS客户端用户,能够将网络远程的NFS服务端分享的目录挂载到本地端的机器中,运行程序和共享文件,但不占用当前的系统资源,所以,在本地端的机器看起来,远程服务端的目录就好像是自己的一个磁盘一样。 - -## 注意事项 - -- 当前NFS文件不支持权限控制,请在创建NFS目录和文件时使用777权限。 - -- 当前NFS文件不支读阻塞和写阻塞。 - -- 当前NFS文件不支持信号功能。 - -- 当前NFS文件系统mount路径长度(不包含IP的长度)不超过255个字符,超过时返回ENAMETOOLONG错误。 - -- 当前NFS文件支持的操作有:open, close, read, write, seek, dup, dup2, sync, opendir, closedir, readdir, readdir\_r, rewinddir, scandir, statfs, remove, unlink, mkdir, rmdir, rename, stat, stat64, seek64, mmap, mount, umount。 - -- 当前NFS支持TCP和UDP两种传输层协议,默认使用TCP。 - -- open打开一个文件,参数有O\_TRUNC时,必须同时拥有写的权限,才会将文件中的内容清空。 - -- 在文件未关闭的情况下,rename\(\)函数重命名A为B之后,不会改变文件fd。 - -- NFS功能目前处于beta测试阶段,可能存在功能不稳定的情况,建议您不要用于正式商用产品当中。 - - -## 开发指导 - -1. **搭建NFS服务器**。 - - 这里以Ubuntu操作系统为例,说明服务器端设置步骤。 - - 1. 安装NFS服务器软件。 - - 设置好Ubuntu系统的下载源,保证网络连接好的情况下执行: - - ``` - sudo apt-get install nfs-kernel-server - ``` - - 2. 创建用于挂载的目录并设置完全权限 - - ``` - mkdir /home/sqbin/nfs - sudo chmod 777 /home/sqbin/nfs - ``` - - 3. 设置和启动NFS server。 - - 修改NFS配置文件/etc/exports,添加如下一行: - - ``` - /home/sqbin/nfs *(rw,no_root_squash,async) - ``` - - 其中/home/sqbin/nfs是NFS共享的根目录。 - - 执行以下命令启动NFS server: - - ``` - sudo /etc/init.d/nfs-kernel-server start - ``` - - 执行以下命令重启NFS server: - - ``` - sudo /etc/init.d/nfs-kernel-server restart - ``` - - -2. **设置单板为NFS客户端**。 - - 本指导中的NFS客户端指运行OpenHarmony内核的设备。 - - 1. 硬件连接设置。 - - OpenHarmony内核设备连接到NFS服务器的网络。设置两者IP,使其处于同一网段。比如,设置NFS服务器的IP为10.67.212.178/24,设置OpenHarmony内核设备IP为10.67.212.3/24,注意:此IP为内网私有IP地址,用户使用时有差异,以用户实际IP为准。 - - OpenHarmony内核设备上的IP信息可通过ifconfig命令查看。 - - 2. 启动网络,确保单板到NFS服务器之间的网络通畅。 - - 启动以太网或者其他类型网络,使用ping命令检查到服务器的网络是否通畅。 - - ``` - OHOS # ping 10.67.212.178 - [0]Reply from 10.67.212.178: time=1ms TTL=63 - [1]Reply from 10.67.212.178: time=0ms TTL=63 - [2]Reply from 10.67.212.178: time=1ms TTL=63 - [3]Reply from 10.67.212.178: time=1ms TTL=63 - --- 10.67.212.178 ping statistics --- - 4 packets transmitted, 4 received, 0 loss - ``` - - 客户端NFS初始化,运行命令: - - ``` - OHOS # mkdir /nfs - OHOS # mount 10.67.212.178:/home/sqbin/nfs /nfs nfs 1011 1000 - ``` - - 将从串口得到如下回应信息,表明初始化NFS客户端成功。 - - ``` - OHOS # mount 10.67.212.178:/home/sqbin/nfs /nfs nfs 1011 1000 - Mount nfs on 10.67.212.178:/home/sqbin/nfs, uid:1011, gid:1000 - Mount nfs finished. - ``` - - 该命令将服务器10.67.212.178上的/home/sqbin/nfs目录mount在OpenHarmony内核设备上的/nfs上。 - - >![](public_sys-resources/icon-note.gif) **说明:** - >本例默认nfs server已经配置可用,即示例中服务器10.67.212.178上的/home/sqbin/nfs已配置可访问。 - - mount命令的格式为: - - ``` - mount nfs - ``` - - 其中“SERVER\_IP“表示服务器的IP地址;“SERVER\_PATH“表示服务器端NFS共享目录路径;“CLIENT\_PATH“表示设备上的NFS路径。 - - 如果不想有NFS访问权限限制,请在Linux命令行将NFS根目录权限设置成777: - - ``` - chmod -R 777 /home/sqbin/nfs - ``` - - 至此,NFS客户端设置完毕。NFS文件系统已成功挂载。 - - -3. **利用NFS共享文件**。 - - 在NFS服务器下新建目录dir,并保存。在OpenHarmony内核下运行ls命令: - - ``` - OHOS # ls /nfs - ``` - - 则可从串口得到如下回应: - - ``` - OHOS # ls /nfs - Directory /nfs: - drwxr-xr-x 0 u:0 g:0 dir - ``` - - 可见,刚刚在NFS服务器上新建的dir目录已同步到客户端\(OpenHarmony内核系统\)的/nfs目录,两者保持同步。 - - 同样地,在客户端\(OpenHarmony内核系统\)上创建文件和目录,在NFS服务器上也可以访问,读者可自行体验。 - - **平台差异性:** - - 目前,NFS客户端仅支持NFS v3部分规范要求,因此对于规范支持不全的服务器,无法完全兼容。在开发测试过程中,建议使用Linux的NFS server,因为其对NFS支持很完善。 - - diff --git "a/zh-cn/device-dev/kernel/OpenHarmony\345\274\200\345\217\221\346\235\277Patch\344\275\277\347\224\250\346\214\207\345\257\274.md" "b/zh-cn/device-dev/kernel/OpenHarmony\345\274\200\345\217\221\346\235\277Patch\344\275\277\347\224\250\346\214\207\345\257\274.md" deleted file mode 100755 index 25eadc954a..0000000000 --- "a/zh-cn/device-dev/kernel/OpenHarmony\345\274\200\345\217\221\346\235\277Patch\344\275\277\347\224\250\346\214\207\345\257\274.md" +++ /dev/null @@ -1,17 +0,0 @@ -# OpenHarmony开发板Patch使用指导 - -Patch文件位于工程项目源码路径:kernel/linux/patches/linux-4.19,存放特定芯片架构驱动补丁。 - -如需使用特定芯片平台驱动的Patch,需要在内核仓代码完成对芯片平台驱动补丁合入。 - -合入芯片平台驱动补丁,针对不同芯片平台合入对应的patch: - -以Hi3516dv300为例: - -``` -patch -p1 < device/hisilicon/hi3516dv300/sdk_linux/open_source/linux/hisi_linux-4.19_hos_l2.patch -``` - ->![](public_sys-resources/icon-notice.gif) **须知:** ->由于OpenHarmony的编译构建流程中会拷贝kernel/linux-4.19的代码环境后进行打补丁动作,在使用OpenHarmony的版本级编译命令前,需要kernel/linux-4.19保持原代码环境。 - diff --git a/zh-cn/device-dev/kernel/Readme-CN.md b/zh-cn/device-dev/kernel/Readme-CN.md index 8b5a59ad1b..3149ba1128 100755 --- a/zh-cn/device-dev/kernel/Readme-CN.md +++ b/zh-cn/device-dev/kernel/Readme-CN.md @@ -1,166 +1,152 @@ # 内核使用指南 -- [轻量和小型系统内核](轻量和小型系统内核.md) - - [轻量系统内核](轻量系统内核.md) - - [基础内核](基础内核.md) - - [进程](进程.md) - - [线程](线程.md) - - [内存](内存.md) - - [网络](网络.md) - - - [文件系统](文件系统.md) - - [VFS](VFS.md) - - [NFS](NFS.md) - - [RAMFS](RAMFS.md) - - [FAT](FAT.md) - - [JFFS2](JFFS2.md) - - - [标准库](标准库.md) - - [标准库](标准库-0.md) - - [与Linux标准库的差异](与Linux标准库的差异.md) - - - [调测](调测.md) - - [Shell介绍](Shell介绍.md) - - [Shell命令开发指导](Shell命令开发指导.md) - - [Shell命令编程实例](Shell命令编程实例.md) - - [Shell命令使用详解](Shell命令使用详解.md) - - [系统命令](系统命令.md) - - [cpup](cpup.md) - - [date](date.md) - - [dmesg](dmesg.md) - - [exec](exec.md) - - [free](free.md) - - [help](help.md) - - [hwi](hwi.md) - - [kill](kill.md) - - [log](log.md) - - [memcheck](memcheck.md) - - [oom](oom.md) - - [pmm](pmm.md) - - [reset](reset.md) - - [sem](sem.md) - - [stack](stack.md) - - [su](su.md) - - [swtmr](swtmr.md) - - [systeminfo](systeminfo.md) - - [task](task.md) - - [uname](uname.md) - - [vmm](vmm.md) - - [watch](watch.md) - - - [文件命令](文件命令.md) - - [cat](cat.md) - - [cd](cd.md) - - [chgrp](chgrp.md) - - [chmod](chmod.md) - - [chown](chown.md) - - [cp](cp.md) - - [format](format.md) - - [ls](ls.md) - - [lsfd](lsfd.md) - - [mkdir](mkdir.md) - - [mount](mount.md) - - [partinfo](partinfo.md) - - [partition](partition.md) - - [pwd](pwd.md) - - [rm](rm.md) - - [rmdir](rmdir.md) - - [statfs](statfs.md) - - [sync](sync.md) - - [touch](touch.md) - - [writeproc](writeproc.md) - - [umount](umount.md) - - - [网络命令](网络命令.md) - - [arp](arp.md) - - [dhclient](dhclient.md) - - [dns](dns.md) - - [ifconfig](ifconfig.md) - - [ipdebug](ipdebug.md) - - [netstat](netstat.md) - - [ntpdate](ntpdate.md) - - [ping](ping.md) - - [ping6](ping6.md) - - [telnet](telnet.md) - - [tftp](tftp.md) - - - [魔法键使用方法](魔法键使用方法.md) - - [用户态异常信息说明](用户态异常信息说明.md) - - - [小型系统内核](小型系统内核.md) - - [认识LiteOS-M内核](认识LiteOS-M内核.md) - - [快速入门](快速入门.md) - - [基础内核](基础内核-1.md) - - [中断管理](中断管理.md) - - [基本概念](基本概念.md) - - [开发指导](开发指导.md) - - - [任务管理](任务管理.md) - - [基本概念](基本概念-2.md) - - [开发指导](开发指导-3.md) - - - [内存管理](内存管理.md) - - [基本概念](基本概念-4.md) - - [静态内存](静态内存.md) - - [动态内存](动态内存.md) - - - [IPC](IPC.md) - - [事件](事件.md) - - [基本概念](基本概念-5.md) - - [开发指导](开发指导-6.md) - - - [互斥锁](互斥锁.md) - - [基本概念](基本概念-7.md) - - [开发指导](开发指导-8.md) - - - [消息队列](消息队列.md) - - [基本概念](基本概念-9.md) - - [开发指导](开发指导-10.md) - - - [信号量](信号量.md) - - [基本概念](基本概念-11.md) - - [开发指导](开发指导-12.md) - - - [时间管理](时间管理.md) - - [基本概念](基本概念-13.md) - - [开发指导](开发指导-14.md) - - - [软件定时器](软件定时器.md) - - [基本概念](基本概念-15.md) - - [开发指导](开发指导-16.md) - - - [扩展组件](扩展组件.md) - - [C++支持](C++支持.md) - - [CPUP](CPUP.md) - - [基本概念](基本概念-17.md) - - [开发指导](开发指导-18.md) - - - [文件系统](文件系统-19.md) - - [FAT](FAT-20.md) - - [LittleFS](LittleFS.md) - - [基本概念](基本概念-21.md) - - [开发指导](开发指导-22.md) - - - [内核调测](内核调测.md) - - [内存调测](内存调测.md) - - [内存信息统计](内存信息统计.md) - - [内存泄漏检测](内存泄漏检测.md) - - [踩内存检测](踩内存检测.md) - - - [异常调测](异常调测.md) - - [Trace调测](Trace调测.md) - - - [附录](附录.md) - - [内核编码规范](内核编码规范.md) - - [基本数据结构](基本数据结构.md) - - [双向链表](双向链表.md) - - - [标准库支持](标准库支持.md) - - [CMSIS支持](CMSIS支持.md) - - [POSIX支持](POSIX支持.md) - -- [标准系统内核](标准系统内核.md) - - [Linux内核概述](Linux内核概述.md) - - [OpenHarmony开发板Patch使用指导](OpenHarmony开发板Patch使用指导.md) - - [Linux内核编译与构建指导](Linux内核编译与构建指导.md) +- [轻量和小型系统内核](kernel-lite.md) + + - [轻量系统内核](kernel-lite-mini.md) + - [内核概述](kernel-lite-mini-m.md) + - [基础内核](kernel-lite-mini-basic.md) + - [中断管理](kernel-lite-mini-basic-interrupt.md) + - [基本概念](kernel-lite-mini-basic-interrupt-concept.md) + - [开发指导](kernel-lite-mini-basic-interrupt-guide.md) + - [任务管理](kernel-lite-mini-basic-task.md) + - [基本概念](kernel-lite-mini-basic-task-basic.md) + - [开发指导](kernel-lite-mini-basic-task-guide.md) + - [内存管理](kernel-lite-mini-basic-memory.md) + - [基本概念](kernel-lite-mini-basic-memory-basic.md) + - [静态内存](kernel-lite-mini-basic-memory-static.md) + - [动态内存](kernel-lite-mini-basic-memory-dynamic.md) + - [内核通信机制](kernel-lite-mini-basic-ipc.md) + - [事件](kernel-lite-mini-basic-ipc-event.md) + - [基本概念](kernel-lite-mini-basic-ipc-event-guide.md) + - [开发指导](kernel-lite-mini-basic-ipc-event-basic.md) + - [互斥锁](kernel-lite-mini-basic-ipc-mutex.md) + - [基本概念](kernel-lite-mini-basic-ipc-mutex-basic.md) + - [开发指导](kernel-lite-mini-basic-ipc-mutex-guide.md) + - [消息队列](kernel-lite-mini-basic-ipc-queue.md) + - [基本概念](kernel-lite-mini-basic-ipc-queue-basic.md) + - [开发指导](kernel-lite-mini-basic-ipc-queue-guide.md) + - [信号量](kernel-lite-mini-basic-ipc-sem.md) + - [基本概念](kernel-lite-mini-basic-ipc-sem-basic.md) + - [开发指导](kernel-lite-mini-basic-ipc-sem-guide.md) + - [时间管理](kernel-lite-basic-mini-time.md) + - [基本概念](kernel-lite-mini-basic-time-basic.md) + - [开发指导](kernel-lite-mini-basic-time-guide.md) + - [软件定时器](kernel-lite-mini-basic-soft.md) + - [基本概念](kernel-lite-mini-basic-soft-basic.md) + - [开发指导](kernel-lite-mini-basic-soft-guide.md) + - [扩展组件](kernel-lite-mini-extend.md) + - [C++支持](kernel-lite-mini-extend-support.md) + - [CPU占用率](kernel-lite-mini-extend-cpup.md) + - [基本概念](kernel-lite-mini-extend-cpup-basic.md) + - [开发指导](kernel-lite-mini-extend-cpup-guide.md) + - [文件系统](kernel-lite-mini-extend-file.md) + - [FAT](kernel-lite-mini-extend-file-fat.md) + - [LittleFS](kernel-lite-mini-extend-file-lit.md) + - [基本概念](kernel-lite-mini-extend-file-lit-basic.md) + - [开发指导](kernel-lite-mini-extend-file-lit-guide.md) + - [内核调测](kernel-lite-mini-inner.md) + - [内存调测](kernel-lite-mini-inner-debug.md) + - [内存信息统计](kernel-lite-mini-inner-debug-mes.md) + - [内存泄漏检测](kernel-lite-mini-inner-debug-det.md) + - [踩内存检测](kernel-lite-mini-inner-debug-cet.md) + - [异常调测](kernel-lite-mini-inner-exception.md) + - [Trace调测](kernel-lite-mini-inner-trace.md) + - [附录](kernel-lite-mini-app.md) + - [内核编码规范](kernel-lite-mini-app-code.md) + - [基本数据结构](kernel-lite-mini-app-data.md) + - [双向链表](kernel-lite-mini-app-data-list.md) + - [标准库支持](kernel-lite-mini-app-lib.md) + - [CMSIS支持](kernel-lite-mini-app-lib-cmsis.md) + - [POSIX支持](kernel-lite-mini-app-lib-posix.md) + + - [小型系统内核](kernel-lite-small.md) + - [基础内核](kernel-lite-small-basic.md) + - [进程](kernel-lite-small-process.md) + - [线程](kernel-lite-small-thread.md) + - [内存](kernel-lite-small-memory.md) + - [网络](kernel-lite-small-net.md) + + - [文件系统](kernel-lite-small-file.md) + - [VFS](kernel-lite-small-file-vfs.md) + - [NFS](kernel-lite-small-file-nfs.md) + - [RAMFS](kernel-lite-small-file-ramfs.md) + - [FAT](kernel-lite-small-file-fat.md) + - [JFFS2](kernel-lite-small-file-jffs.md) + + - [标准库](kernel-lite-small-lib.md) + - [标准库](kernel-lite-small-lib-standard.md) + - [与Linux标准库的差异](kernel-lite-small-lib-differ.md) + + - [调测](kernel-lite-small-shell.md) + - [Shell介绍](kernel-lite-small-shell-des.md) + - [Shell命令开发指导](kernel-lite-small-shell-guide.md) + - [Shell命令编程实例](kernel-lite-small-shell-sample.md) + - [Shell命令使用详解](kernel-lite-small-shell-cmd.md) + - [系统命令](kernel-lite-small-shell-cmd-sys.md) + - [cpup](kernel-lite-small-shell-cmd-sys-cpup.md) + - [date](kernel-lite-small-shell-cmd-sys-date.md) + - [dmesg](kernel-lite-small-shell-cmd-sys-demsg.md) + - [exec](kernel-lite-small-shell-cmd-sys-exec.md) + - [free](kernel-lite-small-shell-cmd-sys-free.md) + - [help](kernel-lite-small-shell-cmd-sys-help.md) + - [hwi](kernel-lite-small-shell-cmd-sys-hwi.md) + - [kill](kernel-lite-small-shell-cmd-sys-kill.md) + - [log](kernel-lite-small-shell-cmd-sys-log.md) + - [memcheck](kernel-lite-small-shell-cmd-sys-mem.md) + - [oom](kernel-lite-small-shell-cmd-sys-oom.md) + - [pmm](kernel-lite-small-shell-cmd-sys-pmm.md) + - [reset](kernel-lite-small-shell-cmd-sys-reset.md) + - [sem](kernel-lite-small-shell-cmd-sys-sem.md) + - [stack](kernel-lite-small-shell-cmd-sys-stack.md) + - [su](kernel-lite-small-shell-cmd-sys-su.md) + - [swtmr](kernel-lite-small-shell-cmd-sys-swymr.md) + - [systeminfo](kernel-lite-small-shell-cmd-sys-sys.md) + - [task](kernel-lite-small-shell-cmd-sys-task.md) + - [uname](kernel-lite-small-shell-cmd-sys-uname.md) + - [vmm](kernel-lite-small-shell-cmd-sys-vmm.md) + - [watch](kernel-lite-small-shell-cmd-sys-watch.md) + + - [文件命令](kernel-lite-small-shell-cmd-file.md) + - [cat](kernel-lite-small-shell-cmd-file-cat.md) + - [cd](kernel-lite-small-shell-cmd-file-cd.md) + - [chgrp](kernel-lite-small-shell-cmd-file-chgrp.md) + - [chmod](kernel-lite-small-shell-cmd-file-chmod.md) + - [chown](kernel-lite-small-shell-cmd-file-chown.md) + - [cp](kernel-lite-small-shell-cmd-file-cp.md) + - [format](kernel-lite-small-shell-cmd-file-format.md) + - [ls](kernel-lite-small-shell-cmd-file-is.md) + - [lsfd](kernel-lite-small-shell-cmd-file-isfd.md) + - [mkdir](kernel-lite-small-shell-cmd-file-mkdir.md) + - [mount](kernel-lite-small-shell-cmd-file-mount.md) + - [partinfo](kernel-lite-small-shell-cmd-file-part.md) + - [partition](kernel-lite-small-shell-cmd-file-partion.md) + - [pwd](kernel-lite-small-shell-cmd-file-pwd.md) + - [rm](kernel-lite-small-shell-cmd-file-rm.md) + - [rmdir](kernel-lite-small-shell-cmd-file-rmdir.md) + - [statfs](kernel-lite-small-shell-cmd-file-sta.md) + - [sync](kernel-lite-small-shell-cmd-file-sync.md) + - [touch](kernel-lite-small-shell-cmd-file-touch.md) + - [writeproc](kernel-lite-small-shell-cmd-file-write.md) + - [umount](kernel-lite-small-shell-cmd-file-umount.md) + + - [网络命令](kernel-lite-small-shell-cmd-net.md) + - [arp](kernel-lite-small-shell-cmd-net-arp.md) + - [dhclient](kernel-lite-small-shell-cmd-net-dh.md) + - [dns](kernel-lite-small-shell-cmd-net-dns.md) + - [ifconfig](kernel-lite-small-shell-cmd-net-ipc.md) + - [ipdebug](kernel-lite-small-shell-cmd-net-ipd.md) + - [netstat](kernel-lite-small-shell-cmd-net-net.md) + - [ntpdate](kernel-lite-small-shell-cmd-net-ntp.md) + - [ping](kernel-lite-small-shell-cmd-net-ping.md) + - [ping6](kernel-lite-small-shell-cmd-net-ping6.md) + - [telnet](kernel-lite-small-shell-cmd-net-tel.md) + - [tftp](kernel-lite-small-shell-cmd-net-tftp.md) + + - [魔法键使用方法](kernel-lite-small-shell-cmd-mag.md) + - [用户态异常信息说明](kernel-lite-small-shell-cmd-abn.md) + +- [标准系统内核](kernel-standard.md) + - [Linux内核概述](kernel-standard-des.md) + - [OpenHarmony开发板Patch使用指导](kernel-standard-patch.md) + - [Linux内核编译与构建指导](kernel-standard-build.md) diff --git "a/zh-cn/device-dev/kernel/Shell\344\273\213\347\273\215.md" "b/zh-cn/device-dev/kernel/Shell\344\273\213\347\273\215.md" deleted file mode 100755 index f72e4f67cb..0000000000 --- "a/zh-cn/device-dev/kernel/Shell\344\273\213\347\273\215.md" +++ /dev/null @@ -1,36 +0,0 @@ -# Shell介绍 - -- [注意事项](#section12298165312328) - -OpenHarmony内核提供的Shell支持调试常用的基本功能,包含系统、文件、网络和动态加载相关命令。同时OpenHarmony内核的Shell支持添加新的命令,可以根据需求来进行定制。 - -- 系统相关命令:提供查询系统任务、内核信号量、系统软件定时器、CPU占用率、当前中断等相关信息的能力。 - -- 文件相关命令:支持基本的ls、cd等功能。 - -- 网络相关命令:支持查询接到开发板的其他设备的IP、查询本机IP、测试网络连接、设置开发板的AP和station模式等相关功能。 - - 新增命令的详细流程可参见[开发指导](Shell命令开发指导.md)和[编程实例](Shell命令编程实例.md)。 - - -## 注意事项 - -在使用Shell功能的过程中,需要注意以下几点: - -- Shell功能支持使用exec命令来运行可执行文件。 -- Shell功能支持默认模式下英文输入。如果出现用户在UTF-8格式下输入了中文字符的情况,只能通过回退三次来删除。 - -- Shell功能支持shell命令、文件名及目录名的Tab键联想补全。若有多个匹配项,则根据共同字符, 打印多个匹配项。对于过多的匹配项(打印多于24行),将会进行打印询问(Display all num possibilities?(y/n)),用户可输入y选择全部打印,或输入n退出打印,选择全部打印并打印超过24行后,会进行--More--提示,此时按回车键继续打印,按q键退出(支持Ctrl+c退出\)。 - -- Shell端工作目录与系统工作目录是分开的,即通过Shell端cd pwd等命令是对Shell端工作目录进行操作,通过chdir getcwd等命令是对系统工作目录进行操作,两个工作目录相互之间没有联系。当文件系统操作命令入参是相对路径时要格外注意。 - -- 在使用网络Shell指令前,需要先调用tcpip\_init函数完成网络初始化并完成telnet连接后才能起作用,内核默认不初始化tcpip\_init。 - -- 不建议使用Shell命令对/dev目录下的设备文件进行操作,这可能会引起不可预知的结果。 - -- Shell功能不符合POSIX标准,仅供调试使用。 - - >![](public_sys-resources/icon-notice.gif) **须知:** - >Shell功能仅供调试使用,在Debug版本中开启(使用时通过menuconfig在配置项中开启"LOSCFG\_DEBUG\_VERSION"编译开关进行相关控制),商用产品中禁止包含该功能。 - - diff --git "a/zh-cn/device-dev/kernel/Shell\345\221\275\344\273\244\344\275\277\347\224\250\350\257\246\350\247\243.md" "b/zh-cn/device-dev/kernel/Shell\345\221\275\344\273\244\344\275\277\347\224\250\350\257\246\350\247\243.md" deleted file mode 100755 index 2faa37c740..0000000000 --- "a/zh-cn/device-dev/kernel/Shell\345\221\275\344\273\244\344\275\277\347\224\250\350\257\246\350\247\243.md" +++ /dev/null @@ -1,13 +0,0 @@ -# Shell命令使用详解 - -本章节介绍了系统关键命令的功能、格式、参数范围、使用指南和使用实例。 - -不在本文档范围内的命令,详见[help](help.md)命令的输出内容,也可以通过命令的“-h | --help”选项,查看该命令的使用帮助。 - -- **[系统命令](系统命令.md)** - -- **[文件命令](文件命令.md)** - -- **[网络命令](网络命令.md)** - - diff --git "a/zh-cn/device-dev/kernel/Shell\345\221\275\344\273\244\345\274\200\345\217\221\346\214\207\345\257\274.md" "b/zh-cn/device-dev/kernel/Shell\345\221\275\344\273\244\345\274\200\345\217\221\346\214\207\345\257\274.md" deleted file mode 100755 index b8d1e6d886..0000000000 --- "a/zh-cn/device-dev/kernel/Shell\345\221\275\344\273\244\345\274\200\345\217\221\346\214\207\345\257\274.md" +++ /dev/null @@ -1,167 +0,0 @@ -# Shell命令开发指导 - -- [开发指导](#section22071515161018) - -## 开发指导 - -新增Shell命令的典型开发流程如下: - -1. 包含如下头文件: - - ``` - #include "shell.h" - #include "shcmd.h" - ``` - -2. 注册命令。用户可以选择静态注册命令方式和系统运行时动态注册命令方式,静态注册命令方式一般用在系统常用命令注册,动态注册命令方式一般用在用户命令注册。 - - 1. 静态注册命令方式: - - 1. 通过宏的方式注册。 - - 这个宏的原型为: - - ``` - SHELLCMD_ENTRY(l, cmdType, cmdKey, paraNum, cmdHook) - ``` - - **表 1** SHELLCMD\_ENTRY参数详解 - - - - - - - - - - - - - - - - - - - - - - -

    参数

    -

    描述

    -

    l

    -

    静态注册全局变量名(注意:不与系统中其他symbol重名)。

    -

    cmdType

    -

    命令类型:

    -
    • CMD_TYPE_EX:不支持标准命令参数输入,会把用户填写的命令关键字屏蔽掉,例如:输入ls /ramfs,传入给注册函数的参数只有/ramfs,而ls命令关键字并不会被传入。

      -
    • CMD_TYPE_STD:支持的标准命令参数输入,所有输入的字符都会通过命令解析后被传入。

      -
    -

    cmdKey

    -

    命令关键字,函数在Shell中访问的名称。

    -

    paraNum

    -

    调用的执行函数的入参最大个数,暂不支持。

    -

    cmdHook

    -

    命令执行函数地址,即命令实际执行函数。

    -
    - - 如: - - ``` - SHELLCMD_ENTRY(ls_shellcmd, CMD_TYPE_EX, "ls", XARGS, (CMD_CBK_FUNC)osShellCmdLs) - ``` - - 2. 在build/mk/liteos\_tables\_ldflags.mk中添加相应选项: - - 如:上述“ls”命令注册时,需在build/mk/liteos\_tables\_ldflags.mk中添加“-uls\_shellcmd”。其中-u后面跟SHELLCMD\_ENTRY的第一个参数。 - - - 2. 动态注册命令方式: - - 注册函数原型: - - ``` - UINT32 osCmdReg(CmdT ype cmdType, CHAR *cmdKey, UINT32 paraNum, CmdCallBackFunc cmdProc) - ``` - - **表 2** UINT32 osCmdReg参数详解 - - - - - - - - - - - - - - - - - - - -

    参数

    -

    描述

    -

    cmdType

    -

    命令类型:

    -
    • CMD_TYPE_EX:不支持标准命令参数输入,会把用户填写的命令关键字屏蔽掉,例如:输入ls /ramfs,传入给注册函数的参数只有/ramfs,而ls命令关键字并不会被传入。

      -
    • CMD_TYPE_STD:支持的标准命令参数输入,所有输入的字符都会通过命令解析后被传入。

      -
    -

    cmdKey

    -

    命令关键字,函数在Shell中访问的名称。

    -

    paraNum

    -

    调用的执行函数的入参最大个数,暂不支持该参数;当前为默认值XARGS(0xFFFFFFFF)。

    -

    cmdHook

    -

    命令执行函数地址,即命令实际执行函数。

    -
    - - 如: - - ``` - osCmdReg(CMD_TYPE_EX, "ls", XARGS, (CMD_CBK_FUNC)osShellCmdLs) - ``` - - - >![](public_sys-resources/icon-note.gif) **说明:** - >命令关键字必须是唯一的,也即两个不同的命令项不能拥有相同的命令关键字,否则只会执行其中一个。 - >Shell在执行用户命令时,如果存在多个命令关键字相同的命令,只会执行其中在"help"命令中排序在最前面的一个。 - -3. 添加内置命令函数原型。 - - ``` - UINT32 osShellCmdLs(UINT32 argc, CHAR **argv) - ``` - - **表 3** osShellCmdLs参数说明 - - - - - - - - - - - - - -

    参数

    -

    参数描述

    -

    argc

    -

    Shell命令中,参数个数。

    -

    argv

    -

    为指针数组,每个元素指向一个字符串,可以根据选择命令类型,决定是否要把命令关键字传入给注册函数。

    -
    - -4. 输入Shell命令,有两种输入方式: - - 在串口工具中直接输入Shell命令。 - - - 在telnet工具中输入Shell命令(telnet使用方式详见[telnet](telnet.md))。 - - - diff --git a/zh-cn/device-dev/kernel/VFS.md b/zh-cn/device-dev/kernel/VFS.md deleted file mode 100755 index 0a16319ccd..0000000000 --- a/zh-cn/device-dev/kernel/VFS.md +++ /dev/null @@ -1,171 +0,0 @@ -# VFS - -- [概述](#section132540468341) -- [基本概念](#section229417111227) -- [运作机制](#section18114182834215) -- [注意事项](#section18311145173712) -- [开发指导](#section422619258380) -- [编程实例](#section180311121420) -- [结果验证](#section16772334714) - -## 概述 - -## 基本概念 - -VFS是Virtual File System(虚拟文件系统)的缩写,它不是一个实际的文件系统,而是一个异构文件系统之上的软件粘合层,为用户提供统一的类Unix文件操作接口。 - -由于不同类型的文件系统接口不统一,若系统中有多个文件系统类型,访问不同的文件系统就需要使用不同的非标准接口。而通过在系统中添加VFS层,提供统一的抽象接口,屏蔽了底层异构类型的文件系统的差异,使得访问文件系统的系统调用不用关心底层的存储介质和文件系统类型,提高开发效率。VFS和各个具体文件系统的关系如下: - -**图 1** VFS和各个文件系统的关系 -![](figures/VFS和各个文件系统的关系.png "VFS和各个文件系统的关系") - -OpenHarmony内核中,VFS框架是通过在内存中的树结构来实现的,树的每个结点都是一个inode结构体。设备注册和文件系统挂载后会根据路径在树中生成相应的结点。VFS最主要是两个功能: - -- 查找节点。 -- 统一调用(标准)。 - -## 运作机制 - -通过VFS层,可以使用标准的Unix文件操作函数(如open、read、write等)来实现对不同介质上不同文件系统的访问。 - -VFS框架内存中的inode树结点有三种类型: - -- 虚拟结点:作为VFS框架的虚拟文件,保持树的连续性,如/usr、/usr/bin。 -- 设备结点:/dev目录下,对应一个设备,如/dev/mmcblk0。 -- 挂载点:挂载具体文件系统,如/vs/sd、/mnt。 - -**图 2** 文件系统树形结构 -![](figures/文件系统树形结构.png "文件系统树形结构") - -## 注意事项 - -- VFS下的所有文件系统,创建的目录名和文件名最多只可以有255个字节,能支持的全路径长度最长为259字节,超过这个路径长度的文件和目录无法创建。 - -- 目前仅有jffs2文件系统支持完整的权限控制。 - -- inode\_find\(\)函数调用后会使查找到的inode节点连接数+1,调用完成后需要调用inode\_release\(\)使连接数-1,所以一般inode\_find\(\)要和inode\_release\(\)配套使用。 - -- 设备分为字符设备和块设备,为了块设备上的文件系统系统数据安全,需挂载相应文件系统后通过文件系统接口操作数据。 - -- los\_vfs\_init\(\)只能调用一次,多次调用将会造成文件系统异常。 - -- 目前OpenHarmony内核所有的文件系统中的文件名和目录名中只可以出现“-” 与“\_”两种特殊字符,使用其他特殊字符可能造成的后果不可预知,请谨慎为之。 - -- OpenHarmony内核支持open\(\)+O\_DIRECTORY的方法获取目录数据信息。 - -- 挂载点必须为空目录,不能重复挂载至同一挂载点或挂载至其他挂载点下的目录或文件,错误挂载可能损坏设备及系统。 - -- open打开一个文件时,参数O\_RDWR、O\_WRONLY、O\_RDONLY互斥,只能出现一个,若出现2个或以上作为open的参数,文件读写操作会被拒绝,并返回EACCESS错误码,禁止使用。 - -- OpenHarmony内核文件系统在umount操作之前,需确保所有目录及文件全部关闭,否则umount会失败。如果强制umount,可能导致包括但不限于文件系统损坏、设备损坏等问题。 - -- SD卡移除前,需确保所有目录及文件全部关闭,并进行umount操作。如果强制拔卡,可能导致包括但不限于SD数据丢失、SD卡损坏等问题。 - - -## 开发指导 - -**开发流程** - -推荐驱动开发人员使用VFS框架来注册/卸载设备,即调用register\_driver\(\)、register\_blockdriver\(\)接口生成设备结点,应用层使用open\(\)、read\(\)操作设备(字符设备)文件来调用驱动。 - -**文件描述符** - -本系统中,进程的文件描述符最多有256个(File和Socket描述符合并统计),系统文件描述符共640个,系统文件描述符规格: - -- File描述符,普通文件描述符,系统总规格为512。 - -- Socket描述符,系统总规格为128。 - - -**VFS支持的操作** - -open, close, read, write, seek, ioctl, fcntl, mmap, sync, dup, dup2, truncate, opendir, closedir, readdir, rewinddir, mount, umount, statfs, unlink, remove, mkdir, rmdir, rename, stat, utime, seek64, fallocate, fallocate64, truncate64, chmod, chown。 - ->![](public_sys-resources/icon-note.gif) **说明:** ->- 当前只提供修改jffs2文件以及vfs设备节点属性的接口,各个系统对只读等属性有各自的处理方式。 ->- 在OpenHarmony内核中属性并不冲突(可以任意修改)。 ->- 在OpenHarmony内核中只读属性文件/目录不允许被删除。 ->- 在OpenHarmony内核中只读属性文件/目录允许rename。 ->- 只读文件不允许以O\_CREAT、O\_TRUNC,以及有含有写的权限的方式打开。 ->- 在OpenHarmony内核中设置的系统文件加上隐藏属性,在Windows中只能通过命令行找到(在显示,不显示隐藏文件的属性情况下都不能看到)。 - -## 编程实例 - -``` -/* 说明:展示创建目录,和遍历目录的操作 */ -#include -#include -#include -#include -#include -#include - -int main() -{ - int ret; - char *dirname = "/test"; - char *pathname0 = "/test/test0"; - char *pathname1 = "/test/test1"; - char *pathname2 = "/test/test2"; - struct dirent **namelist; - int num; - - ret = mkdir(dirname, 0777); - if ((ret < 0) && (errno != EEXIST)) { - printf("mkdir failed. path=%s, errno=%d\n", dirname, errno); - goto EXIT; - } - - ret = mkdir(pathname0, 0777); - if ((ret < 0) && (errno != EEXIST)) { - printf("mkdir failed. path=%s, errno=%d\n", pathname0, errno); - goto EXIT0; - } - - ret = mkdir(pathname1, 0777); - if ((ret < 0) && (errno != EEXIST)) { - printf("mkdir failed. path=%s, errno=%d\n", pathname1, errno); - goto EXIT1; - } - - ret = mkdir(pathname2, 0777); - if ((ret < 0) && (errno != EEXIST)) { - printf("mkdir failed. path=%s, errno=%d\n", pathname2, errno); - goto EXIT2; - } - - num = scandir(dirname, &namelist, NULL, alphasort); - if (num < 0) { - perror("scandir"); - } else { - while (num--) { - printf("%s\n", namelist[num]->d_name); - free(namelist[num]); - } - free(namelist); - } - - printf("fs_demo exit.\n"); - return 0; - -EXIT2: - remove(pathname2); -EXIT1: - remove(pathname1); -EXIT0: - remove(pathname0); -EXIT: - remove(dirname); - return 0; -} -``` - -## 结果验证 - -``` -OHOS # test2 -test1 -test0 -fs_demo exit. -``` - diff --git a/zh-cn/device-dev/kernel/arp.md b/zh-cn/device-dev/kernel/arp.md deleted file mode 100755 index 2cf3628efa..0000000000 --- a/zh-cn/device-dev/kernel/arp.md +++ /dev/null @@ -1,114 +0,0 @@ -# arp - -- [命令功能](#section201149459368) -- [命令格式](#section579813484364) -- [参数说明](#section168065311366) -- [使用指南](#section19190125723612) -- [使用实例](#section10383416372) - -## 命令功能 - -在以太网中,主机之间的通信是直接使用MAC地址(非IP地址)来通信的,所以,对于使用IP通信的协议,必须能够将IP地址转换成MAC地址,才能在局域网(以太网)内通信。解决这个问题的方法就是主机存储一张IP和MAC地址对应的表,即ARP缓存,主机要往一个局域网内的目的IP地址发送IP包时,就可以从ARP缓存表中查询到目的MAC地址。ARP缓存是由TCP/IP协议栈维护的,用户可通过ARP命令查看和修改ARP表。 - -## 命令格式 - -arp - -arp \[_-i IF_\] -s _IPADDR HWADDR_ - -arp \[_-i IF_\] -d _IPADDR_ - -## 参数说明 - -**表 1** 参数说明 - - - - - - - - - - - - - - - - - - - - - - - - -

    参数

    -

    参数说明

    -

    取值范围

    -

    -

    打印整个ARP缓存的内容。

    -

    N/A

    -

    -i IF

    -

    指定的网络接口(可选参数)。

    -

    N/A

    -

    -s IPADDR

    -

    HWADDR

    -

    增加一条ARP表项,后面的参数是局域网中另一台主机的IP地址及其对应的MAC地址。

    -

    N/A

    -

    -d IPADDR

    -

    删除一条ARP表项。

    -

    N/A

    -
    - -## 使用指南 - -- arp命令用来查询和修改TCP/IP协议栈的ARP缓存表,增加非同一子网内的IP地址的ARP表项是没有意义的,协议栈会返回失败。 -- 命令需要启动TCP/IP协议栈后才能使用。 - -## 使用实例 - -举例: - -1. 输入arp - - **图 1** 打印整个 ARP 缓存表 - - - ![](figures/Snipaste_2021-01-26_10-38-58.png) - - **表 2** 参数说明 - - - - - - - - - - - - - - - - - - - -

    参数

    -

    说明

    -

    Address

    -

    表示网络设备的IPv4地址。

    -

    HWaddress

    -

    表示网络设备的MAC地址。

    -

    Iface

    -

    表示该ARP表项使用的接口名。

    -

    Type

    -

    表示该ARP表项是动态的还是静态的,动态是指ARP表项由协议栈自动创建,静态是指ARP表项是由用户增加的。

    -
    - - diff --git a/zh-cn/device-dev/kernel/cat.md b/zh-cn/device-dev/kernel/cat.md deleted file mode 100755 index ef609b4dc0..0000000000 --- a/zh-cn/device-dev/kernel/cat.md +++ /dev/null @@ -1,53 +0,0 @@ -# cat - -- [命令功能](#section16710153391315) -- [命令格式](#section1699392313158) -- [参数说明](#section1677217374136) -- [使用指南](#section186772414131) -- [使用实例](#section12158131814561) -- [输出说明](#section183926225561) - -## 命令功能 - -cat用于显示文本文件的内容。 - -## 命令格式 - -cat \[_pathname_\] - -## 参数说明 - -**表 1** 参数说明 - - - - - - - - - - - - -

    参数

    -

    参数说明

    -

    取值范围

    -

    pathname

    -

    文件路径。

    -

    已存在的文件。

    -
    - -## 使用指南 - -cat用于显示文本文件的内容。 - -## 使用实例 - -举例:cat hello-harmony.txt - -## 输出说明 - -**图 1** 查看 hello-harmony.txt 文件的信息 -![](figures/查看-hello-harmony-txt-文件的信息.png "查看-hello-harmony-txt-文件的信息") - diff --git a/zh-cn/device-dev/kernel/cd.md b/zh-cn/device-dev/kernel/cd.md deleted file mode 100755 index 8acd5da837..0000000000 --- a/zh-cn/device-dev/kernel/cd.md +++ /dev/null @@ -1,57 +0,0 @@ -# cd - -- [命令功能](#section11690184921316) -- [命令格式](#section75695409569) -- [参数说明](#section71961353181311) -- [使用指南](#section3629759111317) -- [使用实例](#section211620301412) -- [输出说明](#section1968117214577) - -## 命令功能 - -cd命令用来改变当前目录。 - -## 命令格式 - -cd \[_path_\] - -## 参数说明 - -**表 1** 参数说明 - - - - - - - - - - - - -

    参数

    -

    参数说明

    -

    取值范围

    -

    path

    -

    文件路径。

    -

    用户必须具有指定目录中的执行(搜索)许可权。

    -
    - -## 使用指南 - -- 未指定目录参数时,会跳转至根目录。 -- cd后加路径名时,跳转至该路径。 -- 路径名以 /(斜杠)开头时,表示根目录。 -- .(点)表示当前目录。 -- ..(点点)表示父目录。 - -## 使用实例 - -举例:cd .. - -## 输出说明 - -**图 1** 显示结果如下 -![](figures/显示结果如下.png "显示结果如下") - diff --git a/zh-cn/device-dev/kernel/chgrp.md b/zh-cn/device-dev/kernel/chgrp.md deleted file mode 100755 index dc292bf35f..0000000000 --- a/zh-cn/device-dev/kernel/chgrp.md +++ /dev/null @@ -1,60 +0,0 @@ -# chgrp - -- [命令功能](#section6103119161418) -- [命令格式](#section186958132141) -- [参数说明](#section81796174141) -- [使用指南](#section14330152417140) -- [使用实例](#section951823119149) -- [输出说明](#section14271133125715) - -## 命令功能 - -chgrp用于修改文件的群组。 - -## 命令格式 - -chgrp \[_group_\] \[_pathname_\] - -## 参数说明 - -**表 1** 参数说明 - - - - - - - - - - - - - - - - -

    参数

    -

    参数说明

    -

    取值范围

    -

    group

    -

    文件群组。

    -

    [0,0xFFFFFFFF]

    -

    pathname

    -

    文件路径。

    -

    已存在的文件。

    -
    - -## 使用指南 - -在需要修改的文件名前加上文件群组值就可以修改该文件的所属组。 - -## 使用实例 - -举例:chgrp 100 hello-harmony.txt - -## 输出说明 - -**图 1** 修改 hello-harmony.txt 文件的群组为100 -![](figures/修改-hello-harmony-txt-文件的群组为100.png "修改-hello-harmony-txt-文件的群组为100") - diff --git a/zh-cn/device-dev/kernel/chmod.md b/zh-cn/device-dev/kernel/chmod.md deleted file mode 100755 index a77659fcdd..0000000000 --- a/zh-cn/device-dev/kernel/chmod.md +++ /dev/null @@ -1,60 +0,0 @@ -# chmod - -- [命令功能](#section13992936121418) -- [命令格式](#section63342439147) -- [参数说明](#section894414671411) -- [使用指南](#section182415221419) -- [使用实例](#section8518195718147) -- [输出说明](#section127391818158) - -## 命令功能 - -chmod用于修改文件操作权限。 - -## 命令格式 - -chmod \[_mode_\] \[_pathname_\] - -## 参数说明 - -**表 1** 参数说明 - - - - - - - - - - - - - - - - -

    参数

    -

    参数说明

    -

    取值范围

    -

    mode

    -

    文件或文件夹权限,用8进制表示对应User、Group、及Other(拥有者、群组、其他组)的权限。

    -

    [0,777]

    -

    pathname

    -

    文件路径。

    -

    已存在的文件。

    -
    - -## 使用指南 - -在需要修改的文件名前加上文件权限值就可以修改该文件的权限值。 - -## 使用实例 - -举例:chmod 666 hello-harmony.txt - -## 输出说明 - -**图 1** 修改 hello-harmony.txt 文件的权限为666 -![](figures/修改-hello-harmony-txt-文件的权限为666.png "修改-hello-harmony-txt-文件的权限为666") - diff --git a/zh-cn/device-dev/kernel/chown.md b/zh-cn/device-dev/kernel/chown.md deleted file mode 100755 index 467da9d89c..0000000000 --- a/zh-cn/device-dev/kernel/chown.md +++ /dev/null @@ -1,70 +0,0 @@ -# chown - -- [命令功能](#section247414691513) -- [命令格式](#section14773151018159) -- [参数说明](#section598731391517) -- [使用指南](#section16524152071510) -- [使用实例](#section17901152561510) -- [输出说明](#section15513163115816) - -## 命令功能 - -chmod用于将指定文件的拥有者改为指定的用户或组。 - -## 命令格式 - -chown \[_owner_\] \[_group_\] \[_pathname_\] - -## 参数说明 - -**表 1** 参数说明 - - - - - - - - - - - - - - - - - - - - -

    参数

    -

    参数说明

    -

    取值范围

    -

    owner

    -

    文件拥有者。

    -

    [0,0xFFFFFFFF]

    -

    group

    -

    文件群组。

    -

    1、为空。

    -

    2、[0,0xFFFFFFFF]

    -

    pathname

    -

    文件路径。

    -

    已存在的文件。

    -
    - -## 使用指南 - -- 在需要修改的文件名前加上文件拥有者和文件群组就可以分别修改该文件的拥有者和群组。 -- 当owner或group值为-1时则表示对应的owner或group不修改。 -- group参数可以为空。 - -## 使用实例 - -举例:chown 100 200 hello-harmony.txt - -## 输出说明 - -**图 1** 修改 hello-harmony.txt 文件的uid为100,gid为200 -![](figures/修改-hello-harmony-txt-文件的uid为100-gid为200.png "修改-hello-harmony-txt-文件的uid为100-gid为200") - diff --git a/zh-cn/device-dev/kernel/cp.md b/zh-cn/device-dev/kernel/cp.md deleted file mode 100755 index eab217ee50..0000000000 --- a/zh-cn/device-dev/kernel/cp.md +++ /dev/null @@ -1,68 +0,0 @@ -# cp - -- [命令功能](#section6841203041513) -- [命令格式](#section24286359150) -- [参数说明](#section558617385152) -- [使用指南](#section16128156162) -- [使用实例](#section19354171211618) -- [输出说明](#section16754183195914) - -## 命令功能 - -拷贝文件,创建一份副本。 - -## 命令格式 - -cp \[_SOURCEFILE_\] \[_DESTFILE_\] - -## 参数说明 - -**表 1** 参数说明 - - - - - - - - - - - - - - - - -

    参数

    -

    参数说明

    -

    取值范围

    -

    SOURCEFILE

    -

    源文件路径。

    -

    目前只支持文件,不支持目录。

    -

    DESTFILE

    -

    目的文件路径。

    -

    支持目录以及文件。

    -
    - -## 使用指南 - -- 同一路径下,源文件与目的文件不能重名。 -- 源文件必须存在,且不为目录。 -- 源文件路径支持“\*”和“?”通配符,“\*”代表任意多个字符,“?”代表任意单个字符。目的路径不支持通配符。当源路径可匹配多个文件时,目的路径必须为目录。 -- 目的路径为目录时,该目录必须存在。此时目的文件以源文件命名。 -- 目的路径为文件时,所在目录必须存在。此时拷贝文件的同时为副本重命名。 -- 目前不支持多文件拷贝。参数大于2个时,只对前2个参数进行操作。 -- 目的文件不存在时创建新文件,已存在则覆盖。 - -拷贝系统重要资源时,会对系统造成死机等重大未知影响,如用于拷贝/dev/uartdev-0 文件时,会产生系统卡死现象。 - -## 使用实例 - -举例:cp hello-harmony.txt ./tmp/ - -## 输出说明 - -**图 1** 显示结果如下 -![](figures/显示结果如下-0.png "显示结果如下-0") - diff --git a/zh-cn/device-dev/kernel/cpup.md b/zh-cn/device-dev/kernel/cpup.md deleted file mode 100755 index c2bf2bba46..0000000000 --- a/zh-cn/device-dev/kernel/cpup.md +++ /dev/null @@ -1,65 +0,0 @@ -# cpup - -- [命令功能](#section1842161614217) -- [命令格式](#section5629527427) -- [参数说明](#section133651361023) -- [使用指南](#section156611948521) -- [使用实例](#section68501605319) -- [输出说明](#section19871522144219) - -## 命令功能 - -cpup命令用于查询系统CPU的占用率。 - -## 命令格式 - -cpup \[_mode_\] \[_taskID_\] - -## 参数说明 - -**表 1** 参数说明 - - - - - - - - - - - - - - - - -

    参数

    -

    参数说明

    -

    取值范围

    -

    mode

    -

    ● 缺省:显示系统最近10s内的CPU占用率。

    -

    ● 0:显示系统最近10s内的CPU占用率。

    -

    ● 1:显示系统最近1s内的CPU占用率。

    -

    ● 其他数字:显示系统启动至今总的CPU 占用率。

    -

    [0,0xFFFFFFFF]

    -

    taskID

    -

    任务ID号

    -

    [0,0xFFFFFFFF]

    -
    - -## 使用指南 - -- 参数缺省时,显示系统10s前的CPU占用率。 -- 只有一个参数时,该参数为mode,显示系统相应时间前的CPU占用率。 -- 输入两个参数时,第一个参数为mode,第二个参数为taskID,显示对应ID号任务的相应时间前的CPU占用率。 - -## 使用实例 - -举例:输入cpup 1 5 - -## 输出说明 - -**图 1** 指令输出结果 -![](figures/指令输出结果.png "指令输出结果") - diff --git a/zh-cn/device-dev/kernel/date.md b/zh-cn/device-dev/kernel/date.md deleted file mode 100755 index d359856e20..0000000000 --- a/zh-cn/device-dev/kernel/date.md +++ /dev/null @@ -1,94 +0,0 @@ -# date - -- [命令功能](#section56472016338) -- [命令格式](#section16635112512316) -- [参数说明](#section15896030039) -- [使用指南](#section116361036636) -- [使用实例](#section021711411237) -- [输出说明](#section17950184414312) - -## 命令功能 - -date命令用于查询及设置系统日期和时间。 - -## 命令格式 - -date - -date --help - -date +\[_Format_\] - -date -s_ _\[_YY/MM/DD_\] - -date_ _-s_ _\[_hh:mm:ss_\]__ - -date -r \[_Filename_\] - -## 参数说明 - -**表 1** 参数说明 - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    参数

    -

    参数说明

    -

    取值范围

    -

    --help

    -

    使用帮助。

    -

    N/A

    -

    +Format

    -

    根据Format格式打印日期和时间。

    -

    --help中列出的占位符。

    -

    -s YY/MM/DD

    -

    设置系统时间,用“/”分割的年月日。

    -

    >= 1970/01/01

    -

    -s hh:mm:ss

    -

    设置系统时间,用“:”分割的时分秒。

    -

    N/A

    -

    -r Filename

    -

    查询Filename文件的修改时间。

    -

    N/A

    -
    - -## 使用指南 - -- date参数缺省时,默认显示当前系统日期和时间。 -- --help、+Format、-s、-r不能混合使用。 - -## 使用实例 - -举例: - -输入date +%Y--%m--%d。 - -## 输出说明 - -**图 1** 按指定格式打印系统日期 -![](figures/按指定格式打印系统日期.png "按指定格式打印系统日期") - diff --git a/zh-cn/device-dev/kernel/dhclient.md b/zh-cn/device-dev/kernel/dhclient.md deleted file mode 100755 index 360efdc808..0000000000 --- a/zh-cn/device-dev/kernel/dhclient.md +++ /dev/null @@ -1,138 +0,0 @@ -# dhclient - -- [命令功能](#section366714216619) -- [命令格式](#section8833164614615) -- [参数说明](#section12809111019453) -- [使用指南](#section15935131220717) -- [使用实例](#section79281818476) -- [输出说明](#section12742311179) - -## 命令功能 - -设置和查看dhclient的参数。 - -## 命令格式 - -dhclient <_netif name_\> - -dhclient -x <_netif name_\> - -dhclient -gb <_netif name_\> - -dhclient -sv <_vendor_\> - -dhclient -gv - -dhclient -gd <_index_\> - -dhclient -sd <_dns\_ip_\> - -## 参数说明 - -**表 1** 参数说明 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    参数

    -

    参数说明

    -

    取值范围

    -

    <netif name>

    -

    启动对应网卡的dhcp请求。

    -

    网卡名字,eth0。

    -

    -x <netif name>

    -

    关闭对应网卡的dhcp功能。

    -

    网卡名字,eth0。

    -

    -gb <netif name>

    -

    查看对应网卡的dhcp请求是否完成。

    -

    网卡名字,eth0。

    -

    -sv <vendor>

    -

    设置dhcp请求的厂商信息。

    -

    厂商信息,长度是32个字符。

    -

    -gv

    -

    查看dhcp请求的厂商信息。

    -

    N/A

    -

    -gd <index>

    -

    获取第index个dns server的信息。

    -

    index,0或者1。

    -

    -sd <dns_ip>

    -

    设置主dns server的ip。

    -

    dns的ip地址。

    -
    - -## 使用指南 - -dhclient eth0 - -dhclient -x eth0 - -dhclient -gb eth0 - -dhclient -sv MFSI - -dhclient -gv - -dhclient -gd 0 - -dhclient -sd 8.8.8.8 - -## 使用实例 - -![](figures/zh-cn_image_0000001053224218.png) - -## 输出说明 - -**表 2** 输出说明 - - - - - - - - - - - - - -

    输出

    -

    说明

    -

    dhclient: set vendor info [MFSI] success

    -

    设置厂商信息MFSI信息成功。

    -

    dns[0]: 192.168.1.100

    -

    dns server ip地址为192.168.1.100。

    -
    - diff --git a/zh-cn/device-dev/kernel/dmesg.md b/zh-cn/device-dev/kernel/dmesg.md deleted file mode 100755 index 197e38fdff..0000000000 --- a/zh-cn/device-dev/kernel/dmesg.md +++ /dev/null @@ -1,113 +0,0 @@ -# dmesg - -- [命令功能](#section4643204919313) -- [命令格式](#section6553153635) -- [参数说明](#section208971157532) -- [使用指南](#section213115219413) -- [使用实例](#section13736564418) -- [输出说明](#section194005101413) - -## 命令功能 - -dmesg命令用于控制内核dmesg缓存区。 - -## 命令格式 - -dmesg - -dmesg \[_-c/-C/-D/-E/-L/-U_\] - -dmesg -s \[_size_\] - -dmesg -l \[_level_\] - -dmesg \> \[_fileA_\] - -## 参数说明 - -**表 1** 参数说明 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    参数

    -

    参数说明

    -

    取值范围

    -

    -c

    -

    打印缓存区内容并清空缓存区。

    -

    N/A

    -

    -C

    -

    清空缓存区。

    -

    N/A

    -

    -D/-E

    -

    关闭/开启控制台打印。

    -

    N/A

    -

    -L/-U

    -

    关闭/开启串口打印。

    -

    N/A

    -

    -s size

    -

    设置缓存区大小 size是要设置的大小。

    -

    N/A

    -

    -l level

    -

    设置缓存等级。

    -

    0 - 5

    -

    > fileA

    -

    将缓存区内容写入文件。

    -

    N/A

    -
    - -## 使用指南 - -- 该命令依赖于LOSCFG\_SHELL\_DMESG,使用时通过menuconfig在配置项中开启"Enable Shell dmesg": - - Debug ---\> Enable a Debug Version ---\> Enable Shell ---\> Enable Shell dmesg - -- dmesg参数缺省时,默认打印缓存区内容。 -- 各“ - ”选项不能混合使用。 - 1. 写入文件需确保已挂载文件系统。 - 2. 关闭串口打印会影响shell使用,建议先连接telnet再尝试关闭串口。 - - -## 使用实例 - -举例: - -输入dmesg \> /usr/dmesg.log。 - -## 输出说明 - -**图 1** dmesg重定向到文件。 -![](figures/dmesg重定向到文件.png "dmesg重定向到文件") - diff --git a/zh-cn/device-dev/kernel/exec.md b/zh-cn/device-dev/kernel/exec.md deleted file mode 100755 index a3b0933672..0000000000 --- a/zh-cn/device-dev/kernel/exec.md +++ /dev/null @@ -1,60 +0,0 @@ -# exec - -- [命令功能](#section4643204919313) -- [命令格式](#section6553153635) -- [参数说明](#section208971157532) -- [使用指南](#section213115219413) -- [使用实例](#section13736564418) -- [输出说明](#section194005101413) - -## 命令功能 - -exec命令属于shell内置命令,目前实现最基础的执行用户态程序的功能。 - -## 命令格式 - -exec <_executable-file_\> - -## 参数说明 - -**表 1** 参数说明 - - - - - - - - - - - - -

    参数

    -

    参数说明

    -

    取值范围

    -

    executable-file

    -

    有效的可执行文件。

    -

    N/A

    -
    - -## 使用指南 - -该命令当前仅支持执行有效的二进制程序,程序成功执行,默认后台运行,但与Shell共用终端,可能会导致程序打印输出与Shell输出交错显示。 - -## 使用实例 - -举例: - -输入exec helloworld。 - -## 输出说明 - -``` -OHOS # exec helloworld -OHOS # hello world! -``` - ->![](public_sys-resources/icon-note.gif) **说明:** ->可执行文件执行后,先打印“OHOS \#”提示符原因:目前Shell “exec”命令执行均为后台执行,结果可能导致提示符提前打印。 - diff --git "a/zh-cn/device-dev/kernel/figure/Cow\346\234\272\345\210\266\347\244\272\346\204\217\345\233\276.png" "b/zh-cn/device-dev/kernel/figure/Cow\346\234\272\345\210\266\347\244\272\346\204\217\345\233\276.png" new file mode 100644 index 0000000000000000000000000000000000000000..bee6020f58b7127c24d0adc1da77fe1761b386de GIT binary patch literal 37179 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 literal 0 HcmV?d00001 diff --git "a/zh-cn/device-dev/kernel/figures/PID\344\270\2723\347\232\204\350\277\233\347\250\213\350\231\232\346\213\237\345\206\205\345\255\230\344\275\277\347\224\250\344\277\241\346\201\257.png" "b/zh-cn/device-dev/kernel/figure/PID\344\270\2723\347\232\204\350\277\233\347\250\213\350\231\232\346\213\237\345\206\205\345\255\230\344\275\277\347\224\250\344\277\241\346\201\257.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/kernel/figures/PID\344\270\2723\347\232\204\350\277\233\347\250\213\350\231\232\346\213\237\345\206\205\345\255\230\344\275\277\347\224\250\344\277\241\346\201\257.png" rename to "zh-cn/device-dev/kernel/figure/PID\344\270\2723\347\232\204\350\277\233\347\250\213\350\231\232\346\213\237\345\206\205\345\255\230\344\275\277\347\224\250\344\277\241\346\201\257.png" diff --git "a/zh-cn/device-dev/kernel/figures/POSIX\346\216\245\345\217\243\346\241\206\346\236\266.png" "b/zh-cn/device-dev/kernel/figure/POSIX\346\216\245\345\217\243\346\241\206\346\236\266.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/kernel/figures/POSIX\346\216\245\345\217\243\346\241\206\346\236\266.png" rename to "zh-cn/device-dev/kernel/figure/POSIX\346\216\245\345\217\243\346\241\206\346\236\266.png" diff --git a/zh-cn/device-dev/kernel/figures/Snipaste_2021-01-26_10-38-58-1.png b/zh-cn/device-dev/kernel/figure/Snipaste_2021-01-26_10-38-58-18.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/kernel/figures/Snipaste_2021-01-26_10-38-58-1.png rename to zh-cn/device-dev/kernel/figure/Snipaste_2021-01-26_10-38-58-18.png diff --git a/zh-cn/device-dev/kernel/figures/Snipaste_2021-01-26_10-38-58-2.png b/zh-cn/device-dev/kernel/figure/Snipaste_2021-01-26_10-38-58-19.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/kernel/figures/Snipaste_2021-01-26_10-38-58-2.png rename to zh-cn/device-dev/kernel/figure/Snipaste_2021-01-26_10-38-58-19.png diff --git a/zh-cn/device-dev/kernel/figures/Snipaste_2021-01-26_10-38-58.png b/zh-cn/device-dev/kernel/figure/Snipaste_2021-01-26_10-38-58.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/kernel/figures/Snipaste_2021-01-26_10-38-58.png rename to zh-cn/device-dev/kernel/figure/Snipaste_2021-01-26_10-38-58.png diff --git "a/zh-cn/device-dev/kernel/figures/VFS\345\222\214\345\220\204\344\270\252\346\226\207\344\273\266\347\263\273\347\273\237\347\232\204\345\205\263\347\263\273.png" "b/zh-cn/device-dev/kernel/figure/VFS\345\222\214\345\220\204\344\270\252\346\226\207\344\273\266\347\263\273\347\273\237\347\232\204\345\205\263\347\263\273.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/kernel/figures/VFS\345\222\214\345\220\204\344\270\252\346\226\207\344\273\266\347\263\273\347\273\237\347\232\204\345\205\263\347\263\273.png" rename to "zh-cn/device-dev/kernel/figure/VFS\345\222\214\345\220\204\344\270\252\346\226\207\344\273\266\347\263\273\347\273\237\347\232\204\345\205\263\347\263\273.png" diff --git "a/zh-cn/device-dev/kernel/figures/dmesg\351\207\215\345\256\232\345\220\221\345\210\260\346\226\207\344\273\266.png" "b/zh-cn/device-dev/kernel/figure/dmesg\351\207\215\345\256\232\345\220\221\345\210\260\346\226\207\344\273\266.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/kernel/figures/dmesg\351\207\215\345\256\232\345\220\221\345\210\260\346\226\207\344\273\266.png" rename to "zh-cn/device-dev/kernel/figure/dmesg\351\207\215\345\256\232\345\220\221\345\210\260\346\226\207\344\273\266.png" diff --git "a/zh-cn/device-dev/kernel/figures/lsfd\350\276\223\345\207\272\350\257\264\346\230\216.png" "b/zh-cn/device-dev/kernel/figure/lsfd\350\276\223\345\207\272\350\257\264\346\230\216.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/kernel/figures/lsfd\350\276\223\345\207\272\350\257\264\346\230\216.png" rename to "zh-cn/device-dev/kernel/figure/lsfd\350\276\223\345\207\272\350\257\264\346\230\216.png" diff --git "a/zh-cn/device-dev/kernel/figures/statfs\350\276\223\345\207\272\350\257\264\346\230\216.png" "b/zh-cn/device-dev/kernel/figure/statfs\350\276\223\345\207\272\350\257\264\346\230\216.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/kernel/figures/statfs\350\276\223\345\207\272\350\257\264\346\230\216.png" rename to "zh-cn/device-dev/kernel/figure/statfs\350\276\223\345\207\272\350\257\264\346\230\216.png" diff --git "a/zh-cn/device-dev/kernel/figures/umount\350\276\223\345\207\272\347\244\272\344\276\213.png" "b/zh-cn/device-dev/kernel/figure/umount\350\276\223\345\207\272\347\244\272\344\276\213.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/kernel/figures/umount\350\276\223\345\207\272\347\244\272\344\276\213.png" rename to "zh-cn/device-dev/kernel/figure/umount\350\276\223\345\207\272\347\244\272\344\276\213.png" diff --git "a/zh-cn/device-dev/kernel/figures/watch-task-\347\273\223\346\236\234.png" "b/zh-cn/device-dev/kernel/figure/watch-task-\347\273\223\346\236\234.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/kernel/figures/watch-task-\347\273\223\346\236\234.png" rename to "zh-cn/device-dev/kernel/figure/watch-task-\347\273\223\346\236\234.png" diff --git a/zh-cn/device-dev/kernel/figures/zh-cn_image_0000001051690323.png b/zh-cn/device-dev/kernel/figure/zh-cn_image_0000001051690323.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/kernel/figures/zh-cn_image_0000001051690323.png rename to zh-cn/device-dev/kernel/figure/zh-cn_image_0000001051690323.png diff --git a/zh-cn/device-dev/kernel/figures/zh-cn_image_0000001052370303.png b/zh-cn/device-dev/kernel/figure/zh-cn_image_0000001052370303.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/kernel/figures/zh-cn_image_0000001052370303.png rename to zh-cn/device-dev/kernel/figure/zh-cn_image_0000001052370303.png diff --git a/zh-cn/device-dev/kernel/figures/zh-cn_image_0000001052370305.png b/zh-cn/device-dev/kernel/figure/zh-cn_image_0000001052370305.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/kernel/figures/zh-cn_image_0000001052370305.png rename to zh-cn/device-dev/kernel/figure/zh-cn_image_0000001052370305.png diff --git a/zh-cn/device-dev/kernel/figures/zh-cn_image_0000001052370307.png b/zh-cn/device-dev/kernel/figure/zh-cn_image_0000001052370307.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/kernel/figures/zh-cn_image_0000001052370307.png rename to zh-cn/device-dev/kernel/figure/zh-cn_image_0000001052370307.png diff --git a/zh-cn/device-dev/kernel/figures/zh-cn_image_0000001052530298.png b/zh-cn/device-dev/kernel/figure/zh-cn_image_0000001052530298.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/kernel/figures/zh-cn_image_0000001052530298.png rename to zh-cn/device-dev/kernel/figure/zh-cn_image_0000001052530298.png diff --git a/zh-cn/device-dev/kernel/figures/zh-cn_image_0000001052810300.png b/zh-cn/device-dev/kernel/figure/zh-cn_image_0000001052810300.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/kernel/figures/zh-cn_image_0000001052810300.png rename to zh-cn/device-dev/kernel/figure/zh-cn_image_0000001052810300.png diff --git a/zh-cn/device-dev/kernel/figures/zh-cn_image_0000001052810304.png b/zh-cn/device-dev/kernel/figure/zh-cn_image_0000001052810304.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/kernel/figures/zh-cn_image_0000001052810304.png rename to zh-cn/device-dev/kernel/figure/zh-cn_image_0000001052810304.png diff --git a/zh-cn/device-dev/kernel/figures/zh-cn_image_0000001053224218.png b/zh-cn/device-dev/kernel/figure/zh-cn_image_0000001053224218.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/kernel/figures/zh-cn_image_0000001053224218.png rename to zh-cn/device-dev/kernel/figure/zh-cn_image_0000001053224218.png diff --git a/zh-cn/device-dev/kernel/figures/zh-cn_image_0000001053710680.png b/zh-cn/device-dev/kernel/figure/zh-cn_image_0000001053710680.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/kernel/figures/zh-cn_image_0000001053710680.png rename to zh-cn/device-dev/kernel/figure/zh-cn_image_0000001053710680.png diff --git a/zh-cn/device-dev/kernel/figures/zh-cn_image_0000001053826366.png b/zh-cn/device-dev/kernel/figure/zh-cn_image_0000001053826366.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/kernel/figures/zh-cn_image_0000001053826366.png rename to zh-cn/device-dev/kernel/figure/zh-cn_image_0000001053826366.png diff --git a/zh-cn/device-dev/kernel/figures/zh-cn_image_0000001054624363.png b/zh-cn/device-dev/kernel/figure/zh-cn_image_0000001054624363.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/kernel/figures/zh-cn_image_0000001054624363.png rename to zh-cn/device-dev/kernel/figure/zh-cn_image_0000001054624363.png diff --git a/zh-cn/device-dev/kernel/figures/zh-cn_image_0000001121429646.png b/zh-cn/device-dev/kernel/figure/zh-cn_image_0000001121429646.png similarity index 100% rename from zh-cn/device-dev/kernel/figures/zh-cn_image_0000001121429646.png rename to zh-cn/device-dev/kernel/figure/zh-cn_image_0000001121429646.png diff --git a/zh-cn/device-dev/kernel/figures/zh-cn_image_0000001124146302.png b/zh-cn/device-dev/kernel/figure/zh-cn_image_0000001124146302.png similarity index 100% rename from zh-cn/device-dev/kernel/figures/zh-cn_image_0000001124146302.png rename to zh-cn/device-dev/kernel/figure/zh-cn_image_0000001124146302.png diff --git a/zh-cn/device-dev/kernel/figures/zh-cn_image_0000001124147160.png b/zh-cn/device-dev/kernel/figure/zh-cn_image_0000001124147160.png similarity index 100% rename from zh-cn/device-dev/kernel/figures/zh-cn_image_0000001124147160.png rename to zh-cn/device-dev/kernel/figure/zh-cn_image_0000001124147160.png diff --git a/zh-cn/device-dev/kernel/figures/zh-cn_image_0000001124306828.png b/zh-cn/device-dev/kernel/figure/zh-cn_image_0000001124306828.png similarity index 100% rename from zh-cn/device-dev/kernel/figures/zh-cn_image_0000001124306828.png rename to zh-cn/device-dev/kernel/figure/zh-cn_image_0000001124306828.png diff --git a/zh-cn/device-dev/kernel/figures/zh-cn_image_0000001124307264.png b/zh-cn/device-dev/kernel/figure/zh-cn_image_0000001124307264.png similarity index 100% rename from zh-cn/device-dev/kernel/figures/zh-cn_image_0000001124307264.png rename to zh-cn/device-dev/kernel/figure/zh-cn_image_0000001124307264.png diff --git a/zh-cn/device-dev/kernel/figures/zh-cn_image_0000001124310992.png b/zh-cn/device-dev/kernel/figure/zh-cn_image_0000001124310992.png similarity index 100% rename from zh-cn/device-dev/kernel/figures/zh-cn_image_0000001124310992.png rename to zh-cn/device-dev/kernel/figure/zh-cn_image_0000001124310992.png diff --git a/zh-cn/device-dev/kernel/figure/zh-cn_image_0000001132085260.png b/zh-cn/device-dev/kernel/figure/zh-cn_image_0000001132085260.png new file mode 100644 index 0000000000000000000000000000000000000000..4bc250489d5cfba6848f63abd9a1ea12502fd9df GIT binary patch literal 21297 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 TQ+($Z@b9#q@yVPMwm1J5z@3n# literal 0 HcmV?d00001 diff --git a/zh-cn/device-dev/kernel/figure/zh-cn_image_0000001132778524.png b/zh-cn/device-dev/kernel/figure/zh-cn_image_0000001132778524.png new file mode 100644 index 0000000000000000000000000000000000000000..7836a009e5e3cb6351c807daf9b927c7d3b71a86 GIT binary patch literal 40753 zcmeFYc|6qX`#)ZhwAd3d8A~O~mTbjLMJUT8iL#rd$bRgzq}13ILRsdNm}D7}W$a~` ztdlGw+t{bHN}qlGPCUq|Lgli=DYJ84hBLSL`qD#<^)CE59G0zc_Wl!= zbC>t&=bpol(n9ygKG|=oiyBt18Ch#4Vpj68tF<9Skjp$g;~=W9(zW|eZpH_53}PO% zRx@8sli9uB@Zui9=Z`p#OK$%Ofecq;WF>d~i!2yu2B_fvYt28)y?=`R^V8qtP?3f= zQUAqqi+&hY@b54E|6s|#fPGoP`|qziRBAFO>^CNoYpDSnu}VkFxokKJc9R~t)u|1O zdGT!j8!D6+iiOX*<-VJrltl?V+xYL(3O=vX;?C>#imdl-#oWI3-`frp-rX>gTlnMZ zPWiBZQNn$S7psPj)&Cbgmrb{S+GhHXc(xZ5T)F5Sn7{tVxqs2^*mRowL;v`{Wxu_^ zOJPrBy;~b5^TmJD7v$M=OUL4b|7hwryHGcQ>i|19(6N|*(Jk5Znggln|B{+b)T7ab zJJetI|3$BgWYaBrXO923nuhPNRY!UaG5D9E3|p}2*e~~F|79m6=|45AdSK_pcG3Zl z>*iTQ^VL;rLm^6XEUkTPxoS-|ojLK_o?hlalZhR7Yvz;()}TG_3BsNc%sS832g$oQ`ER*v z0(SF`+5);5@|^r40=riDL2AmpV@30qPr&&F)g(v}7Dz!QcQy1UN(LxX(D6Ea#cc_& zg5d?brF38pyt6R}Tdb-i$U@OmC|iZGTvcFqHwb5n#^IdXr+ODIWfZ>6IJ<~xEG(%Z zxE$;19oL0T;`+YbTmQY03lFg+p7B+VEFAA{^>47c_1_vJUi~vFt;6LqXfs!I%!|x7 zXwC_RpcQX^u$p2Csj{Z{RNO!h3~v5W^t=>rBg3i5w~|6Lj5ZTrmrBt;1T`nT_FhK! z4UIjw_W22QK#r zx;DWIW{YSg&(sk&Y4X^F>`;10*|WDM;^D7al)KNJzWY6R+hWK3MRWI$w-s4;?d&ed z!nmtTH}7*4tS{|WS&_Q!UY)e%1fc}}uPzrso=IUB+Y}i{x|eziC9MkbkMF~!j=p!DA;YVd^+=3@?-nR9sc0cf7)||ZDoza%1 zIKG??rg^k3CJUO z1rnj)+;~(DErrWCABBg2pbv;HM@abL;&>wO6y_R;F-?&e3!J8Cp(D(-zxv5*^cg^< z=IJ=C30d`YVb*jxhEAf7Ct9*@zb@|0CLYNsLXX~p#udD(70{S*JR5NG8q+H`+MGmn z%AmjmNIu6xjiPjiV1SB{+hm6`1zimu9%fI}4<2T0a8cSipg#5@-cDIHle&kPo!BH6 zPdq4^W0O|EN-Fqe#B1*CBR-+*Z2#(ynpTVXmca95S5({ga#x1UP^Ndxlq)YTcC#WP zrVpwrX0&wGn({af=Xae@GFd@zNhl~vfH*DH4_Juz{SF7ii<~sTZN^d4#u6YJ!}8tJ z4{Kb|N}i@`35bJQNCyOF+^S&h3%6I3h=9iU#TB5_GBfuWx-t_m+4q63fDuSDPLG1v zH|M0i0y`PMbfX+!j3}O#h)zS;tB3ZqsST z>p4Z`rly%IkdWq%Ublb89Xp0lo6e*4tin$C1fYlK4=eT*i5$b(jFsW z-Mx$E^F>(azU1~jg9v^p>_#=RL`XQGmO}@9C+* z2lhvuKKQ!LwOM_osOj=V+Z_?DMQHJ)i)-dcOp*Vgh$}NW8du?&FRbZj-1m(45)u)M zxCvQYmVKMI>zI?ByuH&4Aslh>i#o2Soc7kUk8#>J&42V8Ci$18M&RUIM!ydk>IH6y zT21twDU=~JCs(Kio#aDqrz5uVdyC8NeW7TgW76Ep3HD5q>cu$>h-2ZZ>53{BQf^F1 zJ<}glzn~(VOV1@$gAu0;RNOZ4QSRU;-Wk2|d^P9ItrE;9tbLpO9xf!r(;VCU=Ih~o z6d2UtC?iXiuQXFof5kX#Fy1po8A&tLdaXKh-g@-5hpg9C@06#>8XZYbzl=7ghE8`# zA96YZ@4JofRwqT&uEvDdj@u$d4f;qMg&nbt8KoVm={zoqTw1FtS)d?6z6)~{*mw10 z)eU*_@)K_$Uu&P8a6Nn@#hx&pnN>m3qO8waQSaL=B*9bi72<1*k2eP%h4 zT9F}AMS-{wD{JAX>PvC7`HJd$ zhKxF>2ho1glD_QI=5iDlU`;y{Qyt4;|I*$a#S!FRsr*%Y;>tkpYQQjf?T(K}yzoth*1oC5y0t$f%pZOGO=za%+LiTaq6Q@`iaDLq0snx7JI2hRJAqtZ{C|ccP0cky)`xYtl@hbV2$A(ST&1(6LiJr?}SJ*G~|} z<1L-=2-n!oX9^Q(o3BOI1IXhMwK+ZygmQ~Uq3(7i_64uvD&{Iod@`u^V9AAgnt2cK zAt{g2M|9h+9Lo82gD~`s>ci>8-o7}Z*(#IPp1U!wnn&th4K|7PfB-;GT+xU&iutHV z5f)A9HaO-P_mVOG+DiGodJft(*WU(8WZi6f^^wsIUuv^*NU8F%oz7-9ddz8GXT0F> zcJ1$(rWwwyj{u79%{ieLvy>?5E3ZSGiX0~qCPNXzmA#$Gv?kvN5}lqcR;A-tBub1y=2~s}_ORn1agFH!*ECv7 z)nCb*AX7&n^${=VKPSF`NpuzOLT|1c=aQDMHn|w)r&dZdNV$NXOwutiHrXJC>!zGF zh`1D_u~ttR`{^53MS@KdPUiKDr@;yd0Zttn&cq9Ti?z#lDiyz~dH1xp95!f=9WQMF z!bg;ap9GoyBD!#cw99;!6$6eG zwr|Sn?_qqR>cUrERs<6#lR@L<{=Q9CXXiFJlxQofqybqM(Kx3@S?EyOd&U#A7^Wlty)VfiVK2RUfHys!Z z8n3)-$yf|B@@RSq@ELp+H}#>`Mm4UwhO7#VAc#f`x|4={=lUz`9QL7d0>`y9_{`z? zK%wh^4KeCLbn;RLli{rY|-I;5iz=9jZn<+Xb4wu!SOvii0Q^rCm6i`EC4Kw$b+>p|+e z@wjRdsGIcD*Z;7L$~piKxdzhxjzPpO1X)l&m#$LIZ;U|``P36(HQl~E?oCpNrKz#T zXI5(VeK+D6H$lG4?*Vey=CJZ#ofN;DC>>||8I>m?>EOmkXa#5IG&d%SbpPR?2FndJ zcyg_k+NB*!x6*(NZ#jZSaA(^a2k&mg8RMbrw1TMD8m9TFk-E_vjgqFwddT|K*hRBh zA@B-5B{<<7gx=#%S8m5=#d^Phmb_|?3wFv<0x#V8P!BpWmhWdHTN~{%o!jmUQ>jU8 zN?rB(>X$F$uar>#{iHtHD_Y0Cal7iF(vLP5CUM#i6Shmie*R%! z2M;Amv5o*$>u`Sug$tD3N1KtN4s^QQTqPa^9drY^fk+V=mP_mED_RFJATHS1q+q)@ zG4V_TXqLwx9(SfRUiwaj)MTDt$}~osNqnk*ON8__`NeV|ZuAuErCUB+5CLWSJw1ld z*K$mV56Ylg%vRf-^wRSF>eT$!y7Kw-=#=Nz0fHrBO6`7-Zp_fG-mds7He=6yk@X}5 z>$Odw>O0SZMTib7{IgXsyiL}(kTfj=B}c{fG@$reZP!P|7cu|Ijm`SJACMVS>m<`paR2bbuJvv zM8V1q7XuJxXF#V8u=qVvNy+5-fhCqM}Qg)<&x{GvD#ntO2fwYtreSb}Q9p zBh%Yj!-Q=M%DT>;KMIHdxY=GCp|UyYrx8&sNhe!z-%L6^-DL;iEAT$OrG)z!fsKj0Dx+aOlc*A);> zkXWNsZtZX~>)R0Z zUX`D*InEOO@(R5G-WH?f9m05DF!^E{FVSXM0%iJ{JbS>boy4?5>0@A=aoeRB-Obk! zcZyhhW>9_OjlX&Zp)Bt4hu?_@Gb=JK(Y+8xuT=M}4f_Aepbo!QCB|cM{-bBob2SNh zTGZBt;#m}@;%Q!0{FwoqCHzTIdBv%4An$;$`-)fFrC`NXKFlzROe|P`r?ch@()Sc? zR9QResQp9qtKYfO*U*B5mhblj!9}TbDgUA6pp|lXl{w?UXkXL7k~>9DF39{ z`iB>7_H8C`v`9RHE3EP7u9)6m?#s6$QvpRWyMBSWBj+&v-bBqCv4{op{$HwMAuBJK z`dUu)nvDCqAJz2@VEY;@lGxVF69@7l1eWcI>mX)R-R_o_q`zR7$@aF{)*XQ>f>bD~kKEs`D z2-V$u8>dbaUmsjiI|6sz@6zCyHCpobUBCPYyN6LSN!2xbsf$EtGKmpV{0^1J4;Qkd zm-n5$uEMq!pN3O04+IQKfV1I88jV;sT7t-KL>K5oF5D*_a8x&t#PF#6gJ^>%WKb`q zWr=#-0w}hn&HnD{Y@MZw-C?1mSDL%T_J-4LQ=f$Yus)ODbVd9>POw!m+q__RZ6b@O zQvTJ=d3gL!%>iy>-<@mOoi9r^xoR};{KbSSuCU3c+dn}6)zB(r@6k&}xotSXr59lh@TUh@y0nHsLc;gDc?zh3s5`u(TW z4~rLs`WA#5?AL2}^Ti>+(F-ekvr%g`;o9EOdSduVw$E!z?SA@M>uD%;vdWo9`?91w zuP`c7msB^{^JvfFen>X&?LC5lr*>a?CS9-QHK*p~8TwxHrs#l)DDCciFJyI24SWEP z$`ImFWV1TTW`$$3qA;C#2F(9qMPjpRGR5#(vRR4lZg@KSMa?Tl%}ePwD_hZl>HROg zV_ENRgwhI&--e!$43(AsQ@Q+^vX?|UAulw9o4tGX34e+O_KIDX1a<81e#36n@=5*q z{`$>wu7VP-)!(A34-18?#b5O2j1Hg$$cfvZMeeCA+FlQ`@OPewDLmJP!W1&5Q^SC zeXDd^XyrW2MH1#}&-bk)3}v&K$n)BApl);QT)=;Tn^fmVs*?ywWgp8+)N$Cn8Vc^N zBrs=+ntqwHLv)?05L-Z&qMBvxv)ik-EeUXsXXk>8rzCASNVXgyGwxe9=@|A|C&T#Y zST96&ZO5K>9xCvxH!a^2K0QH2Z!#4h&sCCHb1g0)>ML6q`bwfRbG~|Q$XqpW+-7#i zJ}wTJUL1!lbb_frL{bndZuZE4d$e@qY6!5$PyC^Rrv~3grc}$8NJg6Qj_T>voM~Tv zJ_&dzjEW1XC?}l6K(-4O2J;-YbSi~YtD z>Wcy?2aE07c!`Bg)MNFWs5l~gZsG!Yy&VNQTl4A4F8E@UJuH9~0fCL4@LzrtZ8Af_ z3)T!jb4LUe(E$^e&{<2YH8S#QY(zKVi|7}}{9}twX!0OFz$Xsb_~@APB&u{ge*NmP z*+l~#zmhP6-mc&RA@Nk&`nW83U9pzdFnP3jhpkGKmjTN$DHGJ7*?GX^8b5MW7CANe zW7q((Y+zrraL_(@JrlfM%!kxanO$6if;V#Fx@6T^PQ^X3X+knZf~p%4tZFcG165Si zMsgAY`$x}~AsA>_D=*{D$#$iU?__qVC6*goyt+vDcN0k3vYvX5@cQuRsvK!<=|7e( zpIRcgETQh-u%Epl@|i!iOXd_5^(~y1^Z2-bPRr?0d3fz&jAs=!o%R5-+0~%&`2KNY zr&RyG!WdxVWse9_!!cIUHQHTR@4cDmR~04x0yYaK?MFSE#|?Er=Fj#Hd^xjP*sN2k zjIHW?=4E`Lv?Lmyo^T!+VeXDaRR3cxk96Nn^z%(>9n2FzaToXMKgu#Dhu6rbNf+Ee z$FGm9iMkEmspP)sv^hg$F)MooA|qbV$(s~1Lzx%Uq_W1{K&G{MBJUg6m9&cT7virD zb!FwP+SS5mO;iS;p5_3FivVe3y7^n~m-6A#hnBeFbfl%=(vq&n+y#yn5zVhm`JhF< z#M2WOUzBE@?}J*8eFtliiX;m@D1dsBxUtbsRSd5CNtHJ8D$2RRrcOVh5#c~{x{95i z(pX*<)BxTr7Uwp)sui)&Ixq@koKD^m0J3>s_IQE|DcXhlfX0Hz%0m5jtSRi~6TYYB zdPg3g`J#Ybo*i|~KPLSts&Zg$fC2Y0PBWW>=Z`n9BzF5dRL zOL)hjXg9r!Gd+=KG72mN5;uZkIJulKr7=_Y=W!1GS4?MQ3Y_e($RK(We-S#>GW7ig zj)2`}CVj3(H}4y{ReSkb&BDYlsiHApY9e<}PLUAwT*egTXu*y^Vth3E0`v7E3y46HWbwRti5RavYbYH<~y)8c9ab3-oKJSFs8~ORr$|)AfjH(&SbU zTi7-F9IHDSBjzYjq#`IIu&?NqAW9(lmq?MorN`fXje30mj}}BeH#;_~ldNUU`OQ#s z)H5e9ExVB)XymUmFIE;8%HaMU{ie1;DeN@loD4TKfi8xzqn3Q{ow(}wkecXy&A6w= zvT_KT(23caDY={+z7)c`6cS+p!jQu2UCrUr-&}1A)+1e*aT$${U>8(i+7$VU^~%et z?;yb}e1^P`2IOQXdeIpWS>K;uDYu$K9y9O`+~u9Zf#BqUd|JwGK0R816joWW70vS0 z+snGqC<4hVkme0Ko4nYq;urequ7*=MAKsxB`;g(6&KD*J*}ZP(1o!(77U0^0sYNY$ znVDDEDKsWN6J(j!|IcQX0}4O6_wNRwi54`!&%zml*=O~&yDMyDX1)iQ-fa8Pk(5@k zIS}V#a?IXsV&(-yOtUlv!h)<}_1bMJI$Ik(vhDD)_Zkck{kT!d`$`dT4=X zqMj=Y;#~Q~IYCZ0_8%TdzTicj* z6L|KYAjBOJ{v1(A$uSq+XWJ`TK^JPIy>%}@#zgRob^CdTE#w7t)*iSCTfF&+@dlog zw>afDZ`nWPSCZPY_fo9RWna9;2Go8%8wi)SQ?>WCm&;$pztf{xHh!`#8Td!gbyDA# zX7??Xj4JQJQZwl3y7-&T!GjD^X>iP7A6cu_{Bu=2l=%%E4^C5E8;`?0VQxsn&A+RY zYWqT1rGB`-MBMtU6CEZs_d%I$#!r&EjU-85c8U=1#Ic!NJrAcRYC`giq@JD~;5xZ^-r z_EbW-0D4ttbhTt4I8Ak6{-2b*u)r#<512@%ets>BD#}H^JO|>p4VrpJ4FA;I1C|!* zNUETBx0m>H7mLXh1%5Y}S-zXppA0|r4m_ey%lBRw;*6SF-~tGUHYP3=dT<7-{g z2z16tT{#Y{Eo@F%`Vb@~CKRoedu_yF~uLV&>5syaYB=_XC?}q2{XCAvGl3L=w z9COhaspr%@5SPI@c@_9r8QS89oYE9TMZA>Fj8=ln=tEn~+dIm?b}aqvFi*nkRgVp0 ze6DDllvr z8t?wIvd)aRX!6aUK0E^mc8OUg_t$-+t*6eqVPS`(^Np8*pSRr1HeeUDzpKu+u+M$6 zsC5r|pCwD?oTsqFDtYzryg=2CvKcVJ?VvcSIO%gsOnvQ%XmEQV;)?mA9(k6 z%fbi$9r;oFIeFuvqWLQc=l^VmT?JYStH(~yLQd{TN&l1a)_v>0tK@}?2nGkv*f}^+ zt#G>_7X|2x(#B_JAw&9ysK~Rco0dg=ih5EZ!M2GesmVb`4H zeOIw`yoZ%F-$UvW6Q4whFD8EFnpJI4(qRm=b zIWo8R+Dwk0;h|<6&e0ftW^B}2)!-d!$kP8N4}z?>?^_(VX?SFT8e(vrMAVsLkBx0HBh zlz%rW@I7keOkPK5I!3R%)E+7XbhFQtjphz50aXmTp?L)Y^7*I7$YT;_#p)PWpyDsf z2FFQm(1SRZ+tRacH-_vzbeY%V9NOm?YWT_(*|r;0gki2~;tVuf6*fLOGcz|rNT2-_4$i15hDnY-7qmC` z9V8siFoI3?VS3$1nqNx=__V?Zd~4CQeJ2pM2{{Al_r(@$L56s9xu@Z5$dIef7Gww#8x(`T=_IZH0gH26n%a=Z4m|@uq+30J?2l_d zlDZ8UqB}vfob<&{tXtI50BvA)L4+Jt{Lu|sIZu7Q(Mm|H%^-FGMzIC^V1k*A;Hj0Z zIy`heNaUc3vjOxqVCFe6X(iz}Y9WX^-j+bcQW~z9j1g#}&26sKC55 zSG2VaYTDZFr5Y?DpiO53YDsue(W?|AXI>I+0YiFso^Whei&XHnapQ)(QDu_(zP05zhfE!Gi_O@DwVZjUC#!Z6 zmjKcQ+2tKWgk~#Is$rFb?*3_c*st1`w>3TCCNVFVQ?R?*EQuo#M(8^qxfoU-!i~rS zB!rEpFly1__9&%eVoQNu`T*(3kCGLSh8>~}BTekImNAOX!q0j!_|hcv4Y%6YklD)B z^I9XGCcunHspGD((IMBW1Sks5K50vFy}4T5R!64|0r!l3p>c7zaviQ{SJvz4aZ5(~ z#HW%Nzp@hhGVHW-TZ)Hc@jur=hq(IFU!XCDIg4(!9V1nJld2I<;02WqmyPpu3ZeGs z!xp>0U(s)KZc!Tz8*sDdY`fV$-boMx`ns!ekrwi69F&F8HRdO@x{6eWnw6;9CwPmn zTF*r&&&7cE27xPT9(0S%MUl$aN;MiJ1b$%&15i)|leHxTQ=#$WI<^8A8j zu!_guuAO00*plwz&=~cKai2||#>t`{KwGQr=bCVhI=Py66`PRw3_oRyFK-T3DW^>( z(B=OKAq%YOOsAL!&Kz}%n%{Bd4*}fJ()3)hZE&PFLcq(I3=Yt~P1v(rFLVd!udMmj zKam7?3+}!?9U*L=Y4c(BwHwp#(qqx9fW~fC7Q!`;J6Zli@MdrvmX^DMqm;0NX^R?Y zx>wZmn7O8Z((>#I4g#Xxb+QAT# z^ijgTCp}RtwK&&>x$+4!9&>)})1<;^VdDo<`0)(&ZuNqoYnD$rSs#W!Z`^WDFpSO<6d1E}LM>G|noMO{?e{SE!RVEZLP(n?`z+GrTrPM&wI*K}pO)fULP zs#&-6<5RcBK0n@Zz&MVL0U-uygrYIMAXwR?iz;5--@~5*Os!--J*Eo z1Nu_~;xKUJ2Cl1yC1$@!>hDpW4yv7~A$l(5tVMBp7me&sXfBJbgF_D?HQy2 zeNbl^(ZDJ%9VO-)H?89jXc&2{nfJwGF2?N2CAf47$QHKzB)A$F!NJKh`kc`>UqT9h zw=C;V)ELVdi&DU~Ml_Qq^=b=K1$D*;eX~55@*nduqF;EQMcck#DPJ^)cZ*ug5VCzE z6&9zgf{kHL{W!&LOENdOajnNEQbmjWamT%*kPwMN7lN{8W_?Hbt)0d&QAfh|%_jar#mS{+F*|`0GS)u1dEr{}i)v1xEJ4+oQ;WB8 z%0r(VlY{1*qDvF=o{Zn3;QEFGONSkL&kMYj@N(Vq$B?ue--XVfpE(^VvG= z+dMlW9UN8OM^-#H<(Q%yBD}vu=kXh*UbQt_0A3cgf!9mRUwqnjiV)4?7)n$O(;p-F zC%PQlv@U33lsF$V5Jt6L4ZKNSxO&Vu9yyb%)Y!Gx?%@rC3n$#((P!Y5?rm;uek(Cp zg^5!H1(v6CVPX)Pki4JZEo}w`bo8i{1KH39q$hpQ8#f@fup1ik^$xCi<6Q)`rG)b{6g@FGCZ)slDk8H;1z8kRYi2X);2Mq3IYIsQ z!%xZpXhnj3&7q5~%=FnP zXwIRJoj)kHsCx_~eds+@yUQeki$15oi_zmdlif((tFRia6hsQjCplUWR=B;b##}s7 zP&srt)7I%55u0W7+mXdxH9OC!E01C(S~F!Xf6&y!k6*XP=8|EGSm7(bG$M7|-5Mlt z(R!wA7?6zVhewe-i*^dp005C6$na2uSmV?m+8 zF^oq`vOODb)+R-|{nZw5vdj);ueayzfueA-8kFE47hlyA3uJgX)QIY?e5Sb#9`P34 zG*?P_W-wV)4AGHxZzkM?uN(t61vUE{!PhDYHn-3_YV=jj=RHs8cZyzW>+dsBV)=hRT4uazqWLjo$Rt&Jhp`;)*nCfqZ=V} zkBy8Ow!FjAACAxUaon(Bk6EKr$gy zqAfQ(dPzR)IGt1#Z++|_!a>`W+F~9 zt&%1`(Y&_WwdxhtU#WKTPaD3j@Q5>!RUdk%P&RWI&U(YJcYJTLjV3y%fT<$u)3L!d z0u0Spa?^g!B9 zkn*rzQ|@b3g&=f(bE%#!yTnJJ!Yc5>vfwtlLeDq><|1s=bEmQsN8n|N-05b#*36szt-{p)X-@@SReR;jDfzGJ z)zsm$T}5I2_s_KU+mNSRu+uwgi84_1)cl05z#kSz1pKr-ZwjOo6$qoeB509lMZp|< z-|PqzPHB*wfUh}dQcq&+{T?N)?vT;wX1tBtg(+l9#nvs?Q2?d&&Hx~(si|DN@O_A{ z;ZxQ-`;u3JfbMKNp<;>e0+(ef&01XveoMO1*EK8zJDfrXO8{hj`a9UVWLAeFywWt=k45)3{!x-W`T@mS_`#xV!G^X z$oBJ+y6{J+O<&+fI+)_=!4o}1^~^U1Bw=65OSj8Nr{%h}cUxCKYEs>x8K+BFDxME>TB6^*S7rKLzJ>J!l(mJ>bW`4 zTz1q4!%0Ea6O-9W+aQev2c3Yz(zX@vRd$O)0`q^I8MY&6YRJ85ZVthJwM4j30$kP^ z$`3-?Fwr~0vbGfjnCC2$%5GfzZuo3XXf<2KdUv?^YCU%S^so&_=gxWPgJCr^m&Ys8 z4pWlI!|?Tde9`vfKW&@;*P!de6+}Uo22L~2rfUH{d z)m`j=_n_Eat#4{xDeMjWJ!%}DLD^F+>u_AzJBF-<6Z;cNNwDU>N0PsBIH7)=Y=i)b z$K>?C5Ho^SMi;%ylM?;^#_RlkJEmyNe(W{U3;)=egmiuvLUB- zfj-Ax|BGJ2#{RfneIUDSEPt~a{=z1UWZ0li{x{u0fel8wbEEI-?>+nn3skPmCO?%W zz4;gYf4Ba>QvZM6V1_@9EVTVzz*=UvJ*)d^+4UU`R-k*)`~BCO zciE^PTQ=%v8s?xW$OeSaI5(I|c6P9)IyEn*+5&cCDTNWi#%mPj{s%qchBzEfVD3_8 zM~>lO&ck~NB756k_~OMh-(K9peQe=SD)V;l9bMsl6Kl9fP*Y+zZ+g-Jeo~!QPhH10 zq{T~QC!}SOH~t>`aVGoy=Hp@ZgUTSEj43hA_7H)?Nemju!DI++)8Fv_U;`8rF8I!}%1@#WWxP%?!1*F+bkS zSUol~-cUsEvfUOll33uUZDtbEhvrtonl%ZC8$oKJG$a$eNpDC#WWzzQrVmRNgi`bW!aWVY z`3FLUi@Z2K{2+(hn+Jg8v9XYp-_tI;Cry>|&~+#HNvfw#nDg!9VcO$5EuYvavGTVU z)6U<$gWcuLljh4aV7&!x;zIFrtp#6pPJ@DTqAzMwAv%8q=d<~yL3wOUB;|Lt%k4_j zptyVNL_)pkVFN4y`&^&KQUAzN^Ewf#8Bq7hWJ?(HV&%!(!r(peAIYWw8{WJfyY{xe zD9uI3{)%KU4LmMc2Qc^U*F+yITCJ!GU^xJ5-}Su)vnZy-GUaK`UhIn#WVGg-4isK7M9vpL-7GU zz72{F?Lt8N;CHcd0?zO+5EgF<*Id!!tg!BGFVODcG%Xijx8dkL-oLyaRPMp6c@3!* zlGd~67HorKi)C){ZnG!>asIZ(`(j(-v9s>xVeG;P$JKt4Ux$WX8=fD~3NUgTmY_&C zjO=e1DXUq@PbMNasFmRr^N6)dCG>i$i~l10h*{ENE&J&(q;2?xFS{^ji%w#L7(@#g zN-N7^e=ws6McyGji4gs@98K*vY#_o9qdK{0P$1!!H?15K1y4BN$@;##)Bj4i+i;rO zurcEs8{>;ymPM{EMb$0`*dr)t)=1Xx9KavOlMow z1D>=8_UEVH1h@|gNDJ_}2%%g=w6{h!wPPDHV0z{}KB&d+#N>al0FzR_&%Nb%=hu!e zNrb%E1`9rPyBNwW$2^PF<@;rX`lH`gCeDguP4oGneB+%Lezz_(jIhECZDqJWYnSA& zgxH{M4d*{|qRaYZCz+>sQR+p7|}88UXIZh!gFP}88%z>qQv@NKV=})~GNkQ6}s=)qmr5S$SqDv|GlS+6) zJVf|7cUl+5p7WO7FQMASgz0bsx4?|S+vBAVFbXVD1Lm0c?q}>SK+?i~A^P3FKuJCe zCL2u`oR{87pyd(*oK&)#<)Qc^lP?4M_+uXsN|RsOQW~|_K$cZxx8h2aJ>M?|@VoPw zF#|U8aRyixsdE0IeU>7+p4HHc*hC}e2j`c&$q_AnBC0Fz@D{&TyQ)?kDC!Jo)orjL}Q~* zdipRU(9E1=}>cEcAP^b=SAtVmk=^gQhi;u=6mhH3@H zD-|_SrY8Q6+AM%s#d2SIuh%MhO{vB5q_v7$00~3Dq{*YNDMGu7 zqE5XkeiMUnv*47vuMf$*pNVYVf*6V5En-ma8P6I(khS;yH}ua*DF@x?yJE%6FB<#h zAnY{Gw(^9K#&gZ$HQGAI{Y93!d(5ivQjLb}ce#cs@#OC2YW2zx+RF2qO)1;Pvj{vp zhHiN0idupJGN1Srk9uZgO!!vzWPzlmourk@CGYD?a}?b~zs>?eu-{{W_-kQ8esYUw zPzh+gd!xj?%@1!4>ymXj3S7YzjOF_;LTW6&stjegH6~j9()EbWT?KZJ`10t&*3K4D zryy5kY|P28);26_YP&%y6gEhS-}@^`s`#f2r?k4h)A7ra>gJ=$qi0#t>eBN3=PmNu zBC5^$-}7Gj?t5uGI!yNRhsnq266c9?4U#oUGr>b@2%yrMz`LgEe}SuHBuLD$i?aa@ z(>R{#pYCy*pTx|I#>IM(JOKE7&bsZoLt0S`eqF#{fg^Rh0QL0SO|FIhKqZY zdj@`_ED0YCnZm$2L6-5p!fw3=7q3V*a+z786P-|A(F%U!uWGu?R$)z!rT`CT!#ul_ z{&v-fMBOqR9S+CN`{i$8nOdd5kDtljsZx=iqj$dho~nj~(nV+k4c><@gzW z_ssM3RU1KBzmN#sjMfwS$As3eEB;ui`jz}KE}60XD!73Q$ZekCy7cmU7qrvJX_@Y_ z)3LFww0Zan7+ywT2Gmk3l`JJFN7)@x*4QnT0)%FU5K2H+fM38^zz{a8iXQZOB`9jX zvK+;Smns#w(}bzjf1A5Xp!CJdX0oo{nFkY2vfq4y=W@fd@+mDTLL8}fr1_%E8Bor= z^NjwNkS64sZv(@6R>&7|7`0Cj#U09>${nHoV6@3z*gB~5rplN3T&d$hPQu7cjGyo2 zyItxZWJnn;Lu~L|wsaUKO1}0 zuBj>!+_tXy_?CBI8t&(OROY;nTJ33x@aYu&J*P&WVNE8fI#`(dIs4>sw`5w%?;|~L zKE2i}==LG{7z?V4oa#x+REeW2{*dDO)jyvD`9XDV^%Ouwls&r?XJVHLxF3@A@h^AN z1Lzy-g)Kh;LDHwpKUO{Xpzt^k>=>=o=ZeIevS00*iTl|Cq_jzsj~!A&9;-J;RES~i zI!$l)PpQqy1zqkZB&u_2t&Z!AifBBk%uU$#x7mHy z=Ho(o!J`AGc;hPV=8BL5@{QemO)|T~l%qxS9-lc=vFr8LVHWZp@9pm(X%x*n&yxF- z=GG8Cnvvw+Cm5uh@|en=(bqCwFL!0-uSRHr*%;V}`l_Q9yF??N^~P}C7CE)}^jnU5 zxDFnoVBpT3u4oh3r`CMJDf@tu&sBI#+3NY4?;2wxO{Z%62_%g%w|v`1!C2c*4VF_> zX^o85Rh1J*q*bK_7>P%fsEHqmZY6DMDx+AR+_7Kqf?#l&(~S*z*k_>iZS{=v z-#+yl^3}Kv`8s65J#JFp`5`=>`=Fi!-jpt##vj6-zWZD}w6v_?y$F00rYsgwKQ5F? zYl>ppF}jpNg0- zK%gVzkJM8s~R4Y>Xp4TY@FZ_XfTOW>MKFtXLZ4ItGwn%TDr*=*TdRn%w7PTr}U z%CzeQ*ZQVRBPj#~bI{6svZgN>-d|FJr%Esg`A#;h=j_R^0TP}l8~HZMft6WFKeK;|z`MA}rW1*HGkF#vyh`N#8q*UmH~G8+XI*6GfZYP;z(zQaI>n zfZp(7baX^1{w`vHWW;&GSMNg5Esswp^e57$dpkD{{m#W%9NDv2@V8CbTAI=P(6qoc zT*0W^<-(6wE@p%LEl%lwv*<4&(V{PA5o_1jXnsY^ow6QYV2N?T4{K?4>eSdx$r=Rf zW;+%Kq7Ru;snFW=W&;@+0NicK$S=u-m+J!rpV09#>V8Qr z)00Wje}@SHXYKT6hV)v{6=kW>8~X1j++vwE5}Wf9kKaY6HJ=%MhVfoRPj^jJM5W+O z0D4X(SdeeJY~*;^M1XKEI>UN&RW`YZC^{|bl)QM7JjEAV5<3kV5-2mXrLSpYM8DVi zvY$@uXXN1O=b9&e2NvCi5fk(^_9LWnIbtSvX~?9?w)ZEY%;2nr1+*+u>r9vI9}Ab* zzV@84A$)y?d_#IDQ1HhUKn^=iNjK~ z_keZ@%V$a&w=b+z*N{rs7l}Y~l}vUQxyHh9uH?sH{k#ru4p9_(RdnLp5%J!Ib1IMn zGJ@2^`4W5C2H6ueLJ63cpSpeWZD*fo0wRV_aCOI#%0yz8mDFV-RZ>$G#O zS!ZnMoUK*GCylu44R_g)UC}AjtA&Q_kBPZ#V265o{le3+7QgyGq1g8UctA7bT5FfR-)Mxd5W*| zgkx8OV>*h->yQChI*yI}>RLAWy4LhHHsR!Cm!&1CZzUzN9^M0?Fkdsa3;D&L_0vDb z4EUD}9xj2(8wN_Q>ob6L9SxxCC{wsvPSyo**q8nk!MB@GskPxB^|F1z?+8QaH{ z0XVcdZtS<-xNf>p-rSe0O$h=Cq3L$y={x^i!dJKA?2Xe zIz+ZCm9j4(JEJlf!ekx$ScZui+c1Nf!SAN$d7tO|zTZE8f6jf~bKU24p4W0;*L@tv z`8eY8=cfh(Tk22JcupH_Wn4nc=@$cJu?8!e8R5Cfi~O)mxYgc@en`BZ43DwwVRxA% zwoNTZ+z-C4{s?QEykxksD!{ROV>YLGy)6;8<#}=rE}PJ_C$>uIS>{rob%JsMqyodk z=^L5;zLmU1Id42CS=p74^(F(#EV%^pyZLP^O~N5+tHYtdW};I?YAHwO55UimjxOt< z4&@gpfiblUE5m7XUujger?R!>)GTf=b-j$pYwsF46$BROW&BoLHB3|(vkJ`gPQ zy>BJ@%MvrTD$W}p0A9X>i`!#yF@NqUigTC7d_AS_S5#(T82n*kkwLX@A0BC)w)MrI zo6zjOvL4|$wWXKRs#RZ&GjQ8{mo^3>!Gn|kJIB+RoajH+P8NP+-HLGae zGE-%EYYAJRi07GF73!NS;q5V-LlNXS5+>i5{dXMW18cu~{gM-{5D z3QH7o4_Ae&f5YI$2kXgdN*(A#zd{SQchnvikSbysJti`BF&CqHQ!Jx=7NQJsyX(Ri zQw(VIwI6G3Gv&B~`XZ2LiX!ZzknOzob!23rf2i-2Zx7Xq1~Sk-9s)E<4G$k@O6xQD z#6g{}b@}&aD6=L5I`$9UYtr`KrbM9hCwPi=hwxm=aY)y}!8e2+Hyh;8gzKraw{pm6 zLCAXm35d%tU(6}*Rbe1-_Ren)`7hc`dXON~D^Nt$w*o3~V)#2b@l>u+Nc?;dp>;ho4lm`3ETo%fv8ri4ZS2;7@mKc9tX z&!a%oIhcC&&8NRM(EJ|eE6cpQJqmif)*L%>MP1->?7#h8w9%f2uE{SfIt<$Dt zE{WUAfCS7C9dYtMA03aaJ`;1r2#3>_atJMt!8|o%BSn`Kk3J3+P4DkLT5qoUaF`q0 zALYCVs_&0-aJ2Xp16{*4BW%ep7l3vykzB?iT?V_;*`)x>==mx=$5J)Ka%^>@4+~Ev zBHO5G%g>9n$S2%7p7)D}mVXK2T;ud!p!kc5%<}OeNDJnEV?plM&r00amkh?P3BN-( z0y{uQ^J;y{#iH9|4pmlJB zNx;xZ=-U#V<{AUY#jlO6u?L-9)PCT^=uG&Z%|2K)CfIPd~lk)l)1V zs*~6r>5XVhHmet#>USw0p5z_1Vx_gbc+#!z&Q1$4^Cua7AQy#A^WyXUTQ*h5=yBv+2z(0&e|7tc}OcD+R{YM-RmWo8-(vpmjW*D$;M9P&T_j2|oJ}?T&H2 zgDrKGIQBOwc~subS(v{)ROJMxkCVG#4e5ei$UWz1Y~u{8y2G|^s2RLvq2^i_g%P7V zuWoE$o9iZ?!QIf64!bQb#Oi1>&QN$3M~rFSpW;y5>HQv1T+-3BVrk51LM7x%S7WQN zTcYZSK$V5^QtFa~bBn^mL9`7!pFboN>f?S*ObeR0lGsu-&4@=h)HcFc9qkt`L;-u4 z&XHe~yS&)xf;G1zZAF2;a}pJ3WM;!t+|T4JOGGmcF7s*s?jV`V*}t((3Re%1kW+DE zH`3LO_6d8R^kbP_-si}FT?^iXRv0{1dZ^-z73=c@zY)8#@#Na>5cM0Jws&T=iyA6V zCrnNoQD8&wTK_f9G{PHlf>b}rg;#~epr8N~O7K%=SmP+KgyK;QIt@3!fiIm#AK7>e zDO#H;>W_xg7GnTHTv-~zeN0=b7?EBu5v}fGphdpCe71*WZLvEj`jeQ1dv8#9~!Y-YL}Yn2Om@?(0kbW=K}4p$5+c=x6Vv2PbH5xnx!eQvUE-)%nr9(PLK zQ9^sJ7fL+ea6;V7t)iz{z^%iQxylw>4Qt>+>!iJ5=%9GEzD4R<^RUdnKU*ZxGtn;m zx0eE+8Cn%0Y|)?Z!G`7U@P&NKqA5cHB629N#aYknHu|)!aQ01A`e6CS{3_>Et_h+b zl9)P`GM6;O+@21X^SMZHyvCNe!)V6(jhV-_9O&zea#)X4I$47i02YrSls4D?Yoc6? z!r5!p!dA#)#lIW5UWGDcKX(;{Wjwn+G7M)7N*k|bGeH*_s7t)uU$vXo@*MO0TfA>* zHl3*Vs9kE&nloGP?5NCaO}3~nq;;PVZ_!e4#~gWuVOI6`Gc7aNYwv|g_|1Hee=YM1 zGCV}Fc@W|ZTLKzhfAEv3#?Paj?<$MKzZ(S1BWz}=hc2McPhy*>lXoFJ-B36Dg;ih* zmv3GG>M?Uav!dtaq{>Tq-0-6SL2)NBg!atv4Dw5JFY_ z3YUm3qg^W4w^q|t?1EK;b&DZ*{ogsb`=g3OV3w^~KV-kq-c@wH?1vH*G#Ei#mhVAV~V`=_i|*OOK&Ex@Ay9J){|@ z09tfDPn3xMAWK^m7a4Rt!-L4jog~OUo=$w&W`#SB3T;Td|GNr%2mI5;n!k4YoZ|7mRrU?#sG`)dQZR9FciE|1x%FkeIaGX8)}Qm`GS#DTHUb~5Kct-IEb)1wrdj7hXP-X~I}{D) ztZG&*xZywcO;#{N39N5rL*IigSOfqk0h2q8(H$xjt*)ko7W(&Q^w}~?sBu#RE`$YEJ4|^C67>vEPG#u#) zx1LRmXPqtcln`X!6WDK{?d1FLaM3-Y5N7_EnVZ*^DD^NGDPJjAM?g0Re)!2Rt%+x| zEfUP)$b~Z>i+iHd@9Cp^R-57x!F+DMq-6NS?F+<4`}Q+0Mu>=oSP?A9$;!XCc8On{ zTd}D{YxCIq#Qxs_xt|yM+*?Tlv%pcF%=T*+W0%p&`4)fv%Mg1Dm&MTZIIU4UtRiQl>NKI_4KrEVBcmj|;i*nar=^3{P?kf}e$*N~ z!b&A~@h7Zxb00DfN{jVn_?AW3kyY3Dx)Zqu&?!Hu{R^}|JHl0wwP5S-w3v_KWc z?=#`ru8UEoLwH_~u!g!9$=>yFb(;R|+it3@b>W#YM?BD9|N1D7yGu6BN#kl(UoSNx zT-q9~wml|_a{!ETv^MhLC;`%`Oyv5gtTb&(!U;Colf=s!jR%i~B$^@n95d~vdWP5= zU78;33=*N9?b@BIS{thx@d5v;(74?Fv9V~#IydjWtA$xSjQ-EAw&+xJq^vcchB??F zR(r-^=vu#&wq&TFlC&EB%?=*b}Y=Zo9JWp_i5@^HN$AR3Wc$}OHN5X&N6a)XX9@)m71d)U7O626V=o4 z)Yc$Bd|Aniixu)lzOYCD{H%CsMy>p8CvSyPJvSH5o`;h^aPFaha^dDH{WA!U-bgt&d^YU*29=tu)xspBq=D~@tvHECtzuahKb`Z?R!br69UaV79X16^ zD(7!&Q* zktjI^>EK0#e_`IA%a$gX$GLk#st1dvyNf^`xPm#*`5vNR?;EP=y!oyRPgQ>_NJThx z6ic6W{7I5I;T?5j?P#exc)++f(j7zSCk}@;^gD6LwhMVKh219t%!;eER+rujtit8R ztBRZ>+a*|sAL=&tbXRk~L}$en|6*JV?s1dE>R*MtFqrGLC^ZOpI%1!eAei)?&1AsDEoM- z8s&+-7In6AJc!{=kEVwH>M?_P?;rj>TS^}OsXcD5+aIG^>jVZONJ) z&;N*qej=xPgvne6XQFOIUzlFG4iF#u${iCfR<*C+uzgbGUm5k)U`SY^Ink#h)UHwV z1|(QiY6kMFDnLth2Ut& zswx_iT>aAfrn4Ud>x*s>bDYr@`H>>?dF!5=s?;Np)i;c;v%AD-ox!xE+Ty*2sZnpN z(x{cnc&bPCzp(&iFedcZM*%ndcwN|!h>xSqnFl|h1$4Pkd^dVLc?{-8u%zyQQKcezf z->r_da2w9e#-D`=p%;{yUa`|F51{RvN+JWMEbzw5_Z&X{_4|64o~;#$ zmve`J=YdfK3IttT3N-nIMOr#7Fd5q3`5-}ZKN9anVKwX>-+Ra%UB8l*>eF=F`?s=e z7EZ!D%hW1zt<}0XUTYScrnditj8;%3Co6 zpn0H+aSu~+-nTmDreW72Z6cLgbBI#%>nr7@BT#p{0bzD4mt!;Y;_*6nZ!vkR)gWTO z+&1dz=zeX}_oz?Iv(C1qF`{1xcX?{Lld2lDCmh=o`RvV2dQiYTp-coFH_z{5YUV_k zjOV~zetEF;9!Q;@OgSdAv#y_aAvY%Sg^*4CO%pDv-7K?Tz2k;XkF&p&jOkH)V z!|4LFC0gZ6Q$ntedk4QlZulYVYWLQTT>a0fnH z;I3;C!F%VBn~sVO@!DnB@CNP#bgonBRP~{Y!6pn)XHRoeqHKsYz&A3U&BO^5`^fiT zZcMvGSrODWH3(~Oo`@Pm9*E7c>;)kIwFZubOc)k5Tv(!2@@jm2Ul4Lr6N&YQ^^fZO z#Z-C4XE{b8SqEmAE;LoGD8I^rDswkWYL))klhfJhvY;C_5%=qRqHNC1{9Sc~eCJ`G zxB_}DXt`e0P0-bqn*%PlLJ0EN*_iZM#{yNu{BuRPJh#euwdN@A=73pz#l;_7Qihoh z_C$lmaYyFq*FTrJ|Dmwfr&(e(VLMnJfQasNWY}?XNKPLL7H5dXoL8s8Xu2|s4-PIV zshrrS&kv}r=F|;NCnrLFT(xQ)R44~&m1$3$@-Q*27cJgS+Fd+F{pT8kuRB*@X1e z8p-+>3hY?fjITtRNptT|jJ=5ZHqd(e$ zKX3(xi`XZk92b$(EP<+^E(vxgTQ2dJ8%R1w9`XJ$t~3!nT=ScH7X1$~$FiSs@h9-n zVN2BT8=d^lu#dy}hgbYs|1t-ey?c!X7kR_9dUV$6?U1j0SB7#~apX z%Z>$UR&!r(lYPMVbtO;An^+9I&_Z5h2HQlwqsC-A8k%YQv_;sVs|6Af5KpK4NPbWdFaQ_#7vw7=O~8QwKk2j z=YO$At@UlgIbyrur`&yw))Iv+Dgxr!igP*#UsFH_I~dFD3@xVQjyM$ny6*u1Ax#w) z5pXpbjgEkg7?NjPGsBx!2B(c%{8;pR^+PQnO^xJ8_@lke4A42SH$D3%)YSKc@-~RA zPI8s+sld*=P}T!FNu`cg_5~ zX8QeS9qI6n)qcfl<87HTlb>UE)1uTmW~4v=|6lcYX{T=Ep0w9Dx4l|)trC0fSyVbQ zitvs1%<(jsj4F|!LR{?+HBe`Y3X=bXb3&iwQ5f@PPb}p4?UVz+S zgK^9OfYkw)`0yWVO1P4C6oD!Lj6U|=hmCFB8jjNL*A2*nT$Byg^8D#-9RAo{AiYca z!%R`&-mes#wV9yS9PWxbvVF}u7=W5e9-BG;Z~XoaMPT=V+SkDK zb1O8t{|WjZliVf)BwY)U_`j~71FpM%gxmdJj0FL}yjr}jI^e$lK@)HVuKOL*V()NW z05btgwr{B91|Z^kr@QQT?*2Y>fHPRMF=(JIm|$DH{Fg*?>X{PY(Y*HT$(>X+fffL) z9xI$Gx+C;CwrAVCMBR|T^;K*?{Rph?Z*6LTuqZ*z_0hSVXKC;OpHz04C+zSXo(ThW zb{oD6{mZ=>1#0m<)>pq{7dQ#<1isYq>EAmofIDj@loS7!MF3^@k2$FClr5?PWzEGZ zB|BxBX+YT$^8Wt6|KkJ7f((P7{Ix{~2&?$35kPowyN~DsWsr_AwH?aD_d1|#L2pp? zZ`ptKA3%gJ3b0J$XYXH0*p%(8I@Ze%%m3bK1=KP`@A)g}pOOfa;bP&lJ7tT2;9!Fa zq$hC4GVATw$|}yN?znwS38=H^<0J9E5jX`zKq{;E%3oV<0RMaU;nH6fZ0a_HAs|Zh z<4!Gxz%QfHV!a(|Q`)v8T22p-|8*b?Xae+A!(Y|dZMDM&c$$ARp#2E69#D<^SHQ=L zfQZ-}{A(egQW!$eWJlTT)TezFNK*s?kN)*mERa=5dmvcDddI}X(;rk*9yx~pZA&`v zU>1_by%YcYm&bTF$9QcwXP_Hd;@%srMV!{Zy@%>g3fS7Xay;)}U5&CmZV1*%IXkrs zM}M#9By7>A5O(arPkh!#!=7yIBzb~vbVKXxUsV4~U3Pf;X`5}4GCM8dl6ZC~F#EhF z{y{P@{D3Z3yWLgVxjp{&KKSXy6WhhhZSQM#ik}01Fv9)SllD^IQv^aEY{;@Y&11PO zuQ&zxLIK*yW3to!KE8fQKK?fdwA0^&I&cVJ?odQh(N0A){ri!ZZwt=9v1|V8y!$}S zT*fcQ{|*Anebf6s{amy}K2-i+dWQAO@7GSs9#%MC%yVVuS&x7x!^#`{BwyefqMnJ^f={M9!NIKs)R=kyP)j`IVbs*MA8Vz@KQ1P*~rj)U!vtHL@!h_T0j=B8Ioou%=P z&D$;<8{en;{GRM(K<3nPFYG89_`B=)wixM7uXwrdDeUr}SLt1^YxCZU^?3H7YJ`s$GR1#A<4ya_qqiaRvxu?IZDG*!{r@FvN;t*G|4;LY ze>yPB4Z@YxmuVq47q&6)NPt#w@ZW-@{r*QZ!~dI6aQCF_z7DBPO|<%YN~DmxY?WAGxi)wp;7caNE&@OyI7obr+3EEdK(0%*M`%OV9sp zcFmz6U#*W9JBrh9+nR2>1+p(ij^gxff1xB_0?$l&{ao~B1c&}jL2?luFi(L>?%Dcd zyh&@24z1q;U_&wG9oOB~m>!`b^#US6xK;=YU%_$1}Q z{SJ-eF6+^&{98-_}ulNFV^PAhr$fx(FVs+BNEHc0#K`ZeEdNIZS`M$pIC2~5Y zy&!O#u+almHCZ;tZ~D5gQEbR@#DJ@tppNjEvjZEiUZ2Ah>ynQ{tL&yl>XSj~aWYrOFY|F?> z0D8TD=9h!#|D>#rE;5-=PyDx=+ntRftO^MDW(LuREkOMF(PHAJC*R6@IZ7ItF-$rN{dpd&$W)Syw@gJgbyc-RE({DYwSUR{ zOJ&Ty@B668=;)>vCw+Nwp;pb+0C9hzZnAGPePgk04Ps57K;`OwTPf0${9K**QTx^Y zbiYW&t7jN9iboA?_AQke;T{Itq#4SG8csyDie(H%JI>mP)E{hMl?{mHjT*Z}wcqOK zC6wBceCq#f9^YZ%24z5dFV=6QKV<@}m{kKV!=Y_f3?Rx}I;TfKc|GEo?=w}A1)T%= zmx+P^Fj=M@joypLO}%5w9)(HD%yH5rHg3_&h{@f_RMUt-1+1gaNZ%T$lY61;=lSAH z)hw4YaQCv|0F`aN$iMW6H!5oVAzq76$`6t^aunbTVKtiP>U>{r{s5pu_v5_`L*s!D zs;b_?0-eEQ24b2AtdCv^ZCMb}$9dS_h^TTuqc0HBOT5L2klRqql=aEO;_uQ(HZ(~?eG>E3m{MbmSb_WYUHovZYw4u|tLS zg;T^c9Zwdl|2VD(m07C||G#l`{$JwAIJr(EqNCyf?6#E+*)a5kZr@wg!;ZQqjQP4l zwv;7Z+V-wL!~6-ey!liMrYprn{7N=1oJ=5v(Zq^3nLOh_uS^kl2LN%*!V=+w)R~(qi|+&o~{zj)q$aa-$oq+Z*9{g)jU!L!Y^8g2B)#a?jifX3LAAw>UQyK5*{dMyt^ zh~NE*-xqHNG~589yIA-$KMc}1UTcz@pEkvM<2$5deNObeOFfo*9ka=_u-l9@=HSDT z{smPi{2Th44`O`_zLp6UwF_1IN53lN&jQo@zn2P|mBPU?9_P;|E8|akwfk*G)~|Of zK$nqrKwh43M8WI5t{M$J^WG*(eVaegB(oHjP5nJ_E6Rf{HSbfCJO0?7qqa50dHmh8 zfjpGESxOGGH~crp7dAUlrD)FnP8fyx;s+iWgLo@I8xx-ju?s+ANbtNWhAnl0KH>?rX{k#V+gVbd3a9=r!#oFbo(XxB!|1+*i1;Y zP47GT^MZ0e@n}G3(Bi2qbSt{gX@P-q_*y!$GcsQ})qHq05WrbQF{JET+I*vlBo2*$ zp7rLU-$*;VAc{vrf z9H}|y-RCz^Lm^w-BNnLj7o8)N3!M44^84TU?wQOdK1aW~iw=2V8o`}!MPKC|`n3Xk zF3Gc=JcCzes(t9q3c(c`D}wUPv?sXSRDG@{3O<4R#a9TtL>dCCYB_6bgtReo)22`C zQW<-ExAq>{Pq|@IYbS&0w_~bnVas9o40)+f3jW!!=N_GcyMZ(A#Fd*urouI33q82* z!`VpzU+290r?Qd*XdtZS%+OnD!|KYLMgW&<`UWZJA@21X* zmLnPJO7M-?I;*vc*!q2g_1TpUo=V(W^e^=9X|ARoENDANJ%?~~DlATNs)uikT15cI zn5t)j*9IRecg93dL<4fkFGU!z!;(D3k*a_=sosav0u$4#Cy{pPD|*K>!D^xDNk-0FOK zN3YyIrTb4P8kB*4wf{D^%-TigyT)scjV~-xk=4c{Sjs5lvY7{Sw9M{KZ^0;4ZDb<^ z?cqA9yO{DkY*(xJrqb+PT-U>79rDRY82yxV^S&*g@a)8BBeGC4+*v^xwh*;iZa0wq zf^2dzwXQ&cJ1u!p=tmrnRqs{D`4ZE}lBD&`C0=cYeOd+sqV~C@k2~;Ts-vk#e@`dz zc50eLtyoQ7%;2RLsNhKUZ|nXS<%$5t)qkdH-Za6t;%S@#e5luUd2S-A&y)}WF4-!> z3a_3ZLzwUeYssCw>uhEuaQH48wo?l_+O~ zx5rBe6v^Wu``lbJgle#N1)dx&1}%Zsj~?iOcZEi$!CW~f?~Yle#~^|qc;G-9ql;%0 z9%Pu7v#u5?we~*zGwXGVaCcNRsj!$noL+a%y7E}z#X@Hj4R^0gVy7|@-=6fy6<^hM z8tYx7DiZyH7n+oTNW2cE`=L?ONgsM|FH9^VnumV1Lq=Te7e&eL8N-j91-UT~>p$vB zz}r@0)Zyvn4s3OT;~f=*Qz}{8%IZS5@T~XEj@E|+?bsoq$yr|+@_F(i6?gE}=a_n< z)}d+^+q?hiK;0WK3ln-2eu>`v^xGTpGYpaet?xA$E51%;HayHzsLj}v2=P5IaVJQ~ zpOhHRH+w{cw5T*&04CGw@Z%BRdh3qIOx^tO9EKh|Ya|uK7+6+4+D&{onr_fM^=D*h zlnKA|0U{2M)>+S#@SHeZMcV5-&9_f!14!ByEjOJVlTZucNz;+arxz)aKfoKig!Q>Y zo{uEZ$U1iSD9ZOwc{4Jsov^Js)th96W zu(cgRN~M4ll;lvFIY_-*?1ah}no(yfKKxgxl&v>NV1U zT8_pmp~P5T$XcL{=cBKTesa0bFp{gb@$_~F*aAsxnj8-3c}<$j3y6DEl-k!@e_8fc zv(@!Fo8Xrcc>x8t$;RTk6%Ql1Gx}!o-ol*yf^pRmRSv=6(Wt|(G$v^m^K|Fx(%?5q zbt;vsiQ=aU*mc^^gB>o7-d+$3wq9ZXm*X3 zrupM@gIqnbGAg=bJ~Ovlw78-w7eVl`9Z1Rjn5MJ|bNrPc>@59{XiSWav~=2v=-p2E zO?UJ$rbnD>(IJPilIl#~J7*hjYqe=;v}j5F~q-IIv*O7Ubjkw>GSB*>!M&( zxVvym1Vv?ullXW;O9!Rdb0EXHoc0Y?3yLe~qZ%OPxupGk%tDQVP1NxzsD!U<$VJZM z9L|$@%B!+X4Gexbs>&}IoEA{{-4l`GKTirj{K5^k4>S?u77)ub;I>DGqg$=;%;?ie&&h*{%)Vq^g$^C2ZT>U+C^)G0s zEq(TU`_g*z@w8sDe$}rEHarr)8_SHqMpdWeSMd_=BBy43@EMdTmU=U`X)h5HoWo+m zxy?dW#V+2^o;O1-3eTCANyiTb{jhB#$NC(vZ~9%z2@<{FJx{avr4JyW$-WCk(GAkx z4cu-=KjuYhx-vMhn-#Rhk4ipy&96VGeeP)aNMrPw_+0y>4{D4OoDd&!($SI#S%9te zXJ}2*9H`d@eOuLEU4taK1uUQ2v;V;Hq@(MBx346psLt~Iu>EYTPSfoI`;to%I{Xc$ zU1!%iO$yw^?`0%P+9WT>n_P@B9JPEAAaPsW{fjc{cJBd7jAjcA^)8m)Dd1MES)10j zntrp{>4nNiq(fyzmBZY?WbSm_#b9*cu3cjI>$+ENH;G7QWC{zBNEJ;{CYQ4x<0||< zc;5QpO|dG+KcRWQNclE;;Pv!94avjUK1$D?oH%j9F)Qu^r*xFVLefB0&)0MUnS8(f7!;8V%+W&QC>80XzWj{ zA>V-4VC@5H!`b2>{uj%Kjx$e^QSvj0m z0!pGo9rn64ya9E6sc>qWGS+P;RkxsYdA^wCC#TcCOrCqdfbqPQ6C>Zuz^4qw4y9>I zgtQ(wdd^T+y)3O#Xf?fF%W~bOr(N#C@Q}3!wj(;V^W_Wep65EKlae-OXOlV}X62#s zQXN#UH=s^=`b)`mwbcKT*rQZ2Ye%?u$o^zUAGdZG#A;%xjb*C2qCH`@{wMD()OjG* zXhHWNG+#sg)-lwqWpTk~agjTRg)$cjU?y7^uG_XfFt8ra^v}UYrBJG0G%gEy;@X-= z*>XEmQr-1h$@Oa;t2do1bEMk*6Eb36;cC5eC?yS|2mL8>Ov3OC#C`8PjghLXTPpb8{F!%+h`^-;6!G`<|9ut z*kKaYNRq&RBuDtM(lF~&U>{gAi*Wk$16Re!R8BNf>ZX-DQAd6D&*no?U3;Dz<1Exw zDkMxAI`$bpdm>XQAg#t!yS6-eC;~iz>0is~zZ~~lv7~~oSQ2y2?GZ#f?+6NE)Eh++ zQo}t`c+~pjxCQ)*9lxu?un!rDbvmqec;?W|FQLl!isx(ojOGmthKabZDVKQ0J^mxI z#*ZJjK&>k(*a5o(Z%{FN7QVGOMMBNOLkI!ufRqLuCcd?1vOo=(prGcajI}pr5&}5I z>4}3|9SZ?!&5h^3} zIo&WNNENka8jE1HVEm?ZHvP3eUo8VU5@f`~W~kZ64lmAa9=D@fD<>bz7(CWY6<)t@ zM|Q;2vF+=|m}ugqzAQMTmSuc?v!o|G?z)bklH+$~1ePBqs}-f34#uh7KI zXOxmr32lDU?e^Tb5k7S7M$JM+fa^f|fYdj=u2G!@oJp0qlzK6Aw3aHu0NPLT+rrdx zhKx7cepx_QLlm~?qNEMFCy5=@KvD3URH@_qglS*wVYBMD+KTEqqcA9o4kt0R%-E#0 z?tm6=YeSxeNI@T+)%d1TtGwx?{nj^MxQsGr7loZ8fh^sJTNbG$bw{dbeyOqix3;5?!h| zZS^=z*U4h)}BaQe9z((MA7WaOglJJx3`jgqDK8W*3U4C)6$v zw8WW32GOoz=^y)TB4Q#oXuz?{y?XYoHq(Nh^Iel6;BwkmB6=ZN1nXz4nr;(GD`sP- zYDZykDBI@ZvZ%YD!`BqS+NnshKJBI<+FkATYfDBQOOA#$-m(g0icnB3)~T2HJ!w zF^XfJX87@~mmI|03+v@)%e5L#(AZ1`CmMqG_m61s}qm;xE0e zSjkYZZJ!}0zS1K?i5(2auQ2y7s zCZ6Vu#52l_h-cBmlb&uh!gpFY+V?K-su?!a*Nzjc>Kt7eD+||WNpSGEGHX==#g|!Z*VbV1`MSHbM8F*RM*nq6ai?lzi`NXqMZYXd&9$-*d z=8G7hzqS=@Eh0ubf1~6VKs;s*Z;KLsTH0wsyDDct`4-qohgjiEE_6J-Cf=EjvM}0` zABXhy^{y<}ZwQEw@}|m{P^0_jd8%NquBGKA-&!|!l$TTtzoMw+R1PDXYD-+-)Cy1z zxz^F=5_4dN-!X0>zweK2CVc$hT0}=)dd_^n^FM9RHlN;=PG2^6#E&1rOB~rkqvxbT zB!wXkiZ!ZV^7g$->}p4&-TSQa&uOeD6wo084)j_$Al*C&vn)YflI2>3Xw1H!Qt^!? z&MBxy(EpHgpTzIQ`96Z!P}s61<^m&#jjKGXd^(L@xJP#I8~Z5vgKHr}N@-KeX&Z}} zKBz(6YOR24i_7znVG$sV?;>Z>;N0uX1!JpV=eP`EI`Pu*J!0c+Bl!?+ufk+cSC+n- zKFa@Uw$_T`FQHES0Ko8Cbo-_FgW}gK=p>a1GpCAH)JM)=Fq{feFoib3? zTid1Cw98`NB4>u26zTr_>$&0cWhjp;^HOiZmg1+E@q^+UGj{7Nm7@7!*A`t%CT>~P zm$o{%i0NLCN=<9NYibHrTYI}If1GD$sak1rAPh>YCXc-rc!dOrlFW(P%(Wi z`Y`=Z^2a1YtR?$i$yJ*)fo0Pp`8oScsJb8GkiFOMtWKOGM^{TY1G@Q&ZPr=fcR>$& zB6yq4yxCaHvmed;%{$={lXw&67Jl0N!sE{x?yrq>v!)v`s$vp*)-+1?{~V`q{tRE= zqgGos8pRnmgRpos?A3lQMEJmQIrEcA1TyMD0H#U0sZSkHmxH?3dW1aR=Z0v%;V-;F zy~G;GqxE(wex=VxFGM#qlKI|tDe2cry}FO)qdobfcQ9q_>uBgcl&!(ZN7_qslcv6Q zd1?=`TN#?UflBXoIUT7q$SUFqK%cNOO9`CSH7{jD8^*9P`S|AEnx-kaN5Y(F`* z=XNlJ-)&#!Ww=A0{vt8$>A>i{ddhtEJ~u+Lxiaj1dw<9W@?mSr;rwcqMG^PPL~yRR zrzEUFUM&)eJ9ss)ebn>_k8WvU;AQjmK1H=B!zJ%Fv;7$}-V=zv4+qWqoMUt_Qt2b8 z%J$JJN{jGZ&_bh_JAQCLRWhVh$)d;Yf{jP5dBZ`8Sv+?&kxOs!bQ$^U#AR@cgd<*1i>t`k9sR-aO&c+C8s|0VMW#i# zd%0HG8Cj%|a_zO=pB;B~-D{kBY4hDTwYy#3g|3n6Lb$v^*%Rx%s)bbdX6Xk}el>(d z)Mry|b(?qNyx`i=I_=>sqF$7+Ufct&)0&?9l0D`J2e#PFFr`++*c9C zyw&WmJT20v>*f)KRjbG{ zr6S#30WcAFbWp6w6f8)giaU(%=3GrW2MLLK_F*U&@wtd0D}aut@Dz)T?^4U%thFsd zURw2Ws=I#=u^UEC)9JNu_@g8%jlo2+mup)>gp1)|dnxg;oU(bOvUG*1c4?WM2W&wS zgj?k(L~eQrZ_vz{vwwsv{VRgO@~1*r(*sId(ZcBCI30KHu)Y_%mxCYbR@&+uEXPZz z-66FSLiv;`H-yN1^eA+-l}i`^-e9>ZN0?9S!v zw3rR^Dd4E9chf>SYySQIYUPcRD@3I^h`XZIq#G4HVY2-4+O^U37h2jHLh61!s$Cfx zw-i+Wln$+*njdwG(^#t%zm~(D`YWk)zZRj@T)8LQ_F}tKGgk)rUKS_1H)fbWYj%aU zq}3!w$`@UqpSU7ZhwYf}E9v!Y9@zX}A{(Ov62R+8UH8$?IxXff_2AI0+bv)EuEUlw zslqP@5}F+gnm}s9l8~^e^;-=|WWJI+)K_hyQXxMtW52sjr?U{w%tPW-heIv=qj{G) z^Y$<5+=2PAwJqMWYNaXF(Q+)0nNeD(^Re)hANd4x3rN8)Vu>8r8XrAQf zuA35%guR_5bl#e~tG>Om53hIXpCpVG`L~OIVfYOX39BnSIiv$81U^rE^7O-V zwS9q9g#AOvUxgQVUXA4CDEd6b`we&1%*Cix^(i88&02$n*u^{SdcD|OLB2Po_@kR^ zexjlXvFJUE**IQ@-4cO(i*4%q^gK6kc+|5<&RY!e`dRUo(&f1qWwyj8QR0nMr)R!+ zK}!=2azwJM+JjUgu6EEz(_K1^da2p97eilUtlc>xPfCtmjUPG3$Xkdi-3ZxboxbZ2 z@`W$;;RgWRyUilInX1VyNMdaD2^~_#gi5Rho;;haE zyoByGlxEtr68y~_UH@7tLnk!f@E`HX4K=$r`50O=-7$) z_dVZyq!dYidHicUe6@%m8O#N>>7WOW5+~me*Ob}R_1753NW1?i(!XXy8Jf%HCFRcj zNub9V({gG`PptYuu?ytjI>^f9ySX&pPAuKAhYQGe5a({3W?TLk3}Es z6&FUN@rzy1U*+wDyn+5QqIO3g;0-Qvpzox+>*07+iNG<{>(OHGo$QuRLW{=n z!&Gxatx2;}Fgx-@F($g0!?K%yaH$W|-*n?Ocr+S(Ro}^sr+Bct z{}&9#vlJKw$HO996v_GtCN@+uuW#g9AG$WSMO?dBB$7{SMsEF7b9Fqh=C?lORm7-1Ct>S}p-Q_a!9 zBq*lFvv8Pv%y**N@Bu7cap3WDQK}$(T{K6)YW?+!j0&cK5}c%bDOVha6T4umB&?=N8*4{_Tw&zJHEpH(jg_Ddv;5F$}u%`h|uTGYmPUx%TU5C z-OK**FoOYXNZ(aFm((_r{ZUxx*nXF6q9hj(NiP6{6NK#u8N**kx*RQF*K!w%hJwL` zSYbQL)}6?_rGpx2I(s50#(nf?45Ke4*Z@m4PE_wS8$Lvx?=cM+ekucdG^CBGCJBPMwYog9f_LjQE4VF}T^aZND%EpDdgmK#J539wL z@T}Eh4@oMbO@=)kIVmGuqLtT0)Wr=cA9C$%M*WQ<+&A~0S6xRMf0*GhF*A$ol~1(; zVeJ=!SHSGWic=y<_C-ABq3m8l;hiy2qPoLoLUl;c9K5dvCk`M!DDS~3Vw6&HR|L=! zKcY5gmu%TkZi;oGp4!!w$@CHKD1L@E`=o+2)<4}4Rs8&@W7+W6Q`8J{m|8rG?Z0`w zuh;Ux^E2;$Iu(h#fEYMK7IS;AWWU!4PiWw?_OIdxjOGZI1R+U$l8MVzt$?=^c@3$FUep+h`ID^|;CI-(L0bp( z_zU$+lzOgWVc3g{hrpLor-}2_zi=-TKj>%?1Vp2(M``B@XB*0Ul4PSKxxTY(3XWpPH?pk2_?rXID<=G|6jAS4K$b7}NWy-r(%X^?bgP6Z9=Dd%!!dAIs z5QgcgkVD$*7tztM>YCXiSp0S}(^7XrEhF@?DJZ~v3iU8u9aWnXd+@A7kpmCyYt0+*%QhtWFI10t2GM2m^S720~t9% zTJlM9ZZJ`@tr@exPOp(^LJ8v-GD<9`#rml4HOACgGlM89?QME+FYil+&5?5Y2};)3 z5}Glht#pE#GPa7DYfGoPrqGy@!RlWyP1}>r=BHEA1`dmYz!Jgu&&Id}j>I2{g^;r# zheTU2EB0=c6|qGr1-3C5%1PB7&ox1hGMz27@_J%(Yxvg=dcF4aol4Nm?9_}hr2?sG zl+3vUMtAryR0Im#d3J0ZfG@@uH*{i=f1;?C#DaQsz>gd`1M&c1RyW}BWw51 zLX8dl#$%wyYblbWlUWBiGr~L}=Yis1UQhlInU?PVbYm_IYD6yd1<%sK7+?u%a$BP7 z-9!uYSl)gn}B+Dp^* z$H64viKzLz#W(-$;x`@vknEpoLu%KB(iv|XI22i=Tzy9`nwJScxNSo>UH|auYyMyO z!Ne&BAqVxNVE`hJIPHmp{J!AVleU2@hOml1)r%(o93V(eNaMikJ-&9yV;SX^_q^>9 zs;kzzT-0p@2xj!fu=QG6es}SOR>7cHj}1=E`q8KWQGC9u)-zu(trnmrPUE|E1zMN! zj1K`qjBgCX=%w|~BI%0!e^#XMKr3zHb;T6*1Qwsfe>QSF@d4tn`~V zkA;GRPJBF8J-M!_b;b(dD!(YKRUa`g0n|q&Cx36EM^-5cFw#Ec_8Vxt1JKyKv-1;Y zJ>uOm2OP@rc<=^FKGsrlVd(}#pF~K&hvkX)Tl5hWT;9#JDmhoW9J~1~@CptH*-iG3 G%li$dV|{c0 literal 0 HcmV?d00001 diff --git a/zh-cn/device-dev/kernel/figure/zh-cn_image_0000001132935054.png b/zh-cn/device-dev/kernel/figure/zh-cn_image_0000001132935054.png new file mode 100644 index 0000000000000000000000000000000000000000..238a15fa82b6095a13ee54bd3014ed3c08c21b4e GIT binary patch literal 19889 zcmd?RWmuG5^e+q}>HrEu2uO!?iV8}{pmYcWNDCre!qBN8DX63%AVVobr!*=sN=i2f zNOw29d-Qqq`JeYa*L%L7FJ4~veeb>2+I!`1tszuh_1M96UxGT&NTd1m@p>hnJuD zPBka+KhLCOLb~z)e1U_<#^eu6#uJT|!7ljy9V2|<+`s<^`$WT}LR6n7D>D7NEe;+G zwfzqX?1}&dC?lNxlWOLF7C|)*|3kFl8dwr-l70U-U%%c2a`^luDP=+mfp#erYI6SN z9!Dld;x9=?0esxR`D=q8$p7#ug~O!C@DI;ec@qM0WL!v>wFv(5<`2sx{&f_;nNgO( zVG_Z2N# z-xAHP#^zIA`$4(yPP6Oo@{mg(BL2%*rSn{*fYyj}ezAr}lF-aZDP6hJZlj$hLv@X= zcKmdfP)O+VL#*-%;03h4@(AgsX@Q3bHB9zfAqH^4*Ij14j68TkbA*N0xkm26@H`3b$%XV8%bo}u; zZjwe(r;#!@`+2Jy87uhXrf(_^?2v6O>6XKH4}3b9Z~`Xrl`~sms4qux)QsQXNbz0c z;WES3;AmVzU?}hrGR%}l8VQZX*BTQW6E+{@YW4LX-u_(BT4hT*{|GVuHoGxugu){s zsij4D=9`_JNW5C@PJ2?kzIjw@|M&@eCuL`!szX)2SQXp&s{U?zXL6nOL?f44>Q>Yq zqTYw3!1)p`G(r~W7?Fi_fK(SA&o$eOKqYdbs&P5m+kTpQvFOcO1?W%Yf>AOIF+?h8 zHzjQq;~LS9;s~qH@=P{5`YLOeW13dnm}}$3v%P3rSdZ`AB!j(+I=gB(94&`fsC;G!^R{u6$2ZVq3(illM)^5vm6P-)EuAG z*~zz_#Apv}@=~HG$TT8;dQ4RY-XrHk?r4Rs>Z-<@4e6QdP;Mk_y+^B=&wS2ZF!0SC zS@aewg&}M0T$g;8{XC4-tIJv8h&XSZ0plgACv*_lAQ3P~*W33A@E)r)K%`&1Cqqy? zwY!XbP&xSWWp^B5fk=Sm#^mN9!TG*|VrS9e4s+uP74y4Y=wnjF$B$oGZ}dKvMR*v( z^H#KdooGy>8L9>udbEZnpR_ew@qA1_LHJ}4D~(KvZ2F9|Zymjr#esYw(M^WY5wWt$ zn$+R(?Dj%bh7qQ1pQR!1tTd|(3>s|?GK^UTwdywKOBS+R;ZC|bQGsd*uj+mqSEK@?c((yVj0KSH-et0dWbcqO(JxrezTG7CtJ5Cb`zi+ba`IWAKgtT&Uj z_i|R35;t9kMj75}d!*Z$&K37c3}n|vwezfL){XZv7#1vQ)FP8wt+$j6ee=OtY_X^_ zkX*2Db@17w39e^3Yz#UHutB*)+k&O|s8Ae^+&5p{3;40*WXx*+gybcm@Jv^kck5E| zi%Q0CTL)qU^u{!%sTJ8DhzRM2`ggybkMr)1V;^@QLm=wH%ESGVjd|$J4s*ej+Z!KHblTgbo`hzaNggY(=!Y2 z$)}g$+~K%tr-*hJ>ap;r@)(WpKh52)ptvd&YJLiRFe*c%{g=4%H$69Zf9|zwFSn@; zBnl0^4M*kJAk9CnAoq~9Dj`A#ta}b4l`AlGR;j)7Pc4h=o}01p6D4#AuT10#Vz2T7 zF7%SDNzQqhzlh7f8#bg{*KYrI$4nv;XE8pNt6EWtWpee;sAa<#Qma?Yo+ z3r^=C=V4#Z%f9{S)5$DN=Eui}PBdY9H4*+EG?4UyU+E*e!8AM{f!lYSvnN zl~%S;?1`4Nw%!c?%BeQ(?7Znw=VmyYI59^Hfl);^XjNTe5_zk}c@ z-)OENaga{M&nn{2LLLpH3iS(R?<$j%<6d#Po_pcg;k1`!r_#soCLr&p_s!xo`O~H~5dJwI z9(ZY|@Ca;0O9Y>IWZHAHW@8k|VTTaEZr4{dlHoJ@1ou(WrpxuHNb`Hi4WwihAFL;| z%a`tp9)<8%T(3}C1`*_-a_hs&us8k4yp3Y|aTTTT5xdciR;~-k0aITFOqI_IaS%r7 zfp>M!{eTZ?B3*xEd+yeT8_6Szr!Dm>?NcmaZB-&X9Vo^eCDC5w(94mWt*>2EoO9-% zsL%JRyH*(t_1z2MvO{K@{7u0y>;kcTvLW;nZZUr|x5p|VAlmFb6#J9fCGZ2;ynTXa{v?bh z{UAXsab;)*3iA75zyT?6_Q?h4LZHO|P~Zv2ktuy9nL6rKCCl~tPhJ;*Buz-tPHZx6 zmpuKFynWi~$3EsW>$S9uD5d_h)`f9B@u)6E;v|;6+W^n1OQsjHJ?urVa>xi5-In^Z zS)m@JU)ksU!lF^T@U7dF@1BRj3|Bs)CjVu@h0&z_r;m>Ga7L?$R<+Y>ls0?`@BKsV zmDG=geuM7k+Ik!rBo-OBqa0}K5GLLRp4FyAjTfiRZ3OIp>^=D8)Nv#vZA}yzPQ%@r zay6V373IBWTD8K@Q1DjZvfuHYOV(;I4S64Kk4$@l#L$PTTRWQnhXg5rf{<{{oj~|fF{Vo$HX}Pba zo{;O+5E6Z4Bs*}N@wdWIViOR~yUEQ|^)pg-4}F1_td!(!n4+vK2?f1gO1C;)9y z+GMi}_#-OJlC{COy@Ht;_m2Sn4KVPTta_&MUlv#(Xs=t6h-VhP>;hN*kcf~m;WBIv zo99@~B>nTPIv;MJWo6wb!9Pz5Er9@X)$z?B5BSYXz!Usj)sVO)0-nEzvc&8UGmNjd z;{C&ju6V$=Q{9Dpes5tzug>&^HZw`RS~8r!7SbjGyLbwrJR7MO_g}h{yb?A0Y%xsq=g>-pK2(K1vogp zw-*JVeD5x=vD zE>NB8NcLJa*o$E^iq6YcP4?td=?mCGj7<-h;_aJdS{-PL{uaQ58*dmdV-=%D?kyx` zs%>>>Px`cISpq}xsu(l#mB_AAoFaw-HH_xN@6S@1`Pi1_GD?#wbv9nkN|UVz8Gn61 ze(pE#9MApn-Zmv@%b^2Jl8W>mx=;K*7< zlSRGQG33A#8r#;yUCjl-!1+Yat9HMNz5qGWmyBqyWc!W&-gSe({>-w55_y*@4mhiP zbyznS)1u(?_=>asHMqI6p?GnL;=5)+pIkv0ijxUG#)1vtU8g&pXGSS6%sjEFweBv{?6r{$IVJ$K%Nn zx`Jv+oh$p{JT!do;qW7)wjNj7*50C?YVS}zW1HbQbSlV=mrUfgN%6J+2k}sU?MCg*NCt`=@e+2J^c~ zcb)@EmZO%-*0~-L?#c@_t=W-jtr5&6e0DYC6{l3hrgtPqiu6GLUrnkymkxy~EjMh=r<|B)-4Cb6{lD)2R8jfF|7y!-gQMuaNTmd2yC^(#k%8%XhO z^+U>Ivz=&lV7&Czkvf^0bO;%(nP&I*(|j|{gIQ+rB-3##5#`mA?<30`0Hr;g;d(`g zr-%-Y%lF);@7_^AvsF$%MtHAb*EvjqS<58mm|6lw3b_zzBO4Ps7EG!B3_kG@WeXy=iS?j@R$~jKG8$Cncp!ks2P@+z06aZULyLe@v~`~>SZ!}n0C1QSnIj+ z9*htDPs93M346ljVl}I23cJ-OquTd)lFXnyFZ?mq5|N{-QF5sRE8tRFH0sK$7F#+B zMzX}%zCGtqy<#@yVHDY67NK=Wg-P7h_pVX~+HW?!tu(>{kDt{TJ{Ld%A&4XJBq%0` zLjtAqpq|t27agVkSVZ6=`Ubb6W7--jr zubTXLY;3R~%UDi=4m(syxNf*r&Qn)%RN`RGYgmuoOYNZ#HXZ3^Y7}(uF%^q? zh~yOik;V5dt+##!rG%7**eH6I;jL`rQ@;glPL+DvLdMdsh=6fKH8=%XBEqlzyhea7 z7kNb)WZ9OzP2q|3NH%&p#9f3TLGkggB7|vv1q`0>hDWaqA>>R|xgBsDA(lcrreSR( z^0+QjLX84JF2ne!pzM~gf-W9-bqt9PJl4q0(KnVm$wg(4C(N!I&#fn{sONX~6W|Ha zRPp%**xSfA$^NR5HxzpePY(9|$?JP%1H9efVkal64gwMhM4 zE57k9JWb*t>xqw=SNNxd4k2B4J^4eitQQzAHLGMJFFR16@O!1xiNs$9$QwvnzNdmr zR`SLZDH9Sr)a_m;a&Hw3sUd|85^^(4Dc(FS{>#>h`xr!Prm@{BeLWogM$u+uF)*Wh zKBXn6{K6c7*MY5(x$srv})4y}-=h%cmgjP}U`QJQh9>7<_!4y`1k~AE=$7(<3jaegl zGk}AYZ%?QGlZxN~!+>^CNR9qouf#6U2Vs(NSr8B3{hKEJzdnOeJqL*gResEWu-fkc zoE?UQjQmbTentK-Ff8D6fhF@l==3(LKWs%QV*5Xzm9T-_uXEUkiug~iGphuO4&#Z3 zcmB<#V1on!eYJ_HIiK`5D1!dh4(CY{6yuAStKO-?HUCMToUb{qh)1#c3}&%_WHeIz zmaK^@Ufr%56+g17P^yvt*F1V~M50%`rU5>e~bWLA1MeL2?jEfy!De2<7_MG|Q8Z|GbLS;y# zRjVyso;9;$rm2l$<&2jF{ZZHCBWy}Zhkg_)7J4I8EmR5re)2usH-s95U&z>1Z}#UM zaczA}S_(Jyh!(_;wYc9R3o4Fs{jHHtvs(}{N4Z_=clp9n*mYTO%^FkB_Fa?xfS2^Ik zT1#-Grs&A(gAfU)hxNRid-txXmr+|YwdBl)M84w!qM-3^4sgU-tv*bO#9qQKsjc3f z2vpt@dgu5En{u^l`8dh-y1L|vs>P3>HqrTVlM5mzNW2l(QE{2=k9ZZSXWweGqwCbh zwhuNmFOC!>kYbJHk}}W=fgh1gEO61MIZA8~Ehe+3IY`l)TA>|j+VEQD5rja0t!orF z%07CSy6Hm!gGCffoJf50mu^cj085f6eXdlEwa6Bik1|ysU}Xt*CH%%Dc8dIIgL1Uh zm++^!oF1^kgY~YI@h-Psd#AHe6UpBrta~08x(!ry1!MER7uv=9I(B|(^PAk9IyZ{+ z<>C9|^7e_7-WJiH z$Fhpe4$I8~Eossg)>z=#d$<%>%hV;sn(D;kXRHlVT&D2@n~G#QlCcx!^C?Z)a`ttH zoLw9b2TMPA$6gUmo-;qF>mIpa9DXFilykG|G{GX;EO4H!x4Hcpj4ocd4C{n+MFQ*= zizRaNwG@1w(BD`QqTvakkTZ`SEEyuT?=UM`&>7JP;i`pykh3r-%Oy?Zo7gkRD)8Fr zmKhkRUQPJe(9LChs%XHhV?N8=8(Fme0(ofEV`M&yyp=hz zo$@r`DMZFa^XZqlXovOA^|v2z0d|)H6x6-h&{`_QHBIYPGm0;)j!)*MvD^zeuUnck zT0W@x7Y8-NSA(o;7@~OJA$&{4vtG@&Ek*4Gi`)$%l8bxt%ZoFDzCe4ZvU8mXQx$KU zo=;m)YNI|M1+Q*;A)3rTY4CB^;9hLCT*2_C3jz6f+l37_x%s8?7jdC6K&ADbyTMTA z`?%bU0)!CndoC3ApXH%a@6LhZ_@X?as^E|toZ*1aSe38Lc*D9*tJ9#IkjeAS`Fp@h zYp~V*O8vB+mQv#1M(@s64iP#qRxZ$Cj4@OqUV9uhZsF;^ZGatjxJ#SQ@qfI{hJBrQEihS@cL zG6YhE`qyF5#Mo>kppr}qERY5(eH#d%ZBKC~NRoq+1V|yUdEowsal4;JuVWMmU01VI zru&Ywem1uT!|0-J-2xQ9fF1!+YsGfA1v?yzRk>s}4OX0Omnfvx(a4nY7j5*gz%dr8 zFR)z1DVrb*W{-sSHyBnk_WVvogZ<=7enu9ymy0_+l&n1^i^}Yj*yOLpEtWH>&>7VvLrJq+jR%e&u&B)m$ zH5eX0{@@^10io*2JMn!qIn5>=2IFPnFgcGsu3O;t;wESM@Vi8ojeU=0JdaY7(d01{ z8V9~BG9`H@cleX*XX^^sFZ-VEqx0G0e3B97?R zDSU#lt7@^`(+_hFKTu)?FNX@u*@piVYvnWwp+?6=?1+#uSu?MA;de5RFDsp zit;KfN|=X-Nl9&A086#uxX2A<5~0!~c#iYc=2F1FvjBK^*&6uEA}-Zri3D0+rs9iI z1Cc^vtL_$;$@~}4!H_ap1?Y{rJ3xA#GZZpsen~}khb7^0{?3Y}Oyq%sW?FFN_d?2) zic;SP@!}4y@4cJspFwgXpaWhCiUEcHLad7$@BsEh6jkC#b{Bj^2MSVADLu#6Snw&e zbB*qFucOHG(U2G zQ26DRLfH50rdTFw-S=H`el%#a0cY^W_Y+72-bsT0`aM=^34j^C7Ov=x`*506!26~? z%oK(~JKlJKothA!{wHZn_i$;x!US)1qX%L$JY@Q%F27Spk!&Nu*8uE%CB=|V9XNme z$17l-9AP*Gv#pL7WlAqen#d^z`&DwJeQ|@gt`K?ZehTO&#VIr zw!sLkPRjwNbb(^@DGr_A;oS$%AGSLKUF%HyfxWUjzyY?=xhrq6 zlc9=}zHKLr({LPVwQileW$~&>(3N6An;N7RQYM1Gt0{J8kIE}7@YbCdys{yQcwXQQ z@Hp-rV!P?hQL{|t8~DoCD*y;!2(-Ks8*3~Z5;uXnPuI2S6Bq;r6vP8Cejhct;gSHeU%c_e zLLI2O^u~R6tjgzSU;`9L7LrKc>s>Lw<)WE5@~r{{I6B)HNWc!scjGsUzilfY?|4E% z|JbtAdcJhLl)t&uv|DG(Oem&`vG5v16EB=~Bb^rzyNY+*qY`G7`#f$kx+pI}D@5>3 z--h(O51^EL6aC{vx;lQfMQhtJ8buqLL-4-MoUyeWsSBrj&8&>vv=<;Da<; zL4HF1cPW5&$wU0s>+6z@&O$NWr#+n%RuhR4iKg~%v_kst?7ec3h?dx$ySVTod$;G- zz*<)7VHusoIf0L}ebo!dwP7^|k9kJ%;~k59M+|xL2En=8R@eOfs5czRz_pPC@JsqK z`Ru;(d-JNP^%gSh{AX0){Hl@S+TozI=cgUfg)HK=OfSjm_znrrmvwF_ov=%d+7V5M zLBgw9NnmreRRe01)1t}SqsRX1&qwy$rKo;9a6kEe^Sjqej9=ijXXH7K zc7JA~QNL0YXEEjr_>kMNz3XzWxK@!RNj zLjn;-{7NzBK7S>?xL5*q-t7*z9~Iy9fA=uI$hr02UJt)OJ+w`E+Gqp5Jw?VH&Z-j>3(Gv|(inS(C|3VNe1;)QBRGICs7V4BoX zTg`~C-}<(V@e5w3)%Tt_%iLP1+A~ld7`QPUjq1irfl|NYmyG?L zlHT%zUaRQ42jr0s%`Yf@yv>Xcm;wr(UOp=PK7%&d{ic5OE$F>SlGM6L-K9^{h}%9E z+bY?+#PwX)OV=}x?d$xOlD&e7p#&EaJy> zG3XMyi`P6VCLZ|BMUHJN75v0a%c#p7*!Gm#pJM5xt&1E`oPSAn!Q3r1w@mQR%Wavi z89`54S|BIKR@?Sggg307fI@B>hKVNBIH@6^D~O1sJb73DsEMO=N5xeQPQ}R zvUqtx`2|F~Mewt=Jb{oK=|B8DH^$?B)t8E@~f z`(CkyZd`4Jhp4Vci)pOKdbXXDxr58J#&Wh=znoEB@0g-fAEc7QAnq)2@|oM!U7n+j zpH$3K-hC2a?M=oCUXl$P70fg3cMiD*>4<6J?YF;P2TcgQO6C_ZUVaYUmo37qD%S>| zcmzcT2e$GkE>e2R?=Kk7;pSgU9i%vzjrTK)ufM{n9zKsYIW#_fJ`O{j7nyi!)*_B= zWrRNUadT>tm2uNH+vE1u%y;me%@jS(lMm2?8=vo)*tk^71SfPkje+zcS>PlnGr}O& z-rzw_o#h`%#Xi%O!9EY1qng{l(}2BN&&1VPMW(PrTybrrB;YR zc*1*1R}ok%GC?|A)F>p77AKy@r_soprV^1!UH<(Ee1vqwAAG_LrW)@Z;*ePnku8$Sjgk&Ge&qBT<@vQ4R0IB%ghWsqqdiB1 z=388-IBW^j+YPM3>naCC?OW)D+s>WL1{Aq70b!y;K~?ZZTKZEke%UfUGL+dK-_CS2 zM%=!cRJ*sw!Cn@SB0+5ju=x1@`T!qg7iwpM{Qwqnf;XiL`mG@^S(qQSbqH%4_V)1O z{AT%&RF}7;>OD+&jG!8U93U-l%pm?P_FtKFKZki9;u{5WF#imJUbTUJ*m{AW+}S3+ zq(n}jWJzY4ZCg|lD1l{tVms+v^V=IFC}`KWM#g}&<%Yt>ZsM4Ll(QG@~wyJ4qJ~R z2d!prn4f(THa~hif9J)fa8l1r`{(1jByzuYoPYexHNpggJ$RAKLDcGD-KUQqEN&p{ zAJ%bt)k%jilXC}6eSaFNV7dN@boE`$?wk8GY&%8R->0{iS}PO zlEpRur^fxWhW~#i^DY!VJ~&01vyZr5J#$#UY+B*RAO-Fun44Bvj2Xj za=j%hZBdUOibjd{2aWd)ZDalW;%&m_ox(4e?FoesB011@I=STsv68>;HABHt!48}f zJia#-V@-&au$`jxu^GuPJ#u*r$UPgps>I0ifxcN~Xu3I^ak-T=lUi67GGzAU=H zsrKId{Ihwt-=-K^!CDrCHO0{Dk<(9R8Gy1CJt=z=+tEO_L`DDt-6IO>ol|A3Mi-8~Z2l|eF z7_Vif9yy3Eq+4`kvxWw;mdZ&;FURn@#(nRM8@%u$sVV`pV|9L!D{%gcu^(IQdh^(J z9(z`hibZ|f8H2CmOW%!H(FHrVO@DR0`j0!)UJAtc!jg`-OoxsSP;?;^c?t?X9mLzNwGJ8B;j(JRNe`GW3)h zoQYLn!j&P0I*65}Zc|Kp46J1w)i*93+=q9b^E;c~{ygCw790o(iaZRVCp9{V6sP|| zupQ;Sl{!(10W<|W;g?YbPitr6YLQTlvQ3a9J9FGE6Kt_L+=yQ&8)i#mAvv5W5O*Hj z;1g$DUiVj*@(&?~KIu?#Tg_e?cYcNFl40wo8TYzgd+JJ0s^}pQ;=0c?sdhSL1qfZ` z-;MG~uMj)V`?|m7OP-9t{0@w{_d;?q=lCU(#y10$3IZK!-S`z=Z1t#qL8=yAF+&Q~ zZuVIxY0FH{UJR`84q4mKzTBHufDmW=D(NZz9o?)?|FasE(wjA0f7C%CpiLo77NF8S@KXt+GWj}7gQL*|3+L?l z(`)EHT9pjaG~aN>`t_Frb^MF;GMmA8*nqsR|H^6ZjZna1!PA*T+mJ2hpn2Hk%(iJV zkZ8m$?2Hr~MnT;L23Ma2cr3O~9vVgJ3In0iK@w0ax=UnyXR%uQa7t2g<>u%k?s8L} z{zKLGMwmGVlAo0Hq|djcljkD_mgq^>+e>|4MJ;+eFQ838_)n6eo%TIN6i%aqXGvkG zcJGgb0Fqdj{rsY0HFK`knkv9Ht!DOw-=I3$=%iz8`&4cHB`nAoA7jWsdh?x!KaI{y z*PR#j1kDp+$|WK>0~>2!PqiOK;KP_iE|@R+H^kw4ucY#U&P)sYj{<5#ub$P(&feSy zUx|lyQ#}?m6(T0KHg<#Y_NcvYbjaEyInbX?svd4mQxc7#f&(YczD&<r@& zwkPJf{}AC~IUEBzRF@Q_&}oqtMpx*HC0h8R0PG@`3fh3w_?E1_0ZE9iyIP|FdLUqb z*Qbst@kW$7_FQ*R0!6z%MBzG&>RCgD-+HgJ^vEah>GiLg7XgBA2XVU9yRrOgZF6kT z&Y7=PEYNa+{<8!W58|}bfZY-&MD`bG5@J!})c5W=GyGzc(j;tT)2j|Tm|OM zYk+@E;=?+hTZqL|!%)r}wG+uFa1I;geWZjGgBcQ z1k~}#s}fta&7D!HB7>^tF%T?XAO&eG!JX_Vv<#fTl>GeLFSHdq?PP)v#86siw$r7< ztqq$)9xslnK4U7B2cOGTl{u%wP{|svV2~Nux|?ik5mX6V{n_62cQ40w6l6m9nxae1 z5O~m0^b_G1K@BLtEyc=se=`$YpX3z|WQK&%F@BDW2S6r5EK*`45hM4XFoBU5h2bJD z2;M59GO1a{qzf;^BHY!%W*Uad3z5eO*o4A9wr=550N6H(gfYdg*^aXk@VIepMfVEs ziJIcEgChFL9YD<#OKoXb^|EY;>t{GK7JB$CSAZQritUp)W~5EbQp+DpdhI8ZW41fVE>a7-QtHY5Ga@CucfO-2C-E@bb2OAT+;Q)m>- z$IZ(5y9@FA*^TH0&XWr5p)4F=Hl zR%0^wu#c3Bx{2olu8=aOQ2;0U-~JS_!fZZ`aYL7bVSex!tF7XswN5?redOX>0vw9EV`zMnS+ zr@p#E9n;MN&3y@uJ4lsSp3`j zNdZ>GgKO>|BZHxqb|v#tIf2?J(*=W(zXlQ@4~x7u5|^op%dKZH6UOMs4~*;_1O~3H znivpS@zayk1PAa&gs22uGz&PmdoObrL8}U}npLC(?#3vL-3mA%DKULFkizDVoR#`! z;q8yr{(rCd_gr3HA>XwKUm+q0XJla)(|50H@Yv z=~zKPn-fTp_0C8&`R}@hv8z|`!K=@}I0@XoH_S4@FJ4gIfKfe_(*Gd=CKTL)l>k^C%NHcj0$YgP2G8*HV85Juvo``v(Qt811MKowKhP1p z3>f)TmCqb#Np}_dLk%-B%W#V>dW=w@WrpAy=uOs~1n+ROe&4P3BI-xF=LEioc%3ey zx$3t>?7aJCwkDPq)xemb`M zy;!*wP=)LnwG|jup#L+Z;Uq#6v*OkeTw`f5;?*jOXVr4qyW=j#(hQ*Wu?$X2 z1*+A=8mr05<$OI1HWs+Q?g4%<90Vq0DLIGU( zJy=R#EZqD~`Haj>396&XA**B{_5ZR#$2mu%_vbV7!4O=Y_Ti2W==pHK(JiKOH}@cO zFn@n&X;X>(w<2DGu6+T6*!}_Rd~`oOlU|%;;RQ%CwDi3F#igpxC>Vk|6mHmBLG^Lz zX>IFfqdG!crzmNl6Le(?y|F4n>S*g+(kzTlFpn^7S=ZYtJuYfRG!+?m1d_fl7N zFem%{8IUNSur2@dRM*_8Yz9>fuUIW)@k-an;f0$7^C?sY+RAhIOh(RQzfK2x>aQZr zlBQp*-XUsQ%MzuNx!KLVMa86-Wn4%Ad4V_V>((j#G5@7O2v@QW@0E`yp`VPbXxDv= zXLQ}06&U%I4zArLK_TfUMezES-tnf$2}as^*lr>*Y{}rXh*i%=N122;4{@NA1Yb-(Tf!0ISiQ1BdqJM+9Cg!0K9;0I*&c-tIHNx-@ zE$ApV5CcyhVzIP(4%&r0O6~8A0WLQy@{280>IW1=B$8|BDll*zTWz&`AG&=oR-0M+ z21}zA_+$Mn9Jb(* z3;H(ar9V%k-f@G5kUo5~RQLl6fv z+F>X|g;zv>w+DkMAjxY|_#1|CAcnxYt6wwI{oTGn8$7BAi~jr{iK;-)$dy%2#q2am?MR0;l0ufyiS>HK?OJb?`?6W(k-%bmpCOXIci zDSJ7|+nV*w7SIc(UekGA3)q@Cxc;BRDKm^4^Am(&qXd4Y`;ns-*t;6YhS@%fZy0x?J z1D7!`zAPL2K?S{=Cg3FafU&qJ+n-P|_SJKYhDROjBxz*f>V(>P5vQwkUM?z7 zDaOn|ShAC_`v8Wh8?;`+p~<>|dWF{J+q?{esZLR!w^>Q|hbvMQ>b=K^3Z@B3(n!-i zRSMQ3d^bppy7-;iy0UzMUY)pKiPoFAj_nQsC>K%FE zx2Csx(XTR>jlD2U+xJp`e2SGO0Q#+b;_kNJqdK!q z&htPtAilN4F}1$K z3Uv>kNpa$B%dTXG@GpPdv?%#WBLvM&#^FZYSivPQ`TaD&|C@Q%GwZa+EbszyKi1HP zrcE*z>Dm|NfMOHs+zBN?>4eq4ZWM@Cx-*TZ)IE7tsQnAc`<$Tr2^s|2wiY87VJK+V zkgL%phFE{o^HXcZ``n@DWn6mGq|AdzP2@_|F{N*U0Mu2!L$WF>1&-G|Oda1eki(1| zk{i-d4iYC4RLM#Wl>~4P95P&eEhpgb1(;y}E`Uof(LHn6yn_Fgu9OBvg-EbTTsLJ= zx-A62be2Qn^q0L82HGo=B0-&i>ZNY5)*^F5CG z^@6UlRf7)C6Ij9SXM`${N~ZMfcnB*iD07(MN~@`Z7k=pk4#4h3dh)}ESip;XrH~W} z9}z>Joxb#)V&}PzOmuz~m(`leoKv*QL78T@DyyNxaAZ#$_!S9#krL8Q?=eC&$#%}j z4WhFfw|XFd=Q>srmnlB^og3gU63B%JArbg8p^bG6glhP8;3w(yvpNr|^0zpiJ2P3o zat9e5ThHrNbeoFMz(Y~P3o^aeT86MuOO9U&q`BlMf>j?#30u4vY;VEx0R9gDZh)A5 z4vUedj~!XWCU+`ZxJtPQQBvHS3TLt;MKCG`2=1sfMRQOmm#=z8H-vB8HEVHVq(mv| zT*1T`?N#}jj%v_U&7u`4TLqte)G zV5E8Wc+BZiR>xXs3z;JM%OdZ~L~2kKp&Z)y%5VPn$8$oJ%i$wcaiAHale=*C$awLd zllMpx#&T@Gf9JNVi@`05rThW>t{hi)v0=7MjmqoIjov=ZX|~#xNd4sGq-J`;uB?yR z7K8&y!0RR*kb6-wRT(fXz8kyws&@=cuTFa$|nO*y34% z+tpyFw<4>z{YK|p4^uX`C#Suk8qtHN^h{MgS?MvL<|v1aT~p@@(T5A2Z_ko4V25w1 z()C!Gs=vvsnE;19_YR2HTRU(wl-JzZI$9t6}bGY!M%TD-9O9Vv0GC7QsFU)R-)BxRglAcYkjjqOpB#Hd$Zk- z{c6^}l{pyxE30Ypd``6yJKT(pTGEa<8%*^qxobu&+`kw5y)^Io_(9?>(k{x%dpY6$ z6`SPeJ~x0Hy^(6V29SMTIPd-wX`Mc%D-pbJX)l>MYN_v>WYunJoqudtLMLKR7K%XK z7#@7|Y;6WPKe~6g>})jqns84nxf9K%G?CN_uFHUF7-{R(=1z;LLkn(hWE~+*bI~wl zvWiz9Nk!eXH;v5AinI?aUD^zyS(csUSAnfR9%btcf*Iz+5I^!01%^eEo6rzbO-Ea< zdc}}t&nOmnb@>N-(+F4H!DgF{!D#cEEHh{6kT~v+xI@ZK#L9hI$qsFH3Uo`Zr<9gR zY}Yl4rB%7f*eLFq1!hublEJx8Y8x3!bYTyW`i4G90-<7yi_@OBfY7(%rwV}3-0-o3 z!+fIKsk@S zsUm&y@R)M08{V2-g6A`Anl69Eq&K@!zDgkM%Gt=({f?}eJ&3Kyu~W@HLb&#qjU7zY z@%1;~q!k7pO=ydAmrus!0Q~M|i}SrUey*4u!qLTXCnIgk`}6z67*l}(pJZV>F3F0b zMLol-#b_nE;#zw&y3=4d(6NT!Yqo|{JA$|HeL>Q9e(4bFT*Qu(VJoJnSvnThJ}pBl zse&mo8k%$}5Ti(q)EUO8m{qpaCET6)R$irYu=QlA`-#tO$j&S8k0P8Ngufy{mi?no znYBU}os*XaaYv)Wo|WxNxE>^u)8-;Oql4Dwj&yx}`BS(JjdW@zTykrQ(e^zjT%zqw z(FTUT#yVG>inn*}fI4anK1n`RiN{1OXS_V%6Zn2gftLOH<3_=0Ct7{_&Pbg~73zY> z2TqsJ9a*>Ei7c8b8(G*Vt=hES`8gMvc3l#40`0xG={xh%^U<$}r5W#B*gyVhcuEPk zU)s?8c3wWWC8lA85q)#mMJ=Fyg{(CSS2C_ZFg9ONU@>te&pNv`w<_Dl+8I%aT!{Ck z1Az!})`6+b_wd%)IWus)^J42ZTjT!Z%`oDe0;`^VExO^DaSZnN-6NS>R3)a#IbZf{ z-69MT$oa(X+ovCWkaIcw{bWmXA8CNb2&*<_Vq2R@BAL&!pXIP$27mQ{gWT+n2FIc& z{Wh{*<;TnnMuCmr82OdrqKBGl%1tfpzFAkqSWlU*g>t%g`9y?)n{U2%abCxBUHfmK zv^OX0;>aD2+;W<@_HMIiO(G>qJQYL5B0Ajs!d8P0k(4i7mYHW8Kh!Ic9qNVgAI-0M zdpvqTt7Q6ywgPBT`3)|?^B_iFUM&FnzXS*mr>$rUA z)975j=&Ja^LE>TvnNI1DRjCg3&=1~J_06ps`njYYV7RtS)EFJj`ZkPD&;I>88X>cv z1sG&2FC%1n%{U`_a`tMFLo=(@z2p$8^2`nATIR?bgU2E{ zaaOz7?xFbEVRDAfClzk+bJ?}NlV7bh2IDQQ!=wU(|y#JSJaM zFX*e~Ze4M=f@tj?e<3F71|vWMl`%Kf3uj(7fZkc=l7j`Jl)UIiS0 zI7mXLegB^oe2)G7a&7s$PgVOSykC5;2DnV?@yfrF-!**VwHnpSgLXY@n_F_axhA|M z%W&2EwtWw-TEC1xZ@>G>JGb2m7eKr9#n){T$}XzB*lYcAq4DpIi=9Vbr2i`ecFo+> zrf+iNxaPtHoB*8ZY*+>CgMFG+*Yv*oRq38ECsn8Ye@x>}9^ZHJ<1S$PCjDK#uO4uT z8E~nU^PXk%AC>NnJD#l?qBP}X>a*rd)@Sqg|H%1u*ZSL~&+G1cuCM%m^h^74{U!bL z9`0W3ymr#7>YY)HSLM}!%ZRFE&wIV#Vw3WH18Ee`>@?lE=P7g4#M{2x@9m!cW%})3 zk_$CkZc4opi8j0j)AA(f*^L9MvY6s)p3MAm@AtRMr}J<5+W+4)cgcO#XPax;e$5T| z>oWPD)jWHjRqwiEK-t2v)?xB#;JTY7*Y{=H#}@z96F%)Q`L+JOBy-UGrt>u)J#Hxn z6IO8V-woJ^l$Es{EEO?U=RK?^Y<(@64o(I0UpA};OXk; Jvd$@?2>`-(tXKd5 literal 0 HcmV?d00001 diff --git a/zh-cn/device-dev/kernel/figures/zh-cn_image_0000001170790681.png b/zh-cn/device-dev/kernel/figure/zh-cn_image_0000001170790681.png similarity index 100% rename from zh-cn/device-dev/kernel/figures/zh-cn_image_0000001170790681.png rename to zh-cn/device-dev/kernel/figure/zh-cn_image_0000001170790681.png diff --git "a/zh-cn/device-dev/kernel/figures/\344\272\213\344\273\266\350\277\220\344\275\234\345\216\237\347\220\206\345\233\276.png" "b/zh-cn/device-dev/kernel/figure/\344\272\213\344\273\266\350\277\220\344\275\234\345\216\237\347\220\206\345\233\276.png" similarity index 100% rename from "zh-cn/device-dev/kernel/figures/\344\272\213\344\273\266\350\277\220\344\275\234\345\216\237\347\220\206\345\233\276.png" rename to "zh-cn/device-dev/kernel/figure/\344\272\213\344\273\266\350\277\220\344\275\234\345\216\237\347\220\206\345\233\276.png" diff --git "a/zh-cn/device-dev/kernel/figure/\344\272\222\346\226\245\351\224\201\350\277\220\344\275\234\347\244\272\346\204\217\345\233\276.png" "b/zh-cn/device-dev/kernel/figure/\344\272\222\346\226\245\351\224\201\350\277\220\344\275\234\347\244\272\346\204\217\345\233\276.png" new file mode 100644 index 0000000000000000000000000000000000000000..37559a2a230b4d0a17fa07aaac2ea5ed3923b4df GIT binary patch literal 34146 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 B8g&2w literal 0 HcmV?d00001 diff --git "a/zh-cn/device-dev/kernel/figures/\344\273\245\344\270\211\347\247\215\346\226\271\345\274\217\346\230\276\347\244\272\345\206\205\345\255\230\344\275\277\347\224\250\346\203\205\345\206\265.png" "b/zh-cn/device-dev/kernel/figure/\344\273\245\344\270\211\347\247\215\346\226\271\345\274\217\346\230\276\347\244\272\345\206\205\345\255\230\344\275\277\347\224\250\346\203\205\345\206\265.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/kernel/figures/\344\273\245\344\270\211\347\247\215\346\226\271\345\274\217\346\230\276\347\244\272\345\206\205\345\255\230\344\275\277\347\224\250\346\203\205\345\206\265.png" rename to "zh-cn/device-dev/kernel/figure/\344\273\245\344\270\211\347\247\215\346\226\271\345\274\217\346\230\276\347\244\272\345\206\205\345\255\230\344\275\277\347\224\250\346\203\205\345\206\265.png" diff --git "a/zh-cn/device-dev/kernel/figure/\344\273\273\345\212\241\347\212\266\346\200\201\347\244\272\346\204\217\345\233\276.png" "b/zh-cn/device-dev/kernel/figure/\344\273\273\345\212\241\347\212\266\346\200\201\347\244\272\346\204\217\345\233\276.png" new file mode 100644 index 0000000000000000000000000000000000000000..75c79e501c27a2c41ff011133197eb646981b0f3 GIT binary patch literal 11238 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 literal 0 HcmV?d00001 diff --git "a/zh-cn/device-dev/kernel/figures/\344\277\241\345\217\267\345\217\221\351\200\201\345\244\261\350\264\245.png" "b/zh-cn/device-dev/kernel/figure/\344\277\241\345\217\267\345\217\221\351\200\201\345\244\261\350\264\245.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/kernel/figures/\344\277\241\345\217\267\345\217\221\351\200\201\345\244\261\350\264\245.png" rename to "zh-cn/device-dev/kernel/figure/\344\277\241\345\217\267\345\217\221\351\200\201\345\244\261\350\264\245.png" diff --git "a/zh-cn/device-dev/kernel/figures/\344\277\241\345\217\267\345\217\221\351\200\201\347\273\223\346\236\234\345\233\276.png" "b/zh-cn/device-dev/kernel/figure/\344\277\241\345\217\267\345\217\221\351\200\201\347\273\223\346\236\234\345\233\276.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/kernel/figures/\344\277\241\345\217\267\345\217\221\351\200\201\347\273\223\346\236\234\345\233\276.png" rename to "zh-cn/device-dev/kernel/figure/\344\277\241\345\217\267\345\217\221\351\200\201\347\273\223\346\236\234\345\233\276.png" diff --git "a/zh-cn/device-dev/kernel/figure/\344\277\241\345\217\267\351\207\217\350\277\220\344\275\234\347\244\272\346\204\217\345\233\276.png" "b/zh-cn/device-dev/kernel/figure/\344\277\241\345\217\267\351\207\217\350\277\220\344\275\234\347\244\272\346\204\217\345\233\276.png" new file mode 100644 index 0000000000000000000000000000000000000000..02437a72c3de38cbddf5233282ef9354220002bf GIT binary patch literal 52280 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 a7@wDs=4Dn#*byG^cU$d_YLW88p#K4g)Ql_u literal 0 HcmV?d00001 diff --git "a/zh-cn/device-dev/kernel/figures/\344\277\256\346\224\271-hello-harmony-txt-\346\226\207\344\273\266\347\232\204uid\344\270\272100-gid\344\270\272200.png" "b/zh-cn/device-dev/kernel/figure/\344\277\256\346\224\271-hello-harmony-txt-\346\226\207\344\273\266\347\232\204uid\344\270\272100-gid\344\270\272200.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/kernel/figures/\344\277\256\346\224\271-hello-harmony-txt-\346\226\207\344\273\266\347\232\204uid\344\270\272100-gid\344\270\272200.png" rename to "zh-cn/device-dev/kernel/figure/\344\277\256\346\224\271-hello-harmony-txt-\346\226\207\344\273\266\347\232\204uid\344\270\272100-gid\344\270\272200.png" diff --git "a/zh-cn/device-dev/kernel/figures/\344\277\256\346\224\271-hello-harmony-txt-\346\226\207\344\273\266\347\232\204\346\235\203\351\231\220\344\270\272666.png" "b/zh-cn/device-dev/kernel/figure/\344\277\256\346\224\271-hello-harmony-txt-\346\226\207\344\273\266\347\232\204\346\235\203\351\231\220\344\270\272666.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/kernel/figures/\344\277\256\346\224\271-hello-harmony-txt-\346\226\207\344\273\266\347\232\204\346\235\203\351\231\220\344\270\272666.png" rename to "zh-cn/device-dev/kernel/figure/\344\277\256\346\224\271-hello-harmony-txt-\346\226\207\344\273\266\347\232\204\346\235\203\351\231\220\344\270\272666.png" diff --git "a/zh-cn/device-dev/kernel/figures/\344\277\256\346\224\271-hello-harmony-txt-\346\226\207\344\273\266\347\232\204\347\276\244\347\273\204\344\270\272100.png" "b/zh-cn/device-dev/kernel/figure/\344\277\256\346\224\271-hello-harmony-txt-\346\226\207\344\273\266\347\232\204\347\276\244\347\273\204\344\270\272100.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/kernel/figures/\344\277\256\346\224\271-hello-harmony-txt-\346\226\207\344\273\266\347\232\204\347\276\244\347\273\204\344\270\272100.png" rename to "zh-cn/device-dev/kernel/figure/\344\277\256\346\224\271-hello-harmony-txt-\346\226\207\344\273\266\347\232\204\347\276\244\347\273\204\344\270\272100.png" diff --git "a/zh-cn/device-dev/kernel/figure/\345\205\203\346\225\260\346\215\256\345\255\230\345\202\250\347\244\272\346\204\217\345\233\276.png" "b/zh-cn/device-dev/kernel/figure/\345\205\203\346\225\260\346\215\256\345\255\230\345\202\250\347\244\272\346\204\217\345\233\276.png" new file mode 100644 index 0000000000000000000000000000000000000000..8566e16dbc675362366f07cf9497c2d9073d6f56 GIT binary patch literal 46397 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

    sa(ya(i5 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 A`~Uy| literal 0 HcmV?d00001 diff --git "a/zh-cn/device-dev/kernel/figures/\345\206\205\346\240\270\346\236\266\346\236\204\345\233\276.png" "b/zh-cn/device-dev/kernel/figure/\345\206\205\346\240\270\346\236\266\346\236\204\345\233\276.png" similarity index 100% rename from "zh-cn/device-dev/kernel/figures/\345\206\205\346\240\270\346\236\266\346\236\204\345\233\276.png" rename to "zh-cn/device-dev/kernel/figure/\345\206\205\346\240\270\346\236\266\346\236\204\345\233\276.png" diff --git "a/zh-cn/device-dev/kernel/figures/\345\207\272\347\216\260\345\206\205\345\255\230\350\266\212\347\225\214.png" "b/zh-cn/device-dev/kernel/figure/\345\207\272\347\216\260\345\206\205\345\255\230\350\266\212\347\225\214.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/kernel/figures/\345\207\272\347\216\260\345\206\205\345\255\230\350\266\212\347\225\214.png" rename to "zh-cn/device-dev/kernel/figure/\345\207\272\347\216\260\345\206\205\345\255\230\350\266\212\347\225\214.png" diff --git "a/zh-cn/device-dev/kernel/figures/\345\210\207\346\215\242\345\210\260\344\270\272uid\344\270\2721000-gid\344\270\2721000\347\232\204\347\224\250\346\210\267.png" "b/zh-cn/device-dev/kernel/figure/\345\210\207\346\215\242\345\210\260\344\270\272uid\344\270\2721000-gid\344\270\2721000\347\232\204\347\224\250\346\210\267.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/kernel/figures/\345\210\207\346\215\242\345\210\260\344\270\272uid\344\270\2721000-gid\344\270\2721000\347\232\204\347\224\250\346\210\267.png" rename to "zh-cn/device-dev/kernel/figure/\345\210\207\346\215\242\345\210\260\344\270\272uid\344\270\2721000-gid\344\270\2721000\347\232\204\347\224\250\346\210\267.png" diff --git "a/zh-cn/device-dev/kernel/figures/\345\210\233\345\273\272-share-\347\233\256\345\275\225.png" "b/zh-cn/device-dev/kernel/figure/\345\210\233\345\273\272-share-\347\233\256\345\275\225.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/kernel/figures/\345\210\233\345\273\272-share-\347\233\256\345\275\225.png" rename to "zh-cn/device-dev/kernel/figure/\345\210\233\345\273\272-share-\347\233\256\345\275\225.png" diff --git "a/zh-cn/device-dev/kernel/figures/\345\210\233\345\273\272\344\270\200\344\270\252\345\220\215\344\270\272-file-c-\347\232\204\346\226\207\344\273\266.png" "b/zh-cn/device-dev/kernel/figure/\345\210\233\345\273\272\344\270\200\344\270\252\345\220\215\344\270\272-file-c-\347\232\204\346\226\207\344\273\266.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/kernel/figures/\345\210\233\345\273\272\344\270\200\344\270\252\345\220\215\344\270\272-file-c-\347\232\204\346\226\207\344\273\266.png" rename to "zh-cn/device-dev/kernel/figure/\345\210\233\345\273\272\344\270\200\344\270\252\345\220\215\344\270\272-file-c-\347\232\204\346\226\207\344\273\266.png" diff --git "a/zh-cn/device-dev/kernel/figures/\345\210\240\351\231\244\344\270\200\344\270\252\345\220\215\344\270\272-dir-\347\232\204\347\233\256\345\275\225.png" "b/zh-cn/device-dev/kernel/figure/\345\210\240\351\231\244\344\270\200\344\270\252\345\220\215\344\270\272-dir-\347\232\204\347\233\256\345\275\225.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/kernel/figures/\345\210\240\351\231\244\344\270\200\344\270\252\345\220\215\344\270\272-dir-\347\232\204\347\233\256\345\275\225.png" rename to "zh-cn/device-dev/kernel/figure/\345\210\240\351\231\244\344\270\200\344\270\252\345\220\215\344\270\272-dir-\347\232\204\347\233\256\345\275\225.png" diff --git "a/zh-cn/device-dev/kernel/figure/\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/\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..955aff65c1c8365cc6c932a5e89ef944384bb489 GIT binary patch literal 50972 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 literal 0 HcmV?d00001 diff --git "a/zh-cn/device-dev/kernel/figure/\345\212\250\346\200\201\345\206\205\345\255\230\347\256\241\347\220\206\347\273\223\346\236\204\345\233\276.png" "b/zh-cn/device-dev/kernel/figure/\345\212\250\346\200\201\345\206\205\345\255\230\347\256\241\347\220\206\347\273\223\346\236\204\345\233\276.png" new file mode 100644 index 0000000000000000000000000000000000000000..e67cd13c295d19b6ce45c4749644eea42ada7f05 GIT binary patch literal 36975 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 literal 0 HcmV?d00001 diff --git "a/zh-cn/device-dev/kernel/figures/\345\217\221\351\200\201\344\277\241\345\217\267\347\273\231\346\214\207\345\256\232\350\277\233\347\250\213.png" "b/zh-cn/device-dev/kernel/figure/\345\217\221\351\200\201\344\277\241\345\217\267\347\273\231\346\214\207\345\256\232\350\277\233\347\250\213.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/kernel/figures/\345\217\221\351\200\201\344\277\241\345\217\267\347\273\231\346\214\207\345\256\232\350\277\233\347\250\213.png" rename to "zh-cn/device-dev/kernel/figure/\345\217\221\351\200\201\344\277\241\345\217\267\347\273\231\346\214\207\345\256\232\350\277\233\347\250\213.png" diff --git "a/zh-cn/device-dev/kernel/figure/\345\240\206\346\240\210\345\210\206\346\236\220\345\216\237\347\220\206\347\244\272\346\204\217\345\233\276.png" "b/zh-cn/device-dev/kernel/figure/\345\240\206\346\240\210\345\210\206\346\236\220\345\216\237\347\220\206\347\244\272\346\204\217\345\233\276.png" new file mode 100644 index 0000000000000000000000000000000000000000..6ac9200e867f2c87d14ef89ca8c15102e83d4c10 GIT binary patch literal 42208 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%0D=8J`i#%_cPA^fP&+i~-CeXqya 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 EKj$xo1ONa4 literal 0 HcmV?d00001 diff --git "a/zh-cn/device-dev/kernel/figures/\345\275\223\345\211\215\346\262\241\346\234\211\345\206\205\345\255\230\350\266\212\347\225\214.png" "b/zh-cn/device-dev/kernel/figure/\345\275\223\345\211\215\346\262\241\346\234\211\345\206\205\345\255\230\350\266\212\347\225\214.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/kernel/figures/\345\275\223\345\211\215\346\262\241\346\234\211\345\206\205\345\255\230\350\266\212\347\225\214.png" rename to "zh-cn/device-dev/kernel/figure/\345\275\223\345\211\215\346\262\241\346\234\211\345\206\205\345\255\230\350\266\212\347\225\214.png" diff --git "a/zh-cn/device-dev/kernel/figures/\346\214\207\344\273\244\350\276\223\345\207\272\347\273\223\346\236\234.png" "b/zh-cn/device-dev/kernel/figure/\346\214\207\344\273\244\350\276\223\345\207\272\347\273\223\346\236\234.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/kernel/figures/\346\214\207\344\273\244\350\276\223\345\207\272\347\273\223\346\236\234.png" rename to "zh-cn/device-dev/kernel/figure/\346\214\207\344\273\244\350\276\223\345\207\272\347\273\223\346\236\234.png" diff --git "a/zh-cn/device-dev/kernel/figures/\346\214\211\346\214\207\345\256\232\346\240\274\345\274\217\346\211\223\345\215\260\347\263\273\347\273\237\346\227\245\346\234\237.png" "b/zh-cn/device-dev/kernel/figure/\346\214\211\346\214\207\345\256\232\346\240\274\345\274\217\346\211\223\345\215\260\347\263\273\347\273\237\346\227\245\346\234\237.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/kernel/figures/\346\214\211\346\214\207\345\256\232\346\240\274\345\274\217\346\211\223\345\215\260\347\263\273\347\273\237\346\227\245\346\234\237.png" rename to "zh-cn/device-dev/kernel/figure/\346\214\211\346\214\207\345\256\232\346\240\274\345\274\217\346\211\223\345\215\260\347\263\273\347\273\237\346\227\245\346\234\237.png" diff --git "a/zh-cn/device-dev/kernel/figures/\346\226\207\344\273\266\347\263\273\347\273\237\346\240\221\345\275\242\347\273\223\346\236\204.png" "b/zh-cn/device-dev/kernel/figure/\346\226\207\344\273\266\347\263\273\347\273\237\346\240\221\345\275\242\347\273\223\346\236\204.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/kernel/figures/\346\226\207\344\273\266\347\263\273\347\273\237\346\240\221\345\275\242\347\273\223\346\236\204.png" rename to "zh-cn/device-dev/kernel/figure/\346\226\207\344\273\266\347\263\273\347\273\237\346\240\221\345\275\242\347\273\223\346\236\204.png" diff --git "a/zh-cn/device-dev/kernel/figure/\346\227\245\345\277\227\346\226\271\345\274\217\347\244\272\346\204\217\345\233\276.png" "b/zh-cn/device-dev/kernel/figure/\346\227\245\345\277\227\346\226\271\345\274\217\347\244\272\346\204\217\345\233\276.png" new file mode 100644 index 0000000000000000000000000000000000000000..caf4127a296227a121ef155f9354d1f3ef3837dd GIT binary patch literal 16031 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 z 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 T-3oqq4(XlH*Dlbs3Hkp3K?TpA literal 0 HcmV?d00001 diff --git "a/zh-cn/device-dev/kernel/figures/\346\230\276\347\244\272\347\273\223\346\236\234\345\246\202\344\270\213-0.png" "b/zh-cn/device-dev/kernel/figure/\346\230\276\347\244\272\347\273\223\346\236\234\345\246\202\344\270\213-17.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/kernel/figures/\346\230\276\347\244\272\347\273\223\346\236\234\345\246\202\344\270\213-0.png" rename to "zh-cn/device-dev/kernel/figure/\346\230\276\347\244\272\347\273\223\346\236\234\345\246\202\344\270\213-17.png" diff --git "a/zh-cn/device-dev/kernel/figures/\346\230\276\347\244\272\347\273\223\346\236\234\345\246\202\344\270\213.png" "b/zh-cn/device-dev/kernel/figure/\346\230\276\347\244\272\347\273\223\346\236\234\345\246\202\344\270\213.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/kernel/figures/\346\230\276\347\244\272\347\273\223\346\236\234\345\246\202\344\270\213.png" rename to "zh-cn/device-dev/kernel/figure/\346\230\276\347\244\272\347\273\223\346\236\234\345\246\202\344\270\213.png" diff --git "a/zh-cn/device-dev/kernel/figures/\346\237\245\347\234\213-hello-harmony-txt-\346\226\207\344\273\266\347\232\204\344\277\241\346\201\257.png" "b/zh-cn/device-dev/kernel/figure/\346\237\245\347\234\213-hello-harmony-txt-\346\226\207\344\273\266\347\232\204\344\277\241\346\201\257.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/kernel/figures/\346\237\245\347\234\213-hello-harmony-txt-\346\226\207\344\273\266\347\232\204\344\277\241\346\201\257.png" rename to "zh-cn/device-dev/kernel/figure/\346\237\245\347\234\213-hello-harmony-txt-\346\226\207\344\273\266\347\232\204\344\277\241\346\201\257.png" diff --git "a/zh-cn/device-dev/kernel/figures/\346\237\245\347\234\213\345\275\223\345\211\215\347\263\273\347\273\237\350\267\257\345\276\204\344\270\213\347\232\204\347\233\256\345\275\225-\346\230\276\347\244\272\347\232\204\345\206\205\345\256\271\345\246\202\344\270\213.png" "b/zh-cn/device-dev/kernel/figure/\346\237\245\347\234\213\345\275\223\345\211\215\347\263\273\347\273\237\350\267\257\345\276\204\344\270\213\347\232\204\347\233\256\345\275\225-\346\230\276\347\244\272\347\232\204\345\206\205\345\256\271\345\246\202\344\270\213.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/kernel/figures/\346\237\245\347\234\213\345\275\223\345\211\215\347\263\273\347\273\237\350\267\257\345\276\204\344\270\213\347\232\204\347\233\256\345\275\225-\346\230\276\347\244\272\347\232\204\345\206\205\345\256\271\345\246\202\344\270\213.png" rename to "zh-cn/device-dev/kernel/figure/\346\237\245\347\234\213\345\275\223\345\211\215\347\263\273\347\273\237\350\267\257\345\276\204\344\270\213\347\232\204\347\233\256\345\275\225-\346\230\276\347\244\272\347\232\204\345\206\205\345\256\271\345\246\202\344\270\213.png" diff --git "a/zh-cn/device-dev/kernel/figures/\346\237\245\347\234\213\345\275\223\345\211\215\350\267\257\345\276\204.png" "b/zh-cn/device-dev/kernel/figure/\346\237\245\347\234\213\345\275\223\345\211\215\350\267\257\345\276\204.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/kernel/figures/\346\237\245\347\234\213\345\275\223\345\211\215\350\267\257\345\276\204.png" rename to "zh-cn/device-dev/kernel/figure/\346\237\245\347\234\213\345\275\223\345\211\215\350\267\257\345\276\204.png" diff --git "a/zh-cn/device-dev/kernel/figures/\346\237\245\347\234\213\347\211\251\347\220\206\351\241\265\344\275\277\347\224\250\346\203\205\345\206\265.png" "b/zh-cn/device-dev/kernel/figure/\346\237\245\347\234\213\347\211\251\347\220\206\351\241\265\344\275\277\347\224\250\346\203\205\345\206\265.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/kernel/figures/\346\237\245\347\234\213\347\211\251\347\220\206\351\241\265\344\275\277\347\224\250\346\203\205\345\206\265.png" rename to "zh-cn/device-dev/kernel/figure/\346\237\245\347\234\213\347\211\251\347\220\206\351\241\265\344\275\277\347\224\250\346\203\205\345\206\265.png" diff --git "a/zh-cn/device-dev/kernel/figures/\346\237\245\347\234\213\347\263\273\347\273\237\350\265\204\346\272\220\344\275\277\347\224\250\346\203\205\345\206\265.png" "b/zh-cn/device-dev/kernel/figure/\346\237\245\347\234\213\347\263\273\347\273\237\350\265\204\346\272\220\344\275\277\347\224\250\346\203\205\345\206\265.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/kernel/figures/\346\237\245\347\234\213\347\263\273\347\273\237\350\265\204\346\272\220\344\275\277\347\224\250\346\203\205\345\206\265.png" rename to "zh-cn/device-dev/kernel/figure/\346\237\245\347\234\213\347\263\273\347\273\237\350\265\204\346\272\220\344\275\277\347\224\250\346\203\205\345\206\265.png" diff --git "a/zh-cn/device-dev/kernel/figures/\346\237\245\347\234\213\350\277\233\347\250\213PID.png" "b/zh-cn/device-dev/kernel/figure/\346\237\245\347\234\213\350\277\233\347\250\213PID.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/kernel/figures/\346\237\245\347\234\213\350\277\233\347\250\213PID.png" rename to "zh-cn/device-dev/kernel/figure/\346\237\245\347\234\213\350\277\233\347\250\213PID.png" diff --git "a/zh-cn/device-dev/kernel/figures/\346\237\245\350\257\242\344\273\273\345\212\241\351\203\250\345\210\206\344\277\241\346\201\257.png" "b/zh-cn/device-dev/kernel/figure/\346\237\245\350\257\242\344\273\273\345\212\241\351\203\250\345\210\206\344\277\241\346\201\257.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/kernel/figures/\346\237\245\350\257\242\344\273\273\345\212\241\351\203\250\345\210\206\344\277\241\346\201\257.png" rename to "zh-cn/device-dev/kernel/figure/\346\237\245\350\257\242\344\273\273\345\212\241\351\203\250\345\210\206\344\277\241\346\201\257.png" diff --git "a/zh-cn/device-dev/kernel/figures/\346\237\245\350\257\242\345\257\271\345\272\224-ID-\347\232\204\350\275\257\344\273\266\345\256\232\346\227\266\345\231\250\344\277\241\346\201\257.png" "b/zh-cn/device-dev/kernel/figure/\346\237\245\350\257\242\345\257\271\345\272\224-ID-\347\232\204\350\275\257\344\273\266\345\256\232\346\227\266\345\231\250\344\277\241\346\201\257.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/kernel/figures/\346\237\245\350\257\242\345\257\271\345\272\224-ID-\347\232\204\350\275\257\344\273\266\345\256\232\346\227\266\345\231\250\344\277\241\346\201\257.png" rename to "zh-cn/device-dev/kernel/figure/\346\237\245\350\257\242\345\257\271\345\272\224-ID-\347\232\204\350\275\257\344\273\266\345\256\232\346\227\266\345\231\250\344\277\241\346\201\257.png" diff --git "a/zh-cn/device-dev/kernel/figures/\346\237\245\350\257\242\346\211\200\346\234\211\345\234\250\347\224\250\347\232\204\344\277\241\345\217\267\351\207\217\344\277\241\346\201\257.png" "b/zh-cn/device-dev/kernel/figure/\346\237\245\350\257\242\346\211\200\346\234\211\345\234\250\347\224\250\347\232\204\344\277\241\345\217\267\351\207\217\344\277\241\346\201\257.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/kernel/figures/\346\237\245\350\257\242\346\211\200\346\234\211\345\234\250\347\224\250\347\232\204\344\277\241\345\217\267\351\207\217\344\277\241\346\201\257.png" rename to "zh-cn/device-dev/kernel/figure/\346\237\245\350\257\242\346\211\200\346\234\211\345\234\250\347\224\250\347\232\204\344\277\241\345\217\267\351\207\217\344\277\241\346\201\257.png" diff --git "a/zh-cn/device-dev/kernel/figures/\346\237\245\350\257\242\346\211\200\346\234\211\350\275\257\344\273\266\345\256\232\346\227\266\345\231\250\347\233\270\345\205\263\344\277\241\346\201\257.png" "b/zh-cn/device-dev/kernel/figure/\346\237\245\350\257\242\346\211\200\346\234\211\350\275\257\344\273\266\345\256\232\346\227\266\345\231\250\347\233\270\345\205\263\344\277\241\346\201\257.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/kernel/figures/\346\237\245\350\257\242\346\211\200\346\234\211\350\275\257\344\273\266\345\256\232\346\227\266\345\231\250\347\233\270\345\205\263\344\277\241\346\201\257.png" rename to "zh-cn/device-dev/kernel/figure/\346\237\245\350\257\242\346\211\200\346\234\211\350\275\257\344\273\266\345\256\232\346\227\266\345\231\250\347\233\270\345\205\263\344\277\241\346\201\257.png" diff --git "a/zh-cn/device-dev/kernel/figures/\347\224\250-rm--r-\345\210\240\351\231\244\347\233\256\345\275\225-sd.png" "b/zh-cn/device-dev/kernel/figure/\347\224\250-rm--r-\345\210\240\351\231\244\347\233\256\345\275\225-sd.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/kernel/figures/\347\224\250-rm--r-\345\210\240\351\231\244\347\233\256\345\275\225-sd.png" rename to "zh-cn/device-dev/kernel/figure/\347\224\250-rm--r-\345\210\240\351\231\244\347\233\256\345\275\225-sd.png" diff --git "a/zh-cn/device-dev/kernel/figures/\347\224\250-rm-\345\221\275\344\273\244\345\210\240\351\231\244\346\226\207\344\273\266-log1-txt.png" "b/zh-cn/device-dev/kernel/figure/\347\224\250-rm-\345\221\275\344\273\244\345\210\240\351\231\244\346\226\207\344\273\266-log1-txt.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/kernel/figures/\347\224\250-rm-\345\221\275\344\273\244\345\210\240\351\231\244\346\226\207\344\273\266-log1-txt.png" rename to "zh-cn/device-dev/kernel/figure/\347\224\250-rm-\345\221\275\344\273\244\345\210\240\351\231\244\346\226\207\344\273\266-log1-txt.png" diff --git "a/zh-cn/device-dev/kernel/figures/\347\272\277\347\250\213\347\212\266\346\200\201\350\277\201\347\247\273\347\244\272\346\204\217\345\233\276.png" "b/zh-cn/device-dev/kernel/figure/\347\272\277\347\250\213\347\212\266\346\200\201\350\277\201\347\247\273\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/kernel/figures/\347\272\277\347\250\213\347\212\266\346\200\201\350\277\201\347\247\273\347\244\272\346\204\217\345\233\276.png" rename to "zh-cn/device-dev/kernel/figure/\347\272\277\347\250\213\347\212\266\346\200\201\350\277\201\347\247\273\347\244\272\346\204\217\345\233\276.png" diff --git "a/zh-cn/device-dev/kernel/figures/\350\276\223\345\205\245-telnet-on.png" "b/zh-cn/device-dev/kernel/figure/\350\276\223\345\205\245-telnet-on.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/kernel/figures/\350\276\223\345\205\245-telnet-on.png" rename to "zh-cn/device-dev/kernel/figure/\350\276\223\345\205\245-telnet-on.png" diff --git "a/zh-cn/device-dev/kernel/figures/\350\277\233\347\250\213\347\212\266\346\200\201\350\277\201\347\247\273\347\244\272\346\204\217\345\233\276.png" "b/zh-cn/device-dev/kernel/figure/\350\277\233\347\250\213\347\212\266\346\200\201\350\277\201\347\247\273\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/kernel/figures/\350\277\233\347\250\213\347\212\266\346\200\201\350\277\201\347\247\273\347\244\272\346\204\217\345\233\276.png" rename to "zh-cn/device-dev/kernel/figure/\350\277\233\347\250\213\347\212\266\346\200\201\350\277\201\347\247\273\347\244\272\346\204\217\345\233\276.png" diff --git "a/zh-cn/device-dev/kernel/figure/\351\235\231\346\200\201\345\206\205\345\255\230\347\244\272\346\204\217\345\233\276.png" "b/zh-cn/device-dev/kernel/figure/\351\235\231\346\200\201\345\206\205\345\255\230\347\244\272\346\204\217\345\233\276.png" new file mode 100644 index 0000000000000000000000000000000000000000..f7ffdd153fcfffcc4fdf97a51b66c11c502c6a9c GIT binary patch literal 25459 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 HooD|GN*QnQ diff --git "a/zh-cn/device-dev/kernel/figures/\344\273\273\345\212\241\347\212\266\346\200\201\347\244\272\346\204\217\345\233\276.png" "b/zh-cn/device-dev/kernel/figures/\344\273\273\345\212\241\347\212\266\346\200\201\347\244\272\346\204\217\345\233\276.png" deleted file mode 100644 index cf0684595b4e7b07dfebf6c55c867a97e1e71663..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 51242 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 N0#8>zmvv4FO#q=`=f?m5 diff --git "a/zh-cn/device-dev/kernel/figures/\344\277\241\345\217\267\351\207\217\350\277\220\344\275\234\347\244\272\346\204\217\345\233\276.png" "b/zh-cn/device-dev/kernel/figures/\344\277\241\345\217\267\351\207\217\350\277\220\344\275\234\347\244\272\346\204\217\345\233\276.png" deleted file mode 100644 index fc4591567b7f1643e1c065df5860af3e7aff2a3b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 45092 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 z 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

    mm*8U!Ft&0kuyrO_;T0h8A@@w95})!l9TG2w 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 diff --git "a/zh-cn/device-dev/kernel/figures/\345\206\205\346\240\270\345\220\257\345\212\250\346\265\201\347\250\213.png" "b/zh-cn/device-dev/kernel/figures/\345\206\205\346\240\270\345\220\257\345\212\250\346\265\201\347\250\213.png" deleted file mode 100644 index cb86acd9c05059302f21ac10a3d8604b6e742652..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 41391 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 diff --git "a/zh-cn/device-dev/kernel/figures/\345\212\250\346\200\201\345\206\205\345\255\230\347\256\241\347\220\206\347\273\223\346\236\204\345\233\276.png" "b/zh-cn/device-dev/kernel/figures/\345\212\250\346\200\201\345\206\205\345\255\230\347\256\241\347\220\206\347\273\223\346\236\204\345\233\276.png" deleted file mode 100644 index 96a1c33d124ad5cd67afa331154840ad7b59c9ab..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 32118 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 B6VCtu diff --git "a/zh-cn/device-dev/kernel/figures/\345\240\206\346\240\210\345\210\206\346\236\220\345\216\237\347\220\206\347\244\272\346\204\217\345\233\276.png" "b/zh-cn/device-dev/kernel/figures/\345\240\206\346\240\210\345\210\206\346\236\220\345\216\237\347\220\206\347\244\272\346\204\217\345\233\276.png" deleted file mode 100644 index ce4103b3f82838d3593e7d04523b402b4283effa..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 28092 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 diff --git "a/zh-cn/device-dev/kernel/figures/\351\235\231\346\200\201\345\206\205\345\255\230\347\244\272\346\204\217\345\233\276.png" "b/zh-cn/device-dev/kernel/figures/\351\235\231\346\200\201\345\206\205\345\255\230\347\244\272\346\204\217\345\233\276.png" deleted file mode 100644 index b21c09ee49ceda81474ce085aae1f67feea17f3a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16217 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 literal 0 HcmV?d00001 diff --git a/zh-cn/device-dev/porting/figure/zh-cn_image_0000001126354076.png b/zh-cn/device-dev/porting/figure/zh-cn_image_0000001126354076.png new file mode 100644 index 0000000000000000000000000000000000000000..b241920b30fea1b2a432f6ba01045bbfbae7fb58 GIT binary patch literal 89981 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 Gc>N#PT?mi> literal 0 HcmV?d00001 diff --git a/zh-cn/device-dev/porting/figure/zh-cn_image_0000001126358814.png b/zh-cn/device-dev/porting/figure/zh-cn_image_0000001126358814.png new file mode 100644 index 0000000000000000000000000000000000000000..39c6cb96611a7ced5e17bbeee96ac77ba5c1bf58 GIT binary patch literal 55221 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�`CQ|RV#ExZUQA8abUl4YF<Tjw)MXG`sms%vJq}4 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 literal 0 HcmV?d00001 diff --git "a/zh-cn/device-dev/porting/figure/\345\206\205\346\240\270\345\220\257\345\212\250\346\241\206\346\236\266.jpg" "b/zh-cn/device-dev/porting/figure/\345\206\205\346\240\270\345\220\257\345\212\250\346\241\206\346\236\266.jpg" new file mode 100644 index 0000000000000000000000000000000000000000..dd8e1c235633c3e42fcd1360b66b3ce3452db02d GIT binary patch literal 612762 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 &gix9V;_HEG)$Zf6yxJ@Qw=Nx%hc-RW)`F?LU zjTwozMrSN+LZg{*i})}&=<^wWxjy7HM;q~hTpIBh?CmW>x1Qd-VV9H{F)Tt&hYTkJwGsce&x~usg=`z}?}n+vkI`jLNwySJ0ZX!Yl+YgFYymSX_+J6CK)% z!30_vWm}$mm#XXd+;vk%ar=9NO-na6ZhpSyZsRYa!^>w-QEhw>p zV;yteO{~bM{88;6ATtMyGyXAu`X4F|^<&Cx#GEXVGp)*P2y4Yxja}wqrow~9%!jRw%J3OY2?^Lvp*s9WHdl8BtoW1UaTd}nJ=UjLGicy(oz(X7R z)r>P(EByoAG$V1#*J6+uFJ>-dt80^h%)=@`48m0XEfk7D zA0!+tehosH!n0_g>*pvULp%$V^h|)vr{@M-EOOSKvtXPtJPYDxCo~JpDa<#`NY>g+ z185}iBlc^>@2DqR7=WO`eQX4Me2yh_h;80SWsZb*L8RmXv!XN-P{@H84AEl{@rB~Kt3vrj{XZ9IURJIu1Re`moBvu zxZ?$A+pL2ANZ12jU=6wmU@FoF6wB}AL1q5h2nSG(UxS?<&SAg)^bzdP@;!k3bX~po zPaI_ErwmCH4LIbj`|gl;_F+bxp(4@uVly>Iwup8tVg!#``{u;uPQ%pCrizc6RWSNf}J3q`aVfR8E$ zZ%Y4sk^emAdX0_#yuKYYA{}o*6I#9l0Gau3E?!v!O8QG3R&oUZm6DC|)dnyAU$;Yj z^iy!*eE@(mz7*V%FaK2^=+C#O0m$@)03XPl1|5U&Z;Rf(g(mX44Ca1f0(31Pb&wl(LD`%8!kcOo2L(I7}){K_eray$i2!|4+3Ic3eb@1LD z>oT35^pN!K;)84Zhe(l;D%p&fz4WUU9-ChERX_2<1e>vUWMBJbkG{d|9)J_p8cpl* znM)DRHf_*$xe_4l%*odj+yS0Re#gR6GVpC*RZXh^d8#E?ikGmTXQgE?8ye7G zC14fHWPm~pznPrih|kBu1Ndr4qN6Lk1n`}&A{A(E|M$W!LgWUPyD=1i5@RV9{s5UX z#QJ(lV_d#1dW!yf@!O)KC#F9_9TO0u33V)dHJP(W77IWzStkMCIldNKB_~C9yaqAl zt_mQTGlrPbYnh^7Ag)*fJX6*O2+f#deK_%AK+>nopVl5p5KF;vUTy=cpOJ~Ry3go9 z|KMH!ozMUKxc)w0f8SsKyR650bKyG*6uH3nKfsTJbY-xmEoq>UeVmTwLDr2G-~#1+Jx z4XH1t+oYE!K}f@2TqppD^dG7=-$`c_a6G^DQ^}!$_-f{~n@Ubmo2pm|%b#b5zCLy@ zjMm0@-LyK~p4hkfK#nlh*74L4t)mBQ*KA)|^7JzFqaQSD;7Feil1@NuFh==OTn`xD zCfx--85M=138jU-OV$_14fCYQ@XejtQ`L3gL!eF-TM{mUb_&ffakGmNig`QoYNafJ~ zD~Gl>jqr8e`P-sJ(EBmTv4p>m?B8%X|EK3nsstpj(D3;jHuE)Kx;&H%iWmso+M{=7 zbU_YwlA$WbcZXZoNQ%d<^zfl8(w&HgZ4YKK|Lq1aaqe%aTmyK~JFoG=?j2|}ijJ{f zm~GBcPjwqQ*f&M#)BRB%0owMV(x#C;l3Hl=F8%>$dXkSvHfOZSdvXTPN54bzMw0+z zswL+fDY%EE6A{M8URE)mg;-W8dx(wNVuyxavydo5>z*SSEsZL@XqKwaVLG+K`G0Vu zNpCj(L>%U!*+4*KdEY3vbCpkl=We`#{l>N*R&?Q@mqSpc3km z2NPU>$(^dA)j6{hH0dJX(Alw2i6U4@A#fu<Ly$ej|{pbrS=pYX( z0i)CZvgo%9=dfe*Sn*2in1pm|LF?e(NA`n@^7lFW`#$@7ZT=lK{*JW&=kHF{pYRXc zrZ;k`YU3=|1*-yL3MLQ^Zo$eoZbc}goOFx~pYHi|NJyt5rOgYt`1uz}^ay5x&lUj` zSABTfjJ@D!mRa?y{D+^nwtg51&C!wfaQ+?v<&Ga(2%x_H5~Rn6N10jgFofCbQ9BtGvAwr@F6arN-QbDk zY1$K6%ZGp?OVGbb3W+pwfh*E#s&0SGsIfFBgA(K+W$IM~cNjfnCCrsju>Qjw)uv)^ zqC*EivK2}|FW**=3od--zmgHg9fq`tnfr1)V(oGqdw9J?Jx(9?tTig@et$Rkrj@86 zyYNKuxG=XSFUJ3VU{qXQW5J2yV_vKX+Q|5qBh**)dFngVriNE}uj-RR31KTTR&>_c zYdqZUivX6>lH#tpj3gfufTi6eMI%Ynz@cx8+OTR+(>`nfkt>ewuIq*#T=$ z9)Ph;8Lh|TCs61D;* zR*?~|$l+t-Ab<4Wi)KnKwiP{?B0MLcC4H*$HsLZ^hjn-dY0W5gcd>lWT*j)PA+0Qs zdUgqFdDuit)ghwX;r_YGvX6~=6fWn=y>35s@9Oe3rTwL`SNXOsttTJtk!y8VcNspH zjYi`W0#7`A%<`xXEys9YCkwBHPq{^Bdl-I8+?39>0ul;Lsh) zKAs(>{x!|g$9?O@Ao#->Nt$)(*1d-mjyV`FytP0-rpPfvaIg8o1i{(DQS>ErHD#(p z@S@Gb`r1XFf@c$6t`S2rL~ilk8tv<0l!Z4~dG?Zak1~{lqgt}B`4&&)p3b{i>^0cp z7ZP*-_0VBsFYnub=oW!f7iKCn+W*_ZV37tyqf~vRpR@_uhjFr3%JP~+&a@M7AlRC1(rPw#1FW)=S z)qjPu7jsAYX6n}VJWX?rFxSB5aO!^7b83geSiN_G+7tSLAeBh%WS~(g|D!X}4L3O# z6DO!>JFb8HK5kn?g%5!@lS*0Ih@QM4T`L%C!Np6L2{v(J>+yos11#w_L0de=oc=}( zRG_p{NA?O{HD;DgWV_80_cSR6<(_IZ5}00?zKaCywQiZeJ-q2jt?@piR!;0Hl70;` ziEZhKUnO4E&}rJCJSaYu(>AgugX_wPt1b)z<86kG>n+PLI+mA9&E~I<=dwMXj1PSH z-0Sh?`PmH|L2Yr`dyODW)^q{6pY8sJBzA(FTC+$j>nF`--O@&h^ z)n0iQ80!ICHL@j1905T_=akJ4B zdVc16u?#}=Nlq=WfkHog@A*9h>h(#gfUUO{vm!xSP8bTRW<94y-P&rjw2VhnaY8nZ zXnUDhn&(nl8%kQcxOQva7#`+M@b&x0=*!O)Y}MpyTKXMpK6@-eTb1Ewn&rnnH;Oz* zv(DabcI5^2I7!B8X>nBB)*B^u4<*n8W<}qbGu3;IKleEGL>SmdOZGTEcohG+RoeP_ z&7-P@hfiuR8h)a0qrXd!j!xW2^pERy&%2hDVJXGHrsQ3=0pzmbgSnyK$R%JF;nXX@rKBHeQqDE%*{=sX??f#5)^ryG?z@BdiS? z+LoM~{(I-kt!F&uyx!itry}^(_Y4sY2#uqKK(h^>q|P4ELLxKS6X5sP;Uh zT(VT>1bEyt&+TZ=7!vWAZ3HFnAf>I_Jp;aI%LtfLJ4BWN=RfAARn?Xj2NC$fN0o}K z6&@-@Ip-US)GiLNxnUl?4LLQ<{%f;wafL_C0y^)&Boo%fw<`{ke4Vd06zO8K)E{}6 zz9n`wJHJ0$Zk%IuIKZjEdGXrWM<>ruZ9d^~E^BvhYVg>_)?-d-7-PHO>~xos<_24l zxl{d{>$LddS963oj5imjP4r}q?1r&P^?UhPS>lreJ($B>oEp*Dqla{mOHe`x9uE_o zy6X3FXI2HOn&&!H-whgyXlan%Dh;fS+^H&bW<>;tZe4vZZPq3Yh&`hpK&+5G%@%EJ z{IIXk23~oMFEMxOC&`r%2ZYxUb8g6<)*Jo5|DKbEGrE zU|QXC*i-9t>#TiUw!!4FQCtgSCCLpaQpSjuNC)t+L&oA@lK@JUTN7o-M5^X5+z}rw zx=jzMmlF{tYZeBkLiwehH~kuz7P`$)0%vu-jc;UWdrKKWX8f@#n_e`0%EH*-k09Ox zjqkbA6*_34$w0nP9JExr-l*x@B1DJAHj1~v$CFJ-1VQc7j+ITL8OxMt=p`a7y5e339VoKzGfYL z5HaDHue18`E{()pe8tPHM_9Hta<|?i7_ZY`Z=76@la%Kl;SzC*%IG1yjPwn< zg23j;efKnA5r)19eUR8uRNVNzX9ANpZ8<~&7q;Z1kPEqUpN9i*e1=khFvCNFJ3S(#Sxit0;2A6 zOoh)12Z_P#of&~^%xPZffg{ZvVGT=)Im4Xn9tOQfY7l3}e@R(^%`zvkp!niRonsyD z_X_D6C1+=;FUMWZp35ZBtEZwwf&2m1mh)vBA2=p|xjpt_p_k$4q2!o4UVhAbm=XVp zIZC6zhds4|##oUY_(;d=vmNZCQTK+lK3t9v9TP99?WaeSM%O%e)b%O6xSpKT8T1=o zXYerX#ZPZrF3``wWzUbqJj1`R5i5o9Xl;gg=`vd|&~YgrK=fC_Nf#xBXGp<3&hX6B zC~RuE5OW9(VJO3Unp(#2t>Bipj4OuSt z_>KpgvwnTi7_XiBvAfiV**D(TetxQ)dZBO^H^BGY?snrElZh{JUZ);R>L1p;rr&w-y6Rg5S)$b@HX4v##toTnDs6gZ3k##lj z*_7yuKT~+NP?jsMnBQy{zg#Rar3IlPfrM5 zk2{!@YS!G&-@%`7bxifQ*iA;uxhZ;hRpeCC9IG_~h1O{zdvZI_G$inGsrlLn&~d~0 zAp78v8TJsw#wFL8x8Q%8peTrCq0uT^lCK{hr}=ua2k~tlASQ^Lnn6^voyR9(7l%_8k*o!> zZSm{+d{f+DhuY9mTyRW@2ld;cVf0dMg3cMb^MxdHLSXH2?_Sj#k`?F~bd7Oip8y zpxQ4}>tRne*ev*}(+tr@(q;jv&hi>>OTB@>2naOq9>uM;1>KNU$BGJmpRD*u))QoB z6*p$kU;mmjWL;EK^unn!{PDy50QcSVS}0+fB)=X9pPdvY!<;rK)^fdsa;7RT8sC6S z7Ko3))^zwRu%51dE2QvZf+l$p@sC4CZ^!7eau$4OevBZe$w2>m-s1!PLs$D}J-jwT zDbk+>s?%1#LrteagN6dX;>b1rL~;veT*iKv&bDuB1%xLn9(oEf-GPcD1CG@Rib5@5 zUHIXL0+6za&EB3O_n?%~u0nakU4u0ZlH&8G87`6v-T>Kl3E`Rxxi`ayPoNZCdZ{r1mDs9qC?@Dk9-_pn{SL zz7Mf90WoMfr1~(=*-jG#U9KeEOgQ2?Sdis70>0iw`5Ae!=&E^3<0Y(IF|| zP^rJ~nl7yDwcI2Ix{OaH1m3625WfAR8=L7gk^z#(r6>gFD`mRaeyWP@P@1&3kPzmF zPMmiqKv+u|@^DnbROl!U*_xAH?HQ7MH*i{IhC)W%irw#qNA8yko zJg}@74aY9AFE=9*TV)eVHcFGXO}3A*;mIWe;ZyQvkdb0kqoaA=IHyP5;dn)G8-4C= zH5F(+cuzc(viIeLQ)sd0u&?o*$v9w)p^_C8nnJVEisJ>TJw6$9;>|e(ad}p})z1U# z#V9*>y>Ycl1TEv`=R=!S2ivpsBzW^Cfvc^ZOHfUT?{-A0%I4~Ei`^vBl{IM7VvK&N zvrN1+T^u10jpCYT9gI-%EMo8JCXGELgOaT?Q?_iES*-08hC(3 z4v+Fn1JxG^{MpR4KsP9Vt;I~Dk#A49)|%iEz1}LifymRd_jCfT+jOQnrqZb)dynU? z(|P?S;v#7`ATox00=LMLGH^-t$gTLbV%Je-qE#EdmhzOdBG`k&N(=Ii9RxD~6>m>K< z_Z3*3uVJ3*w^aD3KL1E`IIXmXa#JV~$j#NsoFPK4IEKWG;QBem1U5+Qq3tHK7Lq zi%f8EzW)}N?#3syK#RrtAmuN1f12Y~M~;i(H$?BN?wcu__DlaT(Syt8MH4sL7NzM# z_)hmB0F;om?j>&t#MkDC6~9+&1F>RRJ|}4v>4Kyj%hd!h<_yr*M{GyaT%L*6BNK*) zf}vGFEQ-ND-SE5oVXb-jNf}?bgH3bnrI*d!j_aN#(E7ta+0AcqFn#QucgRO>C8wg; zr;E)GIPsy+!oehDe_3wU*T5$(_w#l=v&=Q+@8atk9#u7HH<3jLF4w>J@MY=Ro6R>$ zdL7mj9woYW=h<#9ZasT6#9d;H7>NSNZBSK4VuaDs?+d&-VX8+k(-O7wH|e^5%nlgO zuWg=5_F3OuwRFZX{Hs}m{Xy6~IpVEd+pp=;h1QmNgVKPq?9ZS32aA-v_Gcsk0vuni z*&E-?(IPJo1iHmwOmQtq7cRl85oz4b6h1-0M|>C_xEc{gAW(@kw)Rgoz3&7^)3~o3 zqHhP7N(heK^r{zw=N?VE3&I&8)~T`|b7bJ&+k+AQ)Pq4e z=J-GIZwZ3lVhmvjIL};!0Ty!m0btz*%nX(CGm^0Zq8VjrE2YLLR;m(!t}vfYD)`8e zw_HU$iq9C?h@iQgL6K`Wc_k9bjhq7JV5-hNjT?e;cUF{G@j|(2cy>-y_nV;nHk8{v zgqCn_mUP3i;ReP#pxrFUYHhB6)%iQ=DZf9~2KGH{%+WnssV%R%o8IqM2~HyQ?NHPA z&!ikFmX-;A-k|rK(OYRpv~yUgSZX74{iMmE?ohhk7G8-{fkV2Sg3XG@6CVagaB(-z zR473MoEFruk?u~42h;YFcF21XuQBRFx%6OXxaBSq^;SFP+?$|lX`9ys5~S_P?&KXH zq!j?f7`RRwB}9F>4EblI;;Zr`K!14kh0o1n&G;qrj7#d~iQy@75?Xj^B~L??F{HuI zc}iIRCUBWyy~V}YgMyt5M#FnaA*bk8Q{n(#nx8o`|j_s20B(`aPjepMj`cG?0Kag~@MB!W?SIR1Q1fSpc&SmOB z)`JHvyiIm$r7Xqxr|m)af=`~S0#v8{j=+UriF7e8xsy27G)vl+)9l;UCALjr4{gm~ zocWY~4xc96JBjB1{$TP zlD74WvB1;lY??rqrLEst4YGp?sj|pq1k9x$E+V$sF`vMIvz#Dp)69W}ch;rW5e5q{ zN_*bx>;j~;Wz8~B(_ZLA_3^cyLMut0a#p;R44l%u?h0y&Vw2nz1DFMJx=M5_6vwP~ zOU8~SGk>mrWx_(kxQ^kH;Z|&QZ(UIykB-|fn3;M7%h(G}=K;}8(H7F?&a!YuC3@-i z9F9j(7$zDyRS#5^V&g4WA_amy4z=)y$}riYdyOAL;!3Y{gsn(e&Ubpk{-CCr-w@8< zPpp4fq+eqsa&Y-ta-`Ym8F0t>RI?#YKRsJ@^ULkMfhT7*&$?ZufAHIt?EdDq%$<{u zKXwb(Uf5$=xKBUJ_wq}0l4ECF9oY-xTTlsP{pxH{vve;K3G_2t8|4L?Zm348DES0v>%o0OTEV2s z1CEFHpnWI}?{!e?ZFS3&N4aYiiKsMAmCYr{e-eipL1tLr7HQ6ZB-w{S!8Bd4-$23~ zNzt}xYR}!8Y;OHNnzS9g%+dglI1C-EOLX@k77bfh^=p@m|9uyLXL8rKHn<;xmDus$j&BP|o?M-O9@fToXh z2l)l(VdQk6$Yugs+PIa3t@q6M8F}IISdvFxE_R36t2~3;3~7^qR7Bp;P(%@^K3$+B ziFZd(IRQgi;!c6@q;rAjrOEBPf(vODowTjtu&KaVIFYt=fR@0x)nN#nR$`mWye*VV zEnIe}m1%lMJvw_wRzK^p9x`xq1)rc)V7;LVUl9rS;!^V0!<=|iXjSmgSd&3U;>a?X z!UC##M%{BWvXj#74=w!D+-yW>UQq$}u(@4)uB`^d$Dlm8sX=7v}Y?BZ}YOI6uW) zd~<;PJUJ`iL$Js~ZRoYfBfUV29qtS62d4wA>6nN2e0NzlZgy^kYjF8E8Hc=OBK^my z6<^a044bd!k{m1%;0$YfK7=x=&NACYz+4K3325@mv@4qXZi$eGCFWM{F>ir zgN{(;+oIS=Kr5sy$GGjz`$Tc76>t)P;T`S@2X>rUfehFRRt#kq@=&Ys!$f&tfQP~H z_hj-iR*??%Da<6APDisNz~BJc0MKc#_>qV3DevLKW{2%ru#IBByJxE)_)*kU?Fk?N)*TSJ@T&h7JYf`%S7>_*w0i;+ zp=Je0_e%Bf6Z}v9M1Lz-LELkc)won55CBLm0F-WW#4ex=oTb{fB2^C{oTbDJ zg4U2uLGjR%#uW&QjYe5+2BRr9EGPvpQ*X-!-R8AbJq$DK;t|qzq-hkpgyi}}P*yRq za7x|i>Rg8`K3KZB*N8sHP#9mRp{=W8Joi2!)%b{2#h_r_qY`j-MjKTq%H)kilQzn# zdQ~m~A#H2G3Oiz@YlD1NbYlo$*yF4x)D->!{*Wh0x=-2%$1z`hE*fr*=d|QZ`(ZA8?Pa^ft!QT&a^tvV zJr+&9sk;l3TKtYl58mi&K4?eX?e>9|_NsVS=i#o_QFBAlmd+S8Uk?vIN?-*1!3gCcv$qa4>> z)4du%F#0yew=9sdtUgjuGjj;+l;~fPtSC#g*rdx(V3hX0rWTe#uG`P31vF|_GX+bL z6DMo2O4WPiZTshAbeb08DFqW>cKXm^oKX7RiWr0&JZLi{3;>*=3P_xS@EsBcPE>q7 zRsabdBxP9tQv!b$L199w*je47f>?P;ewQv2Z--}6Oy8Qj3dUlm&$_YdYN+9bY!%fF zZ-z`W+r)h&*T+a-V6^DyVZjh?*l7badKq2wQdeAoTzwY@EVj{?oN)S;&z5#&RSi-Fu%{M~UoOhj&sPs9$> zJH^Mh?@F?IU4Ld=Dh#63LQRl7X<4P@ckx9oen_`Tx>9?S;LBBvW5F@$ORRRIA@K{h zoe4AD1P)33Y9xh=9h`lNRh_{Ya_K+MHr2fY;y2~gOl~&4D9y;Nv);cXFiMyZdH)ni z55%A}=?m;yz;Q4|PH;88Ez0mPPazuzS_q%Ozmwc0Y0NW}OCxGvpn>Si(rxv43xK*9 z!HZE{7GrU6iXS(m?qhlz`{Aod+KVOqj&D*Dmr!1+PF3(3ASNzh`lAqiW?D7wb>=8z z>Ka@Nx*gE4?m>7U1@gzOw4}nryn)u4c=VcjyhsgFUWw3rSghgg~wZuZA(<<^42kFEF|UM)!Kr$d-iIvm_9gVH{Rw!UEgsO*o2} ziPn*awRO71dqr5}1#cjhY>LFTF#&w#HNi&rRV!!v^G#Y>eC&!^!@90Em|x? ztvca)yaDQtZ@}ZDH#TYdxFtDJ9q223+}K#z!_cMR zYH)+B@1G|+jL0-;?}RV*VK$W^lU&NxMq>~0MkFqj8>7R=CXiLdR(1UaAm{r30I0g=jXTtj(SYSzIr2=2g4 zRK@zewgiZO6BhF0q^UF5PzIP79GlLA2|VEBnmp9T#wv@$5C}Hs;+quYghl;kT9G`5 zEOawL2ASnjo=SAMTZh~(lh-4$zxLGQVW2!%bgOI}`+F2B8T4h)z$y<&IWyBO)qvg7 z-blXOWlK$Q0OA`1qrP`Re}$T?v7@&t$Xy`EyD_x+79XX8p!XpyA`fJYm%su!51&g& zF-0vUR&w!I34o+`I7?d1Q|Tw+?|odzdPdkc6c4`-!+cQ$N3 zZC2vz8{cfBoYZzaEHasU=Jd~wg;&|5pHm&M8i~!WnFaeb_504v1$BK1I%zz$GcX~3 zQyIpf`=wu2FN^CPByB^*w;t!O-1uBzny;f|S9CG{=?NA6tS!7yCCPLT6o{1z##gna zWBnS?tbFrcF&-Wm{c_dPnE0hNJNIlNpcMJA0GcZP-ZGFSq8gD;y|6gA#)LC|)a@&}k}*wyQ-s$5daWSs8PRTNgymQr>AwX~;46b9 zw?}YW9Latsokvgv?Q#X=LCX@Ct4r<@N8&GG-EPXRkn{(m91$02eBhM4a zEzx>%|4~lG8a#X?m^19(qCU_94IA)L(}lp(8TXVj$bXtU&}x(pQZf5L(F*cQ{F-f+ za?%cfd}G!Yy#Skp7NRq1lwei>&mIy8s{^?+vg01xvSrpX8QY z3Uq?;x=q*yF78$Fam2q=tb!~X4UU0?R)`keBT%{mk%w3F2!tG`&aQU6YWl@gY$RO(Z`f`M|% zvWqC`VL4`_MAr1>($-)M4@h`}Mz$<4!N|dyq zd~l81&FFu4uV!iQ2FrW66)glo^V=eafrteL{x464FJ9R9XP*@>8y4Z~s(M|Zdu4AV zQT1;4hc_(93a9_zh4OlvUo`PQ zvRL`-)`UWIb(5I>MyQV?G6*gP zwQ5LD=$((fH-a2Px=QYRbiPo!Y*1G@pgjn0vh)4&8{Us~&CKsQJE!XRq>lI54|QLU z3##})-L(f7eZLx}0L6K$eFKep#2LO3;Iyd_}3QkgZ@q>(1i-&S~c z{HO&gUhK(7$&owpGL3tQR@O)ySnH_QZCnwQgjJZsE=EKiotcNbG2T3^;%lOR^D1IA zt%rFWKWNPo9v#4*{7P1Zf`OjBp2hpI6w+P>@}zZPAO&-bM_G;3;1bopu<@(JPE3I& zM`<3N9F@Rc25~LWO8AyZe%hXv&exN5)=y}hz}!?iwBNv0ZM;`0|k-!{MxPCgz}MG=Ysv_1O-Gy!yS@bQ#$K_*lmNZqF-TCm3N;C&;_I zt8mJJT2@kE{jUFH3y2u5MBDb*ps z{N=~)uy=7=Z1wgzvYhffZooIAT;4BNBW={@?NBa=FSJ`z+|NF#-@GF)svLAA+$AZN z>i>nkHw|klTh~RgL8KEAX#^pqC?Jgy0a3)H6oC?iNRJ4lltMZ&q99R2Qi?Rvr4$gQ zi;56K7m-d8h!C1m1f&;GLJ}3EkvSFOlr-Mq+GpQ;R+Z~HYn`?CbMJjl{hs0puQ>pO;D~TJ>)VOZ z0w09JrH!z8l-VmsONniSD=amP0?8Cv$1{ zRWP!nQsKb8ko&}f=0+`exo7n1qKexgK9^p3H@)-uJX6L)ja=YSL6QE%J!^_E7^Gqt z^6p8_%6b<_ZMsR*nsc9$vhW#+0w>=ZIHQ7C)8U6ugan{n+3DreV_p_?pub*~|8hY- zMt5e=s?;iGKKpt;t8lHmUBJO#AeC=aPDCdZN5GORMlI&{ZpYe#*yN^Rd zRMGBJp9eiF#&FR^4IgOH0%_Gk>}#N3TUX4()Vk)+>n9P7)%>gv-v2PKv$0&>X?wbtEWP3Ol&!=&wSKtn>RIaMBEwU4RA z$Xx)t0>a@oQeh*WT{<-9=SO}*JcEPhuFOi>iRe2!zR?$BmE7_ulL@9m0ICxRGAF!8D=6&}%c-U2w>FknV zIQa9aBi<%=Pi%bDAjFNW^^Blv7;j9lz}_2ZA8NKblV`cFJVYVJxD6P|t;1{Cn*;WR zdyYr&vErUz7EO`W5oz;$BE;xuh}OOYc6h$8?~^>jE|Zjc`6A@Q$ros$y$RvUFU-!eC*H zYFk0ne4(ntQ*_jsLf5V3^&jajFVgQ0h-sUG_Nh>f*S^Y`$h~vx*4H1b0cxWZZE`=VqAN>ykk~h_-qL|f!)rB4ksQT2 zfaAU;vGrXdVOH-JVY)WokGaWrtF*7^+%7v4wrj^X+1TuQ3pH zue;$ht*nWJ_9nTO?W;2NPKpZgJVSTQ49zH1cXrl)j<2GE)BT(vuOG7{OoARH1#(g9 z-hd@tLYfv`bIq@1#8ho;*R>e+s+W;zm@-<2jWnpTO44nw#2bSLry#fzG+!3=g-Y z0)uDSZ!%18JSX{#?R?HQp#R1XD*;tIoJ0Ony8XT_o9@2KX6SovkF)Pycl7?lUHU`v zmpb+Hjv8PZyW+!KiBn;P=brf#^?btriVb9f+i?{o1XO1Pr9Bo@jn^a_fQD~|9Ge<< z_f-4Y?58zlJKu!V*lp*dV<({Nc_G|s?bFR)rCej%ttydgegQ2$3k`2-7SDv7t+TQ{ zofVA@K@BGWH!k2At2C)&O;I66x8yH{J!mcH%M?|KP8bDBCV3#Hu$f~8s}E2u@QNbm z@F@8s+9$gJNE|t9ZwIdcw9REm$B+FMxRs?lB4MbJ}Q^r6~dIJ?w7Q0&S~2Y2={}6Ckw6> z6p3$@k+d129T2URHL}bF2~fKY@wqjRF5H>=R*Py}Pr@K7P~~`Z6MkhA&nakcUldN2 z$Z|%0#%v~5&eT`|);ytvNU(ch?xbIVC zbsT*eUupTI0n4M#%9e`E#o(YDI;$%v6X(z4R1o%)#R1N*Op*mCvi}Cro=h$bH)^(* zhvAo6>#CURje0LFGW8`qAt@9L4G0~b*QM4Kh07T*$h_sg>qUqQZz-j z@Q3Q4h+`vDHbILnwtl06&S$RIH+wC%Oz2zPxN_{?n|@OdqyC&shk*)ngreu2w6NK5 z;O(!4uBC5XJ%SDui)#%TbN8O*7O3CdILR~1_0#b-vNKH6O*~Va5wNzvQD|2ma*us& z+ZQEX(CijC=LvboV7(EjgXj;uNiheYWAO2U=B4yg;Am>q%=+@XPq`0CDpy$>pfvTR_J z>qWIAN$;;VXYZivzb{n1Mps|ukQU_=8KikFm*F1gqx$~Xmcf+!U6&@@?q=NSD>QJ3 zhxNr-F}epDA?L>5kl*YhxM&q5UTfz})KJgDtkxucq?^mRZ0#o8Bsz`+FeV3M zo3g3RonCCzOTnN39(@^d=%sxay(mY8ZLD@CWT{rj{1s0%q4YpuVT+;8^7ej^idH3v zexoL_1bS1PMFTJ9H8;AK<+Dk5x~yx<@pIwU`+apuwmW%`j>>(i-4pDVrn{P9cehZ} zNEttDa3QpQ%sJZi?)H?f(xA<5O4r|IZu5e5B*V{tVKfzn6d~cEm z@18koDe>$(A=~$y>T`Zz!dSi9X6%{#9myAiRInRUj9*nIf+x-w7qP1!H)MC(; zp(cr8RquR^eXIY=dokA zSw*z|g|*o@Krcnw@LU|gww{9R7C|>_Ze}ISE6D+f2_q*?5UIe&dClF9l@H<;Owc^f ztGqCJby`^2`H)SILc~nG___pzBn$2%XN1Sbrgcn{c?34<5>1)BJlIOL{PrFC#jT(k zVcANShvOUWftu%-4y{F9XH!+bNd9iqUH`*G8m{k$iiiEj>U-us=+!)`T69i&O~T-M)GH=HJ~lEn{ouK!Zpe_dB5rS%1^DmQDZUVTA_Rb~1ix^v#T zqwkx|p^t@ex1jkuj2G_rcV=rm-?YJQeHEj4XYLN2(sR0MujO3QPti5Xtw3c@^YuiU z^&VaaB{AQ$w@O>xW@tXok((MvWq+|&;!TT>#ccK4-7>a;HDE2zARVX~vNqD8MTg%y zg5Y@Spy@PX#iL@&Bya`C8<9s+bt~>9b%vgW(Z0nMwBj)A@Kvp2Csmy8=TEsL7JN*;S+FQc>U2$N>V2{`FyT(+O7`{Bar-N+ z`?ht$P9Cu-eErntuq)l*;j;|wowm&5H!GR0-ot#3QH#^tE~n=0bP$!!9mi)J#YS%$ z2Mog--u9YH6u8D8}K^ zd2N;2udkQf0!+<8vfh};8dmOeYR#wL9YOlqO^TXK`*?um@N>{ZLjTm3;!_^QL#I+E zjx6&+)2dTKnI(hIPv;K$mfy*^?GkX>SNf-C+Z{ijoN|4WvEA7rPQg0Rz>R(E9)HUP zz4zE~d-U_uzn?KARb=R>ShTrCL{Lz5yhnU&8%rI;SWv|~ri~XoL{M?Hu)5TT$JT08}M4hRr4Ebdkib6CnE&3>{5!j!D;K*ya%EJ4ZOvgJ<@p~XmP_VoqV zsv+w=U_iZwN!YM+VdY_ju=g}A%J@}$1wKszd{wy7O*mj0h8AaY+DB?H&(_EA2`kBL zRHb@yz3sViKNY`N??H2l{Cgc^$arjNA1Ney{R(im54GzkBAEq<&f>YKQNohY#i|`D z!{oazZiZ`v5(?t-c6O!8dR}w&=@$%N*Ei2KswNN)@Jv0nSXrE7;8xs@Es?ts`Mx7C zv9wqi+{w7t=Mvg!Gkl1?Z_TCXLkx}H6u#?@+%R;wtX;7yJ}w`?n6V_v&*m_;d6qEV z&hB0zlI;Mo;d|hNg5)nB<}3I65>p<=gQNxNgLtzv^*A919=MD zaGhD)*I|4-8?_qw1Ykr}^EtKYI{GE+2#7O>l9zN)RD;A-Zh~s08qVT!lIG`@lQtm0 z?Q5LM#)EaYtll1Kn{JjY1%FrP(x?^(BnHT63rh!M(gg2r%|3{iwbm~P8DU+nSBD68 zXCK0=3L>~!el|{hRk(-u%5MxXH0L7>PlLd1=2I2wRCn$2r+OV-^z*XWUFoSO^w8>d z8Jee>#9^v#((Cv5+JOyCt&A1|y-HB}) zTLo;Owc$#^6~J6%H=$I>o2Fce%vPVQWG*68Byx;V;&#V*?lE%I+0$bzG4XX=ajT9H zZ%+6TM$bGIhEL;F!W*$+tSaJZWt?LyzGIr35!mI>WbRN@@~zYZ*3X}eG-0Gnq8iKe0kJT zu%M%_oSe03nisJawkWiUe3#3;!bpu|^hHEY9yJOu;zbZkSLvAF_kQkdrj1ukDD%=z z$)vD3fFshh!J<1Jcq`Vk9-wEJ@WPdNt)N~b3o6kGNKdh(XOWeRF%hXF44C$Wqw2=< zYQc`+{gB;vLmRaQjWK3Omt(5iK^9co{5SGpqc)MgKivirG#c}v=u6c!MX^zVq?1x3 zsTF!kI%!&DYZ6JE2_&qsi0)lcMD@cLjmnZvlsYzusnJ?Y!a?zXU%vgL7E41ifUQAK}$B{QS#*ZGT8#4cNdn~vX z$0!uH3bN?rXyO@(tebG(OGyW973*i_8VO+2tf*$a?0ACNg2Y&~C(Kh`3fm+);yZv3 z$LF@U?a}40$QpMFxNmdfCw2H7S?PLkIzCw1;b5 zmNPn}ca}IViTnM2hRR96!i%5mxt(D(|I6$3`=N?EdDCv$xy3`S$#Lg@yIyVN&RBo& zmw}3?FwbJX>bm00*Mty54_A+1ET=oOhaqeG(aFLp^6i==gQ8#lcU{l^nb)bpgc+Hy zQX43vY)SVgUbm!p?vjNdlXOJ51jt?D1)u?-QiN0j3GT<^sSyFJ1SQbPFk3pmeGWXg z0sPp5-FNR!(kG>#zezR!*UBk>uVjh;(F+u}tFuJe?XzfbO#CVZX94Tpp~T5$$>Izk zNIpb4&Jq4Vkzp)ybWS~+|)&x@wh>m z+8i(#`S;m(M9Q$_o2dMNA7uBig2PS#d_}?F`E}9Xp6d^Oo}}G&cdnR&}-0yJB8NSp!$VBu6!5P&=uPq#!aX_Y*qd<ydV z>)rnUz>4s~bl@aQ_npq%faIv{TDR5z!){pWU;XZNMbeA{HNgkgIW9)H`5m=s|o?nSY|oqG1mzug0(dvLcX zZEPF33xOic;@QW{f%AWQ?3PlmQatD51|m-K*Mo0j27khI4)MW^e|G~5H8MIC5YkID%@ui zbc&YRebYL~J>0(G?lZA4|ei;{W5tC^t5x zyAW`r9l<_@1@w*zK<8y(KaC2OiCDo@s6dF4$bn_EhxIeI258ubJ9 zi%dVn`ShML?h0;kD%i;W{y!P~>AiqAUN8-CzzM#vK(cqi+ETQLN7k~w=zgO8=^tVL z@K%^TNd}9ZlrM;65^OXvH~>EW^`ZZ6S^PEA|36yZADL-ZIMLcX%xaMhMXf`)il&H; zw@@ilTBStAkFtLL*q$fO64NCY1ETIxue7WWn(F zJK;nL^ZHCh(%+-rk?jlYWfLMpu)kCn;%0GQ)Ia}|n?b4MKR2SVzcz#a5AA?VdH8cH z0ogKi5n~}*f|x}Vk()l(asc)fN(l;uYG;?%Wb2DSwjw)>6wl4x`)J%t39%v8)Qs&v zJ(DS$b&Ojg*!~?~m+wc8l)nN8*tq_Rmj9XC{FNg7l^6XX>-;Mj1j+dS5gG6T?q$cg zS1b0CjylpB4bxh5q=p(dl0p$NpOCuvhN1wfr9tBj%OqC5T~ ziooDGYhhKzH1M6j7)cRIgUZz60mV>H|AennKlq^}P3I|+Yc@WaZwDnN_{A?+@s|8d zrEwQ zSxcE7z=}8g4dRLWNAL`p0;DNF#;|~ElJGH8>{hp#{Hxa&(EAvO4W}Vnhi1TxN+&|y zGw-2Kf}2C607?lm=ocoD{cJ_reJ-99%?7$JYaE(P5_wIO8LLRwN(jFR`I&s?2C z2C>G(6`rd%9NV1as6KG*;~}N_t9Ra8z)bBeENQ?j}&r-t9KJj;U?rJMCWF; zTmcP8gyHF*Xgno0M;aLm*F(Py^QupF%xWcT^+mlmpDgDHs%tOYo5>fAZtghpq_1?J zXZ*%i^%pFz54hRwfxpxjR?wViueKLh#UC27z9Shgg2fE%cm;Mz<2p$vwrZ}GaIprZ zjrjp-AE#fI>>MT%TD(~Iqi5eUCEe;+wMNBPNI`R5O&pJs>W@NH3P^?o*-5-I$@Cr) z(Av1U8etX?qj51<*X>BHbJCdOq?h@*jIEDy11+?KU8_%}+%0&V66mU&?(norc6xKn ztFt ziN6Rs11(eTK-XFP3sl7rjxxqV(lxdmiCI-FSqIUsRF`OJ&8ap;-1DBSEejAZHjZ$1 zB3OxBDmoc-5CB9PCpZDsKEaRd=IPyp9*@s8Vbw)jp|*=cUC9fUoMa=B-QH+4*oYYw z9qbjk!SaHPUb3QSDTIw(brtGpt^`GBS_`+#fr(XAo zbvr*kb3N4BpAym>73is<8BvlPxxsmRUbLM`(L09SX=?S|Z0FKlkG6QE`l1JiKD;;F zMc(K?T)aKbxO<(#Dzzw8FI9)_OvCz541?y?&3yeWr@3LL#by8;9FoXkze?G63b7R4 z$|;suJ(AK~4TcQ>3O%35-5lhS6%&*}UIX~ELn2oxvXq(#?eVGVOV*>hDvztm@Y(VV!reOa>Eyjd~K{dmyHq~`REo!({hvY6*nO5dzrvT^~VrF{A9jGeini;R!k%duG-B-U5 z>cTMGo|5U!zkR*#>^s`fgaV0w*(G(fob}+7p~sezXK6<0w($}};&Z)?aoAhmzu~^W zG?`RuP*{;x6F(54g&TayuLP6_l$jttYnX?Q&&IXMYX>~x)DF$A0b=tgwm8sut8o-s ziD=JL7p>uQUzIRk4Tr9NePmK%*l)dM+pbHCVX|hmQ&?rmm}Wm-i;M<(>n=i7@*uX# znFX0iRA;ct^==UTh&UC9{x_JpAUDS!qjiX99Pj4{E{e+~GDN1=BTdEmjX$TG;z_qBB9x8sKvy43XGk^1Z;16MD|>OgI``W znU$1qv1>xl+XJcrArIX`)`71P?RMURDVM8CsOv)*Wg$bB5*^q=T*F+Ede;*Hi(L9= zBpe!R7aTwyS;k9@gE^JVwmEr3tBs{vkK-u~qXhNvF_JYzX{WC60W=_sFr^gmD$w@g zB+dtvcoRzEVnUomlQ_f;pGzfFGnkkk-uo0?<;lxhW7X36w$58CFNd7&iZTj(80Bo1 zP~-6_@fiKOOP=~>AJqt&OWVG@EqmQPPTk0k(v{^-+uht^u%oC@-mQJWH6!q;;W=NZ zAO1x5(03>e#%aa+_S1I`c-I@>v#Mx$5rqK|e_R-NH>j^t1@FW(7Q8$PFG;S$es_bc z5Aqe4f`Qp2z9+I3niA~=wqmM910IJQ#kRecX=&UbW;L1-{rA{&-(s^FpX*LVVdtk^QZZq^&bE_2K1?#{+ZT5|)FBh{P;MXf3pgv@BSi z_jx8vXz5P^<OZFO<=lbp3lw``-4zHDa5$=3368%p235O3P)1qa;s`Y9=f)UQo#y5S8omsToEl2qS$Cf>&RkiHkUEz6 zBuA|cb!%ykIB9qi1(GtTj51yTGH4Q~^0VZJv=XrKMca#jP?Z6&PDWYI06Dir-D2g@HX4hda&v)Qw4qFq7!r&94XmOo2U=6)=#*WI5 zZ~mMh(RYM{n#fCW!)^!qeLk3&@w!`CX`k!Rmm8%J!>O*3cWkdjB5;^6gg)Hl9nmN^ zwlI-*ayrXD^sqPUr^d&Xj9qORQy_q*$2mm$tE~p9#A283w&x#9)s(rL_&yq?9jJ8v zWMGD&oyzk)8HQXBAB%ha4EO#}&qDhVw}hIB$Z6-Wsop|I>CAUKQ}(skXJ_0;4(dc@ zdA1Iw6e?KOW*T-`+#90f0={z-Pkw)WPFM#D9Ynt%fkIF66Hvp&ryNBN-)k4{1;pDz z(Gj?>)d~~GOV!iHwquuA>q60PmniWE7{nnLDv*NiUtnnyuRFfRwsN4GQzZqXlP~Pc zM_&7I#-?>vagt5MEN){Qtl|w7mE1yfc^!x=$5GM` z=CFyNjBl#})FzdVQhcb6dM`$oc=mv3cR3Qv*4Z3u|ES^q{n~!?4#7!ha@V0U4I6b& zk1d!`a=T29=Tk$^cMp6sP3QF$_RL!K&v~vs73YPs(4RTAFd>&wa3!+9+2Uuui$_TU zBgwtk#!K$E0*3+y{?re>z;pux+LOdcprH zsrkpF6!n&}9-{-e@Zn@-(Y}W;c9sUA@sJ3!u7A_Oyq~3DOMm?y3d6ft$*Ong2xWxk zJlttVKDEb9HkHXilC8)COz8dceC`&H_@0h;O5#|kzu zi4@8oCM!r@jD=U{m97a#4wPkb6lAq#^?r8v;CAW9-zS!qQ`q}QC_U>yxf|-4#*4^x zQ&1Oi$~_EyuP=8bv>fIBW(J5CMD+3wrn(j7W3oe6J6*6^#CVrbB;g8%dmO4iMZ z<)RRcRp$jL7XctVkW-A;~*e@bq6wN={<L8z19=coTWCK5H(b^!>9F47Q7CE(i{D-Qe}9Pf?-+(dfl<5wxVfAB}b zcbD#WbIU;r_f9x=G6mo$Nbmwvg0=tNV)8WOEUNc|5b=;A@kLE<1?OlRISR6sl_j?N zWS{>1GtzhWZvRTKMpZ(9;9Jl)HU`_ii~=uW|M(vMeyxswl{$PHyQl$1xhYD-dOwtH zo%5X#JN=fEjD?(8BS6G)cA0Poxev%rP(rCdvJtzE^~)$LQJp1i?PfW%rGze6&RSEy z2bEyG&q98K&^ISM+~n3JjvF-D?;5~uATJ-B4+yzuo{r^E{y5`h1Vz&M7bII=r&3d` zjx0jwYJ0UL7i(+cwGf@pY)|#hf{>3>(eU1=bEghIV27yeHg?(R+G8AN-T&HRC&8NT zTz2^Ff`^rP@lc7uvy?9eFX)EV#XFnt7Irvi=(~pNcdUGd+y9K-a&EIj2E%6C-6_u! zhg5@S7Du~1tGEuC7F+sK&K0{eR_@*Lh;GmtIzvqO7w)3ZimKfFVd(R}^pdqp{(8ax zllFdpd-|;S*C_qZhl9UH=|2&qsK1uR-=7=*<)txnOTtE}O3Xx#PlD1|NSfVk1wRS8D_3~fc2-B%KP6NyHw>^IFXop1iQEk4K zV~D3g;r6V>OO0mYU$JkDgwa6%LqY=S%K#p-`xR^Rjr#rnI{iEL&-8B=ZEiT$5h)Y? zBKe)Q8ju;|8dZ=&XpTFSgax?AXrt0diQxV~{SVegT$~JPTR(*`HzL!LMN?n}jF5Bef6IBH{t+po`!oT(#KT%*f&WmT2oloQGh zfIxSuWPw_YC2%>(KAYHK%iXqIee^Tc<#>xv^o-kuvO6A#QTN)v_>)IGv#+WuPPjO-PjB_8{{UtCC% z<%Wrk#=T~DLqflARI%{aX6&(@J>1nh@}S3j+jJtCNH!-)$Jo2pK;)8hg~XgE*%OHv z9b%fN|Cp+6qA9Uj|ZZc~J~v%A;M;!9qc7 ziUt7as)vBWT>wy_=F(P%F5;5v_X=&jL$RysO<@%v=C5Ki$i$csAM;H7a$*MY883vzerKwn(^1=h!$Vxy#cor>m1o$&I=wkihawNzbI(eIi zmJ%(6nXR1{#w~wch=N#&QL`#ejSz+Hrxv5uad<$*E@lt&gTIetv-n!o9yeYzXwRoL z0eBk7_v;~rKpsF3F@rAn!&z)0EnZ!HYy||eE=3A2zJXg7z_I?YH(QBsTv3QZL;y!MuA_*bb8t--B~rD+hx6uA8Z>Z=deDl&PSKn_a)dC9cJ- zP{HW-!uia}w}!beVx?jA5M9oj`UN@BxaztlZU2;84#O^;NV2eAwKr=#X!kLrzO=)w z-mgAH71zzfI=!iK=gLCox81lBu-T`^FE$OWl3aGaR}$5TLbp;ck@dydm{mk3kD5xh z7F~dKuHJo3X)?i%=h3R|6R<(3_{DBEXU*i84s1eC!;as<*APIPS`g|oN3I$xg;=sR zHzJ=}B`c6Ue2zNF1$lhJSY)Twx;Qr*z+~cmJbjco)ey@53JqvKr43w zjFrf{fHtMBEPrccLb#mBmdHsLi%cO_@;vqmXLUX9p6CaFj19THkXR6@9**#ig~FM7L)*J{tG4I0~^6iXK3u z0CszqM4Qs2PYL2IY2_Ow&!wVj6F|!%EYFj<0+eezT55pc-w=?k-fO|qK$?#LKh03) zxYDoj4~}$t+bgG)xt1QaQd;5~=aacX z&ck$0y@jNn%?E{q8B=yws_#iW`%(Vkn*lk6K8407HOrS04>raxi+^x%gWE7S*iJdu zFy>^LPh>`>?XQBvGU|bc$r~KkOt%%TU!}k2*{Ag@4x`I$l#-eP2F+A&@FS29KRo{` zl?}LizzG7ZRRK7STuLN&TPZ#19`192WoDiNfE+6$}Xcei`88lky!3yydo0Tve?Kdd*8P=I;!9mJ4~1<#D(B1 zbFt7N5GqiDFc{TJ7%^k#?-rK>ORjDn?#g_)ibM|VnbPuzZPC_DD5q&mC$@P}y_p4$ zy|R=rN&;S?eqAX-$M+K~H0JYAPtJs77hN33Y40hz8B(@uAZ(JFjDil}hGW6r!KSH^ z%wd@p=4czo4vxPOS+*~XifqBo&hdqj3A3wx-%+GRf#N$DJ&_4)tmhcH<~?Q?B$Fh< zM#f#A`|05qIiVd`tji_htom~?u+SaUE#(PmBlOt~7r18pS$p2pd&#E9z1F)S-m|Gb zu2(EZt066~0L^xi;W~8{lmWz9U83lu-)4nPTM$R{%q516u!M1j=QZ8pMJz_Fs?!-( z<}mF@Zl>XxmbPl&{qGO4Jqn#lH%The3X|_OGOR3u-+V0aWDZuY9J<{(^GH7_)5tB( z!*QzW)|7Le!ogFI>~zXbxa+%`wYV}AYPDRfh=~J*Nu68V=r&V3eXi1Yl$q&qlQTYp zl+aWq4{<&)ki%B5x(T|GpNsD_sv$-^Y%>lqqO?$D5G(eRd|BAnDmva;Wfct$lgQ0M z%i3#465@>u;Efn@m`4k<69MQi&6L;%BIfQ=-wwGe822n-2xIJU`Z zuI+VDGiAlrg~x{}p{Of9`oN5w+>WgZYL!6>U{H<$@vMF?zZ1s`O8I8;q!5AuGCVaH z43KnL5h}|=CBvcvuzHIlGrpF#lJ%3d8JLE9;%nBbI<-o%QPffUW*1^sOI>%0$X-33 zGET=ruCpt!tBLHE=%sTl7^A^H2XVQHx(B?qA+qF5>2xhG#?Aeqi^W3!N2!6iF(Yvr zSqk~ojF%Oyy-WR-On$%DpXczP zVExI!%)qq}F*ho7p6_CKBez+l%|-<;ozmJ?=8>HHHaX5daVFJv;nm246oVJfy;R-U z_j>4l#;!Ykj017rxFWZF?n<{t1;c5ZyQ@cdAZUjhD(MFW` z__mVdQNQSBmJ}<9_Ul)v`_fEmWH*X9&DT%BY!;nBb}@((JegTb9&Q=w1X8garHU~` z9N8Evcqm??*}-S3f5}?>DwS%j%GW?|B}8ejnficlnNtC}m){Cg$CQ56J=;F5s1MK3{#aZ*Cikk1n47Qe53u(hcJWjLNt$p8n{x!)IK?jdqe>ZWMHE1#X zF5PEvAz3)>zeJqK3SuSX8)7!~iu6VrbMA^XdVvOZ0!m5bJgCWGV`C{xOXtgWI}J(J zk+wnZBa!F*(+fm)G>5(gT+;cr8fzP{p(LJpU#FJNBLEFsujYJZ=)=WoVqaNOoWpPQ z#M=qiw`1BO1MK1h9Cto}t$5LH3iKnw?bfzbp7r_oRe7Y|e3$r6qrt^@A!2Gm$0rhW zEi%NNyr5uv{;-?J7Wc*0gDZ4@XgxK}OqnII%|xd+pe-Khm8Bf zXF7}dr{~z{OTcxyP5YbP`)t8E=*W)<9i}#&SD!VaKvSRnkV3G9R*NfG$F6*^wi%xT zp;_sz<%mo((4qM}O7TJm%dvk57{vZjA~`Iij^7Jc7Gm`QqP1BUMn9K{I7#A`5ZdaWGC` zi+zzbk_8-3?Cqf^2yh9dDUt`X+na{x$g4wWDJ6d51c7#Y@h?9 zUyCLdM!lDEi*SjfNnSn8Q6cXjKLgOQNdFwyQk*tJRzR@$zDSlLI20mb1tX;W2)Pjr z*~dzBMuX4Cnl!NDKnM13+1Ha6WfEqpc01wr)%FH7Jh=G_c&{kdFVu^ysx}4$#BbNm zQ+1knb8#xfe0&1g8gYSHeCo^stkwJ*GT7XH5RT6(64{Aqjk=_5@Y5I8EmBdlR-^Mx3~uh>eZCfabi6P!DJYgR+e$4)i@0xD>e$2BxOy#LnKp?NU?hnxqDAgYjid_?(TcYJ9w~W$0(n4 zzkB#+ZtOL8M$h56$jLL#-ml0;I~gg3__b3H>rT;sZ96vk&`nSgua~JGPv4hjq@qDc z6o1&LabwIa#N|!iZAaRAZ z!p#56?_Nz~mT*Fw$r-+VD^`IR#v3ae$F3r7s8WIUQ^l$lPtgZ0GD!p>GD#iuUhqxfzNDoaHu&xTVELV=TPfCAdh(6{IiPvYP zV4*S6I?(Y)v74jf=TG~Ctd@Na3i>LQCk6-a)g9pXI|=a;$p(PJ6W@XDw&5D6vm{($ zL7sa-@q7so`y*36{Nc0o{PE)UA{%42BuPh0h=8Q=HaK4XpK~4mC9synkvjACs}!CB zw&aE77M}!v8tgNgwQ-p3VHjPAmW0LzcWYo6<3odQdO*~;yo|f%iz4$qYuIa|Be_ZW z$kTT|BHDY;&wDZR8`oja`Cs?oen3knmH5=IKK1GH$5#_8A7KY&v0>Dw@Jmfa`fv8H zJYe(J_7~c+Gp?mOpu0LrZqF(nhPns8@wKBXbm+G>5`Wop!FUDXV!PLY(nVZe58K^+ zpv*AM^mNim$NBsu(O0S0@U$e&u?>X~FbZF#KCud-+nI~I&>9qOJpvNJE=fHHi9ehm zUTban83vUboAv^r!Fpjcm~AB$%6MrkSVzm|m;O_iqW=Arn*O@bpNIRO8>44PDjzi> z|3pU`woeVm2BVcjKkI1pp0v18)qvvyR>J9+2*7k$auL){T5S^mzGX-gY*QP=tJk6V~lg*c+G?-5$vSUC=;Vg+eWe%{1fA0y+` z=drfTLSKDt;exeE+c}Dw`|~Y7-`|xlS9C-{)d7Bf^dhw?9^?IcPp10CcK)4NW5p;J z_sCZW9C5aNn3^LdWn)WtIi-N)FdI|EDGZ(2H8TLSu@i@OHo*kFFZ52W9a-F;N&LGBdPGZM`(OC zCXmKr#?N+sPKjzjdjf&B?IU`F)gI6oEkdyldhy%Ch7vGQ5+MpNqW)P#!oOxSBvVJVSbq9&N;}epd_Nbh=of2VFTj%DQE&(84aW+ufjnHMWkkP)wM=9W zova<74Qj(zS+aq47T8bgE%?-Ue-ohk+A_BU`NSTvOh#Mm(YJ@MU%m6H)mVaprQ1?V zi3FD_KODY{`zqt8r|K`$fHnGo}xHo;OsAqrk*I!`BP^ED@kOTu$kblxBz<`&}%5`$eSgDV+wr| z4I(%K&+f=ZU1`)7p`pgxuot(!PQN7&H`BNYif-ksCJ*3ifb9DjXpVi}DZWrCP9$A~ znDJPb&7E}oth(4d>=omx>-7WVQ;4JRT$m;fz`q!BZ+5LnRmC1*ALVzCJRXmZlkA!t zGaUrJ_di*0ftHQqTG8u?pWUDjv9R4Iu4NOj#;s-JQBzp?D$c6+V4+!{wU7j7p-fU0 zbL|0co_@2={+jEV3S)5(ynJ#YP}1iAwLUBA^IFM2Mk9 zq*;In31k!%>BWJxQTni>5VoYueLQQO^}F|-x$8Ig+;i5wf6PC!jO>`~{XF0He9Gfz ziQc9cibnPVgV{ax4(XZiHB^ThP`Zp@bCtnLC$+_B4`WC3HJDQUH9+fVoNDh}e~Q$3 zEzdLe`jh2nhDqtf<)UK*QzB6D%Buoq%^eD`ia-b4i^gsS9hpt|P9%W$0U45z)Badp zZmkz`Tm2Ftq%Q+0BTS&+tbx}xatl27mHnPf8N;IKs_1m9eO&4WAGmCSd-CRJcVnn! z%|}ea5TTi}I2i{-+6W{tp!z)vn)Vhoi8pwMg8#lV3v<)o22QNQNsI_%ST7M1 zN*Fi^jNQc2>*Ft!$;o2vmd-wd&@{>xATn;3UlTUrG-H|DsF@bKM$)*ryTX2NZm5Cb zRiC7N(K+6yVm~>TA{G|%6>>ZE=6rvzlGxw(WudD1+TCmWbHW|)AuQ=1^f05 zRbaN0Jk2MtdS~LCo6Uz)^=hj{7h-FU-r0Xw?_!H_v-I8C`qaQr0mda)4jPpOIG1Sm zrd6cpYUbc`5O7Nqa$Oj3q(Nui zB+6UaLSI?aG-3{Nd)q$iK5zmc9-AQKT@V%FoDyo_A~yBak}RC?3Vg2Mg?Kh5tys4k zGx74Q<&`8h>ZYRiDxHD=YY}*W;Q}R7n-lKmTv_eGHGQ>=)08d=8C~nKcA0~{wtCzd z@e@@Z&A;EGnyaOBlt*JnpUJj4Nc0{HGx2_RUB3GAw5*n|z*K1t3>VLY_wNPh2$uZZbZ19y;qiiPKE^hxbLS)9f%Wt=_J==op zm2$fVYI;|)57$+mNK;X`mtgUMZq=xAH)y5eXv{P@_f7SAJT;BhPjSxGl{K(YlE`D2 zrImZ4WRhwQaqg55qW4lhe=NH+ln_Ed zgcB5OHsTpxMKypia~fv^A0WY>nI2GZHw6L0G$90?GbKN4waF~wht?6`w7sNwCRDr| zs=r4LAv^%QFY8$XPzHT~X|!L6h6XuB8BKe|sxXp{Y+*1C6Vs-&M`QH~im=m;n3~M+4(9d z=8U$E0_oeQPtm3=JW;Z$CcLl%qGJ!K zTXaPo&4`=K7J^V7!zxHE=OQK~_%}wy2IBX4711s9&+iV?C+aDQKdh}TG(rMz-sTs@ z5rfQG>Sp}LnW^0`huVU8Nt~3)!hE*ho*za~cjxiO9fPrcK73$81@m1tU=783KCs;& zCmicVTLfctw&-)?W9&|ZTB+Wkc<19br3B7lje~S0e}$7Vi!|ET`QpSficSIFZYYxb z^5EW4iLA;zn!SRZFtI4$L;=XxWZor7n7=@xU&WLp+C8)`<-j3|YD z2x(y}o&A_Yu6aDfH-(=0p0vDOsZ-rk;E@?S;~CA5n@*(*EYLr{f04PjzT!HMI-w*! zp4N>J$gM<)Njy5qkp!S{c@j*<;FHR7AJcoM`#V9rKe@e;~X8uhv8F$wWe zYAfNpHycId0p_Y963fQ_$r}CdWp_^hmA+iu@+KVMPoE{cuEh_44;S^vIu*i-A2#>8 zIeOehd@`O74n>|yLI9=eF`X99)CY0(&t7T&ZKPMk^}p)Ld<&Su66B%`sKbz{=(W10 zu=(&cFEDo5Bg_}Sey<8zx6R&!J)fCh4s#HKedc+8tn<2e9W>d&Qs3?iu-L5(oBaT~ z%_{O{0(DwWpL_@tTpS?^?zXWW79M853-lSZl4WNQf)P0{)cv)1apHTyG2!fX>61~O z1IyTz#0x%#)+;BSTn0y2lT$u4-Fu+(I~LKg51GeoG+ikjUEBl>vJO=MqmER_h0dH% zL3cZKdTC&WC}nlQQIW-{6H&q26us+lI3u+}foYDaYjLbhfZ4EsQnqR_U2MAAqmR zx0U^6{-{FuNNhta?~HU>|m$6z=j!>N5a1vDptS<*9VT?H}nF8C(K8$BDhVxTQlqzXurd z{IM>pY|Dpp0Kc+ir46cN#bwIJV1BA7#l{MY?lwarZM3{;f*Aa}9p6=mg?<84AK?!o zlJFR0{}V6_-U8?O!udSF8=}yNk`pt7IQ@}_ylij$a}MS@RVJeC2&-?SE%1iH?!v~q z`5j$dLp^+0=;mD9)#WkoQIYiO5+CDyhxy#^(z5yaQiBV|cf7lX-$u(nyHFs-4GDNM z9FW4`K$M99b}Grf9(TmkqatIiPSW2ZRbNBJU9?uA?tx>Qpu3^>YjFXE4w1Nhd8RJ%e)E_n!eTc&FWp9RWZ6X(_*&konGciE`L9aQuy0PP{Atrpq}M^Z1S8 z;l1?^KgV3AHD@QC!RbgyTzjUcpf^N2r<+XL;$HJ^`?cmv7FQ%>ycAp&4qR-CE~rR9 zgA0GvKU+y}$Ykh^sW#iRr}qS2AYZ_?S({%_{#8@w4)0$#`6c6TDHVXM07U-MI*~U)?_{OMJIs%M1}|3O`z0ARGH?SY51`6-5Pn{Q4bb$Zi8p;G zpwW!xteQNfSxmET7dl+kqRD_jb0d(gY(^Zn9K!~P#9Pe+t!!+6sOUTSHU^MfY&ze z#UJJwk!#?1&K|g?r%WDNN;O5uj|fV8ozLg};=jhkvoP*sRDp0MzR@RB(Ki1V{ z>euIdsk!Z(MSo^xz`L6r zaZug)Pz28@hN{N_?6u~QkxKPr>UcGod#8(O z-Tma`&VE{=w~2xS0R@iRBlD6KM+wrg$m>&wV0(eR&}Wp&q7YltGIjxA4Y7yXXqIbZ zhRtV9XFm{8gbqO*W*Qo5w2ETSqc_cH>UcnjLZnVzgd&!mYGJP~ zu~r*2Rn9@m%vi2~0Zwxt>>%8oSUau{vK5~ecyI;`whzc3nahg zF25BBmadJ|RV7v|co+O87v-rOaes_`S!nHR-?~=llEi+~Pd?_fHTRb%_w2Wx(_`tM znsy_(9Hc|_n_B{rQ64meo057}mDk<#754&KdZLYMvMJeJ=PHs*Bf6>*obkiX9ct;p zbajvWr`{@fIPRbmf>|(0A>|eM^uuZYLdCPU-(E65R>VPTG^2Bgjd_c*f=l>U9kQY# z@gbo)yjUsR1`!t>xGw6QP&fxz+U*OaZWmf0x`^9^22dR{vkJ0ltpA7w!;aGhFO!!K$ z(AaAnUw5&}9ZtOuE7o03U`U!cKtje(&qN0I_Swk##rs zA5qz;`5W3_oP>Kk!hU%(Me%;lUn^3|?Jm0n2c#b?Gfr@{oN- z^T7&yKVb)szz%Kpi$BH#%>B#_z5W<9JPl#^zM@ie6ey(*^OJc1u3!v*<)_1kS;Vp6 zZe}Afy-lKe5}U-&g5L=oa6vrAVoU(=WeU~)u#&e8&N>PAKY%ayvWwDV-x0d(yO7&E z5HtK2@z*0ekhAy=5Uxy9w4BG^Bg*2ycklWrYDY2KfvIr;V_#L!Lyh;F6ma zM|61QyaD(G_5s+SeoXg#Iw0zOL_B_pF=amw+_#2*Qkm~??#r4{)1?APxmaOlq^nDz zCZO6LkxWWwoU7sNvn$v(P^E=X_uT#nQnG5?Bv}abLaYTXYd@ z!WqCf032`vnH7zb1G7JC8}!HfT$kN_t&WX%u`BlTFN9!bZnUw>+vwORyd7~ zxlv5GX`_nGqid?dM|f8_XKdu)uRU8uR{z?v>-rJpUD-Dgr;g0Y#HhO55Gp;u+A&|L zDkWQ?9>Uv49q#|w3_0hsMY<=UoR*Ym`6s?1En>CCrZl@WhccI$E>;0-iGHFb}FCosz~i(>AAj{`ScvO+f6o;qHc5M>Dc+b9;v&% z&MX)?0N_tr?}2CPvn*_`xsM>i+SiA27ervL9!Kvq*|Q}mGgnWgK0v`qCiP)WU?`_S znNTxa>4jK1!8lZL){~ss#o3R1>wJs1$}+o&4sc05gpo$G>Zu5vE!Qyc6>^iweBK!G zN3g$-BU0Du0CvkdzOxV`FGesRCHB%n)&p#hhBUU#kGoaIsY}(lJhHHR6tzS+@h~eYdsT5uP@)8#QL%wZz#X zMxt}uq{7LQGn&%hof`@3LPj-rr*-;o8^l?&Pii8i=KQxo%QlGTqVsKV0!zcbvxU07 z86g256|h%wi4SKF`EP6kbLbe>M{9lBP8ILQ0~|W&a?vCl8AJ^PhYc7vpNRs(foIPFnM>) z>B?|~iC_F_h?y3(QmQxdyS|3&>W}>wDd)-(^?Ht5Up>e9dhfIEd--Wmr9-vC0h0qr zH%8F&j-ATKIhr~x#wG!ojB`Ac#3tA?02ryC*YvS8h{>S=2nj2 z4B41%uq4g1ObWVE&NyC^2!y?i)k1EY^d>(#aUIFCrHQ64bq2l^tnHf zxp%p7Z!RiXl2M+H9%_fpHe9b9BhKgo3mjT!+u zx?iuR~V_6W4NR_H$xT`TfGkq%Let zr7i<1A&{cN+(JJ4=Lq(Ht1ACLdIYdV_-|5yj=oD}K|SqRQ{X}RF9k14-i zY76dSo_aGo!U%jkN()l4+1zeg_~u~_Zu8lsPS4-S>POv@YK~qe>Fe&j+^XC%Ainyx z&5HA8ygn+UJheA0fOoGaGPm5~f^$jfwktsy-Tl*5P+ix`P^vAk4nP~RyHbWpMk`Mi_FTOnyf4www2guYc(i zTCNd>bipez?p~m%+g8AiTGJzdUxm2TKi28(1=l!2ts(_9xJz&}^N)1}@`QR{09Ua! zh!?ApK7oSMh8lmDKsV>2)+Bn-&^+kVPnA*Q@4Y+ihx*fPt`Mu}cQKdU#h~tFGYDe$ z(|`J^0ibi^W>aSn2H;jvNTQ?Hz}GiD7E6U*`zwM89Ek@$#ddK0mxp=q&y=l%em5B0 z$29Pnzn!*U`_zS5Hf9jm)p*Q`9Jono|J=BLZrp!i#l2@Xp@g>(nMl4a(5KX)p49&> z(TQ&cDK-bjRE86F;7#XMk1gZvDk{T}vO2dJrHYidi}LT(IMqc4JUf%D^6p!olYD?kx@{OQ!gvsGT82YyCnaWSDZ;^X6(Xm zzYP(NLQ5%)^&0f)XW3JQJMY9ut5~a>TpA-~NJeG+Do<@}Gi|m;y};fOq-WgX9C)z#r?JN8{Ege||A`{o0X#*BSM-r$v3+(WVPV z-A*Wxl3)9OWDbR|e=P^Nw&AaAbbeGvE|C6Mr}I((=AYvdur*Ys^4?f8GMh54Uf`~T~oe+k#ZT==Vp_(5_e=s$sAcz5iy*gi^`FgD0R zhz|RW&b9yhOCKa>CI9WYL?iz%HZ{xtvDQ2h0J>Waf23(@LBW{@N*>T?R;)%KO>@t{ zR6>pWP?L3n%d>&z@XgPkmQC;{qYR9GH=Iatx}WekIo0VZr@-~t)Whp&%UBAmU9?d5 zVD{R@v~rljpXqP%Q|;<=>|ajQ7fTbt8Rd_IP3`(lgLT}-!R1LamqyW(@}`C-4Na+P zK8FvVIp5mcnrXf(XV0%Rf`!S-K7fNM6BC~5}= zO~B~cohZ%@L$k+`jTjMv+Da80M*WA@bAJxz!SX4|X@>By7C#)II#>Ctpi2UsQl~3n z?Z9J@sD8%3BP`p9r$9n&rUFlsKi1iq;*MSmGxTnH~{3 zPZ&`_++j<=k(KjeAPbdIu(TK%Q!|Sh_ileXO5puK9mG#ke;Mi+k048nxueq{Ny`F& zEJ&{#LFNDQ1vpYY{P5Jqe?r+mspg;5`A;eEPigbND?K~zh(L7<+4!lB0$LwhSIDg+z&9TvC z5hFKA3k?m3j0{p}lTDxhb>@GeYyMjSLI0_a^FRGlA9R4<<>B%dK{*c2mnSC)bEW7P^`z?z#t^RK4yXGJ%DF5>oerdL4SeT(72 zoU?#p%!+kE_@9I-jz38q^t~{;Vb;u;X=`}r6z2ZbpI>G=1-Tg;BSxrJTO;P}TE{TUyb*wM<1gOY_~9J7t?tFA*VpMzG@0c&AW$%UtzVmhft7i$c&1fB&H zY=YazVnNm;ZGrybr$<9EhV{Eu}EGcWe{x z{}72oLDOuPo45ne>Z>V@r^uN#vlQI!it!ms#j(h7Qw7q>B?`TqvhhqgptSb}xZ79=??;~!bN>CIry zqRT35s0T2DO=87)?~%I4SmPeReRUsh#z=&CO%zrn#^}r%p-@q}#h*W4mAZPN;J5Q< zGbkaT)bs|cxf1Q*5mX;^yzr_Fwcq>Ze0=uLx&$RexeW(hWkN080- zxi*rOR0eV^2}nbA$l^a>*0))3!x!zl3NcC@N^{=Ub;CUwyc4iq_zYean?=LxK$PxH zyw4RZ#UU$gXw~P%OCBN(a~cv?MCs_YXt4Fpf3pbKR;9AM??w1Wuh(H7wEoI_AFA@F zyM_x78pM8#ChJ|T_waDzV<(KSy}%Y^r0z5>nd?1R=A^6A;b_rqK2&g`rRg_Ld1ewV zko-E_+4SkJUHOlz1N6ERH-TviSUfkc5c*4Sn*q5}%^48((d-dm;L^8tFz-4Owhd*n zeZ6RCHLyzT7UKHGxjj=_BZNTeM+p|P=gL4GjzAXoG7&((U-vA0-~qOg77dO#G3r(a zxRgw0Go=TBRmA;FX@mN6Hku2XCVPRtYfoy%U`T`Bs7nK zb%RAJj8{>@-AzjnWryfFAqtVjY&2VxV-u3`63{d)(T8@8xu7J7!w(gCbr=m;xe)3Y zJPH2!fetk$cB_5s^ZvGg2WNDXny=yl$ds(*Zzkh$H886|)hs=Bb0+)uHq;StuWNAL zBUILHrUE+RaNkDUL1<}_0I79OZ9*&I<^0F6^{ec{0xnw39{SpCqcGZ3x*uEP%uDQ} z5i_V#Ha}p2MA(h3aL37`Zy59|Yl?L>Q{n!|(R1q0u705R_jpw(zcJrtaNt?`7j1KP zaA~j*y?7_Gc6afmDa&N$xW|6ik8+xRb9U`|u&>peshdiAp<+t)q0*3`tD2X%hEWPD zn!9?Z-(B>N_r4$IK0y4H@bC8qjKKc1{S;n*=ZAs~Sw8rKf?~UA%Z_or}On5WGMfn+WC;CZbAh9G`X`Emdpl z{@mX=>!8>8%Utl2x9r-YMr;_)?B1wzb+W!|rJaekYkSCPtqG^`^I?CI{fo7i zIDW3Ee{9^I{HwQrm_z8r;+)BpI}?#P!(Y0x;-iB|zL>dIMaBGIrL$9ReeoYPnnWgV6Qw+b8Q$bVq7z9o=tUf z_H*_c5JaV>L^57ILKqL>&tbsE_{gMKyiyp znQ=sTZ(g_086mm~dvCejmR@|qMmEvj|HI>Vogy|Q)Ro3F)VzShzgc8u@u(Utb43}zMS{hxAL9vnvz$~B6!xhymB zj){2KOG#iRW`4lF6iZPP1d;fDOQU>fwVSyauYvO?@=1_=sw>;TN`{xfzc^%dmJJ9r zJD|l}Qf;`|>xhm6kWEvW%;3_>qCfwu!%)+@xWv;-TGZ#?4tHW&B!%)toFYcvxFkPV z;I(i|U@dfk`#|3P##36X;N@}|$VNsFBBx~v!HXnyM{UH~y1?I!IS_C>{}pVoM&P5; zI(CP)0NPC)QUQB+5=)}JsOz~O8d^EWZ@K0?kZjW~BHGFGJW5#QZrf*_WIPK_RHVnu znO7@k-X=MBsJ6IujdvL5cpDR&NcP(wK5w{t%u}f)R}))2NKQ>L^DjN_6_XPd2R$!y z$>%`Ldue5l4w#?lwdvjetlBLzR?oBeF?S*COJeWe%X0oc01g`=Y6AQc%2);eJ`gth zLFgbV>M(~vJfWtwq3Uo4pFrq^UcmMvBrW*QcVBb9QQyg})AtuW!CTJzqnvsZ!=##u zK3F-iBp&qzp*|}4EU5fidNt{luqwhen z`wwjCg9YV5$Ouv|^4fv6ay_@?g_5fk*f*!6^WP0WevZ=1nsC}tewBGIpo6lg{iyVz zxY4PocpyGLvjHOf%}}!hWNR8%g$gJRp_@6b##YKS=uifXT9-u{(3x}qaD55LhlQej z+VFC#b4{7sF_czjkLLExq|ZdW+B! z;@5Dalwq?@rL*tdx!TSqK|mkdqQBhkcB%J!xe7_=JF#s`o;%~CQ!G!Dy=!OtD_x_< z_1+haXnT!+I8$xzSWxW|O|px7axe9esoop$qPDF;x4(C*+qi3TkZbK8arfVeBa}=) z07ZQi@TsD7u@NX*4tB_6t7-g;@O>r5q6-JS$s&=PsPqaWXC?Uvc4JR>iEP;@;Sb_N zuvWz!S{WA{&GtdAhhsQ46b?bIm9F8%0Hj}4$)u%bee<@%(U)GFz<(3Oihso@5`r-k z;rt!2ER;q=BHA3PaEb6oHfB5iLoqc6RQs~bDOiqepN+#j0L0v;sjc}x@@#HIk+7>h zntCIq_u9_2No+;C_=($GGTI8S{UNzJHn2xi2Iabp-+VQM4jDR6~+~a1?!kn8e(S z4q|3%YKzL6T{4(WW?e2BK%OaXDTk;j)TqSb!7< zuUpdwHsi&xbu*fgJHV{P$wW5-Pa(Q(UETe~;_qHMXsso0{!5V$R=-GZ-7(RnbGjMaoz_yCq+68sG14Bf0~WPR1!+fX;Zbl_5f~ zrWb}m(2j;Hpg}e@XJt~KrbJc7>2r{(_%U=7GtDYdlIG{+GuRA>$mY+XyyRxY4%pc` zOkm5a%x$PVJ5xM8-(<|NI_O{ zf2njW2#cK=Y0SPIL(=mgI~MBXHFbFuQ_@KOXKED>rK+Wt?Hf+jtkrWbP`{vR-liSi zJI>kv1y_G6>WoLFE+Q(Wmdt^mx@3xX^8T>}nFyCo;@_$oJMoj~Cd%S&payqSbb}h~ zGR`;yYq2#jAc5rbT01+mc}qRaWU&?8TLq&}0@i^o9jUlbZ-Ux{mE%%C2N;)-SnG$y zpWHdSBn4kMu}EXU)X65Y2s6u!!Q0&04}dE7QQ zA4*~|yAe0NoijLn7hj+&-o_0wfsZmaBP>6=NnUCZwT9Ka?wAhy@I zY_+mha+7tFai*5L$Yj-cNgXZuR(+mZIFz0EsOV|s{pkUA?I!PfPiND{Q@v+uW(5}Xph<9quP6N9)v4eJg?MXkKNd$FmfHCHkdwkDSQAoP?!0iLLM zs?ln6A2}tn@}0fX?ceT}?S3mi_uRmW?D_^eQ~ZQ%*X-e4sdB3Foky23yF7iZNA`kz zP3w)at&(|_nHQ^5!ju;nn+iT;@B1Raj+|-hT~|F&<5)s=?RKp@>~_&<>`%?D{hyPk zKImD)FxkY`>4gA+0q(fy5iXRQHy+MU$0XYr!5D5H5{_s0Ewu7tSS5Tyquo7DZ+O%M z;HMtX18idgL&X%8?ymt~O^oMKHis>mw&YZyl1(E~u269HMbr7s1JDY~3vmaRbXkkP#sndMzk6Dzz8Nrs0xs;{&Ir%*K2*7XrXrOh)fXbB+qjZ%g^=UE!lUC1b))A>T2^eM!u&>GPnT_fj6L{d6 zl(WZyd-yoF-QDb&cf&O<8qS4!jYU7G-Ffm}IppJx{F~(LSEq@FzJBIFMdxoOi_6{d zI^+sQ;-i=2y^m+f@l~$@hpM2h@TtFdMlI9h1M2>2Ce=n0^3 zi6zDFLD?d-1|fv#HDm+GO*>5PQwWkZTrHhrM##D!0( zbs1+0UOQ)zso1994pxze(ivLAA@d(MMY?z)}yBzrouPMJOPKA1`UTgiljX(ZB7 z@Lt_Txhi;&E>;y)qXV=2B-j)NG3$?Y>)X5n>OnbpsN+zGWd{h1HwdzEgfxG%7tqS5 zG@(L%H~&;faYs!#<{jHF(6uR?Klr(+eOP!fIA%K3N$0sB1V1Xa;t>|fY|3?JqvXPP z4J^U8gY&9|yMQ<}GK<zwsy_8R^c&)#`3 zqHL8D^5XeWY}Ut&(G$&B?RuQuo|J7eCn7?t8%Vc2ILDm#M}K}@?xI&}fU5ywGKI(; zUrV0K2U%7V77vt=drEwZj_D~^-=$W^I3LW7RL_hY^8YoC<*12SkwiCKpuDpE(y$Vn|XaVtsGb`V|ksLD7fG; zev+vybP^m3e~SNL35F}ktfl-@@|>!x9x zMfIBUg2{fsvLL@dP@+}JHFmt4qUzpW8quO0;U8!bQ1iY}+seqz?{mj{_lMP|$~`m5 zs=VJUo(z_uHuLU;TMQQN%+*J{)+^A;z_zNItD1m(JoB7;VE74E+KE`oIWXp-eA3;1 z_HWL3@WC+fvGwD^43Dv;Mn~LG+M=*tBmaS8a z*a{uNm)?f2_+ioi(h_Evm4+HaZ&Z?e8LQxT%tUE5T(EApmB9U{({gSO;l{ z_q4tWCnT3y!NFYACYFD=p(ud$bl);4YAal z;@v|_R+6L%0?i%!B1+RwcpgpwNrqmg&8z%eRPGP^l4=ii<`mWYTOUk{LA9Zs)SIDLv;yKJs6Ch<^J<4w&JTSX9kfnl{|( zvO7hq;p)F=yE~kmE4MYH%uMBG;n}q81~}VPl^O^dg@2pk|9RpuedQrKJiXZk-e>*< zq=1Lwu^cvY>?0ef0(e2Ae$Qb)Fr(OO3=#)L>vA z4sqPJ6E6qT%KIQm_QldVc<>Y$ND;#FlFgL-)nGp$3ae>A9ch#05+ty;r$8(iJvrEn zPVwKtyHHSWQ&+`Scb2UUwtn2Ualb-?Y>h+LSi}{%^sk#T-9E(@s2fS79L&CWV3_Q9 z24}d1qpf6TI(G_p_ny-xRp&S$grk*>Jv&%kqU*LblfAHQZ^B^qw2xX2C%Z!CMvAg$ zp-x@s;LSJ%a}Sa2-%8T&zc4QDgQ%)4kt=hM&lQ!RFJvLc`}n>iv6Lj_X233= z0JXf7)jl4P-wqG6Yog>$f$SSPb(Uw_d98?!O2e$fS&(3tSH!3R)5-9zLO{zA5_pFg zv}Jv`t}=72%E3!2 zgKk&q&3o|Btz@4E-LcZ8y1$d#FhDoL+uNgFLl)gw?+TJ0HuF|bFRJSlU2kX41*|#^ zVOypg?2V~H|E-J!F%}I41lWrYzV*#Vu;2(x=1Fo6QQ37dVksu%Jnc8jV2we{lYPp~fJIw0ckT)GMJp(Ea#Z&bsDqs}dP_Ry!wstRu2&X6)hf4!+b z@&oWk;EJW?(4ZFrZSWceNDJUpIpnE{i$ zbg`zW&<0qAn)60-*kqjPL#$XH%1dk0MrEDj8Ijm1**Q(5s+E$;sn`aUM5~@1?JDP^ zpIJN}h>2}5H&`-xU3tX3ySn*y@4nB<#j#gE6`hMwZ|SfOm<_yCpg*<86dId7r#IB> zk=DyQb+PGu^{KbU291Yvf>hp{?mmj1kbC7y_sHJM;f<+ZK+0Ga%nVg*L;m}46D*Fu zIGh5J&7Q%8_XaPV;30xaKBY_%`n_DB zC+-5QWyw6THtrbjP9A%-9r7eXfi&=pvY6rVs)pj$81l>@E#^R}W^IZ7A z)40&U7z4iu9iP-wnHQUVV=A0v?aT?`dS`I{lJmE^IQq3#?giM99EE+o6Q}6sLx$W$ zlP7Etl1?gllz44DlS{rUmxil3T6QHob6-aqxY}giosaqV8|&sG+}SIZ8hQ)FE-A0< zLSFA>yeba;*`V@FxqgAcBl50n@-8SG`U>FCH#308==V_!zZQ0T9LC&;*TmUEOE>UV z_<=HYcvNs|4hgv_wSWPSiIvc9IxDVObNAFX>er2yNT;;k< zgdc@J3GDC_NHwu4C^=q0qFeJwyZyQ>3K5mX~EgY0pt%A{0Ya1657rX*iH$2#j3<1WrN&xE*-WYxRs0pi_MxZI8p@30%TQ0o@yQvl%_U%CTQS z^8&jyB_Xdg&}~O`P07N#lo<@dW_Ot8A@~UEovl|Ejk={N2XPwud~a192{b?15FUgD zr9MU!tY^09C$PnBg5Ebr6bCPwLQeb&QBKEJY*=D^XI(Aq^opPv@laF%PHhOVu2)y0 zoSR=53haZ+qQ_RqDs118fwd z&ACjY>uKiWN%J>mpW<{#Ii$s(t65Km4}7U`buKs?)ZaDwb{~h?6qceH(UD0XD)(#) zcP%(}q{k!RwEeQgU!V^D4Emue2=zgosVI6RJk45y^`bINl*MK^i9stfLDW2TOPdN8 zk;9a(MMq{uZNLIkFU$fDig6HScgP71MA?Lk`h8hqIe5GtcV&cP1;nvrfif+~GSnOX z8qY`LY9@m{Yz_~b<{WgKrd}XU6p5t)%s|FWfWXFciWU)E!e%%av|CT7Q#-c6g@imb zbUY8NU>YIKlC&sW6VBXbx}`%EyF>@_aUm3GSPAGG7d|hCqZqcwMWo;35|A5fuMx5g z3GA&yk9avLwOco-VkgGq_V$!$-3!28X_tOCP-=!re-^GnKZD!JcP$~MSL#_@@g;W| z)f;uh-yZIAt=TrcJNF{*_m&OHubtz?31PeU-R=ys^I89BgT__ezjd2Cfbgfl6+hgu3#`*5{5V>s?Vvy#msmJ>9NsOk zAg&AfW1Sk_0^et|176Q6y)0wTFS})x!0}m1C90uAkQy+GhSa?OQ-5rZt~VS6ZRJGK zy2yZ*fXGl>UJg=1ya`KXw}6eX=?FBv&|5qA0e~XmW!+s*qs=%n+AZ2yw-4Wdf8V7U>B^eeJFR>&`$JGBNJ`Sn| zePLVCubKm-ui(Uf1K~4H_AhJcKh4513H|mzpl_pL=|9$?v{xmY$U*@8eMS66-1s*R zA*Pm3zefC)C*DBqeVy33s7J5@^^C4KxbsgV;=ep@Ty2-XZ2L{?k9F56U%p^2CH(XC z|9SfVEdKvr?)@UMR4E%FgR=n1aWM%ReKlcCO0|+;AwFhtM$>={r-p&U_7t}DI#`me z_%zmULuV;_V3}4kw^mQ$>mSQyF0K`=-J`63q~P{kej zV;w2{g~;nKUR)>I1xEt8QKe*Hry&&t$TXe!gPN*;Blv2B+jazx-Px<;dSY6 zfb8%TkR8s5D#7nE#X#+2?gdXHas6LeWIWi8;=6%g_7mMFEZh)+lbzwK>?-w| zZZ|vhRQeh^4OV~5(N##hlL+9Raq_j#)q}s90%`HVMh^w7SLNX;*-}g87m8%(Hy(RN z^o#pz9HtaMuhvt+O$ny%2xmekQEC7JA|*D)?Gil{MnW}Q$;D#;r}souYNL;T4+PVC zm=grY(Pd1o(u7x*Fc?bec_FzVV4*T>4uG*JD1yb-FGuQ{Cha*FZ#{su82(DbO^I$@ z9fzpY0ioXm*p>JSolIz1?WBxn0bjTZD-B4$vxwQ8w-_hzg75Ro1_?okEc`BLa;5=B zYxmJ8seI%n+%bRwfjKmGJEaG;LkuzlpsXrnTUu85m5n&5|RRhAXCZ#C=rN=h>Q^-pa_X1 zKuS@Wi9kU}QpzklDq%~8>eq9-d-eIg`qnz<-g8f{UhN;Ogiir6&aRo(ly-sY(~$mj`H< zxi%Q{cg8*>S?^&g%D)Ha^6t4_(JHy3mqZ6R_&?&z>r@ha;ngI`p@6sY7t{vJISt9) zX=c6A)fSJ$Dk%=ipWiis(Z!qcDRbG9AK?dRC46@W0|A{Psn!rJ2v~jl0s8|21X;e5 z4k52bw*-~`wZeIDbFUfHwd%HpVYc8>T13rz<*m0uH9DSk*l$>I^yu9i`|h2!KbKR< zp5TH`8BOeVotqRG&Ce;% zu?|6=6#Z6B2&^2)e^ixKn#>+(J2CynDsPk7gGcK+-Pms!TT5TneQ5-He`lR8mG>0` zHH+6=X$?7A%1POL*O;oqiXK|tc?LSc78x{3qvcFa_0G>bWR8mY{EFVP&E_)%F#J~^ z1hj+%;E10zK~l#f_}F&JCj7a6xgr=^tAB>$;{=Gcz{*>`t=F9K1L0r~L-p{4<*LBQ zkv;hdA&4wOv_*bJ2OpvG;(Rmr+NplpO^3QxoO2Sg3ke;M1}>o2`I^XEu89e{0N6!s zg=^n;xi&fDF1H*JcBk7dT$5f9$WHz&^k#?iF^wY<)H-&3?ZC ztz=KI2u))VBx(A`g`PP!gv~GZZl1b}8!5B8<&R-CL0?Tv8 zuE%hg0P_|tc7jM`;?^-ZG@ubOWD0nyQh!;=qUCx#_J}BU$e1tlY4=wvs+r<04_ym= zh^dIU_lGr2=mK)Y3 zlDSjR94keK&oN5-%~%w*-ooboKsz|B_rlb;k<71T-UCL}``n!P#YY&=S=jUf>{69L zYOAn38>KDpW&8jijROGCvS@+Dgk4dJ@|R2imKojml^z;EpCPTm*K$}ReeyRQd1bqr=>8I`t4Wp%`pN)T1kXer1}U?>It`s!of3yB|0r99^%IVtZ5Sg2Lh${ z&{g8Kb~~1j&Z111O?_v*Rjr&ex?Sk>2D07xhjsgi2VQQh+ZS86xaH^(Zi(0XLUiGI zv5ESfJl*?VW)^YjH1fl{3+bhfBktmJ=M%hQzY;>Y4HbvAp4bwso(RVse%QL!|=rFquPLeU`WjU;6w!-jk>5=E#~4a1>eGv2OGy zTxtFz^Kzm@?2{>1B=Heh1)GRnq(>+^AS?TcG;(SH@R#1~C|%zzE|J~(p{dWPAiN~;YEz0z7uDii&XV~_|j$z$WT>9^6UAey;SIw+$@c!**N5#b_ZI!zRsRZLupD8@F+6P-dnEJ-x7qPR?X;I6o^ND;tpj# zJXFwdX^GiWq>;MW?(Spa5!cceBAud0tZ&(TsomZWx}5WA2nFq@9en7i#o_ce{>SPA ziVmqNu0fk|r6%yJm>T-A!xd&7j4N)h&c9Vs&(SX}>k3dTJW)S)8g()990R@Y^-enO z^pk?7s%s$0MDN96W%3326;kAalKd6J60BAyh-0L+q={l?U3@$3>d1pKK6))a#S6wx zpn)uIev4$=4065AGy%s?&H2P)D2k%zhM}}c!BU3VXDlMHMyjvaZy!LL)(tAVF|%`c zT(p7wr7d&{yux0r`2iyWbl_<(bc`FE;f1SQ0vKg=f*!;ZY z0AVkj82xbXiAFn5xe>)jBC-ufJkrQ&u~5z&>6e}&c17wuX){(SfG{BFfeGn^t3O|rloHo+H7(p zP(Bprv#=3@{ZVgX&fh3T&aTfA2HYsCaL}lD7$VDza1-O!Yk0Ym(dPS1j*e67YpxX( zZqcEIXX1^$-S5A19`TN0y>WV6<7!)5IPKDZuIaAN$Mq5`Qkxmk8a5ScK(_POCHr9n z2d#*ns9>%nMPNqqg|=5eQ!RHWdvr|**M2*YuP_53+O^Nu!jsh9p`~lFQ2{>=ogInV@6#XM zAj!;(Ao8j!`G1sSv<|gEPqUTcjQP8EmO0S|4eM^74mrGjE!U$oo#fXA5>v0XhrCN` z=O;c;-%zK0?6i^E@|JX`{6Ul6G=o(ho5&r4hputPvWvHN&&`_BlJAu67$|kEMeeI` zFSbPZYq#v#n!DLS6Hjna@)AnF5J*s34fwtrWu?rCTfiD`ku=;Tz6yo6(XNr|F@ST~ zhC~uv|FFqT)GTLqj)a5Q-=CRR8m;0n> z0(!vyaLHK2a&C7r!5kDFg9yP8?Kx(|K%4=aiX1VryVjuMsUTICOpvZM+yMX)TrR== z3>!-{hG&cQMcmGSXQa95Z4GdcNL|RyLhY3X_O{^Nd2D|QdqD#>@Oi@cd1Nbf;D|=Q zhHIX!>a`LVx6;&CA6xoz5XEs@FzauMI)bg9C)f>cH-S9)*{>hlWe?;Jo!7~#6eKnp zsgeu#RW|27ZvGM$nN!~MJbd4&y4_h`j#s;PM?Uqo+g+-$*{Z_5b@LsYI0L7`lI#~d zd)YFqDpuX090bQN2~-p0iev;c^jRan$Ir5s8!44|pHA-5 zGB&dTsYHmD{78JkY^a%(ZrCqZ`XoebAZUpGKsR9K=S4UHVt&(74D?hog4W_9(xHq?lYnX)23=~EN6r^c-ypHjwdOJnhTxfQ2WAS&mNs+Q= zM59QsbL9C*% z$3$8bbOi4zZ;cc!(8K-=<=v_Dg^ivUuXrkA<`9kwB=cMNP-=IY8R1A}1oN3@-ivTt zRK)sAIYZ-{&Ws#Vetb~3J@sW}#l=cx4X^Jfl@v5iGPa4(QuUUom*pQaE~eeR^`mKEamE z&d}{9gJ*n74zHd(UgDIqX?2=7H!&|D&G(pw(OTEu$_lg7CUl>@M+Kr?ZSOuunjBBl z^xU}@8-6Gie-bBT`~<$(O%R*&gRF#kmIrTZy$&^X&H^t@)CRa)f|(&{w8TTs9Xwrz zW+YbibE~5`NR&-UT{Mpu`aGwu$6Iz%mFEbD1s(l_eYgazY=W&qh7p6b_O(SBu4-)B zwzyQ3FIIzhL1b~1tf>V9c|50XY`HArfukQq6v~g68lpE4cM*H2^zcsJ`l-C}RiYYB zDu^<7?nEO|TM0pMW(dEFxe@2i^OGKcE>(rxn?)HuYZ}h^AUJhZU4W?SE%RqnM1 z90=ECyhr!>`gFWC6Hu=bng~87czQ2t_>AmyE{E@3ccoB zMe|n-EP6p__4UQPQOh>ucf{?aw&SGJR0@)AG=~Gq?kw4@1ptH>^441inYSDP+xdCf zT{KQli-p#<_YigSn=+)^@8g^J;c1}yoiV-*4io9vt40YrZ}2*U*Fod0d`X0ji^ZZt570#qGD-Y^A&F53dRQ{ykSkJlryis~>5B`Xs1+r6^;!@03kP_Zrk1`}f32Vb zOs6}U)G%Hralm`9m~<^RZ}XJ?cc4iy(k&wLT!~~K%{50HkiJfqmTpA)`NNlxDeGgraa|g_4G)wn&au#Ym@9IU16p8NVKKRmVJWU-0H zH1}#$ddZ=fQtVEaTSfd_$sNJ@-xN>h8aou${T8TauMuWvWAYTZOkUzC0F^%_3AIKB zppY}&N!S%~a~IJfX`+e;xkr=`sJ&o*06>| z0e_hP;n`h+DNGUG>DHejt!Avjce9DxFysP-q!vp7W+TBSlQnTsg;8{rQ?P*zy+8E$Z1e6C9ghrW_4GGZ zksoeV4A3&(T(F)Q%(c_@aX#j9B$G4HIhdIh`CdmJYPYeh>x%RUHPoslw#d)nTuiFn zTeBvW8He-03OT|xcgH}xK-PpNS(Mkp-r{JbNaedYI}Z87HfX#?fK;9FF}^o*C9QD2 zbjEJ-s%349Rn;FBcj9bX-<0#8buA!f+|$GRK3Fu|d2ku*eeNKCk#CfxqfaB!kxkvt zk)r|P*Y!kZCD2cKCE7kNG7CLUZnb=O!0D`)|Rs_p3NvDev1mPLHAlOC3nQ*AD z!MhNS3h$)V17ovbo^&6yrYMH*qU_XbCg^EFo1y#TVw%w@((U~DfDV6o5dHdS zVt`(J=kgHcUPSZh8lid2v7T6(azt}?2Hn)u*V6uQ<+NP8rva_zJ7d?v&A(KjmR%OH z&PAVE?jOLuAF}pjT`pg{8UL!*?`#E^GPGTrz4vAP+5P2))2z(wW6$oax3lIiHa9>X zG}q`=$$1+d4xKNZoB8B)oH%srAu~k#Wcg}xMX($FsEf=UUu~my`6WKm_Ycqs4KO;{ zX+~dSz~DJaIQn%6;SccydCvrZiawOd|7(TbG!vY{=7FWVEkpy;-b5W$uR7LJ7d|fU zEjGWykH2Pvy;{JTCl)KfU136*YD0}bX(OK7CbuSKU3*wW>afets*SsIN78+ts6ki* z3nlLI9&lFkV*b)CV6GH z_9H;Opr*=qLtmVMRgq>CAw-Bt_XjY|qIt}7eRaTfshYhLopGFWxWOyLVDka{?RM7$ z#(aD*S@mVM1EVH$x%HeHO@(NYk~MhQr-HS!;$o94tnf#hPpIjL7t2-+0Rl1it zS=_HYc}7q_@~GpfclJ@f6`_1(-tp%?w{T`huIx1q`%UEtCgR%p&cljnEQy(o-Ns41 zU_-Q5=ZR8>bu6L5tv8+n5p4Dp#>Jt07Wkl_U}6O z2@CJw%w3b{;&I~lVA({AyF^W$Xx;K85blN@2^A+ZWn~tN`<W-N7CZWCu@3ADnvAN4U+C}$L0WpaWokQib0D0u{ODe~ z<6CamEFb&m^4XZnA&GAX@{n2u?{2?F)P@)i5Gw+di{8(sSG>&dGNQ0N3TF~eM{iOI z^>^J1bAyLZBTUn_qE$>ocK>nO&0_}tFriE5@cR5PjA@1Q`fdm7UAy0v&KWy`V)vc- zP#{Vot|bECvdJ=ZMoO7idJBTUF0O~!6w*uV+Em>@-jY%4%>ewTuby5wGv{9M3L zodOIHe~F98hk`O1#;doXl%S=|2I_Zshch2gRychNs59xolY06uUz+B55J#w)2aJ(6 z!K=&RZXvIol!<=CY2*C@J{B>zzz5i(WjlI<96@ALRUQo5VDt$;!nT!grXZS)LEu*j zc%4Dfz9JH<6~X7WyNNa|2*>L}LT!IhXJ3~piUOOdiyDFATs~6ijDPnvspCC-D0>8* zPKdhvU`F4H+fbwB(!WU6!cL92)TZ3W;;EhujcJnLmcEAlo6NObo(_gTE8rZhr}x(c zo9@S#{G5soP0zhzvVLiIppD5z$^jFf0Ct{7)(Fv{d%YM zj0dZQhRl%nvjcH2Shq}?bM?^k{x;kYcT1tE$N_qPCIDTPdhob`NsWaV)?%z^62nT3X&ki(`O z%gkiph)gcFgqkuLCNNU`n=EsYIJcynL4D18J-5c>h+a=_nV%54;uSv^EUfq za1-%t8UmjJcBRgkkt#mOjSiJ~%HNXcK7eQ~b(cM$@=2+dpBJ(iwh(pBOF{q{Vmz>@ zr8AUZ8xj=CVpuk4sujGa0ea;CQFj<_{^Z5A`HdcA>nl?I(D>Jiev2gV?(y!}b=`cD z3O<1ygKuiLC0d9AN7iIMnED9c>4+C!(oI~tCOvFe6m@o)n;w1Ey2he&!G9q8O<7F% zgSP=L7op+N`-BfvD3g!69zGGY-w6(ZJ{{|qYvFV$=|r8k({d$fESCzj&XLRE>DDd* zfsi@9@%Bd4`XL*aO&!H1eKvX+_H_C9_%u*(tOf`Dky*Pe9~;+#Y%@mTJ8uuxJ3oh@ z;N}{)lO`={t5&9Udiny{0o^`~fE?NmN;PU_AklQnn3c?$bS-^Qf2QN`uyFc>|=2R#^M&#Fx}6xyL^$;X5wBF#46nGnj3zlzMZs>iLl=f-4uTh=IjnUM*za! zwZuYbDO(yZGLS1yL!C=3Y(xC~9RVhZx{9zpM5K$zLfJwb@S@4c$LFrchfj1XOO2t8 zcB*M90=)pfPb%S{5V6shmSs2uqzVYF8RB*-c0gX-hn@ht5^caMBnd#K$ZFz?X6}5E z2&Tx@TUO!a|=uLIl8F8_{X{ zdZO|S#{L;^|8pr&K0mKUpDHvbu}RIJy*;PB)3lVY#&PReCq5Nw?C2}i-Ff^KoT<@{ zkIYz?|1@Bgd&9*F&oYx3+AZ%_6+L+hJ3B*SHaGbXJ{;=w>1bB%QqO!*=T&OAxb6L8 zh8_!AB%tm7#36FhkP_$NVOhY=vZM=f=kfk;k41mFCb1#*pdnY@MuG#>G@mH}lKM8_ z%XA8xfo`--y$d{)6bZ&4$J&-neZ0iBe47vi3I}dIEeR9dDZIx<^U4COvNRNq7wwBP z4WOywyMA)*icD3-L2a7k8B+Y&EAPGk=~Hm~((cNVMnos)*% z>xhb}#>cp}wmeeAw%+o7v+ma8&wM33;n|)SR{nb<*JnIl0MLH*JxDo5K-j8vny4#d9vBkuVC3D{! zx!3LqFZ!@T@^Y!x1X*(u75-FoHRei>3Rt zQ8v$7f!7#7!eL=!Ofq9FeiD>RAP(lHD=ZT(fMszg7l81?R}!~>j=DJM1*P5OcTLAR z>nQ{c#W}Bx=QpL=QL?BTNnywgW&_yfGIoN5uv}<6b1u6Ic=dwju~ds>(h)4$NU?;E zWaAPs0MGwA&uC$Ws$&r&|CXJ#3RDptkBSUS_%ih%tQz5HFMZ?9zUoTiG;H~E2nhoz%jpGk@90nmsd+lBL2{ng?1c|HK zSFy*piq<6C6dBLkAm@VO{rcqnVm()};`{YCN^XYCG{=SBdRe$&a`Bew5FtE6&~oIc zdxdwYXKV3pyvm*pHYY1w3wI&bO<&|2f2e9ZY2_sH3R#@fOh_rw_RNY52`xN-+JluZ z?kQ8d(o+R0=Kbx>J`I(9*@!b^SE$|La~McV>?W&;L%^m~7WFDtdl8)l8Ut*Z4vP~9 zQ5)qw@=bt}iIp6Og}|<-#ZqEOP#lulhW9R}w;z(dqgK5wD{rK&%Y{k;7W!1ukz=ER(JG zFJvq;+mIus9<2j$GUQK`j(pU{zBuKDj1ixlTIqq1M8UHK)oGM@+9vCPtvDo|SO@dO z=Viqx!!ykF0KP>|Shi8p_4VMkN_;{f+;kV_@#B-EKKG<XTDq~>h*&WGvQOtU ze!j%Bld&Ps%Az9-U+yvUr23}i%eu{UJ^v>ezXcZLIr}$P?Ctlp4N&&b(XD5*ye?$q zcx?`-*vwSiY~!fqo@2B!tE6lGk?%u+F=x2abD|>jykC(;oQ{hyiqiFn{?t^m*R8^1 z6INxaOE0rLT{;dm%~?rs_?ynMOu{~qL|iS)Tcms^e}O{7Xb}p%mY@%4*k&+D&fLyL zsl&>?K;y#az%(IdG(oT?C$^%5OWOvHViOOj@s&q$QSoZ2cg;Rd*PSQT2?&-qFtB;p zQYTI8-~>7aOu(zPU@}R_)Ekq!41qn>GBUMgzhtKzl<%+4_)|JC2>4E0lYC=uLsz!R zM^1Zl7RtD<#(>^5Xq_Dy6KYr*VKhtbzyhdL5w#z0>IUOLX(E~p1VUj71ySQAq;kA6ADz^)3z}`q(;A`okI&>c25UjY{L-mQO;>W~ zZUoI}t@GvByc?igIRDY<)nxsMXR*)v|jA~3-2dhqnCwY zP8;w!hV3VZwzxl-?jAYVUxf^v`)fr(^jn4J`YU1DeK`wVPh(lC`A$<2U=;R(%`9~^ z9*`(ttMiNvP<}FM4N%ZGNy3QTz^7{AD)1wa%;|dP@w7j8U(0U>^W}b;Qlyw0{+zUi zo*mEbR?EIO-PhEIRY3~1=BQr-x!W*{(*t9Jj=;>Kr==(74S%7nvxEt|`KgfE2gF#dIW1+UWW!RuHPGeh@_G`t@uo0pKEcis=fsB7uI zEnH({Ugd8>xum82@V)Y;;8gpc3^JDo?M#sn62d+ z%b8Imu7`O3BvJ)9yw zE{dMN0Cw`-9Q3MLrq&`Qi=-ysC5?Y7%K`;_nbxsEd#wt5mutV=aCTfD&V;&yp@nqd zYcOWn!Pwm(3QvpM2GOeJ9pkHIrKp_*LvZ(yqY!oC+|y7#Z8!n&t7xJsH+V^e=pZRp zqt?zA&@u`8C6NSuh>{#Trobkt(-(l}T>x32)!wbrl>TQcY;+HQ8lgIj2U~$-qA=Mz z#_g~Q5dA`b1@CVQRt0tyqsX-cG?br4P~{)6a5)rY#geN53`GTwcg^=6pxG382k5CE zX?WZpwQXQA8#Jxgfd2T%o|XX`&9e4bzK@lYJPmb^b8>q?o-f{6r}(5SSE-(C^5(+g zr|k|!zN6}g_HK4Hxeu~*g0G&K4*3$%mKbqTDzy(ge5b&THorTNxvg^c@a=(;q~9L} z?su=|+HRW>Ui@QY$hBNwFKPoV_;`gjM?nQCst1KGuvn5&Dx@|?0w6oBz=L|V)-{wi z5oB>Fo6AvB5{wI%=tXETet;0{=wY7N5GW@tV4<-5D)Stgf(DRa7)b;6==f`ex;04` zu6#qv(nM}*U|y9Qz*WNR=wr~D5PQLt$a`x#!A-J{mK-E(6D=h%Pj!#vI|AdK zaxwX-?5wC&&K!`KP2`uM|_^szi%6LbCdC?^M09JfJRw|8|Xg!BekGMHY z-Ar7IE8Z(BvMF-<(B%XTQrh>v>#O~Mew-LD_LtqZcN5H83KT$2IXX#ytLQyhq(TVn zB}COqx4@(-{Ij3oT5FOjK9=CxCp}8y&t`{X;52*m1XJNmXlGu29sZ^S$s+3ZqZ=3< zB@yTSKl3zE3P2t9sbpGT8-53+@Z&p4s%P}K^%KHM@CgDA8_bE)BR!unT2s(?z_h+e zpEXr$+O8w*j=;r)=Qi*|e_Ypoe4Mj(G;M2R^EHcdpRUy!S8Hx^-L883IHnDp_uS%| z^IZ;ld)MAj1a?mwf7+wWDQot0;6CR~&gQ8mzN9ewL`8wdv6)taf-90&j(VbM}ZkFjmhnY_)lq=|cAR2I`DHUMw%4l-?Hn8rF?B-j|8 zNx~sC2}UqqScDLhxpEskNi2~u%!x|G-;oXC62Ugn_Jv=F=8;5ISxJkn>?Xu(YtAJn z(}?TjqiBu!xTxSIjvX?iR&GOZf)f(sp&YKiy!=e{`OgOAo0Ydr1Vv6h?Ox>z%{!M{ z-p{*w{;@0Wg0KA=tJ#fZu4zd1TkkHmop|)9I1z)2!zBctdEsgut|))6vF#S_;y{V> z&D*Y)szAT7J}K7p5dEwJa_6gJORe-O8O3A!iyrfaS##wh^}P!gae9XRNBe6US`U2+ z7$7)bPAoqduHx;JA8atVKtB+GefqS~x11Uq_cn}_$B!)^Dy ziF)aJ@z$Nfr|0mxW zN&zAnjrba6hF-2>tmSI%htC7=IQdBTVGB9<(^;N;O#QP-#tzy}@pu3AhTN0jK++|5 z2^9kxPCW_k0z~uK_PEdgqKSXm%N)kYUE;-2K+vTCfu80yNyhO^pM$jp{l$hi+$8@U z*|s3_Db}MAXo+WAwf-cq$CjC|z#usJZ#43+RPz5X|NQ+BlsGZWWdN`I(^7&b4a*6B zfbbp!IXtQ3vB{v|BObb<6aRI%27}+Hs3o3mM=p~eZFD=bLgR~@korZhCFHLap_p{^ z=lOVS<>EhG`w@Bn-$$D*w*TW$?OFM?qXw^(_m1hp03F=C4!`vmv=QJ_phr1kJz#~@J-pyFNIKg+ z?0js{x*Oovil1f9E`a1oxw^+^IT6$;8q#^(WkPU&3XL<%O99^J#`L%Me zAWIDh`#|34$OqqPQ_Is0@=qT>F3R&5F^f7ljR=1I6z=$U7qPxTd;b6i4gS;D5{i61 z1C(XnMIrzB^SNbU>~rM+0qo)~`%{POK+zdYv(J6LP>o3J=cE(7|O*Q_yMLLPmT1kk)a?fLFo|o zkj3u+TzT1_4MLnm{^KOJe`4(jT5-yFHFsFP?#$x=*#nJ7>%0H_`Pi>tD#tx;yrAct z`S+Vo56K?%C*Vp2XctysHvYQ}^#9tf8r5p~Ma%@6u3%>0fc!N@D$56+1h2mAm+P;R ztO2L}Ir;BA_y!vM`lY_~?=I4+|Lzq~U{9Vhda8hc2K!)8e3jOe&H_|`iu>xZ@NQOS zj+uM=*NX0860l$BzRCRdVE^HB(6<)*))oK9H1lnYeVaV~lOW2s$>ZDP@on<>w)6O( zLSX+>lSi$>R~;i-L3+3!gba~3;a7DKbw%ANgd>v6guqs?Th1gPYo|e^W9PF|R8@xZ z$bs=}+LkDD=_Rbf+@5$fr(+o5IZ{gIq5!dYdXEb+B7ii`_m})+2 zZon>|-m|AUE(>FwZT4EPtnm2rY_saVpS!dz4XoYaJ`JrXQD&yMz=tY@BfzS*w+f#f5#7zB=1FjOa!r%RLL`%%%gcb@fRNe ztN&f#y~5Og%UAk;J~q)4KPh*N)+W8}7a(N&gSa!T|9GiKVHz-&zpQHk<%bi_mNKoN z)(ii>(D8Z2*CzV!`uP`c&u3~i$rRg2l5Pgo*YCUFqkx*V7GBAxr86~9Ti^h!?7Drp z#2v37WZZlxRe>8U?ac))F>QN-Rrf!#;P^nFBK?Ej=b9JOqvH4E zCg9?CC@eZ3xg6hSnJHJ3-6gJ*?tz8S+$?PZk%?02LH&R?oNQ<44cTw6!NQmhJAxgP zOn2^9!zT}M{QDeg?vMFLdN+>b7SVZcKg_?ovG&y+$A|x;81!FJx%`jZ1DmT43OCnB zJCR~*I0f))xN*z0f4&&Ia{1stmXiY=|DpL;{994%CT+GEo!VfIYaib_5EV-T@p(rF z;>KdU8NVJ5E1OzAQaF-U{&4&lK4Yl!<#@uKYY4@SuADNQPdBib&X)q=kR_;R{k1{_ zike>B^r=X-|+xq z_s4*-k)Y8Ro5kFnN4HtAw>qmg@2+bCg{H$Y3VLe42vEA#(Zqv)t(Z!nImv+R{ZB6G zG*9vaNrAZ-3>+!rJBVgbQosP)_%eMEPSapQ~tEcpO`9`Ggx~Z&W)g-<15pCETI6#Vw9c+AxZb_ZT=^Q%$d; zsLei_uK(l3{TbzRa~}qa20zqPHZBEw$Im(4xOL!OM1RBfH%0u&8&{1PVP)m}SnJ{& z%Jv=!dSUcQL3#iowg;Zo3mlsC5OdV$uN5U9DDV~J+~vPk9OO~3a4PAm)8*l@MCTB} zf>I=7s|az`nyC&axQn8%Mm6l`X~4m3|NdzEBm7LXI)`MNRx3SxFW`?C6;qAlTgXm> z+j}MlYHIEcmi9-Fw|&rjGr{TU(_3hKMtkPCbU;Vc{U84Z*+*6oK%MPxIt0K@$P#^0 zPrQ&T--4a5`fEkc64o6K=osH98oCxOi2fc1X4Jc&cVllV!Xg9+Wt@L>daQHRYlK&8 z53uV`^!fSevq!~~KXa|e932LK$hee`8H|;T+0Ac#MlaUx0!`!LEJBi{$O>?yk@!r4 zUqo%Bz9vK$(;tigKiWop?Vx?qqX~T32EqFS7{3PSW8|_kF5fP$=9Qh(OhF8`^+{{v z?)=g2Ba@|9;(KkU?o26;1w}SBkBoKaG5J%Zx=EP=@c>Dn0i-@M1gJy)b1$2ni+mqP z(S`T3nN7QRgzthn z5YVB(LLpmP$ljtKpz(ZbyF5lL&bhaA`XlG^Ls{|okzZ$Km*uJaAZ0(1V}?zQ5u2zB zz0ZA!V{8#=G9M04Eo-KfOl#i6&NRQNuZpw^cpGuW`*vvbfe$4Qd4UHb!Xm!s+FBh^ zIXAnzFhtR_uvF=MR+;gOhpb(xU)~w-xmT*@7qe$x-zUK@XV5n=$pL6cbkDWfuj8egR_%|>8UkvRYT~a6VYC-EHI~%BC%AiS)0n{#hw3{fOwO}FI>b)``l{OZnvi5;cT&vi-&VvKmE17`2CD&l38Q;~m6x%Fb|&#oJs+#-&hD%XBv?xda-u6U$e zhvg)?b*kakse%hPqO3m@QF2KC;htpT@Shn=p>97SL5=-C{(jyL99Q6=|EANR|LGgX ziETEn{NFeaeEaTS2kW=@{xAAF?N2h$aY)pNousC2sYZerEvu4R+IA*jlNkFLkNVNk z@J+z1t+TG`sxg=tOJ$T#w4Utj!~D`StNVr~N?|Q0(w@(|FC0l0V3a!U!Ps_N&G%!A z&c8F8op!7eNI;x4Z7%46pWk%zxl$1u)88NoNZ6#TjC^}j+|%&5?s3C4^ZB!L^MKtI z{@X+&y)k(&zo{wBIz#)qLAJ)mmAJoK+rIVbZ+$xPKe-?J)@Q!;ng6;zGdum)iX?0U zl7#`uTulsn*j9jJs^epvMSJQd#!k!>ZxrPx(Z>)S{%h%p0Y7r3TL4=c0k-5LY84Ty zWvRU3xNNnTN9Qc(qUWy;`Q-I?^>aH(j})Y-q;r7j45+!-0b6Rks@V6IJrlEN~IySi;-U^C=>xz-N9@ z;%QhXG7yx{=SnOHXjw54Db)tX7)K{4+QCNiA);_`0Bj3U*bEJ5VJ<*`9&zqy(%;hC zKvSDuZV1+dOJYQbY!t+0 z-MT55oZk&14WcuN8)f&2h>e%f)i8=4*B2nVLC*TD|rEZUmc8) zco2KMnJV-HMx61rGO`bUDMOAN{~8O~VA-xg#S9R^a?M=LFoI*+n~_;^&8bWAc^+^V zX5h2)Grf2=%B0t!LSw$B{Jr?L=#%(7oCwgPXh0VzfYrr-5}KSR@6p$WCX-307n0V^ zj9AnQvB~IFbY3=bGaSXojF<|VfJX#ARDhoQBta9thV6|K-&`Wv(VsxS!5X6d&v{yL zHRtj9E+Sr*+-Q1FK1#cX>CkdiVhlGg$dwczPA7FWGmJ)IDxkEcne;32UbMbFPJm9w zKJK8*-4;^R;dpVP>^^EUmT(64gG!(CbXssCi7Wh0bSD7r;Oikd%boQQn=ijEbV0Y} z=^KfLs8NC{MY=486OBHVKpS2H660rd-pVQTI_WNcjnRb9oQnwY9Qd!4Netk8@f#2d zN;vlfo|K%2*}`y&Topzif#$@;wz7v&4`5FGLq9m*1)9vVrlnpXQyPHt?I^$V8T9U) zy=leZQOQ}ex}$bDE$98I_BN5$b-z{H*s~RG9xt;GQZ%!+GQr#Z`Ucm-;&w<4eK)3Ds=$HIr3+0XEI2rfK1XWi+-QFS+6Z)RwScY3?;5k11}+&N0PD61rzNfTucnG7|;}W8@c248q6qHOowC9XS!kI$@!Ih$_o64 zh2y<(??_~nMjy&t8VH!lIMoDUa9tvQ%+!03|5QY6pG9nlycn_6MA3XEF7oh60VhUn z`R`Qvn^I_&9lWzyb~_q07wF^Ck02+@{E>MT}jfxt-Ak?xRX5p2Qaxly_eF6Gly!2Q>@_=!CD)T9R9T7n`JU2uk} zhK?X*614}SK)&@hz_M{(eTGz^soU}Un&Q~R%1hf9eiHp_e98+H! zWWC&d)-dijA`#x?AS)n&R@p{s@4nWEt)oiU?~w@de?gx@D#Nn^WG8hP*GXMv!y6Iu zC)>xoRV`c)fg;YF4C)eZgnde+t3(dZs{Ce6N#zkFoq2L*Q`em-TFq=rdZWWi@{R zHZz(V6JU`pwXZ`eK$=by@dtPlAF*Ky7gg~(E+X-Mr%e|%108`(K{t}6rkK&mPJdva z2JUxEc9(z!F1RlNk6gZT+LpH|76EU|D-$5TI|#8k)b#`({SrOOoTbDWCIyQgBoTP( z7Fk3+sC;f%z)aUAEGI5<#ogEDXmhbtHDWd)3hJI86*-EzP(JW1Qsy_2AHZ%BMcA2x zRs}8?F~YlZXFN{`*3|4{b z1vMT5ha~-`2_`vzr}TL1=L_^5f;wNPU$b^}*1x)-G38D_hVmbaT$pud_m}A261ufe z&CBf9Xl{(Ke`$TXG6Z`2%Ee-DMQ=sMyIYlqa&?cFdSCFY5|+599d&=OCNnPAq`ov; zK1iDrd5uNh+Wqp$%!T9%XM_j8JDItbxN;UG7mb$4Umzh@Aki*oJM_!Vr6Ev!&LReI z!P?x;N|7P=iG8|p&-+n7z*PazAV;dD&RUMoY4L~lZ+j1n>VI-d`RcBzbkWEJO;lM936TTb@rG4^wEV6Aw4m*ldnqkf2^*~*&?f|!m zBtnhyG`SLyi(Y>Zu9y5s*b8-cBFW>3UTdJ^S@3|+8TNiv0J62hcVfvTCAk?e{9i(( zkm@HpT1|swr360_1sL#xR!<&0DGOo-T>nSEH`g1cegmArYP0f!&1P&p{b;TRa4o zK)-;v$Bpey2hJLT{PZrEF(^M@Z!z-TK@2w(R}GyW_w z=*Cd{(DM+;r@|(U6SmW;s@KT&b1t)7|Nz_V=;pwViI6`n30?vg*zrO{FqqJM5 zfi9681P9<|)}Cm| zA8G}gnYFN`3ru=2t-F-AiOt)P=fDNZvvbTaWGWU(I!Q}i243SpmBuNyfO{oB6Z=OP zMV0v33GUow8nG*Q1MDK%CfyBR;NKys5LU>3YuUitEZ-}Cqpy1t+?>Tz3>@>Uc0+Q)DLY{u&>UBkM&FJd5IHLJc!$mu|n(O=~)NZ?R(NJd2&5?_I@#X!#T=!i~= z&IrL}5V$}L6k9wRSU{N(>}BbM06t}v^dKCJj$kGSYr`qDNPQ!?L}cYp=UO9EGtJ~m zu(>%m9koRo+|#lLgK#Z6rvKg5*%Oeq;`>K5C7TFto|>O@Z`VHetcd2fW+Q=G>92R< zuk0;UsaH`$UA9qqW>)oE%aUbRj4}JkP_gMQn)b;$-)fYzy?x!z3bOBSe}0^hKHHg9 z>W>Trli|?I%N7=~(J5`<7Mupt& zbZbpv>sy&~anMbHB@3e{HIU_-%eDOQ{Vq?qsJ(;}u&IDKsvy2D`%QY`Axz`&G#bYA zKC8y?BjD@&1yuqXc7)2k@&!LFcjv@W5!1nkMVVrbtdg-q&SE}p0x6WPgzw?&6SR>S zA+|F*8U58?d6RrY_HHEDuOsG`;z07CiL6+@jc~lD#jBKrgEw{TVbUW+o!JwAtyqPD zB-o+YYCtcSi2?Vye)cK<{d=YWi zD8U?be>^NSJXwQfE&dPc6;6xg$#B6rEI>-@lCg5 z+tyUtjF~zwGFMAA;9P(zeNT~PGBih}Y9LgPs)@&n@5-|1MWGWTc%$Qe(g=v#Hm(Ie zDMflfl=h^VmPRnkPhl50{vuTji>ZxVesJ@G5!o7{G95E3Ze~gihU#W=2UE`%5jS}~ zg2R(vUm&au*!l8HAKUG6afIXES7+QREd22V)w7)RPvmy%=`b(IuXaQ0m6(dF=etC^ zShp(o2?UisX_hNJuASk3GSYFN|NO4O_|I6}P?^r)WT)rzQ+`JR8_NP&+J#LT$)zTq zvmRBqLn>pCz(sRpg9ON{HZtXkseH`vr4$q6&0!$XjFW{}Cot+?Kz#Mdud{?>- zI?$LI6~RAaAC_2)X9f=%aitLgy+f)#9ky4zsb9)OT3>@LigEl+GA zLUwdvR!^hp<7CNEtaQJK$NE3md+)d=w{=|EAn0h6gtKtPCeq(wx! zhzdxQn5gucsZx{{krH~8st7~~Whx@l1(c951!>{1{(Y*MeJ%FSX-1Ji9jWyj%R!Z_|CVQp9cG zg{8A4Ywy=LK4MPyxX%dIa1e3T0pX>YN)`o`>8D*GKJ z)#}ctlD>5hz3pKk)my=wP6nrA8~Y#}Z#VmvW~%tQq=#lwCTVV8G!QL&y4bw@h)KxI zahph%qH=A9&l|@H8o~pjpGb4H_)fj+bKNbg^{rDLRoy&Pac|alp*yfwlZOl zF3h*zFhj|rfN)Qb0{x=jg+P^k@yyb^l#r?^OJ}B#< z%=>>l7_=&CU@CWM)x?E5C`{^aao=!G0p&BF3UXhIk$U%$^qM~=xx_(=?z0J!twy(& z>l8p5J*Q;c1D1olmML@Z8Jm+==(XIOj#0it4bE%+Mk@H{$PH>`aVOEt35=oZJo?K& zWi9^;t4d1*(Kh0nh~NY0n4!K5jc*SE3*U81T0hhg z{?98UVE%c9g#TFXe=hsK@fmTm0+5hEkmnn;x`}rPs1F3@Il8!}GI?33c`=|si;Bjq zlvn%D2CO(Dz`Q@+J;BR2vf#%yI+ONHGQR-n)>RdK@^>M}2RDIkh|i|KG4626#34#; z$K1p!f^cY%xL@!VvmGEcc2yi^ypbsjx5f?6c#(l>rNwu#L@g{DeHir31dWLxN%$mw zs!d$X^wh18Yy-Zz>rBQ4N88aGwI3)ijeJ1z2h8T}AiUm-CKXU?Km2u$0<`gs8&t~i zr2+tfZ6x+m)+~1`;1gD*&7KX=S#q2@kQuT(ok6ey(;QayxEB-h_!VGaVl{V=`D8lg`SGE5^x0Q{@$p*tL$8$rm3#lvU8R{{6QUzpgLJ&!#WBJf(iJeidwF-ux92c<^p0q4z32jlSAfk6$lx-0Q@(@vN!%#eN?B3GoT zTiPw#^=R4wdER#=LgwM3FMd%VBEj)w09^&5HvF|k)~EGoKs)%3?hS-*Ys6?R*f{1U z!4bh5cNNI=7FyB;*Bokehvy4hu*zK+gR(=h^BPNXVm1?ujL1dftD%jWCkI2G`|ZWV7tT?J;r zqN1sj`Y+E8Y?0bs#*j4K5K(HA@_0$@Tq&Cai`b!`#M%`d50Xn@czDgL9Z7P zWZAC1i3f>(G*hlY98$BZ=j5c4{(x7H!`C>^L6B;s$aQna!Y0+43AN7rp$O*c^(nK* zJ)xAkE*5tCXkhPW?}i$|tHl}%G2NgtsYy$h2~5;dP;$;jKBb~e_nVOyw2l?iN>4C2 zOx;kCHMX;sGu6^9K{&*r#;VsC4(pz*aSDCjWy+?RzG@qN&lhO5;R3CL9=-55k!7osL zb$X>y-TuAT#>dOkz2zolxwv;f z!eIO!6~2FwXJ3Xl82z;-y#o=DZ=Cn(3Ve^T5@OIOC>v>~jlQqFR~wxDc|CM{^^FFNDh_#(tpf!+@~5n#%-X09JC43_YPwot z7k@WK`}Sm3zsKfRn0z}Bw{4*Z(%yAX_#^}xt>Jib>-hHt2jIoiHT1?lo;Zgw!EB)+ z;U+=1MQ!*8^O;TtQ3~=dEpr|9FvyT-Mo2^V_o-tePoUaX|J*Bi$+@VZ`HDRLbdEDOZnwib% zB>&$ERE~`3Ds4Jkpj>!jT~e{NH8ryJ&GS;L+qojTithHMHl^;V%01ShUIrSvgM!2Y`S|pLs8i1*6HZ zmv@8(vCF*|TE-5;-5k>wXpupOZblOF$;V-Q^qGna-nRozPD!-vTLO3*C?CZz=!x_- zR`0*0dRe)5r)fUOPpgb4t{UT&UZ6(w zSPSzK<78nxy@fe~mLA}FaTZ!AQfFb8iDx{$0-h_V3eZs4GShLu|6{xu(Tr_45zcB< zYUhq1^KP(S(xx1qB@cdS`KY1WrFNz_WN4aMjfz|*kD%J=Rafsl#CKRjSOzT$y#szS zL6RQzTR8-Z0G$|xfU(^@M!Uy5=bbHyM=v*o(_CQNR^;BAUX2F5%Y~!x#pa-8G5Ul;-%`L<29)7X& zH`k@^Ts(omA{@%@B_yhxoAprk@CS0zIeRJ$Hx|9oOFGH+vr7n>EDUdxT%^3fjF4GA z^TGhdM$OAT{4fTiUXWzVs~tJ^l-6OMA&VkzQH;OmlFn#C0ZM0MdaQ1_49}u`R=gnk zUf#69Wa;H%xA!9>!!n->w;}S>u#& zv%Ru?w(Q$fgX;Hr23H*JUMjXpsh&x7wpaP!7TlL*+u#>obS3+v$JUGBDgjY%Je|mA4FL#QovfhU0Ev z;8sX+AY7vTPJVy8%-nqL1jhI@#3`|3Yc zpm;?f2uL0~2xd1?TTv@lpVJ1e|LL)Zh+afA^UH2LR`4PXw{qb5bv9a#^m`Nwv%2;S z=~Mmur@y7=KNTPwdMmjIx*|Z*wg1Vg1y~)O2fiK%Wg7^Ai0LP~RqK92>HhLBldVFp zeGVogNAPp$b9*@*fS_KRuNo>YCPMsgHoN^kw`EcXU3-) z)I~OEuyJv?O*I(UU>%#BNDv6M72*Th>jW5%@tde|ru4KF zr7vvWb9LW)VvlV1Egtp}eU2Yi0h?Mvhi|W7=dC%0Y|K2C^YD{EsWM!2c3~@Tdmlhv zZ{fs3P$(?*1DIso0B08a<|si~Vu4BpMy zd03VC+T|I94miWFv`Zr+<8^-gx6mlIx4Edn?;7y7|i}N3VfkH}kFdeGn9)$hC zZqs*C#>3j^x4#hf4>T$B_V)(yuv3E90D~gW8Tqkr^6)(;j$>qbgLo0)SJ;iM8B5#@ zVd85v#r$hmE=H95j|6oCUnCsgq)zO`t)=@fB+Y`lk_af_ZT>Mik~yEvp#nFrO!8tT zIM+oJJUAA=fJu+Wpb!e*;`Ful33{(vl3Rdm75wV!_|@kHF4Ohg=TH-F3r?|}Rt%G@ zd#Szi3m7{ZW;|PsO}Uw)1Rr59pkPdkGdUTJ;UVE+b|$!$)MmOI24n}(gK3};NmR${ zu~R?a1Ehl!#D0ME;Ks2@1X4KbgCEZYG93qV+YqJxL~Up{oLBs*o|>%ltwzDIr2(WC z>+e9xaRodl4sMRQYV~Ps4IBzpah<>nC)z|Oip<;ynsqD)#$a^B6q`1`4zhKJd}07` z0&D}hS*`=pVhY|i?e3kUHQabeINo2e=WTViZEJm9TxfW?^XIRnv794mffhQgMryR= zuFFQ2v9`$v&_f%Hh8WJzthQ$B9U14)?Y;{+U4D>!CLyB0IZZ1%Fw;{p{p|D!4VuLP z`PW+Nm1$UWry>tbW$>1?V4QWS!OquG>k=w?SN8`KJ5lkW^s0kPPwp$u`woI*Q29IG z-`;=X;Bu1;JPalRgdNs`9l5C>0Dpl=HlViA0oK+mmfH{TWy5g_nIM{L$~jLQ9NWjq zmknwS66Tpg>Fr>MM&VGKv@~(w+t2xZ#ChxeG+;L~0)XI)lO7 z+Fr+*TxcVS8OeDSv;}w;`h6j2b7GR3cDUm3;a0t%LQz$wBZg=n6OVtRSmP32G+*BI zQu9fCOZ|ZMsopdsd5}I>q4MU+oUZ?lC;EvO<>b;n4j#WpLj<0v&rp!XVdq^4_?m1eP<^_B?0axZge?Ol4#kPjmehl58a)HEgBhY8ZK61euF<6mzsl?$^_ zH;H1fOACPqh$Bza_B6F7|y*m)HZ<{u^Xugr}|7NtTW-D+HYpfuh~l4=4oXW7gIlK(K6;ifr4 zWodR`*N$RdklxYR3xF%|87!}n9i3m2q5_TMPDrXc(r;p(GItEI#2oyNoNnrL0QkPF9_)JhF z2+jbb2gQtX!`3E|NAjNBSZhaU6UZJ0K=6SnPw&(2v=UUAJv{di+hmt$c=AnmV4j&yzB3#|?ME1LX z?$GBb^ZTzW6KAYawCkO=D4PB8O@k0f*ncKW{B&Majw;^V>B4#Kxd?-T^uAC#5=(D$ z?7e1>K`DJgWwhkP<7;TSgQW(V5-uBX3K=z-KKCyu*e@dHA(jPsGj??gY_Mnn*Od8F zHq!woYZTQg3(l){8+`{s5ejpI=q(GwQ>@8s)&c@HZKbad?G_=JN@q0Dlq;WBaSBTd z(ND?z%wnA;g@%EpQD&DV)^dQL$N?iXftoXgydn(d9+n^?D39rL!w}8}`U+Bp(HQP? z*m8oIgc1)$Ai-b)%q`*;f;N2Q5wZ7rMP3Q-Sg&adT^Jr^F`GYVvjY6aHbWJSdGGL4 z7Pqm)Z>1@f55^sGL-|j1gJORpTpnyP6ucSJg(;jVz;>bt3A)EnJ)nDl8A}pIBk@*1 z1bFMS@ndYV0?(0h8YqXOVG28GDzf3oc&V9@E(;-w<=i_3ZOrB875cA?C1-pf#}X75 z1&zS0ln(;sQXFHu0Mz2;8%{hTSUd*~CI(Oox=gvZ1_;)GcZO=EB!IGFyx=Gpz=|j* zsPrylw$2Qaq#Han#_~Lh;9yo*E9v%_5Om<~ib+Cwhi}skPIB?X#d8PmzrPq3_a?yO zMz-se;mbo#OL?fkm^@ppuFChF2nU@fAso0t>>~1YK>zC^3wh3~g00e%X__hrd`{KmRc@AT23(DC+b6_yw3;^TK^Zc1t1_tgXJIroaA+dVEn^Og|1SynkyQ)=7h z)9-p|b_O$oIru4OKRi7VG)m=q!rfpV_SnuLq8hBnngZ3R7)Ma2Uj`K3p?Tom*Uw`| zgvTX5t%Sw%%*Oc=?2dWU3C%dv)=;Jl5Z=F-#KLUn9p%T{`aIKm z7{f7SF(b3Evg`#S+xKxDbx51 z)=PELwN^PBpY}<3^-Hg??!R*hC%quw2C<Q()rg;I*0d=)H&E;DZje+b}ReiXz_%_vp`snm=tY3ABpx-x&{w#^B#~ zisED+B)dj*#% zKW9zNSpdRzDeFMZ>ONSsm4cYeJl;$4!piufkPX)3s2Gf7H6^~@F+!J;@Rd|k7fVDb z3hF|0-@)N+IeV($HDYPSd6vcHF;Pp`G(A@}=c2;jxqF#kcDlw=E?EruG*m3|uD-9> zJjxm7x%t}%^cLeJ94$!>8URt*Mj=C6LRF=x-=x9 zutBLw?aSV;+W;!^&(-MvH$V4NwBp|tr~j+4_CLWy|DfU&le9#O9g~4sP>|abFuF*% zJwrH=@*;g?e;sSxcxi%?8>+ch7MU9qjC?k6bmPj%jOePFV`sP)Svp3B6+%Bw@97X{|5|dCx^zQDGmXI$Oddm$`N_}>YRQvapVmBLv zstgp^fZvTQ*xX`n9q1os=LitA&4^a=iXJwJ35#($0Rtiw#rchQ5~x9kz@QL$levZd zZOY**DB!&9+z)6DlUP7=7$XflXkIqz6hwYo5bUfX3C;~ezHa_9O2WwYN-agEB z%%=}%J<_-yLsM|ApVV>!Otwqvn+OxEBY?j?m2C_n#3iklbj~+$jTgfx%ibv4*Yr== z98lX!&;v{e&DlTR%*3-uf8L+61SSf8ZZ)72D76X(j;gu2v}zDDkQ6P#L5p(h>gTxH znLTgzLWUts&+6|&C!dbCUjEIcsO$KS5ei z)AzVmN``gdubg))e&&Vt*~br@zMb;r)QHNPvI(m!iL}iJ{8N=gE+v1-N;#L6O}2jY z6!+)d`NMk4{7CwH{QP5g>nbJzZ3N$7GdF^asfyXQ>So(IqC1%68C*h+uB{JjZ2RQo znXxjd8T(c1Sb%uo;;Y|Iy_Bum^ga>Q@6Q8Vt&FGFyc&*}q-m~;E5$0bO8TD=PHvv? zGS9w%L71eJlqp^xdug94`-)QiaVn%lnR(ZN@6zIWKr31=ZianHpQmW>)E!AR$G_jG zy}sm4lB>Yp(_%Knch%8cx2Qg+JM-R1-(;Q9MNp*wrm}kaUm=X+_>)$*q2W}BGPmZt z&~Dr)UC_PA9uky*Tuf)pip+m1!u(m_<-e=?@()1zm90CsV9yG4(4T8k@V_%XCfxd> znYf}cL@D(b-CobH7fdan3b-K)hbI=iQboAP2*;J9om!pLx z{ZxebWmsSrspNgXFrz=6aCm%U9!E;n1~#?=n>iZ`00i2H8>Pb+@?{5 zYIIdvEV_(plG3kyw!pp6pqi>YVy9y1GW>oO`vR@q+q4_jW8~=e$QgviR{yR!ky!sy zF@J80;|O8yscmo}(=^y4wC@=#fM{VuKHhk)C1KVuX$EgM>Q>vjVZw_cjj=%TW+-_#Bm3S}l zQLkTN#MW{#U*%G#fjt8cE+Zk^(saz4{ir>_c(VtM%ZUlBL| z{d4^PB94AZM8l@eAd!ASNpfGud4KRdKB1ktnYb4={iW{d)8yW<8v(63TL(h|RY7@H zO{`jr>HgyGd-Go}<>@3JFV>y4J1zW2Ofw|`RZC$6Mf|8rDEQMkmYAfkE7Y4rIlOeU zb1Ijz`ir0)b+(btp+zkaR*wsU zv;6af>%djq;>XihcF!(l#0&8N))$?`fBao&S_TDVZFYek4MFU63@eXx0kdLa3KWq} zqTZE)dmogZ3M+l9H{Onr*U`}gzzdw>3Ye*S&G{#Ev2kt9KU zPp=M&MDHdXgxxAYo$)Z;S1w3~cNVP!5+4aGY%=OeSF6E&n3T(4YwnO)7A28;-%S^G zSUkJ!8=ZGKfZHA{nVWImcXqj+4t$<3`5T%ED`EK`h6KeQw%7(^Bc%K6(@yge2-?z!xF?mz|g8}n4xo7qm zYRxS+{hMTi86X>rd43nN9MWx)=1+kX0yj;X{{221^8pyyp$z)UujE(E2u!u`yk{Zc z0fu?xk(!SX^0+hziFuCTMdvsKWscciw@?$A@bTm>uPYj@7rPh0^qO)kH0R zAGqDU{-Oxk;-}_*1+bg}+Id%;Ll(3m#7NVXBHZhryGeh9WqlWVHv||m{q-FijRAl6 zRHmTq3`y|F8grQR6CXkTnRlS|`m4P|d>pAY--WND&!d@0_M6C@c)3lSxLqdpl%19ntsa;Isg=|NB zgZP9(kTECcISUbkmhYw4){tX}yCBmjO!a|^2Bo6+a&CsMjlLTBwR&PZ-atxYI{$Z? z{Vzuce(1vffAJyt4JiKnN_xo!zRrO3`7?dl>Qm~<8XN_<4pSZ_h$lf6d;Q%_SNymx3cqoWph@R&2SeSOFcLO`>2M(rhf ztv_bxGWj+|q=q~qZORFYK_8h#uI03sL!JyABHac=QJM^-QU6kDz=AmJ!w3$Lt*9%; z`Q<3|`%sKy?CSfefllvg3-64yg(>7C>wejA7Ecox2W=<4TL*L*`a-*c28H86^N$0h z#J{Oa=Igl*!nm(l7(S^0yi0pLW4{Z9(Ljr#Kgcb&8!`VJU_j(QpTXwGrdK z|Ikg$$^VrHJRAF`m(b#l z>JR;<^NEI(i>$f(O=s~!x@M5Ui{3bAnd2!Jzx))1L?L+?em;G?5VhTC!#FuM12uPM zRdnQ2(@_pNy1_4RWQNYM!IIzlr;Xs^Ljp8{v330qtH8-~z&W2NI^lO?OV}M}rn^hW zrOJKMj^Z00tSrDTOpYCPMH}-D1xP#gt0zcHMWydBf6r5{NFS#FEGi1vB^)DrFMFt& z4lY=WCuh~Yzri-&&wZDm4MM~;4HV%u+nk4P6D))HsqAc}6NBS|E(oAbN!ne{`aEtg z&XEH9KGyer*0?ye>>w4L;O-->7VOW?vMUIjE70H1wX(*ZQG>|}vCd;E!A1Kg@-h?i zb4inzs5a(?Pg|~-_XHA_!3g?rfe2`ZF!5Pk2L{u>qWcC3QYBHGI{J7KWyzcL7$ZpS~V+@C9oQav=d{@fSh|Rgg9*R(dB?ryq z-hT@a(}Q$=&H*FEu!&}<#wdvOi6{*e&#Ww>2MA`QiGb|mD8zJzL-JtQ<5@@Nq~(%N zLk^C$*Qvt?=01DGOUlbJhT2N*;9a%vwzBP=8qf+Yg<6RN*N3y7Te^{8^rZ?oGoz|4;Y>}SmpkCPeMAd zjV)u~5IiFFJP^G2E(BN7MgWXiU~J0MSb$ZP_%f6^kbWen0+RTOogFiZ&auW0Td=>9 zjYK)4j4@@P=Zldd*!Srkbz$k?9G}ud56(=AOE3r09<(F;kz1H{qwJv{9(YI6z(34TDrHKEf7h*q6m&OE;hZn{j zla_#`#7Gi%ky)&+$0C9izf`c1w;R62 zqDLWhAXFTa?UP89;+er+EYupjCJWa_iAQRH9-8jRE3h{L<)5SQ7BnBC+E$Y5%KRkY z4#p)XSkLnIRC|*m#r7mYgEjAO5ztomExu16(z7Z*gESm$l6G!-UdUOzrp@0k4Lj%BLrFR;_!U` ztF?OC-5#OxW~Wsyt@$ZZCQ)S#N_w(g?R2y6@KlwOU_UV*bn|76ID_SYjJ~ z1$B9C{w*N(?}e)dw$~vx^fmSvqvIEKa4hCmcOIX9j3`Mj?Gf4_925hM) zs3MB#kR<(@Hun=i0>4>gT7%`()Xlzu!}ejGOb+cGnp`y8O(aClzs8Jp>0P4t{%!gEZx)D%mUB-+CwA6Zh()(L7Uh{InVIU|cL*tPv&zif zU}9T#HzZHq`1(#)qXKL6uchqE`UG965&HnPau2o3rd*$%LuUn%nyoRPUIWmA#5?2o zqszDVQJz5RD^F5Fkl4)?1`0o^#J5bos_HU*#FYC8R#{cVOPjz+&}eJM*BB$v5rl*> ztgz^gs3v)WCH#aPB+fel-zqwMZ=AjfAO3=}sX<|aE0Sp>1``Oc>r( z^Lqw+{k=|t+A4u34Bg=KqsWn%3zibA+KeVe$Wl-+u>dOp7O@w8tS2;v8msD>vyUy9ZF4gl*WoWr|ltBmmClBifeyn9ZywKKVHazxLT7HB||w< z_a2pBFR9p{dg`d2=;Bb6`Ju*>`X$Vtxgx-x_^IEzA;(FW&|{#;s7(#)pa~Wx;X(tB zlg=jHUJ8nJ-vp&djijaemElj|`pykhe{gWaxK;KpXDf`f+XsBmcI^xKfHQk)HWwNo zsx}*t;M;UGT_94tD)BpUJA=iPBjDg964cEi)<9J(?>J5n*M$EVt%nCp<;^+>De~GG zk~kt7y$$SbU2F(ua|b(4Lub~~vo*t;98h8mx*c-TzGhg}<>TCE9feJzK|gA-b(=|9 zk%gFpd$+hOCoi$pDk0C%&fepMX2(#f9unX4VnS6XH@aNe$3h{FW-+_tTEJ=UrPBH0 z6C*ZUd)3ngR@CY!*4&h%M0CMsW}5vW9S^CG4jDISKlMkXpF1z-yu`EnyDAp%F2z76&*+~e2)(Y>Mua9o2`XagwTfWyDWUs`s4WEsfeJ=4GR1Tvi;e>tM*U`(W<>XbjmaKR6i& z>HU?Lg~Q>gt@YRlaA7p1XS+$r7%&~c0YX;oPt6NJ@9pn1?@>RXd-T{6py>u<2MEV1 za2f^GT><&N*WC-s{B0wv`Ys$;*dM)Fex41s=RQfa(ZPxExqj1=RvJf_vwtu%)*%!%NDF>snZ#pi>r$<0ugQ9 zYWeDIi%BG86S_TFc4ull-jA(Vvy&|)Ec?kkFTUh4o@&`SvwTf$_9^XyFP)_NB=<8( z)`?WQithzOI`8H!muc3XeokF3k>@pyr0c!G{grES9$3K*NBGg>m`c=0(~;)$l)AL4 z3SU&^g|C2l(WK_&OmOSx9WC;^?zVI_EInt#?V*;mI>(I3#2i$A!!^CA>TXF!$@CCW zx?xa#L1XIPC{dR$S9TyhhAlNOXIX(SnL5r{uIgH^CtGcc-EzgIxyN5jMc47*8Oy`@BgGl@FhR9* zmtgEHr2l%q!r2Le#SdK|F0r>!`6X5%t}wH>bA!CtsW(=aK3aGB-3T0bz3;=_7ky`l zn2~cIicZWpz41?&8EB-W{I!^e`w@@rppD?h)91P#escaU)Q*!yA@mY>$9!0tYw_4) zoS}rKJv=O&%I=)r>(rpZp|OM+mh0NS3rP}H;544tv0b+(z>OpmM0J_Nu_FWt)|aS^uH?_2e|s z9EX%=o|Z4av>XUd%?tBw(MrkbiBHMCTMtqGnul#v8b{5Cazwdl{e;V`g($Sf5H?95 z<2o$`!b`Li&jR*=u;ZrfLF-Sj70^d*8P4>0q9`GR7a4Gz^QeiTqIPErj@%xHn#yE_s%EejJ5VNGZnD5Q2`V>QC1 z?f^Bp?4kKI$`(1URo&oTNFKr)gkNjYepm-hfVXIaVaLR-k!=N$xvK9#n}5z;=}mSm z9{n^I39ACaVX5p>M->+aBO(3wNaS{^j0sQ*@IQ31;JS5I196W|>CnAIUzSVq{;GJp z$6u0>wFk@_O?_cgn5FBqe4$Vor?vA1hWI7yc7-+dETRhLLy2UO%bptYL9cm_8UP8V)L+#1=+!g!v)EkE{?M0J&x7~ztX*Tf2irV~RsVK(y5-`iuVAM$1G{5*1m4mLI|BkAj{g$A<sN)ayT1ORRM>HvDVOXh+i6AIJm|x+F1s1S5#6FByg4_+;7buB_ zqZ5|G+_-@TQ@zM}A_BCZ_^?qMrb*k068JHVtKxyh)3_Z3rEzXg;Kd8NfnIYuNfy|q zdb`K({NJc1a4YcfPA64u?d2hRsQ=5WoxWd~nc^;5<))ei#_k2DLY?s^joC`F7fKV` zPTPd`KFT$>pPcFA`tR6%E5}E*H~8bn0{Pn1Q!Vxi4<8>aP6+g1>^OZs(Us)H7V zsuFHyq6jyDOD^P?w&0>=0ap{P4>^BA?}twK)*oxA>1!MLgxuQGaDsiqI_cwl*`868 zo=~|;ud!W+@{^m^uyC-l-V2;eKs_p^I%ut6^xzmA&Fy7aH9{z!gsDK}=r~g>zpkt} z=yD0nXh&7%fVOPJGzBPbw>Osi)m!HO+8r9cW!F=8hRBTh-MgWlvcahs-^P3o`~D;q zbLmOzVpUyFD@*5#sm4<86}=&R+oplbHAh~Rd06-QOQdcvvCos?X{GKQdN`9mT3Fh9 z1_b^D%zlcI!`X-nL$@$XmDl=2@wP^zz0l@O(sSjPhk)x zDHgSmX)NI=%aA;*dNkbmEl)4F!nbxsP+s`X^_}nH%!;dXQd>ht)T6FX=p!IgN+xzv zwl)Asz85)rDctC%a02AX3Y==EfHo*j%$)VAKj^+KL+_j(`ACTl)s)0PX9Y19hQGFg zNn%8~=0bdgO<(m53oAH@MHdM$2o>ac1cg(7`C8io~XGf)`3Dx zZSubhef(%{cZGMu`M0Q#B6xK-Gevn_pLMhN&aNx7=G%(x!R-bOo^*{7H_{!I7+b5sb&^&>=_?fl--(;8sdj z1K!cwq}rI6a?p71gNwQj(9;A1eafXs)LXK%Zm)^Kq9@D5VtTK+wN!-QgDRe4J)u{5vUsX>@vdPA;OVI zFxCb_&Bd&q#Y=U!2bJ+u`iP3}J0{#5+1+!CoW2*#s?Yg#(qU+M&Ol5%T>*Arwja|; zBAx69jaJB%O6phc6pa$;s+mR0(Ss%T(0!@4ZNaBTE@rIW4fK-Ha}&^r!F*Cea_ zBK>|M^{*It$L>@|Ia2(GM%O0j@4~pfaKJcbnB3~wjFRSgvcsA0GF^LhaHyAl zoUf;2nhj2Kb%RDiqkpe&HXjoSYVsBGrXxJ&k4%pcHk3u?XY6B`m}da~}b4s*13 zf`OC61kl$JY&h?=VC`}Ge8B1+a9>3$jMn5e1lRGa+scn$d5mcFKcYJ(y z)kPJ+thsSrU%m?!>-n;k*(z+6mv6IF&56(BPIq)YZ9n2=%ngYk&Geh5DbC(J8Q16B)H^G%ER%z zFkR(#n}&aV4XK(~`g00!^rp79diSXjbV1h`S6uTprlI$#@ zOg8S;@&o$$57(J&KDmXo#yJ3~k3;ZOY9X(w#QE~-{=OiP@cD-!5A^ag1xV9XfLit# z@|!S_9r#mrSV6?Ac)LrX#RmN|CLsfUr)}(QCbKTVryP&!*B00!RP{%Y-O`p8q7Egk z9@7pvdxaAUe#udiGk;W|uiqcyiA(JbO50A0Whi&$_p7NsHGhS__H>9UY+gOxo~$Hh zQ!({dHo#S^o44aD*QJJELQq`QcnSH8-^GLC%2tXS$RkWA767Y$Gr^~isHtGf5TC|W z4UsXRxg*wq9?_(ZU&jtgYA~DtGWMLU_h{31W>&I4XHKBRVCr#>J2ltOv~?^TU}GCj zKn|1}P>1Dn;1B(YOmTNX*T}{PY;w{z5RQYcgY~R?f^A)*PMoMIvd-*+mL{xh+s4+c z#@nze9shp)F&^Wdkbyt1Oz z*t5(G{LRkg#WkCCNJqB5&07-wD|_fbln@L%1G0P)MT{te*Jg2R5RpxL1nuZ8{3mpl z!O(I*fS4^K0}HyQr&pvI3o$Fy$dFY9Pb-SspiU1!2^|L18v=E6lJufotZHip&-Lf^ z&tD^fl&Sd_qAU*$cL4!4Y{$wCdW2xD;I)C~i+L1#XkMvkR<52LZAbaAvsqFdFLTs)DpBqZZ=d=yp03{XB*h!gOGlYdbsH0>C%<{Csppr5W6CGorNtsv+FTiH z6`NR>%Gy=F>J6EG_N=#ybLOgN`kTaaSx>~v(44Ki%Io=T4neWng3tdh6kGBK(nW-O}Ls;wzzz7BvZ?`CG3 zFTHDHp@uD*QPs=ct;0rkTO>Nb|HS7Uh5hs*C@qzE;)d#&lel%Y4P(mp+O}(q_?uz_ z*ZzJ+ZnexKhGAtL>Cyl>@nkPr9ds(A?IoDqw@x*4&QgqixxJ%1$J#1ux-TO2dUY|@ z4-|k347$^Y`xs}TyZ(o+tW9E-eRmW~kU zIFp+7G2?kFZ?Y%4Je||sY9Y$)W$aqe;-fG(LhnnksB?6vIHVmsJ3Fx5%%(=k=$i_!YP*di8jwY zSy{5yAL~OX+LNUsYH64q^G7O(zw)z=7M%IgOFhCE{VVYK7m_@w*|uqoA7(QXoE!!X z0TA4TJiHIL9E`P4CfIYLb5}8fKGIh7At0O`(^|;6ntKHTgFeDu#0m`YeQrHQiWA+U z_|j9Hm}s<|n;YCRV@7!^~!sgg^+!v>ISrX)$A>Ff$BFIDwNT zzNK#@`I3hNTDfD|uosIg3@0#hHUalb;@*Z)<0up_6f$jHB}*H#x;K5IZ<$+GaIu4Q zOYlLA>!f&s1zzW*^Z@78*1U@cllSDvJbTIbnp!zmb(rz0*Bpz8?_5l*5|3;vSax-8 z>!U`OJ5*-tYgU}&S1T)zm3`_K-=uocwSW3tmAs^Hu?fV530Btk`&wDFo=+^3GtaYbnX>z*G(J5WflDI;J0V(M{%L$?<|&<_GzNox}`SUlB)+zpc+jlL{=@2}7i zkNM*aB+b8BL*nbbcXU8)FxOAi(@{NcRfr^1O-7vzerkEV{D`7~{n`9HhbX6(8j*Or zQrjpeEAfxC`wnTSZ4;_j%(L;u#wy2MEC=QVa*FZdtqy?IbmX}2$IJ0YS(Kt!3+ii!*p2L?qXtu~<0fXp*d zX~w7#fhI^uS{cHeZV^xrq9TSlB9kH{LIUXq5o8{ekfd#9*;^%S$KHn5ZZJZr6It=}LlyVq**Pv<%-%&{f;SwcHSvP}vmUr$DjMk|}F z+Fjx%uPtJ}YKEY}9Ir1RC_|5TX@^73Jo>Bp2T&x+A07b6R_qxe_CI*&dH1M=UH*0v zBi*!2W~VNpr3$NZ`a{qI_-8Zge`iL3yXs;$I3v!NuSes!u{8NQ8O6B|q5adhhyAA` zE@sn#lDX)3(0X2rVhT_20EJf0X3UW6{zGSui90UKmM2SrZ=AvitOE{!pnS#+e6iO1 zcVqHDZ|E&{9at^W1#$OP;yjWK<{Ymm%-L16%6}{oia%^maH54%rcNzO?SMMV6n5l` z3k~7T|FE6c2%y|LV?ipt7Iyd@*g=%B)qUeyOoUNkZlPRl}Rju zT9*BPS|+srxk{}6dy)K4@XmiPl7BOzfA{FW7sV8KB+QGlU)W(dU3p)zI>ONJ zz@+G^Adaxc)HFbr?Ifwd)D+S;u(J=+Jyluc);_MEBt5g^g@CO~%n(?#>BPD`9gOB{ zj2h>SGdKyGg`KP8A2(P$-9*^G(u_2T*ZsBT7xp4(nuLCZLxIj^Y@6nv+&+fA$~C8t zp0Tn0Jw-$-N8f=vAp`aro}R-nu6$M9X1kZl%!a>RHvhLeY)1YQ5-}GIeZTb84gj_fm z29xPi>T%<@x&?!lfwe+M2bZB3f-+AK1Bpvb z9ww-N%stugo~s%knaQdvxN+PIIhQZX zmEU~E(nKznkl(Nj|CYU(sv~cdJs|Iy=PP0_VN%(U8zzIIOx6YdnpusNQG}_Uc-{@5 z)TT7=JAI2vtw*bcT|+!a#N0vYDRE)O;*QU4Do9p~4@l_hZZ?E%mhv%DxGb3+!lngU z6beJLNJrsy910My+QPWiVkctXWTV+(pkLS_KLN$GWSJKVoYPo(vO<;t>A(=nfJiuX z8$SZE(%>CS+*Lxd6O&14KYpc@whey?xI9Hu#za#lHz5~n$a}4+ruLo_;&_}A4*6EP ztqIad(GdJFi5emg$f^aE%r!-aTMoxPnp=vGH)mdqdE!W@co#V7Kc^TK85_CxZvVpr z7Z0>QzUW$`b?ch8>eDato*a&PO53Glj)Sj*?z%dtYs&=JS`mp7g)W|wxRU#D%JOZv(eR+} z-!|Zq{#v7KZ4FLK?xLaqq`Tq9}2)FPV8(tuh&mJ4KSS9@)S%nq7=(nr$3 z`SG-JJ9bneR{U{G+pd2=v+E5{>~|Xe5e?awuRXle_>tY_>+7Cs(W0tR!LE1S%?b7I z1x2#Pk9iBq6P(qk-DQF@`(jNal$*M3BWjmr?qE=W0Ds|WLxA_xtXFy03^Uv*T5q#= z#Bs9H+H!|&(-t_CAKJAv%(nI1aOvr4ZQEUz+wMPo+i^xcJt^G1(<4Lr9F*%#K$d7x z3K(qlR+PWR+n03_4cu0F|5eJ5&d5G{%QV|4Px$KOF5G4? zYdO)oQR)gFn+h?UWj0RQ2vpYe0vaJg2O$mchm);NOkrsS6zU@A|0r-+dzxwy+ezbo zGch#zD?Uh66eM6KTLp&`F67_PVJA(uv^K@lH7J*GV^N~s1(9HB%t*M@9)RiO13Yq4 zm9_Tlqz1IVqy}jorl2@b?w33yA@VV?+X3D{r5T$!qj-<0mLV zC>fBm93tPI$JH&hW3~b5&?t$`ysnBQw9`3>wE^aHoT-zC<&*G9wpig7d4C}BZ+ylo z1~`i~59+E9Q5ru=H3au4^$o2k*P(j;0v~gh{WSgac?ZTUdJS1M45vfFOB})j)g+kC z-c*XRR0E=STAP92XbQCUbk`v9)kHei8r6ptXulW^f%53GU#o~bZaxM0tRx0kN1(^C zp+ja`6MiQ)9gJ=7cw5ftFDmH5!`1$FCN+`5v+$=^6&g)PA0rIR>UjCW;K}Txqs{U+ z)Zyd7JD{;vbvR__RaA+M>~1%ezrF=uv62aJ{*}a~isuF|B>wsh?s4<+s7uT)$56Rj z{1jSZGs0!cA}Ca|FA8bWc(B{h_3(Z+eu_QjEZz%@v9DCkohRb_VJt9W6|s{@=cY-iYNCo#~)Mw`~N!!Wh98b}g$_ zfHF)89N@o_D=-K}0PLXsoc^R=g}imxmnFydCl6@Q3rImR5JuBa3~w zFZRcKjXM=Nc{tUe4Vbn?-d*Qo=3IO`og6-35EC1A+DG|%Id2C`ap(&gg>+8KH)lz{ zIR$#H9oE`|Ru=_D8r&#SXg$qlh;&A9P`|@^iFp z`RBXU;ai*_A};BZPhXyLrFTqVF=kI^_k^wg(6ynbG5)i|Ps+}FR}}N-ay;c$o*o!nH{-ol5ekk-uTD0g9;(bGd|CMLPv#n8Rbt4e1be8ogtUPO@*b)S)SK9Xp9cK|JK*@? zJHL&HbHz8jWM>b!4o9D~^L#59Tn>x&lUeHcxjNJsiD(N3lH&mOt4=x$^MuOx;Ha}m z>(tUW5p1PsR4Qd7C7eGVFTM)fusJ__;(8?q7r1#PYkOFlLFw)f{l@+z%JqLE=BF7-3>;lJ z7Y`r#edfd0tD2b+GSBRQpQ|lm``(QLs1c;)A}Ut~ew!6S>iCH6RcK?%-y#h}WEn9mtb3pX~mJ99fs zS1uAaa^zN*+4KDqz=5rl6c7pO-_NoFGv{QWyQ_%2lxyk<2^>t;>i!(TQYu*!%w+K7 zah%rH$^1uixN)(f;0j*IU;IYoyiIznMKd*BxZ;5jDv1srL)P6vJIdqZHYDG<7CJ`$ z4LF(%Y5+7GJLCY%RO*Sa8KYZ`IK>-e6@V-R`uOK{C{vB4!4&~x6L?qrHK_v}x=0YT z9z8!$e={cT!JG?eE4;r{w{-mu^L#lvdsXCJ|CZ%DWax|>F{@4h>`O&~<6bEg5 zXnhmL2^AI{OF=0~Tl}&~hXL^x7~mmk4uZSii+r|gTHAHj6g$S`Y?BZBMwt|`bk>ec zJ)vFE8XtW(=FeQzr&=X|>-C!9jnpf`rLi;OZ-LrnWL5Z6V!jVF4FKaJUOMU2;~CY- z(*>;3he#+mTipsKVx3^++8{JP8LPF_r~|WW;L}6$;NtB+ZP)`3hZ^=a=ch1y8!S?jEx%qpQsn>gSldv9gL+;k3w5~Cc4vrC zkk;wm=JtEgT_^VsH@lABm)9r`cK}dd?+s$X-5VY!lZvd!J8IBJy6`-EB564Du(y@@ zo>uR9FI3XQ?9QOzn~8Y!to9FmT+8iWBTXrafFy;jv#A2HbV;fjBqktgrL(#_2gzFG z*KFv#5o)aKwa?=l&WZBfq)mts5K%|h$-eB!>$&_3Pk;l3Xxojf=c%2wtm3Sc^S`}| z1-Fu2fLR=a`Qk&e>K3D`SwIS#xd;lf^?isNG{1QGhmmHGKE@BtQtFp@GPBSSzf0q| z#E$@IhfZ0Y{Bk+Qys&B*RXk3RnKEtesA9&116y_ z3JBi)PboWREaxyt5K9VxVKvx?x}e8|KH}K38l(&`zk6 ztDfkFFO!@r1N}LIb6HC_zszeSo~?xn!kQCO@;CIC`yP{)9PS(}4~+Aq zTH4J}IKWeezUJ9N$gZKveU^izdDF+XFmAj1Z~xTt6R{TSlRpGCklUF&)Q%2AP=wyF zMmdV+({P;Il(xex13SqH--ya>Zyz8f8jC7|{m2S7xnOQXD$+kKsON9Van}rfJ>HJk z4$t&#Wo3`hBENJ?zXxmmp~6M7yvHb$*b#iPe7#~siGqDc|Z#yq-n;c%9Tlu^(lJs6;fr{ zV=HwASUe+wmv^1Vqdj4I@)c{1`QrW1P>=Z6ny}$j>+15b+rPMFV@zHflsR575|y}S z`A9Te^CEu<^~d^NYteVWj03%T_2u3zh;PT<#P(vfK~hkpfUYE~ zbIbn@49^>`I61I&Sl|H%k-0bW(=nto6e!;9WnTH(O!ZCvjpH^HCceFo2Wz2g3g%;`d+Fiw7mUG*~LvN=z4B6={93Jz$ zRNkC>-T3O!UCAYed3iz0RjAEw?zPW9C^~E|yY$?3`=Muy#LfgiV_rM`pzl3jAKK?d zxJeM&$1+0Ow=;4icZ5*&ll9Wt=nkXWwem z73p3}Tj19bSG@mi!@YX?v#+b#1;MXZjynEPyhV14{UeiFtN=}O2Cug8 z7cVmW;?-+axzl&GC#%iuk69bEM>_6wDSH8V-z6qz_a3!6dE#x-;V+*9QEzI;5_~Qt zBtc&rJ?_|TU3mIDGsGl6S95dzR;_1P=Uo*s=P9p>yBfAJ5@T- z{j7W-MKj!ri7p!8TDj+GDfxZkzna`5D~m=U#=U>@#CE-$T6yK14zT?Ca>Wk-1Vlvm zlCz{UGWy1p-4K&USvV?agwP9>5=XRp(f8ez6#P~flBVg!V1}0Y2)n_=_SX+=9c(Z& zjj{$v&v%2}p@V-lg43elmk^WCg)8ui5S1iX;}a7-5J#y0z%pBzWDenOT4@MT+h+n* zVTG)#ru+>=jWewMYuN$C+)G7M!K5W{os6wlYHC1*#*3f)_1lu+OROXmw%~Z&IPT zK++y)1g+3mC}Q`kz!QDT2^&AfnN*pWGF5%oKOZxyY;ieq?L5Ox31`?b@S!sG)$~0R z^Om{pU%L%nMgHl~dF&mFx=-KHsrff(bFS|l9is41{fsQ4Sd(?cLvpw-#cbO2j}H#0 zyC2lA-Esf6)a;%Er}@5yomQ$V-D2P7=Pm7nWy4vTcMV~t7s^e`{?L`kv|vLVoh;tTMUjU+qJR%A{jir*pcpUjcb4MSIA z${zO7h0}{DkpqA2oc{T`#@h*$S6+d;;0;49r`zY<3)%|Cs*q5*;yi?Ew_Ku1&y*nZ z;&*u~9Lt*gs_;C}kdbchm2b8Y^0)pTRr0 z0-<<4J2KnccrStB?~FI8zxaDbZn*hF*Wy5iNw~)!c{^A^hG`e(%u=e+!D$bVbzM(n z>bs$Q50%;$`Bti!`6(to)Y+F*Ufk{7X;O96Ui*Zm^0B*h;A3S&?t}Tp&`^oN zV5=q8h!hK&PvFegb`rbr8-;+AIkJOSKVillY!SGI(iUaC-k02qQ?*u+V&KOV$bp`% zHfITr<%C=0BM2;rXDVYBZJ-2A{!)3yDQ{Kc*gGV*2NQV;z&X)9dmVx58c=v^M$M zS-OTPEn`v{+EEELeTPt?P;rrr!46s4?kBYxF_U1o&&jv74zfdWnOLR0!_kgsxV}FX zRlXa?Q^t2MMb9f9vF?c2!$a9e@8hW6c9VB-;ZlFsrDtA?&YGDtzxFI<0Zmr&Qj_~AjY9}e=iqXr@&!m;cAD$@geB^ zfNTH9@c~?etP)rhoa>i*H(iN}We`QL*s4|v72$_}zgiGer6FdI*WI9HU2Sm#kCdvp zIKrvcZ(gaMV;HDJ;c0wzVykT=HV827)^KmK0xM z;Da%#mwbI(U=KU5mGiKQ);dJI5RA;Q!lm(&^ZoJzVJ;v`H3eGAnkiQR>uKMBDI#L0 zUA5LhdWE5jio&Ixq}?O-a~2z&w@derkkp0YKW4Z4#Kh)14CoGwko8D=A&U+|GT^nC ziCR%Vz_^>hB`MCzpkg-A^sUti*rfks_rlwb;P^_=8&x+YXe0QJ)s&)`4Ns~S;mKrS zrIO6|jZ*7%j_2QIP^xqBTiiHJnxEU>W?48DsT&NJIH+qzxZHnePf(saC7AYg^eom_ zH=N{57V8^ZmIA;J7oU>7zohJg;q7ZBzC<6-Yc4IK#TSOQ)t0Wby@y6|A#+iNMBEfr z=#?s0AYG7^{k7%_okr1??+06De+%fID}f^(=U~v8L8+U>N6x{iRK=vWxIqH~ea=?P zUV%HkAz!*JRLqi^FUg6TZA_50Y&vIdN(XyI+ zQxojK<8QVKlHfqqaGwNJGuBIyHar+kXy{sIyuxjwT&4W{6Zz1{7fcGUe$p3c6~#~4 zW=QlXZRXfe+URHDn?m6|ia>q1W>N`6Rn`IE9L2?K3dhzLv2RK}YR34Wsanrh1Jj86 zz)a`}VvSkzw;uehLh>YQHqoxv^EEzNbnZ$TlED^ zX^-HML~AgfM@C5tI>{2o!klcCIt;GE4Ek&v73pK z)2(&!FDvmS@lPfLNBujMP@A{!PL46`FWs``NSMT8r=d@vmf{^dCC|(kk?O3MryJKc zSZ+78kDj|&lEO%PO|A`WyqG+qo+_Rd>N}|)&gmR{9ntwY*Ya+~TwS#z>#|`sTFp=0 zwPt_Sg$lt}k018yKECj56=-y?v}07IX9ld-AazsIi`}q9L`@~{A`fZc8mpIhxV6An zj=3;?TWTSDya?XWQ}iZEC`Oscn+i>r`apTzo%xg6)K0YOhvtzfWJJWwF#nZkzm}y9 zNw1m)-l(xLI9+=!HEW8!=Cf#5rUyf-t5>OV3Ag|6q zO&^j06we9V`Rq9o2`jbjXuOfzN>6J!^%!|&^5P*vyZkaQ?fQ|;zjNTz=@gS1zq?b{?*4G8YQ~Mz$LTdMmzAdFTAlPhtzO$uYjW%d+dY-o6Rb_h zN8EUcco)I}d!bu)-{cETgG4}@B<^HBSylEx>V>76Sj9k1Vmri0gqjeE69=W|gcKTf ztXL1K+C~)dJRzc|3i_-LiumfB5^v&X5ia90Ypg=6Cs4=N!C^PSJKR1`A0y5h zN;>Qlh}H46@5}s@es}YovI~0{hR?6Yq*N}?iQI3cABnK_T6 zg*@qYFL8CgI9rw{w^qEIq z6MhbeGgKnJ0`~VXNgc6~SR%kGu#=v-s*%E;s(_^DWDi)zbJmta@;$ypBLS;65@yJi z4hm6YE3dF?mzR+5mW_JVaflNN_+^q@$4_?N+`w;h(8>S<9rVCK#=^AVqy?zLIw`P3i<=lclEw)fgA3^-C?nlz0gnS*w|= zvZYijZ0yFOhwUuwq*LWOZokNi*}>l<>LOY?dwa_{SR^7WYQPRcc@FfML*5VExVmvS zZ#b2Q3Y>ww&s~Qp{+5{njfEA+Zpz~3;$>r??JjIREjrJFo|FiUBw6Qe;%Xd&f*3yI zLAM@1?dv|S?^@(vbF2WSA5_w=)ghBOmVS{U)>f>CmA?VM6Ai2)L+m?9Um4CJpl-Uvo? z64ho|h29EM`I10CyCv3~ULAm(2^@*0ZO8o%#oItVPhLEZ$lJ)_=za^kdx}f^o8QK~ zS6V0ZS^#v|ozgu}(*hrw7WMLIV+?U1aK%2x+KBsm0tJFhXu^qClg3E6Sn-RI4CMpP zwSed;q;)Q;PJ2VGT$bkGaxay?gQQZ^TKIdFZ-jaA!D10N=UUKHj236~UCHe`hkc4& zxN$$i>i%}|2WO0n~iPL6sYYoqCot!Qgi(or(hlZXba4f&FI96wk2!a0(idI|9B()}PxUS=3ush| zHuf@V+|34Q3Ko2U16`us`E9fmtg4mCIG6_Lz&ZXP zx(rb2QH$ylZ^xfZ052dzN6m9kt`}}OnI+J{w8=G)@TuOlVY;f&lV9-?emSMh%=#NJ zlwhXIzm@lEUSaT@)s$$P!zgR7UNx2cwPwxlk^?}T1YZ+AsfQ2*=rIuvVx+q9_{uH# zVBtx9XE-*SWs1aiHivQvXyUU0Cw|$C?k0$LQ>rL%-rmQa%E#@r!a@o>^qMaO#DKRL z4!V8BPE@w%QzWRJtw^~T2~C`SiVO((I>@8x?;HE2aS{X4X@p04G|PtydxOgX2A(%Y za;U2JYVx&9lkUZsN&--flezvO8Wz5yAS@+6aHiGH+MuchHn{8 z*W+we8>5^}{_F-Qw7F@5NvBou6BjBc@{hS=mSg5xDyf-=j$isM$WOz@BQEjv^-)n- z(9!#B)mckvMM_Y5`v+XW?GBgjnW>6iB`QyJG|XXYf}Tv*uvU|Lg9v+&^b;~9`3@0@ z^4kfCdCmDZ<;t^Q5{4H!u+t`wzl~vzt`k?nD_Pb?B!A@Glp=Y51jvHZkpjwAU?dnN zKyQ_r(K|<;HQp5U#M@h@)WVmM(Dun-G^aO>0=Y90BQ`e+BclEcFao$yx)?{7D+-{~ z6jeZ&uzoRxQd71Cu-bAxeDnT%IICp?a~`)1lt$|#iVqKx+ypeVR25)Wa?THl8rpj&jQ#yFp)hcti-5Y1wY~T8sKIM#n`cY zA$4I|Y)olCONUb8=+HBY;IPDrUWdD(7bEJIo_0OUpqoVAfj3y02l;qq zX+CeR>p5z5B>J$L`++ILKesV&cKkjSbZeUPh9Takjd}U=Ya=Lj(+A><^DPE09e=b0 zX?LsVpLdTFBqbg3RjH`;KGqfUS>sl@gBG=_&i*-*E;si^;>C&3P$yNQC*1)8q8>sK zUm3PakeDG$JTG>m!lDJJ+x`G_Bda-_atIPv380=D?PxIV@mgSm6q(w{T625id*}iD zfqsj%o2c>XMi%fr(Ag;FcWNe-zHdzX>NaJDyoFI5Z0%A;Gt4LjVYxEml!5xtmKqD8aPhN2^*+3Tf*Q)z7X_$29d%*sSC0u+;Ku)xtpn z=4$=Y=z9gZA~4f%L}D0H9UxVU9Y4XtDVkAqNM1-e%oj|)6ahUI!uPT&YkldD@YQM& zb|+FNP8($HkRCzegst&*EkiMdFOB$#li$D^96A6Gbp&dkwK@nZ2r!u>D;ne67u2GX z1SorpdgyI&(YQ4Fc5EnnC%KnwPUoRFk-wF0c20ge&r)e&A+f@xWZ#<9;+;q<#1^i! z7vVUT^qVdC>TuO?%N0(wv&5{EUN&Q)X z<6wF1r4r-s4>-@|M(uLv{@7Q3Tts;mXBd(j@#oN-;OY1a-pZY8zh8vDl-%QBJX#;C z8yjOxbUAN|bsP6=V{Wl{R&w7SC{2V|^Cgy<&t_bz{XSU;P0A(ah{dad*o6tnS@|&k zse)8ZUljW@Hmo-ZU2j{ziUk&=OXG#&M7Xv0X0(pUQac%o zCS*&EXV`e!gr4{wfLom>?M2{fa(`o>5rTt_1bI{_R={6WknANHAt!{rDdTo+Ollw| z!9q-gvA0OyXd*&CP-kt+@PXHpjRz?tN(gRD(kevtfD*8rlX zu?~PfU@eFk@gSj(g6ts0!?aE` z1fog1o9qQvOqcG(L5=J>b}dDqGXM;TDFU zdfLg-=3LmlIjS5t@4{HTo=IC5n5XG}=ves_&^r@Ym+x}XDnbRNRcc=MZr=IB4%C_o zLuFTnyq2SudG7SBc6R8^p65AgDFA(eQ@2B9GN})JcV+pSi9QpgYAr;CPG9EYaai)5 ztdSkkJ3-~KHCcMZUGm+;Ua>RvOuw}<=|mF}3%vv=EP&(e(Qj`Kh;IP>_926WLr|L7k{$4jl9;@(8WRM-QKSi^i*X~ccArDc-y z(Lb;5Ov6pSbtrbBwHlBPN0|FR^=vriMm>1!>&U{&Uu*VS2(YqLGU%iXTvlK35V7m{ z(qH%hPbS`t0D7t8Q?FXDt8ss=(W?^4JMU5DrNhUbVZW;W0WL5C32|996i;4^pz5}voL6f~6i@*_YVx*66< z_y&iS592=J(e-Ru;otgGGOs|r2g;a#f?Qweg0N%Ga>v-e4_nU^pm+e=pQhsZMtnbv z%~$lH6*BWP&|JQI>;L5hx%R*Md)75%U`JDp^gG08DgfI_#z2Aj!tP!)t08`>)l~=W z^&IR=N;^DP5Pj)Wyb&V3^Fn!Vx^^pW8hDpIs0`$z z9C8ll+Uz{;()D@n%h%cV$3cFmUqd{~2LCAEb*d}Z_gcAf*h{Cwd9%8hZ6=qSw@=&; z@-zLd%>9r1vt91^>3cDngI{O6j=GfFM=`8@jM`nZdvYm);u`i0oBWo71kUiKzr6*u z#&XPGYiuN95Tx2yY=M)VEi2;@ef9VIls*rvbk8fw=R@qFcO~+h6%;|piEjBL(yyNx z(xXEoGL5Bi3}}$P2TT8+W;S80-!C<|i7pyhR54ZK?LBIvPc!w*_AYh3Z97NOOR=*x z>>_^q3w~zRpl0tIH^)m43Su2EKn715!)1QgNXK&;LX*n|-ZCuLX>Lf)1K!R;C@B974qm8+bno^GZaVJe< zv!&$$re?KoZpC1==k;>W>T^TouD)F{hUdDXa^?-rHS&Lo-(K!kVqc_r-hI|3$-p(q zqhxcm@Zlz#XqWVJCcgp2=hy%LSWIP5E?~bZ$tTfb3VjD<*^8vYtgjUEM^WeWC0wPrE+uQmH? zB@O`R%$9=hhhl`5|DKl}?r$K~{+AMSaPd0iwlK64tDa{sB9ofoSyFyoW;#g8)F zpFn^9@ITlxe=}zO6aT=dQzXK6ieMmebyJR}C*KH3p28yES7-4uNfyHQ@t%VUSZvW?_56afnXJF(Z5_HSRRpQ&7Z;seYtFN2`C^*I6aF^-IR z(JiYh2CUhYV_^Tzu}7Te7XEQ$khoF$LZ=kuT1%;H=`zTQ$%X&&B_pSF>+(EGUm+NE zaIR`~ONwzBAJG%Xmt?3Yn$)CH7A>!N{l9u+C3E*eWs1O9(_GNPe(?ce3I5N$E2C7< z*&fFS!udb91X-k#*Yjehj$1kIyQ4xx3D^3)qpO8+?4C>939w=KzE78Qf81kK=y;p- zCKUJHtJKBsJmV(Eaj@jhkI?bG48aDmCVh7s?Z{Yp@Xi@A_rB-0t7L**njCW&dB}bPe^>#*Zs`ONn>47+b}ch&5UQBYSN*(YAdrX+0okt zPJLJJ*LtUvcE6TYI@UkR=M!V^g?PUUNjRfJ>kx$tps|C#O6nfN(Tvo}`|U529>2I< zu5G3q)+o9W{6(D9&=BOsvdocf#=^OA<4}>ULfT%tFK>2a-6z#6DF3P_0yGQeBDEAujjiMxq`0TDJCul%T0)ETX#Qx$m3Yzn z_ajoZ)%iASvwUGF7o2!k(b*=Zv`uFuE)h3A=A%0g8gZNXDbfS^bVbskNln04DaA!V zQj5lcs{npQPL@xyw@C?5yudEqdjEU*5Uvih&;}i~gHozXrKd-%PmhG(otQB8E7K@IMVO&G&={L>`vURVeV~am{9Y8SiP9Jva zE@kb2(2nPTRRkE-ZHZz+fE~!8x9rJpdnDh3);VQiNrc&q@NJM}cuBCxlx|0P3`vhq z^(yy58IFV2CK0RXn@fz0_SlshfKf5w5I=v=p7Up=5bs)9=oACjm!Cnm!AV7zOI_Og zv%~Kj|2}m8&*9D4`bw$Y6=&vEOP0GfJ0I~la6zDr9rfZDoovW8k zV!hO8$!2#v-OE79;2x!It9iJ?r5KHJYB8{XqFZE1o;Z}#A%8}~$*SaLq+_z;mSD+g ze{#2&zv&Ahd7A6X=k_Q7^)SH$q9!oB03FYswOd1$cyi4bvW%8pU=XdSYnbA2FLXc; z;x;y;(q0!_eHdL3{Y&E=GhFXR@Jak4fB%W({R~ddU+7>owHvg2V?r&H?tOuP`hP>} z%a;7k`RXh?dxZLc_}EjZ|P2DZ+xsM1ufd^m}Ce(d(s-M@Mi zY^|(iJ{Y#uQZv5b!2i0|%H#nGiX9QKmarL7;_;uwO4VM91qdH%TzVDju#ZlwY6%rk z0Pm|D>40}E$GlXFEtv^4?zcWd(sEXw|0UqG7S}Q>`OQ5IAr*|;Nk0NxYz&pJ#8L$x zO$~V;AT<;|K{#$uUXBPeMw2VY18u#NXgdTP8aE9V?;Vr|!~q%^kB8R$SfA7Y@5@S| z$3r+V5g7rhU?+MMoRFWb(KDJddU^@xXr~Bzk&}7Y@cy-0&VYCLV7r5g1KQ1m>&koE zF(v$CZeJ2}i+i{*+&y_qyT{?@HulFzPfC?ra!k4pBL{4~^*vdJH7A=P2F=_41zEQS zrJlr0?)0cPIOqP5R^oZB+P>QVpye_9^y|#5WXe1GdP>_lD|{rh8*E@yDh@=-lw}1krYx2OXqqlQ%58`Ih1e&bN z&tZkMm?f0-dt~cF#EsWz4Rm8)xAxVy>a`6A?t!l+md|+6Ra#C~;4O+x`UvEW}jZ12A*3 z8{&8RPUZ-}%)HH>r7UbZ5P+5Yl?ik&aKI)_X0|0FK# z54PH8eDa3c1LUZFPI;0$lso%p14Odp9!qaHgkY=P<-d2e)+nL8jx+MR(QTgDIBMQ* zJEg=&we=uH1P{FakeN)h^*@zal0@usP}@AZ!Ho)SV_G>zL<_VhG&HYP8|$2N<0KeO z5yta{v7PL#(%@R;jKqA7wGDX>VTE>7mNt+parzSMfSi=sL?^&CG`Os^J-cG z3r+&wi`Ir)Pu@WS+u~Lp_zY+{E(3Bkgw|QCh){tIz#G5_Y*$4jLOO?@PCi*TD76sq zx6cpj?(Ey`oIIi^z$tfc_yBO=Qkw;eqSOdJBfk3vB zN=ghx37O^7UKoDy zdJX!wC}R)H?VqF`R*wFB{qk&X&^0mhRFySaaujWwtl3aY@nvRlJyu!DdFzb0q7z}k zW0x2XTV^iIT{^lYP)Rv&4=c!)7&ly+#H}*MUz`zLc>jabJ_C2gW;M(LOuXv#b4#4$ zg!~OwdGU%_K!|X}u`m#9SmwH!g1GzGab``Xxf-%^6MGpw&hKE?VHQtT%tDxUb|$4( zw+S{SorjwMs1pUmqpfzsI9rIHLh^vo9M)!Nj{F@msQgWRKH+kkMO?!^ODq#HkjRmFy{NJAx8YI%(N- zs9V>17}Q?OZF4|1%{rIzuz|huhf0u-k z{Q9g7$e_2SZ2c{f9@q>s+6ZfiCj@!9LiR2a(SeTGA7ojRyb=YA1Mj_wbCZ5WVQ&sh z-@yt@JoHm~;JE#vxwbCcx8h?ahrH>?*-D4e(-@WHxb*g5^@;{7tEZ!Lam5x}le?jN z^}F)ielxNW&Gw?)j2PUwbs2dmHN)G#R|b#1cDiC5;O}3$<>Y}2*WwxtbIqJwi+oLm z^R68{<2%@kXmPi!T)u%w7h_@lMU04Y3#%eWk^3jtz)P7ejwSLp{MyjPgQyO|H|!Mh z_HgXB`rd_;*mgj_K*Uc*ASWFc!U9YQqa8sqK-;6MUA~|!)+n7;GvfS>P?p3 z1k&p_XtfV|**4zvvl(U^dOQDBjH20A+fRP)PX`u?-y(Ju2w$|aPzYHFdTI4bDXUWU zGmFJ}!B$jfGYb@%il&o_{ma-C{zkc$HxVe>&R5JZE9@TPh>4ERLtYF;ckh3xQZ*7{ zmpv?kp9ti-4Qti*#!}>5-?h zGAqTXsij@=4$J(-Q&1?6WrP%o&VJc?AfgY6ck0t<^Rl)c2+9H4#1@~kxWdZm7b)w$ zvCP2m{=DnY__qCY3p7R>th*c%oHJ6aak!(!QS)ofI`iyvsqIxi;s>)gv!Z$pj~O#| zWk1XgxY-7V2NynHesi06-+YHpaZGBKrt2%gT=3Af9FCxtsBL^LSMO%e^%;0A(+|Ux zfBm^juuQ2Ax_0L?YUZdwVNnTiN}M}rVT9x|Ops0?y`mFrHIsW$ z!iGl3JV(f1N5Tw5d&hL2RFv90L001zH9!72aBh(LY8d;}E6I90d5HaNI?>7l0^q-; z2LZ?eDI9jb#WIq2(4TfTNz|l2Aub|HiuE@s0a{#54A;>}T#RrSNTEY>V#jKdX8tXb zpFqdCZME`L#OlYKstImm#zSb`6mC%onvzej>j(>4LR2F58M_3W|f)knbnfb*yADkvdS}$&F`jBs{4$sT5v`ZO3k3 z*15jqm|lBqA=uZ4ThU*n?dfwHwhpq*TU+Trn(1`(Am_rxKo5O8rOk2X&Rk-;eUXnx zQbpfybtH4kxMf3xWUhqiW}IdW!R~{HcV2#CR{MO;q-e8|qOU7Ycx`Z|zd9@VGEXh< zd_ne(`xRXtb+2o(1GJko@@;NdEChpWiiS04@^9pAETxgEW!iWYsJtFoX*~d9pbTou zHj;wi1Um(%P}r%_jLu|-vD0hE{g9}(;!V)i#E4&g0Y|uRY_{NUP?sv#>gd!~J$E+M zr@0?I-}$d&AQxYmV{gJv72_aV;4M;5`I)>Wtbk7=>yMHC2YYV<)kOZSi=wuo3`S*= zF|DX5qbQRQl2%%1K#0tfkVZr%F)AQYLP|kE=57&C6w-=-h!BxU5fdQ{t%%4N0VO0j zFiMp|D9PaadCoiMzW+Vlcb)s*J!idhuWP|#tt?WhRQ+o2{rmQ}zYlN>pvYn_)M5_A zYe`Cy9im_RXo?hCB)KjBER;G|EHnioCV`Py2j$qahUbF?o!08a-b%x&GSWl=GwU*U zZlb?j=G7g_ol9*F89Ewf$|b(;I&uxNIx@7uE8|d&XIoEO+R<-qe z|Dm?rZdY4>%h=SfFzHZ7;0d^5Cf7GxKD}bcK&3;H@2j&)5A}L)!LJw`C_55H3cOk^*)hJ0B0`@MZ#ZSv@hDv0iX~N}cRekY_&qn zNu@KJFUMD&&FrsqeZ6q>_4{`^r=~p0Jz6}%or}vH6n~s@a63`#cx|XBG3U5R`De#V z1+|;H4Be}`)lhRGPP9Q>R4IxI25o(M5>0uMzJVHZTXX;^%^Z7-3vE88(02n;;b*JG&88ocl3~-`gHmkqmPDFN8eEuz}&GKjA;Y?;;ggoB*nV9 z)P@35`n;7BnGa&AaIffaugKsgx_Ia%kVqG6^X3wn2H(oN1e)sP+4tqV?6sx?DeUgG z=;0oH69XOF`ZRg1mf;pc@kDu&nn{sTUy1XzC%in&4?O3c6r5U1$MSnuycC&?Wbf@Z zt8Tlzy>+iTOVe&>|K3o<;wsKD_v|Oiv-^zn&;aLSmElc!Zw3c{@!Bc)HZi8j;||wE0eq!o=C5tl%=$X{GnOAxOoi4qb^~`MJwNOg7f4?4v6dT4hL|RS13k{s zll>*0nGPq)ZCQl+5(``Ria6hc#csoWmrj(=Ztp8|piX}7Et5Ibv`Mih)AwGXLze+t~#NW(yFuBv*SK(0TaNL5@7_&*WxnuQQQhG*C zwxQ~Dif5flCEj(Cuh&bjEAg$f%!&!OygcQsAjrL(8-5)LKeXWf_RcfWfMUt>H$#pG z`l4r5ocreEvBdje>27=0cc8bna#ydcyp>bm-5;|CJBWQVkwIz0FP^;^-dC}l8fXKjp5S|i@W$38C0P~qBZ!gm+Hb7JMuB9 z(GN}iwH<0$InE%d))kW4m)_+#N7j*5rW*58$@~X{j4DR(e53CBT!*x~y@l>mb*>Qw zH)C#CdK6r1%BgU^H95dp{OvkVuiXh(yuuZWp|s zk}!l{S+B~#G+8SoFY-tC2z5m(QBy>_4kp{(%4{>#FNgMC2O!U~W{e!*>r!!m&1}cDAe@?{R zlVHiRO+*KQp==t^YGC_-=U3v$xWAoIUfh0t|GrE)oH50YD8DaRIlJ!ZC*K8a8+ixC z?QXf@U*a7GtP9mnl&QLx?>W_`qZ9PD0ydXBd~#!k)1j46WE#Uy$-l2F>g>)!>VBU= zhKp-)cA3N45}y~RGA(Rzy{FUg<^X{XLvMiL1tp;QkX!>c$)bEa(QaZJX33&rPGnjH zI23Oig`3m*#1uYpY0VRem+~WMV+ZChoo`{yF9RD__TU-7bUo!oA^~g0*$W2Gt&yl(C`JuMWMQ{H&z1bMM)l z=Yy9z*Bx<8N^?`#2^k=@Vm6?dzJDl*D729$8Z#U!aa$_7F)|kVYh@Haq`7Mc9JkOg zQ`?>U3-7j$Zd#}e zqdCoI`8 zoDWMj_woOml)@D()0 z*q|}=184|NMtq}>+9QjSOASI$&hY?QApu}E^L3Nr)A^tJg~cF}rwc7vpIw2?0N@M$ zi4E@|DM5dI1_WLz9uF+RJpo%8q!M!$>>LhQ92SykLm>S?~^UNa^8PuQt+O z|37+|n9Z8cWsQ9M%JM+w3|y}gh8-siG9We*L|32?FG)BFRs1UTWyP$o9-r|yZx9*l zba0m(xU=7mle{Qd1HN4^r+B)Sl~?u#D>*=@srV{oY9x|@MCS#SN{H9ryy5R|!NM@9 z)9vH8+lCziocDr!$;$ticWq*6*63aNq8*@|U}iv%vda-zR?xpn{TN@dpX%{9w;J4; z_TPk?@A2s$Q_=t0__Xi|v}Z^O*gC>_Rv2-}ZtQ&yNXZAp z4IgpFNS{QdOtiIOIGasCw;dQ36aoe6jwimcY0+5J&ajd-R+v{1UpBlT`*0Ho)V1@E zNwdn~zYoPHoZ!g)O|T^Rf6sIOcd79`&wa0(zSm8ES8RQ+o4(iK-|O)Iwy&%Eiy2pw z?!T^?0zM0O(z<+OXF7NUjnH*eH?#x+qXrv*tXe*xDQ7XYMZXf0UIG^kEn~#?Do?B? zu-C`S0})9A{P{p%WOTP&m~x((CHB0@y#&>xjd>s6pV@{(um7xPYn*l|+-vcYzuM%s zn82NN+nrsnB|76Oa-TkWgRl0_E&;^H>U{#1(Vwg+Y)LzP9W*)ok>xS{ z-@kN@@XJ3=icDWbBfm;*Rsl@tnKgjbb91`kkLCZXCx-t=$NP(G$NK57uk`j6^Z%)* z_8+iNn@ED+kX1E2!Vnj5*{FMN9}3gj1aq39w16L9#zgF^h$)%2G(W%a#?G-n@@nqD zaeYSR9}h3wzn{9<)jeyqbgc_18@r5fxJ$MJS}u{LjJL9Cxw8vr_ykqzHZ+R=mTvxi# zL!nP_3-l{;f5MjZd%e#V?Zlk_DmC$zMV=E8iNiTxrHVYT@Dn`XQ5Rnlvsj2VA)F{V z|r1 zO_D9i6Y|X%WueByKB3SW)48=_zw5IPTr!nRv3TdG7|^`kDuf{ZSz146pH}1!f>}6# z?KkcHW|r3-fIbx-n+`BS;|(90p9j*Uk`ZieCg@gERn1f9>tBlOjgn%nF)r?!vRpB} zq-T~>X_k93JjU8WoVNI)LHtH4UI;6U&84tHSP66)rZmOvASWgpBias33UO;nr;BzB z7%s3BDd%x}O8mn5DCw=kUGp`g;Y@90W&iGJ%a6q;^*ZD3aQ$B!YaNxYq;PIVk-CHbpmc#ZsP=*0IIG&UVfKbFDuSf> zt?k&-Qr|1tD(N%xB*6!bhF7%Zkyc7p4pa4z93ZVtKKJ5b*-#kJBHKazsUNpu{F+c! z4>UmmbZp}c2bLJi))uYT# zHl^*bznb085jN6}n5^9Gg94uyt1>2@$<$W#o;e?Ie;lU z9YG5Ew2VR=FHPZLe|Uw;I>RhBCKGQ6zx$Bly4X&VWh#Zzw8Ud2QE0}>l-Vowx1C8|z-ZU|lw4q5oPKcF^oc6-XF|8^4WYGm{;&@0) zx|5Zi+J|=X+6mv-1e)=L){i~Z{jnt!zm7qsVefGkK7UMS)&L89KP57Ik>Yl&78F5G z1j8UA2(}XhacJ8_E5sQhRURR;NFQMU^@J?i7I8ImwMZ9r;<;2zFu?&8kPu!zsDxm; z3;bbLfpAeofKzzH><{R*@oelBiRKh%X*99KKB}*hBu^aPf%`0< zQG%zQLJ2&h3j_^7`{i`dwsDRzWgG&8v6sttyxit7pA-tS|fbPPv(}j znIyk(td!ngBnle@201&T8ACPWI&5+xO&V?HKQ}l}`3q}tlW=A>H8o6ffaLL<7UmN&I)UZ-IrTy^9FCNGG zOj`SH6pnqlLr3-U+qjCfrv=v*u9kgxSUuCS7q~1M~kC|!X$FC5irr0D~ z@0#|3f##JF&j{5^X{+>mLfib(pl&_p;(H)E7twZ_ruleZgNwiIE^ZZm6Z%z37#%@S zlNeGhP;H@_NR`9X5*d(Eew$>eK%to7{Bh|g>PBhiOf%RcKW)JWuMx^zFHUBKYAX2m z;#8n0^Q1blEk>);fY}f}$T2g^QAscY)K3-EO>iCEDwKtq_kT0xQ=@nZUc>a6T-Zw> zjVhJWUYxa?E#u9-x&+V=HRmQER-6OEy=o{;0j(3t4Ta;Ski4s<6gLpN@;>ZCI9W~m z5xspyZWR%yfs%fziQlZ(G;!n<7TpE`3H4%N)y3v!L-*%qf`Pi~emFK;qD>q8Dy50n zqdgu_ zlGF=3cqOTfO!u|;GY2V8`RPWQdXe#&(o=CUPpi;W ztuEJNBX0*M{}r?r2f)RZH&7oi{P{@~ipmOCNM4R=_n0y+2I#&t&Hh313W#Dbwa_Zz zlS`xAX~}vto{(h1LbowlHz^HZvbFCJ#ksF_*n}oiha~ug_P#;AoCf{e2TTKO1mHPK zI7jQDuc`ei^{QsvAAp(Xg>DmIgk+OZ%QPX2AWtg+V8S#akD|lVIZF}k}Z2|^rBO>Ext{cS8ZeY7TWcXUv7D+kxRPEW+=1p7b$2(5;&HqB6YJ z!vPiHcS|Sb1^dKVZfr8Zy`VgFW%y=URk=gMHP`j;Jj)kETa3v2mTY%anyvQnG<4s= zKLKAjayyr}xas+8TSifgeX3P26Lr@E;mN;W`GxP*i z76{#@0`X$OdUTObUKh$#9hB%rkT4>vG5^y}yFnD-Sz}v$yK?jLIKK4E=m$8fusZ=G zFMfs1k|Lvy{|*w@qD0o5Z{T)NoNj8A84J8zo3@61Gx{A_!3Q6A61EXw#8uQVnBfWA zHP1RP^19jLxaQ%(eE8b<UTa1EI?Sgji~U7ibq!cR)j$_`CS^}#rqnU z%q44VZjDg)57M^L`U5l`!EGHgi{KLyuq#=CtfB1ofHklI1H^-5)<%hz39ljM&XB^Ozt568*C7MS-gxBk&>-%*Mmua@@Xz3UTdqZu7YPU~WTCF&$x zFX_BLVt5tV-NJ3a%xneL2qB&|Fd+r6N2%b)&XfyxPtlcdU>;deAg=lq)@k7`r~W)Z z+eOuD1k&Ggt0s$#3-lPty_DUpz|Edmh8`zhOh+&-k@C)k$E=?Gy8ZBNPtWINUYZ#t zo)=E8e_qn|CFKXtHsZQslI|b(hc&EIUX+g)sd@XlJU3Q-yg$9u*h5brr)*enrQ)h2 zz8>~YCQEjOYhjqJJFkUu+$c-QIxmfo!@5uPW&$ z)j%00g(`gW*&>!aO_uhjS%AL3mY)#lCX5SMk??rSS(S^mPCvg1YXA#H8s`^R8NpI8 zIdg+mU(-j^MDM5?#4MBXeM37g>4sn@kV@#aT%fwZ<%21=6i_xeauuoOq+xRpn0NuV zU+6_^V*z)Q;!z#MD|w~~4C-B63ds-|AVhw*NYT+2Zb$;MjH!6t(Kkbs5U^s-QP+=^ z_3?T?Wc7a8R2^|(gfJ8|mM_|wKjSAnIDwU;s=|xy0;rxi!#cy`Uf{~)w*s?OP>_lC zej7SisfVhUh&+(RW_ltpzA|d{!LOgv!d1i0zu%NM{~0kWyMgMpEYh~Vq$-t6Dvz2V zeUysQLVfG-p=~QvVM$Tn-dxWcPEk3AOYr7Krx4HIg;p(slAfI>bgqR1Y|S)9dXrpfG@` zk=8{6m524c)WC8{_vlJg6S_rpMvgL>*q-^hl=`KZ#Z;UhU(>m}xdFccu9k2v4SsgI z21fB7MGz{WBSypFp9S@3$Q@D0J(MusokW*2?cO+bg1VYR+r+#UbXOFGnk!$u`5Fxx zXVS-By#p3dalCA;DV4KBaDI~H$FO1ZjN>As(oo6Hrrx{9a2{p8&1f(%e}9h-9f#e-vM0s#45bnK~emky`1prKo>7C9X}Phjxw6q5DNd z;V&qo%~I>}*i))aFrS>rk^|cOah~wyoj|py>vb=elIxDcr&FCQJZ`;Vt%g(`k90_VOQUFE6*&~%?%H#u#*ocxZ&V&eF~=-cx?Z%(}pIW zH9CxM7VizbKeGkF*)2FJy7(vpT~n$53cpGSeP$WZekP5uzG**mBzHjYHWdU@LxfV$ zpI(Bwf0FF01Co8Lu}mpi^1mobd%d&Eg5I7+QpB0~AA!_$-5Xj3=ij_0Mf;6v1_Zce zTOh#?_rFT@#Efv(!y}TPjljBpwV@LT4Rgr?m8cK&^e(Lzw2;Z55`-4~DOt>O ze<{)TQd;`kM&W6dq>Cl^NrHi9j0?E+W8EpkR%q;#fOT+30*@95qC;bA|ysw(&s zwy;Oap2F@Q2BS zp3r4tAl2!jl`m_%*Hg_AZjvc|6?B9v+J{_e>K9?+c#lI`eQA$liqUHa2Td-{9*dNu z-OSe&9K7-Dagt>~OQE_^uye{|;T76DWxaNQ%xr&K!Jy;f-X;H=W7t(NYuY4PMCf*=@MBVY)(4~bTwjyEM; zzVFXhq9hkol}BGriEUxYk@h277X~XTM|>%E?9*zVzn2~gR~uO1UfkMW+Zku=gtN0k z)71Z5c-%1l{_zUQ8Wm9bwe_rGm=z0UBwd6JrmS_-`J-Ea11rsnx)apzvr33gz+jzX zgJb6#GC!r`8X0gA)|*CcuTRaBw`pB8d-?2W!Ro_#@87)>E8o1fSTWeC{ybi%+T4f-{bhrL$micxRf|taLtsncF4W$Vz28SKA2GES*aWG zy3DoGqFqU6rK*KLmVEN zO;VYBw=IiOC9)pxPNAv7tW1$XIorhLF_XcgubZ?idH93PnTxRYSt+tO3Y}-&09%{H=J53$*Q2MNlS!hCJ1}ua9`I z*OUEZNjgomyCN(=p~hd&vCpKf?xleVx{6-r?el}sw4~|eLXkWGK(R)4MBhEL(~aKK$`LpWRGb1`od>aVJNm;mFcNo(Ct! zKce;0GQN^xz-yzO-CkDzLVz#_~2S(YS zK6qhY<$Zf!L7MwyZ>G$N`)|u^mBKig8|`>W+c_l;wP9`Bb!*G}?VZ<0@aVu3*BD?& zg)}pS)rv`_uO}SF43YVaR#F-X z=&ik7JFDQF+{yMe7%b#fTK@d7@m{Y%)q=cj9K)@Lbp$)q$!7h4*OYV(W7t-j>SNh0 zWJM7Hp|crMVFh#P`q5k&G?5q5TByhWaL&*~I30i1I&6k&imdp#x9*YChB>!~FF!QY zWbbA69T!>jh8fKlDweZ?G;rG`QycAnElWxwoU#ae$LxC7%WgMw4?Y)N9`E4ZAD}YS zCs<40a_rrld%17Gf-hsk)IeUHF7C*6B}J~|vJ&nW{eT)Ei)@Kz|J%VP!VPK!>NiGCD=6X1 z%_YgR)rLibJ_f^XviCK~U}w7mzeds>u%0YMU5;A8HDj^oMm!#K{F({U5-i1$S9Zbg zP=9fKip!uMu&n4c@!vSrfcW^d#ofMURQJX%>{w3M=H_)ox0@GfbHhSH)X2!lsW|5F z=!;QK-e~V=d+x(IaP^r4#mBkgo3s~;ZyPH-@P4FWcgdMUH-Qra z_+2s18g5w=6X^x^Q%47IHi0+MM7~aH&|oE)8YZu&ct$#F?&gs*7aY~&z|xnSDzGg! ztz#BPMpEi4V+FAf5>&Tj4x4mj14JA+7m6ezP~x#W5fFl|H43taVA zB4z3R^b+R6NhMgM_uCz%ih~|I(WM;saOZ+T;_TgCI<8;Cz3i#;y7#g9TQ;c=?=X6A zNXQ63nH4*$t#&=9led;q{>es&HKgmGVRUMpc|pC?S>T$>*v8HMt4}BJoY378h^7tk z-l1TPcD*@UqBM^sbpVm`<3@l|9|3&|=@7~gKEKZg4s2hvyufSZX8LC#q7L-3jM}l1 z;}ZZZHy`W%B1S>GIwgM`^Hs_`X6mxbf(R0?0+c?uv;oXZX|-gFzLbEV&6C*uyH7RW=+WUYd+EEEAl9YSJK+8A`8hZf!{tkjmML?N|z*^6OKZyc?m%_(v)Qu+hRf^8N z$VJc4c7B!m92-!+{~y0i;0(wk-327n5c~EFNwkBt3hJI~C5v#ZjnJ1z#S%qsBH_a# z-&~?a${>i|aPGL+aS$+Or=AY3UjbKiCGPvh_&@PtFm6Ie!Wh`G`TB;ld5k+%*@)wK z*7>s6(*^D2j47AUB}_X}V^YoZLSubhEOf`et#mT)biH!vr%z|J>l%{R3AGPe+?in= zA%EGj)FIAe3~K|aRz|DZ7iVjR-})A%!n1V|mS-fyKc`;AXzYRa%$aLnqc**+eqYB3 zjvK;4yl4;nu6JchtGiR8LM)oMms`A7#pqqiynOvk$+I`JU3$m6%WmIH6KP1Y{}0KFi1On*PDnQYbyT?TU>(m%$92HyT^6_f zB|tz)hq_O0-m7@9;?JK?-dyQ2`RytG@1M5&tfSm7=Hzp9!G5MP&=;4#;Z@67C?#jK z^>)=bL?hk>(Ub2jUb&UYECjCJx3Qo)W7Ec`w#FH*89|Dd?6+L9Lk#_#3lBV6wx{pH z2b{8U)ODV!!>L@EszI1L=44>JIm=`)N6s%UnxsoIP}% z9y*`OB46)Izy9Xkw(^#B&Q5i!ZS{V+#fpRT4D9_;^wSI=taD5!)z{APoe2Eo)Id*b_LPA5BGa*rRJ+&Qg7slJP&H;eF#?S->Q~1W7q3@*jKjSeuPEtZ728mQXnC#?kZ} zQDPozI-ArOF>=EM8a|~?%cF_Kp0{2V2K?4$;=|EBH~z5{F%vN}Q?p zm3Hnqu5OwOPAF5jkX8<%v*So8&pMs>;`e`VViO3nba}T3R(|-HCnr5n*wL^&DrvYUyQV$ zExpDo+=opXU4>|@@E#BuGyx$d`AE1zuogJfk~2rGS?E*5TtG+3LQ7HfAQS`*GX#C8 zif}h2;aPVxNl~&1?FOq+#;qAN-A%fazDg;UzN~$-fx8zeYhxv;Ev9$PW#G*DP72P5 zhz@5xy%8q4Dm+Y85Cggu-qq zprBH;6;0>++we@wQlq)+s1%ePT=8a7jg%x(87HM#nzQN4xc(@)MWWx>FNzv}6f%O6 z;S?K~HM@g9mo8w{q_jdq9|U{ESyX?p9+fF>PezqdCxp<}xH!9B=r8&O&dY^6I)Hbt zq68SGtgVIAC^@zOx-wesKdpvOGG`m5SVoq$k+eknk;S(3M-fj=D*Xajh_>yQLg@?# z3squrO}Y5wXLt5X9(6EFN4a`I*P&Delf;+1lx4o-`R20OlFY7CI6PsE+LhO0mxXt( zxwtz8>;dx5J7|N^h5HN6MVd!dv+VK%@425)y!XuF*#fWd{YG50UY~1=-`3|Lxy`{} z0$frn-$E+5y$D$l19ym&x|^XDrWkdqH(Zv`v2X7x10;V&k`PqPaJl{8i3VV|dvkBja{iO>2a9 z6GfWhKP1+Y7oPO{-AO6ua8a<|_*@$XM9&p86_HgF>K6|Sd4x9ZsxZ8E&4WIsDdq6E zdu`4*#4cwl+ZUr4Z-moIlIK!2drT`2e|}$S1r{b&vh20w1s0?q@(tn7c6>}4y*9Q3 zn+jGd(~#B*feE^>!c%jCKM)=8TFA(opr0F^?e@aq`Oo!xS1#FMkEL&ErKic7qtjtfQE}d+HS_&QNZg;HAC}#iG@$z}#?5-Jqi=(fO+4@|H zi)!)Awq!TImt^Qs=Zo(aGd? zucvTt$A{lac6gO!=1H4Bg%x+$x`(xUPi-8od7tH1pdZqtBT}+y;nsXhTNxy|CNCZ) z^Q5G^AivpYC0Zd+0Pr&F$Xo`u26NGrn_48_H_uIGZV{)^RKiGVz%YB;08NK-&AT7s zEl0}OlgGf&-a3-EFFM|O)>={!@q`oxka4Q_sa zF)^XVYRoGJAurC+W3gPg(KENOw@hXCumOu8S^!I~uu z6UMo%~@3aa*rq4rju^*CwVexyI_{e$i>Lisy)bTMt> z{euj@%ux5|VV>e2n$x+NpnheG6r$IuPQ6k6{3z;O(hhT7zPu}pl z86JNBkw4648y4xvmX7*W&@#Mwd1Y$?Z{Hz!=V@t;7RuS`x>Q_j-_A#5n7WmrE%f@B zlXRbVmqU5?YA4$jcQqL*Y%k8|l~bK}DFyjItKB&t;a=tt)xzUXvSo@L6w6(5*8pIg z5a^uiS>axhT6L#GCB2fQbg?qv#(qW5j_v0O0Bw@%PsUnH~@LVf4#q14sCLjK$?Ar0IJGQ#civDUt_s@wfOFsly4=_!j zW}g^>3>CzIgiBQWl;(oGlCfDUf7I&_N`5<6owk)C`(#udc?axN0wa;#ZFoyKg)Q`1 z__;?SPu=LG*U<>IlGiR_K!b8r8Jy`ZlIXCwgr-0nIwb)W{wiFkHtG^pJWZ%Sor3sc zvhZq+^cJ;{EGUFLR4kBd=%MLMaOF+RdqrV)A@)AW%Ox`wV$<4~ovk6-`4G;2QVZvm zjAQa=S%9d?x*!yRE|N`02y&tm zppJ|KIlrB(3|gbK;!=@C|7OrNY$cpm%WsKS=Ti%;+i$GQPr(~d65cP44KhCMIa{96 z7KrR(w^V6WnVC)tw;xRFyuEMNQX&I;yRR~5pj@q1mj~}=s3{Gu8L$4*y6d&a0h-4m zrQEgkSLIbo6))RuR_gC6v>&Y0aNb3UJL>JbOY%}c`O@xv=3qrYk}lfRNO>Ck(9O`V9r<8=aqFVo@6&y$w1ys?or~Va6Usn(yP7e5oa-dd?)Xt0B_UxhM)kVt+wnN=3WC6>Ni~Q1jL$PV=ml#{=XtQ>SmCyRUnLNDi$76=We= zDEt-V0&z*5ff49b(y*lcw;Yk0@x?ZR2GtjmMh|!JBndRhZLVAe$&?e0Tnu93HFbh;dZ#Q_-mSSkDY?&k)fHYzCqqcExV z$@0H)v_C5U!i|LIJ1bYYFSoAR_7_^a(WwJ1SN%HW6?A@LrE8paPr~lneKu z+0JlxtF_7@IQ(f;iLYo^->;8E_t7vOX=Kwk<~6F*ItYl~M`&a;q6)2h}#ikDe* zMU)nL^MUXVbaVO+-9mx7-HATQmDP1lGa2FtBByP zi8k7ZR@lIc2@>`4er6j_Q>7)(46l;Vz4sTBNe^B+eJ#J(De#S<_S0$p4)+c|9MHWc z6$yS%(T_Y}l9RV~pV-(`=*~zjDR>$WFo2b6g9d+y zOM%5ODT$@XIyyJJLXbNMW=`x9_adxB@F?i( zj^YE}I9emP#k_}Kb5DF{0a{NPcZWrdt+W+Df_!x_T74&spfdI{IvazAe_%V^O!Bq3 z%U&OltE2ny#hC=}@Z3`wmL(cTb&{%0j7eVQ3DNzNf$-=X&x5Y)gI(3$(A_&VT@^uf z?@CD0IX%Ux6_`74smiW$-#qLd#%y??u}0X&F>$>**14>{eSqC0^T$Y@jzTUkKr72o z@zY&Hk^nO+Ki-|mS_KN#tJwSW*12@7sz@3JrcCFX{Kp>KHA_^)^-WtrcExH?ZG;X! zRM!Cl&y@llLTBTIzlzjzo)qYzCmAM$%u!v0F47lolF0Z|76Sm8z^l3Z_Ha0J$S?=^ z#6<}b#mP9QQcQW5nN6y}aNAd@W5gt^0^T@)5+OK%_LWUBH^C%! zrQiOVzL>f6QRB=71_m9XYBd6amQzd_#kSKC?v4XXD8d#ceA}x_2AO7JI@5wGC8p!# z!}#94KEK29=R7)=|`nbCM#uv5513UB$4!y5DJ8;LL&byali2c)8 z@$<^e=fT|4YZ3wm)1NZS(qG(IxcDqnTEE%7weR`vV-2gA)+wIiQd1)hRBue0 zT`2n#%7N!v2(X7y7Ty$%uafjZ_4ys0bE+d~oWK^&TukjgN3{c!JY)H@+T-fvWSS~s zU7rLMqunmZhg8$6O~KYx$&%%DJ*F#>-{-T}Le0O>mP|q~F_}AlfaoC$vWRE6tbJGNdVl zal@3-MJ?$8rlyZ59O1Ui4F>_%kqeY~8dwEDA#+1IEi@?}>(JH~f$ID@Y{UdZ7k!c~xQ3CpG`#@g&vsO&7 zyPtlb-nmoowpRiMad05Bpj$rXpEP?I4Cjxj%(7u;c}Lei>YgeJt4*TKdI%!+Po*W5 z4Jl1K%EE^iQ>ot=QL59sr($1D7Q_z>mhqivXMS*6j#dbX>a6Th)y&yhgUY#Df+{h%!bG|L z_i*LX?UA{0Mk7`NlY20+o$!h)7=85UpHM*~O_8yujci6L`BEp&+9=!38;Re>`=$)5OyqbC-S5W9+A!;eo zQJJ}+K@?^MP#L}BQ@%jH^@6F?y%GPaBEE^QWs7T+$ z5)q|~4G1D8rIb*B5ETIdAu5G*Vx$C(5VGtbG-ApY1tBUT(ixFfghU8U*&xz)N;(w; zA}b1UL6YU0?t9O@`|YC6e&^hK&hMP};}1nwNHW)4-<=jJ{$VL0GOha8IsD&hJc zPJdG}`4RR;8_4GgQ(O5{vRCYduL16l&EN~w4#|vYyo1R0M zh|Xj_p@4dX73Tfua~0my{by&ASF>I*I>3*AU8jk?L2-)k&P)dC9ePnJNEkbTlN$Ra z3jmG#F_S7NIJlBROij*&w|vPh%y?e|40qWI6{JtsO-xwdz z9$+B@5X`eD)Hwk7v48>PYiEQ?%{@;37uKZy2cC2T05gX@J&Rx|HIE&uR^e&f5Xm&M!mih*6tc&Sk)u^=Gmyb1D~Zx1{?43v$YdnGig3T zqWt_Ll58YA^#y3VPv}0t>2V# z!>bhD(_BHF{cZ2msO3)1Lib<~Bl0U3jZa0ytD61Ln-}k29;?261Le(U} z()sT%`n@CwEs=$eq)OF52(%X3T$(^LC9hfiKFyu7N(i*o+Ru4{p2&m7mYlAj)k)VO)@QgXCu+s(dY z=k1$(R$jt`dWQsO#Z|&kFBIG&-+*02n9RsVbxfptfP7exf=Pg1QbCY^IKn=ArwZ!2 z0H(V;^erHLEk6JVBZjV@Hi7=i(gRl^FdcH;XMa<=Ay0cl1&?6iWtl0|`Uq`dB8Tw$ z&=(sg`Fi4L9E+uv-94!2d@F-WIhZ_ZVkPs*UV{t?DxWO{0NFQXb+ZV+G;^tv6n$qpl-e8AY z)IhrlmmopzEO0NV>!*KHe}a;{BxvY1C}a~~hrT#nlATrf2sl$FpNVoSK4FsiEUu}A zIZb>a=luVfBfnz3u6M)_v^BDndKLs8Z zWc(G2|8t94rwIVk)>fyf)_TtP&Or`x{3T&B`&nEqS_tzL>XRm@?oq6~sl2E|m0=E@swc>_ zdXu@C%U;%M#lwVn&HFqYK2j2NH&nALCN8h4=5b~9gIw>NEfvkcO4S<~l+FI+{u@_xeL z@I3Fd{RJ+IuH*~W+8(xc_BgUW>djEwxtsd87uec7f3u>m+B13eo$B`gEh7U`27Dah z5ot8PzJ&IYS2D6;sSl%;Nnd%%-FYQKUU~VM$)(Wgqr(j3PJa#$$)Drn;>=|5zi0ZH z$zW!60;~Q1Z&oM6UHlfXP|arRhbz|;F!+T)>CccIVbcEUF(}idEr!_-4_o@0Jbq-C zMbGXT$Z(~fQO@dVdH4KveVdW?YliooJpc5Bo&OXQ8KXh!9Oy5{#Z_K{WkFL~YYH!nTa}Mx&^5{t` zpcd}S{pFt}@ZSIBS)B!M`+RwQZ+dvX{R2G%{mr2#gHJ3xv9aQK#kx`(&F+m~%(z>s z;U^7N>$988kNh$GynZp}92CS%CM*<#T^+9X`2utWMRNfk!N3VRw=){5=KRJrhcMOl zm$sXe@0&HPJd$IeKhJCK-XG?(D4=wv2!4Vl6Hh^KF$|V_^Y9i(Fu-|eqR<{2g+Qr# zD-3pk*YgR}T~r#!A-+6S&d^;1BtoiK4D`8?@uw@*Ur~b**$+_b1r+3cNGf(NP;XDp zp6=o;%(g$bDCEzVW*RxulQS{-cQG(CaAu~UnR)VG)}Wac=ij$>r_;>kW?tLLNf4&< z?#dNR9m>%SS9iZ$Y~X6{x%Hru?M`RDHxob^HPC+I)H)tuG64mKY(D3k(mGF=)5Pf^ zNmsT*5#%1sPwkvQR&M}zo5VzJ?Id66Ymqkk6~5H%+zo(zwtC3dDko`IhVr?$K7O99@SZJ=NP z(MesrDk!P*@8g97`hk0DgSt>8{lQr-QXT*+N-mMW?DMa zr!#RnGoof@shRn7W{vuX1@^z_YTEsh0~6I;iJhMaN8(&vI3*q9Bb@$0VaK(KskjcU za_@DF1j3xx&&bh-KW|;H?B(D3#PWU6tF0O%Sa^)oqmG_GAteBEc?g07Csdwss_-BX zf5M#|(4p6o=A-(Ex`2E(;=!jevD_FQtTV*IP6_+j9V^vI1Ke8(&}g>0|6nZW2frs* zN_`&uI_txU1L;bihVCT)&ChGb$m*YPJN_B>W4hP>jX}bEum>O@5}5N8(qS(fX%?~)nCjKIyGZv_nu(p` zliN;0f=YN-9&{(XJUuumsu}A`Cw7h+(|5K9)wD;@`g7m-k^Bm;rLA={$^Ku}G=Hm& z|GVm%|B(Nat{Q@K^NanBSg93q_M4J>ck~qN&ljU+O>O;0nZkWeT=L}NY7;;Uam6XL z{A>QE@2KJA(P{No-L1nqGk9lln^oM3#xal1vIzH2s%kbn+7Da2d&2IpRvme~qU=%e zqq1bbj3-ZS9IPm>NOrz=(a7;Y3>#7ua^8U|DoADnO87Wa52~GhG6bjEn1g`S=mWL6 z682-{I~cuSTa;yug{7c4BTccgQ&W#E6u@PJl8F9s@goR7xLhsx+Gz^MazL%IwkR!hG0 z1$xN`NIwdHrM=?FB?Y4~tEU(Wz&m&jDJnUooR2LiASiqa1`P6PS_0UB(>6Pfu^kIu z%jHahdXox_7&mq7o6=Q+?1rRCz9j|yZmZ{P4%k?d^?-xCT$kfNI{WFK-&b6sNXnPulsAvz-h9uM)%clgcG-YB*v;ZZ0cv< znzEbe*KVvlA$7GbD9pWgd;gKko)6O9tX1!&SA~8VPVdCu{~m@-|E>W_2o^Es4&yB( z%BKM1PYVeE^?|gdt<_tE1PzL53#si$wV!~Ap;W~k@2*S#nrLq`w|~TLW2!Kgsft|d z=l0#p362OXA`0FfH`o|^!zy!Y#3cDFK^Lz_driVvLCK)haAH#K3CrrW283=^zzB@`+axIPb}G?P*a^9m0lFp7JA>`sD08gYl)2 zbw5bLI(tBp%H%!AkEiQV49CPck zjxclKbpQA$Zhgz{j&Ye@%Kc9)i#wNo6!B(b^|1*?jkINirD=89O%d=oCFK{qEoqK{ zpG=AJ2SOAx`$cuR{-6P?B@5aCXL1qXB`)Qa$CZ4wGFMY%7LfX5gB)LT%BDCKQuI~( zR|UN@65oFfZ5f`JoQz9#-}S*unwCut8m%cB_Un~F2k*zawtwAHQh%V+GCY<@cDjUi z>GReBG;O-+e)=Ia-o(KFNKqA#&P|XF_JUPFT{iLk)Tur^i@e{oXol_~PY2j{$bP*RQNi$&C zL&^I=E<$z6ej$n_&K|BRLgRCgSA%s)l)iDpWgTTTIFHss`|TEILbcK#WJ0<91I{Oc zBNvA5_qdc?c=PUi4Gq<2mAf-f-hKS(&FXE@cP~|kZi_a!t=WDuW!JGN-E)WEn|Qo+ z?#S70g9{Fd=^SeFj_D|JQ60#egMuaS->@jJQT(r^2b6h_gJs@~7ZC@zWjp3_kP!AkTn8p?0Pm z5EkFGT$p|+WdFs$kr^iAv%e`3q0az>K7#%4)-{}D9Ach3ngZs8Rz(?y|A_R+yNN+( z!aE5)>v_`Sikt_9w-uGqirG?*f@yIJ-qP|^v9V9KTQV>EzAx4B=QeBH1*Te|6**yG zY0a4hJAjJ3^F)!)-OJvVfI8^>S6SG1;Crqk$TxQ&fj_raTMK}oP?KD}2~e;SZuGHIp#6kNRdfLR zz1j?#@TM*)3>PTQ?|D4QGV{CkRu2vC8R8y9i#Iv-e)hHR{_ugF=liDk6D=OdR6air zNR2Nepo7L*U3f4HOP_CyorMfVzz7ihGnIf&Jh=dT&01;9rP_ltCeBR2_cO zNLV5d1~yWLmL2wSGN)c1lG`}2qRZY}xOrp?MtTLQxE*q>BK^aYlThB9{*WodjNFjE zed_-9zO<_cf^vP$H(q<_fbC-b`FjSLqt0+Fse@s*nZ|@c>U?!1tsG$;LmX_c)$aPL2mtD^Kw_35Z^=93{CbfN>%DSDqA4zd9 zul^#AyZ=^r-^0Z#FM&08Rr;NLd&k)q_vDKmFGmhWMh9blvtG$GH?{ua=`FLrS0pP8 z(!K1=3K=R~6{KV9LG0@cXxrlvzqS3UUVoNnaiVH!dY@vO)B+#KfiZqAnf&__DiNADMsglor#p*cKL5YhgF}7t9%I+{B z2{odGwRlVLSF=O=q}g)_E+J4!usBp^1Uwb)SdaB^epY1SE#*dv`}ozsX7!9j85C-p z2)pZUiAL7zQZ89qPFM*pZTC8ih2e6E##yLxmxSdKMZR zI>(y&5Iw`La7sOo_(pqAy-jW6?^8@It0Z3DcmZQkU%94g=R4*?!SDfNmm*5Xi*=P( z3M^wL)Ba$V;4XmiWDp2sEcylH(@;52{6c1pwyzyR^(Ed7j9x8Ng(L*Q>MLmxZ-&zv zvJAVs>$8@?O|^{vil#ooIX-gv7Q(8v=^KS~34s*3!(GZESzVUd>j&mk2bfp?DD*dI zYbOGREKW*MR6&Q$aJ`~hLOJ0624c<{Dj`_O6MnAPOvC|QHwze}9Y9({WCO~G6q2k; z6ZxxeL!$X(Nz4+~QyI2*3@8gGjv8mw<2O_y#lVFvUHSB)B6#Zg3m+zMWV3H&CqsxS zOTKix2|ofe7#SR^(N2T=eh668c7L6Oc1Or*H9Lj z09DU#O6AI@2f0xLmeUi{1`b614#^Pn^V=tBJU3M zRvAHoV}azlkfoD%e&Zdy3%J4J}qRLy2V9Ol1c1v=eR*eSrWl=%eOFn@ha|aYtz*Zuf%!ys zK^f9z?G{_BiLUR`)gvTT*}X-RQ83GCrEns~Qg~{dQ0Np%oxK1!V;X|Z@SHD-3PNxT zhH{Od8y3^Z6mk}$U3OUR&j?9GP#M9i!YwKG8y?7Q5^xK6Z;`Y0UUuVYt-WtQmLRd) zCAuwZ%fAr&0od*#371|{0AhYH<1`TL1Xi#%NSw?=z6j`JargmwqPW8&M0ik$se9Lk z*ZWA)Lp8#E70h$iMD4A7-eR!3!%#O!u(f^X@k=5cvHEg**kd5H$}JNuv#7{Cm7RDy z{^djD{ws~hJ@6*-qX##G6Y~60?fqEhQRL9JEPsc!g0Sl!2_d52MW*dJ@vQR+a}QKS zYOLvMdS4deo^jjp9!^jEW3WrbBLP$OzDM0Fm)0whoon|I9p>fQ?WGJZJCM}Soqg`Y zszQa0l+i`?6LJt!`lyeL@K)}Kl-!apM@nRiX#EwO#r9gTOgL6Q7GKU@-W5e&g1(A5 zep+}rPi`d%J~#0e*T~i`>7MwbdW|SfYfpQ%zrdkjcsFvww|!N0;-ar#d*#lVv6A+*jsK7bd$CyO9>40N2(k0Q81<*4wUFG_R~6d zA{9H)?pC>h;0a;0$RnVpH3}5Pj+KVSL|^TEFaJuqOIi#CkrM;VK{zGSo@2|(GYgUR zSUUCx&LLi(2Y)Q3)bFi>AEU94k;Gm%!kZUOTu7oEb34neu+tcb4?9+FiT z@B21K=R9EE3rpJa=Gq2C54g0Q6)=%CIPn76LDGofq6|SAm}5MoG+@80jV( z%2In?XcQJ*DLLdG={_F0RI-Zgpzql({e7x&^NONV=O?eKbguPWlYcBn$Kjes{=*wD zjW*?9;vOY-?D_Rm!A?4T{8;X`mN(4e+F+~VM+~zfm#p;~`l8(~P;`$E_g+tLXxG>Y z9s3BsP2dtmDUCGYR$W{=o;-6lr{=7pxG7L|!p->LigZ(Y`E zhkKD_+={NH9#lNU>i~&22WY>4pwv=Ph%R!Ktwu(qp^qPT5yHvKC|W;NcRyfT53x5^ zcgu}IQRrE030dqZAglL^y&3l$`72fB=t$Y(<8qnIlE7QC{`MP`5osJxOuJ4sV6I`%41F;yZCoQJhfST># zaIsMnNskIVYqO=_lz^h{T#4xy=}8Hpk*P}cl4#X2wB)Y-IHA@Vxpkz>p0rmU()p=+ zm!P|<{Wd(vO{F=7o#nPY6=GRq^Q|}%Tci=BW8_s;mFt=%ByGA zq&{3D0rqFkq0HmDc9lBIZSn(pMo8sHin8UJjK=bfeXVRbiWO;cempg-53`iA&H|`e zZ*ge~l(s4|f%Xuu?~C*}q8`Sct+>v{QXvE<3;8baTlxf1LR)znR8Kgzp0*5879sW_ zRvJhf;aBD&O1rZJlk#JQ>q6`)-D?@QUKkOj;vl0X&nC3EkS@xL$xV$i!vMIh#Ay`b zlj%0<`&dcflXy}A(kk(8ta7W``_?(wGMG;O>HP(MS7gGd6DIQ4sulxRa#tG z)v=-dI%;Y1$S~vvERp4ZGP7X5hfa=#B%>egMMjllykozhwQk|oPu0^gs;0Bls z+AN70>kQ#gvx84%4ZEhhEEAH_+o<8NS^crMZ@~cVW9LfdolKXapByXGM38}RICBo+ zFsCOFs8K#7gkX@>xebu&5C?YU=uut>lYnRE3Lr}aWY2WuTNU@jY&-epGT${y*hDJ%)=)YlW&7ZnYTWGs3c1d4Y5*v|hLY|u!Pwzv@RqPa-FxkJ``NN> zAAty^f9`1N1E6}Y)x_v?;2QDM@kn@Wd9o#+KTYoaS88-l2*O`-UTq zrm1Qqy4Kws?rwZHdEvk_yPm>;0}Ffia9!26S+D=}gJ|J{3tgHAA)=$rg;&fvPIwZgG>uNxDr^Azxjix5LE?a$m0Q2nUOnsZLl6XIKcA*%Ve zDe2c87y4ShetLFev`8oEP`KamLkE3sod3mj-KLe7esg}8nrVMvON%xDWwSfz5}&seFxFt3(KRv)v<0uFECo|eRF0xGbh}} zdsn|&j#WX2^l~JlbN$x^UH5C4mBm-yyIbeHa8a)gZOmHoqQ7nfch~!yxy~IT>9I>( zneCTn2RCT%iPyH-?eXAq-pd*jPP9*nq@ zr+0JN>Jr0>o z-T(%87w?u9`&y4a_D;#gRJ15^NVz&HM9?%yeoOg@>bJ*bpC#4ojG&X^>-&<=`Atc zwa50!?35g9KQ*1Uk>tAS&9w(jU6|4wm+OavT%ts~%T>+dHFFd1^?M#Y$&g+!v3U90 zjv#F>#i#ApTUl;x895{{=kp7|d_RlN>*JvdP6|jD2&H2woI{-66d@rI3ZH{C3Dssx zA0szp`iN_NFpxpBiVGHWa?ayTuad z$I90#ZlP*Rvl;{b{nWC}9L+Nw!1QrKM$5aAF)^iIcz^6m|nSCRU zUEo$O;a4E!_rzxpYyM7f^KD|GkuB9tK4Y>ncmh7YK9Vj3Y#8JjNQajPB_z-XLn zy{{odV!0)}zHhYZ9^*ujone!KaYB7SytBli?%*K(s_xz-ujj{fb$s z_Kq%F`Svh&vB37k0&k3ptNQi#^3Ghl-ot^u>n>PcP+ys_;-;xf#ls?p!~vuAXk&i1 zhWL$|T#>8qxa*s5= z_i45g+QHN11Y?wG%^YR9jRf12rG}91g@V7;M65X!BO#}LS71)9h^R~90l!Yvbl*sT zQ8fe1r-2MX7dRc>vmb4Rz={-t>76YFTfs9{6mRKyL?$7N9B<#p^o?v)+=*uOw)2A< z{kP-sVOdzjD3oy4ng#sKLEdm7O|luN@VC$>%$`{Ie(*P`t;jNLwZ30Q(hCJUZmW}e zZmsAk#7Sm@4iFxKGFRG<)Y*#POL4tsBJAi_NC@h0*?44j9_=+#2fv=GCm9@_h?Mv> z0Aa{ikKyimLu~|-;pNBL@pweJc3`b!*;M!0=tvMTjN~I!n^+UBcyGfh#sSfja!MeO zpp!hQV`>9yXXawSx$4vWrX&*cMlU{~b+IkJLkk;3m?V3$Nj)|ZU8A^5ogJO+i%l@p z<3QNZ0UbbLl{?3+$`p*z)7Ws??_>UEILJ2G-rAR<(i5$Vo`iFyH63hwsP0O^mn{6LxQ*-kY&@j$+_ok|e-J2gRz zs@E7KWNsNt(tOdBwF<^@4V>x&blc5uKfdO6%m)};FF0Z@x)xrv=$V5PX=NAzFhAISa$T(<~c=lSsJ=V3&5A~e?JQr-I(vz+=~OOq){p{|?joAWPo zy^1cH56`;(W#IOK6Klz+K#jJ{yB5;%K^uZ=4V4ww2nTSz93iQ;pShU&i)5@RmUPZnxsK55 z=ZItgIdc{RZ;zBb9k54I;V%toRpf@s!`48WW*EPwvdi4kOukfc?L%oBCr~Yx2>RPe z?g*0`i?FB)An+}%j*vxt$3h;}JSch~UtOihXRo7Nw0A2)Qn;jL(YSuY{-^1TGtmUK zlL4zGyjrnptvV&9#kC`+tGmt{uh%(&3sMwwetk;VYK_KaufKy@29hh$4HRKhJ>g4Xa9J{>y5O5&9fQ-OO1gHK2@deq*OVl~!B ztTPfZ&yTw~)CbJ&qWvIW`uHqS@*xlGJqW!H&Wf8+B)XJoFbF>M1`s!gB6BI>J7Ka| z2lkeNHR4Q`+^yqq>STM)YaodDMS1`s%61F~m_6!Tp0=yFRZNWletSS?R5iQ`fB6BD zCOn=b!-q)rhNQQ6{eXX7?yc-zrg9Ry7)FCnr5^E4x*6h{@NxfVxy!k=NMc}Q6y=9_ zJM``QwwGUGdhbeX_f|I+*x;!U6Rc0l3q{j zcq%YzO16!4U7wrwzS5r4>lJ{byj1-~3Ly9BEJiLHVVqe*?v$$oYY zB~9dAOVXws6R{dtT0Q-UO&w}9Hi1(?UurU8H$uOI5I5TYfcAz^aug^NgTszQ+9t)N z6<|=F$pCu`=L~cy(1r&#>~+B9q_LEOa0YRXq+xG9psLV@eml6oQ7oR3qO`ZzK- z4R2Kga~Pa(h6dPGO}r}Ra|}W`+EGt3dhwPN$U{O%vbJz?x!hPn;d*WFn)pbnFLwCs zBqo7{cHZYD`eZsUYu&J!x`Wk_12`%92bl50HfM&^>` z-BgUs9UTDX9r#f8LU^-pXqI(~D-t2IN4%S2TIz}Ms7`xSKiG5+kPO1j4UCea zF1iqJyNAn{Oj_FQHN8gJ=dPLM#@*R);1azw!Ortxl*Cp)LU+@z!3(=rzW68z$Bnj0G=6f+fit}r!BBPAgcTAKfj=N1IBP0Q#cLbcceN#$?N(M(mMHo7#Y|#@T zb}`kjm8u2*)*@_Xj5foV+BBXT^lK#mZ5VdEh7=Z-`kREqkRKC%v_uzB^tj9=wB?Aa zkeRT25M55I=M~!%V0S=xv1#DUNB_V+Ivy`7GLtHh8b0O>a|v)3u&3f)%iUm^3p^-} zFLz-ZpRaLq_3f!@3J!qImfi&AH~(jO7BnWf63EU^0u7cs?w zg|rt?iE=GLYv`MjHhccxumDx++-}S99k^@X?c5@8D`;*ftAG+N*}BIYnC07WylrkN*5KGk0h?QT%MN{Js5Vy==bU; zOB}Nzu7mCAHEbfA75}o>_9k<4&biM8?E%k%KK*u0^SteejYV3vU5r)0FWAQ&e>O_& zszF-YaH#d%=h0=6+Bdfx(Ph~?s;Zu8`t?fMOKho01F_#spe1gRdC=Ok79*Es)|3`^ zWX&;|2Cadu2bg-q+`=0G1@%@9VjL|XXbi|n zK+9FO9n4Btcz{_r4Adp5L5d4_TiR=Eg%zm`H#*2~QKPEE^wEBa%~oJ-3Xh21kuEiCNM&ybK{o@mkVXxZgo{3~w8V6CLaE_x83C%bI#PW=2rWi{ zYJQ`e!&7wgBZ3wo6g!{RQFTt*N6QwBFc-ZUkegRX*g3($_ue2lhc1f;_FGonez&K< zV-{D!(nyM49n_23Sk?)`e(S7z-QfBBSpMGU+I9EaTXl;45oEHJy5J2=Bj+E)?rn`sw=Al zLp|&F59oB{k}SA(kPCH(;(6UZ^6dw`+p1=B2Ti_ zyp5zuio5s?Axzj0mkggFPe9~x|Lv!@YjkU0GvcRGz|pkEG{t+s%?4q^sLFWq*WrX6qf4yitAn-1czP zP*-Z#v~>YST;lOu)R4$mQRSZE#aKD>K(_<9!hsF$Pd9{W9bF3->LT2@>d%GGkr{G~3()cUsj z(Q~)>K&P+7d^#oA|Ez0fLS7FB-3Cf|=-(x0nF>$doN%!zQXvJH^6wn6;BShv!GJh& zqE=T3c12ilgwgLa6vP9+3#PdKJAWgud@y|aH^#|(rwh=#;}W_e^?L%?UiOw&(EX=t zO0?gp8$s!oY8@o~PMB|v?(bgmk2P99{f!L+q%>td(6d4sIDM6p0nQ9f_){*hPq6?e zI2<==&FCYc&0u4TLkn0-UMp+K)&N!D2WT@#`V)$QhO1$5?0d>zn52#srQMM;uE%n` zCxL49j;;UE1#ABqpHI?6pF*Ft6x9S!B8CU2k;4xVBT}e$1Lq-D4w%7Y%y)ZR!c+l! zez)dkNyM zQ-NmPG6QK;sM>5FN$}{HWTb9Dzx{zV$WzkzoCX|b$jqn5BrNNy-pp6%{n8mBd{T}?8<%w)CHb^0-RJjgrMhX-iW8|<8HIq){?s1O zf*kv05G0&O>mbR+BmJIvKD5tzxH2q`FfxXZe$6@|OV8jG<34{u3tOsJv(5s+3%;Q; z(4L7d>s1oM}3rqk-kW=$kK00;FB;1NGKJgqfd>|0I2iE*LV#WlH1P) zF+3i@srZU64;BNU_tgLcp(um&aHt<5kI8>(=>sQtnKg!eX>tV}ox^FFl5u;yzbP@T zA$S3l#+*15C)iHKf^<>|CMfjCVg=ak>d1CMUn)Q?#VkHFwUO5^1Llt#q<28ACE2Mw z2ebw}_tUs9C>xe)fQ!u}`46P`g9;xeWfuwD*PrhM>~83%C|EQV)B^!zYoX#kXR^Ol zoCme^KzvvEHzii}mUw9L3uu^9+T=+f4jnwO%)1s4CSVL$I$Fz79uGOqEYtd?v^j<_ zP4C6d^wdmG&BWBq=$o0R{u|Ed@5{)@8cuDIYW=`c_((ClSvuHG^%QZ$V~9hkYD*7U zdcC5P>I|S7Hq)>`h#d{rp&8`7x~*X3x@mmMmhOEoGcHZBk{Rvq_}3PKsSPtL-Aqm} zlRf<@_x#re%}k#8_gVT(Pt9cHGkcfm5TGv1beqv~h@W{BxhCUs%4`^AJUS44MfE>2 zH93dByU;DER=*?nf^mtc9_5v+HVvJR_z7fcM`X2G7RBxMPTBpuuq?f<6(w%o#M1N+ zdb>_6B!_RQZj*>iw?zrFZJ&J^cyJdNn$Wys|EY~(y)ns)kt63|;3v3-@vA4$o zVlkNiAAnf=XTWdYzk>vz$xe4x~Fw~-ce)Eb`(H-6&nDGSuEt0l9SwL1p+Uvj&bH(<5Q}TejQ^wV>4Tc6C9Kj}V zFms?63JLK=Gb8dp+VBFw5!PMJG$}Lu;ggC=ne{|b**nAFtH;O-|ByWRrX=6k-Nc*P zZX*7s1TZ31bOFHS+gBHDxk{Rx0NPss4bq8?A$*xiLl@E~nYT;52h*m1OE#((E*ev; zxC{mbfS>?8J*VQE(#I>iM)QG)Sw0h)!}()N4R%uD3T&Yrp?vNFk6 z^rEv20$?4u(=&bmW_!L`>In^Y5&_!v&TxPsM*$Re_D3{$C_-cM{a?KWFi-jr0HFPH zSHS^2CV*-!z9~%wEsHhfd>PI~XW>3$$WAD<8w};&fg{-X#$@^Dzj_bEjiAN>O`zR0 z9^h>s1yX3BykdRw-*uL9MK*xv@*w^n(2Xg*?X;7B@fL!hoQ?mc)V78I`de-bM1>&q z#&*N!EcsL(uyuBopX~>PPG$!O{*~}jp>~I3&zbfeSh$~rg+4B0g1$!efdn16#~pVV zLEdQGp1(nrTg3qTYZ)ei`lS!FgjP}(Y5I2{5iAC0JedgM39z$(-W<5Yd%K(-6@Zh6 ze25Pq(B;x`XmA22*TH-tIE1iTaDVZZzX*?BPjEk;1OR&eJ`+&?5`=#d9Ww#-_c1sV zP%|?WnA84Zy7>>Ep~~cIp;{*n|AP&11?A@e-gdaeL%Kjx&J>RI9BabrQ!Vm*8YE4> zXns>#R!T@QRBnr6%%it z^5-qUh{du6;n)fj`LYbDzM{t74J@a5ii*)fC^#b}2l>j6<>^7SxVssmTcuOpg2!K8OsHg#pxmN~1ucYrNJ(V^6@`B#Q|3Hy7GBxljR8!=J zL|t%otd^k%+}gDg?1O~Fb5-}MvW&a%`os8@ZAE1#;Ny>r8t#Vd92l9Jb0YHN6nxgT zqN1#8c}+=0?EMH)b>&3W%n~}YgwEt-GdbBzl0TE=&+Hoiuk9MYGJDTTueNhSTNWT9 z(pf=p1MUpE9ONTT^_=sSG5kWw6)IjZ)}U~+IhvR`--o;&D45LbD#RTzRvs4*B>AIwRb#c*{

    4y(8%w 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

    rel@wb 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 diff --git a/zh-cn/device-dev/porting/public_sys-resources/icon-danger.gif b/zh-cn/device-dev/porting/public_sys-resources/icon-danger.gif deleted file mode 100755 index 6e90d7cfc2193e39e10bb58c38d01a23f045d571..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 580 zcmV-K0=xZ3Nk%w1VIu$?0Hp~4{QBgqmQ+MG9K51r{QB&)np^||1PlfQ%(86!{`~yv zv{XhUWKt}AZaiE{EOcHp{O-j3`t;<+eEiycJT4p@77X;(jQsMfB$R?oG%6hQ z+MMLZbQBH@)Vg&1^3?qHb(5!%>3r0+`eq=&V&E}0Dypi0000000000 z00000A^8LW000R9EC2ui03!e$000L5z=Uu}ED8YtqjJd<+B}(9bIOb$3-31_h|V>=0A{ z1Hh0#H30>fNT})^fRU_83uewx9oRr{f{Sx1Ml`t)EQ zGkHZ67&~y{W5Jpq4H_WfuLxp*3<7O}GEl;1ESe36fLNs=B0&LQM1Buf(R)qg(BRd`t1OPjI1m_q4 diff --git a/zh-cn/device-dev/porting/public_sys-resources/icon-note.gif b/zh-cn/device-dev/porting/public_sys-resources/icon-note.gif deleted file mode 100755 index 6314297e45c1de184204098efd4814d6dc8b1cda..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 394 zcmZ?wbhEHblx7fPSjxcg=ii?@_wH=jwxy=7CMGH-B`L+l$wfv=#>UF#$gv|VY%C^b zCQFtrnKN(Bo_%|sJbO}7RAORe!otL&qo<>yq_Sq+8Xqqo5h0P3w3Lvb5E(g{p01vl zxR@)KuDH0l^z`+-dH3eaw=XqSH7aTIx{kzVBN;X&hha0dQSgWuiw0NWUvMRmkD|> diff --git a/zh-cn/device-dev/porting/public_sys-resources/icon-notice.gif b/zh-cn/device-dev/porting/public_sys-resources/icon-notice.gif deleted file mode 100755 index 86024f61b691400bea99e5b1f506d9d9aef36e27..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 406 zcmV;H0crk6Nk%w1VIu$@0J8u9|NsB@_xJDb@8;&_*4Ea}&d#;9wWXz{jEszHYim+c zQaU<1At50E0000000000A^8Le000gEEC2ui03!e%000R7038S%NU)&51O^i-Tu6`s z0)`MFE@;3YqD6xSC^kTNu_J>91{PH8XfZ(p1pp2-SU@u3#{mEUC}_}tg3+I#{z}{Ok@D_ZUDg- zt0stin4;pC8M{WLSlRH*1pzqEw1}3oOskyNN?j;7HD{BBZ*OEcv4HK!6Bk6beR+04 z&8}k>SkTusVTDmkyOz#5fCA$JTPGJVQvr3uZ?QzzPQFvD0rGf_PdrcF`pMs}p^BcF zKtKTd`0wipR%nKN&Wj+V}pX;WC3SdJV!a_8Qi zE7z`U*|Y^H0^}fB$R?oG%6hQ z+MMLZbQBH@)Vg&1^3?qHb(5!%>3r0+`eq=&V&E}0Dypi0000000000 z00000A^8LW000R9EC2ui03!e$000L5z=Uu}ED8YtqjJd<+B}(9bIOb$3-31_h|V>=0A{ z1Hh0#H30>fNT})^fRU_83uewx9oRr{f{Sx1Ml`t)EQ zGkHZ67&~y{W5Jpq4H_WfuLxp*3<7O}GEl;1ESe36fLNs=B0&LQM1Buf(R)qg(BRd`t1OPjI1m_q4 diff --git a/zh-cn/device-dev/porting/transplant-chip-board-bundle.md b/zh-cn/device-dev/porting/transplant-chip-board-bundle.md new file mode 100644 index 0000000000..8e235f7c54 --- /dev/null +++ b/zh-cn/device-dev/porting/transplant-chip-board-bundle.md @@ -0,0 +1,57 @@ +# 三方组件适配 + +如果需要使用third\_party目录下与产品相关的三方组件,可能需要对三方组件进行适配,下面以比较常用的mbedtls为例,介绍下适配步骤,注意本小节中仅介绍如何将适配的代码与OpenHarmony的编译框架融合,不会详细介绍mbedtls本身的原理和适配代码的具体逻辑,这些内容请参考mbedtls官方网站上的适配指南。 + +1. 编写适配层代码 + + 根据mbedtls官网的适配指南,编写需要的适配层代码,以适配硬件随机数举例,下面的路径都是相对third\_party/mbedtls的路径: + + 1. 拷贝include/mbedtls/config.h到ports目录下,并修改打开MBEDTLS\_ENTROPY\_HARDWARE\_ALT开关。 + 2. 在ports目录下创建entropy\_poll\_alt.c文件include并实现entropy\_poll.h中的硬件随机数接口 + 3. 在BUILD.gn中的mbedtls\_sources中增加刚才适配的entropy\_poll\_alt.c的路径 + 4. 在BIULD.gn中的lite\_library\("mbedtls\_static"\)中增加一行MBEDTLS\_CONFIG\_FILE指定新配置文件的位置 + + ``` + lite_library("mbedtks_static") { + ... + defines += ["MBEDTLS_CONFIG_FILE=<../port/config.h>"] + ... + } + ``` + + + 注意,上面的修改最好都新建一个config或者新建一个xxx\_alt.c文件来修改,不要直接在原先的代码中修改,侵入式的修改会导致后续版本升级出现大量零散冲突,增加升级维护成本。 + +2. 制作patch + + 由于上面的适配是硬件相关的,上库代码时,不能直接放到通用的third\_party/mbedtls目录中,因此需要将上面的修改制作成patch,在编译之前通过打patch的方式注入到代码中。 + + 1. 首先增加设备的patch配置文件device///patch.yml + 2. 编辑device///patch.yml,增加要打的patch的信息: + + ``` + # 需要打patch的路径,路径均为相对代码根目录的路径 + third_party/mbedtls: + # 该路径下需要打的patch存放路径 + - device///third_party/mbedtls/adapter.patch + third_party/wpa_supplicant: + # 当一个路径下有多个patch的时候会依次执行patch + - device///third_party/wpa_supplicant/xxxxx.patch + - device///third_party/wpa_supplicant/yyyyy.patch + ... + ``` + + 3. 制作上述**步骤1**修改的patch并放到对应的目录即可 + +3. 使用带patch的编译 + + 想要在编译的时候带上patch,其他步骤不变,仅需要在触发编译的时候加上 --patch,例如全编译的命令编程 + + ``` + hb build -f --patch + ``` + + >![](../public_sys-resources/icon-caution.gif) **注意:** + >最后一次打patch的产品信息会被记录,在进行下一次编译操作时,会对上一次的patch进行回退(即执行\`patch -p1 -R < xxx\`),回退patch失败或新增patch失败均会终止编译过程,请解决patch冲突后再次尝试编译。 + + diff --git a/zh-cn/device-dev/porting/transplant-chip-board-component.md b/zh-cn/device-dev/porting/transplant-chip-board-component.md new file mode 100644 index 0000000000..618fc8acfa --- /dev/null +++ b/zh-cn/device-dev/porting/transplant-chip-board-component.md @@ -0,0 +1,26 @@ +# 系统组件调用 + +- [SAMGR](#section105874301910) +- [DFX](#section20064420420) + +系统组件为上层应用提供基础能力,包括SAMGR(系统服务框架子系统)、DFX子系统等。在板级系统移植过程中,只需要选择使用即可,不用对其进行适配。 + +## SAMGR + +**基本介绍** + +系统服务框架基于面向服务的架构,提供了服务开发、服务的子功能开发、对外接口的开发、以及多服务共进程、进程间服务调用等开发能力。 + +>![](../public_sys-resources/icon-notice.gif) **须知:** +>本组件在板级系统移植中必须要使用,否则其他服务组件无法运行。 + +**SAMGR使用说明,请参考:[SAMGR 使用指导](https://gitee.com/openharmony/distributedschedule_samgr_lite/blob/master/README_zh.md)** + +## DFX + +**基本介绍** + +DFX子系统主要包含DFR(Design for Reliability,可靠性)和DFT(Design for Testability,可测试性)特性,为开发者提供代码维测信息。 + +**DFX子系统使用说明,请参考:[DFX子系统使用指导](../subsystems/subsys-dfx-overview.md)** + diff --git "a/zh-cn/device-dev/porting/\346\235\277\347\272\247\351\251\261\345\212\250\351\200\202\351\205\215.md" b/zh-cn/device-dev/porting/transplant-chip-board-drive.md old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/porting/\346\235\277\347\272\247\351\251\261\345\212\250\351\200\202\351\205\215.md" rename to zh-cn/device-dev/porting/transplant-chip-board-drive.md diff --git "a/zh-cn/device-dev/porting/HAL\345\261\202\345\256\236\347\216\260.md" b/zh-cn/device-dev/porting/transplant-chip-board-hal.md old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/porting/HAL\345\261\202\345\256\236\347\216\260.md" rename to zh-cn/device-dev/porting/transplant-chip-board-hal.md diff --git a/zh-cn/device-dev/porting/transplant-chip-board-overview.md b/zh-cn/device-dev/porting/transplant-chip-board-overview.md new file mode 100644 index 0000000000..732872af5b --- /dev/null +++ b/zh-cn/device-dev/porting/transplant-chip-board-overview.md @@ -0,0 +1,57 @@ +# 移植概述 + +- [板级移植流程](#section1283115812294) +- [板级目录规范](#section6204129143013) + +## 板级移植流程 + +最小系统移植完成后,下一步进行板级系统移植,板级系统移植包含以下几步操作: + +1. 板级驱动适配。 +2. HAL层实现。 +3. XTS测试套。 +4. 业务功能验证。 + +**图 1** 单板驱动适配流程 +![](figure/单板驱动适配流程.png "单板驱动适配流程") + +## 板级目录规范 + +板级系统编译适配参考[编译系统介绍](transplant-chip-prepare-process.md),板级相关的驱动、SDK、目录、HAL实现存放在device目录,目录结构和具体描述如下: + +``` +. +├── device --- 单板样例 +│ └── xxx --- <单板厂商名> +│ └── xxx --- <单板名>,里面包含liteos-m内核的,并且能够运行的demo +│ ├── BUILD.gn --- 定义单板的编译配置文件 +│ ├── board --- 板子特定的实现(可选,如果本单板直接提供产品级demo,则相关应用层实现放在此目录) +│ ├── liteos_m --- 根据BUILD.gn文件中的kernel_type,使用liteos_m内核 +│ │ └── config.gni --- 编译选项 +│ ├── libraries --- 板级SDK +│ │ └── include --- SDK提供对外头文件 +│ │ └── ... --- binary or source +│ ├── main.c --- main函数入口(如果产品级存在相同定义,则使用产品级配置) +│ ├── target_config.h --- 板级内核配置 +│ ├── project --- 单板级工程配置文件(如果产品级存在相同定义,则使用产品级配置) +│ └── adapter --- 单板适配上层应用组件的适配层接口,根据能力可选 +│ └── hals +│ ├── communication +│ │ └── wifi_lite +│ │ ├── ... +│ └── iot_hardware +│ ├── upgrade +│ ├── utils +│ └── wifiiot_lite +├── vendor --- 提供端到端的OpenHarmony特性产品样例 +│ └── huawei --- 厂商名字 +│ └── wifiiot --- wifiiot表示特性产品 +│ ├── app +│ │ └── main.c --- 产品的main函数入口 +│ ├── project --- 工程配置文件 +│ ├── BUILD.gn --- 工程编译入口 +│ └── config.json --- 定义产品的编译配置文件,配置产品所使用的组件等。 +└── out --- 编译过程中的输出目录 + ├── ... --- 单板/产品编译产生的bin等 +``` + diff --git a/zh-cn/device-dev/porting/transplant-chip-board-xts.md b/zh-cn/device-dev/porting/transplant-chip-board-xts.md new file mode 100644 index 0000000000..00253685f7 --- /dev/null +++ b/zh-cn/device-dev/porting/transplant-chip-board-xts.md @@ -0,0 +1,65 @@ +# XTS认证 + +- [XTS简介](#section6725155811454) + - [将XTS认证子系统加入编译组件中](#section46981118105417) + - [执行联接类模组acts测试用例](#section9489122319819) + + +## XTS简介 + +XTS是OpenHarmony生态认证测试套件的集合,当前包括acts(application compatibility test suite)应用兼容性测试套。test/xts仓当前包括acts与tools软件包: + +- acts,存放acts相关测试用例源码与配置文件,其目的是帮助终端设备厂商尽早发现软件与OpenHarmony的不兼容性,确保软件在整个开发过程中满足OpenHarmony的兼容性要求。 +- tools,存放acts相关测试用例开发框架。 + +>![](../public_sys-resources/icon-note.gif) **说明:** +>XTS的启动依赖SAMGR系统服务。 + +适配分为两步,包括: + +1. 将XTS认证子系统加入编译组件中。 +2. 执行联接类模组acts测试用例。 + +### 将XTS认证子系统加入编译组件中 + +举例:将XTS认证子系统加入hispark\_aries产品编译组件中为例。 + +1. 在vendor/hisilicon/hispark\_aries/config.json中加入XTS认证子系统定义: + + ``` + { + "subsystem": "test", + "components": [ + { "component": "xts_acts", "features":[] }, + { "component": "xts_tools", "features":[] } + ] + }, + ``` + +2. Debug版本才会触发XTS认证子系统编译; + +### 执行联接类模组acts测试用例 + +举例:以hispark\_aries产品执行联接类模组acts测试用例为例。 + +1. 获取编译镜像。 + + 请在如下目录获取版本镜像:out/hispark\_pegasus/wifiiot\_hispark\_pegasus/。 + + >![](../public_sys-resources/icon-note.gif) **说明:** + >判断当前版本镜像是否集成acts测试套件方法:在map文件中查看对应.a是否被编译即可。 + +2. 版本镜像烧录进开发板。 +3. 测试步骤。 + + (1)使用串口工具登录开发板,并保存串口打印信息。 + + (2)重启设备,查看串口日志。 + +4. 测试结果分析指导。 + + (1)基于串口打印日志进行分析; + + (2)每个测试套件执行以“Start to run test suite”开始,以“xx Tests xx Failures xx Ignored”结束。 + + diff --git a/zh-cn/device-dev/porting/transplant-chip-board.md b/zh-cn/device-dev/porting/transplant-chip-board.md new file mode 100644 index 0000000000..f5d7b754b5 --- /dev/null +++ b/zh-cn/device-dev/porting/transplant-chip-board.md @@ -0,0 +1,15 @@ +# 板级系统移植 + +- **[移植概述](transplant-chip-board-overview.md)** + +- **[板级驱动适配](transplant-chip-board-drive.md)** + +- **[HAL层实现](transplant-chip-board-hal.md)** + +- **[系统组件调用](transplant-chip-board-component.md)** + +- **[三方组件适配](transplant-chip-board-bundle.md)** + +- **[XTS认证](transplant-chip-board-xts.md)** + + diff --git "a/zh-cn/device-dev/porting/\345\270\270\350\247\201\351\227\256\351\242\230.md" b/zh-cn/device-dev/porting/transplant-chip-faqs.md old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/porting/\345\270\270\350\247\201\351\227\256\351\242\230.md" rename to zh-cn/device-dev/porting/transplant-chip-faqs.md diff --git a/zh-cn/device-dev/porting/transplant-chip-kernel-adjustment.md b/zh-cn/device-dev/porting/transplant-chip-kernel-adjustment.md new file mode 100644 index 0000000000..40f82e0cd7 --- /dev/null +++ b/zh-cn/device-dev/porting/transplant-chip-kernel-adjustment.md @@ -0,0 +1,83 @@ +# 内核基础适配 + +- [基础适配](#section14523241594) +- [特性配置项](#section112994366592) + +芯片架构适配完成后,liteos-m提供系统运行所需的系统初始化流程和定制化配置选项。移植过程中,需要关注初始化流程中跟硬件配置相关的函数;了解内核配置选项,才能裁剪出适合单板的最小内核。 + +## 基础适配 + +如下图所示,基础适配主要分为以下两步: + +1. 启动文件startup.S和相应链接配置文件。 +2. main. c中的串口初始化和tick中断注册。 + +**图 1** 启动流程 + + +![](figure/zh-cn_image_0000001073943511.png) + +启动文件startup.S需要确保中断向量表的入口函数(例如reset\_vector)放在RAM的首地址,它由链接配置文件来指定。其中iar、keil和gcc工程的链接配置文件分别为xxx.icf、xxx.sct和xxx.ld,如果startup.S已经完成系统时钟初始化,并且能够引导到main函数,则启动文件不需要进行修改,采用厂商自带的startup.S即可,否则需要实现以上功能。 + +在main.c文件中,需要关注串口初始化UartInit和系统Tick的handler函数注册。 + +- UartInit函数表示单板串口的初始化,具体的函数名根据单板自行定义。这个函数是可选的,用户可以根据硬件单板是否支持串口来自行选择调用该函数。如果硬件单板支持串口,则该函数需要完成使能串口TX和RX通道,设置波特率。 +- HalTickStart设置tick中断的handler函数OsTickHandler。 + +对于中断向量表不可重定向的芯片,需要关闭LOSCFG\_PLATFORM\_HWI宏,并且在startup.S中新增tick中断的handler函数。 + +## 特性配置项 + +liteos\_m的完整配置能力及默认配置在los\_config.h定义,该头文件中的配置项可以根据不同的单板进行裁剪配置。 + +如果针对这些配置项需要进行不同的板级配置,则可将对应的配置项直接定义到对应单板的device/xxxx/target\_config.h文件中,其他未定义的配置项,采用los\_config.h中的默认值。 + +一份典型的配置参数如下: + +**表 1** 内核典型配置项说明 + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    配置项

    +

    说明

    +

    LOSCFG_BASE_CORE_SWTMR

    +

    软件定时器特性开关,1表示打开,0表示关闭

    +

    LOSCFG_BASE_CORE_SWTMR_ALIGN

    +

    对齐软件定时器特性开,1表示打开,依赖软件定时器特性打开,0表示关闭

    +

    LOSCFG_BASE_IPC_MUX

    +

    mux功能开关,1表示打开,0表示关闭

    +

    LOSCFG_BASE_IPC_QUEUE

    +

    队列功能开关,1表示打开,0表示关闭

    +

    LOSCFG_BASE_IPC_SEM

    +

    信号量功能开关,1表示打开,0表示关闭

    +

    LOSCFG_PLATFORM_EXC

    +

    异常特性开关,1表示打开,0表示关闭

    +

    LOSCFG_KERNEL_PRINTF

    +

    打印特性开关,1表示打开,0表示关闭

    +
    + diff --git a/zh-cn/device-dev/porting/transplant-chip-kernel-overview.md b/zh-cn/device-dev/porting/transplant-chip-kernel-overview.md new file mode 100644 index 0000000000..34095a2318 --- /dev/null +++ b/zh-cn/device-dev/porting/transplant-chip-kernel-overview.md @@ -0,0 +1,64 @@ +# 移植概述 + +- [移植场景](#section93781277367) +- [目录规范](#section18127744153119) +- [芯片架构适配点](#section137431650339) + +## 移植场景 + +芯片架构适配是可选过程,如果在liteos\_m/kernel/arch目录下已经支持对应芯片架构,则可以跳过芯片架构适配,进行单板适配过程,否则需要进行芯片架构移植工作。 + +## 目录规范 + +模组芯片使用的内核为liteos-m,liteos-m中主要分为KAL、Components、Kernel和Utils四个模块。 + +- KAL模块作为内核对外的接口依赖Components模块和Kernel模块。 +- Components模块可插拔,它依赖Kernel模块。 + +- 在Kernel模块中,其中硬件相关的代码放在kernel的arch目录中,其余为硬件无关的代码。内核功能集(task、sem等)的实现依赖硬件相关的arch代码,例如任务上下文切换、原子操作等。 +- Utils模块作为基础代码块,被其他模块依赖。 + +**图 1** liteos-m内核模块图 + + +![](figure/zh-cn_image_0000001072304191.png) + +内核的目录结构和说明如下: + +``` +. +├── components --- 移植可选组件,依赖内核,单独对外提供头文件 +├── kal --- 内核抽象层,提供内核对外接口,当前支持cmsis接口和部分posix接口 +├── kernel --- 内核最小功能集代码 +│ ├── arch --- 内核指令架构层代码 +│ │ ├── arm --- arm32架构的代码 +│ │ │ ├── cortex-m3 --- cortex-m3架构的代码 +│ │ │ │ ├── iar --- iar编译工具链实现 +│ │ │ │ ├── keil --- keil编译工具链实现 +│ │ │ │ └── xxx --- xxx编译工具链实现 +│ │ │ └── cortex-m4 --- cortex-m4架构的代码 +│ │ │ ├── iar --- iar编译工具链实现 +│ │ │ ├── keil --- keil编译工具链实现 +│ │ │ └── xxx --- xxx编译工具链实现 +│ │ ├── include --- 所有的arch需要实现的函数定义,内核依赖 +│ │ └── risc-v --- risk-v架构 +│ │ └── gcc --- iar编译工具链实现 +│ ├── include --- 内核最小功能集代码 +│ └── src --- 内核最小功能集代码 +└──utils --- 基础代码,作为依赖的最底层,被系统依赖 +``` + +## 芯片架构适配点 + +如内核的[目录结构](#section18127744153119)所示,arch/include定义通用的芯片架构所需要实现的函数,另外芯片架构相关的代码会有部分的汇编代码,而汇编代码会因编译工具链的不同而不同,因此在具体的芯片架构下,还包含不同工具链(iar、keil、gcc等)的实现。 + +arch/include 目录定义通用的文件以及函数列表,该目录下的所有函数在新增arch组件时都需要适配,详见每一个头文件: + +``` +los_arch.h --- 定义芯片架构初始化所需要的函数 +los_atomic.h --- 定义芯片架构所需要实现的原子操作函数 +los_context.h --- 定义芯片架构所需要实现的任务上下文相关函数 +los_interrupt.h --- 定义芯片架构所需要实现的中断和异常相关的函数 +los_timer.h --- 定义芯片架构所需要实现的系统时钟相关的函数 +``` + diff --git a/zh-cn/device-dev/porting/transplant-chip-kernel-verify.md b/zh-cn/device-dev/porting/transplant-chip-kernel-verify.md new file mode 100644 index 0000000000..fc16eeb224 --- /dev/null +++ b/zh-cn/device-dev/porting/transplant-chip-kernel-verify.md @@ -0,0 +1,59 @@ +# 内核移植验证 + +在工程device目录下添加编译main.c示例程序文件,此示例程序的主要目的是:LOS\_KernelInit完成之后,创建两个任务,循环调度延时并打印日志信息,通过此方法可以验证系统是否可正常调度以及时钟是否正常。 + +``` +VOID TaskSampleEntry2(VOID) // 任务2的入口函数 +{ + while(1) { + LOS_TaskDelay(10000); + printf("taskSampleEntry2 running...\n"); + } +} + +VOID TaskSampleEntry1(VOID) // 任务1的入口函数 +{ + while(1) { + LOS_TaskDelay(2000); + printf("taskSampleEntry1 running...\n"); + } +} + +UINT32 TaskSample(VOID) +{ + UINT32 uwRet; + UINT32 taskID1,taskID2; + TSK_INIT_PARAM_S stTask1={0}; + stTask1.pfnTaskEntry = (TSK_ENTRY_FUNC)TaskSampleEntry1; + stTask1.uwStackSize = 0X1000; + stTask1.pcName = "taskSampleEntry1"; + stTask1.usTaskPrio = 6; //stTask1的任务优先级设定,不同于stTask2 + uwRet = LOS_TaskCreate(&taskID1, &stTask1); + + stTask1.pfnTaskEntry = (TSK_ENTRY_FUNC)TaskSampleEntry2; + stTask1.uwStackSize = 0X1000; + stTask1.pcName = "taskSampleEntry2"; + stTask1.usTaskPrio = 7; + uwRet = LOS_TaskCreate(&taskID2, &stTask1); + + return LOS_OK; +} + +LITE_OS_SEC_TEXT_INIT int main(void) +{ + UINT32 ret; + UartInit(); // 硬件串口配置,通过串口输出调试日志,实际函数名根据单板实现不一样而不一样。 + printf("\n\rhello world!!\n\r"); + ret = LOS_KernelInit(); + TaskSample(); + if (ret == LOS_OK) { + LOS_Start(); // 开始系统调度,循环执行stTask1/stTask2任务,串口输出任务日志 + } + while (1) { + __asm volatile("wfi"); + } +} +``` + +第一个任务运行正常后,说明最小系统的核心流程基本OK;由于xts用例框架对外依赖较多,主要是utils、bootstrap的链接脚本和编译框架,暂时无法支撑内核单独跑xts;此处略过内核测试套的测试,可以通过[XTS测试套](transplant-chip-board-xts.md)来覆盖最小系统是否完整移植成功。 + diff --git a/zh-cn/device-dev/porting/transplant-chip-kernel.md b/zh-cn/device-dev/porting/transplant-chip-kernel.md new file mode 100644 index 0000000000..e27fea3d59 --- /dev/null +++ b/zh-cn/device-dev/porting/transplant-chip-kernel.md @@ -0,0 +1,9 @@ +# 内核移植 + +- **[移植概述](transplant-chip-kernel-overview.md)** + +- **[内核基础适配](transplant-chip-kernel-adjustment.md)** + +- **[内核移植验证](transplant-chip-kernel-verify.md)** + + diff --git a/zh-cn/device-dev/porting/transplant-chip-prepare-knows.md b/zh-cn/device-dev/porting/transplant-chip-prepare-knows.md new file mode 100644 index 0000000000..6c0282c492 --- /dev/null +++ b/zh-cn/device-dev/porting/transplant-chip-prepare-knows.md @@ -0,0 +1,84 @@ +# 移植须知 + +- [移植目录](#section284217487490) +- [移植流程](#section639315306506) +- [移植规范](#section187870185219) + +本文为OpenHarmony平台系统开发人员和芯片(或模组)制造商提供基础的开发移植指导,典型的芯片架构例如cortex-m系列、risc-v系列等都可以按照本文进行移植,暂时不支持蓝牙服务。OpenHarmony是个持续演进的复杂项目,随着版本和API的改变,本文将会不断更新。 + +本文要求读者具有一定的嵌入式系统开发经验,因此它的重点未放在基本的OS基础介绍,而更多地描述OpenHarmony平台移植过程中主要操作和所需要关注的方面。 + +## 移植目录 + +OpenHarmony整体工程较为复杂,目录及实现为系统本身功能,如果不涉及复杂的特性增强,不需要关注每一层实现,移植过程中重点关注如下目录即可: + +**表 1** 移植过程中的重点目录 + + + + + + + + + + + + + + + + + + + +

    目录名称

    +

    描述

    +

    /build/lite

    +

    OpenHarmony基础编译构建框架

    +

    /kernel/liteos_m

    +

    基础内核,其中芯片架构相关实现在arch目录下

    +

    /device

    +

    板级相关实现,各个三方厂商按照OpenHarmony规范适配实现,device下具体目录结构及移植过程参见板级系统移植

    +

    /vendor

    +

    产品级相关实现,主要由华为或者产品厂商贡献

    +
    + +device目录规则:device/\{芯片解决方案厂商\}/\{开发板\}。以hisilicon的hispark\_taurus为例: + +``` +device +└── hisilicon # 芯片解决方案厂商名 + ├── common # 芯片解决方案开发板公共部分 + └── hispark_taurus # 开发板名称 + ├── BUILD.gn # 开发板编译入口 + ├── hals # 芯片解决方案厂商OS硬件适配 + ├── linux # linux版本 + │ └── config.gni # linux版本编译工具链和编译选项配置 + └── liteos_a # liteos-a版本 + └── config.gni # liteos_a版本编译工具链和编译选项配置 +``` + +vendor目录规则:vendor/\{产品解决方案厂商\}/\{产品名称\}。以华为的wifiiot产品为例: + +``` +vendor # 产品解决方案厂商 +└── huawei # 产品解决方案厂商名称 + └── wifiiot # 产品名称 + ├── hals # 产品解决方案厂商OS适配 + ├── BUILD.gn # 产品编译脚本 + └── config.json # 产品配置文件 +``` + +## 移植流程 + +OpenHarmony的device目录是基础芯片的适配目录,如果在三方芯片应用过程中发现此目录下已经有完整的芯片适配,则不需要再额外移植,直接跳过移植过程进行系统应用开发即可,如果该目录下无对应的芯片移植实现,则根据本文完成移植过程。OpenHarmony三方芯片移植主要过程如下: + +**图 1** 芯片移植关键步骤 +![](figure/芯片移植关键步骤.png "芯片移植关键步骤") + +## 移植规范 + +- 满足OpenHarmony[开源贡献基本规范和准则](https://gitee.com/openharmony/docs/blob/master/zh-cn/contribute/%E5%8F%82%E4%B8%8E%E8%B4%A1%E7%8C%AE.md)。 +- 三方芯片适配所需要贡献的代码主要在device、vendor和arch三个目录,参照[内核目录规范](transplant-chip-kernel-overview.md)和[板级目录规范](transplant-chip-board-overview.md#section6204129143013)满足基本目录命名和使用规范。 + diff --git "a/zh-cn/device-dev/porting/\347\274\226\350\257\221\346\236\204\345\273\272\351\200\202\351\205\215\346\265\201\347\250\213.md" b/zh-cn/device-dev/porting/transplant-chip-prepare-process.md old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/porting/\347\274\226\350\257\221\346\236\204\345\273\272\351\200\202\351\205\215\346\265\201\347\250\213.md" rename to zh-cn/device-dev/porting/transplant-chip-prepare-process.md diff --git a/zh-cn/device-dev/porting/transplant-chip-prepare.md b/zh-cn/device-dev/porting/transplant-chip-prepare.md new file mode 100644 index 0000000000..358da845b7 --- /dev/null +++ b/zh-cn/device-dev/porting/transplant-chip-prepare.md @@ -0,0 +1,7 @@ +# 移植准备 + +- **[移植须知](transplant-chip-prepare-knows.md)** + +- **[编译构建适配流程](transplant-chip-prepare-process.md)** + + diff --git a/zh-cn/device-dev/porting/transplant-chip.md b/zh-cn/device-dev/porting/transplant-chip.md new file mode 100644 index 0000000000..d0fbee119d --- /dev/null +++ b/zh-cn/device-dev/porting/transplant-chip.md @@ -0,0 +1,11 @@ +# 三方芯片移植指导 + +- **[移植准备](transplant-chip-prepare.md)** + +- **[内核移植](transplant-chip-kernel.md)** + +- **[板级系统移植](transplant-chip-board.md)** + +- **[常见问题](transplant-chip-faqs.md)** + + diff --git a/zh-cn/device-dev/porting/transplant-minichip.md b/zh-cn/device-dev/porting/transplant-minichip.md new file mode 100644 index 0000000000..58bebe026e --- /dev/null +++ b/zh-cn/device-dev/porting/transplant-minichip.md @@ -0,0 +1,11 @@ +# 轻量系统芯片移植指导 + +- **[移植准备](transplant-chip-prepare.md)** + +- **[内核移植](transplant-chip-kernel.md)** + +- **[板级系统移植](transplant-chip-board.md)** + +- **[常见问题](transplant-chip-faqs.md)** + + diff --git a/zh-cn/device-dev/porting/transplant-smallchip-drive-des.md b/zh-cn/device-dev/porting/transplant-smallchip-drive-des.md new file mode 100644 index 0000000000..bba3736632 --- /dev/null +++ b/zh-cn/device-dev/porting/transplant-smallchip-drive-des.md @@ -0,0 +1,11 @@ +# 移植概述 + +驱动主要包含两部分,平台驱动和器件驱动。平台驱动主要包括通常在SOC内的GPIO、I2C、SPI等;器件驱动则主要包含通常在SOC外的器件,如 LCD、TP、WLAN等。 + +**图 1** OpenHarmony 驱动分类 + + +![](figure/分类.png) + +HDF驱动被设计为可以跨OS使用的驱动程序,HDF驱动框架会为驱动达成这个目标提供有力的支撑。开发HDF驱动中,请尽可能只使用HDF驱动框架提供的接口,否则会导致驱动丧失跨OS使用的特性。在开始驱动开发前,建议先了解[HDF驱动框架](https://gitee.com/openharmony/docs/blob/master/zh-cn/device-dev/driver/HDF%E9%A9%B1%E5%8A%A8%E6%A1%86%E6%9E%B6.md)。 + diff --git a/zh-cn/device-dev/porting/transplant-smallchip-drive-oom.md b/zh-cn/device-dev/porting/transplant-smallchip-drive-oom.md new file mode 100644 index 0000000000..353aa15d2a --- /dev/null +++ b/zh-cn/device-dev/porting/transplant-smallchip-drive-oom.md @@ -0,0 +1,390 @@ +# 器件驱动移植 + +- [LCD驱动移植](#section1574513454119) +- [TP驱动移植](#section20284142116422) +- [WLAN驱动移植](#section0969448164217) + +本章节讲解如何移植各类器件驱动。 + +## LCD驱动移植 + +移植LCD驱动的主要工作是编写一个驱动,在驱动中生成模型的实例,并完成注册。 + +这些LCD的驱动被放置在源码目录//drivers/framework/model/display/driver/panel中。 + +1. 创建Panel驱动 + + 创建HDF驱动,在驱动初始化中调用RegisterPanel接口注册模型实例。如: + + ``` + int32_t LCDxxEntryInit(struct HdfDeviceObject *object) + { + struct PanelData *panel = CreateYourPanel(); + // 注册模型实例 + if (RegisterPanel(panel) != HDF_SUCCESS) { + HDF_LOGE("%s: RegisterPanel failed", __func__); + return HDF_FAILURE; + } + return HDF_SUCCESS; + } + + struct HdfDriverEntry g_xxxxDevEntry = { + .moduleVersion = 1, + .moduleName = "LCD_XXXX", + .Init = LCDxxEntryInit, + }; + + HDF_INIT(g_xxxxDevEntry); + ``` + +2. 配置加载panel驱动 + + 产品的所有设备信息被定义在源码文件//vendor/vendor\_name/product\_name/config/device\_info/device\_info.hcs中。修改该文件,在display的host中,名为device\_lcd的device中增加配置。 + + >![](../public_sys-resources/icon-caution.gif) **注意:** + >moduleName 要与panel驱动中的moduleName相同。 + + ``` + root { + ... + display :: host { + device_lcd :: device { + deviceN :: deviceNode { + policy = 0; + priority = 100; + preload = 2; + moduleName = "LCD_XXXX"; + } + } + } + } + ``` + + +## TP驱动移植 + +本节描述如何移植触摸屏驱动。触摸屏的器件驱动被放置在源码目录//drivers/framework/model/input/driver/touchscreen中。 移植触摸屏驱动主要工作是向系统注册ChipDevice模型实例。 + +详细的驱动开发指导,请参考 [TOUCHSCREEN开发指导](https://gitee.com/openharmony/docs/blob/master/zh-cn/device-dev/driver/TOUCHSCREEN.md)。 + +1. 创建触摸屏器件驱动 + + 在上述touchscreen目录中创建名为touch\_ic\_name.c的文件。编写如下内容 + + ``` + #include "hdf_touch.h" + + static int32_t HdfXXXXChipInit(struct HdfDeviceObject *device) + { + ChipDevice *tpImpl = CreateXXXXTpImpl(); + if(RegisterChipDevice(tpImpl) != HDF_SUCCESS) { // 注册ChipDevice模型 + ReleaseXXXXTpImpl(tpImpl); + return HDF_FAILURE; + } + return HDF_SUCCESS; + } + + struct HdfDriverEntry g_touchXXXXChipEntry = { + .moduleVersion = 1, + .moduleName = "HDF_TOUCH_XXXX", // 注意这里的moduleName要与后续的配置完全一致 + .Init = HdfXXXXChipInit, + }; + + HDF_INIT(g_touchXXXXChipEntry); + ``` + + 其中ChipDevice中要实现如下方法: + + + + + + + + + + + + + + + + + + + + + + + + + +

    方法

    +

    实现说明

    +

    int32_t (*Init)(ChipDevice *device)

    +

    实现器件初始化

    +

    int32_t (*Detect)(ChipDevice *device)

    +

    实现器件探测

    +

    int32_t (*Suspend)(ChipDevice *device)

    +

    实现器件休眠

    +

    int32_t (*Resume)(ChipDevice *device)

    +

    实现器件唤醒

    +

    int32_t (*DataHandle)(ChipDevice *device)

    +

    需要实现从器件读取数据,将触摸点数据填写入device->driver->frameData中

    +

    int32_t (*UpdateFirmware)(ChipDevice *device)

    +

    实现固件升级

    +
    + +2. 配置产品,加载器件驱动 + + 产品的所有设备信息被定义在源码文件//vendor/vendor\_name/product\_name/config/device\_info/device\_info.hcs中。修改该文件,在名为input的host中,名为device\_touch\_chip的device中增加配置。 + + >![](../public_sys-resources/icon-note.gif) **说明:** + >moduleName 要与触摸屏驱动中的moduleName相同。 + + ``` + deviceN :: deviceNode { + policy = 0; + priority = 130; + preload = 0; + permission = 0660; + moduleName = "HDF_TOUCH_XXXX"; + deviceMatchAttr = "touch_XXXX_configs"; + } + ``` + + +## WLAN驱动移植 + +WLAN驱动分为两部分,一部分负责管理WLAN设备,另一个部分负责处理WLAN流量。 + +**图 1** OpenHarmony WLAN结构示意图 + + +![](figure/HDF_WIFI.png) + +如图1,左半部分负责管理WLAN设备,右半部分负责WLAN流量。HDF WLAN分别为这两部分做了抽象,驱动的移植过程可以看做分别实现这两部分所需接口。这些接口有: + + + + + + + + + + + + + + + + + + + + +

    接口

    +

    定义头文件

    +

    接口说明

    +

    HdfChipDriverFactory

    +

    drivers\framework\include\wifi\hdf_wlan_chipdriver_manager.h

    +

    ChipDriver的Factory,用于支持一个芯片多个WLAN端口

    +

    HdfChipDriver

    +

    drivers\framework\include\wifi\wifi_module.h

    +

    每个WLAN端口对应一个HdfChipDriver,用来管理一个特定端口

    +

    NetDeviceInterFace

    +

    drivers\framework\include\wifi\net_device.h

    +

    与协议栈之间的接口,如发送数据、设置网络接口状态等

    +
    + +>![](../public_sys-resources/icon-note.gif) **说明:** +>详细的接口开发指导,请参考[WLAN开发](https://gitee.com/openharmony/docs/blob/master/zh-cn/device-dev/driver/WLAN.md)。 + +具体的移植步骤如下: + +1. 创建HDF WLAN 芯片驱动 + + 在目录/device/vendor\_name/peripheral/wifi/chip\_name/ 创建文件 hdf\_wlan\_chip\_name.c。内容模板如下: + + ``` + static int32_t HdfWlanHisiChipDriverInit(struct HdfDeviceObject *device) { + static struct HdfChipDriverFactory factory = CreateChipDriverFactory(); // 需要移植者实现的方法 + struct HdfChipDriverManager *driverMgr = HdfWlanGetChipDriverMgr(); + if (driverMgr->RegChipDriver(&factory) != HDF_SUCCESS) { // 注册驱动工厂 + HDF_LOGE("%s fail: driverMgr is NULL!", __func__); + return HDF_FAILURE; + } + return HDF_SUCCESS; + } + + struct HdfDriverEntry g_hdfXXXChipEntry = { + .moduleVersion = 1, + .Init = HdfWlanXXXChipDriverInit, + .Release = HdfWlanXXXChipRelease, + .moduleName = "HDF_WIFI_CHIP_XXX" // 注意:这个名字要与配置一致 + }; + + HDF_INIT(g_hdfXXXChipEntry); + ``` + + 在上述代码的CreateChipDriverFactory方法中,需要创建一个HdfChipDriverFactory类型的对象。该对象提供如下方法 + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    接口

    +

    说明

    +

    const char *driverName

    +

    当前driverName

    +

    int32_t (*InitChip)(struct HdfWlanDevice *device)

    +

    初始化芯片

    +

    int32_t (*DeinitChip)(struct HdfWlanDevice *device)

    +

    去初始化芯片

    +

    void (*ReleaseFactory)(struct HdfChipDriverFactory *factory)

    +

    释放HdfChipDriverFactory对象

    +

    struct HdfChipDriver *(*Build)(struct HdfWlanDevice *device, uint8_t ifIndex)

    +

    创建一个HdfChipDriver;输入参数中,device是设备信息,ifIndex是当前创建的接口在这个芯片中的序号

    +

    void (*Release)(struct HdfChipDriver *chipDriver)

    +

    释放chipDriver

    +

    uint8_t (*GetMaxIFCount)(struct HdfChipDriverFactory *factory)

    +

    获取当前芯片支持的最大接口数

    +
    + + 其中Build方法负责创建一个管理指定网络接口的对象HdfChipDriver 。该对象需要提供方法: + + + + + + + + + + + + + + + + + + + + + + +

    接口

    +

    说明

    +

    int32_t (*init)(struct HdfChipDriver *chipDriver, NetDevice *netDev)

    +

    初始化当前网络接口,这里需要向netDev提供接口NetDeviceInterFace

    +

    int32_t (*deinit)(struct HdfChipDriver *chipDriver, NetDevice *netDev)

    +

    去初始化当前网络接口

    +

    struct HdfMac80211BaseOps *ops

    +

    WLAN基础能力接口集

    +

    struct HdfMac80211STAOps *staOps

    +

    支持STA模式所需的接口集

    +

    struct HdfMac80211APOps *apOps

    +

    支持AP模式所需要的接口集

    +
    + +2. 编写配置文件描述驱动支持的芯片 + + 在产品配置目录下创建芯片的配置文件,保存至源码路径//vendor/vendor\_name/product\_name/config/wifi/wlan\_chip\_chip\_name.hcs + + 该文件模板如下: + + ``` + root { + wlan_config { + chip_name :& chipList { + chip_name :: chipInst { + match_attr = "hdf_wlan_chips_chip_name"; /* 这是配置匹配属性,用于提供驱动的配置根 */ + driverName = "driverName"; /* 需要与HdfChipDriverFactory中的driverName相同*/ + sdio { + vendorId = 0xXXXX; /* your vendor id */ + deviceId = [0xXXXX]; /*your supported devices */ + } + } + } + } + } + ``` + + >![](../public_sys-resources/icon-note.gif) **说明:** + >路径和文件中的vendor\_name、product\_name、chip\_name请替换成实际名称 + >vendorId 和 deviceId需要根据实际芯片的识别码进行填写。 + +3. 编写配置文件,加载驱动 + + 产品的所有设备信息被定义在源码文件//vendor/vendor\_name/product\_name/config/device\_info/device\_info.hcs中。修改该文件,在名为network的host中,名为device\_wlan\_chips的device中增加配置。模板如下: + + ``` + deviceN :: deviceNode { + policy = 0; + preload = 2; + moduleName = "HDF_WLAN_CHIPS"; + deviceMatchAttr = "hdf_wlan_chips_chip_name"; + serviceName = "driverName"; + } + ``` + + >![](../public_sys-resources/icon-note.gif) **说明:** + >moduleName 要与HDF WLAN 芯片驱动中的moduleName相同。 + +4. 修改Kconfig文件,让移植的WLAN模组出现再内核配置中 + + 在device/vendor\_name/drivers/Kconfig中增加配置菜单,模板如下 + + ``` + config DRIVERS_HDF_WIFI_chip_name + bool "Enable chip_name Host driver" + default n + depends on DRIVERS_HDF_WLAN help + Answer Y to enable chip_name Host driver. + ``` + + >![](../public_sys-resources/icon-note.gif) **说明:** + >请替换模板中的chip\_name为实际的芯片名称 + +5. 修改构建脚本,让驱动参与内核构建 + + 在源码文件//device/vendor\_name/drivers/lite.mk末尾追加如下内容 + + ``` + ifeq ($(LOSCFG_DRIVERS_HDF_WIFI_chip_name), y) + # 构建完成要链接一个叫hdf_wlan_chipdriver_chip_name的对象,建议按这个命名,防止冲突 + LITEOS_BASELIB += -lhdf_wlan_chipdriver_chip_name + # 增加构建目录gpio + LIB_SUBDIRS += ../peripheral/wifi/chip_name + endif + ``` + + >![](../public_sys-resources/icon-note.gif) **说明:** + >请替换模板中的chip\_name为实际的芯片名称 + + diff --git a/zh-cn/device-dev/porting/transplant-smallchip-drive-plat.md b/zh-cn/device-dev/porting/transplant-smallchip-drive-plat.md new file mode 100644 index 0000000000..a28bc2faf3 --- /dev/null +++ b/zh-cn/device-dev/porting/transplant-smallchip-drive-plat.md @@ -0,0 +1,165 @@ +# 平台驱动移植 + +在这一步,我们会在源码目录//device/vendor\_name/soc\_name/drivers 目录下创建平台驱动,如果你要移植的SOC的厂商还没有创建仓库的话,请联系[sig-devboard](https://gitee.com/openharmony/community/blob/master/sig/sig-devboard/sig_devboard_cn.md)创建。 + +建议的目录结构: + +``` +device +├── vendor_name +│ ├── drivers +│ │ │ ├── common +│ │ │ ├── Kconfig # 厂商驱动内核菜单入口 +│ │ │ └── lite.mk # 构建的入口 +│ ├── soc_name +│ │ ├── drivers +│ │ │ ├── dmac +│ │ │ ├── gpio +│ │ │ ├── i2c +│ │ │ ├── LICENSE +│ │ │ ├── mipi_dsi +│ │ │ ├── mmc +│ │ │ ├── pwm +│ │ │ ├── README.md # docs 如果需要的话 +│ │ │ ├── README_zh.md +│ │ │ ├── rtc +│ │ │ ├── spi +│ │ │ ├── uart +│ │ │ └── watchdog +│ ├── board_name +``` + +HDF为所有的平台驱动都创建了驱动模型,移植平台驱动的主要工作是向模型注入实例。 这些模型你可以在源码目录//drivers/framework/support/platform/include中找到定义。 + +本节我们会以GPIO为例,讲解如何移植平台驱动,移植过程包含以下步骤: + +1. 创建GPIO驱动 + + 在源码目录//device/vendor\_name/soc\_name/drivers/gpio中创建文件soc\_name\_gpio.c 内容模板如下: + + ``` + #include "gpio_core.h" + + // 定义GPIO结构体,如果需要的话 + struct SocNameGpioCntlr { + struct GpioCntlr cntlr; // 这是HDF GPIO驱动框架需要的结构体 + int myData; // 以下是当前驱动自身需要的 + }; + + // Bind 方法在HDF驱动中主要用户对外发布服务,这里我们不需要,直接返回成功即可 + static int32_t GpioBind(struct HdfDeviceObject *device) + { + (void)device; + return HDF_SUCCESS; + } + + // Init方法时驱动初始化的入口,我们需要在Init方法中完成模型实例的注册 + static int32_t GpioInit(struct HdfDeviceObject *device) + { + SocNameGpioCntlr *impl = CreateGpio(); // 你的创建代码 + ret = GpioCntlrAdd(&impl->cntlr); // 注册GPIO模型实例 + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: err add controller:%d", __func__, ret); + return ret; + } + return HDF_SUCCESS; + } + + // Release方法会在驱动卸载时被调用,这里主要完成资源回收 + static void GpioRelease(struct HdfDeviceObject *device) + { + // GpioCntlrFromDevice 方法能从抽象的设备对象中获得init方法注册进去的模型实例。 + struct GpioCntlr *cntlr = GpioCntlrFromDevice(device); + //资源释放... + } + + struct HdfDriverEntry g_gpioDriverEntry = { + .moduleVersion = 1, + .Bind = GpioBind, + .Init = GpioInit, + .Release = GpioRelease, + .moduleName = "SOC_NAME_gpio_driver", // 这个名字我们稍后会在配置文件中用到,用来加载驱动。 + }; + HDF_INIT(g_gpioDriverEntry); // 注册一个GPIO的驱动入口 + ``` + +2. 创建厂商驱动构建入口 + + 如前所述device/vendor\_name/drivers/lite.mk是厂商驱动的构建的入口。我们需要从这个入口开始,进行构建 + + ``` + #文件device/vendor_name/drivers/lite.mk + + SOC_VENDOR_NAME := $(subst $/",,$(LOSCFG_DEVICE_COMPANY)) + SOC_NAME := $(subst $/",,$(LOSCFG_PLATFORM)) + BOARD_NAME := $(subst $/",,$(LOSCFG_PRODUCT_NAME)) + + # 指定SOC进行构建 + LIB_SUBDIRS += $(LITEOSTOPDIR)/../../device/$(SOC_VENDOR_NAME)/$(SOC_NAME)/drivers/ + ``` + +3. 创建SOC驱动构建入口 + + ``` + #文件device/vendor_name/soc_name/drivers/lite.mk + + SOC_DRIVER_ROOT := $(LITEOSTOPDIR)/../../device/$(SOC_VENDOR_NAME)/$(SOC_NAME)/drivers/ + + # 判断如果打开了GPIO的内核编译开关 + ifeq ($(LOSCFG_DRIVERS_HDF_PLATFORM_GPIO), y) + # 构建完成要链接一个叫hdf_gpio的对象 + LITEOS_BASELIB += -lhdf_gpio + # 增加构建目录gpio + LIB_SUBDIRS += $(SOC_DRIVER_ROOT)/gpio + endif + + # 后续其他驱动在此基础上追加 + ``` + +4. 创建GPIO构建入口 + + ``` + include $(LITEOSTOPDIR)/config.mk + include $(LITEOSTOPDIR)/../../drivers/adapter/khdf/liteos/lite.mk + + # 指定输出对象的名称,注意要与SOC驱动构建入口里的LITEOS_BASELIB 保持一致 + MODULE_NAME := hdf_gpio + + # 增加HDF框架的INCLUDE + LOCAL_CFLAGS += $(HDF_INCLUDE) + + # 要编译的文件 + LOCAL_SRCS += soc_name_gpio.c + + # 编译参数 + LOCAL_CFLAGS += -fstack-protector-strong -Wextra -Wall -Werror -fsigned-char -fno-strict-aliasing -fno-common + + include $(HDF_DRIVER) + ``` + +5. 配置产品加载驱动 + + 产品的所有设备信息被定义在源码文件//vendor/vendor\_name/product\_name/config/device\_info/device\_info.hcs中。 + + 平台驱动请添加到platform的host中。 + + >![](../public_sys-resources/icon-note.gif) **说明:** + >moduleName要与驱动定义中的相同。 + + ``` + root { + ... + platform :: host { + device_gpio :: device { + device0 :: deviceNode { + policy = 0; + priority = 10; + permission = 0644; + moduleName = "SOC_NAME_gpio_driver"; + } + } + } + } + ``` + + diff --git a/zh-cn/device-dev/porting/transplant-smallchip-drive.md b/zh-cn/device-dev/porting/transplant-smallchip-drive.md new file mode 100644 index 0000000000..8d265ae4d0 --- /dev/null +++ b/zh-cn/device-dev/porting/transplant-smallchip-drive.md @@ -0,0 +1,9 @@ +# 驱动移植 + +- **[移植概述](transplant-smallchip-drive-des.md)** + +- **[平台驱动移植](transplant-smallchip-drive-plat.md)** + +- **[器件驱动移植](transplant-smallchip-drive-oom.md)** + + diff --git a/zh-cn/device-dev/porting/transplant-smallchip-kernel-a.md b/zh-cn/device-dev/porting/transplant-smallchip-kernel-a.md new file mode 100644 index 0000000000..f4de2f397d --- /dev/null +++ b/zh-cn/device-dev/porting/transplant-smallchip-kernel-a.md @@ -0,0 +1,265 @@ +# LiteOS-A内核 + +- [移植概述](#section14876256185510) + - [移植场景](#section1986014410569) + - [目录规范](#section10916181716564) + +- [基础适配](#section814974018565) + - [编程样例](#section10854481825) + +- [验证](#section646410453212) + +## 移植概述 + +### 移植场景 + +LiteOS-A当前支持ARMv7-a指令集架构,如果三方芯片为ARMv7-a架构,可以进行内核基础适配;否则还需要先根据芯片的架构来新增内核对该芯片架构的支持,这个工作较为复杂,不在这篇文章范围内。 + +### 目录规范 + +LiteOS-A目录规范参考[LiteOS-A 简介](https://gitee.com/openharmony/kernel_liteos_a)。 + +## 基础适配 + +LiteOS-A提供系统运行所需的系统初始化流程和定制化配置选项。移植过程中,需要关注初始化流程中跟硬件配置相关的函数。 + +如下图所示,LiteOS-A的初始化流程主要包含以下五步: + +1. 新增target\_config.h文件,并且编写单板内存相关的配置宏DDR\_MEM\_ADDR和DDR\_MEM\_SIZE,分别表示内存起始地址和内存的长度,预链接脚本board.ld.S会根据这两个宏进行展开生成链接脚本board.ld。 +2. 链接阶段根据链接脚本board.ld生成内核镜像。 +3. 单核CPU镜像运行入口为汇编文件reset\_vector\_up.S,多核CPU的入口为reset\_vector\_mp.S,在汇编文件中进行中断向量表初始化、MMU页表初始化等操作。 +4. reset\_vector.S汇编代码最终会跳转到C语言的main函数,进行硬件时钟、软件定时器、内存和任务等初始化,这个过程会依赖target\_config.h的特性宏配置,最后会创建SystemInit任务,并且开启任务调度OsSchedStart\(\)。 +5. SystemInit任务在单板代码中实现,其中调用DeviceManagerStart函数进行HDF驱动初始化,这个过程会调用单板代码中的驱动配置文件hdf.hcs以及drivers源码实现。 + +整体启动流程如下图所示: + +**图 1** 整体启动流程 + + +![](figure/zh-cn_image_0000001126358814.png) + +从图1中可以看到,内核基础适配需要单板进行适配的代码包含三部分: + +- 新增target\_config.h文件,其中新增单板硬件配置参数和特性开关的配置参数,具体说明如下: + + **表 1** target\_config.h配置项说明 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    配置项

    +

    说明

    +

    OS_SYS_CLOCK

    +

    系统cycle的频率

    +

    DDR_MEM_ADDR

    +

    系统内存的起始地址

    +

    DDR_MEM_SIZE

    +

    系统内存的大小

    +

    PERIPH_PMM_BASE

    +

    外设寄存器的起始地址

    +

    PERIPH_PMM_SIZE

    +

    外设寄存器的长度大小

    +

    OS_HWI_MIN

    +

    系统中断最小值

    +

    OS_HWI_MAX

    +

    系统中断最大值

    +

    NUM_HAL_INTERRUPT_UART0

    +

    UART0中断号

    +

    UART0_REG_BASE

    +

    UART0寄存器基址

    +

    GIC_BASE_ADDR

    +

    GIC中断寄存器基址

    +

    GICD_OFFSET

    +

    GICD相对GIC基址的偏移地址

    +

    GICC_OFFSET

    +

    GICC相对GIC基址的偏移地址

    +
    + +- SystemInit函数用于单板用户态业务初始化,典型的初始化场景如图2所示: + + **图 1** 业务启动流程 + + + ![](figure/zh-cn_image_0000001126198996.png) + +- main函数用于内核基础初始化和单板内核态业务初始化,流程如下图3所示,整体由内核启动框架主导初始化流程,图中浅蓝色部分为启动框架中可接受外部模块注册启动的阶段。 + + >![](../public_sys-resources/icon-caution.gif) **注意:** + >同一层级内的模块不能有依赖关系。 + + **图 2** 内核启动框架 + ![](figure/内核启动框架.jpg "内核启动框架") + + **表 2** 启动框架层级 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    层级

    +

    说明

    +

    LOS_INIT_LEVEL_EARLIEST

    +

    最早期初始化

    +

    说明:不依赖架构,单板以及后续模块会对其有依赖的纯软件模块初始化

    +

    例如:Trace模块

    +

    LOS_INIT_LEVEL_ARCH_EARLY

    +

    架构早期初始化

    +

    说明:架构相关,后续模块会对其有依赖的模块初始化,如启动过程中非必需的功能,建议放到LOS_INIT_LEVEL_ARCH层

    +

    LOS_INIT_LEVEL_PLATFORM_EARLY

    +

    平台早期初始化

    +

    说明:单板平台、驱动相关,后续模块会对其有依赖的模块初始化,如启动过程中必需的功能,建议放到LOS_INIT_LEVEL_PLATFORM层

    +

    例如:uart模块

    +

    LOS_INIT_LEVEL_KMOD_PREVM

    +

    内存初始化前的内核模块初始化

    +

    说明:在内存初始化之前需要使能的模块初始化

    +

    LOS_INIT_LEVEL_VM_COMPLETE

    +

    基础内存就绪后的初始化

    +

    说明:此时内存初始化完毕,需要进行使能且不依赖进程间通讯机制与系统进程的模块初始化

    +

    例如:共享内存功能

    +

    LOS_INIT_LEVEL_ARCH

    +

    架构后期初始化

    +

    说明:架构拓展功能相关,后续模块会对其有依赖的模块初始化

    +

    LOS_INIT_LEVEL_PLATFORM

    +

    平台后期初始化

    +

    说明:单板平台、驱动相关,后续模块会对其有依赖的模块初始化

    +

    例如:驱动内核抽象层初始化(mmc、mtd)

    +

    LOS_INIT_LEVEL_KMOD_BASIC

    +

    内核基础模块初始化

    +

    说明:内核可拆卸的基础模块初始化

    +

    例如:VFS初始化

    +

    LOS_INIT_LEVEL_KMOD_EXTENDED

    +

    内核扩展模块初始化

    +

    说明:内核可拆卸的扩展模块初始化

    +

    例如:系统调用初始化、ProcFS初始化、Futex初始化、HiLog初始化、HiEvent初始化、LiteIPC初始化

    +

    LOS_INIT_LEVEL_KMOD_TASK

    +

    内核任务创建

    +

    说明:进行内核任务的创建(内核线程,软件定时器任务)

    +

    例如:资源回收系统常驻任务的创建、SystemInit任务创建、CPU占用率统计任务创建

    +
    + + 进行单板移植适配,推荐关注LOS\_INIT\_LEVEL\_ARCH至LOS\_INIT\_LEVEL\_KMOD\_TASK之间的层级,且尽可能拆分初始化行为进行细化阶段注册。 + + >![](../public_sys-resources/icon-note.gif) **说明:** + >启动框架中同一层级内的注册模块不能有依赖关系,建议新增模块按照上述启动阶段进行模块初始化的拆分,按需注册启动。 + >可通过查看系统编译生成文件OHOS\_Image.map中.rodata.init.kernel.\*段内的符号表来了解当前已注册进内核启动框架中的各个模块初始化入口,以及检查新注册的模块初始化入口是否生效。 + + +### 编程样例 + +在单板SDK文件中 + +``` +/* 内核启动框架头文件 */ +#include "los_init.h" +...... + +/* 新增模块的初始化函数 */ +unsigned int OsSampleModInit(void) +{ + PRINTK("OsSampleModInit SUCCESS!\n"); + ...... +} +...... +/* 在启动框架的目标层级中注册新增模块 */ +LOS_MODULE_INIT(OsSampleModInit, LOS_INIT_LEVEL_KMOD_EXTENDED); +``` + +## 验证 + +``` +main core booting up... +OsSampleModInit SUCCESS! +releasing 1 secondary cores +cpu 1 entering scheduler +cpu 0 entering scheduler +``` + +根据上述系统启动阶段的打印可知,内核在启动时进行了该注册模块的初始化函数调用,完成该模块的初始化操作。 + +系统启动完毕后进入内核态shell,能够运行task命令能够正常显示即可。 + +``` +OHOS # help +*******************shell commands:************************* + +arp cat cd chgrp chmod chown cp cpup +date dhclient dmesg dns format free help hwi +ifconfig ipdebug kill log ls lsfd memcheck mkdir +mount netstat oom partinfo partition ping ping6 pmm +pwd reset rm rmdir sem shm stack statfs +su swtmr sync systeminfo task telnet touch umount +uname v2p virstatfs vmm watch writeproc + +``` + diff --git a/zh-cn/device-dev/porting/transplant-smallchip-kernel-linux.md b/zh-cn/device-dev/porting/transplant-smallchip-kernel-linux.md new file mode 100644 index 0000000000..911329dbd1 --- /dev/null +++ b/zh-cn/device-dev/porting/transplant-smallchip-kernel-linux.md @@ -0,0 +1,125 @@ +# Linux内核 + +- [移植概述](#section6282121355111) + - [基本信息](#section19589322515) + - [Bootloader](#section19062510518) + +- [适配编译和烧录启动](#section11112101695215) +- [验证](#section17318153325311) + +## 移植概述 + +Linux内核移植主要涉及基于linux内核基线合入三方芯片补丁后,进行基础的内核编译构建及验证。 + +### 基本信息 + +当前Linux内核基线是基于Linux社区 4.19 LTS版本演进,合入CVE及bugfix补丁。具体信息参考[代码库](https://gitee.com/openharmony/kernel_linux),对应repo工程代码路径为kernel/linux-4.19。 + +### Bootloader + +可以使用芯片厂商自带的Bootloader,或者是开源Uboot等加载内核镜像。比如为支持Hi3516DV300开发板,OpenHarmony引入的开源[Uboot](https://gitee.com/openharmony/device_hisilicon_third_party_uboot)。 + +## 适配编译和烧录启动 + +1. 准备内核config(特别是芯片相关的config)。 + + config文件所在源码目录:kernel/linux/config/ + + 以hi3516dv300芯片为例,可在对应的linux-4.19/arch/arm/configs/目录下新建\_small\_defconfig,如hi3516dv300\_small\_defconfig表示针对hi3516dv300小型系统的defconfig。该config文件可以由基础defconfig文件small\_common\_defconfig与该芯片相关的config组合生成。 + +2. 准备芯片补丁。 + + 补丁文件所在源码目录:kernel/linux/patches/linux-4.19 + + 以hi3516dv300芯片为例,参考已有的patch目录hi3516dv300\_small\_patch目录,新建\_patch目录,放置相关芯片补丁,注意hdf.patch等驱动补丁。 + +3. 编译。 + + 具体内核编译入口脚本位于工程目录kernel/linux/patches/下面,版本级整编命令会通过BUILD.gn进入kernel\_module\_build.sh和kernel.mk,需要在这2个文件中针对性进行patch及defconfig文件路径、编译器、芯片架构、内核Image格式等的适配。 + + 通过编译错误日志调整补丁,典型错误场景: + + (1)补丁合入失败,出现冲突,需要进行上下文适配修改。 + + (2)编译失败,内核版本差异(函数实现调整等)需要针对性进行内核适配。 + + >![](../public_sys-resources/icon-caution.gif) **注意:** + >- 参考kernel.mk,在OpenHarmony工程的编译构建流程中会拷贝kernel/linux-4.19的代码环境后进行打补丁动作,在使用版本级编译命令前,需要kernel/linux-4.19保持原代码环境。 + >- 对应拷贝后的目录位于: out/<\*\*\*\>/kernel/linux-4.19,可以在该目录下进行补丁的修改适配。 + +4. 烧录启动。 + + 由于不同芯片的开发板的烧录方式不一样,此处不表述具体的烧录方式。需要注意烧录的各镜像的大小及启动参数的配置,参考hi3516dv300采用uboot启动参数: + + ``` + setenv bootargs 'mem=128M console=ttyAMA0,115200 root=/dev/mmcblk0p3 ro rootfstype=ext4 rootwait blkdevparts=mmcblk0:1M(boot),9M(kernel),50M(rootfs),50M(userfs)' + ``` + + +## 验证 + +调试init进程、启动shell和运行简单的用户态程序,验证内核移植是否成功。OpenHarmony[小型系统](https://device.harmonyos.com/cn/docs/start/introduce/oem_start_guide-0000001054913231)的OS镜像结构以及linux用户态的启动流程如下图1所示: + +**图 1** 基于linux内核的OS镜像结构和用户态程序启动流程 + + +![](figure/zh-cn_image_0000001126354076.png) + +基于上述流程,推荐按以下步骤完成验证: + +1. 制作根文件系统镜像。 + + 请参考[新建芯片解决方案和产品解决方案](https://device.harmonyos.com/cn/docs/develop/subsystems/oem_subsys_build_guide-0000001060378721)生成根文件系统镜像rootfs.img。从上图可以看到启动过程与产品配置强相关,在制作rootfs.img过程中请完成如下四种配置: + + - 组件配置 + + 产品组件配置文件vendor/\{company\}/\{product\}/config.json需配置启动恢复子系统\(startup\)的init\_lite组件和内核子系统的linux\_4\_1\_9组件。 + + - 系统服务配置 + + 系统服务配置文件vendor/\{company\}/\{product\}/init\_configs/init\_xxx.cfg需要启动shell服务。 + + - 文件系统配置 + + 文件系统配置vendor/\{company\}/\{product\}/fs.yml中需要创建“/bin/sh -\> mksh“和“/lib/ld-musl-arm.so.1 -\> libc.so“软连接,这两个文件分别是shell可执行程序和可执行程序依赖的c库。 + + - 启动配置 + + 启动配置在vendor/\{company\}/\{product\}/init\_configs/etc目录下,包括fstab、rsS和Sxxx文件,请按开发板实际情况配置。 + + + 编译完成后,可通过检查产品编译输出目录下的rootfs内容,确认rootfs.img文件生成是否符合预期。 + +2. 调试init进程和shell。 + + 烧录rootfs.img并调试init进程和shell,不同厂商的开发板的烧录工具和流程可能不同,请按芯片解决方案提供的流程进行烧录。烧录rootfs.img前请确认bootloader和linux内核启动正常。如果rootfs.img被内核正常挂载,接着将运行/bin/init程序,init进程为用户态的第一个应用程序,它的运行意味着用户态的开始。 + + init程序首先会调用/etc/init.d/rcS脚本,rcS脚本执行第一条命令为"/bin/mount -a”,该命令会加载fstab文件,在fstab中的命令执行完后rcS将顺序调用Sxxx脚本完成设备节点创建和扫描、文件权限配置等操作。 + + 最后,init程序会读取init.cfg系统服务配置文件。根据步骤1中的设置,init程序将会启动shell。如果上述流程运行正常,系统则会进入shell。 + + 若串口有如下版本号日志打印,则表示init程序启动正常: + + **图 2** init启动正常日志 + + + ![](figure/init.jpg) + + 正常进入shell后执行ls命令,串口打印信息如下图: + + **图 3** 正常进入shell后输入ls命令串口打印 + + + ![](figure/shell.jpg) + +3. 配置NFS。 + + init进程和shell正常启动后,以服务端IP为192.168.1.22、客户端IP为192.168.1.4为例,可在根目录执行如下命令开启NFS: + + ``` + ifconfig eth0 192.168.1.4 netmask 255.255.255.0 + mkdir -p /storgage/nfs + mount -t nfs -o nolock,addr=192.168.1.22 192.168.1.22:/nfs /storage/nfs + ``` + + diff --git a/zh-cn/device-dev/porting/transplant-smallchip-kernel.md b/zh-cn/device-dev/porting/transplant-smallchip-kernel.md new file mode 100644 index 0000000000..a1adc2dde7 --- /dev/null +++ b/zh-cn/device-dev/porting/transplant-smallchip-kernel.md @@ -0,0 +1,7 @@ +# 移植内核 + +- **[LiteOS-A内核](transplant-smallchip-kernel-a.md)** + +- **[Linux内核](transplant-smallchip-kernel-linux.md)** + + diff --git a/zh-cn/device-dev/porting/transplant-smallchip-prepare-building.md b/zh-cn/device-dev/porting/transplant-smallchip-prepare-building.md new file mode 100644 index 0000000000..6ca5022e46 --- /dev/null +++ b/zh-cn/device-dev/porting/transplant-smallchip-prepare-building.md @@ -0,0 +1,142 @@ +# 编译构建 + +- [编译环境搭建](#section3336103410314) +- [编译构建系统介绍](#section354343816319) +- [新建芯片解决方案](#section18612153175011) + +## 编译环境搭建 + +首先请搭建OpenHarmony基础环境,步骤请参考轻量和小型系统入门[linux环境搭建](https://device.harmonyos.com/cn/docs/start/introduce/oem_minitinier_environment_lin-0000001105407498)。用户态和LiteOS-A的内核态编译均使用llvm编译器编译,安装方法在搭建基础环境中已提供。若选择移植linux内核,请执行如下命令安装gcc-arm-linux-gnueabi交叉编译工具链,用于编译linux内核态镜像: + +``` +sudo apt-get install gcc-arm-linux-gnueabi +``` + +## 编译构建系统介绍 + +编译构建流程、编译脚本编写、目录规则、独立编译单个组件、独立编译芯片解决方案等介绍请见[编译构建子系统介绍](https://gitee.com/openharmony/docs/blob/master/zh-cn/device-dev/subsystems/%E7%BC%96%E8%AF%91%E6%9E%84%E5%BB%BA.md)。 + +## 新建芯片解决方案 + +了解编译框架和搭建完编译环境后,请参考如下步骤新建芯片解决方案: + +1. 新建目录 + + 芯片解决方案的目录规则为:device/\{芯片解决方案厂商\}/\{开发板\}。以海思的hispark\_taurus开发板为例,在代码根目录执行如下命令建立目录: + + ``` + mkdir -p device/hisilicon/hispark_taurus + ``` + + 芯片解决方案目录树的规则如下: + + ``` + device + └── company # 芯片解决方案厂商 + └── board # 开发板名称 + ├── BUILD.gn # 编译脚本 + ├── hals # OS南向接口适配 + ├── linux # 可选,linux内核版本 + │ └── config.gni # linux版本编译配置 + └── liteos_a # 可选,liteos内核版本 + └── config.gni # liteos_a版本编译配置 + ``` + + 以hispark\_taurus移植linux内核为例,目录树应该如下: + + ``` + device + └── hisilicon + └── hispark_tautus + ├── BUILD.gn + ├── hals + ├── ...... + └── linux + └── config.gni + ``` + + 目录树建立后开发板相关的源码放到hispark\_taurus目录下。 + +2. 配置开发板编译选项 + + [步骤1](#li20894101862)中的config.gni可配置开发板相关的编译选项,编译构建框架将会遵照该配置文件中的参数编译所有用户态OS组件。其中关键的字段说明如下: + + ``` + kernel_type: 开发板使用的内核类型,例如:“liteos_a”, “liteos_m”, “linux”。 + kernel_version: 开发板使用的内核版本,例如:“4.19”。 + board_cpu: 开发板CPU类型,例如:“cortex-a7”, “riscv32”。 + board_arch: 开发板芯片arch, 例如: “armv7-a”, “rv32imac”。 + board_toolchain: 开发板自定义的编译工具链名称,例如:“gcc-arm-none-eabi”。若为空,则使用默认为ohos-clang。 + board_toolchain_prefix:编译工具链前缀,例如:“gcc-arm-none-eabi”。 + board_toolchain_type: 编译工具链类型,目前支持gcc和clang。例如:“gcc” ,“clang”。 + board_cflags: 开发板配置的c文件编译选项。 + board_cxx_flags: 开发板配置的cpp文件编译选项。 + board_ld_flags: 开发板配置的链接选项。 + ``` + + 还以海思的hispark\_taurus开发板为例,对应的device/hisilicon/hispark\_taurus/config.gni内容如下: + + ``` + # Board CPU type, e.g. "cortex-a7", "riscv32". + board_cpu = "cortex-a7" + + # Toolchain name used for system compiling. + # E.g. gcc-arm-none-eabi, arm-linux-harmonyeabi-gcc, ohos-clang, riscv32-unknown-elf. + # Note: The default toolchain is "ohos-clang". It's not mandatory if you use the default toochain. + board_toolchain = "mips-linux-gnu-gcc" + + # The toolchain path instatlled, it's not mandatory if you have added toolchian path to your ~/.bashrc. + board_toolchain_path = + rebase_path("//prebuilts/gcc/linux-x86/arm/arm-linux-ohoseabi-gcc/bin", + root_build_dir) + + # Compiler prefix. + board_toolchain_prefix = "arm-linux-ohoseabi-" + + # Compiler type, "gcc" or "clang". + board_toolchain_type = "gcc" + + # Board related common compile flags. + board_cflags = [ + ] + board_cxx_flags = [ + ] + board_ld_flags = [] + + # Board related headfiles search path. + board_include_dirs = [] + board_include_dirs += [ rebase_path( + "//prebuilts/gcc/linux-x86/arm/arm-linux-ohoseabi-gcc/target/usr/include", + root_build_dir) ] + + # Board adapter dir for OHOS components. + board_adapter_dir = "" + + # Sysroot path. + board_configed_sysroot = "" + + # Board storage type, it used for file system generation. + storage_type = "emmc" + ``` + +3. 编写开发板编译脚本 + + 步骤1中的BUILD.gn为新增的开发板的编译入口,主要用于编译开发板相关的代码,主要为设备侧驱动、设备侧接口适配\(媒体,图形等\)和开发板的SDK等等。 + + 海思的hispark\_taurus开发板的device/hisilicon/hispark\_taurus/BUILD.gn可写成: + + ``` + # group名称建议与开发板名称一致 + group("hispark_taurus") { + deps = [ "//kernel/linux/patches:linux_kernel" ] # 拉起内核编译 + deps += [ + ...... # 开发板其他编译单元 + ] + } + ``` + +4. 编译调试 + + 在开发板目录下执行hb set和hb build即可启动芯片解决方案的编译,编译框架会以开发板下的BUILD.gn为入口启动编译。 + + diff --git a/zh-cn/device-dev/porting/transplant-smallchip-prepare-needs.md b/zh-cn/device-dev/porting/transplant-smallchip-prepare-needs.md new file mode 100644 index 0000000000..afe392369f --- /dev/null +++ b/zh-cn/device-dev/porting/transplant-smallchip-prepare-needs.md @@ -0,0 +1,98 @@ +# 移植须知 + +本文详细介绍如何将OpenHarmony[小型系统](https://device.harmonyos.com/cn/docs/start/introduce/oem_start_guide-0000001054913231)的linux和LiteOS-A内核移植到新的开发板上,要求读者具有一定的嵌入式系统开发经验。建议先查看[入门指导](https://gitee.com/openharmony/docs/blob/master/zh-cn/OpenHarmony-Overview_zh.md),以了解OpenHarmony软件架构、目录结构、内核子系统和驱动子系统相关知识。当前小型系统已适配的开发板如下表所示: + +**表 1** OpenHarmony小型系统已适配的开发板 + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    开发板

    +

    内核

    +

    arch

    +

    ROM

    +

    RAM

    +

    文件系统

    +

    Flash 类型

    +

    hispark_taurus

    +

    LiteOS-A和linux-4.19

    +

    ARM cortex-a7

    +

    8G

    +

    1GB

    +

    VFAT、EXT4

    +

    eMMC4.5

    +

    hispark_aries

    +

    LiteOS-A

    +

    ARM cortex-a7

    +

    16M

    +

    512M

    +

    JFFS2

    +

    SPI NOR

    +
    + +表1中的开发板可作为待移植开发板的参考,当前LiteOS-A和linux-4.19支持的arch、ROM占用、支持的文件系统和支持的Flash类型如下表所示: + +**表 2** OpenHarmony小型系统内核移植信息表 + + + + + + + + + + + + + + + + + + + + + + +

    内核

    +

    支持的arch

    +

    ROM

    +

    文件系统

    +

    Flash类型

    +

    LiteOS-A

    +

    ARMv7

    +

    > 2M

    +

    VFAT、JFFS2、YAFFS2

    +

    SPI NOR、NAND、EMMC

    +

    linux-4.19

    +

    ARM, ARM64、 MIPS、 X86等

    +

    > 5M

    +

    VFAT、JFFS2、YAFFS、EXT/2/3/4、NFS等等

    +

    NOR、NAND、EMMC等

    +
    + diff --git a/zh-cn/device-dev/porting/transplant-smallchip-prepare.md b/zh-cn/device-dev/porting/transplant-smallchip-prepare.md new file mode 100644 index 0000000000..6ec4b45dff --- /dev/null +++ b/zh-cn/device-dev/porting/transplant-smallchip-prepare.md @@ -0,0 +1,7 @@ +# 移植准备 + +- **[移植须知](transplant-smallchip-prepare-needs.md)** + +- **[编译构建](transplant-smallchip-prepare-building.md)** + + diff --git a/zh-cn/device-dev/porting/transplant-smallchip.md b/zh-cn/device-dev/porting/transplant-smallchip.md new file mode 100644 index 0000000000..4ba38ff448 --- /dev/null +++ b/zh-cn/device-dev/porting/transplant-smallchip.md @@ -0,0 +1,9 @@ +# 小型系统芯片移植指导 + +- **[移植准备](../porting/transplant-smallchip-prepare.md)** + +- **[移植内核](../porting/transplant-smallchip-kernel.md)** + +- **[驱动移植](../porting/transplant-smallchip-drive.md)** + + diff --git a/zh-cn/device-dev/porting/transplant-thirdparty-cmake.md b/zh-cn/device-dev/porting/transplant-thirdparty-cmake.md new file mode 100644 index 0000000000..fb23041d28 --- /dev/null +++ b/zh-cn/device-dev/porting/transplant-thirdparty-cmake.md @@ -0,0 +1,435 @@ +# CMake方式组织编译的库移植 + +- [源码获取](#section1771132116245) +- [移植思路](#section9737174410328) +- [交叉编译](#section38205577332) + - [编译参考](#section1088111263418) + - [设置执行交叉编译](#section8168182883515) + +- [测试](#section6686144293611) +- [将该库编译添加到OpenHarmony工程中](#section1651053153715) + +以double-conversion库为例,其移植过程如下文所示 + +## 源码获取 + +从仓库[获取double-conversion源码](https://github.com/google/double-conversion),其目录结构如下表: + +**表 1** 源码目录结构 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    名称

    +

    描述

    +

    double-conversion/cmake/

    +

    CMake组织编译使用到的模板

    +

    double-conversion/double-conversion/

    +

    源文件目录

    +

    double-conversion/msvc/

    +

    -

    +

    double-conversion/test/

    +

    测试用例源文件

    +

    double-conversion/.gitignore

    +

    -

    +

    double-conversion/AUTHORS

    +

    -

    +

    double-conversion/BUILD

    +

    -

    +

    double-conversion/CMakeLists.txt

    +

    CMake方式顶层编译组织文件

    +

    double-conversion/COPYING

    +

    -

    +

    double-conversion/Changelog

    +

    -

    +

    double-conversion/LICENSE

    +

    -

    +

    double-conversion/Makefile

    +

    -

    +

    double-conversion/README.md

    +

    -

    +

    double-conversion/SConstruct

    +

    -

    +

    double-conversion/WORKSPACE

    +

    -

    +
    + +## 移植思路 + +移植思路:通过修改工具链,交叉编译该三方库,生成OpenHarmony平台的可执行文件,最后再通过GN调用CMake的方式添加到OpenHarmony工程中。 + +## 交叉编译 + +### 编译参考 + +代码仓库的[README.md](https://github.com/google/double-conversion/blob/master/README.md)中详细介绍了使用CMake编译double-conversion库的步骤,以及测试方法。本文参考该指导设置该库的编译配置,并完成测试。若开发人员在移植过程中对该库的编译选项配置有疑惑的地方,可参考该指导。对于其他使用CMake可独立编译的三方库,在移植时可以参考其自带的编译指导。 + +### 设置执行交叉编译 + +CMake方式可通过指定工具链进行交叉编译,修改并编译该库,生成OpenHarmony平台的可执行文件,步骤如下: + +1. 设置工具链 + + 将下列clang工具链配置添加到该工程的顶层CMakeLists.txt(即[表1中的该文件](#table824211132418))中即可。 + + ``` + set(CMAKE_CROSSCOMPILING TRUE) + set(CMAKE_SYSTEM_NAME Generic) + set(CMAKE_CXX_COMPILER_ID Clang) + set(CMAKE_TOOLCHAIN_PREFIX llvm-) + #指定c编译工具(确保工具链所在路径已经添加到了PATH环境变量中)和编译标志,使用clang编译时标志中必须指定--target,否则无法交叉编译。 + set(CMAKE_C_COMPILER clang) + set(CMAKE_C_FLAGS "--target=arm-liteos -D__clang__ -march=armv7-a -w") + #指定c++编译工具(确保工具链所在路径已经添加到了PATH环境变量中)和编译标志,必须指定--target,否则无法交叉编译。 + set(CMAKE_CXX_COMPILER clang++) + set(CMAKE_CXX_FLAGS "--target=arm-liteos -D__clang__ -march=armv7-a -w") + #指定链接工具和链接标志,必须指定--target和--sysroot,其中OHOS_ROOT_PATH可通过cmake命令后缀参数来指定。 + set(MY_LINK_FLAGS "--target=arm-liteos --sysroot=${OHOS_SYSROOT_PATH}") + set(CMAKE_LINKER clang) + set(CMAKE_CXX_LINKER clang++) + set(CMAKE_C_LINKER clang) + set(CMAKE_C_LINK_EXECUTABLE "${CMAKE_C_LINKER} + ${MY_LINK_FLAGS} -o ") + set(CMAKE_CXX_LINK_EXECUTABLE "${CMAKE_CXX_LINKER} + ${MY_LINK_FLAGS} -o ") + #指定链接库的查找路径。 + set(CMAKE_SYSROOT ${OHOS_SYSROOT_PATH}) + ``` + +2. 执行编译 + + linux命令行中进入double-conversion的源文件目录(即[表1所示目录](#table824211132418)),执行下列命令: + + ``` + mkdir build && cd build + cmake .. -DBUILD_TESTING=ON -DOHOS_SYSROOT_PATH="..." + make -j + ``` + + 其中OHOS\_SYSROOT\_PATH需用绝对路径指定出sysroot目录的位置,以OpenHarmony为例即目录openHarmony/prebuilts/lite/sysroot的绝对路径。 + +3. 查看结果 + + 步骤2操作完成后,build目录下会生成静态库文件和测试用例: + + **表 2** 编译生成文件目录结构 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    名称

    +

    描述

    +

    double-conversion/build/libdouble-conversion.a

    +

    生成的静态库文件

    +

    double-conversion/build/test/

    +

    目录下存放生成的测试用例和相关CMake缓存文件

    +

    double-conversion/build/CMakeCache.txt

    +

    CMake构建过程中的缓存文件

    +

    double-conversion/build/CMakeFiles/

    +

    -

    +

    double-conversion/build/cmake_install.cmake

    +

    -

    +

    double-conversion/build/CTestTestfile.cmake

    +

    -

    +

    double-conversion/build/DartConfiguration.tcl

    +

    -

    +

    double-conversion/build/generated/

    +

    -

    +

    double-conversion/build/Makefile

    +

    -

    +

    double-conversion/build/Testing/

    +

    -

    +
    + + +## 测试 + +1. 搭建OpenHarmony环境 + + 以hi3518ev300为例,编译出OpenHarmony镜像,烧写到开发板,参考[开发Hi3518第一个示例程序](../quick-start/quickstart-lite-steps-board3518-running.md)。 + + 进入系统如下所示: + + **图 1** OpenHarmony启动成功界面 + ![](figure/OpenHarmony启动成功界面.png "OpenHarmony启动成功界面") + +2. 挂载nfs目录,将[表2](#table1452412391911)中test目录下cctest可执行文件放入nfs目录 +3. 执行用例 + + 该库采用非交叉编译时用例是通过make test执行,CMake会有相关的执行结果统计;交叉编译时无法使用该方法,因此可直接执行生成的测试文件完成测试。 + + - 挂载成功后执行下列命令可列出用例所有条目: + + ``` + cd nfs + ./cctest --list + ``` + + 上述命令执行结果部分展示: + + ``` + test-bignum/Assign< + test-bignum/ShiftLeft< + test-bignum/AddUInt64< + test-bignum/AddBignum< + test-bignum/SubtractBignum< + test-bignum/MultiplyUInt32< + test-bignum/MultiplyUInt64< + test-bignum/MultiplyPowerOfTen< + test-bignum/DivideModuloIntBignum< + test-bignum/Compare< + test-bignum/PlusCompare< + test-bignum/Square< + test-bignum/AssignPowerUInt16< + test-bignum-dtoa/BignumDtoaVariousDoubles< + test-bignum-dtoa/BignumDtoaShortestVariousFloats< + test-bignum-dtoa/BignumDtoaGayShortest< + test-bignum-dtoa/BignumDtoaGayShortestSingle< + test-bignum-dtoa/BignumDtoaGayFixed< + test-bignum-dtoa/BignumDtoaGayPrecision< + test-conversions/DoubleToShortest< + test-conversions/DoubleToShortestSingle< + ... + ``` + + - 以test-bignum条目为例,执行下列命令开始测试: + + ``` + ./cctest test-bignum + ``` + + 测试结果如下则表示通过: + + ``` + Ran 13 tests. + ``` + + +## 将该库编译添加到OpenHarmony工程中 + +1. 复制库到OpenHarmony工程中 + + 拷贝已经能够成功交叉编译的库到OpenHarmony的third\_party目录,为了不修改要移植的三方库目录下的BUILD.gn文件,再添加一层目录放置新增的gn转CMake编译适配文件,新增的文件有BUILD.gn、build\_thirdparty.py、 config.gni,新增后的目录结构如下所示。 + + **表 3** 添加到工程后的目录结构 + + + + + + + + + + + + + + + + + + + +

    名称

    +

    描述

    +

    openHarmony/third_party/double-conversion/BUILD.gn

    +

    将三方库加入工程的gn适配文件

    +

    openHarmony/third_party/double-conversion/build_thirdparty.py

    +

    GN调用shell命令脚本文件,由上面GN文件将相关命令传入,实现GN转CMake

    +

    openHarmony/third_party/double-conversion/config.gni

    +

    三方库编译配置文件,可修改该文件来配置用例是否参与构建等

    +

    openHarmony/third_party/double-conversion/double-conversion/

    +

    要移植的三方库目录

    +
    + +2. 添加gn到CMake适配文件 + + - **新增的BUILD.gn文件实现如下,其他采用CMake方式可独立编译的三方库移植到OpenHarmony平台时只需修改路径即可**。 + + ``` + import("config.gni") + group("double-conversion") { + if (ohos_build_thirdparty_migrated_from_fuchisa == true) { + deps = [":make"] + } + } + if (ohos_build_thirdparty_migrated_from_fuchisa == true) { + action("make") { + script = "//third_party/double-conversion/build_thirdparty.py" + outputs = ["$root_out_dir/log_dc.txt"] + exec_path = rebase_path(rebase_path("./build", ohos_third_party_dir)) + command = "rm * .* -rf && $CMAKE_TOOLS_PATH/cmake .. $CMAKE_FLAG $CMAKE_TOOLCHAIN_FLAG && make -j" + args = [ + "--path=$exec_path", + "--command=${command}" + ] + } + } + ``` + + - **新增的config.gni用于配置该库,实现如下,其他采用CMake方式可独立编译的三方库移植到OpenHarmony时只需修改CMAKE\_FLAG的配置即可。** + + ``` + #CMAKE_FLAG: config compile feature + CMAKE_FLAG = "-DBUILD_TESTING=ON -DCMAKE_CXX_STANDARD=11" + + #toolchain:follow up-layer,depend on $ohos_build_compiler + if (ohos_build_compiler == "clang") { + CMAKE_TOOLCHAIN_FLAG = "-DOHOS_SYSROOT_PATH=${ohos_root_path}prebuilts/lite/sysroot/" + } else { + CMAKE_TOOLCHAIN_FLAG = "" + } + + #CMake tools path,no need setting if this path already joined to $PATH. + CMAKE_TOOLS_PATH = "setting CMake tools path..." + ``` + + - **新增的build\_thirdparty.py实现如下,其他采用CMake方式可独立编译的三方库移植到OpenHarmony时无需修改即可使用。** + + ``` + import os + import sys + from subprocess import Popen + import argparse + import shlex + + def cmd_exec(command): + cmd = shlex.split(command) + proc = Popen(cmd) + proc.wait() + ret_code = proc.returncode + if ret_code != 0: + raise Exception("{} failed, return code is {}".format(cmd, ret_code)) + + def main(): + parser = argparse.ArgumentParser() + parser.add_argument('--path', help='Build path.') + parser.add_argument('--command', help='Build command.') + parser.add_argument('--enable', help='enable python.', nargs='*') + args = parser.parse_args() + + if args.enable: + if args.enable[0] == 'false': + return + + if args.path: + curr_dir = os.getcwd() + os.chdir(args.path) + if args.command: + if '&&' in args.command: + command = args.command.split('&&') + for data in command: + cmd_exec(data) + else: + cmd_exec(args.command) + os.chdir(curr_dir) + + if __name__ == '__main__': + sys.exit(main()) + ``` + + - 在配置文件中添加开关控制该库编译,默认设为关闭 + + 在//build/lite/ohos\_var.gni文件中添加下列配置: + + ``` + declare_args() { + ohos_build_thirdparty_migrated_from_fuchisa = true + } + ``` + +3. 编译构建 + + - 手动单独构建: + + 执行下列命令 + + ``` + hb build -T //third_party/double-conversion:double-conversion + ``` + + 编译成功则[build](#li15717101715249)目录下会生成静态库文件和测试用例 + + diff --git a/zh-cn/device-dev/porting/transplant-thirdparty-makefile.md b/zh-cn/device-dev/porting/transplant-thirdparty-makefile.md new file mode 100644 index 0000000000..ddabc1ef30 --- /dev/null +++ b/zh-cn/device-dev/porting/transplant-thirdparty-makefile.md @@ -0,0 +1,309 @@ +# Makefile方式组织编译的库移植 + +- [源码获取](#section114115321416) +- [设置交叉编译](#section81263255384) +- [测试](#section1830015913391) +- [将该库编译添加到OpenHarmony工程中](#section1898016213406) + +以yxml库为例,其移植过程如下文所示 + +## 源码获取 + +从仓库[获取yxml源码](https://github.com/getdnsapi/yxml),其目录结构如下表: + +**表 1** 源码目录结构 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    名称

    +

    描述

    +

    yxml/bench/

    +

    benchmark相关代码

    +

    yxml/test/

    +

    测试输入输出文件,及测试脚本

    +

    yxml/Makefile

    +

    编译组织文件

    +

    yxml/.gitattributes

    +

    -

    +

    yxml/.gitignore

    +

    -

    +

    yxml/COPYING

    +

    -

    +

    yxml/yxml.c

    +

    -

    +

    yxml/yxml.c.in

    +

    -

    +

    yxml/yxml-gen.pl

    +

    -

    +

    yxml/yxml.h

    +

    -

    +

    yxml/yxml.md

    +

    -

    +

    yxml/yxml-states

    +

    -

    +
    + +## 设置交叉编译 + +设置Makefile的交叉编译工具链,修改并编译该库,生成OpenHarmony平台的可执行文件,步骤如下: + +1. 设置工具链 + + 将下列clang工具链配置替换掉yxml库根目录的MakeFile(即[表1中的文件](#table16520154171813))中的原有配置。 + + clang工具链配置 + + ``` + #设置交叉编译工具链,确保工具链所在路径已经添加到了PATH环境变量中 + CC:=clang + AR:=llvm-ar + #cflags中必须要添加--target及--sysroot选项 + CFLAGS:=-Wall -Wextra -Wno-unused-parameter -O2 -g --target=arm-liteos -march=armv7-a --sysroot=$(OHOS_ROOT_PATH)prebuilts/lite/sysroot + ``` + + 原有配置 + + ``` + CC:=gcc + AR:=ar + CFLAGS:=-Wall -Wextra -Wno-unused-parameter -O2 -g + ``` + +2. 执行编译 + + linux命令行中进入yxml的源文件目录(即图1所示目录),执行下列命令: + + ``` + make test OHOS_SYSROOT_PATH=... + ``` + + 其中OHOS\_SYSROOT\_PATH需用绝对路径指定出sysroot所在目录,以OpenHarmony为例即源码根目录prebuilts/lite/sysroot/所在的绝对路径。 + +3. 查看结果 + + 步骤2操作完成后,yxml下会生成out目录,里面有静态库文件和测试用例: + + **表 2** yxml编译生成目录 + + + + + + + + + + + + + +

    名称

    +

    描述

    +

    openHarmony/third_party/yxml/yxml/out/lib/

    +

    编译生成的静态库的存放目录

    +

    openHarmony/third_party/yxml/yxml/out/test/

    +

    编译生成的测试用例及其输入输出等文件的存放目录

    +
    + + +## 测试 + +yxml库测试步骤与double-conversion库基本一致,可参考[CMake方式组织编译的库移植](transplant-thirdparty-cmake.md#section6686144293611)的测试过程,以下内容介绍yxml库测试用例的使用方法: + +**表 3** 生成的test目录结构示意 + + + + + + + + + + + + + + + + + + + +

    名称

    +

    描述

    +

    openHarmony/third_party/yxml/yxml/out/test/test.sh

    +

    自动化测试脚本,由于OpenHarmony不支持脚本运行,因此无法使用,可参考其内容手动测试

    +

    openHarmony/third_party/yxml/yxml/out/test/test

    +

    用于测试的可执行文件

    +

    openHarmony/third_party/yxml/yxml/out/test/*.xml

    +

    测试输入文件

    +

    openHarmony/third_party/yxml/yxml/out/test/*.out

    +

    期望的输出文件

    +
    + +test.sh内容如下所示: + +``` +#!/bin/sh +for i in *.xml; do + b=`basename $i .xml` + o=${b}.out + t=${b}.test + ./test <$i >$t + if [ -n "`diff -q $o $t`" ]; then + echo "Test failed for $i:" + diff -u $o $t + exit 1 + fi +done +echo "All tests completed successfully." +``` + +由于OpenHarmony的shell中暂不支持输入输出重定向(<和\>),所以测试时需要将输入\*.xml文件内容直接复制进shell后回车,输出内容会直接展示在shell窗口。过程如下: + +下列操作假定已按照2.4节的步骤搭建OpenHarmony,挂载并进入nfs目录: + +1. 执行下列命令 + + ``` + ./test + ``` + +2. 复制\*.xml内容到shell + + 以[test目录](#table115941423164318)下pi01.xml为例,内容如下,输入到shell并回车: + + ``` + + ``` + +3. 比较shell中输出的内容与[test目录](#table115941423164318)中对应的\*.out文件是否一致 + + 输出结果如下: + + ``` + pistart SomePI + picontent abc + piend + elemstart a + elemend + ok + ``` + + 经比较与[test目录](#table115941423164318)下pi01.out内容一致,测试通过。 + + +## 将该库编译添加到OpenHarmony工程中 + +yxml库添加的过程除了适配文件build.gn和config.gni有些许变化外,其他和double-conversion库完全一致,参考[CMake方式组织编译的库移植](transplant-thirdparty-cmake.md#section1651053153715)的配置过程。要修改的适配文件及添加后的目录结构如下: + +- yxml库新增的BUILD.gn实现如下: + +``` +import("config.gni") +group("yxml") { + if (ohos_build_thirdparty_migrated_from_fuchisa == true) { + deps = [":make"] + } +} +if (ohos_build_thirdparty_migrated_from_fuchisa == true) { + action("make") { + script = "//third_party/yxml/build_thirdparty.py" + outputs = ["$target_out_dir/log_yxml.txt"] + exec_path = rebase_path(rebase_path("./yxml", root_build_dir)) + command = "make clean && $MAKE_COMMAND" + args = [ + "--path=$exec_path", + "--command=${command}" + ] + } +} +``` + +- yxml库新增的config.gni配置如下: + +``` +TEST_ENABLE = "YES" + +if (TEST_ENABLE == "YES") { + MAKE_COMMAND = "make test OHOS_SYSROOT_PATH=${ohos_root_path}prebuilts/lite/sysroot/" +} else { + MAKE_COMMAND = "make OHOS_SYSROOT_PATH=${ohos_root_path}prebuilts/lite/sysroot/" +} +``` + +- 添加完成后目录结构示意: + +**表 4** 添加到工程后的目录结构 + + + + + + + + + + + + + + + + + + + +

    名称

    +

    描述

    +

    openHarmony/third_party/yxml/BUILD.gn

    +

    将三方库加入工程的gn适配文件

    +

    openHarmony/third_party/yxml/build_thirdparty.py

    +

    GN调用shell命令脚本文件,由上面GN文件将相关命令传入,实现GN转Makefile

    +

    openHarmony/third_party/yxml/config.gni

    +

    三方库编译配置文件,可修改该文件来配置用例是否参与构建等

    +

    openHarmony/third_party/yxml/yxml/

    +

    要移植的三方库目录

    +
    + diff --git "a/zh-cn/device-dev/porting/\346\246\202\350\277\260.md" b/zh-cn/device-dev/porting/transplant-thirdparty-overview.md old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/porting/\346\246\202\350\277\260.md" rename to zh-cn/device-dev/porting/transplant-thirdparty-overview.md diff --git a/zh-cn/device-dev/porting/transplant-thirdparty.md b/zh-cn/device-dev/porting/transplant-thirdparty.md new file mode 100644 index 0000000000..ca27b2d339 --- /dev/null +++ b/zh-cn/device-dev/porting/transplant-thirdparty.md @@ -0,0 +1,9 @@ +# 三方库移植指导 + +- **[概述](transplant-thirdparty-overview.md)** + +- **[CMake方式组织编译的库移植](transplant-thirdparty-cmake.md)** + +- **[Makefile方式组织编译的库移植](transplant-thirdparty-makefile.md)** + + diff --git a/zh-cn/device-dev/porting/transplant.md b/zh-cn/device-dev/porting/transplant.md new file mode 100644 index 0000000000..bc8d8a3ad1 --- /dev/null +++ b/zh-cn/device-dev/porting/transplant.md @@ -0,0 +1,9 @@ +# 移植 + +- **[三方库移植指导](transplant-thirdparty.md)** + +- **[轻量系统芯片移植指导](transplant-minichip.md)** + +- **[小型系统芯片移植指导](transplant-smallchip.md)** + + diff --git "a/zh-cn/device-dev/porting/\344\270\211\346\226\271\345\272\223\347\247\273\346\244\215\346\214\207\345\257\274.md" "b/zh-cn/device-dev/porting/\344\270\211\346\226\271\345\272\223\347\247\273\346\244\215\346\214\207\345\257\274.md" deleted file mode 100755 index e54970ed8f..0000000000 --- "a/zh-cn/device-dev/porting/\344\270\211\346\226\271\345\272\223\347\247\273\346\244\215\346\214\207\345\257\274.md" +++ /dev/null @@ -1,9 +0,0 @@ -# 三方库移植指导 - -- **[概述](概述.md)** - -- **[CMake方式组织编译的库移植](CMake方式组织编译的库移植.md)** - -- **[Makefile方式组织编译的库移植](Makefile方式组织编译的库移植.md)** - - diff --git "a/zh-cn/device-dev/porting/\344\270\211\346\226\271\347\273\204\344\273\266\351\200\202\351\205\215.md" "b/zh-cn/device-dev/porting/\344\270\211\346\226\271\347\273\204\344\273\266\351\200\202\351\205\215.md" deleted file mode 100644 index 0999f32a53..0000000000 --- "a/zh-cn/device-dev/porting/\344\270\211\346\226\271\347\273\204\344\273\266\351\200\202\351\205\215.md" +++ /dev/null @@ -1,57 +0,0 @@ -# 三方组件适配 - -如果需要使用third\_party目录下与产品相关的三方组件,可能需要对三方组件进行适配,下面以比较常用的mbedtls为例,介绍下适配步骤,注意本小节中仅介绍如何将适配的代码与OpenHarmony的编译框架融合,不会详细介绍mbedtls本身的原理和适配代码的具体逻辑,这些内容请参考mbedtls官方网站上的适配指南。 - -1. 编写适配层代码 - - 根据mbedtls官网的适配指南,编写需要的适配层代码,以适配硬件随机数举例,下面的路径都是相对third\_party/mbedtls的路径: - - 1. 拷贝include/mbedtls/config.h到ports目录下,并修改打开MBEDTLS\_ENTROPY\_HARDWARE\_ALT开关。 - 2. 在ports目录下创建entropy\_poll\_alt.c文件include并实现entropy\_poll.h中的硬件随机数接口 - 3. 在BUILD.gn中的mbedtls\_sources中增加刚才适配的entropy\_poll\_alt.c的路径 - 4. 在BIULD.gn中的lite\_library\("mbedtls\_static"\)中增加一行MBEDTLS\_CONFIG\_FILE指定新配置文件的位置 - - ``` - lite_library("mbedtks_static") { - ... - defines += ["MBEDTLS_CONFIG_FILE=<../port/config.h>"] - ... - } - ``` - - - 注意,上面的修改最好都新建一个config或者新建一个xxx\_alt.c文件来修改,不要直接在原先的代码中修改,侵入式的修改会导致后续版本升级出现大量零散冲突,增加升级维护成本。 - -2. 制作patch - - 由于上面的适配是硬件相关的,上库代码时,不能直接放到通用的third\_party/mbedtls目录中,因此需要将上面的修改制作成patch,在编译之前通过打patch的方式注入到代码中。 - - 1. 首先增加设备的patch配置文件device///patch.yml - 2. 编辑device///patch.yml,增加要打的patch的信息: - - ``` - # 需要打patch的路径,路径均为相对代码根目录的路径 - third_party/mbedtls: - # 该路径下需要打的patch存放路径 - - device///third_party/mbedtls/adapter.patch - third_party/wpa_supplicant: - # 当一个路径下有多个patch的时候会依次执行patch - - device///third_party/wpa_supplicant/xxxxx.patch - - device///third_party/wpa_supplicant/yyyyy.patch - ... - ``` - - 3. 制作上述**步骤1**修改的patch并放到对应的目录即可 - -3. 使用带patch的编译 - - 想要在编译的时候带上patch,其他步骤不变,仅需要在触发编译的时候加上 --patch,例如全编译的命令编程 - - ``` - hb build -f --patch - ``` - - >![](public_sys-resources/icon-caution.gif) **注意:** - >最后一次打patch的产品信息会被记录,在进行下一次编译操作时,会对上一次的patch进行回退(即执行\`patch -p1 -R < xxx\`),回退patch失败或新增patch失败均会终止编译过程,请解决patch冲突后再次尝试编译。 - - diff --git "a/zh-cn/device-dev/porting/\344\270\211\346\226\271\350\212\257\347\211\207\347\247\273\346\244\215\346\214\207\345\257\274.md" "b/zh-cn/device-dev/porting/\344\270\211\346\226\271\350\212\257\347\211\207\347\247\273\346\244\215\346\214\207\345\257\274.md" deleted file mode 100755 index c6c7b4103e..0000000000 --- "a/zh-cn/device-dev/porting/\344\270\211\346\226\271\350\212\257\347\211\207\347\247\273\346\244\215\346\214\207\345\257\274.md" +++ /dev/null @@ -1,11 +0,0 @@ -# 三方芯片移植指导 - -- **[移植准备](移植准备.md)** - -- **[内核移植](内核移植.md)** - -- **[板级系统移植](板级系统移植.md)** - -- **[常见问题](常见问题.md)** - - diff --git "a/zh-cn/device-dev/porting/\345\206\205\346\240\270\345\237\272\347\241\200\351\200\202\351\205\215.md" "b/zh-cn/device-dev/porting/\345\206\205\346\240\270\345\237\272\347\241\200\351\200\202\351\205\215.md" deleted file mode 100755 index a4eaf54ec5..0000000000 --- "a/zh-cn/device-dev/porting/\345\206\205\346\240\270\345\237\272\347\241\200\351\200\202\351\205\215.md" +++ /dev/null @@ -1,83 +0,0 @@ -# 内核基础适配 - -- [基础适配](#section14523241594) -- [特性配置项](#section112994366592) - -芯片架构适配完成后,liteos-m提供系统运行所需的系统初始化流程和定制化配置选项。移植过程中,需要关注初始化流程中跟硬件配置相关的函数;了解内核配置选项,才能裁剪出适合单板的最小内核。 - -## 基础适配 - -如下图所示,基础适配主要分为以下两步: - -1. 启动文件startup.S和相应链接配置文件。 -2. main. c中的串口初始化和tick中断注册。 - -**图 1** 启动流程 - - -![](figures/zh-cn_image_0000001073943511.png) - -启动文件startup.S需要确保中断向量表的入口函数(例如reset\_vector)放在RAM的首地址,它由链接配置文件来指定。其中iar、keil和gcc工程的链接配置文件分别为xxx.icf、xxx.sct和xxx.ld,如果startup.S已经完成系统时钟初始化,并且能够引导到main函数,则启动文件不需要进行修改,采用厂商自带的startup.S即可,否则需要实现以上功能。 - -在main.c文件中,需要关注串口初始化UartInit和系统Tick的handler函数注册。 - -- UartInit函数表示单板串口的初始化,具体的函数名根据单板自行定义。这个函数是可选的,用户可以根据硬件单板是否支持串口来自行选择调用该函数。如果硬件单板支持串口,则该函数需要完成使能串口TX和RX通道,设置波特率。 -- HalTickStart设置tick中断的handler函数OsTickHandler。 - -对于中断向量表不可重定向的芯片,需要关闭LOSCFG\_PLATFORM\_HWI宏,并且在startup.S中新增tick中断的handler函数。 - -## 特性配置项 - -liteos\_m的完整配置能力及默认配置在los\_config.h定义,该头文件中的配置项可以根据不同的单板进行裁剪配置。 - -如果针对这些配置项需要进行不同的板级配置,则可将对应的配置项直接定义到对应单板的device/xxxx/target\_config.h文件中,其他未定义的配置项,采用los\_config.h中的默认值。 - -一份典型的配置参数如下: - -**表 1** 内核典型配置项说明 - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    配置项

    -

    说明

    -

    LOSCFG_BASE_CORE_SWTMR

    -

    软件定时器特性开关,1表示打开,0表示关闭

    -

    LOSCFG_BASE_CORE_SWTMR_ALIGN

    -

    对齐软件定时器特性开,1表示打开,依赖软件定时器特性打开,0表示关闭

    -

    LOSCFG_BASE_IPC_MUX

    -

    mux功能开关,1表示打开,0表示关闭

    -

    LOSCFG_BASE_IPC_QUEUE

    -

    队列功能开关,1表示打开,0表示关闭

    -

    LOSCFG_BASE_IPC_SEM

    -

    信号量功能开关,1表示打开,0表示关闭

    -

    LOSCFG_PLATFORM_EXC

    -

    异常特性开关,1表示打开,0表示关闭

    -

    LOSCFG_KERNEL_PRINTF

    -

    打印特性开关,1表示打开,0表示关闭

    -
    - diff --git "a/zh-cn/device-dev/porting/\345\206\205\346\240\270\347\247\273\346\244\215.md" "b/zh-cn/device-dev/porting/\345\206\205\346\240\270\347\247\273\346\244\215.md" deleted file mode 100755 index 1dfe36434a..0000000000 --- "a/zh-cn/device-dev/porting/\345\206\205\346\240\270\347\247\273\346\244\215.md" +++ /dev/null @@ -1,9 +0,0 @@ -# 内核移植 - -- **[移植概述](移植概述.md)** - -- **[内核基础适配](内核基础适配.md)** - -- **[内核移植验证](内核移植验证.md)** - - diff --git "a/zh-cn/device-dev/porting/\345\206\205\346\240\270\347\247\273\346\244\215\351\252\214\350\257\201.md" "b/zh-cn/device-dev/porting/\345\206\205\346\240\270\347\247\273\346\244\215\351\252\214\350\257\201.md" deleted file mode 100755 index 4604f13ad9..0000000000 --- "a/zh-cn/device-dev/porting/\345\206\205\346\240\270\347\247\273\346\244\215\351\252\214\350\257\201.md" +++ /dev/null @@ -1,59 +0,0 @@ -# 内核移植验证 - -在工程device目录下添加编译main.c示例程序文件,此示例程序的主要目的是:LOS\_KernelInit完成之后,创建两个任务,循环调度延时并打印日志信息,通过此方法可以验证系统是否可正常调度以及时钟是否正常。 - -``` -VOID TaskSampleEntry2(VOID) // 任务2的入口函数 -{ - while(1) { - LOS_TaskDelay(10000); - printf("taskSampleEntry2 running...\n"); - } -} - -VOID TaskSampleEntry1(VOID) // 任务1的入口函数 -{ - while(1) { - LOS_TaskDelay(2000); - printf("taskSampleEntry1 running...\n"); - } -} - -UINT32 TaskSample(VOID) -{ - UINT32 uwRet; - UINT32 taskID1,taskID2; - TSK_INIT_PARAM_S stTask1={0}; - stTask1.pfnTaskEntry = (TSK_ENTRY_FUNC)TaskSampleEntry1; - stTask1.uwStackSize = 0X1000; - stTask1.pcName = "taskSampleEntry1"; - stTask1.usTaskPrio = 6; //stTask1的任务优先级设定,不同于stTask2 - uwRet = LOS_TaskCreate(&taskID1, &stTask1); - - stTask1.pfnTaskEntry = (TSK_ENTRY_FUNC)TaskSampleEntry2; - stTask1.uwStackSize = 0X1000; - stTask1.pcName = "taskSampleEntry2"; - stTask1.usTaskPrio = 7; - uwRet = LOS_TaskCreate(&taskID2, &stTask1); - - return LOS_OK; -} - -LITE_OS_SEC_TEXT_INIT int main(void) -{ - UINT32 ret; - UartInit(); // 硬件串口配置,通过串口输出调试日志,实际函数名根据单板实现不一样而不一样。 - printf("\n\rhello world!!\n\r"); - ret = LOS_KernelInit(); - TaskSample(); - if (ret == LOS_OK) { - LOS_Start(); // 开始系统调度,循环执行stTask1/stTask2任务,串口输出任务日志 - } - while (1) { - __asm volatile("wfi"); - } -} -``` - -第一个任务运行正常后,说明最小系统的核心流程基本OK;由于xts用例框架对外依赖较多,主要是utils、bootstrap的链接脚本和编译框架,暂时无法支撑内核单独跑xts;此处略过内核测试套的测试,可以通过[XTS测试套](XTS认证.md)来覆盖最小系统是否完整移植成功。 - diff --git "a/zh-cn/device-dev/porting/\346\235\277\347\272\247\347\263\273\347\273\237\347\247\273\346\244\215.md" "b/zh-cn/device-dev/porting/\346\235\277\347\272\247\347\263\273\347\273\237\347\247\273\346\244\215.md" deleted file mode 100755 index 3029464912..0000000000 --- "a/zh-cn/device-dev/porting/\346\235\277\347\272\247\347\263\273\347\273\237\347\247\273\346\244\215.md" +++ /dev/null @@ -1,15 +0,0 @@ -# 板级系统移植 - -- **[移植概述](移植概述-0.md)** - -- **[板级驱动适配](板级驱动适配.md)** - -- **[HAL层实现](HAL层实现.md)** - -- **[系统组件调用](系统组件调用.md)** - -- **[三方组件适配](三方组件适配.md)** - -- **[XTS认证](XTS认证.md)** - - diff --git "a/zh-cn/device-dev/porting/\347\247\273\346\244\215\345\207\206\345\244\207.md" "b/zh-cn/device-dev/porting/\347\247\273\346\244\215\345\207\206\345\244\207.md" deleted file mode 100755 index 1637d5d893..0000000000 --- "a/zh-cn/device-dev/porting/\347\247\273\346\244\215\345\207\206\345\244\207.md" +++ /dev/null @@ -1,7 +0,0 @@ -# 移植准备 - -- **[移植须知](移植须知.md)** - -- **[编译构建适配流程](编译构建适配流程.md)** - - diff --git "a/zh-cn/device-dev/porting/\347\247\273\346\244\215\346\246\202\350\277\260-0.md" "b/zh-cn/device-dev/porting/\347\247\273\346\244\215\346\246\202\350\277\260-0.md" deleted file mode 100755 index a5d18d9bd4..0000000000 --- "a/zh-cn/device-dev/porting/\347\247\273\346\244\215\346\246\202\350\277\260-0.md" +++ /dev/null @@ -1,57 +0,0 @@ -# 移植概述 - -- [板级移植流程](#section1283115812294) -- [板级目录规范](#section6204129143013) - -## 板级移植流程 - -最小系统移植完成后,下一步进行板级系统移植,板级系统移植包含以下几步操作: - -1. 板级驱动适配。 -2. HAL层实现。 -3. XTS测试套。 -4. 业务功能验证。 - -**图 1** 单板驱动适配流程 -![](figures/单板驱动适配流程.png "单板驱动适配流程") - -## 板级目录规范 - -板级系统编译适配参考[编译系统介绍](编译构建适配流程.md),板级相关的驱动、SDK、目录、HAL实现存放在device目录,目录结构和具体描述如下: - -``` -. -├── device --- 单板样例 -│ └── xxx --- <单板厂商名> -│ └── xxx --- <单板名>,里面包含liteos-m内核的,并且能够运行的demo -│ ├── BUILD.gn --- 定义单板的编译配置文件 -│ ├── board --- 板子特定的实现(可选,如果本单板直接提供产品级demo,则相关应用层实现放在此目录) -│ ├── liteos_m --- 根据BUILD.gn文件中的kernel_type,使用liteos_m内核 -│ │ └── config.gni --- 编译选项 -│ ├── libraries --- 板级SDK -│ │ └── include --- SDK提供对外头文件 -│ │ └── ... --- binary or source -│ ├── main.c --- main函数入口(如果产品级存在相同定义,则使用产品级配置) -│ ├── target_config.h --- 板级内核配置 -│ ├── project --- 单板级工程配置文件(如果产品级存在相同定义,则使用产品级配置) -│ └── adapter --- 单板适配上层应用组件的适配层接口,根据能力可选 -│ └── hals -│ ├── communication -│ │ └── wifi_lite -│ │ ├── ... -│ └── iot_hardware -│ ├── upgrade -│ ├── utils -│ └── wifiiot_lite -├── vendor --- 提供端到端的OpenHarmony特性产品样例 -│ └── huawei --- 厂商名字 -│ └── wifiiot --- wifiiot表示特性产品 -│ ├── app -│ │ └── main.c --- 产品的main函数入口 -│ ├── project --- 工程配置文件 -│ ├── BUILD.gn --- 工程编译入口 -│ └── config.json --- 定义产品的编译配置文件,配置产品所使用的组件等。 -└── out --- 编译过程中的输出目录 - ├── ... --- 单板/产品编译产生的bin等 -``` - diff --git "a/zh-cn/device-dev/porting/\347\247\273\346\244\215\346\246\202\350\277\260.md" "b/zh-cn/device-dev/porting/\347\247\273\346\244\215\346\246\202\350\277\260.md" deleted file mode 100755 index 6f6b421748..0000000000 --- "a/zh-cn/device-dev/porting/\347\247\273\346\244\215\346\246\202\350\277\260.md" +++ /dev/null @@ -1,64 +0,0 @@ -# 移植概述 - -- [移植场景](#section93781277367) -- [目录规范](#section18127744153119) -- [芯片架构适配点](#section137431650339) - -## 移植场景 - -芯片架构适配是可选过程,如果在liteos\_m/kernel/arch目录下已经支持对应芯片架构,则可以跳过芯片架构适配,进行单板适配过程,否则需要进行芯片架构移植工作。 - -## 目录规范 - -模组芯片使用的内核为liteos-m,liteos-m中主要分为KAL、Components、Kernel和Utils四个模块。 - -- KAL模块作为内核对外的接口依赖Components模块和Kernel模块。 -- Components模块可插拔,它依赖Kernel模块。 - -- 在Kernel模块中,其中硬件相关的代码放在kernel的arch目录中,其余为硬件无关的代码。内核功能集(task、sem等)的实现依赖硬件相关的arch代码,例如任务上下文切换、原子操作等。 -- Utils模块作为基础代码块,被其他模块依赖。 - -**图 1** liteos-m内核模块图 - - -![](figures/zh-cn_image_0000001072304191.png) - -内核的目录结构和说明如下: - -``` -. -├── components --- 移植可选组件,依赖内核,单独对外提供头文件 -├── kal --- 内核抽象层,提供内核对外接口,当前支持cmsis接口和部分posix接口 -├── kernel --- 内核最小功能集代码 -│ ├── arch --- 内核指令架构层代码 -│ │ ├── arm --- arm32架构的代码 -│ │ │ ├── cortex-m3 --- cortex-m3架构的代码 -│ │ │ │ ├── iar --- iar编译工具链实现 -│ │ │ │ ├── keil --- keil编译工具链实现 -│ │ │ │ └── xxx --- xxx编译工具链实现 -│ │ │ └── cortex-m4 --- cortex-m4架构的代码 -│ │ │ ├── iar --- iar编译工具链实现 -│ │ │ ├── keil --- keil编译工具链实现 -│ │ │ └── xxx --- xxx编译工具链实现 -│ │ ├── include --- 所有的arch需要实现的函数定义,内核依赖 -│ │ └── risc-v --- risk-v架构 -│ │ └── gcc --- iar编译工具链实现 -│ ├── include --- 内核最小功能集代码 -│ └── src --- 内核最小功能集代码 -└──utils --- 基础代码,作为依赖的最底层,被系统依赖 -``` - -## 芯片架构适配点 - -如内核的[目录结构](#section18127744153119)所示,arch/include定义通用的芯片架构所需要实现的函数,另外芯片架构相关的代码会有部分的汇编代码,而汇编代码会因编译工具链的不同而不同,因此在具体的芯片架构下,还包含不同工具链(iar、keil、gcc等)的实现。 - -arch/include 目录定义通用的文件以及函数列表,该目录下的所有函数在新增arch组件时都需要适配,详见每一个头文件: - -``` -los_arch.h --- 定义芯片架构初始化所需要的函数 -los_atomic.h --- 定义芯片架构所需要实现的原子操作函数 -los_context.h --- 定义芯片架构所需要实现的任务上下文相关函数 -los_interrupt.h --- 定义芯片架构所需要实现的中断和异常相关的函数 -los_timer.h --- 定义芯片架构所需要实现的系统时钟相关的函数 -``` - diff --git "a/zh-cn/device-dev/porting/\347\247\273\346\244\215\351\241\273\347\237\245.md" "b/zh-cn/device-dev/porting/\347\247\273\346\244\215\351\241\273\347\237\245.md" deleted file mode 100755 index b28e2b5d0f..0000000000 --- "a/zh-cn/device-dev/porting/\347\247\273\346\244\215\351\241\273\347\237\245.md" +++ /dev/null @@ -1,84 +0,0 @@ -# 移植须知 - -- [移植目录](#section284217487490) -- [移植流程](#section639315306506) -- [移植规范](#section187870185219) - -本文为OpenHarmony平台系统开发人员和芯片(或模组)制造商提供基础的开发移植指导,典型的芯片架构例如cortex-m系列、risc-v系列等都可以按照本文进行移植,暂时不支持蓝牙服务。OpenHarmony是个持续演进的复杂项目,随着版本和API的改变,本文将会不断更新。 - -本文要求读者具有一定的嵌入式系统开发经验,因此它的重点未放在基本的OS基础介绍,而更多地描述OpenHarmony平台移植过程中主要操作和所需要关注的方面。 - -## 移植目录 - -OpenHarmony整体工程较为复杂,目录及实现为系统本身功能,如果不涉及复杂的特性增强,不需要关注每一层实现,移植过程中重点关注如下目录即可: - -**表 1** 移植过程中的重点目录 - - - - - - - - - - - - - - - - - - - -

    目录名称

    -

    描述

    -

    /build/lite

    -

    OpenHarmony基础编译构建框架

    -

    /kernel/liteos_m

    -

    基础内核,其中芯片架构相关实现在arch目录下

    -

    /device

    -

    板级相关实现,各个三方厂商按照OpenHarmony规范适配实现,device下具体目录结构及移植过程参见板级系统移植

    -

    /vendor

    -

    产品级相关实现,主要由华为或者产品厂商贡献

    -
    - -device目录规则:device/\{芯片解决方案厂商\}/\{开发板\}。以hisilicon的hispark\_taurus为例: - -``` -device -└── hisilicon # 芯片解决方案厂商名 - ├── common # 芯片解决方案开发板公共部分 - └── hispark_taurus # 开发板名称 - ├── BUILD.gn # 开发板编译入口 - ├── hals # 芯片解决方案厂商OS硬件适配 - ├── linux # linux版本 - │ └── config.gni # linux版本编译工具链和编译选项配置 - └── liteos_a # liteos-a版本 - └── config.gni # liteos_a版本编译工具链和编译选项配置 -``` - -vendor目录规则:vendor/\{产品解决方案厂商\}/\{产品名称\}。以华为的wifiiot产品为例: - -``` -vendor # 产品解决方案厂商 -└── huawei # 产品解决方案厂商名称 - └── wifiiot # 产品名称 - ├── hals # 产品解决方案厂商OS适配 - ├── BUILD.gn # 产品编译脚本 - └── config.json # 产品配置文件 -``` - -## 移植流程 - -OpenHarmony的device目录是基础芯片的适配目录,如果在三方芯片应用过程中发现此目录下已经有完整的芯片适配,则不需要再额外移植,直接跳过移植过程进行系统应用开发即可,如果该目录下无对应的芯片移植实现,则根据本文完成移植过程。OpenHarmony三方芯片移植主要过程如下: - -**图 1** 芯片移植关键步骤 -![](figures/芯片移植关键步骤.png "芯片移植关键步骤") - -## 移植规范 - -- 满足OpenHarmony[开源贡献基本规范和准则](https://gitee.com/openharmony/docs/blob/master/zh-cn/contribute/%E5%8F%82%E4%B8%8E%E8%B4%A1%E7%8C%AE.md)。 -- 三方芯片适配所需要贡献的代码主要在device、vendor和arch三个目录,参照[内核目录规范](移植概述.md)和[板级目录规范](移植概述-0.md#section6204129143013)满足基本目录命名和使用规范。 - diff --git "a/zh-cn/device-dev/porting/\347\263\273\347\273\237\347\273\204\344\273\266\350\260\203\347\224\250.md" "b/zh-cn/device-dev/porting/\347\263\273\347\273\237\347\273\204\344\273\266\350\260\203\347\224\250.md" deleted file mode 100755 index 5f2a6f6f6a..0000000000 --- "a/zh-cn/device-dev/porting/\347\263\273\347\273\237\347\273\204\344\273\266\350\260\203\347\224\250.md" +++ /dev/null @@ -1,26 +0,0 @@ -# 系统组件调用 - -- [SAMGR](#section105874301910) -- [DFX](#section20064420420) - -系统组件为上层应用提供基础能力,包括SAMGR(系统服务框架子系统)、DFX子系统等。在板级系统移植过程中,只需要选择使用即可,不用对其进行适配。 - -## SAMGR - -**基本介绍** - -系统服务框架基于面向服务的架构,提供了服务开发、服务的子功能开发、对外接口的开发、以及多服务共进程、进程间服务调用等开发能力。 - ->![](public_sys-resources/icon-notice.gif) **须知:** ->本组件在板级系统移植中必须要使用,否则其他服务组件无法运行。 - -**SAMGR使用说明,请参考:[SAMGR 使用指导](https://gitee.com/openharmony/distributedschedule_samgr_lite/blob/master/README_zh.md)** - -## DFX - -**基本介绍** - -DFX子系统主要包含DFR(Design for Reliability,可靠性)和DFT(Design for Testability,可测试性)特性,为开发者提供代码维测信息。 - -**DFX子系统使用说明,请参考:[DFX子系统使用指导](../subsystems/DFX.md)** - diff --git a/zh-cn/device-dev/bundles/public_sys-resources/icon-caution.gif b/zh-cn/device-dev/public_sys-resources/icon-caution.gif old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/bundles/public_sys-resources/icon-caution.gif rename to zh-cn/device-dev/public_sys-resources/icon-caution.gif diff --git a/zh-cn/device-dev/bundles/public_sys-resources/icon-danger.gif b/zh-cn/device-dev/public_sys-resources/icon-danger.gif old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/bundles/public_sys-resources/icon-danger.gif rename to zh-cn/device-dev/public_sys-resources/icon-danger.gif diff --git a/zh-cn/device-dev/bundles/public_sys-resources/icon-note.gif b/zh-cn/device-dev/public_sys-resources/icon-note.gif old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/bundles/public_sys-resources/icon-note.gif rename to zh-cn/device-dev/public_sys-resources/icon-note.gif diff --git a/zh-cn/device-dev/bundles/public_sys-resources/icon-notice.gif b/zh-cn/device-dev/public_sys-resources/icon-notice.gif old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/bundles/public_sys-resources/icon-notice.gif rename to zh-cn/device-dev/public_sys-resources/icon-notice.gif diff --git a/zh-cn/device-dev/bundles/public_sys-resources/icon-tip.gif b/zh-cn/device-dev/public_sys-resources/icon-tip.gif old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/bundles/public_sys-resources/icon-tip.gif rename to zh-cn/device-dev/public_sys-resources/icon-tip.gif diff --git a/zh-cn/device-dev/bundles/public_sys-resources/icon-warning.gif b/zh-cn/device-dev/public_sys-resources/icon-warning.gif old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/bundles/public_sys-resources/icon-warning.gif rename to zh-cn/device-dev/public_sys-resources/icon-warning.gif diff --git "a/zh-cn/device-dev/quick-start/Hi3516\345\274\200\345\217\221\346\235\277.md" "b/zh-cn/device-dev/quick-start/Hi3516\345\274\200\345\217\221\346\235\277.md" deleted file mode 100755 index 1a6f14d262..0000000000 --- "a/zh-cn/device-dev/quick-start/Hi3516\345\274\200\345\217\221\346\235\277.md" +++ /dev/null @@ -1,11 +0,0 @@ -# Hi3516开发板 - -- **[安装开发板环境](安装开发板环境-2.md)** - -- **[运行Hello OHOS](运行Hello-OHOS.md)** - -- **[驱动开发示例](驱动开发示例.md)** - -- **[常见问题](常见问题-3.md)** - - diff --git "a/zh-cn/device-dev/quick-start/Hi3516\345\274\200\345\217\221\346\235\277\344\273\213\347\273\215.md" "b/zh-cn/device-dev/quick-start/Hi3516\345\274\200\345\217\221\346\235\277\344\273\213\347\273\215.md" deleted file mode 100755 index 3e24c43eb0..0000000000 --- "a/zh-cn/device-dev/quick-start/Hi3516\345\274\200\345\217\221\346\235\277\344\273\213\347\273\215.md" +++ /dev/null @@ -1,42 +0,0 @@ -# Hi3516开发板介绍 - -- [简介](#section26131214194212) -- [开发板规格](#section15192203316533) - -## 简介 - -Hi3516DV300作为新一代行业专用Smart HD IP摄像机SOC,集成新一代ISP\(Image Signal Processor\)、H.265视频压缩编码器,同时集成高性能NNIE引擎,使得Hi3516DV300在低码率、高画质、智能处理和分析、低功耗等方面引领行业水平。 - -**图 1** Hi3516单板正面外观图 - - -![](figures/3516正面.png) - -## 开发板规格 - -**表 1** Hi3516开发板规格清单 - - - - - - - - - - - - - -

    规格类型

    -

    规格清单

    -

    处理器及内部存储

    -
    • Hi3516DV300芯片
    • DDR3 1GB
    • eMMC4.5,8GB容量
    -

    外部器件

    -
    • 以太网口
    • 音频视频
      • 1路语音输入
      • 1路单声道(AC_L)输出,接3W功放(LM4871)
      • MicroHDMI(1路HDMI 1.4)
      -
    • 摄像头
      • 传感器IMX335
      • 镜头M12,焦距4mm,光圈1.8
      -
    • 显示屏
      • LCD连接器(2.35寸)
      • LCD连接器(5.5寸)
      -
    • 外部器件及接口
      • SD卡接口
      • JTAG/I2S 接口
      • ADC接口
      • 舵机接口
      • Grove连接器
      • USB2.0(Type C)
      • 功能按键3个,2个用户自定义按键,1个升级按键
      • LED指示灯,绿灯,红灯
      -
    -
    - diff --git "a/zh-cn/device-dev/quick-start/Hi3518\345\274\200\345\217\221\346\235\277.md" "b/zh-cn/device-dev/quick-start/Hi3518\345\274\200\345\217\221\346\235\277.md" deleted file mode 100755 index 61807ea64d..0000000000 --- "a/zh-cn/device-dev/quick-start/Hi3518\345\274\200\345\217\221\346\235\277.md" +++ /dev/null @@ -1,9 +0,0 @@ -# Hi3518开发板 - -- **[安装开发板环境](安装开发板环境-4.md)** - -- **[运行Hello OHOS](运行Hello-OHOS-5.md)** - -- **[常见问题](常见问题-6.md)** - - diff --git "a/zh-cn/device-dev/quick-start/Hi3518\345\274\200\345\217\221\346\235\277\344\273\213\347\273\215.md" "b/zh-cn/device-dev/quick-start/Hi3518\345\274\200\345\217\221\346\235\277\344\273\213\347\273\215.md" deleted file mode 100755 index 1f77aeac07..0000000000 --- "a/zh-cn/device-dev/quick-start/Hi3518\345\274\200\345\217\221\346\235\277\344\273\213\347\273\215.md" +++ /dev/null @@ -1,57 +0,0 @@ -# Hi3518开发板介绍 - -- [简介](#section14815247616) -- [开发板规格](#section765112478446) - -## 简介 - -Hi3518EV300作为新一代智慧视觉处理SOC,集成新一代ISP\(Image Signal Processor\)以及H.265视频压缩编码器,同时采用先进低功耗工艺和低功耗架构设计,使其在低码率、高画质、低功耗等方面引领行业水平。 - -**图 1** Hi3518EV300单板正面外观图 -![](figures/Hi3518EV300单板正面外观图.png "Hi3518EV300单板正面外观图") - -**图 2** Hi3518EV300单板背面外观图 - - -![](figures/Hi3518正背面.png) - -## 开发板规格 - -**表 1** Hi3518开发板规格清单 - - - - - - - - - - - - - - - - - - - - - - -

    规格类型

    -

    规格清单

    -

    处理器内核

    -
    • 海思3518EV300
    -

    成像器件

    -
    • 1/2.9 F23
    -

    外部接口

    -
    • 外置麦克风MIC
    • 外置8Ω/1.5W扬声器
    -

    外部存储器接口

    -
    • TF卡

      最大支持128GB(通用FAT32格式)

      -
    -

    WLAN协议

    -
    • 支持 802.11 b/g/n
    -
    - diff --git "a/zh-cn/device-dev/quick-start/Hi3861\345\274\200\345\217\221\346\235\277.md" "b/zh-cn/device-dev/quick-start/Hi3861\345\274\200\345\217\221\346\235\277.md" deleted file mode 100755 index f6c5f5833f..0000000000 --- "a/zh-cn/device-dev/quick-start/Hi3861\345\274\200\345\217\221\346\235\277.md" +++ /dev/null @@ -1,11 +0,0 @@ -# Hi3861开发板 - -- **[安装开发板环境](安装开发板环境.md)** - -- **[WLAN联网](WLAN联网.md)** - -- **[运行Hello World](运行Hello-World.md)** - -- **[常见问题](常见问题-1.md)** - - diff --git "a/zh-cn/device-dev/quick-start/Hi3861\345\274\200\345\217\221\346\235\277\344\273\213\347\273\215.md" "b/zh-cn/device-dev/quick-start/Hi3861\345\274\200\345\217\221\346\235\277\344\273\213\347\273\215.md" deleted file mode 100755 index ac6a21df22..0000000000 --- "a/zh-cn/device-dev/quick-start/Hi3861\345\274\200\345\217\221\346\235\277\344\273\213\347\273\215.md" +++ /dev/null @@ -1,157 +0,0 @@ -# Hi3861开发板介绍 - -- [简介](#section19352114194115) -- [资源和约束](#section82610215014) -- [开发板规格](#section169054431017) -- [OpenHarmony关键特性](#section1317173016507) - -## 简介 - -Hi3861 WLAN模组是一片大约2cm\*5cm大小的开发板,是一款高度集成的2.4GHz WLAN SoC芯片,集成IEEE 802.11b/g/n基带和RF(Radio Frequency)电路。支持OpenHarmony,并配套提供开放、易用的开发和调试运行环境。 - -**图 1** Hi3861 WLAN模组外观图 - - -![](figures/3861正面.png) - -另外,Hi3861 WLAN模组还可以通过与Hi3861底板连接,扩充自身的外设能力,底板如下图所示。 - -**图 2** Hi3861底板外观图 - - -![](figures/zh-cn_image_0000001174350615.png) - -- RF电路包括功率放大器PA(Power Amplifier)、低噪声放大器LNA(Low Noise Amplifier)、RF Balun、天线开关以及电源管理等模块;支持20MHz标准带宽和5MHz/10MHz窄带宽,提供最大72.2Mbit/s物理层速率。 -- Hi3861 WLAN基带支持正交频分复用(OFDM)技术,并向下兼容直接序列扩频(DSSS)和补码键控(CCK)技术,支持IEEE 802.11 b/g/n协议的各种数据速率。 -- Hi3861芯片集成高性能32bit微处理器、硬件安全引擎以及丰富的外设接口,外设接口包括SPI(Synchronous Peripheral Interface)、UART(Universal Asynchronous Receiver & Transmitter)、I2C(The Inter Integrated Circuit)、PWM(Pulse Width Modulation)、GPIO(General Purpose Input/Output)和多路ADC(Analog to Digital Converter),同时支持高速SDIO2.0(Secure Digital Input/Output)接口,最高时钟可达50MHz;芯片内置SRAM(Static Random Access Memory)和Flash,可独立运行,并支持在Flash上运行程序。 -- Hi3861芯片适用于智能家电等物联网智能终端领域。 - - **图 3** Hi3861功能框图 - - - ![](figures/zh-cn_image_0000001128311066.png) - - -## 资源和约束 - -Hi3861 WLAN模组资源十分有限,整板共2MB FLASH,352KB RAM。在编写业务代码时,需注意资源使用效率。 - -## 开发板规格 - -**表 1** Hi3861 WLAN模组规格清单 - - - - - - - - - - - - - - - - - - - - - - - - - -

    规格类型

    -

    规格清单

    -

    通用规格

    -
    • 1×1 2.4GHz频段(ch1~ch14)
    • PHY支持IEEE 802.11b/g/n
    • MAC支持IEEE802.11 d/e/h/i/k/v/w
    -
    • 内置PA和LNA,集成TX/RX Switch、Balun等
    • 支持STA和AP形态,作为AP时最大支持6 个STA接入
    • 支持WFA WPA/WPA2 personal、WPS2.0
    • 支持与BT/BLE芯片共存的2/3/4 线PTA方案
    • 电源电压输入范围:2.3V~3.6V
    -
    • IO电源电压支持1.8V和3.3V
    -
    • 支持RF自校准方案
    • 低功耗:
      • Ultra Deep Sleep模式:5μA@3.3V
      • DTIM1:1.5mA@3.3V
      • DTIM3:0.8mA@3.3V
      -
    -

    PHY特性

    -
    • 支持IEEE802.11b/g/n单天线所有的数据速率
    • 支持最大速率:72.2Mbps@HT20 MCS7
    • 支持标准20MHz带宽和5M/10M窄带宽
    • 支持STBC
    • 支持Short-GI
    -

    MAC特性

    -
    • 支持A-MPDU,A-MSDU
    • 支持Blk-ACK
    • 支持QoS,满足不同业务服务质量需求
    -

    CPU子系统

    -
    • 高性能 32bit微处理器,最大工作频率160MHz
    • 内嵌SRAM 352KB、ROM 288KB
    • 内嵌 2MB Flash
    -

    外围接口

    -
    • 1个SDIO接口、2个SPI接口、2个I2C接口、3个UART接口、15个GPIO接口、7路ADC输入、6路PWM、1个I2S接口(注:上述接口通过复用实现)
    • 外部主晶体频率40M或24M
    -

    其他信息

    -
    • 封装:QFN-32,5mm×5mm
    • 工作温度:-40℃ ~ +85℃
    -
    - -## OpenHarmony关键特性 - -OpenHarmony基于Hi3861平台提供了多种开放能力,提供的关键组件如下表所示。 - -**表 2** OpenHarmony关键组件列表 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    组件名

    -

    能力介绍

    -

    WLAN服务

    -

    提供WLAN服务能力。包括:station和hotspot模式的连接、断开、状态查询等。

    -

    模组外设控制

    -

    提供操作外设的能力。包括:I2C、I2S、ADC、UART、SPI、SDIO、GPIO、PWM、FLASH等。

    -

    分布式软总线

    -

    OpenHarmony分布式网络中,提供设备被发现、数据传输的能力。

    -

    设备安全绑定

    -

    提供在设备互联场景中,数据在设备之间的安全流转的能力。

    -

    基础加解密

    -

    提供密钥管理、加解密等能力。

    -

    系统服务管理

    -

    系统服务管理基于面向服务的架构,提供了OpenHarmony统一化的系统服务开发框架。

    -

    启动引导

    -

    提供系统服务的启动入口标识。在系统服务管理启动时,调用boostrap标识的入口函数,并启动系统服务。

    -

    系统属性

    -

    提供获取与设置系统属性的能力。

    -

    基础库

    -

    提供公共基础库能力。包括:文件操作、KV存储管理等。

    -

    DFX

    -

    提供DFX能力。包括:流水日志、时间打点等。

    -

    XTS

    -

    提供OpenHarmony生态认证测试套件的集合能力。

    -
    - diff --git a/zh-cn/device-dev/quick-start/Readme-CN.md b/zh-cn/device-dev/quick-start/Readme-CN.md index 69991d66be..f7f7e0d931 100644 --- a/zh-cn/device-dev/quick-start/Readme-CN.md +++ b/zh-cn/device-dev/quick-start/Readme-CN.md @@ -1,41 +1,41 @@ # 快速入门 -- [轻量和小型系统入门](轻量和小型系统入门.md) - - [概述](概述.md) - - [了解开发板](了解开发板.md) - - [Hi3861开发板介绍](Hi3861开发板介绍.md) - - [Hi3516开发板介绍](Hi3516开发板介绍.md) - - [Hi3518开发板介绍](Hi3518开发板介绍.md) +- [轻量和小型系统入门](quickstart-lite.md) + - [概述](quickstart-lite-overview.md) + - [了解开发板](quickstart-lite-introduction.md) + - [Hi3861开发板介绍](quickstart-lite-introduction-hi3861.md) + - [Hi3516开发板介绍](quickstart-lite-introduction-hi3516.md) + - [Hi3518开发板介绍](quickstart-lite-introduction-hi3518.md) - - [搭建系统环境](搭建系统环境.md) - - [概述](概述-0.md) - - [Windows开发环境准备](Windows开发环境准备.md) - - [Ubuntu编译环境准备](Ubuntu编译环境准备.md) - - [常见问题](常见问题.md) + - [搭建系统环境](quickstart-lite-env-setup.md) + - [概述](quickstart-lite-env-setup-des.md) + - [Windows开发环境准备](quickstart-lite-env-setup-win.md) + - [Ubuntu编译环境准备](quickstart-lite-env-setup-lin.md) + - [常见问题](quickstart-lite-env-setup-faqs.md) - - [开发步骤](开发步骤.md) - - [Hi3861开发板](Hi3861开发板.md) - - [安装开发板环境](安装开发板环境.md) - - [WLAN联网](WLAN联网.md) - - [运行Hello World](运行Hello-World.md) - - [常见问题](常见问题-1.md) + - [开发步骤](quickstart-lite-steps.md) + - [Hi3861开发板](quickstart-lite-steps-board3861.md) + - [安装开发板环境](quickstart-lite-steps-board3861-setting.md) + - [WLAN联网](quickstart-lite-steps-board3861-connection.md) + - [运行Hello World](quickstart-lite-steps-board3861-running.md) + - [常见问题](quickstart-lite-steps-board3861-faqs.md) - - [Hi3516开发板](Hi3516开发板.md) - - [安装开发板环境](安装开发板环境-2.md) - - [运行Hello OHOS](运行Hello-OHOS.md) - - [驱动开发示例](驱动开发示例.md) - - [常见问题](常见问题-3.md) + - [Hi3516开发板](quickstart-lite-steps-board3516.md) + - [安装开发板环境](quickstart-lite-steps-board3516-setting.md) + - [运行Hello OHOS](quickstart-lite-steps-board3516-running.md) + - [驱动开发示例](quickstart-lite-steps-board3516-program.md) + - [常见问题](quickstart-lite-steps-board3516-faqs.md) - - [Hi3518开发板](Hi3518开发板.md) - - [安装开发板环境](安装开发板环境-4.md) - - [运行Hello OHOS](运行Hello-OHOS-5.md) - - [常见问题](常见问题-6.md) + - [Hi3518开发板](quickstart-lite-steps-board3518.md) + - [安装开发板环境](quickstart-lite-steps-board3518-setting.md) + - [运行Hello OHOS](quickstart-lite-steps-board3518-running.md) + - [常见问题](quickstart-lite-steps-board3518-faqs.md) -- [标准系统入门](标准系统入门.md) - - [入门介绍](入门介绍.md) - - [Windows开发环境准备](Windows开发环境准备-7.md) - - [搭建Ubuntu环境及编译(Docker方式)](搭建Ubuntu环境及编译(Docker方式).md) - - [搭建Ubuntu环境及编译(安装包方式)](搭建Ubuntu环境及编译(安装包方式).md) - - [镜像烧录](镜像烧录.md) - - [常见问题](常见问题-8.md) +- [标准系统入门](quickstart-standard.md) + - [常见问题](quickstart-lite-env-setup-faqs.md) + - [Windows开发环境准备](quickstart-standard-windows-environment.md) + - [搭建Ubuntu环境及编译(Docker方式)](quickstart-standard-docker-environment.md) + - [搭建Ubuntu环境及编译(安装包方式)](quickstart-standard-package-environment.md) + - [镜像烧录](quickstart-standard-burn.md) + - [常见问题](quickstart-standard-faq.md) diff --git "a/zh-cn/device-dev/quick-start/Ubuntu\347\274\226\350\257\221\347\216\257\345\242\203\345\207\206\345\244\207.md" "b/zh-cn/device-dev/quick-start/Ubuntu\347\274\226\350\257\221\347\216\257\345\242\203\345\207\206\345\244\207.md" deleted file mode 100755 index 168c618482..0000000000 --- "a/zh-cn/device-dev/quick-start/Ubuntu\347\274\226\350\257\221\347\216\257\345\242\203\345\207\206\345\244\207.md" +++ /dev/null @@ -1,361 +0,0 @@ -# Ubuntu编译环境准备 - -- [获取软件](#section1897711811517) -- [获取源码](#section1545225464016) -- [安装和配置Python](#section1238412211211) -- [安装gn](#section29216201423) -- [安装ninja](#section8762358731) -- [安装LLVM](#section12202192215415) -- [安装hb](#section15794154618411) - - [前提条件](#section1083283711515) - - [安装方法](#section11518484814) - - [卸载方法](#section3512551574) - -- [安装其他工具](#section830511218494) - - [安装方法](#section54409586499) - - -系统要求:Ubuntu16.04及以上64位系统版本。 - -编译环境搭建分为如下几步: - -1. 获取源码 -2. 安装和配置python -3. 安装gn -4. 安装ninja -5. 安装LLVM -6. 安装hb - ->![](public_sys-resources/icon-notice.gif) **须知:** ->- 针对Ubuntu编译环境我们提供了对应的Docker,该Docker封装了相关编译工具,选择使用Docker的开发者可跳过此章节。Docker使用可参考[Docker方式获取编译环境](../get-code/Docker编译环境.md)。 ->- 通常系统默认安装samba、vim等常用软件,需要做适当适配以支持Linux服务器与Windows工作台之间的文件共享。 ->- 想要详细了解OpenHarmony编译构建模块功能的开发者可参考[编译构建使用指南](../subsystems/编译构建.md)。 - -## 获取软件 - -Linux服务器通用环境配置需要的工具及其获取途径如下表所示: - -**表 1** Linux服务器开发工具及获取途径 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    开发工具

    -

    用途

    -

    获取途径

    -

    源码

    -

    功能开发

    -

    参考源码获取

    -

    Python3.7+

    -

    编译构建工具

    -

    通过互联网获取

    -

    gn

    -

    产生ninja编译脚本

    -

    https://repo.huaweicloud.com/harmonyos/compiler/gn/1717/linux/gn-linux-x86-1717.tar.gz

    -

    ninja

    -

    执行ninja编译脚本

    -

    https://repo.huaweicloud.com/harmonyos/compiler/ninja/1.9.0/linux/ninja.1.9.0.tar

    -

    -

    LLVM

    -

    -

    -

    编译工具链

    -

    -

    Master及OpenHarmony_v2.x分支/标签,请使用以下10.0.1版本:

    -

    https://repo.huaweicloud.com/harmonyos/compiler/clang/10.0.1-62608/linux/llvm.tar.gz

    -

    OpenHarmony_v1.x分支/标签,请使用以下9.0.0版本:

    -

    https://repo.huaweicloud.com/harmonyos/compiler/clang/9.0.0-36191/linux/llvm-linux-9.0.0-36191.tar

    -

    hb

    -

    OpenHarmony编译构建命令行工具

    -

    通过互联网获取

    -

    其他工具

    -

    编译构建中依赖的其他工具(如打包、镜像制作等)

    -

    通过互联网获取

    -
    - ->![](public_sys-resources/icon-notice.gif) **须知:** ->- 如果后续通过“HPM组件方式”或“HPM包管理器命令行工具方式”获取源码,不需要安装gn、ninja编译工具。 ->- (推荐)如果后续通过“镜像站点方式”或“代码仓库方式”获取源码,需要安装gn、ninja、LLVM编译工具。安装gn、ninja、LLVM编译工具时,请确保编译工具的环境变量路径唯一。 - -## 获取源码 - -开发者需要在Linux服务器上下载并解压一套源代码,请参见[源码获取](../get-code/源码获取.md)。 - -## 安装和配置Python - -1. 打开Linux编译服务器终端。 -2. 输入如下命令,查看python版本号,需使用python3.7以上版本。 - - ``` - python3 --version - ``` - - 如果低于python3.7版本,不建议直接升级,请按照如下步骤重新安装。以python3.8为例,按照以下步骤安装python。 - - 1. 运行如下命令,查看Ubuntu版本: - - ``` - cat /etc/issue - ``` - - 1. 根据Ubuntu不同版本,安装python。 - - 如果Ubuntu 版本为18+,运行如下命令。 - - ``` - sudo apt-get install python3.8 - ``` - - - 如果Ubuntu版本为16。 - - a. 安装依赖包 - - ``` - sudo apt update && sudo apt install software-properties-common - ``` - - b. 添加deadsnakes PPA 源,然后按回车键确认安装。 - - ``` - sudo add-apt-repository ppa:deadsnakes/ppa - ``` - - c. 安装python3.8 - - ``` - sudo apt upgrade && sudo apt install python3.8 - ``` - - - -3. 设置python和python3软链接为python3.8。 - - ``` - sudo update-alternatives --install /usr/bin/python python /usr/bin/python3.8 1 - sudo update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.8 1 - ``` - -4. 安装并升级Python包管理工具(pip3),任选如下一种方式。 - - **命令行方式:** - - ``` - sudo apt-get install python3-setuptools python3-pip -y - sudo pip3 install --upgrade pip - ``` - - - **安装包方式:** - - ``` - curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py - python get-pip.py - ``` - - - -## 安装gn - -1. 打开Linux编译服务器终端。 -2. [下载gn工具](https://repo.huaweicloud.com/harmonyos/compiler/gn/1717/linux/gn-linux-x86-1717.tar.gz)。 -3. 在根目录下创建gn文件夹。 - - ``` - mkdir ~/gn - ``` - -4. 解压gn安装包至\~/gn路径下。 - - ``` - tar -xvf gn-linux-x86-1717.tar.gz -C ~/gn - ``` - -5. 设置环境变量。 - - ``` - vim ~/.bashrc - ``` - - 将以下命令拷贝到.bashrc文件的最后一行,保存并退出。 - - ``` - export PATH=~/gn:$PATH - ``` - -6. 生效环境变量。 - - ``` - source ~/.bashrc - ``` - - -## 安装ninja - -1. 打开Linux编译服务器终端。 -2. [下载ninja工具](https://repo.huaweicloud.com/harmonyos/compiler/ninja/1.9.0/linux/ninja.1.9.0.tar)。 -3. 解压ninja安装包至\~/ninja路径下。 - - ``` - tar -xvf ninja.1.9.0.tar -C ~/ - ``` - -4. 设置环境变量。 - - ``` - vim ~/.bashrc - ``` - - 将以下命令拷贝到.bashrc文件的最后一行,保存并退出。 - - ``` - export PATH=~/ninja:$PATH - ``` - -5. 生效环境变量。 - - ``` - source ~/.bashrc - ``` - - -## 安装LLVM - -1. 打开Linux编译服务器终端。 -2. [下载LLVM工具](https://repo.huaweicloud.com/harmonyos/compiler/clang/10.0.1-62608/linux/llvm.tar.gz)。 - - >![](public_sys-resources/icon-note.gif) **说明:** - >针对OpenHarmony\_v1.x分支/标签,使用此链接[下载LLVM工具](https://repo.huaweicloud.com/harmonyos/compiler/clang/9.0.0-36191/linux/llvm-linux-9.0.0-36191.tar)。 - -3. 解压LLVM安装包至\~/llvm路径下。 - - ``` - tar -zxvf llvm.tar.gz -C ~/ - ``` - - >![](public_sys-resources/icon-note.gif) **说明:** - >针对OpenHarmony\_v1.x分支/标签,使用如下命令解压: - >``` - >tar -xvf llvm-linux-9.0.0-36191.tar -C ~/ - >``` - -4. 设置环境变量。 - - ``` - vim ~/.bashrc - ``` - - 将以下命令拷贝到.bashrc文件的最后一行,保存并退出。 - - ``` - export PATH=~/llvm/bin:$PATH - ``` - -5. 生效环境变量。 - - ``` - source ~/.bashrc - ``` - - -## 安装hb - -### 前提条件 - -请先安装Python 3.7.4及以上版本,请见[安装和配置Python](#section1238412211211)。 - -### 安装方法 - -1. 运行如下命令安装hb - - ``` - python3 -m pip install --user ohos-build - ``` - -2. 设置环境变量 - - ``` - vim ~/.bashrc - ``` - - 将以下命令拷贝到.bashrc文件的最后一行,保存并退出。 - - ``` - export PATH=~/.local/bin:$PATH - ``` - - 执行如下命令更新环境变量。 - - ``` - source ~/.bashrc - ``` - -3. 执行"hb -h",有打印以下信息即表示安装成功: - - ``` - usage: hb - - OHOS build system - - positional arguments: - {build,set,env,clean} - build Build source code - set OHOS build settings - env Show OHOS build env - clean Clean output - - optional arguments: - -h, --help show this help message and exit - ``` - - -### 卸载方法 - -``` -python3 -m pip uninstall ohos-build -``` - ->![](public_sys-resources/icon-notice.gif) **须知:** ->如果安装hb的过程中遇到问题,请参见下文[常见问题](常见问题.md)进行解决。 - -## 安装其他工具 - -### 安装方法 - -1. apt安装全部依赖的工具 - - ``` - sudo apt-get install build-essential gcc g++ make zlib* libffi-dev e2fsprogs pkg-config flex bison perl bc openssl libssl-dev libelf-dev libc6-dev-amd64 binutils binutils-dev libdwarf-dev u-boot-tools mtd-utils - ``` - - diff --git "a/zh-cn/device-dev/quick-start/WLAN\350\201\224\347\275\221.md" "b/zh-cn/device-dev/quick-start/WLAN\350\201\224\347\275\221.md" deleted file mode 100755 index ab20f083f9..0000000000 --- "a/zh-cn/device-dev/quick-start/WLAN\350\201\224\347\275\221.md" +++ /dev/null @@ -1,142 +0,0 @@ -# WLAN联网 - -- [源码编译](#section191121332125319) -- [镜像烧录](#section19458165166) -- [WLAN模组联网](#section194671619167) - -本示例将演示如何通过AT命令完成WLAN模组与网关联网。 - -## 源码编译 - -本节描述如何在Linux服务器上进行WLAN模组版本的编译。 - -如果Linux编译环境通过Docker方式安装,具体编译过程请参见[Docker方式获取编译环境](../get-code/Docker编译环境.md)的编译操作。如果Linux编译环境通过软件包方式安装,请参考如下步骤。 - -1. 打开DevEco Device Tool工具,点击“View \> Terminal”,进入终端界面。 - - **图 1** IDE终端工具打开方法 - - - ![](figures/1.png) - - 在终端界面使用ssh命令连接linux服务器,如“ssh user@ipaddr”。 - - **图 2** 终端界面示意图 - - - ![](figures/2.png) - -2. 进入代码根路径,并在终端窗口,执行脚本命令“hb set”、“.”,选择需要编译的版本“wifiiot\_hispark\_pegasus”。 - - **图 3** 在终端界面选择目标构建版本示意图 - - - ![](figures/3.png) - -3. 执行“hb build”启动版本构建。 - - **图 4** 在终端界面执行编译命令示意图 - - - ![](figures/4.png) - -4. 编译结束后,如果出现“wifiiot\_hispark\_pegasus build success”字样,则证明构建成功,如下图所示。 - - **图 5** 编译成功示意图 - - - ![](figures/5.png) - -5. 构建成功后,会在./out/wifiiot/路径中生成以下文件,使用如下命令可以查看,至此编译构建流程结束。 - - ``` - ls -l out/hispark_pegasus/wifiiot_hispark_pegasus/ - ``` - - **图 6** 编译文件存放目录示意图 - - - ![](figures/3-0.png) - - -## 镜像烧录 - -Hi3861 WLAN模组的镜像烧录可以通过OpenHarmony IDE工具DevEco完成,工具的基本使用请参考[DevEco Device Tool使用指南](https://device.harmonyos.com/cn/docs/ide/user-guides/service_introduction-0000001050166905),烧录过程包含如下步骤。 - -1. 请连接好电脑和待烧录开发板,需要连接USB口,具体可参考[Hi3861开发板介绍](https://device.harmonyos.com/cn/docs/start/introduce/oem_minitinier_des_3861-0000001105041324)。 -2. 打开电脑的设备管理器,查看并记录对应的串口号。 - - >![](public_sys-resources/icon-note.gif) **说明:** - >如果对应的串口异常,请根据[Hi3861系列开发板串口驱动安装](https://device.harmonyos.com/cn/docs/ide/user-guides/hi3861-drivers-0000001058153433)安装USB转串口的驱动程序。 - - ![](figures/zh-cn_image_0000001128311118.png) - -3. 打开DevEco Device Tool,在Projects中,点击**Settings**打开工程配置界面。 - - ![](figures/zh-cn_image_0000001128311116.png) - -4. 在“Partition Configuration”页签,设置待烧录文件信息,默认情况下,DevEco Device Tool已针对Hi3861系列开发板进行适配,无需单独修改。 -5. 在“hi3861”页签,设置烧录选项,包括upload\_port、upload\_partitions和upload\_protocol。 - - - upload\_port:选择步骤[2](#zh-cn_topic_0000001056563976_li848662117291)中查询的串口号。 - - upload\_protocol:选择烧录协议,固定选择“burn-serial”。 - - upload\_partitions:选择待烧录的文件,默认选择hi3861\_app。 - - ![](figures/zh-cn_image_0000001128470922.png) - -6. 所有的配置都修改完成后,在工程配置页签的顶部,点击**Save**进行保存。 -7. 打开工程文件,在DevEco Device Tool界面的“PROJECT TASKS”中,点击hi3861下的**Upload**按钮,启动烧录。 - - ![](figures/zh-cn_image_0000001174270749.png) - -8. 启动烧录后,显示如下提示信息时,请按开发板上的RST按钮重启开发板。 - - ![](figures/zh-cn_image_0000001174270751.png) - -9. 重新上电后,启动烧录,界面提示如下信息时,表示烧录成功。 - - ![](figures/zh-cn_image_0000001174350669.png) - - -## WLAN模组联网 - -完成版本构建及烧录后,下面开始介绍如何在串口终端上执行AT命令,使WLAN模组联网。 - -1. 保持Windows工作台和WLAN模组的连接状态,在DevEco工具最下方,点击“DevEco:Serial Monitor”按钮。 - - **图 7** 打开DevEco串口终端示意图 - - - ![](figures/5-1.png) - -2. 复位WLAN模组,终端界面显示“ready to OS start”,则启动成功。 - - **图 8** WLAN复位成功示意图 - - - ![](figures/6.png) - -3. 在DevEco的串口终端中,依次执行如下AT命令,启动STA模式,连接指定AP热点,并开启DHCP功能。 - - ``` - AT+STARTSTA # 启动STA模式 - AT+SCAN # 扫描周边AP - AT+SCANRESULT # 显示扫描结果 - AT+CONN="SSID",,2,"PASSWORD" # 连接指定AP,其中SSID/PASSWORD为待连接的热点名称和密码 - AT+STASTAT # 查看连接结果 - AT+DHCP=wlan0,1 # 通过DHCP向AP请求wlan0的IP地址 - ``` - -4. 查看WLAN模组与网关联通是否正常,如下图所示。 - - ``` - AT+IFCFG # 查看模组接口IP - AT+PING=X.X.X.X # 检查模组与网关的联通性,其中X.X.X.X需替换为实际的网关地址 - ``` - - **图 9** WLAN模组联网成功示意图 - - - ![](figures/截图.png) - - diff --git "a/zh-cn/device-dev/quick-start/Windows\345\274\200\345\217\221\347\216\257\345\242\203\345\207\206\345\244\207-7.md" "b/zh-cn/device-dev/quick-start/Windows\345\274\200\345\217\221\347\216\257\345\242\203\345\207\206\345\244\207-7.md" deleted file mode 100644 index bb7588a5ce..0000000000 --- "a/zh-cn/device-dev/quick-start/Windows\345\274\200\345\217\221\347\216\257\345\242\203\345\207\206\345\244\207-7.md" +++ /dev/null @@ -1,176 +0,0 @@ -# Windows开发环境准备 - -- [获取软件](#zh-cn_topic_0000001058091994_section1483143015558) -- [安装Visual Studio Code](#zh-cn_topic_0000001058091994_section71401018163318) -- [安装Python](#zh-cn_topic_0000001058091994_section16266553175320) -- [安装Node.js](#zh-cn_topic_0000001058091994_section5353233124511) -- [安装hpm](#zh-cn_topic_0000001058091994_section173054793610) -- [安装DevEco Device Tool插件](#zh-cn_topic_0000001058091994_section4336315185716) - -系统要求:Windows 10 64位系统。 - -DevEco Device Tool以插件方式提供,基于Visual Studio Code进行扩展,安装分为如下几步: - -1. 安装Visual Studio Code -2. 安装Python -3. 安装Node.js -4. 安装hpm -5. 安装DevEco Device Tool插件 - -## 获取软件 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    工具名称

    -

    用途说明

    -

    版本要求

    -

    获取渠道

    -

    Visual Studio Code

    -

    代码编辑工具

    -

    V1.53及以上 64位版本。

    -

    https://code.visualstudio.com/Download

    -

    Python

    -

    编译构建工具

    -

    V3.7.4~V3.8.x 64位版本

    -

    https://www.python.org/downloads/

    -

    Node.js

    -

    提供npm环境

    -

    v12.0.0及以上 64位版本

    -

    https://nodejs.org/zh-cn/download/

    -

    hpm

    -

    包管理工具

    -

    最新版

    -

    请参考安装hpm

    -

    DevEco Device Tool

    -

    OpenHarmony源码的编译、烧录、调试插件工具

    -

    v2.2 Beta1

    -

    https://device.harmonyos.com/cn/ide#download

    -

    下载前,请使用华为开发者帐号登录,如未注册,请先注册华为开发者帐号

    -
    - -## 安装Visual Studio Code - ->![](public_sys-resources/icon-note.gif) **说明:** ->如果已安装Visual Studio Code,打开命令行工具,输入**code --version**命令,检查版本号是否为1.53及以上版本;可以正常返回版本号,说明环境变量设置也正确。 - -1. 双击Visual Studio Code软件包进行安装。安装过程中,请勾选“添加到PATH(重启后生效)”。 - - ![](figures/zh-cn_image_0000001057335403.png) - -2. 安装完成后,打开命令行工具,输入**code --version**命令,可以正常显示版本号说明安装成功。 - -## 安装Python - -1. 双击Python安装包进行安装,勾选“**Add Python 3.8 to PATH**”,然后点击**Install Now**开始安装。 - - ![](figures/zh-cn_image_0000001176317561.png) - -2. 等待安装完成后,点击**Close**。 - - ![](figures/zh-cn_image_0000001142794291.png) - -3. 打开命令行工具,输入python --version,检查安装结果。 - - ![](figures/zh-cn_image_0000001130278040.png) - -4. 在命令行工具中,分别执行如下命令设置pip源,用于后续安装DevEco Device Tool过程中下载依赖的组件包。 - - ``` - pip config set global.trusted-host repo.huaweicloud.com - pip config set global.index-url https://repo.huaweicloud.com/repository/pypi/simple - pip config set global.timeout 120 - ``` - - -## 安装Node.js - ->![](public_sys-resources/icon-note.gif) **说明:** ->如果已安装Node.js,打开命令行工具,输入**node -v**命令,检查版本号是否为12.0.0及以上版本。 - -1. 点击下载后的软件包进行安装,全部按照默认设置点击**Next**,直至**Finish**。安装过程中,Node.js会自动在系统的path环境变量中配置node.exe的目录路径。 -2. 重新打开命令行工具,输入“node -v“命令,能正常查询Node.js的版本号,说明Node.js安装成功。 - -## 安装hpm - -该方式需先确保**Node.js**安装成功。 - -在安装hpm前,请检查网络连接状态,如果网络不能直接访问Internet,则需要通过代理服务器才可以访问。这种情况下,需要先[设置npm代理](https://device.harmonyos.com/cn/docs/ide/user-guides/npm_proxy-0000001054491032),才能安装hpm。 - ->![](public_sys-resources/icon-note.gif) **说明:** ->如果已安装hpm,可以执行**npm update -g @ohos/hpm-cli**命令升级hpm至最新版本。 - -1. 建议将npm源配置为国内镜像,例如设置为华为云镜像源。 - - ``` - npm config set registry https://repo.huaweicloud.com/repository/npm/ - ``` - -2. 打开命令行工具,执行如下命令安装最新版本hpm。 - - ``` - npm install -g @ohos/hpm-cli - ``` - - ![](figures/zh-cn_image_0000001073840162.png) - -3. 安装完成后,执行如下命令(V为大写字母)检查hpm安装结果。 - - ``` - hpm -V - ``` - - -## 安装DevEco Device Tool插件 - -安装DevEco Device Tool插件,**主机的用户名不能包含中文字符**,否则可能导致运行出现错误。 - -DevEco Device Tool正常运行需要依赖于C/C++和CodeLLDB插件,在安装完DevEco Device Tool后,会自动从Visual Studio Code的插件市场安装C/C++和CodeLLDB插件。因此,在安装DevEco Device Tool前,请检查Visual Studio Code的网络连接状态,如果网络不能直接访问Internet,则需要通过代理服务器才可以访问,请先[Visual Studio Code代理设置](https://device.harmonyos.com/cn/docs/ide/user-guides/vscode_proxy-0000001074231144)。 - ->![](public_sys-resources/icon-note.gif) **说明:** ->安装DevEco Device Tool时,请先关闭Visual Studio Code。 - -1. 解压DevEco Device Tool插件压缩包,双击安装包程序进行安装。 -2. 安装过程中,会自动安装DevEco Device Tool所需的依赖文件(如C/C++和CodeLLDB插件)和执行程序。 - - ![](figures/zh-cn_image_0000001072468991.png) - -3. 安装完成后,会自动关闭命令行工具窗口。 -4. 启动Visual Studio Code,点击左侧的![](figures/zh-cn_image_0000001072757874.png)按钮,检查INSTALLED中,是否已成功安装C/C++、CodeLLDB和DevEco Device Tool。 - - >![](public_sys-resources/icon-note.gif) **说明:** - >如果C/C++和CodeLLDB插件安装不成功,则DevEco Device Tool不能正常运行,解决方法,详细请参考:[离线安装C/C++和CodeLLDB插件](https://device.harmonyos.com/cn/docs/ide/user-guides/offline_plugin_install-0000001074376846)。 - - ![](figures/zh-cn_image_0000001142802505.png) - - diff --git "a/zh-cn/device-dev/quick-start/Windows\345\274\200\345\217\221\347\216\257\345\242\203\345\207\206\345\244\207.md" "b/zh-cn/device-dev/quick-start/Windows\345\274\200\345\217\221\347\216\257\345\242\203\345\207\206\345\244\207.md" deleted file mode 100755 index cffea83cad..0000000000 --- "a/zh-cn/device-dev/quick-start/Windows\345\274\200\345\217\221\347\216\257\345\242\203\345\207\206\345\244\207.md" +++ /dev/null @@ -1,182 +0,0 @@ -# Windows开发环境准备 - -- [获取软件](#zh-cn_topic_0000001058091994_section1483143015558) -- [安装Visual Studio Code](#zh-cn_topic_0000001058091994_section71401018163318) -- [安装Python](#zh-cn_topic_0000001058091994_section16266553175320) -- [安装Node.js](#zh-cn_topic_0000001058091994_section5353233124511) -- [安装hpm](#zh-cn_topic_0000001058091994_section173054793610) -- [安装DevEco Device Tool插件](#zh-cn_topic_0000001058091994_section4336315185716) - -系统要求:Windows 10 64位系统。 - -DevEco Device Tool以插件方式提供,基于Visual Studio Code进行扩展,安装分为如下几步: - -1. 安装Visual Studio Code -2. 安装Python -3. 安装Node.js -4. 安装hpm -5. 安装DevEco Device Tool插件 - -## 获取软件 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    工具名称

    -

    用途说明

    -

    版本要求

    -

    获取渠道

    -

    Visual Studio Code

    -

    代码编辑工具

    -

    V1.53及以上 64位版本。

    -

    https://code.visualstudio.com/Download

    -

    Python

    -

    编译构建工具

    -

    V3.7.4~V3.8.x 64位版本

    -

    推荐下载:https://www.python.org/downloads/release/python-388/

    -

    Node.js

    -

    提供npm环境

    -

    v12.0.0及以上 64位版本

    -

    https://nodejs.org/zh-cn/download/

    -

    hpm

    -

    包管理工具

    -

    最新版

    -

    请参考安装hpm

    -

    DevEco Device Tool

    -

    OpenHarmony源码的编译、烧录、调试插件工具

    -

    v2.2 Beta1

    -

    https://device.harmonyos.com/cn/ide#download

    -

    下载前,请使用华为开发者帐号登录,如未注册,请先注册华为开发者帐号

    -
    - -## 安装Visual Studio Code - ->![](public_sys-resources/icon-note.gif) **说明:** ->如果已安装Visual Studio Code,打开命令行工具,输入**code --version**命令,检查版本号是否为1.53及以上版本;可以正常返回版本号,说明环境变量设置也正确。 - -1. 双击Visual Studio Code软件包进行安装。安装过程中,请勾选“添加到PATH(重启后生效)”。 - - ![](figures/zh-cn_image_0000001174350653.png) - -2. 安装完成后,重启计算机,使Visual Studio Code的环境变量生效。 -3. 打开命令行工具,输入**code --version**命令,可以正常显示版本号说明安装成功。 - -## 安装Python - -1. 双击Python安装包进行安装,勾选“**Add Python 3.8 to PATH**”,然后点击**Install Now**开始安装。 - - ![](figures/zh-cn_image_0000001128470908.png) - -2. 等待安装完成后,点击**Close**。 - - ![](figures/zh-cn_image_0000001128311104.png) - -3. 打开命令行工具,输入python --version,检查安装结果。 - - ![](figures/zh-cn_image_0000001174350655.png) - -4. 在命令行工具中,分别执行如下命令设置pip源,用于后续安装DevEco Device Tool过程中下载依赖的组件包。 - - ``` - pip config set global.trusted-host repo.huaweicloud.com - pip config set global.index-url https://repo.huaweicloud.com/repository/pypi/simple - pip config set global.timeout 120 - ``` - - -## 安装Node.js - ->![](public_sys-resources/icon-note.gif) **说明:** ->如果已安装Node.js,打开命令行工具,输入**node -v**命令,检查版本号是否为12.0.0及以上版本。 - -1. 点击下载后的软件包进行安装,全部按照默认设置点击**Next**,直至**Finish**。安装过程中,Node.js会自动在系统的path环境变量中配置node.exe的目录路径。 -2. 重新打开命令行工具,输入“node -v“命令,能正常查询Node.js的版本号,说明Node.js安装成功。 - - ![](figures/zh-cn_image_0000001128311096.png) - - -## 安装hpm - -该方式需先确保**Node.js**安装成功。 - -在安装hpm前,请检查网络连接状态,如果网络不能直接访问Internet,则需要通过代理服务器才可以访问。这种情况下,需要先[设置npm代理](https://device.harmonyos.com/cn/docs/ide/user-guides/npm_proxy-0000001054491032),才能安装hpm。 - ->![](public_sys-resources/icon-note.gif) **说明:** ->如果已安装hpm,可以执行**npm update -g @ohos/hpm-cli**命令升级hpm至最新版本。 - -1. 建议将npm源配置为国内镜像,例如设置为华为云镜像源。 - - ``` - npm config set registry https://repo.huaweicloud.com/repository/npm/ - ``` - -2. 打开命令行工具,执行如下命令安装最新版本hpm。 - - ``` - npm install -g @ohos/hpm-cli - ``` - - ![](figures/zh-cn_image_0000001128311100.png) - -3. 安装完成后,执行如下命令(V为大写字母)检查hpm安装结果。 - - ``` - hpm -V - ``` - - ![](figures/zh-cn_image_0000001174270735.png) - - -## 安装DevEco Device Tool插件 - -安装DevEco Device Tool插件,**主机的用户名不能包含中文字符**,否则可能导致运行出现错误。 - -DevEco Device Tool正常运行需要依赖于C/C++和CodeLLDB插件,在安装完DevEco Device Tool后,会自动从Visual Studio Code的插件市场安装C/C++和CodeLLDB插件。因此,在安装DevEco Device Tool前,请检查Visual Studio Code的网络连接状态,如果网络不能直接访问Internet,则需要通过代理服务器才可以访问,请先[Visual Studio Code代理设置](https://device.harmonyos.com/cn/docs/ide/user-guides/vscode_proxy-0000001074231144)。 - ->![](public_sys-resources/icon-note.gif) **说明:** ->安装DevEco Device Tool时,请先关闭Visual Studio Code。 - -1. 解压DevEco Device Tool插件压缩包,双击安装包程序进行安装。 -2. 安装过程中,会自动安装DevEco Device Tool所需的依赖文件(如C/C++和CodeLLDB插件)和执行程序。 - - ![](figures/zh-cn_image_0000001128470902.png) - -3. 安装完成后,会自动关闭命令行工具窗口。 -4. 启动Visual Studio Code,点击左侧的![](figures/zh-cn_image_0000001174350651.png)按钮,检查INSTALLED中,是否已成功安装C/C++、CodeLLDB和DevEco Device Tool。 - - >![](public_sys-resources/icon-note.gif) **说明:** - >如果C/C++和CodeLLDB插件安装不成功,则DevEco Device Tool不能正常运行,解决方法,详细请参考:[离线安装C/C++和CodeLLDB插件](https://device.harmonyos.com/cn/docs/ide/user-guides/offline_plugin_install-0000001074376846)。 - - ![](figures/zh-cn_image_0000001174270727.png) - - diff --git a/zh-cn/device-dev/quick-start/figures/1.png b/zh-cn/device-dev/quick-start/figure/1.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/quick-start/figures/1.png rename to zh-cn/device-dev/quick-start/figure/1.png diff --git a/zh-cn/device-dev/quick-start/figures/10.png b/zh-cn/device-dev/quick-start/figure/10.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/quick-start/figures/10.png rename to zh-cn/device-dev/quick-start/figure/10.png diff --git a/zh-cn/device-dev/quick-start/figures/2.png b/zh-cn/device-dev/quick-start/figure/2.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/quick-start/figures/2.png rename to zh-cn/device-dev/quick-start/figure/2.png diff --git a/zh-cn/device-dev/quick-start/figures/2021-01-27_170334-17.png b/zh-cn/device-dev/quick-start/figure/2021-01-27_170334-16.png similarity index 100% rename from zh-cn/device-dev/quick-start/figures/2021-01-27_170334-17.png rename to zh-cn/device-dev/quick-start/figure/2021-01-27_170334-16.png diff --git a/zh-cn/device-dev/quick-start/figures/2021-01-27_170334-2.png b/zh-cn/device-dev/quick-start/figure/2021-01-27_170334-2.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/quick-start/figures/2021-01-27_170334-2.png rename to zh-cn/device-dev/quick-start/figure/2021-01-27_170334-2.png diff --git a/zh-cn/device-dev/quick-start/figures/2021-01-27_170334-5.png b/zh-cn/device-dev/quick-start/figure/2021-01-27_170334-5.png similarity index 100% rename from zh-cn/device-dev/quick-start/figures/2021-01-27_170334-5.png rename to zh-cn/device-dev/quick-start/figure/2021-01-27_170334-5.png diff --git a/zh-cn/device-dev/quick-start/figures/2021-01-27_170334.png b/zh-cn/device-dev/quick-start/figure/2021-01-27_170334.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/quick-start/figures/2021-01-27_170334.png rename to zh-cn/device-dev/quick-start/figure/2021-01-27_170334.png diff --git a/zh-cn/device-dev/quick-start/figures/3-0.png b/zh-cn/device-dev/quick-start/figure/3-0.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/quick-start/figures/3-0.png rename to zh-cn/device-dev/quick-start/figure/3-0.png diff --git a/zh-cn/device-dev/quick-start/figures/3.png b/zh-cn/device-dev/quick-start/figure/3.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/quick-start/figures/3.png rename to zh-cn/device-dev/quick-start/figure/3.png diff --git "a/zh-cn/device-dev/quick-start/figures/3516\346\255\243\351\235\242.png" "b/zh-cn/device-dev/quick-start/figure/3516\346\255\243\351\235\242.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/quick-start/figures/3516\346\255\243\351\235\242.png" rename to "zh-cn/device-dev/quick-start/figure/3516\346\255\243\351\235\242.png" diff --git "a/zh-cn/device-dev/quick-start/figures/3861\346\255\243\351\235\242.png" "b/zh-cn/device-dev/quick-start/figure/3861\346\255\243\351\235\242.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/quick-start/figures/3861\346\255\243\351\235\242.png" rename to "zh-cn/device-dev/quick-start/figure/3861\346\255\243\351\235\242.png" diff --git a/zh-cn/device-dev/quick-start/figures/4.png b/zh-cn/device-dev/quick-start/figure/4.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/quick-start/figures/4.png rename to zh-cn/device-dev/quick-start/figure/4.png diff --git a/zh-cn/device-dev/quick-start/figures/5-1.png b/zh-cn/device-dev/quick-start/figure/5-1.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/quick-start/figures/5-1.png rename to zh-cn/device-dev/quick-start/figure/5-1.png diff --git a/zh-cn/device-dev/quick-start/figures/5.png b/zh-cn/device-dev/quick-start/figure/5.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/quick-start/figures/5.png rename to zh-cn/device-dev/quick-start/figure/5.png diff --git a/zh-cn/device-dev/quick-start/figures/6.png b/zh-cn/device-dev/quick-start/figure/6.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/quick-start/figures/6.png rename to zh-cn/device-dev/quick-start/figure/6.png diff --git "a/zh-cn/device-dev/quick-start/figures/Hi3518EV300\345\215\225\346\235\277\346\255\243\351\235\242\345\244\226\350\247\202\345\233\276.png" "b/zh-cn/device-dev/quick-start/figure/Hi3518EV300\345\215\225\346\235\277\346\255\243\351\235\242\345\244\226\350\247\202\345\233\276.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/quick-start/figures/Hi3518EV300\345\215\225\346\235\277\346\255\243\351\235\242\345\244\226\350\247\202\345\233\276.png" rename to "zh-cn/device-dev/quick-start/figure/Hi3518EV300\345\215\225\346\235\277\346\255\243\351\235\242\345\244\226\350\247\202\345\233\276.png" diff --git "a/zh-cn/device-dev/quick-start/figures/Hi3518\346\255\243\350\203\214\351\235\242.png" "b/zh-cn/device-dev/quick-start/figure/Hi3518\346\255\243\350\203\214\351\235\242.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/quick-start/figures/Hi3518\346\255\243\350\203\214\351\235\242.png" rename to "zh-cn/device-dev/quick-start/figure/Hi3518\346\255\243\350\203\214\351\235\242.png" diff --git "a/zh-cn/device-dev/quick-start/figures/SCons\345\256\211\350\243\205\346\210\220\345\212\237\347\225\214\351\235\242-\347\211\210\346\234\254\350\246\201\346\261\2023-0-4\344\273\245\344\270\212.png" "b/zh-cn/device-dev/quick-start/figure/SCons\345\256\211\350\243\205\346\210\220\345\212\237\347\225\214\351\235\242-\347\211\210\346\234\254\350\246\201\346\261\2023-0-4\344\273\245\344\270\212.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/quick-start/figures/SCons\345\256\211\350\243\205\346\210\220\345\212\237\347\225\214\351\235\242-\347\211\210\346\234\254\350\246\201\346\261\2023-0-4\344\273\245\344\270\212.png" rename to "zh-cn/device-dev/quick-start/figure/SCons\345\256\211\350\243\205\346\210\220\345\212\237\347\225\214\351\235\242-\347\211\210\346\234\254\350\246\201\346\261\2023-0-4\344\273\245\344\270\212.png" diff --git "a/zh-cn/device-dev/quick-start/figures/U-boot\347\203\247\345\206\231\345\256\214\346\210\220\344\270\262\345\217\243\346\230\276\347\244\272\345\233\276.png" "b/zh-cn/device-dev/quick-start/figure/U-boot\347\203\247\345\206\231\345\256\214\346\210\220\344\270\262\345\217\243\346\230\276\347\244\272\345\233\276.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/quick-start/figures/U-boot\347\203\247\345\206\231\345\256\214\346\210\220\344\270\262\345\217\243\346\230\276\347\244\272\345\233\276.png" rename to "zh-cn/device-dev/quick-start/figure/U-boot\347\203\247\345\206\231\345\256\214\346\210\220\344\270\262\345\217\243\346\230\276\347\244\272\345\233\276.png" diff --git a/zh-cn/device-dev/quick-start/figures/changjian1-10.png b/zh-cn/device-dev/quick-start/figure/changjian1-10.png similarity index 100% rename from zh-cn/device-dev/quick-start/figures/changjian1-10.png rename to zh-cn/device-dev/quick-start/figure/changjian1-10.png diff --git a/zh-cn/device-dev/quick-start/figures/changjian1.png b/zh-cn/device-dev/quick-start/figure/changjian1.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/quick-start/figures/changjian1.png rename to zh-cn/device-dev/quick-start/figure/changjian1.png diff --git a/zh-cn/device-dev/quick-start/figures/chuankou1-6.png b/zh-cn/device-dev/quick-start/figure/chuankou1-6.png similarity index 100% rename from zh-cn/device-dev/quick-start/figures/chuankou1-6.png rename to zh-cn/device-dev/quick-start/figure/chuankou1-6.png diff --git a/zh-cn/device-dev/quick-start/figures/chuankou1.png b/zh-cn/device-dev/quick-start/figure/chuankou1.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/quick-start/figures/chuankou1.png rename to zh-cn/device-dev/quick-start/figure/chuankou1.png diff --git a/zh-cn/device-dev/quick-start/figures/qi1.png b/zh-cn/device-dev/quick-start/figure/qi1.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/quick-start/figures/qi1.png rename to zh-cn/device-dev/quick-start/figure/qi1.png diff --git a/zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001057335403.png b/zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001057335403.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001057335403.png rename to zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001057335403.png diff --git a/zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001072468991.png b/zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001072468991.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001072468991.png rename to zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001072468991.png diff --git a/zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001072757874.png b/zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001072757874.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001072757874.png rename to zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001072757874.png diff --git a/zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001073840162.png b/zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001073840162.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001073840162.png rename to zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001073840162.png diff --git a/zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001113969542.png b/zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001113969542.png similarity index 100% rename from zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001113969542.png rename to zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001113969542.png diff --git a/zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001114129428.png b/zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001114129428.png similarity index 100% rename from zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001114129428.png rename to zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001114129428.png diff --git a/zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001114129432.png b/zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001114129432.png similarity index 100% rename from zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001114129432.png rename to zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001114129432.png diff --git a/zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001117463460.png b/zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001117463460.png similarity index 100% rename from zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001117463460.png rename to zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001117463460.png diff --git a/zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001117621400.png b/zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001117621400.png similarity index 100% rename from zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001117621400.png rename to zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001117621400.png diff --git a/zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001128311066.png b/zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001128311066.png similarity index 100% rename from zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001128311066.png rename to zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001128311066.png diff --git a/zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001128311070.png b/zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001128311070.png similarity index 100% rename from zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001128311070.png rename to zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001128311070.png diff --git a/zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001128311072.png b/zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001128311072.png similarity index 100% rename from zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001128311072.png rename to zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001128311072.png diff --git a/zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001128311090.png b/zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001128311090.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001128311090.png rename to zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001128311090.png diff --git a/zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001128311092.png b/zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001128311092.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001128311092.png rename to zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001128311092.png diff --git a/zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001128311094.png b/zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001128311094.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001128311094.png rename to zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001128311094.png diff --git a/zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001128311096.png b/zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001128311096.png similarity index 100% rename from zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001128311096.png rename to zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001128311096.png diff --git a/zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001128311098.png b/zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001128311098.png similarity index 100% rename from zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001128311098.png rename to zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001128311098.png diff --git a/zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001128311100.png b/zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001128311100.png similarity index 100% rename from zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001128311100.png rename to zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001128311100.png diff --git a/zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001128311104.png b/zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001128311104.png similarity index 100% rename from zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001128311104.png rename to zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001128311104.png diff --git a/zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001128311116.png b/zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001128311116.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001128311116.png rename to zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001128311116.png diff --git a/zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001128311118.png b/zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001128311118.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001128311118.png rename to zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001128311118.png diff --git a/zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001128470864.png b/zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001128470864.png similarity index 100% rename from zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001128470864.png rename to zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001128470864.png diff --git a/zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001128470880.png b/zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001128470880.png similarity index 100% rename from zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001128470880.png rename to zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001128470880.png diff --git a/zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001128470900.png b/zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001128470900.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001128470900.png rename to zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001128470900.png diff --git a/zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001128470902.png b/zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001128470902.png similarity index 100% rename from zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001128470902.png rename to zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001128470902.png diff --git a/zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001128470904.png b/zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001128470904.png similarity index 100% rename from zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001128470904.png rename to zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001128470904.png diff --git a/zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001128470906.png b/zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001128470906.png similarity index 100% rename from zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001128470906.png rename to zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001128470906.png diff --git a/zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001128470908.png b/zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001128470908.png similarity index 100% rename from zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001128470908.png rename to zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001128470908.png diff --git a/zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001128470922.png b/zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001128470922.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001128470922.png rename to zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001128470922.png diff --git a/zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001130278040.png b/zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001130278040.png similarity index 100% rename from zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001130278040.png rename to zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001130278040.png diff --git a/zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001130584312.png b/zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001130584312.png similarity index 100% rename from zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001130584312.png rename to zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001130584312.png diff --git a/zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001142794291.png b/zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001142794291.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001142794291.png rename to zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001142794291.png diff --git a/zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001142802505.png b/zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001142802505.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001142802505.png rename to zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001142802505.png diff --git a/zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001174270699.png b/zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001174270699.png similarity index 100% rename from zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001174270699.png rename to zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001174270699.png diff --git a/zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001174270713.png b/zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001174270713.png similarity index 100% rename from zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001174270713.png rename to zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001174270713.png diff --git a/zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001174270715.png b/zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001174270715.png similarity index 100% rename from zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001174270715.png rename to zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001174270715.png diff --git a/zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001174270727.png b/zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001174270727.png similarity index 100% rename from zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001174270727.png rename to zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001174270727.png diff --git a/zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001174270729.png b/zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001174270729.png similarity index 100% rename from zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001174270729.png rename to zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001174270729.png diff --git a/zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001174270731.png b/zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001174270731.png similarity index 100% rename from zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001174270731.png rename to zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001174270731.png diff --git a/zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001174270733.png b/zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001174270733.png similarity index 100% rename from zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001174270733.png rename to zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001174270733.png diff --git a/zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001174270735.png b/zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001174270735.png similarity index 100% rename from zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001174270735.png rename to zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001174270735.png diff --git a/zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001174270737.png b/zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001174270737.png similarity index 100% rename from zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001174270737.png rename to zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001174270737.png diff --git a/zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001174270739.png b/zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001174270739.png similarity index 100% rename from zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001174270739.png rename to zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001174270739.png diff --git a/zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001174270743.png b/zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001174270743.png similarity index 100% rename from zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001174270743.png rename to zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001174270743.png diff --git a/zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001174270749.png b/zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001174270749.png similarity index 100% rename from zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001174270749.png rename to zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001174270749.png diff --git a/zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001174270751.png b/zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001174270751.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001174270751.png rename to zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001174270751.png diff --git a/zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001174350615.png b/zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001174350615.png similarity index 100% rename from zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001174350615.png rename to zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001174350615.png diff --git a/zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001174350623.png b/zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001174350623.png similarity index 100% rename from zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001174350623.png rename to zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001174350623.png diff --git a/zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001174350633.png b/zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001174350633.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001174350633.png rename to zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001174350633.png diff --git a/zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001174350641.png b/zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001174350641.png similarity index 100% rename from zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001174350641.png rename to zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001174350641.png diff --git a/zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001174350643.png b/zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001174350643.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001174350643.png rename to zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001174350643.png diff --git a/zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001174350647.png b/zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001174350647.png similarity index 100% rename from zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001174350647.png rename to zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001174350647.png diff --git a/zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001174350649.png b/zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001174350649.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001174350649.png rename to zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001174350649.png diff --git a/zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001174350651.png b/zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001174350651.png similarity index 100% rename from zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001174350651.png rename to zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001174350651.png diff --git a/zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001174350653.png b/zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001174350653.png similarity index 100% rename from zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001174350653.png rename to zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001174350653.png diff --git a/zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001174350655.png b/zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001174350655.png similarity index 100% rename from zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001174350655.png rename to zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001174350655.png diff --git a/zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001174350659.png b/zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001174350659.png similarity index 100% rename from zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001174350659.png rename to zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001174350659.png diff --git a/zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001174350661.png b/zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001174350661.png similarity index 100% rename from zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001174350661.png rename to zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001174350661.png diff --git a/zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001174350669.png b/zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001174350669.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001174350669.png rename to zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001174350669.png diff --git a/zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001176317561.png b/zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001176317561.png similarity index 100% rename from zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001176317561.png rename to zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001176317561.png diff --git "a/zh-cn/device-dev/quick-start/figures/\345\205\201\350\256\270Visual-Studio-Code\345\272\224\347\224\250\350\256\277\351\227\256\347\275\221\347\273\234-15.png" "b/zh-cn/device-dev/quick-start/figure/\345\205\201\350\256\270Visual-Studio-Code\345\272\224\347\224\250\350\256\277\351\227\256\347\275\221\347\273\234-15.png" similarity index 100% rename from "zh-cn/device-dev/quick-start/figures/\345\205\201\350\256\270Visual-Studio-Code\345\272\224\347\224\250\350\256\277\351\227\256\347\275\221\347\273\234-15.png" rename to "zh-cn/device-dev/quick-start/figure/\345\205\201\350\256\270Visual-Studio-Code\345\272\224\347\224\250\350\256\277\351\227\256\347\275\221\347\273\234-15.png" diff --git "a/zh-cn/device-dev/quick-start/figures/\345\205\201\350\256\270Visual-Studio-Code\345\272\224\347\224\250\350\256\277\351\227\256\347\275\221\347\273\234.png" "b/zh-cn/device-dev/quick-start/figure/\345\205\201\350\256\270Visual-Studio-Code\345\272\224\347\224\250\350\256\277\351\227\256\347\275\221\347\273\234.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/quick-start/figures/\345\205\201\350\256\270Visual-Studio-Code\345\272\224\347\224\250\350\256\277\351\227\256\347\275\221\347\273\234.png" rename to "zh-cn/device-dev/quick-start/figure/\345\205\201\350\256\270Visual-Studio-Code\345\272\224\347\224\250\350\256\277\351\227\256\347\275\221\347\273\234.png" diff --git "a/zh-cn/device-dev/quick-start/figures/\345\205\263\351\227\255\344\270\262\345\217\243\347\273\210\347\253\257-9.png" "b/zh-cn/device-dev/quick-start/figure/\345\205\263\351\227\255\344\270\262\345\217\243\347\273\210\347\253\257-9.png" similarity index 100% rename from "zh-cn/device-dev/quick-start/figures/\345\205\263\351\227\255\344\270\262\345\217\243\347\273\210\347\253\257-9.png" rename to "zh-cn/device-dev/quick-start/figure/\345\205\263\351\227\255\344\270\262\345\217\243\347\273\210\347\253\257-9.png" diff --git "a/zh-cn/device-dev/quick-start/figures/\345\205\263\351\227\255\344\270\262\345\217\243\347\273\210\347\253\257.png" "b/zh-cn/device-dev/quick-start/figure/\345\205\263\351\227\255\344\270\262\345\217\243\347\273\210\347\253\257.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/quick-start/figures/\345\205\263\351\227\255\344\270\262\345\217\243\347\273\210\347\253\257.png" rename to "zh-cn/device-dev/quick-start/figure/\345\205\263\351\227\255\344\270\262\345\217\243\347\273\210\347\253\257.png" diff --git "a/zh-cn/device-dev/quick-start/figures/\345\220\257\345\212\250\345\271\266\346\210\220\345\212\237\346\211\247\350\241\214\345\272\224\347\224\250\347\250\213\345\272\217\345\233\276.png" "b/zh-cn/device-dev/quick-start/figure/\345\220\257\345\212\250\345\271\266\346\210\220\345\212\237\346\211\247\350\241\214\345\272\224\347\224\250\347\250\213\345\272\217\345\233\276.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/quick-start/figures/\345\220\257\345\212\250\345\271\266\346\210\220\345\212\237\346\211\247\350\241\214\345\272\224\347\224\250\347\250\213\345\272\217\345\233\276.png" rename to "zh-cn/device-dev/quick-start/figure/\345\220\257\345\212\250\345\271\266\346\210\220\345\212\237\346\211\247\350\241\214\345\272\224\347\224\250\347\250\213\345\272\217\345\233\276.png" diff --git "a/zh-cn/device-dev/quick-start/figures/\345\220\257\345\212\250\346\210\220\345\212\237\345\271\266\346\211\247\350\241\214\345\272\224\347\224\250\347\250\213\345\272\217\345\233\276.png" "b/zh-cn/device-dev/quick-start/figure/\345\220\257\345\212\250\346\210\220\345\212\237\345\271\266\346\211\247\350\241\214\345\272\224\347\224\250\347\250\213\345\272\217\345\233\276.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/quick-start/figures/\345\220\257\345\212\250\346\210\220\345\212\237\345\271\266\346\211\247\350\241\214\345\272\224\347\224\250\347\250\213\345\272\217\345\233\276.png" rename to "zh-cn/device-dev/quick-start/figure/\345\220\257\345\212\250\346\210\220\345\212\237\345\271\266\346\211\247\350\241\214\345\272\224\347\224\250\347\250\213\345\272\217\345\233\276.png" diff --git "a/zh-cn/device-dev/quick-start/figures/\346\210\252\345\233\276.png" "b/zh-cn/device-dev/quick-start/figure/\346\210\252\345\233\276.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/quick-start/figures/\346\210\252\345\233\276.png" rename to "zh-cn/device-dev/quick-start/figure/\346\210\252\345\233\276.png" diff --git "a/zh-cn/device-dev/quick-start/figures/\346\211\223\345\274\200\344\270\262\345\217\243\345\244\261\350\264\245\345\233\276-7.png" "b/zh-cn/device-dev/quick-start/figure/\346\211\223\345\274\200\344\270\262\345\217\243\345\244\261\350\264\245\345\233\276-7.png" similarity index 100% rename from "zh-cn/device-dev/quick-start/figures/\346\211\223\345\274\200\344\270\262\345\217\243\345\244\261\350\264\245\345\233\276-7.png" rename to "zh-cn/device-dev/quick-start/figure/\346\211\223\345\274\200\344\270\262\345\217\243\345\244\261\350\264\245\345\233\276-7.png" diff --git "a/zh-cn/device-dev/quick-start/figures/\346\211\223\345\274\200\344\270\262\345\217\243\345\244\261\350\264\245\345\233\276.png" "b/zh-cn/device-dev/quick-start/figure/\346\211\223\345\274\200\344\270\262\345\217\243\345\244\261\350\264\245\345\233\276.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/quick-start/figures/\346\211\223\345\274\200\344\270\262\345\217\243\345\244\261\350\264\245\345\233\276.png" rename to "zh-cn/device-dev/quick-start/figure/\346\211\223\345\274\200\344\270\262\345\217\243\345\244\261\350\264\245\345\233\276.png" diff --git "a/zh-cn/device-dev/quick-start/figures/\346\237\245\346\211\276Visual-Studio-Code\345\272\224\347\224\250\345\233\276-14.png" "b/zh-cn/device-dev/quick-start/figure/\346\237\245\346\211\276Visual-Studio-Code\345\272\224\347\224\250\345\233\276-14.png" similarity index 100% rename from "zh-cn/device-dev/quick-start/figures/\346\237\245\346\211\276Visual-Studio-Code\345\272\224\347\224\250\345\233\276-14.png" rename to "zh-cn/device-dev/quick-start/figure/\346\237\245\346\211\276Visual-Studio-Code\345\272\224\347\224\250\345\233\276-14.png" diff --git "a/zh-cn/device-dev/quick-start/figures/\346\237\245\346\211\276Visual-Studio-Code\345\272\224\347\224\250\345\233\276.png" "b/zh-cn/device-dev/quick-start/figure/\346\237\245\346\211\276Visual-Studio-Code\345\272\224\347\224\250\345\233\276.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/quick-start/figures/\346\237\245\346\211\276Visual-Studio-Code\345\272\224\347\224\250\345\233\276.png" rename to "zh-cn/device-dev/quick-start/figure/\346\237\245\346\211\276Visual-Studio-Code\345\272\224\347\224\250\345\233\276.png" diff --git "a/zh-cn/device-dev/quick-start/figures/\346\237\245\346\211\276\346\230\257\345\220\246\345\255\230\345\234\250\345\215\240\347\224\250\344\270\262\345\217\243\347\232\204\347\273\210\347\253\257-8.png" "b/zh-cn/device-dev/quick-start/figure/\346\237\245\346\211\276\346\230\257\345\220\246\345\255\230\345\234\250\345\215\240\347\224\250\344\270\262\345\217\243\347\232\204\347\273\210\347\253\257-8.png" similarity index 100% rename from "zh-cn/device-dev/quick-start/figures/\346\237\245\346\211\276\346\230\257\345\220\246\345\255\230\345\234\250\345\215\240\347\224\250\344\270\262\345\217\243\347\232\204\347\273\210\347\253\257-8.png" rename to "zh-cn/device-dev/quick-start/figure/\346\237\245\346\211\276\346\230\257\345\220\246\345\255\230\345\234\250\345\215\240\347\224\250\344\270\262\345\217\243\347\232\204\347\273\210\347\253\257-8.png" diff --git "a/zh-cn/device-dev/quick-start/figures/\346\237\245\346\211\276\346\230\257\345\220\246\345\255\230\345\234\250\345\215\240\347\224\250\344\270\262\345\217\243\347\232\204\347\273\210\347\253\257.png" "b/zh-cn/device-dev/quick-start/figure/\346\237\245\346\211\276\346\230\257\345\220\246\345\255\230\345\234\250\345\215\240\347\224\250\344\270\262\345\217\243\347\232\204\347\273\210\347\253\257.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/quick-start/figures/\346\237\245\346\211\276\346\230\257\345\220\246\345\255\230\345\234\250\345\215\240\347\224\250\344\270\262\345\217\243\347\232\204\347\273\210\347\253\257.png" rename to "zh-cn/device-dev/quick-start/figure/\346\237\245\346\211\276\346\230\257\345\220\246\345\255\230\345\234\250\345\215\240\347\224\250\344\270\262\345\217\243\347\232\204\347\273\210\347\253\257.png" diff --git "a/zh-cn/device-dev/quick-start/figures/\347\237\251\345\275\242\345\244\207\344\273\275-292.png" "b/zh-cn/device-dev/quick-start/figure/\347\237\251\345\275\242\345\244\207\344\273\275-292.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/quick-start/figures/\347\237\251\345\275\242\345\244\207\344\273\275-292.png" rename to "zh-cn/device-dev/quick-start/figure/\347\237\251\345\275\242\345\244\207\344\273\275-292.png" diff --git "a/zh-cn/device-dev/quick-start/figures/\347\241\254\344\273\266\350\277\236\347\272\277\345\233\276-3.png" "b/zh-cn/device-dev/quick-start/figure/\347\241\254\344\273\266\350\277\236\347\272\277\345\233\276-3.png" similarity index 100% rename from "zh-cn/device-dev/quick-start/figures/\347\241\254\344\273\266\350\277\236\347\272\277\345\233\276-3.png" rename to "zh-cn/device-dev/quick-start/figure/\347\241\254\344\273\266\350\277\236\347\272\277\345\233\276-3.png" diff --git "a/zh-cn/device-dev/quick-start/figures/\347\241\254\344\273\266\350\277\236\347\272\277\345\233\276.png" "b/zh-cn/device-dev/quick-start/figure/\347\241\254\344\273\266\350\277\236\347\272\277\345\233\276.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/quick-start/figures/\347\241\254\344\273\266\350\277\236\347\272\277\345\233\276.png" rename to "zh-cn/device-dev/quick-start/figure/\347\241\254\344\273\266\350\277\236\347\272\277\345\233\276.png" diff --git "a/zh-cn/device-dev/quick-start/figures/\347\275\221\347\273\234\344\270\215\351\200\232-\345\215\225\346\235\277\346\227\240\346\263\225\350\216\267\345\217\226\346\226\207\344\273\266\345\233\276-11.png" "b/zh-cn/device-dev/quick-start/figure/\347\275\221\347\273\234\344\270\215\351\200\232-\345\215\225\346\235\277\346\227\240\346\263\225\350\216\267\345\217\226\346\226\207\344\273\266\345\233\276-11.png" similarity index 100% rename from "zh-cn/device-dev/quick-start/figures/\347\275\221\347\273\234\344\270\215\351\200\232-\345\215\225\346\235\277\346\227\240\346\263\225\350\216\267\345\217\226\346\226\207\344\273\266\345\233\276-11.png" rename to "zh-cn/device-dev/quick-start/figure/\347\275\221\347\273\234\344\270\215\351\200\232-\345\215\225\346\235\277\346\227\240\346\263\225\350\216\267\345\217\226\346\226\207\344\273\266\345\233\276-11.png" diff --git "a/zh-cn/device-dev/quick-start/figures/\347\275\221\347\273\234\344\270\215\351\200\232-\345\215\225\346\235\277\346\227\240\346\263\225\350\216\267\345\217\226\346\226\207\344\273\266\345\233\276.png" "b/zh-cn/device-dev/quick-start/figure/\347\275\221\347\273\234\344\270\215\351\200\232-\345\215\225\346\235\277\346\227\240\346\263\225\350\216\267\345\217\226\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/quick-start/figures/\347\275\221\347\273\234\344\270\215\351\200\232-\345\215\225\346\235\277\346\227\240\346\263\225\350\216\267\345\217\226\346\226\207\344\273\266\345\233\276.png" rename to "zh-cn/device-dev/quick-start/figure/\347\275\221\347\273\234\344\270\215\351\200\232-\345\215\225\346\235\277\346\227\240\346\263\225\350\216\267\345\217\226\346\226\207\344\273\266\345\233\276.png" diff --git "a/zh-cn/device-dev/quick-start/figures/\347\275\221\347\273\234\351\230\262\347\201\253\345\242\231\350\256\276\347\275\256\345\233\276-12.png" "b/zh-cn/device-dev/quick-start/figure/\347\275\221\347\273\234\351\230\262\347\201\253\345\242\231\350\256\276\347\275\256\345\233\276-12.png" similarity index 100% rename from "zh-cn/device-dev/quick-start/figures/\347\275\221\347\273\234\351\230\262\347\201\253\345\242\231\350\256\276\347\275\256\345\233\276-12.png" rename to "zh-cn/device-dev/quick-start/figure/\347\275\221\347\273\234\351\230\262\347\201\253\345\242\231\350\256\276\347\275\256\345\233\276-12.png" diff --git "a/zh-cn/device-dev/quick-start/figures/\347\275\221\347\273\234\351\230\262\347\201\253\345\242\231\350\256\276\347\275\256\345\233\276.png" "b/zh-cn/device-dev/quick-start/figure/\347\275\221\347\273\234\351\230\262\347\201\253\345\242\231\350\256\276\347\275\256\345\233\276.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/quick-start/figures/\347\275\221\347\273\234\351\230\262\347\201\253\345\242\231\350\256\276\347\275\256\345\233\276.png" rename to "zh-cn/device-dev/quick-start/figure/\347\275\221\347\273\234\351\230\262\347\201\253\345\242\231\350\256\276\347\275\256\345\233\276.png" diff --git "a/zh-cn/device-dev/quick-start/figures/\350\256\276\347\275\256\345\233\276\344\276\213-4.png" "b/zh-cn/device-dev/quick-start/figure/\350\256\276\347\275\256\345\233\276\344\276\213-4.png" similarity index 100% rename from "zh-cn/device-dev/quick-start/figures/\350\256\276\347\275\256\345\233\276\344\276\213-4.png" rename to "zh-cn/device-dev/quick-start/figure/\350\256\276\347\275\256\345\233\276\344\276\213-4.png" diff --git "a/zh-cn/device-dev/quick-start/figures/\350\256\276\347\275\256\345\233\276\344\276\213.png" "b/zh-cn/device-dev/quick-start/figure/\350\256\276\347\275\256\345\233\276\344\276\213.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/quick-start/figures/\350\256\276\347\275\256\345\233\276\344\276\213.png" rename to "zh-cn/device-dev/quick-start/figure/\350\256\276\347\275\256\345\233\276\344\276\213.png" diff --git "a/zh-cn/device-dev/quick-start/figures/\351\230\262\347\201\253\345\242\231\345\222\214\347\275\221\347\273\234\344\277\235\346\212\244\347\225\214\351\235\242\345\233\276-13.png" "b/zh-cn/device-dev/quick-start/figure/\351\230\262\347\201\253\345\242\231\345\222\214\347\275\221\347\273\234\344\277\235\346\212\244\347\225\214\351\235\242\345\233\276-13.png" similarity index 100% rename from "zh-cn/device-dev/quick-start/figures/\351\230\262\347\201\253\345\242\231\345\222\214\347\275\221\347\273\234\344\277\235\346\212\244\347\225\214\351\235\242\345\233\276-13.png" rename to "zh-cn/device-dev/quick-start/figure/\351\230\262\347\201\253\345\242\231\345\222\214\347\275\221\347\273\234\344\277\235\346\212\244\347\225\214\351\235\242\345\233\276-13.png" diff --git "a/zh-cn/device-dev/quick-start/figures/\351\230\262\347\201\253\345\242\231\345\222\214\347\275\221\347\273\234\344\277\235\346\212\244\347\225\214\351\235\242\345\233\276.png" "b/zh-cn/device-dev/quick-start/figure/\351\230\262\347\201\253\345\242\231\345\222\214\347\275\221\347\273\234\344\277\235\346\212\244\347\225\214\351\235\242\345\233\276.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/quick-start/figures/\351\230\262\347\201\253\345\242\231\345\222\214\347\275\221\347\273\234\344\277\235\346\212\244\347\225\214\351\235\242\345\233\276.png" rename to "zh-cn/device-dev/quick-start/figure/\351\230\262\347\201\253\345\242\231\345\222\214\347\275\221\347\273\234\344\277\235\346\212\244\347\225\214\351\235\242\345\233\276.png" diff --git "a/zh-cn/device-dev/quick-start/figures/3516\346\255\243\351\235\242-16.png" "b/zh-cn/device-dev/quick-start/figures/3516\346\255\243\351\235\242-16.png" deleted file mode 100644 index 6975fb5fef92e35dec2de84b7e7035a39794bdf4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 420903 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

    -`862MRvZSD;N654l!^>als0f^x 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

    71! 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 diff --git a/zh-cn/device-dev/quick-start/public_sys-resources/icon-caution.gif b/zh-cn/device-dev/quick-start/public_sys-resources/icon-caution.gif deleted file mode 100755 index 6e90d7cfc2193e39e10bb58c38d01a23f045d571..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 580 zcmV-K0=xZ3Nk%w1VIu$?0Hp~4{QBgqmQ+MG9K51r{QB&)np^||1PlfQ%(86!{`~yv zv{XhUWKt}AZaiE{EOcHp{O-j3`t;<+eEiycJT4p@77X;(jQsMfB$R?oG%6hQ z+MMLZbQBH@)Vg&1^3?qHb(5!%>3r0+`eq=&V&E}0Dypi0000000000 z00000A^8LW000R9EC2ui03!e$000L5z=Uu}ED8YtqjJd<+B}(9bIOb$3-31_h|V>=0A{ z1Hh0#H30>fNT})^fRU_83uewx9oRr{f{Sx1Ml`t)EQ zGkHZ67&~y{W5Jpq4H_WfuLxp*3<7O}GEl;1ESe36fLNs=B0&LQM1Buf(R)qg(BRd`t1OPjI1m_q4 diff --git a/zh-cn/device-dev/quick-start/public_sys-resources/icon-danger.gif b/zh-cn/device-dev/quick-start/public_sys-resources/icon-danger.gif deleted file mode 100755 index 6e90d7cfc2193e39e10bb58c38d01a23f045d571..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 580 zcmV-K0=xZ3Nk%w1VIu$?0Hp~4{QBgqmQ+MG9K51r{QB&)np^||1PlfQ%(86!{`~yv zv{XhUWKt}AZaiE{EOcHp{O-j3`t;<+eEiycJT4p@77X;(jQsMfB$R?oG%6hQ z+MMLZbQBH@)Vg&1^3?qHb(5!%>3r0+`eq=&V&E}0Dypi0000000000 z00000A^8LW000R9EC2ui03!e$000L5z=Uu}ED8YtqjJd<+B}(9bIOb$3-31_h|V>=0A{ z1Hh0#H30>fNT})^fRU_83uewx9oRr{f{Sx1Ml`t)EQ zGkHZ67&~y{W5Jpq4H_WfuLxp*3<7O}GEl;1ESe36fLNs=B0&LQM1Buf(R)qg(BRd`t1OPjI1m_q4 diff --git a/zh-cn/device-dev/quick-start/public_sys-resources/icon-note.gif b/zh-cn/device-dev/quick-start/public_sys-resources/icon-note.gif deleted file mode 100755 index 6314297e45c1de184204098efd4814d6dc8b1cda..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 394 zcmZ?wbhEHblx7fPSjxcg=ii?@_wH=jwxy=7CMGH-B`L+l$wfv=#>UF#$gv|VY%C^b zCQFtrnKN(Bo_%|sJbO}7RAORe!otL&qo<>yq_Sq+8Xqqo5h0P3w3Lvb5E(g{p01vl zxR@)KuDH0l^z`+-dH3eaw=XqSH7aTIx{kzVBN;X&hha0dQSgWuiw0NWUvMRmkD|> diff --git a/zh-cn/device-dev/quick-start/public_sys-resources/icon-notice.gif b/zh-cn/device-dev/quick-start/public_sys-resources/icon-notice.gif deleted file mode 100755 index 86024f61b691400bea99e5b1f506d9d9aef36e27..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 406 zcmV;H0crk6Nk%w1VIu$@0J8u9|NsB@_xJDb@8;&_*4Ea}&d#;9wWXz{jEszHYim+c zQaU<1At50E0000000000A^8Le000gEEC2ui03!e%000R7038S%NU)&51O^i-Tu6`s z0)`MFE@;3YqD6xSC^kTNu_J>91{PH8XfZ(p1pp2-SU@u3#{mEUC}_}tg3+I#{z}{Ok@D_ZUDg- zt0stin4;pC8M{WLSlRH*1pzqEw1}3oOskyNN?j;7HD{BBZ*OEcv4HK!6Bk6beR+04 z&8}k>SkTusVTDmkyOz#5fCA$JTPGJVQvr3uZ?QzzPQFvD0rGf_PdrcF`pMs}p^BcF zKtKTd`0wipR%nKN&Wj+V}pX;WC3SdJV!a_8Qi zE7z`U*|Y^H0^}fB$R?oG%6hQ z+MMLZbQBH@)Vg&1^3?qHb(5!%>3r0+`eq=&V&E}0Dypi0000000000 z00000A^8LW000R9EC2ui03!e$000L5z=Uu}ED8YtqjJd<+B}(9bIOb$3-31_h|V>=0A{ z1Hh0#H30>fNT})^fRU_83uewx9oRr{f{Sx1Ml`t)EQ zGkHZ67&~y{W5Jpq4H_WfuLxp*3<7O}GEl;1ESe36fLNs=B0&LQM1Buf(R)qg(BRd`t1OPjI1m_q4 diff --git "a/zh-cn/device-dev/quick-start/\346\246\202\350\277\260-0.md" b/zh-cn/device-dev/quick-start/quickstart-lite-env-setup-des.md similarity index 100% rename from "zh-cn/device-dev/quick-start/\346\246\202\350\277\260-0.md" rename to zh-cn/device-dev/quick-start/quickstart-lite-env-setup-des.md diff --git "a/zh-cn/device-dev/quick-start/\345\270\270\350\247\201\351\227\256\351\242\230.md" b/zh-cn/device-dev/quick-start/quickstart-lite-env-setup-faqs.md old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/quick-start/\345\270\270\350\247\201\351\227\256\351\242\230.md" rename to zh-cn/device-dev/quick-start/quickstart-lite-env-setup-faqs.md diff --git a/zh-cn/device-dev/quick-start/quickstart-lite-env-setup-lin.md b/zh-cn/device-dev/quick-start/quickstart-lite-env-setup-lin.md new file mode 100644 index 0000000000..ddd8fd5f4f --- /dev/null +++ b/zh-cn/device-dev/quick-start/quickstart-lite-env-setup-lin.md @@ -0,0 +1,361 @@ +# Ubuntu编译环境准备 + +- [获取软件](#section1897711811517) +- [获取源码](#section1545225464016) +- [安装和配置Python](#section1238412211211) +- [安装gn](#section29216201423) +- [安装ninja](#section8762358731) +- [安装LLVM](#section12202192215415) +- [安装hb](#section15794154618411) + - [前提条件](#section1083283711515) + - [安装方法](#section11518484814) + - [卸载方法](#section3512551574) + +- [安装其他工具](#section830511218494) + - [安装方法](#section54409586499) + + +系统要求:Ubuntu16.04及以上64位系统版本。 + +编译环境搭建分为如下几步: + +1. 获取源码 +2. 安装和配置python +3. 安装gn +4. 安装ninja +5. 安装LLVM +6. 安装hb + +>![](../public_sys-resources/icon-notice.gif) **须知:** +>- 针对Ubuntu编译环境我们提供了对应的Docker,该Docker封装了相关编译工具,选择使用Docker的开发者可跳过此章节。Docker使用可参考[Docker方式获取编译环境](../get-code/gettools-acquire.md)。 +>- 通常系统默认安装samba、vim等常用软件,需要做适当适配以支持Linux服务器与Windows工作台之间的文件共享。 +>- 想要详细了解OpenHarmony编译构建模块功能的开发者可参考[编译构建使用指南](../subsystems/subsys-build-mini-lite.md)。 + +## 获取软件 + +Linux服务器通用环境配置需要的工具及其获取途径如下表所示: + +**表 1** Linux服务器开发工具及获取途径 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    开发工具

    +

    用途

    +

    获取途径

    +

    源码

    +

    功能开发

    +

    参考源码获取

    +

    Python3.7+

    +

    编译构建工具

    +

    通过互联网获取

    +

    gn

    +

    产生ninja编译脚本

    +

    https://repo.huaweicloud.com/harmonyos/compiler/gn/1717/linux/gn-linux-x86-1717.tar.gz

    +

    ninja

    +

    执行ninja编译脚本

    +

    https://repo.huaweicloud.com/harmonyos/compiler/ninja/1.9.0/linux/ninja.1.9.0.tar

    +

    +

    LLVM

    +

    +

    +

    编译工具链

    +

    +

    Master及OpenHarmony_v2.x分支/标签,请使用以下10.0.1版本:

    +

    https://repo.huaweicloud.com/harmonyos/compiler/clang/10.0.1-62608/linux/llvm.tar.gz

    +

    OpenHarmony_v1.x分支/标签,请使用以下9.0.0版本:

    +

    https://repo.huaweicloud.com/harmonyos/compiler/clang/9.0.0-36191/linux/llvm-linux-9.0.0-36191.tar

    +

    hb

    +

    OpenHarmony编译构建命令行工具

    +

    通过互联网获取

    +

    其他工具

    +

    编译构建中依赖的其他工具(如打包、镜像制作等)

    +

    通过互联网获取

    +
    + +>![](../public_sys-resources/icon-notice.gif) **须知:** +>- 如果后续通过“HPM组件方式”或“HPM包管理器命令行工具方式”获取源码,不需要安装gn、ninja编译工具。 +>- (推荐)如果后续通过“镜像站点方式”或“代码仓库方式”获取源码,需要安装gn、ninja、LLVM编译工具。安装gn、ninja、LLVM编译工具时,请确保编译工具的环境变量路径唯一。 + +## 获取源码 + +开发者需要在Linux服务器上下载并解压一套源代码,请参见[源码获取](../get-code/sourcecode-acquire.md)。 + +## 安装和配置Python + +1. 打开Linux编译服务器终端。 +2. 输入如下命令,查看python版本号,需使用python3.7以上版本。 + + ``` + python3 --version + ``` + + 如果低于python3.7版本,不建议直接升级,请按照如下步骤重新安装。以python3.8为例,按照以下步骤安装python。 + + 1. 运行如下命令,查看Ubuntu版本: + + ``` + cat /etc/issue + ``` + + 1. 根据Ubuntu不同版本,安装python。 + - 如果Ubuntu 版本为18+,运行如下命令。 + + ``` + sudo apt-get install python3.8 + ``` + + - 如果Ubuntu版本为16。 + + a. 安装依赖包 + + ``` + sudo apt update && sudo apt install software-properties-common + ``` + + b. 添加deadsnakes PPA 源,然后按回车键确认安装。 + + ``` + sudo add-apt-repository ppa:deadsnakes/ppa + ``` + + c. 安装python3.8 + + ``` + sudo apt upgrade && sudo apt install python3.8 + ``` + + + +3. 设置python和python3软链接为python3.8。 + + ``` + sudo update-alternatives --install /usr/bin/python python /usr/bin/python3.8 1 + sudo update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.8 1 + ``` + +4. 安装并升级Python包管理工具(pip3),任选如下一种方式。 + - **命令行方式:** + + ``` + sudo apt-get install python3-setuptools python3-pip -y + sudo pip3 install --upgrade pip + ``` + + - **安装包方式:** + + ``` + curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py + python get-pip.py + ``` + + + +## 安装gn + +1. 打开Linux编译服务器终端。 +2. [下载gn工具](https://repo.huaweicloud.com/harmonyos/compiler/gn/1717/linux/gn-linux-x86-1717.tar.gz)。 +3. 在根目录下创建gn文件夹。 + + ``` + mkdir ~/gn + ``` + +4. 解压gn安装包至\~/gn路径下。 + + ``` + tar -xvf gn-linux-x86-1717.tar.gz -C ~/gn + ``` + +5. 设置环境变量。 + + ``` + vim ~/.bashrc + ``` + + 将以下命令拷贝到.bashrc文件的最后一行,保存并退出。 + + ``` + export PATH=~/gn:$PATH + ``` + +6. 生效环境变量。 + + ``` + source ~/.bashrc + ``` + + +## 安装ninja + +1. 打开Linux编译服务器终端。 +2. [下载ninja工具](https://repo.huaweicloud.com/harmonyos/compiler/ninja/1.9.0/linux/ninja.1.9.0.tar)。 +3. 解压ninja安装包至\~/ninja路径下。 + + ``` + tar -xvf ninja.1.9.0.tar -C ~/ + ``` + +4. 设置环境变量。 + + ``` + vim ~/.bashrc + ``` + + 将以下命令拷贝到.bashrc文件的最后一行,保存并退出。 + + ``` + export PATH=~/ninja:$PATH + ``` + +5. 生效环境变量。 + + ``` + source ~/.bashrc + ``` + + +## 安装LLVM + +1. 打开Linux编译服务器终端。 +2. [下载LLVM工具](https://repo.huaweicloud.com/harmonyos/compiler/clang/10.0.1-62608/linux/llvm.tar.gz)。 + + >![](../public_sys-resources/icon-note.gif) **说明:** + >针对OpenHarmony\_v1.x分支/标签,使用此链接[下载LLVM工具](https://repo.huaweicloud.com/harmonyos/compiler/clang/9.0.0-36191/linux/llvm-linux-9.0.0-36191.tar)。 + +3. 解压LLVM安装包至\~/llvm路径下。 + + ``` + tar -zxvf llvm.tar.gz -C ~/ + ``` + + >![](../public_sys-resources/icon-note.gif) **说明:** + >针对OpenHarmony\_v1.x分支/标签,使用如下命令解压: + >``` + >tar -xvf llvm-linux-9.0.0-36191.tar -C ~/ + >``` + +4. 设置环境变量。 + + ``` + vim ~/.bashrc + ``` + + 将以下命令拷贝到.bashrc文件的最后一行,保存并退出。 + + ``` + export PATH=~/llvm/bin:$PATH + ``` + +5. 生效环境变量。 + + ``` + source ~/.bashrc + ``` + + +## 安装hb + +### 前提条件 + +请先安装Python 3.7.4及以上版本,请见[安装和配置Python](#section1238412211211)。 + +### 安装方法 + +1. 运行如下命令安装hb + + ``` + python3 -m pip install --user ohos-build + ``` + +2. 设置环境变量 + + ``` + vim ~/.bashrc + ``` + + 将以下命令拷贝到.bashrc文件的最后一行,保存并退出。 + + ``` + export PATH=~/.local/bin:$PATH + ``` + + 执行如下命令更新环境变量。 + + ``` + source ~/.bashrc + ``` + +3. 执行"hb -h",有打印以下信息即表示安装成功: + + ``` + usage: hb + + OHOS build system + + positional arguments: + {build,set,env,clean} + build Build source code + set OHOS build settings + env Show OHOS build env + clean Clean output + + optional arguments: + -h, --help show this help message and exit + ``` + + +### 卸载方法 + +``` +python3 -m pip uninstall ohos-build +``` + +>![](../public_sys-resources/icon-notice.gif) **须知:** +>如果安装hb的过程中遇到问题,请参见下文[常见问题](quickstart-lite-env-setup-faqs.md)进行解决。 + +## 安装其他工具 + +### 安装方法 + +1. apt安装全部依赖的工具 + + ``` + sudo apt-get install build-essential gcc g++ make zlib* libffi-dev e2fsprogs pkg-config flex bison perl bc openssl libssl-dev libelf-dev libc6-dev-amd64 binutils binutils-dev libdwarf-dev u-boot-tools mtd-utils gcc-arm-linux-gnueabi + ``` + + diff --git a/zh-cn/device-dev/quick-start/quickstart-lite-env-setup-win.md b/zh-cn/device-dev/quick-start/quickstart-lite-env-setup-win.md new file mode 100644 index 0000000000..7f51e21e0b --- /dev/null +++ b/zh-cn/device-dev/quick-start/quickstart-lite-env-setup-win.md @@ -0,0 +1,182 @@ +# Windows开发环境准备 + +- [获取软件](#zh-cn_topic_0000001058091994_section1483143015558) +- [安装Visual Studio Code](#zh-cn_topic_0000001058091994_section71401018163318) +- [安装Python](#zh-cn_topic_0000001058091994_section16266553175320) +- [安装Node.js](#zh-cn_topic_0000001058091994_section5353233124511) +- [安装hpm](#zh-cn_topic_0000001058091994_section173054793610) +- [安装DevEco Device Tool插件](#zh-cn_topic_0000001058091994_section4336315185716) + +系统要求:Windows 10 64位系统。 + +DevEco Device Tool以插件方式提供,基于Visual Studio Code进行扩展,安装分为如下几步: + +1. 安装Visual Studio Code +2. 安装Python +3. 安装Node.js +4. 安装hpm +5. 安装DevEco Device Tool插件 + +## 获取软件 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    工具名称

    +

    用途说明

    +

    版本要求

    +

    获取渠道

    +

    Visual Studio Code

    +

    代码编辑工具

    +

    V1.53及以上 64位版本。

    +

    https://code.visualstudio.com/Download

    +

    Python

    +

    编译构建工具

    +

    V3.7.4~V3.8.x 64位版本

    +

    推荐下载:https://www.python.org/downloads/release/python-388/

    +

    Node.js

    +

    提供npm环境

    +

    v12.0.0及以上 64位版本

    +

    https://nodejs.org/zh-cn/download/

    +

    hpm

    +

    包管理工具

    +

    最新版

    +

    请参考安装hpm

    +

    DevEco Device Tool

    +

    OpenHarmony源码的编译、烧录、调试插件工具

    +

    v2.2 Beta1

    +

    https://device.harmonyos.com/cn/ide#download

    +

    下载前,请使用华为开发者帐号登录,如未注册,请先注册华为开发者帐号

    +
    + +## 安装Visual Studio Code + +>![](../public_sys-resources/icon-note.gif) **说明:** +>如果已安装Visual Studio Code,打开命令行工具,输入**code --version**命令,检查版本号是否为1.53及以上版本;可以正常返回版本号,说明环境变量设置也正确。 + +1. 双击Visual Studio Code软件包进行安装。安装过程中,请勾选“添加到PATH(重启后生效)”。 + + ![](figure/zh-cn_image_0000001174350653.png) + +2. 安装完成后,重启计算机,使Visual Studio Code的环境变量生效。 +3. 打开命令行工具,输入**code --version**命令,可以正常显示版本号说明安装成功。 + +## 安装Python + +1. 双击Python安装包进行安装,勾选“**Add Python 3.8 to PATH**”,然后点击**Install Now**开始安装。 + + ![](figure/zh-cn_image_0000001128470908.png) + +2. 等待安装完成后,点击**Close**。 + + ![](figure/zh-cn_image_0000001128311104.png) + +3. 打开命令行工具,输入python --version,检查安装结果。 + + ![](figure/zh-cn_image_0000001174350655.png) + +4. 在命令行工具中,分别执行如下命令设置pip源,用于后续安装DevEco Device Tool过程中下载依赖的组件包。 + + ``` + pip config set global.trusted-host repo.huaweicloud.com + pip config set global.index-url https://repo.huaweicloud.com/repository/pypi/simple + pip config set global.timeout 120 + ``` + + +## 安装Node.js + +>![](../public_sys-resources/icon-note.gif) **说明:** +>如果已安装Node.js,打开命令行工具,输入**node -v**命令,检查版本号是否为12.0.0及以上版本。 + +1. 点击下载后的软件包进行安装,全部按照默认设置点击**Next**,直至**Finish**。安装过程中,Node.js会自动在系统的path环境变量中配置node.exe的目录路径。 +2. 重新打开命令行工具,输入“node -v“命令,能正常查询Node.js的版本号,说明Node.js安装成功。 + + ![](figure/zh-cn_image_0000001128311096.png) + + +## 安装hpm + +该方式需先确保**Node.js**安装成功。 + +在安装hpm前,请检查网络连接状态,如果网络不能直接访问Internet,则需要通过代理服务器才可以访问。这种情况下,需要先[设置npm代理](https://device.harmonyos.com/cn/docs/ide/user-guides/npm_proxy-0000001054491032),才能安装hpm。 + +>![](../public_sys-resources/icon-note.gif) **说明:** +>如果已安装hpm,可以执行**npm update -g @ohos/hpm-cli**命令升级hpm至最新版本。 + +1. 建议将npm源配置为国内镜像,例如设置为华为云镜像源。 + + ``` + npm config set registry https://repo.huaweicloud.com/repository/npm/ + ``` + +2. 打开命令行工具,执行如下命令安装最新版本hpm。 + + ``` + npm install -g @ohos/hpm-cli + ``` + + ![](figure/zh-cn_image_0000001128311100.png) + +3. 安装完成后,执行如下命令(V为大写字母)检查hpm安装结果。 + + ``` + hpm -V + ``` + + ![](figure/zh-cn_image_0000001174270735.png) + + +## 安装DevEco Device Tool插件 + +安装DevEco Device Tool插件,**主机的用户名不能包含中文字符**,否则可能导致运行出现错误。 + +DevEco Device Tool正常运行需要依赖于C/C++和CodeLLDB插件,在安装完DevEco Device Tool后,会自动从Visual Studio Code的插件市场安装C/C++和CodeLLDB插件。因此,在安装DevEco Device Tool前,请检查Visual Studio Code的网络连接状态,如果网络不能直接访问Internet,则需要通过代理服务器才可以访问,请先[Visual Studio Code代理设置](https://device.harmonyos.com/cn/docs/ide/user-guides/vscode_proxy-0000001074231144)。 + +>![](../public_sys-resources/icon-note.gif) **说明:** +>安装DevEco Device Tool时,请先关闭Visual Studio Code。 + +1. 解压DevEco Device Tool插件压缩包,双击安装包程序进行安装。 +2. 安装过程中,会自动安装DevEco Device Tool所需的依赖文件(如C/C++和CodeLLDB插件)和执行程序。 + + ![](figure/zh-cn_image_0000001128470902.png) + +3. 安装完成后,会自动关闭命令行工具窗口。 +4. 启动Visual Studio Code,点击左侧的![](figure/zh-cn_image_0000001174350651.png)按钮,检查INSTALLED中,是否已成功安装C/C++、CodeLLDB和DevEco Device Tool。 + + >![](../public_sys-resources/icon-note.gif) **说明:** + >如果C/C++和CodeLLDB插件安装不成功,则DevEco Device Tool不能正常运行,解决方法,详细请参考:[离线安装C/C++和CodeLLDB插件](https://device.harmonyos.com/cn/docs/ide/user-guides/offline_plugin_install-0000001074376846)。 + + ![](figure/zh-cn_image_0000001174270727.png) + + diff --git a/zh-cn/device-dev/quick-start/quickstart-lite-env-setup.md b/zh-cn/device-dev/quick-start/quickstart-lite-env-setup.md new file mode 100644 index 0000000000..f5782f2a9f --- /dev/null +++ b/zh-cn/device-dev/quick-start/quickstart-lite-env-setup.md @@ -0,0 +1,11 @@ +# 搭建系统环境 + +- **[概述](quickstart-lite-env-setup-des.md)** + +- **[Windows开发环境准备](quickstart-lite-env-setup-win.md)** + +- **[Ubuntu编译环境准备](quickstart-lite-env-setup-lin.md)** + +- **[常见问题](quickstart-lite-env-setup-faqs.md)** + + diff --git a/zh-cn/device-dev/quick-start/quickstart-lite-introduction-hi3516.md b/zh-cn/device-dev/quick-start/quickstart-lite-introduction-hi3516.md new file mode 100644 index 0000000000..1224e4f346 --- /dev/null +++ b/zh-cn/device-dev/quick-start/quickstart-lite-introduction-hi3516.md @@ -0,0 +1,42 @@ +# Hi3516开发板介绍 + +- [简介](#section26131214194212) +- [开发板规格](#section15192203316533) + +## 简介 + +Hi3516DV300作为新一代行业专用Smart HD IP摄像机SOC,集成新一代ISP\(Image Signal Processor\)、H.265视频压缩编码器,同时集成高性能NNIE引擎,使得Hi3516DV300在低码率、高画质、智能处理和分析、低功耗等方面引领行业水平。 + +**图 1** Hi3516单板正面外观图 + + +![](figure/3516正面.png) + +## 开发板规格 + +**表 1** Hi3516开发板规格清单 + + + + + + + + + + + + + +

    规格类型

    +

    规格清单

    +

    处理器及内部存储

    +
    • Hi3516DV300芯片
    • DDR3 1GB
    • eMMC4.5,8GB容量
    +

    外部器件

    +
    • 以太网口
    • 音频视频
      • 1路语音输入
      • 1路单声道(AC_L)输出,接3W功放(LM4871)
      • MicroHDMI(1路HDMI 1.4)
      +
    • 摄像头
      • 传感器IMX335
      • 镜头M12,焦距4mm,光圈1.8
      +
    • 显示屏
      • LCD连接器(2.35寸)
      • LCD连接器(5.5寸)
      +
    • 外部器件及接口
      • SD卡接口
      • JTAG/I2S 接口
      • ADC接口
      • 舵机接口
      • Grove连接器
      • USB2.0(Type C)
      • 功能按键3个,2个用户自定义按键,1个升级按键
      • LED指示灯,绿灯,红灯
      +
    +
    + diff --git a/zh-cn/device-dev/quick-start/quickstart-lite-introduction-hi3518.md b/zh-cn/device-dev/quick-start/quickstart-lite-introduction-hi3518.md new file mode 100644 index 0000000000..211dffba8a --- /dev/null +++ b/zh-cn/device-dev/quick-start/quickstart-lite-introduction-hi3518.md @@ -0,0 +1,57 @@ +# Hi3518开发板介绍 + +- [简介](#section14815247616) +- [开发板规格](#section765112478446) + +## 简介 + +Hi3518EV300作为新一代智慧视觉处理SOC,集成新一代ISP\(Image Signal Processor\)以及H.265视频压缩编码器,同时采用先进低功耗工艺和低功耗架构设计,使其在低码率、高画质、低功耗等方面引领行业水平。 + +**图 1** Hi3518EV300单板正面外观图 +![](figure/Hi3518EV300单板正面外观图.png "Hi3518EV300单板正面外观图") + +**图 2** Hi3518EV300单板背面外观图 + + +![](figure/Hi3518正背面.png) + +## 开发板规格 + +**表 1** Hi3518开发板规格清单 + + + + + + + + + + + + + + + + + + + + + + +

    规格类型

    +

    规格清单

    +

    处理器内核

    +
    • 海思3518EV300
    +

    成像器件

    +
    • 1/2.9 F23
    +

    外部接口

    +
    • 外置麦克风MIC
    • 外置8Ω/1.5W扬声器
    +

    外部存储器接口

    +
    • TF卡

      最大支持128GB(通用FAT32格式)

      +
    +

    WLAN协议

    +
    • 支持 802.11 b/g/n
    +
    + diff --git a/zh-cn/device-dev/quick-start/quickstart-lite-introduction-hi3861.md b/zh-cn/device-dev/quick-start/quickstart-lite-introduction-hi3861.md new file mode 100644 index 0000000000..84549ecc12 --- /dev/null +++ b/zh-cn/device-dev/quick-start/quickstart-lite-introduction-hi3861.md @@ -0,0 +1,157 @@ +# Hi3861开发板介绍 + +- [简介](#section19352114194115) +- [资源和约束](#section82610215014) +- [开发板规格](#section169054431017) +- [OpenHarmony关键特性](#section1317173016507) + +## 简介 + +Hi3861 WLAN模组是一片大约2cm\*5cm大小的开发板,是一款高度集成的2.4GHz WLAN SoC芯片,集成IEEE 802.11b/g/n基带和RF(Radio Frequency)电路。支持OpenHarmony,并配套提供开放、易用的开发和调试运行环境。 + +**图 1** Hi3861 WLAN模组外观图 + + +![](figure/3861正面.png) + +另外,Hi3861 WLAN模组还可以通过与Hi3861底板连接,扩充自身的外设能力,底板如下图所示。 + +**图 2** Hi3861底板外观图 + + +![](figure/zh-cn_image_0000001174350615.png) + +- RF电路包括功率放大器PA(Power Amplifier)、低噪声放大器LNA(Low Noise Amplifier)、RF Balun、天线开关以及电源管理等模块;支持20MHz标准带宽和5MHz/10MHz窄带宽,提供最大72.2Mbit/s物理层速率。 +- Hi3861 WLAN基带支持正交频分复用(OFDM)技术,并向下兼容直接序列扩频(DSSS)和补码键控(CCK)技术,支持IEEE 802.11 b/g/n协议的各种数据速率。 +- Hi3861芯片集成高性能32bit微处理器、硬件安全引擎以及丰富的外设接口,外设接口包括SPI(Synchronous Peripheral Interface)、UART(Universal Asynchronous Receiver & Transmitter)、I2C(The Inter Integrated Circuit)、PWM(Pulse Width Modulation)、GPIO(General Purpose Input/Output)和多路ADC(Analog to Digital Converter),同时支持高速SDIO2.0(Secure Digital Input/Output)接口,最高时钟可达50MHz;芯片内置SRAM(Static Random Access Memory)和Flash,可独立运行,并支持在Flash上运行程序。 +- Hi3861芯片适用于智能家电等物联网智能终端领域。 + + **图 3** Hi3861功能框图 + + + ![](figure/zh-cn_image_0000001128311066.png) + + +## 资源和约束 + +Hi3861 WLAN模组资源十分有限,整板共2MB FLASH,352KB RAM。在编写业务代码时,需注意资源使用效率。 + +## 开发板规格 + +**表 1** Hi3861 WLAN模组规格清单 + + + + + + + + + + + + + + + + + + + + + + + + + +

    规格类型

    +

    规格清单

    +

    通用规格

    +
    • 1×1 2.4GHz频段(ch1~ch14)
    • PHY支持IEEE 802.11b/g/n
    • MAC支持IEEE802.11 d/e/h/i/k/v/w
    +
    • 内置PA和LNA,集成TX/RX Switch、Balun等
    • 支持STA和AP形态,作为AP时最大支持6 个STA接入
    • 支持WFA WPA/WPA2 personal、WPS2.0
    • 支持与BT/BLE芯片共存的2/3/4 线PTA方案
    • 电源电压输入范围:2.3V~3.6V
    +
    • IO电源电压支持1.8V和3.3V
    +
    • 支持RF自校准方案
    • 低功耗:
      • Ultra Deep Sleep模式:5μA@3.3V
      • DTIM1:1.5mA@3.3V
      • DTIM3:0.8mA@3.3V
      +
    +

    PHY特性

    +
    • 支持IEEE802.11b/g/n单天线所有的数据速率
    • 支持最大速率:72.2Mbps@HT20 MCS7
    • 支持标准20MHz带宽和5M/10M窄带宽
    • 支持STBC
    • 支持Short-GI
    +

    MAC特性

    +
    • 支持A-MPDU,A-MSDU
    • 支持Blk-ACK
    • 支持QoS,满足不同业务服务质量需求
    +

    CPU子系统

    +
    • 高性能 32bit微处理器,最大工作频率160MHz
    • 内嵌SRAM 352KB、ROM 288KB
    • 内嵌 2MB Flash
    +

    外围接口

    +
    • 1个SDIO接口、2个SPI接口、2个I2C接口、3个UART接口、15个GPIO接口、7路ADC输入、6路PWM、1个I2S接口(注:上述接口通过复用实现)
    • 外部主晶体频率40M或24M
    +

    其他信息

    +
    • 封装:QFN-32,5mm×5mm
    • 工作温度:-40℃ ~ +85℃
    +
    + +## OpenHarmony关键特性 + +OpenHarmony基于Hi3861平台提供了多种开放能力,提供的关键组件如下表所示。 + +**表 2** OpenHarmony关键组件列表 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    组件名

    +

    能力介绍

    +

    WLAN服务

    +

    提供WLAN服务能力。包括:station和hotspot模式的连接、断开、状态查询等。

    +

    模组外设控制

    +

    提供操作外设的能力。包括:I2C、I2S、ADC、UART、SPI、SDIO、GPIO、PWM、FLASH等。

    +

    分布式软总线

    +

    OpenHarmony分布式网络中,提供设备被发现、数据传输的能力。

    +

    设备安全绑定

    +

    提供在设备互联场景中,数据在设备之间的安全流转的能力。

    +

    基础加解密

    +

    提供密钥管理、加解密等能力。

    +

    系统服务管理

    +

    系统服务管理基于面向服务的架构,提供了OpenHarmony统一化的系统服务开发框架。

    +

    启动引导

    +

    提供系统服务的启动入口标识。在系统服务管理启动时,调用boostrap标识的入口函数,并启动系统服务。

    +

    系统属性

    +

    提供获取与设置系统属性的能力。

    +

    基础库

    +

    提供公共基础库能力。包括:文件操作、KV存储管理等。

    +

    DFX

    +

    提供DFX能力。包括:流水日志、时间打点等。

    +

    XTS

    +

    提供OpenHarmony生态认证测试套件的集合能力。

    +
    + diff --git a/zh-cn/device-dev/quick-start/quickstart-lite-introduction.md b/zh-cn/device-dev/quick-start/quickstart-lite-introduction.md new file mode 100644 index 0000000000..65e4fde55c --- /dev/null +++ b/zh-cn/device-dev/quick-start/quickstart-lite-introduction.md @@ -0,0 +1,9 @@ +# 了解开发板 + +- **[Hi3861开发板介绍](quickstart-lite-introduction-hi3861.md)** + +- **[Hi3516开发板介绍](quickstart-lite-introduction-hi3516.md)** + +- **[Hi3518开发板介绍](quickstart-lite-introduction-hi3518.md)** + + diff --git "a/zh-cn/device-dev/quick-start/\346\246\202\350\277\260.md" b/zh-cn/device-dev/quick-start/quickstart-lite-overview.md similarity index 100% rename from "zh-cn/device-dev/quick-start/\346\246\202\350\277\260.md" rename to zh-cn/device-dev/quick-start/quickstart-lite-overview.md diff --git a/zh-cn/device-dev/quick-start/quickstart-lite-steps-board3516-faqs.md b/zh-cn/device-dev/quick-start/quickstart-lite-steps-board3516-faqs.md new file mode 100644 index 0000000000..ff748404f0 --- /dev/null +++ b/zh-cn/device-dev/quick-start/quickstart-lite-steps-board3516-faqs.md @@ -0,0 +1,175 @@ +# 常见问题 + +- [烧写选择串口后提示失败](#section627268185113) +- [Windows电脑与单板网络连接失败](#section195391036568) +- [烧写失败](#section571164016565) +- [编译构建过程中,提示找不到“python”](#section1039835245619) +- [串口无回显](#section14871149155911) + +## 烧写选择串口后提示失败 + +- **现象描述** + + 点击烧写并选择串口后,出现Error: Opening COMxx: Access denied。 + + **图 1** 打开串口失败图 + ![](figure/打开串口失败图.png "打开串口失败图") + +- **可能原因** + + 串口已经被占用。 + +- **解决办法** + +1. 按图依次选择下拉框,查找带有serial-xx的终端 + + **图 2** 查找是否存在占用串口的终端 + ![](figure/查找是否存在占用串口的终端.png "查找是否存在占用串口的终端") + +2. 点击标号中的垃圾桶图标,关闭串口。 + + **图 3** 关闭串口终端 + ![](figure/关闭串口终端.png "关闭串口终端") + +3. 重新点击烧写,选择串口并开始烧写程序 + + **图 4** 重新启动烧写任务 + + + ![](figure/changjian1.png) + + +## Windows电脑与单板网络连接失败 + +- **现象描述** + + 点击烧写并选择串口后,无法获取文件。 + + **图 5** 网络不通,单板无法获取文件图 + ![](figure/网络不通-单板无法获取文件图.png "网络不通-单板无法获取文件图") + +- **可能原因** + + 单板网络与Windows电脑不联通。 + + Windows电脑防火墙未允许Visual Studio Code联网。 + +- **解决方法** + +1. 检查网线是否连接。 +2. 点击Windows防火墙。 + + **图 6** 网络防火墙设置图 + ![](figure/网络防火墙设置图.png "网络防火墙设置图") + +3. 点击“允许应用通过防火墙”。 + + **图 7** 防火墙和网络保护界面图 + ![](figure/防火墙和网络保护界面图.png "防火墙和网络保护界面图") + +4. 查找Visual Studio Code应用。 + + **图 8** 查找Visual Studio Code应用图 + ![](figure/查找Visual-Studio-Code应用图.png "查找Visual-Studio-Code应用图") + +5. 勾选Visual Studio Code的专用和公用网络的访问权限。 + + **图 9** 允许Visual Studio Code应用访问网络 + ![](figure/允许Visual-Studio-Code应用访问网络.png "允许Visual-Studio-Code应用访问网络") + + +## 烧写失败 + +- **现象描述** + + 点击烧写并选择串口后,出现无法烧写的情况。 + +- **可能原因** + + 安装IDE插件DevEco后未重启。 + +- **解决方法** + + 重启IDE。 + + +## 编译构建过程中,提示找不到“python” + +- **现象描述** + + ![](figure/zh-cn_image_0000001174270715.png) + + +- **可能原因1** + + 没有装python。 + +- **解决办法** + + 请按照[安装python](quickstart-lite-env-setup-lin.md)。 + +- **可能原因2** + + ![](figure/zh-cn_image_0000001128470880.png) + +- **解决办法** + + usr/bin目录下没有python软链接,请运行以下命令: + + ``` + # cd /usr/bin/ + # which python3 + # ln -s /usr/local/bin/python3 python + # python --version + ``` + + 例: + + ![](figure/zh-cn_image_0000001174270713.png) + + +## 串口无回显 + +- **现象描述** + + 串口显示已连接,重启单板后,回车无任何回显。 + +- **可能原因1** + + 串口连接错误。 + +- **解决办法** + + 修改串口号。 + + 请查看设备管理器,确认连接单板的串口与终端中连接串口是否一致,若不一致,请按镜像运行内[步骤1](#section627268185113)修改串口号。 + + +- **可能原因2** + + 单板U-boot被损坏。 + +- **解决办法** + + 烧写U-boot。 + + 若上述步骤依旧无法连接串口,可能由于单板U-boot损坏,按下述步骤烧写U-boot。 + + +1. 获取引导文件U-boot。 + + >![](../public_sys-resources/icon-notice.gif) **须知:** + >单板的U-boot文件请在开源包中获取: + >Hi3516DV300:device\\hisilicon\\hispark\_taurus\\sdk\_liteos\\uboot\\out\\boot\\u-boot-hi3516dv300.bin + >Hi3518EV300:device\\hisilicon\\hispark\_aries\\sdk\_liteos\\uboot\\out\\boot\\u-boot-hi3518ev300.bin + +2. 根据USB烧写步骤烧写U-boot文件。 + + 按照[Hi3516系列USB烧写步骤](https://device.harmonyos.com/cn/docs/ide/user-guides/hi3516_upload-0000001052148681)/[Hi3518系列USB烧写步骤](https://device.harmonyos.com/cn/docs/ide/user-guides/hi3518_upload-0000001057313128)中描述的USB烧写方法,选择对应单板的U-boot文件进行烧写。 + +3. 烧写完成后,登录串口如下图所示。 + + **图 10** U-boot烧写完成串口显示图 + ![](figure/U-boot烧写完成串口显示图.png "U-boot烧写完成串口显示图") + + diff --git a/zh-cn/device-dev/quick-start/quickstart-lite-steps-board3516-program.md b/zh-cn/device-dev/quick-start/quickstart-lite-steps-board3516-program.md new file mode 100644 index 0000000000..7b43c52c82 --- /dev/null +++ b/zh-cn/device-dev/quick-start/quickstart-lite-steps-board3516-program.md @@ -0,0 +1,503 @@ +# 驱动开发示例 + +- [驱动程序介绍](#s8efc1952ebfe4d1ea717182e108c29bb) +- [编译和烧写](#section660016185110) +- [镜像运行](#section333215226219) +- [下一步学习](#section9712145420182) + +本节指导开发者在单板上运行第一个驱动程序,其中包括驱动程序介绍、编译、烧写、运行等步骤。 + +## 驱动程序介绍 + +下面基于HDF框架,提供一个简单的UART(Universal Asynchronous Receiver/Transmitter)平台驱动开发样例,包含配置文件的添加,驱动代码的实现以及用户态程序和驱动交互的流程。驱动程序源码位于vendor/huawei/hdf/sample目录 + +1. 添加配置。 + + 在HDF框架的驱动配置文件(例如device/hisilicon/hi3516dv300/sdk\_liteos/config/uart/uart\_config.hcs)中添加该驱动的配置信息,如下所示: + + ``` + root { + platform { + uart_sample { + num = 5; // UART设备编号 + base = 0x120a0000; // UART 寄存器基地址 + irqNum = 38; + baudrate = 115200; + uartClk = 24000000; + wlen = 0x60; + parity = 0; + stopBit = 0; + match_attr = "sample_uart_5"; + } + } + } + ``` + + 在HDF框架的设备配置文件(例如vendor/hisilicon/ipcamera\_hi3516dv300\_liteos/config/device\_info/device\_info.hcs)中添加该驱动的设备节点信息,如下所示: + + ``` + root { + device_info { + platform :: host { + hostName = "platform_host"; + priority = 50; + device_uart :: device { + device5 :: deviceNode { + policy = 2; + priority = 10; + permission = 0660; + moduleName = "UART_SAMPLE"; + serviceName = "HDF_PLATFORM_UART_5"; + deviceMatchAttr = "sample_uart_5"; + } + } + } + } + } + ``` + + >![](../public_sys-resources/icon-note.gif) **说明:** + >配置文件与UART驱动示例的源码在同一个路径,需要手动添加到Hi3516DV300单板路径下。 + +2. 注册UART驱动入口。 + + 基于HDF框架注册UART驱动的入口HdfDriverEntry,代码如下: + + ``` + // 绑定UART驱动接口到HDF框架 + static int32_t SampleUartDriverBind(struct HdfDeviceObject *device) + { + struct UartHost *uartHost = NULL; + + if (device == NULL) { + return HDF_ERR_INVALID_OBJECT; + } + HDF_LOGI("Enter %s:", __func__); + + uartHost = UartHostCreate(device); + if (uartHost == NULL) { + HDF_LOGE("%s: UartHostCreate failed", __func__); + return HDF_FAILURE; + } + uartHost->service.Dispatch = SampleDispatch; + return HDF_SUCCESS; + } + + // 从UART驱动的HCS中获取配置信息 + static uint32_t GetUartDeviceResource( + struct UartDevice *device, const struct DeviceResourceNode *resourceNode) + { + struct UartResource *resource = &device->resource; + struct DeviceResourceIface *dri = NULL; + dri = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE); + if (dri == NULL || dri->GetUint32 == NULL) { + HDF_LOGE("DeviceResourceIface is invalid"); + return HDF_FAILURE; + } + + if (dri->GetUint32(resourceNode, "num", &resource->num, 0) != HDF_SUCCESS) { + HDF_LOGE("uart config read num fail"); + return HDF_FAILURE; + } + if (dri->GetUint32(resourceNode, "base", &resource->base, 0) != HDF_SUCCESS) { + HDF_LOGE("uart config read base fail"); + return HDF_FAILURE; + } + resource->physBase = (unsigned long)OsalIoRemap(resource->base, 0x48); + if (resource->physBase == 0) { + HDF_LOGE("uart config fail to remap physBase"); + return HDF_FAILURE; + } + if (dri->GetUint32(resourceNode, "irqNum", &resource->irqNum, 0) != HDF_SUCCESS) { + HDF_LOGE("uart config read irqNum fail"); + return HDF_FAILURE; + } + if (dri->GetUint32(resourceNode, "baudrate", &resource->baudrate, 0) != HDF_SUCCESS) { + HDF_LOGE("uart config read baudrate fail"); + return HDF_FAILURE; + } + if (dri->GetUint32(resourceNode, "wlen", &resource->wlen, 0) != HDF_SUCCESS) { + HDF_LOGE("uart config read wlen fail"); + return HDF_FAILURE; + } + if (dri->GetUint32(resourceNode, "parity", &resource->parity, 0) != HDF_SUCCESS) { + HDF_LOGE("uart config read parity fail"); + return HDF_FAILURE; + } + if (dri->GetUint32(resourceNode, "stopBit", &resource->stopBit, 0) != HDF_SUCCESS) { + HDF_LOGE("uart config read stopBit fail"); + return HDF_FAILURE; + } + if (dri->GetUint32(resourceNode, "uartClk", &resource->uartClk, 0) != HDF_SUCCESS) { + HDF_LOGE("uart config read uartClk fail"); + return HDF_FAILURE; + } + return HDF_SUCCESS; + } + + // 将UART驱动的配置和接口附加到HDF驱动框架 + static int32_t AttachUartDevice(struct UartHost *host, struct HdfDeviceObject *device) + { + int32_t ret; + struct UartDevice *uartDevice = NULL; + if (device->property == NULL) { + HDF_LOGE("%s: property is NULL", __func__); + return HDF_FAILURE; + } + uartDevice = (struct UartDevice *)OsalMemCalloc(sizeof(struct UartDevice)); + if (uartDevice == NULL) { + HDF_LOGE("%s: OsalMemCalloc uartDevice error", __func__); + return HDF_ERR_MALLOC_FAIL; + } + ret = GetUartDeviceResource(uartDevice, device->property); + if (ret != HDF_SUCCESS) { + (void)OsalMemFree(uartDevice); + return HDF_FAILURE; + } + host->num = uartDevice->resource.num; + host->priv = uartDevice; + AddUartDevice(host); + return InitUartDevice(uartDevice); + } + + // 初始化UART驱动 + static int32_t SampleUartDriverInit(struct HdfDeviceObject *device) + { + int32_t ret; + struct UartHost *host = NULL; + + if (device == NULL) { + HDF_LOGE("%s: device is NULL", __func__); + return HDF_ERR_INVALID_OBJECT; + } + HDF_LOGI("Enter %s:", __func__); + host = UartHostFromDevice(device); + if (host == NULL) { + HDF_LOGE("%s: host is NULL", __func__); + return HDF_FAILURE; + } + ret = AttachUartDevice(host, device); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: attach error", __func__); + return HDF_FAILURE; + } + host->method = &g_sampleUartHostMethod; + return ret; + } + + static void DeinitUartDevice(struct UartDevice *device) + { + struct UartRegisterMap *regMap = (struct UartRegisterMap *)device->resource.physBase; + /* wait for uart enter idle. */ + while (UartPl011IsBusy(regMap)); + UartPl011ResetRegisters(regMap); + uart_clk_cfg(0, false); + OsalIoUnmap((void *)device->resource.physBase); + device->state = UART_DEVICE_UNINITIALIZED; + } + + // 解绑并释放UART驱动 + static void DetachUartDevice(struct UartHost *host) + { + struct UartDevice *uartDevice = NULL; + + if (host->priv == NULL) { + HDF_LOGE("%s: invalid parameter", __func__); + return; + } + uartDevice = host->priv; + DeinitUartDevice(uartDevice); + (void)OsalMemFree(uartDevice); + host->priv = NULL; + } + + // 释放UART驱动 + static void SampleUartDriverRelease(struct HdfDeviceObject *device) + { + struct UartHost *host = NULL; + HDF_LOGI("Enter %s:", __func__); + + if (device == NULL) { + HDF_LOGE("%s: device is NULL", __func__); + return; + } + host = UartHostFromDevice(device); + if (host == NULL) { + HDF_LOGE("%s: host is NULL", __func__); + return; + } + if (host->priv != NULL) { + DetachUartDevice(host); + } + UartHostDestroy(host); + } + + struct HdfDriverEntry g_sampleUartDriverEntry = { + .moduleVersion = 1, + .moduleName = "UART_SAMPLE", + .Bind = SampleUartDriverBind, + .Init = SampleUartDriverInit, + .Release = SampleUartDriverRelease, + }; + + HDF_INIT(g_sampleUartDriverEntry); + ``` + +3. 注册UART驱动接口。 + + HDF框架提供了UART驱动接口的模板方法UartHostMethod,实现UART驱动接口的代码如下: + + ``` + static int32_t SampleUartHostInit(struct UartHost *host) + { + HDF_LOGI("%s: Enter", __func__); + if (host == NULL) { + HDF_LOGE("%s: invalid parameter", __func__); + return HDF_ERR_INVALID_PARAM; + } + return HDF_SUCCESS; + } + + static int32_t SampleUartHostDeinit(struct UartHost *host) + { + HDF_LOGI("%s: Enter", __func__); + if (host == NULL) { + HDF_LOGE("%s: invalid parameter", __func__); + return HDF_ERR_INVALID_PARAM; + } + return HDF_SUCCESS; + } + + // 向UART中写入数据 + static int32_t SampleUartHostWrite(struct UartHost *host, uint8_t *data, uint32_t size) + { + HDF_LOGI("%s: Enter", __func__); + uint32_t idx; + struct UartRegisterMap *regMap = NULL; + struct UartDevice *device = NULL; + + if (host == NULL || data == NULL || size == 0) { + HDF_LOGE("%s: invalid parameter", __func__); + return HDF_ERR_INVALID_PARAM; + } + device = (struct UartDevice *)host->priv; + if (device == NULL) { + HDF_LOGE("%s: device is NULL", __func__); + return HDF_ERR_INVALID_PARAM; + } + regMap = (struct UartRegisterMap *)device->resource.physBase; + for (idx = 0; idx < size; idx++) { + UartPl011Write(regMap, data[idx]); + } + return HDF_SUCCESS; + } + + // 设置UART的波特率 + static int32_t SampleUartHostSetBaud(struct UartHost *host, uint32_t baudRate) + { + HDF_LOGI("%s: Enter", __func__); + struct UartDevice *device = NULL; + struct UartRegisterMap *regMap = NULL; + UartPl011Error err; + + if (host == NULL) { + HDF_LOGE("%s: invalid parameter", __func__); + return HDF_ERR_INVALID_PARAM; + } + device = (struct UartDevice *)host->priv; + if (device == NULL) { + HDF_LOGE("%s: device is NULL", __func__); + return HDF_ERR_INVALID_PARAM; + } + regMap = (struct UartRegisterMap *)device->resource.physBase; + if (device->state != UART_DEVICE_INITIALIZED) { + return UART_PL011_ERR_NOT_INIT; + } + if (baudRate == 0) { + return UART_PL011_ERR_INVALID_BAUD; + } + err = UartPl011SetBaudrate(regMap, device->uartClk, baudRate); + if (err == UART_PL011_ERR_NONE) { + device->baudrate = baudRate; + } + return err; + } + + // 获取UART的波特率 + static int32_t SampleUartHostGetBaud(struct UartHost *host, uint32_t *baudRate) + { + HDF_LOGI("%s: Enter", __func__); + struct UartDevice *device = NULL; + + if (host == NULL) { + HDF_LOGE("%s: invalid parameter", __func__); + return HDF_ERR_INVALID_PARAM; + } + device = (struct UartDevice *)host->priv; + if (device == NULL) { + HDF_LOGE("%s: device is NULL", __func__); + return HDF_ERR_INVALID_PARAM; + } + *baudRate = device->baudrate; + return HDF_SUCCESS; + } + + // 在HdfUartSampleInit方法中绑定 + struct UartHostMethod g_sampleUartHostMethod = { + .Init = SampleUartHostInit, + .Deinit = SampleUartHostDeinit, + .Read = NULL, + .Write = SampleUartHostWrite, + .SetBaud = SampleUartHostSetBaud, + .GetBaud = SampleUartHostGetBaud, + .SetAttribute = NULL, + .GetAttribute = NULL, + .SetTransMode = NULL, + }; + ``` + + 在device/hisilicon/drivers/lite.mk编译脚本中增加示例UART驱动模块,代码如下: + + ``` + LITEOS_BASELIB += -lhdf_uart_sample + LIB_SUBDIRS += $(LITEOS_SOURCE_ROOT)/vendor/huawei/hdf/sample/platform/uart + ``` + +4. 用户程序和驱动交互代码。 + + UART驱动成功初始化后,会创建/dev/uartdev-5设备节点,通过设备节点与UART驱动交互的代码如下: + + ``` + #include + #include + #include + #include "hdf_log.h" + + #define HDF_LOG_TAG "hello_uart" + #define INFO_SIZE 16 + + int main(void) + { + int ret; + int fd; + const char info[INFO_SIZE] = {" HELLO UART! "}; + + fd = open("/dev/uartdev-5", O_RDWR); + if (fd < 0) { + HDF_LOGE("hello_uart uartdev-5 open failed %d", fd); + return -1; + } + ret = write(fd, info, INFO_SIZE); + if (ret != 0) { + HDF_LOGE("hello_uart write uartdev-5 ret is %d", ret); + } + ret = close(fd); + if (ret != 0) { + HDF_LOGE("hello_uart uartdev-5 close failed %d", fd); + return -1; + } + return ret; + } + ``` + + 在build/lite/components/drivers.json驱动配置中hdf\_hi3516dv300\_liteos\_a组件下的targets中增加hello\_uart\_sample组件,代码如下: + + ``` + { + "components": [ + { + "component": "hdf_hi3516dv300_liteos_a", + ... + "targets": [ + "//vendor/huawei/hdf/sample/platform/uart:hello_uart_sample" + ] + } + ] + } + ``` + + >![](../public_sys-resources/icon-note.gif) **说明:** + >如上代码均为示例代码,完整代码可以在vendor/huawei/hdf/sample查看。 + >示例代码默认不参与编译,需要手动添加到编译脚本中。 + + +## 编译和烧写 + +参考《运行Hello OHOS》进行编译和烧写:[编译](quickstart-lite-steps-board3516-running.md#section1077671315253)、[烧录](quickstart-lite-steps-board3516-running.md#section1347011412201) + +## 镜像运行 + +1. 连接串口。 + + >![](../public_sys-resources/icon-notice.gif) **须知:** + >若无法连接串口,请参考[常见问题](quickstart-lite-steps-board3516-faqs.md)进行排查。 + + **图 1** 连接串口图 + + + ![](figure/chuankou1.png) + + 1. 单击**Monitor**打开串口。 + 2. 连续输入回车直到串口显示"hisilicon"。 + 3. 单板初次启动或修改启动参数,请进入[步骤2](quickstart-lite-steps-board3516-running.md#l5b42e79a33ea4d35982b78a22913b0b1),否则进入[步骤3](quickstart-lite-steps-board3516-running.md#ld26f18828aa44c36bfa36be150e60e49)。 + +2. (单板初次启动必选)修改U-boot的bootcmd及bootargs内容:该步骤为固化操作,若不修改参数只需执行一次。每次复位单板均会自动进入系统。 + + >![](../public_sys-resources/icon-notice.gif) **须知:** + >U-boot引导程序默认会有2秒的等待时间,用户可使用回车打断等待并显示"hisilicon",通过**reset**命令可再次启动系统。 + + **表 1** U-boot修改命令 + + + + + + + + + + + + + + + + + + + +

    执行命令

    +

    命令解释

    +

    setenv bootcmd "mmc read 0x0 0x80000000 0x800 0x4800; go 0x80000000";

    +

    读取FLASH起始地址为0x800(单位为512B,即1MB),大小为0x4800(单位为512B,即9MB)的内容到0x80000000的内存地址,该大小(9MB)与IDE中所填写OHOS_Image.bin文件大小必须相同

    +

    setenv bootargs "console=ttyAMA0,115200n8 root=emmc fstype=vfat rootaddr=10M rootsize=20M rw";

    +

    表示设置启动参数,输出模式为串口输出,波特率为115200,数据位8,rootfs挂载于emmc器件,文件系统类型为vfat,

    +

    “rootaddr=10M rootsize=20M rw”处对应填入rootfs.img的烧写起始位置与长度,此处与IDE中新增rootfs.img文件时所填大小必须相同

    +

    saveenv

    +

    表示保存当前配置。

    +

    reset

    +

    表示复位单板。

    +
    + + >![](../public_sys-resources/icon-notice.gif) **须知:** + >**“go 0x80000000”**为可选指令,默认配置已将该指令固化在启动参数中,单板复位后可自动启动。若想切换为手动启动,可在U-boot启动倒数阶段使用"回车"打断自动启动。 + +3. 输入**“reset”**指令并回车,重启单板,启动成功如下图,输入回车串口显示OHOS字样。 + + **图 2** 系统启动图 + + + ![](figure/qi1.png) + +4. 根目录下,在命令行输入指令“**./bin/hello\_uart**”执行写入的demo程序,显示成功结果如下所示。 + + ``` + OHOS # ./bin/hello_uart + OHOS # HELLO UART! + ``` + + +## 下一步学习 + +恭喜,您已完成Hi3516 快速上手!建议您下一步进入[带屏摄像头产品开发](../guide/device-camera.md)的学习 。 + diff --git a/zh-cn/device-dev/quick-start/quickstart-lite-steps-board3516-running.md b/zh-cn/device-dev/quick-start/quickstart-lite-steps-board3516-running.md new file mode 100644 index 0000000000..336d979c20 --- /dev/null +++ b/zh-cn/device-dev/quick-start/quickstart-lite-steps-board3516-running.md @@ -0,0 +1,269 @@ +# 运行Hello OHOS + +- [新建应用程序](#section204672145202) +- [编译](#section1077671315253) +- [烧录](#section1347011412201) +- [镜像运行](#section24721014162010) +- [执行应用程序](#section5276734182615) + +本节指导开发者在单板上运行第一个应用程序,其中包括新建应用程序、编译、烧写、运行等步骤,最终输出“Hello OHOS!”。 + +## 新建应用程序 + +1. 新建目录及源码 + + 新建**applications/sample/camera/apps/src/helloworld.c**目录及文件,代码如下所示,用户可以自定义修改打印内容(例如:修改OHOS为World)。当前应用程序可支持标准C及C++的代码开发。 + + ``` + #include + + int main(int argc, char **argv) + { + printf("\n************************************************\n"); + printf("\n\t\tHello OHOS!\n"); + printf("\n************************************************\n\n"); + + return 0; + } + ``` + +2. 新建编译组织文件 + + 新建**applications/sample/camera/apps/BUILD.gn**文件,内容如下所示: + + ``` + import("//build/lite/config/component/lite_component.gni") + lite_component("hello-OHOS") { + features = [ ":helloworld" ] + } + executable("helloworld") { + output_name = "helloworld" + sources = [ "src/helloworld.c" ] + include_dirs = [] + defines = [] + cflags_c = [] + ldflags = [] + } + ``` + +3. 添加新组件 + + 修改文件**build/lite/components/applications.json**,添加组件hello\_world\_app的配置,如下所示为applications.json文件片段,"\#\#start\#\#"和"\#\#end\#\#"之间为新增配置("\#\#start\#\#"和"\#\#end\#\#"仅用来标识位置,添加完配置后删除这两行): + + ``` + { + "components": [ + { + "component": "camera_sample_communication", + "description": "Communication related samples.", + "optional": "true", + "dirs": [ + "applications/sample/camera/communication" + ], + "targets": [ + "//applications/sample/camera/communication:sample" + ], + "rom": "", + "ram": "", + "output": [], + "adapted_kernel": [ "liteos_a" ], + "features": [], + "deps": { + "components": [], + "third_party": [] + } + }, + ##start## + { + "component": "hello_world_app", + "description": "Communication related samples.", + "optional": "true", + "dirs": [ + "applications/sample/camera/apps" + ], + "targets": [ + "//applications/sample/camera/apps:hello-OHOS" + ], + "rom": "", + "ram": "", + "output": [], + "adapted_kernel": [ "liteos_a" ], + "features": [], + "deps": { + "components": [], + "third_party": [] + } + }, + ##end## + { + "component": "camera_sample_app", + "description": "Camera related samples.", + "optional": "true", + "dirs": [ + "applications/sample/camera/launcher", + "applications/sample/camera/cameraApp", + "applications/sample/camera/setting", + "applications/sample/camera/gallery", + "applications/sample/camera/media" + ], + ``` + +4. 修改单板配置文件 + + 修改文件**vendor/hisilicon/hispark\_taurus/config.json**,新增hello\_world\_app组件的条目,如下所示代码片段为applications子系统配置,"\#\#start\#\#"和"\#\#end\#\#"之间为新增条目("\#\#start\#\#"和"\#\#end\#\#"仅用来标识位置,添加完配置后删除这两行): + + ``` + { + "subsystem": "applications", + "components": [ + { "component": "camera_sample_app", "features":[] }, + { "component": "camera_sample_ai", "features":[] }, + ##start## + { "component": "hello_world_app", "features":[] }, + ##end## + { "component": "camera_screensaver_app", "features":[] } + ] + }, + ``` + + +## 编译 + +如果Linux编译环境通过Docker方式安装,具体编译过程请参见[Docker方式获取编译环境](../get-code/gettools-acquire.md)的编译操作。如果Linux编译环境通过软件包方式安装,请进入源码根目录,执行如下命令进行编译: + +``` +hb set(设置编译路径) +.(选择当前路径) +选择ipcamera_hispark_taurus@hisilicon并回车 +hb build -f(执行编译) +``` + +**图 1** 设置图例 +![](figure/设置图例.png "设置图例") + +结果文件生成在out/hispark\_taurus/ipcamera\_hispark\_taurus目录下。 + +>![](../public_sys-resources/icon-notice.gif) **须知:** +>Hi3516DV300单板的U-boot文件获取路径:device/hisilicon/hispark\_taurus/sdk\_liteos/uboot/out/boot/u-boot-hi3516dv300.bin + +## 烧录 + +Hi3516开发板的代码烧录支持USB烧录、网口烧录和串口烧录三种方式。此处仅以网口烧录为例进行说明。 + +1. 请连接好电脑和待烧录开发板,以Hi3516DV300为例,需要同时连接串口、网口和电源,具体可参考[Hi3516开发板介绍](quickstart-lite-introduction-hi3516.md)。 +2. 打开电脑的设备管理器,查看并记录对应的串口号。 + + >![](../public_sys-resources/icon-note.gif) **说明:** + >如果对应的串口异常,请根据[Hi3516/Hi3518系列开发板串口驱动安装指导](https://device.harmonyos.com/cn/docs/ide/user-guides/hi3516_hi3518-drivers-0000001050743695)安装USB转串口的驱动程序。 + + ![](figure/zh-cn_image_0000001174350647.png) + +3. 打开DevEco Device Tool,在Projects中,点击**Settings**打开工程配置界面。 + + ![](figure/2021-01-27_170334.png) + +4. 在“Partition Configuration”页签,设置待烧录文件信息,默认情况下,DevEco Device Tool已针对Hi3516系列开发板进行适配,无需单独修改。 +5. 在“hi3516dv300”页签,设置烧录选项,包括upload\_port、upload\_partitions和upload\_protocol。 + + - upload\_port:选择步骤[2](#zh-cn_topic_0000001056443961_li142386399535)中查询的串口号。 + - upload\_protocol:选择烧录协议,固定选择“hiburn-net”。 + - upload\_partitions:选择待烧录的文件,默认情况下会同时烧录fastboot、kernel、rootfs和userfs。 + + ![](figure/zh-cn_image_0000001128470904.png) + +6. 检查和设置连接开发板后的网络适配器的IP地址信息,设置方法请参考[设置Hi3516网口烧录的IP地址信息](https://device.harmonyos.com/cn/docs/ide/user-guides/set_ipaddress-0000001141825075)。 +7. 设置网口烧录的IP地址信息,设置如下选项: + + - upload\_net\_server\_ip:选择[6](#zh-cn_topic_0000001056443961_li1558813168234)中设置的IP地址信息。例如192.168.1.2 + - upload\_net\_client\_mask:设置开发板的子网掩码,工具会自动根据选择的upload\_net\_server\_ip进行设置。例如255.255.255.0 + - upload\_net\_client\_gw:设置开发板的网关,工具会自动根据选择的upload\_net\_server\_ip进行设置。例如192.168.1.1 + - upload\_net\_client\_ip:设置开发板的IP地址,工具会自动根据选择的upload\_net\_server\_ip进行设置。例如192.168.1.3 + + ![](figure/zh-cn_image_0000001174270733.png) + +8. 所有的配置都修改完成后,在工程配置页签的顶部,点击**Save**进行保存。 +9. 打开工程文件,点击![](figure/2021-01-27_170334-2.png)图标,打开DevEco Device Tool界面,在“PROJECT TASKS”中,点击hi3516dv300下的**Upload**按钮,启动烧录。 + + ![](figure/zh-cn_image_0000001174270729.png) + +10. 启动烧录后,显示如下提示信息时,请重启开发板(下电再上电)。 + + ![](figure/zh-cn_image_0000001128470906.png) + +11. 重新上电后,启动烧录,界面提示如下信息时,表示烧录成功。 + + ![](figure/zh-cn_image_0000001128311098.png) + + +## 镜像运行 + +1. 连接串口。 + + >![](../public_sys-resources/icon-notice.gif) **须知:** + >若无法连接串口,请参考[常见问题](quickstart-lite-steps-board3516-faqs.md)进行排查。 + + **图 2** 连接串口图 + + + ![](figure/chuankou1.png) + + 1. 单击**Monitor**打开串口。 + 2. 连续输入回车直到串口显示"hisilicon"。 + 3. 单板初次启动或修改启动参数,请进入[步骤2](#l5b42e79a33ea4d35982b78a22913b0b1),否则进入[步骤3](#ld26f18828aa44c36bfa36be150e60e49)。 + +2. (单板初次启动必选)修改U-boot的bootcmd及bootargs内容:该步骤为固化操作,若不修改参数只需执行一次。每次复位单板均会自动进入系统。 + + >![](../public_sys-resources/icon-notice.gif) **须知:** + >U-boot引导程序默认会有2秒的等待时间,用户可使用回车打断等待并显示"hisilicon",通过**reset**命令可再次启动系统。 + + **表 1** U-boot修改命令 + + + + + + + + + + + + + + + + + + + +

    执行命令

    +

    命令解释

    +

    setenv bootcmd "mmc read 0x0 0x80000000 0x800 0x4800; go 0x80000000";

    +

    读取FLASH起始地址为0x800(单位为512B,即1MB),大小为0x4800(单位为512B,即9MB)的内容到0x80000000的内存地址,该大小(9MB)与IDE中所填写OHOS_Image.bin文件大小必须相同

    +

    setenv bootargs "console=ttyAMA0,115200n8 root=emmc fstype=vfat rootaddr=10M rootsize=20M rw";

    +

    表示设置启动参数,输出模式为串口输出,波特率为115200,数据位8,rootfs挂载于emmc器件,文件系统类型为vfat,

    +

    “rootaddr=10M rootsize=20M rw”处对应填入rootfs.img的烧写起始位置与长度,此处与IDE中新增rootfs.img文件时所填大小必须相同

    +

    saveenv

    +

    表示保存当前配置。

    +

    reset

    +

    表示复位单板。

    +
    + + >![](../public_sys-resources/icon-notice.gif) **须知:** + >**“go 0x80000000”**为可选指令,默认配置已将该指令固化在启动参数中,单板复位后可自动启动。若想切换为手动启动,可在U-boot启动倒数阶段使用"回车"打断自动启动。 + +3. 输入**“reset”**指令并回车,重启单板,启动成功如下图,输入回车串口显示OHOS字样。 + + **图 3** 系统启动图 + + + ![](figure/qi1.png) + + +## 执行应用程序 + +根目录下,在命令行输入指令“**./bin/helloworld**”执行写入的demo程序,显示成功结果如下图所示。 + +**图 4** 启动并成功执行应用程序图 +![](figure/启动并成功执行应用程序图.png "启动并成功执行应用程序图") + diff --git a/zh-cn/device-dev/quick-start/quickstart-lite-steps-board3516-setting.md b/zh-cn/device-dev/quick-start/quickstart-lite-steps-board3516-setting.md new file mode 100644 index 0000000000..1b5e88ef8f --- /dev/null +++ b/zh-cn/device-dev/quick-start/quickstart-lite-steps-board3516-setting.md @@ -0,0 +1,122 @@ +# 安装开发板环境 + +- [Hi3516工具要求](#section179175261196) + - [硬件要求](#section5840424125014) + - [软件要求](#section965634210501) + +- [安装Linux服务器工具](#section182916865219) + - [将Linux shell改为bash](#section1715027152617) + - [安装编译依赖基础软件(仅Ubuntu 20+需要)](#section45512412251) + - [安装文件打包工具及Java虚拟机环境](#section16199102083717) + + +## Hi3516工具要求 + +### 硬件要求 + +- Hi3516DV300 IoT Camera开发板 +- USB转串口线、网线(Windows工作台通过USB转串口线、网线与Hi3516DV300 开发板连接) + +各硬件连接关系如下图所示。 + +**图 1** 硬件连线图 + + +![](figure/矩形备份-292.png) + +### 软件要求 + +>![](../public_sys-resources/icon-notice.gif) **须知:** +>本节描述安装包方式搭建编译环境的操作步骤。如果是Docker方式安装编译环境,请跳过此章节以及下述[安装Linux服务器工具](#section182916865219)章节。 + +Hi3516开发板对Linux服务器通用环境配置需要的工具及其获取途径如下表所示。 + +**表 1** Linux服务器开发工具及获取途径 + + + + + + + + + + + + + + + + + + + + + + + + +

    开发工具

    +

    用途

    +

    获取途径

    +

    bash

    +

    命令行处理工具

    +

    系统配置

    +

    编译基础软件包(仅ubuntu 20+需要)

    +

    编译依赖的基础软件包

    +

    通过互联网获取

    +

    dosfstools、mtools、mtd-utils

    +

    文件打包工具

    +

    通过apt-get install安装

    +

    Java 虚拟机环境

    +

    编译、调试和运行Java程序

    +

    通过apt-get install安装

    +
    + +## 安装Linux服务器工具 + +>![](../public_sys-resources/icon-notice.gif) **须知:** +>- 如果通过“HPM组件方式”或“HPM包管理器命令行工具方式”获取源码,不需要安装LLVM、hc-gen编译工具。 +>- (推荐)如果通过“镜像站点方式”或“代码仓库方式”获取源码,需要安装hc-gen编译工具。安装hc-gen编译工具时,请确保编译工具的环境变量路径唯一。 + +### 将Linux shell改为bash + +查看shell是否为bash,在终端运行如下命令 + +``` +ls -l /bin/sh +``` + +如果显示为“/bin/sh -\> bash”则为正常,否则请按以下方式修改: + +**方法一**:在终端运行如下命令,然后选择 no。 + +``` +sudo dpkg-reconfigure dash +``` + +**方法二**:先删除sh,再创建软链接。 + +``` +sudo rm -rf /bin/sh +sudo ln -s /bin/bash /bin/sh +``` + +### 安装编译依赖基础软件(仅Ubuntu 20+需要) + +执行以下命令进行安装: + +``` +sudo apt-get install build-essential gcc g++ make zlib* libffi-dev +``` + +### 安装文件打包工具及Java虚拟机环境 + +1. 打开Linux编译服务器终端 +2. 运行如下命令,安装dosfstools,mtools,mtd-utils,Java运行时环境(JRE)和Java sdk 开发工具包。 + + ``` + sudo apt-get install dosfstools mtools mtd-utils default-jre default-jdk + ``` + + diff --git a/zh-cn/device-dev/quick-start/quickstart-lite-steps-board3516.md b/zh-cn/device-dev/quick-start/quickstart-lite-steps-board3516.md new file mode 100644 index 0000000000..3972550797 --- /dev/null +++ b/zh-cn/device-dev/quick-start/quickstart-lite-steps-board3516.md @@ -0,0 +1,11 @@ +# Hi3516开发板 + +- **[安装开发板环境](quickstart-lite-steps-board3516-setting.md)** + +- **[运行Hello OHOS](quickstart-lite-steps-board3516-running.md)** + +- **[驱动开发示例](quickstart-lite-steps-board3516-program.md)** + +- **[常见问题](quickstart-lite-steps-board3516-faqs.md)** + + diff --git a/zh-cn/device-dev/quick-start/quickstart-lite-steps-board3518-faqs.md b/zh-cn/device-dev/quick-start/quickstart-lite-steps-board3518-faqs.md new file mode 100644 index 0000000000..dc71a35fb6 --- /dev/null +++ b/zh-cn/device-dev/quick-start/quickstart-lite-steps-board3518-faqs.md @@ -0,0 +1,174 @@ +# 常见问题 + +- [烧写选择串口后提示失败](#section1498892119619) +- [Windows电脑与单板网络连接失败](#section8512971816) +- [烧写失败](#section1767804111198) +- [编译构建过程中,提示找不到“python”](#zh-cn_topic_0000001053466255_section1039835245619) +- [串口无回显](#zh-cn_topic_0000001053466255_section14871149155911) + +## 烧写选择串口后提示失败 + +- **现象描述** + + 点击烧写并选择串口后,出现Error: Opening COMxx: Access denied。 + + **图 1** 打开串口失败图 + ![](figure/打开串口失败图-7.png "打开串口失败图-7") + +- **可能原因** + + 串口已经被占用。 + +- **解决办法** + +1. 按图依次选择下拉框,查找带有serial-xx的终端 + + **图 2** 查找是否存在占用串口的终端 + ![](figure/查找是否存在占用串口的终端-8.png "查找是否存在占用串口的终端-8") + +2. 点击标号中的垃圾桶图标,关闭串口。 + + **图 3** 关闭串口终端 + ![](figure/关闭串口终端-9.png "关闭串口终端-9") + +3. 重新点击烧写,选择串口并开始烧写程序 + + **图 4** 重新启动烧写任务 + + + ![](figure/changjian1-10.png) + + +## Windows电脑与单板网络连接失败 + +- **现象描述** + + 点击烧写并选择串口后,无法获取文件。 + + **图 5** 网络不通,单板无法获取文件图 + ![](figure/网络不通-单板无法获取文件图-11.png "网络不通-单板无法获取文件图-11") + +- **可能原因** + + 单板网络与Windows电脑不联通。 + + Windows电脑防火墙未允许Visual Studio Code联网。 + +- **解决方法** + +1. 检查网线是否连接。 +2. 点击Windows防火墙。 + + **图 6** 网络防火墙设置图 + ![](figure/网络防火墙设置图-12.png "网络防火墙设置图-12") + +3. 点击“允许应用通过防火墙”。 + + **图 7** 防火墙和网络保护界面图 + ![](figure/防火墙和网络保护界面图-13.png "防火墙和网络保护界面图-13") + +4. 查找Visual Studio Code应用。 + + **图 8** 查找Visual Studio Code应用图 + ![](figure/查找Visual-Studio-Code应用图-14.png "查找Visual-Studio-Code应用图-14") + +5. 勾选Visual Studio Code的专用和公用网络的访问权限。 + + **图 9** 允许Visual Studio Code应用访问网络 + ![](figure/允许Visual-Studio-Code应用访问网络-15.png "允许Visual-Studio-Code应用访问网络-15") + + +## 烧写失败 + +- **现象描述** + + 点击烧写并选择串口后,出现无法烧写的情况。 + +- **可能原因** + + 安装IDE插件DevEco后未重启。 + +- **解决方法** + + 重启IDE。 + + +## 编译构建过程中,提示找不到“python” + +- **现象描述** + + ![](figure/zh-cn_image_0000001174270743.png) + + +- **可能原因1** + + 没有装python。 + +- **解决办法** + + 请按照[安装python](quickstart-lite-env-setup-lin.md)。 + +- **可能原因2** + + ![](figure/zh-cn_image_0000001174270739.png) + +- **解决办法** + + usr/bin目录下没有python软链接,请运行以下命令: + + ``` + # cd /usr/bin/ + # which python3 + # ln -s /usr/local/bin/python3 python + # python --version + ``` + + 例: + + ![](figure/zh-cn_image_0000001174350661.png) + + +## 串口无回显 + +- **现象描述** + + 串口显示已连接,重启单板后,回车无任何回显。 + +- **可能原因1** + + 串口连接错误。 + +- **解决办法** + + 修改串口号。 + + 请查看设备管理器,确认连接单板的串口与终端中连接串口是否一致,若不一致,请按镜像运行内[步骤1](quickstart-lite-steps-board3518-running.md)修改串口号。 + + +- **可能原因2** + + 单板U-boot被损坏。 + +- **解决办法** + + 烧写U-boot。 + + 若上述步骤依旧无法连接串口,可能由于单板U-boot损坏,按下述步骤烧写U-boot。 + + +1. 获取引导文件U-boot。 + + >![](../public_sys-resources/icon-notice.gif) **须知:** + >单板的U-boot文件请在开源包中获取: + >Hi3516DV300:device\\hisilicon\\hispark\_taurus\\sdk\_liteos\\uboot\\out\\boot\\u-boot-hi3516dv300.bin + >Hi3518EV300:device\\hisilicon\\hispark\_aries\\sdk\_liteos\\uboot\\out\\boot\\u-boot-hi3518ev300.bin + +2. 根据USB烧写步骤烧写U-boot文件。 + + 按照[Hi3516系列USB烧写步骤](https://device.harmonyos.com/cn/docs/ide/user-guides/hi3516_upload-0000001052148681)/[Hi3518系列USB烧写步骤](https://device.harmonyos.com/cn/docs/ide/user-guides/hi3518_upload-0000001057313128)中描述的USB烧写方法,选择对应单板的U-boot文件进行烧写。 + +3. 烧写完成后,登录串口如下图所示。 + + ![](figure/zh-cn_image_0000001174350659.png) + + diff --git a/zh-cn/device-dev/quick-start/quickstart-lite-steps-board3518-running.md b/zh-cn/device-dev/quick-start/quickstart-lite-steps-board3518-running.md new file mode 100644 index 0000000000..2b5a833cfc --- /dev/null +++ b/zh-cn/device-dev/quick-start/quickstart-lite-steps-board3518-running.md @@ -0,0 +1,262 @@ +# 运行Hello OHOS + +- [新建应用程序](#section1550972416485) +- [编译](#section234175193114) +- [烧录](#section7609155824819) +- [镜像运行](#section17612105814480) +- [下一步学习](#section9712145420182) + +本节指导开发者在单板上运行第一个应用程序,其中包括新建应用程序、编译、烧写、运行等步骤,最终输出“Hello OHOS!”。 + +## 新建应用程序 + +1. 新建目录及源码 + + 新建**applications/sample/camera/apps/src/helloworld.c**目录及文件,代码如下所示,用户可以自定义修改打印内容(例如:修改OHOS为World)。当前应用程序可支持标准C及C++的代码开发。 + + ``` + #include + + int main(int argc, char **argv) + { + printf("\n************************************************\n"); + printf("\n\t\tHello OHOS!\n"); + printf("\n************************************************\n\n"); + + return 0; + } + ``` + +2. 新建编译组织文件 + + 新建**applications/sample/camera/apps/BUILD.gn**文件,内容如下所示: + + ``` + import("//build/lite/config/component/lite_component.gni") + lite_component("hello-OHOS") { + features = [ ":helloworld" ] + } + executable("helloworld") { + output_name = "helloworld" + sources = [ "src/helloworld.c" ] + include_dirs = [] + defines = [] + cflags_c = [] + ldflags = [] + } + ``` + +3. 添加新组件 + + 修改文件**build/lite/components/applications.json**,添加组件hello\_world\_app的配置,如下所示为applications.json文件片段,"\#\#start\#\#"和"\#\#end\#\#"之间为新增配置("\#\#start\#\#"和"\#\#end\#\#"仅用来标识位置,添加完配置后删除这两行): + + ``` + { + "components": [ + { + "component": "camera_sample_communication", + "description": "Communication related samples.", + "optional": "true", + "dirs": [ + "applications/sample/camera/communication" + ], + "targets": [ + "//applications/sample/camera/communication:sample" + ], + "rom": "", + "ram": "", + "output": [], + "adapted_kernel": [ "liteos_a" ], + "features": [], + "deps": { + "components": [], + "third_party": [] + } + }, + ##start## + { + "component": "hello_world_app", + "description": "Communication related samples.", + "optional": "true", + "dirs": [ + "applications/sample/camera/apps" + ], + "targets": [ + "//applications/sample/camera/apps:hello-OHOS" + ], + "rom": "", + "ram": "", + "output": [], + "adapted_kernel": [ "liteos_a" ], + "features": [], + "deps": { + "components": [], + "third_party": [] + } + }, + ##end## + { + "component": "camera_sample_app", + "description": "Camera related samples.", + "optional": "true", + "dirs": [ + "applications/sample/camera/launcher", + "applications/sample/camera/cameraApp", + "applications/sample/camera/setting", + "applications/sample/camera/gallery", + "applications/sample/camera/media" + ], + ``` + +4. 修改单板配置文件 + + 修改文件**vendor/hisilicon/hispark\_aries/config.json**,新增hello\_world\_app组件的条目,如下所示代码片段为applications子系统配置,"\#\#start\#\#"和"\#\#end\#\#"之间为新增条目("\#\#start\#\#"和"\#\#end\#\#"仅用来标识位置,添加完配置后删除这两行): + + ``` + { + "subsystem": "applications", + "components": [ + ##start## + { "component": "hello_world_app", "features":[] }, + ##end## + { "component": "camera_sample_app", "features":[] } + + ] + }, + ``` + + +## 编译 + +如果Linux编译环境通过Docker方式安装,具体编译过程请参见[Docker方式获取编译环境](../get-code/gettools-acquire.md)的编译操作。如果Linux编译环境通过软件包方式安装,进入源码根目录,执行如下命令进行编译: + +``` +hb set(设置编译路径) +.(选择当前路径) +选择ipcamera_hispark_aries@hisilicon并回车 +hb build -f(执行编译) +``` + +结果文件生成在out/hispark\_aries/ipcamera\_hispark\_aries目录下。 + +**图 1** 设置图例 +![](figure/设置图例-4.png "设置图例-4") + +>![](../public_sys-resources/icon-notice.gif) **须知:** +>Hi3518EV300单板的U-boot文件获取路径:device/hisilicon/hispark\_aries/sdk\_liteos/uboot/out/boot/u-boot-hi3518ev300.bin + +## 烧录 + +Hi3518开发板的代码烧录仅支持USB烧录方式。 + +1. 请连接好电脑和待烧录开发板,以Hi3518EV300为例,需要同时连接串口和USB口,具体可参考[Hi3518开发板介绍](quickstart-lite-introduction-hi3518.md)。 +2. 打开电脑的设备管理器,查看并记录对应的串口号。 + + >![](../public_sys-resources/icon-note.gif) **说明:** + >如果对应的串口异常,请根据[Hi3516/Hi3518系列开发板串口驱动安装指导](https://device.harmonyos.com/cn/docs/ide/user-guides/hi3516_hi3518-drivers-0000001050743695)安装USB转串口的驱动程序。 + + ![](figure/zh-cn_image_0000001128470900.png) + +3. 打开DevEco Device Tool,在Projects中,点击**Settings**打开工程配置界面。 + + ![](figure/zh-cn_image_0000001174350649.png) + +4. 在“Partition Configuration”页签,设置待烧录文件信息,默认情况下,DevEco Device Tool已针对Hi3518系列开发板进行适配,无需单独修改。 +5. 在“hi3518ev300”页签,设置烧录选项,包括upload\_port、upload\_partitions和upload\_protocol。 + + - upload\_port:选择步骤[2](#zh-cn_topic_0000001057313128_li46411811196)中查询的串口号。 + - upload\_protocol:选择烧录协议,固定选择“hiburn-usb”。 + - upload\_partitions:选择待烧录的文件,默认情况下会同时烧录fastboot、kernel、rootfs和userfs。 + + ![](figure/zh-cn_image_0000001128311090.png) + +6. 所有的配置都修改完成后,在工程配置页签的顶部,点击**Save**进行保存。 +7. 打开工程文件,点击![](figure/2021-01-27_170334-5.png)图标,打开DevEco Device Tool界面,在“PROJECT TASKS”中,点击hi3518ev300\_fastboot下的**Erase**按钮,擦除U-Boot。 + + ![](figure/zh-cn_image_0000001174270731.png) + +8. 执行**Erase**擦除操作后,显示如下提示信息时,请重启开发板(下电再上电)。 + + ![](figure/zh-cn_image_0000001128311092.png) + +9. 重新上电后,显示如下信息时,表示擦除U-Boot成功。 + + ![](figure/zh-cn_image_0000001128311094.png) + +10. 擦除完成后,点击hi3518ev300下的**Upload**按钮,启动烧录。 + + ![](figure/zh-cn_image_0000001174350641.png) + +11. 启动烧录后,界面提示如下信息时,表示烧录成功。 + + ![](figure/zh-cn_image_0000001174350643.png) + + +## 镜像运行 + +1. 连接串口。 + + >![](../public_sys-resources/icon-notice.gif) **须知:** + >若无法连接串口,请参考[常见问题](quickstart-lite-steps-board3518-faqs.md)进行排查。 + + **图 2** 连接串口图 + + + ![](figure/chuankou1-6.png) + + 1. 单击**Monitor**打开串口。 + 2. 连续输入回车直到串口显示"hisilicon"。 + 3. 单板初次启动或修改启动参数,请进入[步骤2](#li9441185382314),否则进入[步骤3](#li6442853122312)。 + +2. (初次烧写必选)修改U-boot的bootcmd及bootargs内容:该步骤为固化操作,可保存执行结果,但U-boot重新烧入,则需要再次执行下述步骤。 + + **表 1** U-boot修改命令 + + + + + + + + + + + + + + + + + + + + + + +

    执行命令

    +

    命令解释

    +

    setenv bootcmd "sf probe 0;sf read 0x40000000 0x100000 0x600000;go 0x40000000";

    +

    设置bootcmd内容,选择FLASH器件0,读取FLASH起始地址为0x100000,大小为0x600000字节的内容到0x40000000的内存地址,此处0x600000为6MB,与IDE中填写OHOS_Image.bin的文件大小必须相同

    +

    setenv bootargs "console=ttyAMA0,115200n8 root=flash fstype=jffs2 rw rootaddr=7M rootsize=8M";

    +

    表示设置bootargs参数为串口输出,波特率为115200,数据位8,rootfs挂载于FLASH上,文件系统类型为jffs2 rw,以支持可读写JFFS2文件系统。“rootaddr=7M rootsize=8M”处对应填入实际rootfs.img的烧写起始位置与长度,与IDE内所填大小必须相同

    +

    saveenv

    +

    表示保存当前配置。

    +

    reset

    +

    表示复位单板。

    +

    pri

    +

    表示查看显示参数。

    +
    + + >![](../public_sys-resources/icon-notice.gif) **须知:** + >**“go 0x40000000”**为可选指令,默认配置已将该指令固化在启动参数中,单板复位后可自动启动。若想切换为手动启动,可在U-boot启动倒数阶段使用"回车"打断自动启动。 + +3. 若启动时显示**"hisilicon \#**字样,请输入**“reset”**指令,等待系统自启动进入系统,系统启动后,显示**“OHOS”**字样,输入**”./bin/helloworld”**并回车,显示成功结果如下图所示。 + + **图 3** 启动成功并执行应用程序图 + ![](figure/启动成功并执行应用程序图.png "启动成功并执行应用程序图") + + +## 下一步学习 + +恭喜您,已完成Hi3518的快速上手!建议您下一步进入[无屏摄像头产品开发](../guide/device-iotcamera.md)的学习 。 + diff --git a/zh-cn/device-dev/quick-start/quickstart-lite-steps-board3518-setting.md b/zh-cn/device-dev/quick-start/quickstart-lite-steps-board3518-setting.md new file mode 100644 index 0000000000..b4a3556e11 --- /dev/null +++ b/zh-cn/device-dev/quick-start/quickstart-lite-steps-board3518-setting.md @@ -0,0 +1,114 @@ +# 安装开发板环境 + +- [Hi3518环境搭建](#section1724111409282) + - [硬件要求](#section487353718276) + - [软件要求](#section17315193935817) + +- [安装Linux服务器工具](#section8831868501) + - [将Linux shell改为bash](#section434110241084) + - [安装编译依赖基础软件(仅Ubuntu 20+需要)](#section25911132141020) + - [安装文件打包工具](#section390214473129) + + +## Hi3518环境搭建 + +### 硬件要求 + +- Hi3518EV300 IoT Camera开发板 +- USB转串口线、网线(Windows工作台通过USB转串口线、网线与开发板连接) + + 各硬件连接关系如下图所示。 + + +**图 1** 硬件连线图 +![](figure/硬件连线图-3.png "硬件连线图-3") + +### 软件要求 + +>![](../public_sys-resources/icon-notice.gif) **须知:** +>本节描述安装包方式搭建编译环境的操作步骤。如果是Docker方式安装编译环境,请跳过此章节以及下述[安装Linux服务器工具](#section8831868501)章节。 + +Hi3518开发板对Linux服务器通用环境配置需要的工具及其获取途径如下表所示。 + +**表 1** Linux服务器开发工具及获取途径 + + + + + + + + + + + + + + + + + + + + +

    开发工具

    +

    用途

    +

    获取途径

    +

    bash

    +

    命令行处理工具

    +

    系统配置

    +

    编译基础软件包(仅ubuntu 20+需要)

    +

    编译依赖的基础软件包

    +

    通过互联网获取

    +

    dosfstools、mtools、mtd-utils

    +

    文件打包工具

    +

    通过apt-get install安装

    +
    + +## 安装Linux服务器工具 + +>![](../public_sys-resources/icon-notice.gif) **须知:** +>- 如果通过“HPM组件方式”或“HPM包管理器命令行工具方式”获取源码,不需要安装hc-gen编译工具。 +>- (推荐)如果通过“镜像站点方式”或“代码仓库方式”获取源码,需要安装hc-gen编译工具。安装hc-gen编译工具时,请确保编译工具的环境变量路径唯一。 + +### 将Linux shell改为bash + +查看shell是否为bash,在终端运行如下命令 + +``` +ls -l /bin/sh +``` + +如果显示为“/bin/sh -\> bash”则为正常,否则请按以下方式修改: + +**方法一**:在终端运行如下命令,然后选择 no。 + +``` +sudo dpkg-reconfigure dash +``` + +**方法二**:先删除sh,再创建软链接。 + +``` +sudo rm -rf /bin/sh +sudo ln -s /bin/bash /bin/sh +``` + +### 安装编译依赖基础软件(仅Ubuntu 20+需要) + +执行以下命令进行安装: + +``` +sudo apt-get install build-essential gcc g++ make zlib* libffi-dev +``` + +### 安装文件打包工具 + +1. 打开Linux编译服务器终端。 +2. 运行如下命令,安装dosfstools,mtools,mtd-utils。 + + ``` + sudo apt-get install dosfstools mtools mtd-utils + ``` + + diff --git a/zh-cn/device-dev/quick-start/quickstart-lite-steps-board3518.md b/zh-cn/device-dev/quick-start/quickstart-lite-steps-board3518.md new file mode 100644 index 0000000000..d0f3f9a587 --- /dev/null +++ b/zh-cn/device-dev/quick-start/quickstart-lite-steps-board3518.md @@ -0,0 +1,9 @@ +# Hi3518开发板 + +- **[安装开发板环境](quickstart-lite-steps-board3518-setting.md)** + +- **[运行Hello OHOS](quickstart-lite-steps-board3518-running.md)** + +- **[常见问题](quickstart-lite-steps-board3518-faqs.md)** + + diff --git a/zh-cn/device-dev/quick-start/quickstart-lite-steps-board3861-connection.md b/zh-cn/device-dev/quick-start/quickstart-lite-steps-board3861-connection.md new file mode 100644 index 0000000000..fe69412c06 --- /dev/null +++ b/zh-cn/device-dev/quick-start/quickstart-lite-steps-board3861-connection.md @@ -0,0 +1,142 @@ +# WLAN联网 + +- [源码编译](#section191121332125319) +- [镜像烧录](#section19458165166) +- [WLAN模组联网](#section194671619167) + +本示例将演示如何通过AT命令完成WLAN模组与网关联网。 + +## 源码编译 + +本节描述如何在Linux服务器上进行WLAN模组版本的编译。 + +如果Linux编译环境通过Docker方式安装,具体编译过程请参见[Docker方式获取编译环境](../get-code/sourcecode-acquire.md)的编译操作。如果Linux编译环境通过软件包方式安装,请参考如下步骤。 + +1. 打开DevEco Device Tool工具,点击“View \> Terminal”,进入终端界面。 + + **图 1** IDE终端工具打开方法 + + + ![](figure/1.png) + + 在终端界面使用ssh命令连接linux服务器,如“ssh user@ipaddr”。 + + **图 2** 终端界面示意图 + + + ![](figure/2.png) + +2. 进入代码根路径,并在终端窗口,执行脚本命令“hb set”、“.”,选择需要编译的版本“wifiiot\_hispark\_pegasus”。 + + **图 3** 在终端界面选择目标构建版本示意图 + + + ![](figure/3.png) + +3. 执行“hb build”启动版本构建。 + + **图 4** 在终端界面执行编译命令示意图 + + + ![](figure/4.png) + +4. 编译结束后,如果出现“wifiiot\_hispark\_pegasus build success”字样,则证明构建成功,如下图所示。 + + **图 5** 编译成功示意图 + + + ![](figure/5.png) + +5. 构建成功后,会在./out/wifiiot/路径中生成以下文件,使用如下命令可以查看,至此编译构建流程结束。 + + ``` + ls -l out/hispark_pegasus/wifiiot_hispark_pegasus/ + ``` + + **图 6** 编译文件存放目录示意图 + + + ![](figure/3-0.png) + + +## 镜像烧录 + +Hi3861 WLAN模组的镜像烧录可以通过OpenHarmony IDE工具DevEco完成,工具的基本使用请参考[DevEco Device Tool使用指南](https://device.harmonyos.com/cn/docs/ide/user-guides/service_introduction-0000001050166905),烧录过程包含如下步骤。 + +1. 请连接好电脑和待烧录开发板,需要连接USB口,具体可参考[Hi3861开发板介绍](quickstart-lite-introduction-hi3861.md)。 +2. 打开电脑的设备管理器,查看并记录对应的串口号。 + + >![](../public_sys-resources/icon-note.gif) **说明:** + >如果对应的串口异常,请根据[Hi3861系列开发板串口驱动安装](https://device.harmonyos.com/cn/docs/ide/user-guides/hi3861-drivers-0000001058153433)安装USB转串口的驱动程序。 + + ![](figure/zh-cn_image_0000001128311118.png) + +3. 打开DevEco Device Tool,在Projects中,点击**Settings**打开工程配置界面。 + + ![](figure/zh-cn_image_0000001128311116.png) + +4. 在“Partition Configuration”页签,设置待烧录文件信息,默认情况下,DevEco Device Tool已针对Hi3861系列开发板进行适配,无需单独修改。 +5. 在“hi3861”页签,设置烧录选项,包括upload\_port、upload\_partitions和upload\_protocol。 + + - upload\_port:选择步骤[2](#zh-cn_topic_0000001056563976_li848662117291)中查询的串口号。 + - upload\_protocol:选择烧录协议,固定选择“burn-serial”。 + - upload\_partitions:选择待烧录的文件,默认选择hi3861\_app。 + + ![](figure/zh-cn_image_0000001128470922.png) + +6. 所有的配置都修改完成后,在工程配置页签的顶部,点击**Save**进行保存。 +7. 打开工程文件,在DevEco Device Tool界面的“PROJECT TASKS”中,点击hi3861下的**Upload**按钮,启动烧录。 + + ![](figure/zh-cn_image_0000001174270749.png) + +8. 启动烧录后,显示如下提示信息时,请按开发板上的RST按钮重启开发板。 + + ![](figure/zh-cn_image_0000001174270751.png) + +9. 重新上电后,启动烧录,界面提示如下信息时,表示烧录成功。 + + ![](figure/zh-cn_image_0000001174350669.png) + + +## WLAN模组联网 + +完成版本构建及烧录后,下面开始介绍如何在串口终端上执行AT命令,使WLAN模组联网。 + +1. 保持Windows工作台和WLAN模组的连接状态,在DevEco工具最下方,点击“DevEco:Serial Monitor”按钮。 + + **图 7** 打开DevEco串口终端示意图 + + + ![](figure/5-1.png) + +2. 复位WLAN模组,终端界面显示“ready to OS start”,则启动成功。 + + **图 8** WLAN复位成功示意图 + + + ![](figure/6.png) + +3. 在DevEco的串口终端中,依次执行如下AT命令,启动STA模式,连接指定AP热点,并开启DHCP功能。 + + ``` + AT+STARTSTA # 启动STA模式 + AT+SCAN # 扫描周边AP + AT+SCANRESULT # 显示扫描结果 + AT+CONN="SSID",,2,"PASSWORD" # 连接指定AP,其中SSID/PASSWORD为待连接的热点名称和密码 + AT+STASTAT # 查看连接结果 + AT+DHCP=wlan0,1 # 通过DHCP向AP请求wlan0的IP地址 + ``` + +4. 查看WLAN模组与网关联通是否正常,如下图所示。 + + ``` + AT+IFCFG # 查看模组接口IP + AT+PING=X.X.X.X # 检查模组与网关的联通性,其中X.X.X.X需替换为实际的网关地址 + ``` + + **图 9** WLAN模组联网成功示意图 + + + ![](figure/截图.png) + + diff --git a/zh-cn/device-dev/quick-start/quickstart-lite-steps-board3861-faqs.md b/zh-cn/device-dev/quick-start/quickstart-lite-steps-board3861-faqs.md new file mode 100644 index 0000000000..b0dbbae1b3 --- /dev/null +++ b/zh-cn/device-dev/quick-start/quickstart-lite-steps-board3861-faqs.md @@ -0,0 +1,292 @@ +# 常见问题 + +- [安装python3过程中,提示“configure: error: no acceptable C compiler found in $PATH”](#section1221016541119) +- [安装python3过程中,提示“-bash: make: command not found”](#section1913477181213) +- [安装python3过程中,提示“zlib not available”](#section108211415131210) +- [安装python3过程中,提示“No module named '\_ctypes'”](#section2062268124) +- [编译构建过程中,提示“No module named 'Crypto'”](#section982315398121) +- [编译构建过程中,提示“No module named 'ecdsa'”](#section102035451216) +- [编译构建过程中,提示“Could not find a version that satisfies the requirement six\>=1.9.0”](#section4498158162320) +- [编译构建过程中,提示找不到“-lgcc”](#section11181036112615) +- [编译构建过程中,提示找不到“python”](#section1571810194619) +- [安装 kconfiglib时,遇到lsb\_release错误](#section691681635814) + +## 安装python3过程中,提示“configure: error: no acceptable C compiler found in $PATH” + +- **现象描述** + + 安装python3过程中出现以下错误: + + ``` + configure: error: no acceptable C compiler found in $PATH. See 'config.log' for more details + ``` + +- **可能原因** + + 环境中未安装“gcc”。 + +- **解决办法** + + 1、通过命令“apt-get install gcc”在线安装。 + + 2、完成后,重新安装python3。 + + +## 安装python3过程中,提示“-bash: make: command not found” + +- **现象描述** + + 安装python3过程中出现以下错误: + + ``` + -bash: make: command not found + ``` + +- **可能原因** + + 环境中未安装“make”。 + +- **解决办法** + + 1、通过命令“apt-get install make”在线安装。 + + 2、完成后,重新安装python3。 + + +## 安装python3过程中,提示“zlib not available” + +- **现象描述** + + 安装python3过程中出现以下错误: + + ``` + zipimport.ZipImportError: can't decompress data; zlib not avaliable + ``` + +- **可能原因** + + 环境中未安装“zlib”。 + +- **解决办法** + + 方法1:通过命令“apt-get install zlib”在线安装。 + + 方法2:如果软件源中没有该软件,请从“www.zlib.net”下载版本代码,并离线安装。 + + ![](figure/10.png) + + 完成下载后,通过以下命令安装: + + ``` + # tar xvf zlib-1.2.11.tar.gz + # cd zlib-1.2.11 + # ./configure + # make && make install + ``` + + 完成后,重新安装python3。 + + +## 安装python3过程中,提示“No module named '\_ctypes'” + +- **现象描述** + + 安装python3过程中出现以下错误: + + ``` + ModuleNotFoundError:No module named ‘_ctypes’ + ``` + + +- **可能原因** + + 环境中未安装“libffi”和“libffi-devel”。 + + +- **解决办法** + + 1、通过命令“apt-get install libffi\* -y”,在线安装。 + + 2、完成后,重新安装python3。 + + +## 编译构建过程中,提示“No module named 'Crypto'” + +- **现象描述** + + 编译构建过程中出现以下错误: + + ``` + ModuleNotFoundError: No module named 'Crypto' + ``` + + +- **可能原因** + + 环境中未安装“Crypto”。 + + +- **解决办法** + + 方法1:通过命令“pip3 install Crypto”,在线安装。 + + 方法2:离线安装 + + 通过网页[https://pypi.org/project/pycrypto/\#files](https://pypi.org/project/pycrypto/#files),下载源码。 + + ![](figure/zh-cn_image_0000001128470864.png) + + 将源码放置在Linux服务器中,解压,并安装“python3 setup.py install”。 + + 完成上述安装后,重新构建。 + + +## 编译构建过程中,提示“No module named 'ecdsa'” + +- **现象描述** + + 编译构建过程中出现以下错误: + + ``` + ModuleNotFoundError:No module named 'ecdsa' + ``` + + +- **可能原因** + + 环境中未安装“ecdsa”。 + + +- **解决办法** + + 方法1:通过命令“pip3 install ecdsa”,在线安装。 + + 方法2:离线安装 + + 通过网页[https://pypi.org/project/ecdsa/\#files](https://pypi.org/project/ecdsa/#files),下载安装包。 + + ![](figure/zh-cn_image_0000001128311072.png) + + 将安装包放置Linux服务器中,并安装“pip3 install ecdsa-0.15-py2.py3-none-any.whl”。 + + 完成上述安装后,重新构建。 + + +## 编译构建过程中,提示“Could not find a version that satisfies the requirement six\>=1.9.0” + +- **现象描述** + + 编译构建过程中出现以下错误: + + ``` + Could not find a version that satisfies the requirement six>=1.9.0 + ``` + + +- **可能原因** + + 环境中未安装合适的“six”。 + + +- **解决办法** + + 方法1:通过命令“pip3 install six”,在线安装。 + + 方法2:离线安装 + + 通过网页[https://pypi.org/project/six/\#files](https://pypi.org/project/six/#files),下载安装包。 + + ![](figure/zh-cn_image_0000001174270699.png) + + 将源码放置在Linux服务器中,并安装“pip3 install six-1.14.0-py2.py3-none-any.whl”。 + + 完成上述安装后,重新构建。 + + +## 编译构建过程中,提示找不到“-lgcc” + +- **现象描述** + + 编译构建过程中出现以下错误: + + ``` + riscv32-unknown-elf-ld: cannot find -lgcc + ``` + + +- **可能原因** + + 交叉编译器gcc\_riscv32的PATH添加错误,如下,在"bin"后多添加了一个“/”,应该删除。 + + ``` + ~/gcc_riscv32/bin/:/data/toolchain/ + ``` + + +- **解决办法** + + 重新修改gcc\_riscv32的PATH,将多余的“/”删除。 + + ``` + ~/gcc_riscv32/bin:/data/toolchain/ + ``` + + +## 编译构建过程中,提示找不到“python” + +- **现象描述** + + 编译构建过程中出现以下错误: + + ``` + -bash: /usr/bin/python: No such file or directory + ``` + + +- **可能原因**1 + + 没有装python。 + +- **解决办法** + + 请按照 [安装Python环境](quickstart-lite-env-setup-lin.md) + +- **可能原因2** + + ![](figure/zh-cn_image_0000001128311070.png) + +- **解决办法** + + usr/bin目录下没有python软链接,请运行以下命令添加软链接: + + ``` + # cd /usr/bin/ + # which python3 + # ln -s /usr/local/bin/python3 python + # python --version + ``` + + 例: + + ![](figure/zh-cn_image_0000001174350623.png) + + +## 安装 kconfiglib时,遇到lsb\_release错误 + +- **现象描述** + + 安装kconfiglib过程中遇到如下错误打印: + + ``` + subprocess.CalledProcessError: Command '('lsb_release', '-a')' returned non-zero exit status 1. + ``` + +- **可能原因** + + lsb\_release模块基于的python版本与现有python版本不一致 + +- **解决办法** + + 执行"find / -name lsb\_release",找到lsb\_release位置并删除,如:"sudo rm -rf /usr/bin/lsb\_release" + + diff --git a/zh-cn/device-dev/quick-start/quickstart-lite-steps-board3861-running.md b/zh-cn/device-dev/quick-start/quickstart-lite-steps-board3861-running.md new file mode 100644 index 0000000000..547aa5affc --- /dev/null +++ b/zh-cn/device-dev/quick-start/quickstart-lite-steps-board3861-running.md @@ -0,0 +1,158 @@ +# 运行Hello World + +- [修改源码](#section79601457101015) +- [调测验证](#section1621064881419) +- [printf打印](#section1246911301217) +- [根据asm文件进行问题定位](#section199621957141014) +- [运行结果](#section18115713118) +- [下一步学习](#section9712145420182) + +本示例将演示如何编写简单业务,输出“Hello World”,初步了解OpenHarmony 如何运行在开发板上。 + +## 修改源码 + +bugfix和新增业务两种情况,涉及源码修改。下面以新增业务(my\_first\_app)为例,向开发者介绍如何进行源码修改。 + +1. 确定目录结构。 + + 开发者编写业务时,务必先在./applications/sample/wifi-iot/app路径下新建一个目录(或一套目录结构),用于存放业务源码文件。 + + 例如:在app下新增业务my\_first\_app,其中hello\_world.c为业务代码,BUILD.gn为编译脚本,具体规划目录结构如下: + + ``` + . + └── applications + └── sample + └── wifi-iot + └── app + │── my_first_app + │ │── hello_world.c + │ └── BUILD.gn + └── BUILD.gn + ``` + +2. 编写业务代码。 + + 新建./applications/sample/wifi-iot/app/my\_first\_app下的hello\_world.c文件,在hello\_world.c中新建业务入口函数HelloWorld,并实现业务逻辑。并在代码最下方,使用OpenHarmony启动恢复模块接口SYS\_RUN\(\)启动业务。(SYS\_RUN定义在ohos\_init.h文件中) + + ``` + #include + #include "ohos_init.h" + #include "ohos_types.h" + + void HelloWorld(void) + { + printf("[DEMO] Hello world.\n"); + } + SYS_RUN(HelloWorld); + ``` + +3. 编写用于将业务构建成静态库的BUILD.gn文件。 + + 新建./applications/sample/wifi-iot/app/my\_first\_app下的BUILD.gn文件,并完成如下配置。 + + 如[步骤1](#li5479332115116)所述,BUILD.gn文件由三部分内容(目标、源文件、头文件路径)构成,需由开发者完成填写。 + + ``` + static_library("myapp") { + sources = [ + "hello_world.c" + ] + include_dirs = [ + "//utils/native/lite/include" + ] + } + ``` + + - static\_library中指定业务模块的编译结果,为静态库文件libmyapp.a,开发者根据实际情况完成填写。 + - sources中指定静态库.a所依赖的.c文件及其路径,若路径中包含"//"则表示绝对路径(此处为代码根路径),若不包含"//"则表示相对路径。 + - include\_dirs中指定source所需要依赖的.h文件路径。 + +4. 编写模块BUILD.gn文件,指定需参与构建的特性模块。 + + 配置./applications/sample/wifi-iot/app/BUILD.gn文件,在features字段中增加索引,使目标模块参与编译。features字段指定业务模块的路径和目标,以my\_first\_app举例,features字段配置如下。 + + ``` + import("//build/lite/config/component/lite_component.gni") + + lite_component("app") { + features = [ + "my_first_app:myapp", + ] + } + ``` + + - my\_first\_app是相对路径,指向./applications/sample/wifi-iot/app/my\_first\_app/BUILD.gn。 + - myapp是目标,指向./applications/sample/wifi-iot/app/my\_first\_app/BUILD.gn中的static\_library\("myapp"\)。 + + +## 调测验证 + +目前调试验证的方法有两种,分别为通过printf打印日志、通过asm文件定位panic问题,开发者可以根据具体业务情况选择。 + +由于本示例业务简单,采用printf打印日志的调试方式即可。下面开始介绍这两种调试手段的使用方法。 + +## printf打印 + +代码中增加printf维测,信息会直接打印到串口上。开发者可在业务关键路径或业务异常位置增加日志打印,如下所示。 + +``` +void HelloWorld(void) +{ + printf("[DEMO] Hello world.\n"); +} +``` + +## 根据asm文件进行问题定位 + +系统异常退出时,会在串口上打印异常退出原因调用栈信息,如下文所示。通过解析异常栈信息可以定位异常位置。 + +``` +=======KERNEL PANIC======= +**********************Call Stack********************* +Call Stack 0 -- 4860d8 addr:f784c +Call Stack 1 -- 47b2b2 addr:f788c +Call Stack 2 -- 3e562c addr:f789c +Call Stack 3 -- 4101de addr:f78ac +Call Stack 4 -- 3e5f32 addr:f78cc +Call Stack 5 -- 3f78c0 addr:f78ec +Call Stack 6 -- 3f5e24 addr:f78fc +********************Call Stack end******************* +``` + +为解析上述调用栈信息,需要使用到Hi3861\_wifiiot\_app.asm文件,该文件记录了代码中函数在Flash上的符号地址以及反汇编信息。asm文件会随版本大包一同构建输出,存放在./out/wifiiot/路径下。 + +1. 将调用栈CallStack信息保存到txt文档中,以便于编辑。(可选) +2. 打开asm文件,并搜索CallStack中的地址,列出对应的函数名 信息。通常只需找出前几个栈信息对应的函数,就可明确异常代码方向。 + + ``` + Call Stack 0 -- 4860d8 addr:f784c -- WadRecvCB + Call Stack 1 -- 47b2b2 addr:f788c -- wal_sdp_process_rx_data + Call Stack 2 -- 3e562c addr:f789c + Call Stack 3 -- 4101de addr:f78ac + Call Stack 4 -- 3e5f32 addr:f78cc + Call Stack 5 -- 3f78c0 addr:f78ec + Call Stack 6 -- 3f5e24 addr:f78fc + ``` + +3. 根据以上调用栈信息,可以定位WadRecvCB函数中出现了异常。 + + ![](figure/zh-cn_image_0000001174270737.png) + +4. 完成代码排查及修改。 + +## 运行结果 + +示例代码编译、烧录、运行、调测后,在串口界面会显示如下结果: + +``` +ready to OS start +FileSystem mount ok. +wifi init success! +[DEMO] Hello world. +``` + +## 下一步学习 + +恭喜,您已完成Hi3861 WLAN模组快速上手!建议您下一步进入[WLAN产品开发](../guide/device-wifi.md)的学习 。 + diff --git a/zh-cn/device-dev/quick-start/quickstart-lite-steps-board3861-setting.md b/zh-cn/device-dev/quick-start/quickstart-lite-steps-board3861-setting.md new file mode 100644 index 0000000000..90998c5acf --- /dev/null +++ b/zh-cn/device-dev/quick-start/quickstart-lite-steps-board3861-setting.md @@ -0,0 +1,367 @@ +# 安装开发板环境 + +- [Hi3861工具要求](#section466851916410) + - [硬件要求](#section19202111020215) + - [软件要求](#section727451210318) + +- [安装Linux编译工具](#section497484245614) + - [安装编译依赖基础软件(仅Ubuntu 20+需要)](#section45512412251) + - [安装Scons](#section7438245172514) + - [安装python模块](#section88701892341) + - [安装gcc\_riscv32(WLAN模组类编译工具链)](#section34435451256) + +- [安装USB转串口驱动](#section1027732411513) + +## Hi3861工具要求 + +### 硬件要求 + +- Linux服务器 +- Windows工作台(主机电脑) +- Hi3861 WLAN模组 +- USB Type-C线(Windows工作台通过USB与Hi3861 WLAN模组连接) + +各硬件连接关系如下图所示。 + +**图 1** 硬件连线图 +![](figure/硬件连线图.png "硬件连线图") + +### 软件要求 + +>![](../public_sys-resources/icon-notice.gif) **须知:** +>本节描述采用安装包方式安装相关工具的操作步骤。如果是Docker方式安装,无需安装[表1](#table6299192712513)中的Linux服务器相关工具,只需安装Windows工作台工具即可。 + +Hi3861开发板需要的工具如下表所示。 + +**表 1** Hi3861开发板需要的工具 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    平台类型

    +

    开发工具

    +

    用途

    +

    获取途径

    +

    Linux服务器

    +

    编译基础软件包(仅ubuntu 20+需要)

    +

    编译依赖的基础软件包

    +

    通过互联网获取

    +

    Linux服务器

    +

    SCons3.0.4+

    +

    编译构建工具

    +

    通过互联网获取

    +

    Linux服务器

    +

    python模块:setuptools、kconfiglib、pycryptodome、six、ecdsa

    +

    编译构建工具

    +

    通过互联网获取

    +

    Linux服务器

    +

    gcc riscv32

    +

    编译构建工具

    +

    通过互联网获取

    +

    Windows工作台

    +

    CH341SER.EXE

    +

    USB转串口驱动

    +

    http://www.wch.cn/search?q=ch340g&t=downloads

    +
    + +## 安装Linux编译工具 + +>![](../public_sys-resources/icon-notice.gif) **须知:** +>- 如果通过“HPM组件方式”或“HPM包管理器命令行工具方式”获取源码,不需要安装gcc\_riscv32编译工具。 +>- (推荐)如果通过“镜像站点方式”或“代码仓库方式”获取源码,需要安装gcc\_riscv32编译工具。安装gcc\_riscv32编译工具时,请确保编译工具的环境变量路径唯一。 + +### 安装编译依赖基础软件(仅Ubuntu 20+需要) + +执行以下命令进行安装: + +``` +sudo apt-get install build-essential gcc g++ make zlib* libffi-dev +``` + +### 安装Scons + +1. 打开Linux编译服务器终端。 +2. 运行如下命令,安装SCons安装包。 + + ``` + python3 -m pip install scons + ``` + +3. 运行如下命令,查看是否安装成功。如果安装成功,查询结果下图所示。 + + ``` + scons -v + ``` + + **图 2** SCons安装成功界面,版本要求3.0.4以上 + ![](figure/SCons安装成功界面-版本要求3-0-4以上.png "SCons安装成功界面-版本要求3-0-4以上") + + +### 安装python模块 + +1. 运行如下命令,安装python模块setuptools。 + + ``` + pip3 install setuptools + ``` + +2. 安装GUI menuconfig工具(Kconfiglib),建议安装Kconfiglib 13.2.0+版本,任选如下一种方式。 + - **命令行方式:** + + ``` + sudo pip3 install kconfiglib + ``` + + + - **安装包方式:** + 1. 下载.whl文件(例如:kconfiglib-13.2.0-py2.py3-none-any.whl)。 + + 下载路径:“[https://pypi.org/project/kconfiglib\#files](https://pypi.org/project/kconfiglib#files)” + + + 1. 运行如下命令,安装.whl文件。 + + ``` + sudo pip3 install kconfiglib-13.2.0-py2.py3-none-any.whl + ``` + + + +3. 安装pycryptodome,任选如下一种方式。 + + 安装升级文件签名依赖的Python组件包,包括:pycryptodome、six、ecdsa。安装ecdsa依赖six,请先安装six,再安装ecdsa。 + + - **命令行方式:** + + ``` + sudo pip3 install pycryptodome + ``` + + - **安装包方式:** + 1. 下载.whl文件(例如:pycryptodome-3.9.9-cp38-cp38-manylinux1\_x86\_64.whl)。 + + 下载路径:“[https://pypi.org/project/pycryptodome/\#files](https://pypi.org/project/pycryptodome/#files)”。 + + + 1. 运行如下命令,安装.whl文件。 + + ``` + sudo pip3 install pycryptodome-3.9.9-cp38-cp38-manylinux1_x86_64.whl + ``` + + + +4. 安装six,任选如下一种方式。 + - **命令行方式:** + + ``` + sudo pip3 install six --upgrade --ignore-installed six + ``` + + + - **安装包方式:** + 1. 下载.whl文件(例如:six-1.12.0-py2.py3-none-any.whl)。 + + 下载路径:“[https://pypi.org/project/six/\#files](https://pypi.org/project/six/#files)” + + + 1. 运行如下命令,安装.whl文件。 + + ``` + sudo pip3 install six-1.12.0-py2.py3-none-any.whl + ``` + + + +5. 安装ecdsa,任选如下一种方式。 + - **命令行方式:** + + ``` + sudo pip3 install ecdsa + ``` + + - **安装包方式:** + 1. 下载.whl文件(例如:ecdsa-0.14.1-py2.py3-none-any.whl)。 + + 下载路径:“[https://pypi.org/project/ecdsa/\#files](https://pypi.org/project/ecdsa/#files)” + + + 1. 运行如下命令,安装.whl文件。 + + ``` + sudo pip3 install ecdsa-0.14.1-py2.py3-none-any.whl + ``` + + + + +### 安装gcc\_riscv32(WLAN模组类编译工具链) + +>![](../public_sys-resources/icon-notice.gif) **须知:** +>- Hi3861平台仅支持使用libgcc运行时库的静态链接,不建议开发者使用libgcc运行时库的动态链接,会导致商业分发时被GPL V3污染。 +>- 通过下述步骤2-15,我们编译好了gcc\_riscv32 镜像,提供给开发者[直接下载](https://repo.huaweicloud.com/harmonyos/compiler/gcc_riscv32/7.3.0/linux/gcc_riscv32-linux-7.3.0.tar.gz)使用。直接下载 gcc\_riscv32 镜像的开发者可省略下述2-15步。 + +1. 打开Linux编译服务器终端。 +2. 环境准备,请安装"gcc, g++, bison, flex, makeinfo"软件,确保工具链能正确编译。 + + ``` + sudo apt-get install gcc && sudo apt-get install g++ && sudo apt-get install flex bison && sudo apt-get install texinfo + ``` + +3. 下载riscv-gnu-toolchain交叉编译工具链。 + + ``` + git clone --recursive https://gitee.com/mirrors/riscv-gnu-toolchain.git + ``` + +4. 打开文件夹riscv-gnu-toolchain,先删除空文件夹,以防止下载newlib,binutils,gcc时冲突。 + + ``` + cd riscv-gnu-toolchain && rm -rf riscv-newlib && rm -rf riscv-binutils && rm -rf riscv-gcc + ``` + +5. 下载riscv-newlib-3.0.0。 + + ``` + git clone -b riscv-newlib-3.0.0 https://github.com/riscv/riscv-newlib.git + ``` + +6. 下载riscv-binutils-2.31.1。 + + ``` + git clone -b riscv-binutils-2.31.1 https://github.com/riscv/riscv-binutils-gdb.git + ``` + +7. 下载riscv-gcc-7.3.0。 + + ``` + git clone -b riscv-gcc-7.3.0 https://github.com/riscv/riscv-gcc + ``` + +8. 添加riscv-gcc-7.3.0补丁。 + + 访问gcc官方补丁链接[89411](https://gcc.gnu.org/git/?p=gcc.git;a=commitdiff;h=026216a753ef0a757a9e368a59fa667ea422cf09;hp=2a23a1c39fb33df0277abd4486a3da64ae5e62c2),[86724](https://gcc.gnu.org/git/?p=gcc.git;a=blobdiff;f=gcc/graphite.h;h=be0a22b38942850d88feb159603bb846a8607539;hp=4e0e58c60ab83f1b8acf576e83330466775fac17;hb=b1761565882ed6a171136c2c89e597bc4dd5b6bf;hpb=fbd5f023a03f9f60c6ae36133703af5a711842a3),按照补丁链接中要求的修改,手动将变更添加到对应的.c和.h文件中,注意由于patch版本与下载的gcc版本有所偏差,行数有可能对应不上,请自行查找patch中的关键字定位到对应行。 + +9. 下载[GMP 6.1.2](https://gmplib.org/download/gmp/gmp-6.1.2.tar.bz2),并解压安装。 + + ``` + tar -xvf gmp-6.1.2.tar.bz2 && mkdir build_gmp && cd build_gmp && ../gmp-6.1.2/configure --prefix=/usr/local/gmp-6.1.2 --disable-shared --enable-cxx && make && make install + ``` + +10. 下载[mpfr-4.0.2 ](https://www.mpfr.org/mpfr-4.0.2/mpfr-4.0.2.tar.gz),并解压安装。 + + ``` + tar -xvf mpfr-4.0.2.tar.gz && mkdir build_mpfr && cd build_mpfr && ../mpfr-4.0.2/configure --prefix=/usr/local/mpfr-4.0.2 --with-gmp=/usr/local/gmp-6.1.2 --disable-shared && make && make install + ``` + +11. 下载[mpc-1.1.0](https://ftp.gnu.org/gnu/mpc/mpc-1.1.0.tar.gz) ,并解压安装。 + + ``` + tar -xvf mpc-1.1.0.tar.gz && mkdir build_mpc && cd build_mpc && ../mpc-1.1.0/configure --prefix=/usr/local/mpc-1.1.0 --with-gmp=/usr/local/gmp-6.1.2 --with-mpfr=/usr/local/mpfr-4.0.2 --disable-shared && make && make install + ``` + +12. 打开文件夹riscv-gnu-toolchain,新建工具链输出目录。 + + ``` + cd /opt && mkdir gcc_riscv32 + ``` + +13. 编译binutils。 + + ``` + mkdir build_binutils && cd build_binutils && ../riscv-binutils-gdb/configure --prefix=/opt/gcc_riscv32 --target=riscv32-unknown-elf --with-arch=rv32imc --with-abi=ilp32 --disable-__cxa_atexit --disable-libgomp --disable-libmudflap --enable-libssp --disable-libstdcxx-pch --disable-nls --disable-shared --disable-threads --disable-multilib --enable-poison-system-directories --enable-languages=c,c++ --with-gnu-as --with-gnu-ld --with-newlib --with-system-zlib CFLAGS="-fstack-protector-strong -O2 -D_FORTIFY_SOURCE=2 -Wl,-z,relro,-z,now,-z,noexecstack -fPIE" CXXFLAGS="-fstack-protector-strong -O2 -D_FORTIFY_SOURCE=2 -Wl,-z,relro,-z,now,-z,noexecstack -fPIE" CXXFLAGS_FOR_TARGET="-Os -mcmodel=medlow -Wall -fstack-protector-strong -Wl,-z,relro,-z,now,-z,noexecstack -Wtrampolines -fno-short-enums -fno-short-wchar" CFLAGS_FOR_TARGET="-Os -mcmodel=medlow -Wall -fstack-protector-strong -Wl,-z,relro,-z,now,-z,noexecstack -Wtrampolines -fno-short-enums -fno-short-wchar" --bindir=/opt/gcc_riscv32/bin --libexecdir=/opt/gcc_riscv32/riscv32 --libdir=/opt/gcc_riscv32 --includedir=/opt/gcc_riscv32 && make -j16 && make install && cd .. + ``` + +14. 编译newlib。 + + ``` + mkdir build_newlib && cd build_newlib && ../riscv-newlib/configure --prefix=/opt/gcc_riscv32 --target=riscv32-unknown-elf --with-arch=rv32imc --with-abi=ilp32 --disable-__cxa_atexit --disable-libgomp --disable-libmudflap --enable-libssp --disable-libstdcxx-pch --disable-nls --disable-shared --disable-threads --disable-multilib --enable-poison-system-directories --enable-languages=c,c++ --with-gnu-as --with-gnu-ld --with-newlib --with-system-zlib CFLAGS="-fstack-protector-strong -O2 -D_FORTIFY_SOURCE=2 -Wl,-z,relro,-z,now,-z,noexecstack -fPIE" CXXFLAGS="-fstack-protector-strong -O2 -D_FORTIFY_SOURCE=2 -Wl,-z,relro,-z,now,-z,noexecstack -fPIE" \CXXFLAGS_FOR_TARGET="-Os -mcmodel=medlow -Wall -fstack-protector-strong -Wl,-z,relro,-z,now,-z,noexecstack -Wtrampolines -fno-short-enums -fno-short-wchar" CFLAGS_FOR_TARGET="-Os -mcmodel=medlow -Wall -fstack-protector-strong -Wl,-z,relro,-z,now,-z,noexecstack -Wtrampolines -fno-short-enums -fno-short-wchar" --bindir=/opt/gcc_riscv32/bin --libexecdir=/opt/gcc_riscv32 --libdir=/opt/gcc_riscv32 --includedir=/opt/gcc_riscv32 && make -j16 && make install && cd .. + ``` + +15. 编译gcc。 + + ``` + mkdir build_gcc && cd build_gcc && ../riscv-gcc/configure --prefix=/opt/gcc_riscv32 --target=riscv32-unknown-elf --with-arch=rv32imc --with-abi=ilp32 --disable-__cxa_atexit --disable-libgomp --disable-libmudflap --enable-libssp --disable-libstdcxx-pch --disable-nls --disable-shared --disable-threads --disable-multilib --enable-poison-system-directories --enable-languages=c,c++ --with-gnu-as --with-gnu-ld --with-newlib --with-system-zlib CFLAGS="-fstack-protector-strong -O2 -D_FORTIFY_SOURCE=2 -Wl,-z,relro,-z,now,-z,noexecstack -fPIE" CXXFLAGS="-fstack-protector-strong -O2 -D_FORTIFY_SOURCE=2 -Wl,-z,relro,-z,now,-z,noexecstack -fPIE" LDFLAGS="-Wl,-z,relro,-z,now,-z,noexecstack" CXXFLAGS_FOR_TARGET="-Os -mcmodel=medlow -Wall -fstack-protector-strong -Wl,-z,relro,-z,now,-z,noexecstack -Wtrampolines -fno-short-enums -fno-short-wchar" CFLAGS_FOR_TARGET="-Os -mcmodel=medlow -Wall -fstack-protector-strong -Wl,-z,relro,-z,now,-z,noexecstack -Wtrampolines -fno-short-enums -fno-short-wchar" --with-headers="/opt/gcc-riscv32/riscv32-unknown-elf/include" --with-mpc=/usr/local/mpc-1.1.0 --with-gmp=/usr/local/gmp-6.1.2 --with-mpfr=/usr/local/mpfr-4.0.2 && make -j16 && make install + ``` + +16. 设置环境变量。 + + >![](../public_sys-resources/icon-note.gif) **说明:** + >如果直接采用编译好的riscv32 gcc包,请参照如下步骤设置环境变量: + >1. 将压缩包解压到根目录 + > ``` + > tar -xvf gcc_riscv32-linux-7.3.0.tar.gz -C ~ + > ``` + >2. 设置环境变量。 + > ``` + > vim ~/.bashrc + > ``` + >3. 将以下命令拷贝到.bashrc文件的最后一行,保存并退出。 + > ``` + > export PATH=~/gcc_riscv32/bin:$PATH + > ``` + + ``` + vim ~/.bashrc + ``` + + 将以下命令拷贝到.bashrc文件的最后一行,保存并退出。 + + ``` + export PATH=~/gcc_riscv32/bin:$PATH + ``` + +17. 生效环境变量。 + + ``` + source ~/.bashrc + ``` + +18. Shell命令行中输入如下命令,如果能正确显示编译器版本号,表明编译器安装成功。 + + ``` + riscv32-unknown-elf-gcc -v + ``` + + +## 安装USB转串口驱动 + +相关步骤在Windows工作台操作。 + +1. 点击链接[下载CH341SER USB转串口](http://www.hihope.org/download/download.aspx?mtt=8)驱动程序。 +2. 点击安装包,安装驱动程序。 +3. 驱动安装完成后,重新插拔USB接口,串口信息显示如下图所示。 + + ![](figure/zh-cn_image_0000001174350633.png) + + diff --git a/zh-cn/device-dev/quick-start/quickstart-lite-steps-board3861.md b/zh-cn/device-dev/quick-start/quickstart-lite-steps-board3861.md new file mode 100644 index 0000000000..8aca858907 --- /dev/null +++ b/zh-cn/device-dev/quick-start/quickstart-lite-steps-board3861.md @@ -0,0 +1,11 @@ +# Hi3861开发板 + +- **[安装开发板环境](quickstart-lite-steps-board3861-setting.md)** + +- **[WLAN联网](quickstart-lite-steps-board3861-connection.md)** + +- **[运行Hello World](quickstart-lite-steps-board3861-running.md)** + +- **[常见问题](quickstart-lite-steps-board3861-faqs.md)** + + diff --git a/zh-cn/device-dev/quick-start/quickstart-lite-steps.md b/zh-cn/device-dev/quick-start/quickstart-lite-steps.md new file mode 100644 index 0000000000..49545483c6 --- /dev/null +++ b/zh-cn/device-dev/quick-start/quickstart-lite-steps.md @@ -0,0 +1,9 @@ +# 开发步骤 + +- **[Hi3861开发板](quickstart-lite-steps-board3861.md)** + +- **[Hi3516开发板](quickstart-lite-steps-board3516.md)** + +- **[Hi3518开发板](quickstart-lite-steps-board3518.md)** + + diff --git a/zh-cn/device-dev/quick-start/quickstart-lite.md b/zh-cn/device-dev/quick-start/quickstart-lite.md new file mode 100644 index 0000000000..47a4ec111d --- /dev/null +++ b/zh-cn/device-dev/quick-start/quickstart-lite.md @@ -0,0 +1,11 @@ +# 轻量和小型系统入门 + +- **[概述](quickstart-lite-overview.md)** + +- **[了解开发板](quickstart-lite-introduction.md)** + +- **[搭建系统环境](quickstart-lite-env-setup.md)** + +- **[开发步骤](quickstart-lite-steps.md)** + + diff --git a/zh-cn/device-dev/quick-start/quickstart-standard-burn.md b/zh-cn/device-dev/quick-start/quickstart-standard-burn.md new file mode 100644 index 0000000000..be86e001d6 --- /dev/null +++ b/zh-cn/device-dev/quick-start/quickstart-standard-burn.md @@ -0,0 +1,201 @@ +# 镜像烧录 + +- [下一步](#section5600113114323) + +标准系统烧录,在V2.2 Beta1及以上版本支持。 + +Hi3516DV300支持烧录标准系统,其烧录方式包括网口烧录和串口烧录三种方式,其中: + +- **Windows系统:支持网口烧录和串口烧录** +- **Linux系统:支持串口烧录和网口烧录。** + +同一种烧录方式(如网口烧录),在Windows和Linux环境下的烧录操作完全一致,区别仅在于DevEco Device Tool环境搭建不同。 + +>![](../public_sys-resources/icon-note.gif) **说明:** +>当前Hi3516DV300开发板支持通过网口、USB、串口三种方式烧录OpenHarmony标准系统。本文以网口方式为例讲解烧录操作,其他两种烧录方式请参照[Hi3516DV300烧录指导](https://device.harmonyos.com/cn/docs/ide/user-guides/hi3516_upload-0000001052148681)。 + +### 前提条件 + +在DevEco Device Tool中[打开一个工程](https://device.harmonyos.com/cn/docs/ide/user-guides/open_project-0000001071680043),该工程文件夹选择待烧录文件所在文件夹即可。其中开发板类型固定选择Hi3516DV300,Framework选择“Hb”。 + +### 使用网口烧录 + +Hi3516DV300开发板使用网口录方式,支持Windows和Linux系统。 + +1. 请连接好电脑和待烧录开发板,需要同时连接串口、网口和电源,具体可参考[Hi3516DV300开发板介绍](https://device.harmonyos.com/cn/docs/start/introduce/oem_minitinier_des_3516-0000001152041033)。 +2. 打开电脑的设备管理器,查看并记录对应的串口号。 + + >![](../public_sys-resources/icon-note.gif) **说明:** + >如果对应的串口异常,请根据[Hi3516DV300/Hi3518EV300开发板串口驱动安装指导](https://device.harmonyos.com/cn/docs/ide/user-guides/hi3516_hi3518-drivers-0000001050743695)安装USB转串口的驱动程序。 + + ![](figure/zh-cn_image_0000001114129428.png) + +3. 打开DevEco Device Tool,在Projects中,点击**Settings**打开工程配置界面。 + + ![](figure/2021-01-27_170334-16.png) + +4. 在**Partition Configuration**页签中,按照下表内容填写烧录文件信息,包括: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    Name

    +

    Binary

    +

    Memory

    +

    System

    +

    Address

    +

    Length

    +

    Board

    +

    Type

    +

    fastboot

    +

    选择“u-boot-hi3516dv300_emmc.bin”

    +

    emmc

    +

    none

    +

    0x000000

    +

    0x100000

    +

    固定选择“hi3516dv300”

    +

    NA

    +

    boot

    +

    选择“uImage”

    +

    emmc

    +

    none

    +

    0x100000

    +

    0xf00000

    +

    NA

    +

    updater

    +

    选择“updater.img”

    +

    emmc

    +

    ext3/4

    +

    0x1000000

    +

    0x1400000

    +

    NA

    +

    misc

    +

    空白,不用选择

    +

    emmc

    +

    none

    +

    0x2400000

    +

    0x100000

    +

    NA

    +

    system

    +

    选择“system.img”

    +

    emmc

    +

    ext3/4

    +

    0x2500000

    +

    0xceb00000

    +

    NA

    +

    vendor

    +

    选择“vendor.img”

    +

    emmc

    +

    ext3/4

    +

    0xd1000000

    +

    0x10000000

    +

    NA

    +

    userdata

    +

    选择“userdata.img”

    +

    emmc

    +

    ext3/4

    +

    0xe1000000

    +

    0x5b800000

    +

    NA

    +
    + + ![](figure/zh-cn_image_0000001130584312.png) + +5. 在“hi3516dv300”页签,设置烧录选项,包括upload\_port、upload\_partitions和upload\_protocol。 + + - upload\_port:选择步骤[2](#zh-cn_topic_0000001056443961_li1050616379507)中查询的串口号。 + - upload\_protocol:选择烧录协议,固定选择“hiburn-net”。 + - upload\_partitions:选择待烧录的文件,包括fastboot、boot、updater、misc、system、vendor和userdata。 + + ![](figure/zh-cn_image_0000001117621400.png) + +6. 检查和设置连接开发板后的网络适配器的IP地址信息,设置方法请参考[设置Hi3516DV300网口烧录的IP地址信息](https://device.harmonyos.com/cn/docs/ide/user-guides/set_ipaddress-0000001141825075)。 +7. 设置网口烧录的IP地址信息,设置如下选项: + + - upload\_net\_server\_ip:选择步骤6中设置的IP地址信息。例如192.168.1.2 + - upload\_net\_client\_mask:设置开发板的子网掩码,工具会自动根据选择的upload\_net\_server\_ip进行设置。例如255.255.255.0 + - upload\_net\_client\_gw:设置开发板的网关,工具会自动根据选择的upload\_net\_server\_ip进行设置。例如192.168.1.1 + - upload\_net\_client\_ip:设置开发板的IP地址,工具会自动根据选择的upload\_net\_server\_ip进行设置。例如192.168.1.3 + + ![](figure/zh-cn_image_0000001117463460.png) + +8. 所有的配置都修改完成后,在工程配置页签的顶部,点击**Save**进行保存。 +9. 启动烧录后,显示如下提示信息时,请重启开发板(下电再上电)。 + + ![](figure/zh-cn_image_0000001114129432.png) + +10. 重新上电后,启动烧录,界面提示如下信息时,表示烧录成功。 + + ![](figure/zh-cn_image_0000001113969542.png) + + +## 下一步 + +恭喜!您已经完成了OpenHarmony标准系统的快速入门,接下来可[开发一个小示例](../guide/device-clock-guide.md),进一步熟悉OpenHarmony的开发。 + diff --git a/zh-cn/device-dev/quick-start/quickstart-standard-docker-environment.md b/zh-cn/device-dev/quick-start/quickstart-standard-docker-environment.md new file mode 100644 index 0000000000..6f3ed7f03f --- /dev/null +++ b/zh-cn/device-dev/quick-start/quickstart-standard-docker-environment.md @@ -0,0 +1,118 @@ +# 搭建Ubuntu环境及编译(Docker方式) + +- [获取标准系统源码](#section8761819202511) + - [前提条件](#section102871547153314) + - [操作步骤](#section429012478331) + +- [获取Docker环境](#section181431248132513) +- [编译](#section92391739152318) + +OpenHarmony标准系统为开发者提供的Docker环境已经将对应的编译工具链进行了封装,开发者可省略对应工具的安装。 + +>![](../public_sys-resources/icon-note.gif) **说明:** +>- 在使用Docker前需要先安装Docker,Docker安装请参考[官方指导](https://docs.docker.com/engine/install/ubuntu/)。 +>- Docker方式和安装包方式二选一即可。选择Docker方式的开发者可跳过[安装包方式](quickstart-standard-package-environment.md)的内容。 + +## 获取标准系统源码 + +### 前提条件 + +1. 注册码云gitee账号。 +2. 注册码云SSH公钥,请参考[码云帮助中心](https://gitee.com/help/articles/4191)。 +3. 安装[git客户端](http://git-scm.com/book/zh/v2/%E8%B5%B7%E6%AD%A5-%E5%AE%89%E8%A3%85-Git)和[git-lfs](https://gitee.com/vcs-all-in-one/git-lfs?_from=gitee_search#downloading))并配置用户信息。 + + ``` + git config --global user.name "yourname" + git config --global user.email "your-email-address" + git config --global credential.helper store + ``` + +4. 安装码云repo工具,可以执行如下命令。 + + ``` + curl -s https://gitee.com/oschina/repo/raw/fork_flow/repo-py3 > /usr/local/bin/repo #如果没有权限,可下载至其他目录,并将其配置到环境变量中 + chmod a+x /usr/local/bin/repo + pip3 install -i https://repo.huaweicloud.com/repository/pypi/simple requests + ``` + + +### 操作步骤 + +方式一(推荐):通过repo + ssh 下载(需注册公钥,请参考[码云帮助中心](https://gitee.com/help/articles/4191))。 + +``` +repo init -u git@gitee.com:openharmony/manifest.git -b master --no-repo-verify +repo sync -c +repo forall -c 'git lfs pull' +``` + +方式二:通过repo + https 下载。 + +``` +repo init -u https://gitee.com/openharmony/manifest.git -b master --no-repo-verify +repo sync -c +repo forall -c 'git lfs pull' +``` + +## 获取Docker环境 + +**方式一:从HuaweiCloud SWR上直接获取Docker镜像进行构建:** + +1. 获取Docker镜像。 + + ``` + docker pull swr.cn-south-1.myhuaweicloud.com/openharmony-docker/openharmony-docker-standard:0.0.1 + ``` + +2. 进入OpenHarmony代码根目录执行如下命令,从而进入Docker构建环境。 + + ``` + docker run -it -v $(pwd):/home/openharmony swr.cn-south-1.myhuaweicloud.com/openharmony-docker/openharmony-docker-standard:0.0.1 + ``` + + +**方式二:通过Dockerfile 构建本地Docker镜像进行构建** + +1. 获取Dockerfile脚本文件,用来构建本地Docker镜像。 + + ``` + git clone https://gitee.com/openharmony/docs.git + ``` + +2. 进入Dockerfile代码目录路径执行Docker镜像构建命令。 + + ``` + cd docs/docker/standard + ./build.sh + ``` + +3. 进入OpenHarmony代码根目录执行如下命令,从而进入Docker构建环境。 + + ``` + docker run -it -v $(pwd):/home/openharmony openharmony-docker-standard:0.0.1 + ``` + + +## 编译 + +1. 在源码的根目录执行预处理脚本。 + + ``` + ../scripts/prepare.sh + ``` + +2. 通过如下编译脚本启动标准系统类设备(参考内存≥128MB)的编译。 + + ``` + ./build.sh --product-name {product_name} + ``` + + \{product\_name\}为当前版本支持的平台,比如:Hi3516DV300 + + 编译所生成的文件都归档在out/ohos-arm-release/目录下,结果镜像输出在 out/ohos-arm-release/packages/phone/images/ 目录下。 + +3. 编译源码完成,请进行镜像烧录,具体请参见[镜像烧录](quickstart-standard-burn.md)。 + +>![](../public_sys-resources/icon-note.gif) **说明:** +>退出Docker执行exit命令即可。 + diff --git "a/zh-cn/device-dev/quick-start/\345\270\270\350\247\201\351\227\256\351\242\230-8.md" b/zh-cn/device-dev/quick-start/quickstart-standard-faq.md similarity index 100% rename from "zh-cn/device-dev/quick-start/\345\270\270\350\247\201\351\227\256\351\242\230-8.md" rename to zh-cn/device-dev/quick-start/quickstart-standard-faq.md diff --git a/zh-cn/device-dev/quick-start/quickstart-standard-package-environment.md b/zh-cn/device-dev/quick-start/quickstart-standard-package-environment.md new file mode 100644 index 0000000000..d35cc27499 --- /dev/null +++ b/zh-cn/device-dev/quick-start/quickstart-standard-package-environment.md @@ -0,0 +1,98 @@ +# 搭建Ubuntu环境及编译(安装包方式) + +- [安装依赖工具](#section18431165519244) +- [获取标准系统源码](#section113751052102517) + - [前提条件](#section102871547153314) + - [操作步骤](#section429012478331) + +- [执行prebuilts](#section0495320152619) +- [编译](#section1664835963517) + +## 安装依赖工具 + +安装命令如下: + +``` +sudo apt-get update && sudo apt-get install binutils git git-lfs gnupg flex bison gperf build-essential zip curl zlib1g-dev gcc-multilib g++-multilib libc6-dev-i386 lib32ncurses5-dev x11proto-core-dev libx11-dev lib32z1-dev ccache libgl1-mesa-dev libxml2-utils xsltproc unzip m4 bc gnutls-bin python3.8 python3-pip +``` + +>![](../public_sys-resources/icon-note.gif) **说明:** +>以上安装命令适用于Ubuntu18.04,其他版本请根据安装包名称采用对应的安装命令。 + +## 获取标准系统源码 + +### 前提条件 + +1. 注册码云gitee账号。 +2. 注册码云SSH公钥,请参考[码云帮助中心](https://gitee.com/help/articles/4191)。 +3. 安装[git客户端](http://git-scm.com/book/zh/v2/%E8%B5%B7%E6%AD%A5-%E5%AE%89%E8%A3%85-Git)和[git-lfs](https://gitee.com/vcs-all-in-one/git-lfs?_from=gitee_search#downloading))并配置用户信息。 + + ``` + git config --global user.name "yourname" + git config --global user.email "your-email-address" + git config --global credential.helper store + ``` + +4. 安装码云repo工具,可以执行如下命令。 + + ``` + curl -s https://gitee.com/oschina/repo/raw/fork_flow/repo-py3 > /usr/local/bin/repo #如果没有权限,可下载至其他目录,并将其配置到环境变量中 + chmod a+x /usr/local/bin/repo + pip3 install -i https://repo.huaweicloud.com/repository/pypi/simple requests + ``` + + +### 操作步骤 + +方式一(推荐):通过repo + ssh 下载(需注册公钥,请参考[码云帮助中心](https://gitee.com/help/articles/4191))。 + +``` +repo init -u git@gitee.com:openharmony/manifest.git -b master --no-repo-verify +repo sync -c +repo forall -c 'git lfs pull' +``` + +方式二:通过repo + https 下载。 + +``` +repo init -u https://gitee.com/openharmony/manifest.git -b master --no-repo-verify +repo sync -c +repo forall -c 'git lfs pull' +``` + +## 执行prebuilts + +在源码根目录下执行脚本,安装编译器及二进制工具。 + +``` +bash build/prebuilts_download.sh +``` + +下载的prebuilts二进制默认存放在与OpenHarmony同目录下的OpenHarmony\_2.0\_canary\_prebuilts下。 + +## 编译 + +在Linux环境进行如下操作: + +1. 进入源码根目录,执行如下命令进行版本编译。 + + ``` + ./build.sh --product-name {product_name} + ``` + + \{product\_name\}为当前版本支持的平台,比如:Hi3516DV300 + +2. 检查编译结果。编译完成后,log中显示如下: + + ``` + build system image successful. + =====build Hi3516DV300 successful. + ``` + + 编译所生成的文件都归档在out/ohos-arm-release/目录下,结果镜像输出在 out/ohos-arm-release/packages/phone/images/ 目录下。 + + >![](../public_sys-resources/icon-note.gif) **说明:** + >其他模块化编译操作,可参见[编译构建指导](../subsystems/subsys-build-standard-large.md)。 + +3. 编译源码完成,请进行镜像烧录,具体请参见[镜像烧录](quickstart-standard-burn.md)。 + diff --git a/zh-cn/device-dev/quick-start/quickstart-standard-windows-environment.md b/zh-cn/device-dev/quick-start/quickstart-standard-windows-environment.md new file mode 100644 index 0000000000..bf45ab1684 --- /dev/null +++ b/zh-cn/device-dev/quick-start/quickstart-standard-windows-environment.md @@ -0,0 +1,179 @@ +# Windows开发环境准备 + +- [获取软件](#zh-cn_topic_0000001058091994_section1483143015558) +- [安装Visual Studio Code](#zh-cn_topic_0000001058091994_section71401018163318) +- [安装Python](#zh-cn_topic_0000001058091994_section16266553175320) +- [安装Node.js](#zh-cn_topic_0000001058091994_section5353233124511) +- [安装hpm](#zh-cn_topic_0000001058091994_section173054793610) +- [安装DevEco Device Tool插件](#zh-cn_topic_0000001058091994_section4336315185716) + +系统要求:Windows 10 64位系统。 + +DevEco Device Tool以插件方式提供,基于Visual Studio Code进行扩展,安装分为如下几步: + +1. 安装Visual Studio Code +2. 安装Python +3. 安装Node.js +4. 安装hpm +5. 安装DevEco Device Tool插件 + +## 获取软件 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    工具名称

    +

    用途说明

    +

    版本要求

    +

    获取渠道

    +

    Visual Studio Code

    +

    代码编辑工具

    +

    V1.53及以上 64位版本。

    +

    https://code.visualstudio.com/Download

    +

    Python

    +

    编译构建工具

    +

    V3.7.4~V3.8.x 64位版本

    +

    https://www.python.org/downloads/

    +

    Node.js

    +

    提供npm环境

    +

    v12.0.0及以上 64位版本

    +

    https://nodejs.org/zh-cn/download/

    +

    hpm

    +

    包管理工具

    +

    最新版

    +

    请参考安装hpm

    +

    DevEco Device Tool

    +

    OpenHarmony源码的编译、烧录、调试插件工具

    +

    v2.2 Beta1

    +

    https://device.harmonyos.com/cn/ide#download

    +

    下载前,请使用华为开发者帐号登录,如未注册,请先注册华为开发者帐号

    +
    + +## 安装Visual Studio Code + +>![](../public_sys-resources/icon-note.gif) **说明:** +>如果已安装Visual Studio Code,打开命令行工具,输入**code --version**命令,检查版本号是否为1.53及以上版本;可以正常返回版本号,说明环境变量设置也正确。 + +1. 双击Visual Studio Code软件包进行安装。安装过程中,请勾选“添加到PATH(重启后生效)”。 + + ![](figure/zh-cn_image_0000001057335403.png) + +2. 安装完成后,打开命令行工具,输入**code --version**命令,可以正常显示版本号说明安装成功。 + +## 安装Python + +>![](../public_sys-resources/icon-note.gif) **说明:** +>请注意,Python版本要求为V3.7.4\~V3.8.x 64位版本。 + +1. 双击Python安装包进行安装,勾选“**Add Python 3.8 to PATH**”,然后点击**Install Now**开始安装。 + + ![](figure/zh-cn_image_0000001176317561.png) + +2. 等待安装完成后,点击**Close**。 + + ![](figure/zh-cn_image_0000001142794291.png) + +3. 打开命令行工具,输入python --version,检查安装结果。 + + ![](figure/zh-cn_image_0000001130278040.png) + +4. 在命令行工具中,分别执行如下命令设置pip源,用于后续安装DevEco Device Tool过程中下载依赖的组件包。 + + ``` + pip config set global.trusted-host repo.huaweicloud.com + pip config set global.index-url https://repo.huaweicloud.com/repository/pypi/simple + pip config set global.timeout 120 + ``` + + +## 安装Node.js + +>![](../public_sys-resources/icon-note.gif) **说明:** +>如果已安装Node.js,打开命令行工具,输入**node -v**命令,检查版本号是否为12.0.0及以上版本。 + +1. 点击下载后的软件包进行安装,全部按照默认设置点击**Next**,直至**Finish**。安装过程中,Node.js会自动在系统的path环境变量中配置node.exe的目录路径。 +2. 重新打开命令行工具,输入“node -v“命令,能正常查询Node.js的版本号,说明Node.js安装成功。 + +## 安装hpm + +该方式需先确保**Node.js**安装成功。 + +在安装hpm前,请检查网络连接状态,如果网络不能直接访问Internet,则需要通过代理服务器才可以访问。这种情况下,需要先[设置npm代理](https://device.harmonyos.com/cn/docs/ide/user-guides/npm_proxy-0000001054491032),才能安装hpm。 + +>![](../public_sys-resources/icon-note.gif) **说明:** +>如果已安装hpm,可以执行**npm update -g @ohos/hpm-cli**命令升级hpm至最新版本。 + +1. 建议将npm源配置为国内镜像,例如设置为华为云镜像源。 + + ``` + npm config set registry https://repo.huaweicloud.com/repository/npm/ + ``` + +2. 打开命令行工具,执行如下命令安装最新版本hpm。 + + ``` + npm install -g @ohos/hpm-cli + ``` + + ![](figure/zh-cn_image_0000001073840162.png) + +3. 安装完成后,执行如下命令(V为大写字母)检查hpm安装结果。 + + ``` + hpm -V + ``` + + +## 安装DevEco Device Tool插件 + +安装DevEco Device Tool插件,**主机的用户名不能包含中文字符**,否则可能导致运行出现错误。 + +DevEco Device Tool正常运行需要依赖于C/C++和CodeLLDB插件,在安装完DevEco Device Tool后,会自动从Visual Studio Code的插件市场安装C/C++和CodeLLDB插件。因此,在安装DevEco Device Tool前,请检查Visual Studio Code的网络连接状态,如果网络不能直接访问Internet,则需要通过代理服务器才可以访问,请先[Visual Studio Code代理设置](https://device.harmonyos.com/cn/docs/ide/user-guides/vscode_proxy-0000001074231144)。 + +>![](../public_sys-resources/icon-note.gif) **说明:** +>安装DevEco Device Tool时,请先关闭Visual Studio Code。 + +1. 解压DevEco Device Tool插件压缩包,双击安装包程序进行安装。 +2. 安装过程中,会自动安装DevEco Device Tool所需的依赖文件(如C/C++和CodeLLDB插件)和执行程序。 + + ![](figure/zh-cn_image_0000001072468991.png) + +3. 安装完成后,会自动关闭命令行工具窗口。 +4. 启动Visual Studio Code,点击左侧的![](figure/zh-cn_image_0000001072757874.png)按钮,检查INSTALLED中,是否已成功安装C/C++、CodeLLDB和DevEco Device Tool。 + + >![](../public_sys-resources/icon-note.gif) **说明:** + >如果C/C++和CodeLLDB插件安装不成功,则DevEco Device Tool不能正常运行,解决方法,详细请参考:[离线安装C/C++和CodeLLDB插件](https://device.harmonyos.com/cn/docs/ide/user-guides/offline_plugin_install-0000001074376846)。 + + ![](figure/zh-cn_image_0000001142802505.png) + + diff --git a/zh-cn/device-dev/quick-start/quickstart-standard.md b/zh-cn/device-dev/quick-start/quickstart-standard.md new file mode 100644 index 0000000000..3931c32643 --- /dev/null +++ b/zh-cn/device-dev/quick-start/quickstart-standard.md @@ -0,0 +1,15 @@ +# 标准系统入门 + +- **[常见问题](quickstart-lite-env-setup-faqs.md)** + +- **[Windows开发环境准备](quickstart-standard-windows-environment.md)** + +- **[搭建Ubuntu环境及编译(Docker方式)](quickstart-standard-docker-environment.md)** + +- **[搭建Ubuntu环境及编译(安装包方式)](quickstart-standard-package-environment.md)** + +- **[镜像烧录](quickstart-standard-burn.md)** + +- **[常见问题](quickstart-standard-faq.md)** + + diff --git a/zh-cn/device-dev/quick-start/quickstart.md b/zh-cn/device-dev/quick-start/quickstart.md new file mode 100644 index 0000000000..5ab9867ff4 --- /dev/null +++ b/zh-cn/device-dev/quick-start/quickstart.md @@ -0,0 +1,7 @@ +# 快速入门 + +- **[轻量和小型系统入门](quickstart-lite.md)** + +- **[标准系统入门](quickstart-standard.md)** + + diff --git "a/zh-cn/device-dev/quick-start/\344\272\206\350\247\243\345\274\200\345\217\221\346\235\277.md" "b/zh-cn/device-dev/quick-start/\344\272\206\350\247\243\345\274\200\345\217\221\346\235\277.md" deleted file mode 100755 index fae4d8bb46..0000000000 --- "a/zh-cn/device-dev/quick-start/\344\272\206\350\247\243\345\274\200\345\217\221\346\235\277.md" +++ /dev/null @@ -1,9 +0,0 @@ -# 了解开发板 - -- **[Hi3861开发板介绍](Hi3861开发板介绍.md)** - -- **[Hi3516开发板介绍](Hi3516开发板介绍.md)** - -- **[Hi3518开发板介绍](Hi3518开发板介绍.md)** - - diff --git "a/zh-cn/device-dev/quick-start/\345\205\245\351\227\250\344\273\213\347\273\215.md" "b/zh-cn/device-dev/quick-start/\345\205\245\351\227\250\344\273\213\347\273\215.md" deleted file mode 100644 index 3e0807591c..0000000000 --- "a/zh-cn/device-dev/quick-start/\345\205\245\351\227\250\344\273\213\347\273\215.md" +++ /dev/null @@ -1,54 +0,0 @@ -# 入门介绍 - -- [快速入门流程](#section7825218111517) -- [开发板简介](#zh-cn_topic_0000001053666242_section047719215429) -- [开发板规格](#zh-cn_topic_0000001053666242_section15192203316533) - -开发者可通过本文快速掌握OpenHarmony标准系统的环境搭建、编译、烧录、启动等操作。标准系统可以使用Windows环境进行开发、烧录,使用Linux环境进行编译。 - -本文将以当前推荐的Hi3516DV300开发板为例对上述操作进行说明。 - -## 快速入门流程 - -标准系统快速入门流程如下图所示,其中“搭建Ubuntu环境及编译”环节可根据实际情况选择docker方式或工具包方式其中一种即可。 - -**图 1** 标准环境快速入门流程 -![](figures/标准环境快速入门流程.png "标准环境快速入门流程") - -## 开发板简介 - -Hi3516DV300作为新一代行业专用Smart HD IP摄像机SOC,集成新一代ISP\(Image Signal Processor\)、H.265视频压缩编码器,同时集成高性能NNIE引擎,使得Hi3516DV300在低码率、高画质、智能处理和分析、低功耗等方面引领行业水平。 - -**图 2** Hi3516单板正面外观图 - - -![](figures/3516正面-16.png) - -## 开发板规格 - -**表 1** Hi3516开发板规格清单 - - - - - - - - - - - - - -

    规格类型

    -

    规格清单

    -

    处理器及内部存储

    -
    • Hi3516DV300芯片
    • DDR3 1GB
    • eMMC4.5,8GB容量
    -

    外部器件

    -
    • 以太网口
    • 音频视频
      • 1路语音输入
      • 1路单声道(AC_L)输出,接3W功放(LM4871)
      • MicroHDMI(1路HDMI 1.4)
      -
    • 摄像头
      • 传感器IMX335
      • 镜头M12,焦距4mm,光圈1.8
      -
    • 显示屏
      • LCD连接器(2.35寸)
      • LCD连接器(5.5寸)
      -
    • 外部器件及接口
      • SD卡接口
      • JTAG/I2S 接口
      • ADC接口
      • 舵机接口
      • Grove连接器
      • USB2.0(Type C)
      • 功能按键3个,2个用户自定义按键,1个升级按键
      • LED指示灯,绿灯,红灯
      -
    -
    - diff --git "a/zh-cn/device-dev/quick-start/\345\256\211\350\243\205\345\274\200\345\217\221\346\235\277\347\216\257\345\242\203-2.md" "b/zh-cn/device-dev/quick-start/\345\256\211\350\243\205\345\274\200\345\217\221\346\235\277\347\216\257\345\242\203-2.md" deleted file mode 100644 index 3f827074bf..0000000000 --- "a/zh-cn/device-dev/quick-start/\345\256\211\350\243\205\345\274\200\345\217\221\346\235\277\347\216\257\345\242\203-2.md" +++ /dev/null @@ -1,122 +0,0 @@ -# 安装开发板环境 - -- [Hi3516工具要求](#section179175261196) - - [硬件要求](#section5840424125014) - - [软件要求](#section965634210501) - -- [安装Linux服务器工具](#section182916865219) - - [将Linux shell改为bash](#section1715027152617) - - [安装编译依赖基础软件(仅Ubuntu 20+需要)](#section45512412251) - - [安装文件打包工具及Java虚拟机环境](#section16199102083717) - - -## Hi3516工具要求 - -### 硬件要求 - -- Hi3516DV300 IoT Camera开发板 -- USB转串口线、网线(Windows工作台通过USB转串口线、网线与Hi3516DV300 开发板连接) - -各硬件连接关系如下图所示。 - -**图 1** 硬件连线图 - - -![](figures/矩形备份-292.png) - -### 软件要求 - ->![](public_sys-resources/icon-notice.gif) **须知:** ->本节描述安装包方式搭建编译环境的操作步骤。如果是Docker方式安装编译环境,请跳过此章节以及下述[安装Linux服务器工具](#section182916865219)章节。 - -Hi3516开发板对Linux服务器通用环境配置需要的工具及其获取途径如下表所示。 - -**表 1** Linux服务器开发工具及获取途径 - - - - - - - - - - - - - - - - - - - - - - - - -

    开发工具

    -

    用途

    -

    获取途径

    -

    bash

    -

    命令行处理工具

    -

    系统配置

    -

    编译基础软件包(仅ubuntu 20+需要)

    -

    编译依赖的基础软件包

    -

    通过互联网获取

    -

    dosfstools、mtools、mtd-utils

    -

    文件打包工具

    -

    通过apt-get install安装

    -

    Java 虚拟机环境

    -

    编译、调试和运行Java程序

    -

    通过apt-get install安装

    -
    - -## 安装Linux服务器工具 - ->![](public_sys-resources/icon-notice.gif) **须知:** ->- 如果通过“HPM组件方式”或“HPM包管理器命令行工具方式”获取源码,不需要安装LLVM、hc-gen编译工具。 ->- (推荐)如果通过“镜像站点方式”或“代码仓库方式”获取源码,需要安装hc-gen编译工具。安装hc-gen编译工具时,请确保编译工具的环境变量路径唯一。 - -### 将Linux shell改为bash - -查看shell是否为bash,在终端运行如下命令 - -``` -ls -l /bin/sh -``` - -如果显示为“/bin/sh -\> bash”则为正常,否则请按以下方式修改: - -**方法一**:在终端运行如下命令,然后选择 no。 - -``` -sudo dpkg-reconfigure dash -``` - -**方法二**:先删除sh,再创建软链接。 - -``` -sudo rm -rf /bin/sh -sudo ln -s /bin/bash /bin/sh -``` - -### 安装编译依赖基础软件(仅Ubuntu 20+需要) - -执行以下命令进行安装: - -``` -sudo apt-get install build-essential gcc g++ make zlib* libffi-dev -``` - -### 安装文件打包工具及Java虚拟机环境 - -1. 打开Linux编译服务器终端 -2. 运行如下命令,安装dosfstools,mtools,mtd-utils,Java运行时环境(JRE)和Java sdk 开发工具包。 - - ``` - sudo apt-get install dosfstools mtools mtd-utils default-jre default-jdk - ``` - - diff --git "a/zh-cn/device-dev/quick-start/\345\256\211\350\243\205\345\274\200\345\217\221\346\235\277\347\216\257\345\242\203-4.md" "b/zh-cn/device-dev/quick-start/\345\256\211\350\243\205\345\274\200\345\217\221\346\235\277\347\216\257\345\242\203-4.md" deleted file mode 100644 index b2bbd77880..0000000000 --- "a/zh-cn/device-dev/quick-start/\345\256\211\350\243\205\345\274\200\345\217\221\346\235\277\347\216\257\345\242\203-4.md" +++ /dev/null @@ -1,114 +0,0 @@ -# 安装开发板环境 - -- [Hi3518环境搭建](#section1724111409282) - - [硬件要求](#section487353718276) - - [软件要求](#section17315193935817) - -- [安装Linux服务器工具](#section8831868501) - - [将Linux shell改为bash](#section434110241084) - - [安装编译依赖基础软件(仅Ubuntu 20+需要)](#section25911132141020) - - [安装文件打包工具](#section390214473129) - - -## Hi3518环境搭建 - -### 硬件要求 - -- Hi3518EV300 IoT Camera开发板 -- USB转串口线、网线(Windows工作台通过USB转串口线、网线与开发板连接) - - 各硬件连接关系如下图所示。 - - -**图 1** 硬件连线图 -![](figures/硬件连线图-3.png "硬件连线图-3") - -### 软件要求 - ->![](public_sys-resources/icon-notice.gif) **须知:** ->本节描述安装包方式搭建编译环境的操作步骤。如果是Docker方式安装编译环境,请跳过此章节以及下述[安装Linux服务器工具](#section8831868501)章节。 - -Hi3518开发板对Linux服务器通用环境配置需要的工具及其获取途径如下表所示。 - -**表 1** Linux服务器开发工具及获取途径 - - - - - - - - - - - - - - - - - - - - -

    开发工具

    -

    用途

    -

    获取途径

    -

    bash

    -

    命令行处理工具

    -

    系统配置

    -

    编译基础软件包(仅ubuntu 20+需要)

    -

    编译依赖的基础软件包

    -

    通过互联网获取

    -

    dosfstools、mtools、mtd-utils

    -

    文件打包工具

    -

    通过apt-get install安装

    -
    - -## 安装Linux服务器工具 - ->![](public_sys-resources/icon-notice.gif) **须知:** ->- 如果通过“HPM组件方式”或“HPM包管理器命令行工具方式”获取源码,不需要安装hc-gen编译工具。 ->- (推荐)如果通过“镜像站点方式”或“代码仓库方式”获取源码,需要安装hc-gen编译工具。安装hc-gen编译工具时,请确保编译工具的环境变量路径唯一。 - -### 将Linux shell改为bash - -查看shell是否为bash,在终端运行如下命令 - -``` -ls -l /bin/sh -``` - -如果显示为“/bin/sh -\> bash”则为正常,否则请按以下方式修改: - -**方法一**:在终端运行如下命令,然后选择 no。 - -``` -sudo dpkg-reconfigure dash -``` - -**方法二**:先删除sh,再创建软链接。 - -``` -sudo rm -rf /bin/sh -sudo ln -s /bin/bash /bin/sh -``` - -### 安装编译依赖基础软件(仅Ubuntu 20+需要) - -执行以下命令进行安装: - -``` -sudo apt-get install build-essential gcc g++ make zlib* libffi-dev -``` - -### 安装文件打包工具 - -1. 打开Linux编译服务器终端。 -2. 运行如下命令,安装dosfstools,mtools,mtd-utils。 - - ``` - sudo apt-get install dosfstools mtools mtd-utils - ``` - - diff --git "a/zh-cn/device-dev/quick-start/\345\256\211\350\243\205\345\274\200\345\217\221\346\235\277\347\216\257\345\242\203.md" "b/zh-cn/device-dev/quick-start/\345\256\211\350\243\205\345\274\200\345\217\221\346\235\277\347\216\257\345\242\203.md" deleted file mode 100644 index 2bf84d7aab..0000000000 --- "a/zh-cn/device-dev/quick-start/\345\256\211\350\243\205\345\274\200\345\217\221\346\235\277\347\216\257\345\242\203.md" +++ /dev/null @@ -1,367 +0,0 @@ -# 安装开发板环境 - -- [Hi3861工具要求](#section466851916410) - - [硬件要求](#section19202111020215) - - [软件要求](#section727451210318) - -- [安装Linux编译工具](#section497484245614) - - [安装编译依赖基础软件(仅Ubuntu 20+需要)](#section45512412251) - - [安装Scons](#section7438245172514) - - [安装python模块](#section88701892341) - - [安装gcc\_riscv32(WLAN模组类编译工具链)](#section34435451256) - -- [安装USB转串口驱动](#section1027732411513) - -## Hi3861工具要求 - -### 硬件要求 - -- Linux服务器 -- Windows工作台(主机电脑) -- Hi3861 WLAN模组 -- USB Type-C线(Windows工作台通过USB与Hi3861 WLAN模组连接) - -各硬件连接关系如下图所示。 - -**图 1** 硬件连线图 -![](figures/硬件连线图.png "硬件连线图") - -### 软件要求 - ->![](public_sys-resources/icon-notice.gif) **须知:** ->本节描述采用安装包方式安装相关工具的操作步骤。如果是Docker方式安装,无需安装[表1](#table6299192712513)中的Linux服务器相关工具,只需安装Windows工作台工具即可。 - -Hi3861开发板需要的工具如下表所示。 - -**表 1** Hi3861开发板需要的工具 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    平台类型

    -

    开发工具

    -

    用途

    -

    获取途径

    -

    Linux服务器

    -

    编译基础软件包(仅ubuntu 20+需要)

    -

    编译依赖的基础软件包

    -

    通过互联网获取

    -

    Linux服务器

    -

    SCons3.0.4+

    -

    编译构建工具

    -

    通过互联网获取

    -

    Linux服务器

    -

    python模块:setuptools、kconfiglib、pycryptodome、six、ecdsa

    -

    编译构建工具

    -

    通过互联网获取

    -

    Linux服务器

    -

    gcc riscv32

    -

    编译构建工具

    -

    通过互联网获取

    -

    Windows工作台

    -

    CH341SER.EXE

    -

    USB转串口驱动

    -

    http://www.wch.cn/search?q=ch340g&t=downloads

    -
    - -## 安装Linux编译工具 - ->![](public_sys-resources/icon-notice.gif) **须知:** ->- 如果通过“HPM组件方式”或“HPM包管理器命令行工具方式”获取源码,不需要安装gcc\_riscv32编译工具。 ->- (推荐)如果通过“镜像站点方式”或“代码仓库方式”获取源码,需要安装gcc\_riscv32编译工具。安装gcc\_riscv32编译工具时,请确保编译工具的环境变量路径唯一。 - -### 安装编译依赖基础软件(仅Ubuntu 20+需要) - -执行以下命令进行安装: - -``` -sudo apt-get install build-essential gcc g++ make zlib* libffi-dev -``` - -### 安装Scons - -1. 打开Linux编译服务器终端。 -2. 运行如下命令,安装SCons安装包。 - - ``` - python3 -m pip install scons - ``` - -3. 运行如下命令,查看是否安装成功。如果安装成功,查询结果下图所示。 - - ``` - scons -v - ``` - - **图 2** SCons安装成功界面,版本要求3.0.4以上 - ![](figures/SCons安装成功界面-版本要求3-0-4以上.png "SCons安装成功界面-版本要求3-0-4以上") - - -### 安装python模块 - -1. 运行如下命令,安装python模块setuptools。 - - ``` - pip3 install setuptools - ``` - -2. 安装GUI menuconfig工具(Kconfiglib),建议安装Kconfiglib 13.2.0+版本,任选如下一种方式。 - - **命令行方式:** - - ``` - sudo pip3 install kconfiglib - ``` - - - - **安装包方式:** - 1. 下载.whl文件(例如:kconfiglib-13.2.0-py2.py3-none-any.whl)。 - - 下载路径:“[https://pypi.org/project/kconfiglib\#files](https://pypi.org/project/kconfiglib#files)” - - - 1. 运行如下命令,安装.whl文件。 - - ``` - sudo pip3 install kconfiglib-13.2.0-py2.py3-none-any.whl - ``` - - - -3. 安装pycryptodome,任选如下一种方式。 - - 安装升级文件签名依赖的Python组件包,包括:pycryptodome、six、ecdsa。安装ecdsa依赖six,请先安装six,再安装ecdsa。 - - - **命令行方式:** - - ``` - sudo pip3 install pycryptodome - ``` - - - **安装包方式:** - 1. 下载.whl文件(例如:pycryptodome-3.9.9-cp38-cp38-manylinux1\_x86\_64.whl)。 - - 下载路径:“[https://pypi.org/project/pycryptodome/\#files](https://pypi.org/project/pycryptodome/#files)”。 - - - 1. 运行如下命令,安装.whl文件。 - - ``` - sudo pip3 install pycryptodome-3.9.9-cp38-cp38-manylinux1_x86_64.whl - ``` - - - -4. 安装six,任选如下一种方式。 - - **命令行方式:** - - ``` - sudo pip3 install six --upgrade --ignore-installed six - ``` - - - - **安装包方式:** - 1. 下载.whl文件(例如:six-1.12.0-py2.py3-none-any.whl)。 - - 下载路径:“[https://pypi.org/project/six/\#files](https://pypi.org/project/six/#files)” - - - 1. 运行如下命令,安装.whl文件。 - - ``` - sudo pip3 install six-1.12.0-py2.py3-none-any.whl - ``` - - - -5. 安装ecdsa,任选如下一种方式。 - - **命令行方式:** - - ``` - sudo pip3 install ecdsa - ``` - - - **安装包方式:** - 1. 下载.whl文件(例如:ecdsa-0.14.1-py2.py3-none-any.whl)。 - - 下载路径:“[https://pypi.org/project/ecdsa/\#files](https://pypi.org/project/ecdsa/#files)” - - - 1. 运行如下命令,安装.whl文件。 - - ``` - sudo pip3 install ecdsa-0.14.1-py2.py3-none-any.whl - ``` - - - - -### 安装gcc\_riscv32(WLAN模组类编译工具链) - ->![](public_sys-resources/icon-notice.gif) **须知:** ->- Hi3861平台仅支持使用libgcc运行时库的静态链接,不建议开发者使用libgcc运行时库的动态链接,会导致商业分发时被GPL V3污染。 ->- 通过下述步骤2-15,我们编译好了gcc\_riscv32 镜像,提供给开发者[直接下载](https://repo.huaweicloud.com/harmonyos/compiler/gcc_riscv32/7.3.0/linux/gcc_riscv32-linux-7.3.0.tar.gz)使用。直接下载 gcc\_riscv32 镜像的开发者可省略下述2-15步。 - -1. 打开Linux编译服务器终端。 -2. 环境准备,请安装"gcc, g++, bison, flex, makeinfo"软件,确保工具链能正确编译。 - - ``` - sudo apt-get install gcc && sudo apt-get install g++ && sudo apt-get install flex bison && sudo apt-get install texinfo - ``` - -3. 下载riscv-gnu-toolchain交叉编译工具链。 - - ``` - git clone --recursive https://gitee.com/mirrors/riscv-gnu-toolchain.git - ``` - -4. 打开文件夹riscv-gnu-toolchain,先删除空文件夹,以防止下载newlib,binutils,gcc时冲突。 - - ``` - cd riscv-gnu-toolchain && rm -rf riscv-newlib && rm -rf riscv-binutils && rm -rf riscv-gcc - ``` - -5. 下载riscv-newlib-3.0.0。 - - ``` - git clone -b riscv-newlib-3.0.0 https://github.com/riscv/riscv-newlib.git - ``` - -6. 下载riscv-binutils-2.31.1。 - - ``` - git clone -b riscv-binutils-2.31.1 https://github.com/riscv/riscv-binutils-gdb.git - ``` - -7. 下载riscv-gcc-7.3.0。 - - ``` - git clone -b riscv-gcc-7.3.0 https://github.com/riscv/riscv-gcc - ``` - -8. 添加riscv-gcc-7.3.0补丁。 - - 访问gcc官方补丁链接[89411](https://gcc.gnu.org/git/?p=gcc.git;a=commitdiff;h=026216a753ef0a757a9e368a59fa667ea422cf09;hp=2a23a1c39fb33df0277abd4486a3da64ae5e62c2),[86724](https://gcc.gnu.org/git/?p=gcc.git;a=blobdiff;f=gcc/graphite.h;h=be0a22b38942850d88feb159603bb846a8607539;hp=4e0e58c60ab83f1b8acf576e83330466775fac17;hb=b1761565882ed6a171136c2c89e597bc4dd5b6bf;hpb=fbd5f023a03f9f60c6ae36133703af5a711842a3),按照补丁链接中要求的修改,手动将变更添加到对应的.c和.h文件中,注意由于patch版本与下载的gcc版本有所偏差,行数有可能对应不上,请自行查找patch中的关键字定位到对应行。 - -9. 下载[GMP 6.1.2](https://gmplib.org/download/gmp/gmp-6.1.2.tar.bz2),并解压安装。 - - ``` - tar -xvf gmp-6.1.2.tar.bz2 && mkdir build_gmp && cd build_gmp && ../gmp-6.1.2/configure --prefix=/usr/local/gmp-6.1.2 --disable-shared --enable-cxx && make && make install - ``` - -10. 下载[mpfr-4.0.2 ](https://www.mpfr.org/mpfr-4.0.2/mpfr-4.0.2.tar.gz),并解压安装。 - - ``` - tar -xvf mpfr-4.0.2.tar.gz && mkdir build_mpfr && cd build_mpfr && ../mpfr-4.0.2/configure --prefix=/usr/local/mpfr-4.0.2 --with-gmp=/usr/local/gmp-6.1.2 --disable-shared && make && make install - ``` - -11. 下载[mpc-1.1.0](https://ftp.gnu.org/gnu/mpc/mpc-1.1.0.tar.gz) ,并解压安装。 - - ``` - tar -xvf mpc-1.1.0.tar.gz && mkdir build_mpc && cd build_mpc && ../mpc-1.1.0/configure --prefix=/usr/local/mpc-1.1.0 --with-gmp=/usr/local/gmp-6.1.2 --with-mpfr=/usr/local/mpfr-4.0.2 --disable-shared && make && make install - ``` - -12. 打开文件夹riscv-gnu-toolchain,新建工具链输出目录。 - - ``` - cd /opt && mkdir gcc_riscv32 - ``` - -13. 编译binutils。 - - ``` - mkdir build_binutils && cd build_binutils && ../riscv-binutils-gdb/configure --prefix=/opt/gcc_riscv32 --target=riscv32-unknown-elf --with-arch=rv32imc --with-abi=ilp32 --disable-__cxa_atexit --disable-libgomp --disable-libmudflap --enable-libssp --disable-libstdcxx-pch --disable-nls --disable-shared --disable-threads --disable-multilib --enable-poison-system-directories --enable-languages=c,c++ --with-gnu-as --with-gnu-ld --with-newlib --with-system-zlib CFLAGS="-fstack-protector-strong -O2 -D_FORTIFY_SOURCE=2 -Wl,-z,relro,-z,now,-z,noexecstack -fPIE" CXXFLAGS="-fstack-protector-strong -O2 -D_FORTIFY_SOURCE=2 -Wl,-z,relro,-z,now,-z,noexecstack -fPIE" CXXFLAGS_FOR_TARGET="-Os -mcmodel=medlow -Wall -fstack-protector-strong -Wl,-z,relro,-z,now,-z,noexecstack -Wtrampolines -fno-short-enums -fno-short-wchar" CFLAGS_FOR_TARGET="-Os -mcmodel=medlow -Wall -fstack-protector-strong -Wl,-z,relro,-z,now,-z,noexecstack -Wtrampolines -fno-short-enums -fno-short-wchar" --bindir=/opt/gcc_riscv32/bin --libexecdir=/opt/gcc_riscv32/riscv32 --libdir=/opt/gcc_riscv32 --includedir=/opt/gcc_riscv32 && make -j16 && make install && cd .. - ``` - -14. 编译newlib。 - - ``` - mkdir build_newlib && cd build_newlib && ../riscv-newlib/configure --prefix=/opt/gcc_riscv32 --target=riscv32-unknown-elf --with-arch=rv32imc --with-abi=ilp32 --disable-__cxa_atexit --disable-libgomp --disable-libmudflap --enable-libssp --disable-libstdcxx-pch --disable-nls --disable-shared --disable-threads --disable-multilib --enable-poison-system-directories --enable-languages=c,c++ --with-gnu-as --with-gnu-ld --with-newlib --with-system-zlib CFLAGS="-fstack-protector-strong -O2 -D_FORTIFY_SOURCE=2 -Wl,-z,relro,-z,now,-z,noexecstack -fPIE" CXXFLAGS="-fstack-protector-strong -O2 -D_FORTIFY_SOURCE=2 -Wl,-z,relro,-z,now,-z,noexecstack -fPIE" \CXXFLAGS_FOR_TARGET="-Os -mcmodel=medlow -Wall -fstack-protector-strong -Wl,-z,relro,-z,now,-z,noexecstack -Wtrampolines -fno-short-enums -fno-short-wchar" CFLAGS_FOR_TARGET="-Os -mcmodel=medlow -Wall -fstack-protector-strong -Wl,-z,relro,-z,now,-z,noexecstack -Wtrampolines -fno-short-enums -fno-short-wchar" --bindir=/opt/gcc_riscv32/bin --libexecdir=/opt/gcc_riscv32 --libdir=/opt/gcc_riscv32 --includedir=/opt/gcc_riscv32 && make -j16 && make install && cd .. - ``` - -15. 编译gcc。 - - ``` - mkdir build_gcc && cd build_gcc && ../riscv-gcc/configure --prefix=/opt/gcc_riscv32 --target=riscv32-unknown-elf --with-arch=rv32imc --with-abi=ilp32 --disable-__cxa_atexit --disable-libgomp --disable-libmudflap --enable-libssp --disable-libstdcxx-pch --disable-nls --disable-shared --disable-threads --disable-multilib --enable-poison-system-directories --enable-languages=c,c++ --with-gnu-as --with-gnu-ld --with-newlib --with-system-zlib CFLAGS="-fstack-protector-strong -O2 -D_FORTIFY_SOURCE=2 -Wl,-z,relro,-z,now,-z,noexecstack -fPIE" CXXFLAGS="-fstack-protector-strong -O2 -D_FORTIFY_SOURCE=2 -Wl,-z,relro,-z,now,-z,noexecstack -fPIE" LDFLAGS="-Wl,-z,relro,-z,now,-z,noexecstack" CXXFLAGS_FOR_TARGET="-Os -mcmodel=medlow -Wall -fstack-protector-strong -Wl,-z,relro,-z,now,-z,noexecstack -Wtrampolines -fno-short-enums -fno-short-wchar" CFLAGS_FOR_TARGET="-Os -mcmodel=medlow -Wall -fstack-protector-strong -Wl,-z,relro,-z,now,-z,noexecstack -Wtrampolines -fno-short-enums -fno-short-wchar" --with-headers="/opt/gcc-riscv32/riscv32-unknown-elf/include" --with-mpc=/usr/local/mpc-1.1.0 --with-gmp=/usr/local/gmp-6.1.2 --with-mpfr=/usr/local/mpfr-4.0.2 && make -j16 && make install - ``` - -16. 设置环境变量。 - - >![](public_sys-resources/icon-note.gif) **说明:** - >如果直接采用编译好的riscv32 gcc包,请参照如下步骤设置环境变量: - >1. 将压缩包解压到根目录 - > ``` - > tar -xvf gcc_riscv32-linux-7.3.0.tar.gz -C ~ - > ``` - >2. 设置环境变量。 - > ``` - > vim ~/.bashrc - > ``` - >3. 将以下命令拷贝到.bashrc文件的最后一行,保存并退出。 - > ``` - > export PATH=~/gcc_riscv32/bin:$PATH - > ``` - - ``` - vim ~/.bashrc - ``` - - 将以下命令拷贝到.bashrc文件的最后一行,保存并退出。 - - ``` - export PATH=~/gcc_riscv32/bin:$PATH - ``` - -17. 生效环境变量。 - - ``` - source ~/.bashrc - ``` - -18. Shell命令行中输入如下命令,如果能正确显示编译器版本号,表明编译器安装成功。 - - ``` - riscv32-unknown-elf-gcc -v - ``` - - -## 安装USB转串口驱动 - -相关步骤在Windows工作台操作。 - -1. 点击链接[下载CH341SER USB转串口](http://www.hihope.org/download/download.aspx?mtt=8)驱动程序。 -2. 点击安装包,安装驱动程序。 -3. 驱动安装完成后,重新插拔USB接口,串口信息显示如下图所示。 - - ![](figures/zh-cn_image_0000001174350633.png) - - diff --git "a/zh-cn/device-dev/quick-start/\345\270\270\350\247\201\351\227\256\351\242\230-1.md" "b/zh-cn/device-dev/quick-start/\345\270\270\350\247\201\351\227\256\351\242\230-1.md" deleted file mode 100644 index f8e0b7384e..0000000000 --- "a/zh-cn/device-dev/quick-start/\345\270\270\350\247\201\351\227\256\351\242\230-1.md" +++ /dev/null @@ -1,292 +0,0 @@ -# 常见问题 - -- [安装python3过程中,提示“configure: error: no acceptable C compiler found in $PATH”](#section1221016541119) -- [安装python3过程中,提示“-bash: make: command not found”](#section1913477181213) -- [安装python3过程中,提示“zlib not available”](#section108211415131210) -- [安装python3过程中,提示“No module named '\_ctypes'”](#section2062268124) -- [编译构建过程中,提示“No module named 'Crypto'”](#section982315398121) -- [编译构建过程中,提示“No module named 'ecdsa'”](#section102035451216) -- [编译构建过程中,提示“Could not find a version that satisfies the requirement six\>=1.9.0”](#section4498158162320) -- [编译构建过程中,提示找不到“-lgcc”](#section11181036112615) -- [编译构建过程中,提示找不到“python”](#section1571810194619) -- [安装 kconfiglib时,遇到lsb\_release错误](#section691681635814) - -## 安装python3过程中,提示“configure: error: no acceptable C compiler found in $PATH” - -- **现象描述** - - 安装python3过程中出现以下错误: - - ``` - configure: error: no acceptable C compiler found in $PATH. See 'config.log' for more details - ``` - -- **可能原因** - - 环境中未安装“gcc”。 - -- **解决办法** - - 1、通过命令“apt-get install gcc”在线安装。 - - 2、完成后,重新安装python3。 - - -## 安装python3过程中,提示“-bash: make: command not found” - -- **现象描述** - - 安装python3过程中出现以下错误: - - ``` - -bash: make: command not found - ``` - -- **可能原因** - - 环境中未安装“make”。 - -- **解决办法** - - 1、通过命令“apt-get install make”在线安装。 - - 2、完成后,重新安装python3。 - - -## 安装python3过程中,提示“zlib not available” - -- **现象描述** - - 安装python3过程中出现以下错误: - - ``` - zipimport.ZipImportError: can't decompress data; zlib not avaliable - ``` - -- **可能原因** - - 环境中未安装“zlib”。 - -- **解决办法** - - 方法1:通过命令“apt-get install zlib”在线安装。 - - 方法2:如果软件源中没有该软件,请从“www.zlib.net”下载版本代码,并离线安装。 - - ![](figures/10.png) - - 完成下载后,通过以下命令安装: - - ``` - # tar xvf zlib-1.2.11.tar.gz - # cd zlib-1.2.11 - # ./configure - # make && make install - ``` - - 完成后,重新安装python3。 - - -## 安装python3过程中,提示“No module named '\_ctypes'” - -- **现象描述** - - 安装python3过程中出现以下错误: - - ``` - ModuleNotFoundError:No module named ‘_ctypes’ - ``` - - -- **可能原因** - - 环境中未安装“libffi”和“libffi-devel”。 - - -- **解决办法** - - 1、通过命令“apt-get install libffi\* -y”,在线安装。 - - 2、完成后,重新安装python3。 - - -## 编译构建过程中,提示“No module named 'Crypto'” - -- **现象描述** - - 编译构建过程中出现以下错误: - - ``` - ModuleNotFoundError: No module named 'Crypto' - ``` - - -- **可能原因** - - 环境中未安装“Crypto”。 - - -- **解决办法** - - 方法1:通过命令“pip3 install Crypto”,在线安装。 - - 方法2:离线安装 - - 通过网页[https://pypi.org/project/pycrypto/\#files](https://pypi.org/project/pycrypto/#files),下载源码。 - - ![](figures/zh-cn_image_0000001128470864.png) - - 将源码放置在Linux服务器中,解压,并安装“python3 setup.py install”。 - - 完成上述安装后,重新构建。 - - -## 编译构建过程中,提示“No module named 'ecdsa'” - -- **现象描述** - - 编译构建过程中出现以下错误: - - ``` - ModuleNotFoundError:No module named 'ecdsa' - ``` - - -- **可能原因** - - 环境中未安装“ecdsa”。 - - -- **解决办法** - - 方法1:通过命令“pip3 install ecdsa”,在线安装。 - - 方法2:离线安装 - - 通过网页[https://pypi.org/project/ecdsa/\#files](https://pypi.org/project/ecdsa/#files),下载安装包。 - - ![](figures/zh-cn_image_0000001128311072.png) - - 将安装包放置Linux服务器中,并安装“pip3 install ecdsa-0.15-py2.py3-none-any.whl”。 - - 完成上述安装后,重新构建。 - - -## 编译构建过程中,提示“Could not find a version that satisfies the requirement six\>=1.9.0” - -- **现象描述** - - 编译构建过程中出现以下错误: - - ``` - Could not find a version that satisfies the requirement six>=1.9.0 - ``` - - -- **可能原因** - - 环境中未安装合适的“six”。 - - -- **解决办法** - - 方法1:通过命令“pip3 install six”,在线安装。 - - 方法2:离线安装 - - 通过网页[https://pypi.org/project/six/\#files](https://pypi.org/project/six/#files),下载安装包。 - - ![](figures/zh-cn_image_0000001174270699.png) - - 将源码放置在Linux服务器中,并安装“pip3 install six-1.14.0-py2.py3-none-any.whl”。 - - 完成上述安装后,重新构建。 - - -## 编译构建过程中,提示找不到“-lgcc” - -- **现象描述** - - 编译构建过程中出现以下错误: - - ``` - riscv32-unknown-elf-ld: cannot find -lgcc - ``` - - -- **可能原因** - - 交叉编译器gcc\_riscv32的PATH添加错误,如下,在"bin"后多添加了一个“/”,应该删除。 - - ``` - ~/gcc_riscv32/bin/:/data/toolchain/ - ``` - - -- **解决办法** - - 重新修改gcc\_riscv32的PATH,将多余的“/”删除。 - - ``` - ~/gcc_riscv32/bin:/data/toolchain/ - ``` - - -## 编译构建过程中,提示找不到“python” - -- **现象描述** - - 编译构建过程中出现以下错误: - - ``` - -bash: /usr/bin/python: No such file or directory - ``` - - -- **可能原因**1 - - 没有装python。 - -- **解决办法** - - 请按照 [安装Python环境](../quick-start/Ubuntu编译环境准备.md) - -- **可能原因2** - - ![](figures/zh-cn_image_0000001128311070.png) - -- **解决办法** - - usr/bin目录下没有python软链接,请运行以下命令添加软链接: - - ``` - # cd /usr/bin/ - # which python3 - # ln -s /usr/local/bin/python3 python - # python --version - ``` - - 例: - - ![](figures/zh-cn_image_0000001174350623.png) - - -## 安装 kconfiglib时,遇到lsb\_release错误 - -- **现象描述** - - 安装kconfiglib过程中遇到如下错误打印: - - ``` - subprocess.CalledProcessError: Command '('lsb_release', '-a')' returned non-zero exit status 1. - ``` - -- **可能原因** - - lsb\_release模块基于的python版本与现有python版本不一致 - -- **解决办法** - - 执行"find / -name lsb\_release",找到lsb\_release位置并删除,如:"sudo rm -rf /usr/bin/lsb\_release" - - diff --git "a/zh-cn/device-dev/quick-start/\345\270\270\350\247\201\351\227\256\351\242\230-3.md" "b/zh-cn/device-dev/quick-start/\345\270\270\350\247\201\351\227\256\351\242\230-3.md" deleted file mode 100644 index ece72f0351..0000000000 --- "a/zh-cn/device-dev/quick-start/\345\270\270\350\247\201\351\227\256\351\242\230-3.md" +++ /dev/null @@ -1,175 +0,0 @@ -# 常见问题 - -- [烧写选择串口后提示失败](#section627268185113) -- [Windows电脑与单板网络连接失败](#section195391036568) -- [烧写失败](#section571164016565) -- [编译构建过程中,提示找不到“python”](#section1039835245619) -- [串口无回显](#section14871149155911) - -## 烧写选择串口后提示失败 - -- **现象描述** - - 点击烧写并选择串口后,出现Error: Opening COMxx: Access denied。 - - **图 1** 打开串口失败图 - ![](figures/打开串口失败图.png "打开串口失败图") - -- **可能原因** - - 串口已经被占用。 - -- **解决办法** - -1. 按图依次选择下拉框,查找带有serial-xx的终端 - - **图 2** 查找是否存在占用串口的终端 - ![](figures/查找是否存在占用串口的终端.png "查找是否存在占用串口的终端") - -2. 点击标号中的垃圾桶图标,关闭串口。 - - **图 3** 关闭串口终端 - ![](figures/关闭串口终端.png "关闭串口终端") - -3. 重新点击烧写,选择串口并开始烧写程序 - - **图 4** 重新启动烧写任务 - - - ![](figures/changjian1.png) - - -## Windows电脑与单板网络连接失败 - -- **现象描述** - - 点击烧写并选择串口后,无法获取文件。 - - **图 5** 网络不通,单板无法获取文件图 - ![](figures/网络不通-单板无法获取文件图.png "网络不通-单板无法获取文件图") - -- **可能原因** - - 单板网络与Windows电脑不联通。 - - Windows电脑防火墙未允许Visual Studio Code联网。 - -- **解决方法** - -1. 检查网线是否连接。 -2. 点击Windows防火墙。 - - **图 6** 网络防火墙设置图 - ![](figures/网络防火墙设置图.png "网络防火墙设置图") - -3. 点击“允许应用通过防火墙”。 - - **图 7** 防火墙和网络保护界面图 - ![](figures/防火墙和网络保护界面图.png "防火墙和网络保护界面图") - -4. 查找Visual Studio Code应用。 - - **图 8** 查找Visual Studio Code应用图 - ![](figures/查找Visual-Studio-Code应用图.png "查找Visual-Studio-Code应用图") - -5. 勾选Visual Studio Code的专用和公用网络的访问权限。 - - **图 9** 允许Visual Studio Code应用访问网络 - ![](figures/允许Visual-Studio-Code应用访问网络.png "允许Visual-Studio-Code应用访问网络") - - -## 烧写失败 - -- **现象描述** - - 点击烧写并选择串口后,出现无法烧写的情况。 - -- **可能原因** - - 安装IDE插件DevEco后未重启。 - -- **解决方法** - - 重启IDE。 - - -## 编译构建过程中,提示找不到“python” - -- **现象描述** - - ![](figures/zh-cn_image_0000001174270715.png) - - -- **可能原因1** - - 没有装python。 - -- **解决办法** - - 请按照[安装python](../quick-start/Ubuntu编译环境准备.md)。 - -- **可能原因2** - - ![](figures/zh-cn_image_0000001128470880.png) - -- **解决办法** - - usr/bin目录下没有python软链接,请运行以下命令: - - ``` - # cd /usr/bin/ - # which python3 - # ln -s /usr/local/bin/python3 python - # python --version - ``` - - 例: - - ![](figures/zh-cn_image_0000001174270713.png) - - -## 串口无回显 - -- **现象描述** - - 串口显示已连接,重启单板后,回车无任何回显。 - -- **可能原因1** - - 串口连接错误。 - -- **解决办法** - - 修改串口号。 - - 请查看设备管理器,确认连接单板的串口与终端中连接串口是否一致,若不一致,请按镜像运行内[步骤1](../quick-start/运行Hello-OHOS.md)修改串口号。 - - -- **可能原因2** - - 单板U-boot被损坏。 - -- **解决办法** - - 烧写U-boot。 - - 若上述步骤依旧无法连接串口,可能由于单板U-boot损坏,按下述步骤烧写U-boot。 - - -1. 获取引导文件U-boot。 - - >![](public_sys-resources/icon-notice.gif) **须知:** - >单板的U-boot文件请在开源包中获取: - >Hi3516DV300:device\\hisilicon\\hispark\_taurus\\sdk\_liteos\\uboot\\out\\boot\\u-boot-hi3516dv300.bin - >Hi3518EV300:device\\hisilicon\\hispark\_aries\\sdk\_liteos\\uboot\\out\\boot\\u-boot-hi3518ev300.bin - -2. 根据USB烧写步骤烧写U-boot文件。 - - 按照[Hi3516系列USB烧写步骤](https://device.harmonyos.com/cn/docs/ide/user-guides/hi3516_upload-0000001052148681)/[Hi3518系列USB烧写步骤](https://device.harmonyos.com/cn/docs/ide/user-guides/hi3518_upload-0000001057313128)中描述的USB烧写方法,选择对应单板的U-boot文件进行烧写。 - -3. 烧写完成后,登录串口如下图所示。 - - **图 10** U-boot烧写完成串口显示图 - ![](figures/U-boot烧写完成串口显示图.png "U-boot烧写完成串口显示图") - - diff --git "a/zh-cn/device-dev/quick-start/\345\270\270\350\247\201\351\227\256\351\242\230-6.md" "b/zh-cn/device-dev/quick-start/\345\270\270\350\247\201\351\227\256\351\242\230-6.md" deleted file mode 100644 index b2dc3ad512..0000000000 --- "a/zh-cn/device-dev/quick-start/\345\270\270\350\247\201\351\227\256\351\242\230-6.md" +++ /dev/null @@ -1,174 +0,0 @@ -# 常见问题 - -- [烧写选择串口后提示失败](#section1498892119619) -- [Windows电脑与单板网络连接失败](#section8512971816) -- [烧写失败](#section1767804111198) -- [编译构建过程中,提示找不到“python”](#zh-cn_topic_0000001053466255_section1039835245619) -- [串口无回显](#zh-cn_topic_0000001053466255_section14871149155911) - -## 烧写选择串口后提示失败 - -- **现象描述** - - 点击烧写并选择串口后,出现Error: Opening COMxx: Access denied。 - - **图 1** 打开串口失败图 - ![](figures/打开串口失败图-7.png "打开串口失败图-7") - -- **可能原因** - - 串口已经被占用。 - -- **解决办法** - -1. 按图依次选择下拉框,查找带有serial-xx的终端 - - **图 2** 查找是否存在占用串口的终端 - ![](figures/查找是否存在占用串口的终端-8.png "查找是否存在占用串口的终端-8") - -2. 点击标号中的垃圾桶图标,关闭串口。 - - **图 3** 关闭串口终端 - ![](figures/关闭串口终端-9.png "关闭串口终端-9") - -3. 重新点击烧写,选择串口并开始烧写程序 - - **图 4** 重新启动烧写任务 - - - ![](figures/changjian1-10.png) - - -## Windows电脑与单板网络连接失败 - -- **现象描述** - - 点击烧写并选择串口后,无法获取文件。 - - **图 5** 网络不通,单板无法获取文件图 - ![](figures/网络不通-单板无法获取文件图-11.png "网络不通-单板无法获取文件图-11") - -- **可能原因** - - 单板网络与Windows电脑不联通。 - - Windows电脑防火墙未允许Visual Studio Code联网。 - -- **解决方法** - -1. 检查网线是否连接。 -2. 点击Windows防火墙。 - - **图 6** 网络防火墙设置图 - ![](figures/网络防火墙设置图-12.png "网络防火墙设置图-12") - -3. 点击“允许应用通过防火墙”。 - - **图 7** 防火墙和网络保护界面图 - ![](figures/防火墙和网络保护界面图-13.png "防火墙和网络保护界面图-13") - -4. 查找Visual Studio Code应用。 - - **图 8** 查找Visual Studio Code应用图 - ![](figures/查找Visual-Studio-Code应用图-14.png "查找Visual-Studio-Code应用图-14") - -5. 勾选Visual Studio Code的专用和公用网络的访问权限。 - - **图 9** 允许Visual Studio Code应用访问网络 - ![](figures/允许Visual-Studio-Code应用访问网络-15.png "允许Visual-Studio-Code应用访问网络-15") - - -## 烧写失败 - -- **现象描述** - - 点击烧写并选择串口后,出现无法烧写的情况。 - -- **可能原因** - - 安装IDE插件DevEco后未重启。 - -- **解决方法** - - 重启IDE。 - - -## 编译构建过程中,提示找不到“python” - -- **现象描述** - - ![](figures/zh-cn_image_0000001174270743.png) - - -- **可能原因1** - - 没有装python。 - -- **解决办法** - - 请按照[安装python](../quick-start/Ubuntu编译环境准备.md)。 - -- **可能原因2** - - ![](figures/zh-cn_image_0000001174270739.png) - -- **解决办法** - - usr/bin目录下没有python软链接,请运行以下命令: - - ``` - # cd /usr/bin/ - # which python3 - # ln -s /usr/local/bin/python3 python - # python --version - ``` - - 例: - - ![](figures/zh-cn_image_0000001174350661.png) - - -## 串口无回显 - -- **现象描述** - - 串口显示已连接,重启单板后,回车无任何回显。 - -- **可能原因1** - - 串口连接错误。 - -- **解决办法** - - 修改串口号。 - - 请查看设备管理器,确认连接单板的串口与终端中连接串口是否一致,若不一致,请按镜像运行内[步骤1](../quick-start/运行Hello-OHOS.md)修改串口号。 - - -- **可能原因2** - - 单板U-boot被损坏。 - -- **解决办法** - - 烧写U-boot。 - - 若上述步骤依旧无法连接串口,可能由于单板U-boot损坏,按下述步骤烧写U-boot。 - - -1. 获取引导文件U-boot。 - - >![](public_sys-resources/icon-notice.gif) **须知:** - >单板的U-boot文件请在开源包中获取: - >Hi3516DV300:device\\hisilicon\\hispark\_taurus\\sdk\_liteos\\uboot\\out\\boot\\u-boot-hi3516dv300.bin - >Hi3518EV300:device\\hisilicon\\hispark\_aries\\sdk\_liteos\\uboot\\out\\boot\\u-boot-hi3518ev300.bin - -2. 根据USB烧写步骤烧写U-boot文件。 - - 按照[Hi3516系列USB烧写步骤](https://device.harmonyos.com/cn/docs/ide/user-guides/hi3516_upload-0000001052148681)/[Hi3518系列USB烧写步骤](https://device.harmonyos.com/cn/docs/ide/user-guides/hi3518_upload-0000001057313128)中描述的USB烧写方法,选择对应单板的U-boot文件进行烧写。 - -3. 烧写完成后,登录串口如下图所示。 - - ![](figures/zh-cn_image_0000001174350659.png) - - diff --git "a/zh-cn/device-dev/quick-start/\345\274\200\345\217\221\346\255\245\351\252\244.md" "b/zh-cn/device-dev/quick-start/\345\274\200\345\217\221\346\255\245\351\252\244.md" deleted file mode 100644 index 70e795860f..0000000000 --- "a/zh-cn/device-dev/quick-start/\345\274\200\345\217\221\346\255\245\351\252\244.md" +++ /dev/null @@ -1,9 +0,0 @@ -# 开发步骤 - -- **[Hi3861开发板](Hi3861开发板.md)** - -- **[Hi3516开发板](Hi3516开发板.md)** - -- **[Hi3518开发板](Hi3518开发板.md)** - - diff --git "a/zh-cn/device-dev/quick-start/\346\220\255\345\273\272Ubuntu\347\216\257\345\242\203\345\217\212\347\274\226\350\257\221\357\274\210Docker\346\226\271\345\274\217\357\274\211.md" "b/zh-cn/device-dev/quick-start/\346\220\255\345\273\272Ubuntu\347\216\257\345\242\203\345\217\212\347\274\226\350\257\221\357\274\210Docker\346\226\271\345\274\217\357\274\211.md" deleted file mode 100644 index 2f4c97aa4a..0000000000 --- "a/zh-cn/device-dev/quick-start/\346\220\255\345\273\272Ubuntu\347\216\257\345\242\203\345\217\212\347\274\226\350\257\221\357\274\210Docker\346\226\271\345\274\217\357\274\211.md" +++ /dev/null @@ -1,118 +0,0 @@ -# 搭建Ubuntu环境及编译(Docker方式) - -- [获取标准系统源码](#section8761819202511) - - [前提条件](#section102871547153314) - - [操作步骤](#section429012478331) - -- [获取Docker环境](#section181431248132513) -- [编译](#section92391739152318) - -OpenHarmony标准系统为开发者提供的Docker环境已经将对应的编译工具链进行了封装,开发者可省略对应工具的安装。 - ->![](public_sys-resources/icon-note.gif) **说明:** ->- 在使用Docker前需要先安装Docker,Docker安装请参考[官方指导](https://docs.docker.com/engine/install/ubuntu/)。 ->- Docker方式和安装包方式二选一即可。选择Docker方式的开发者可跳过[安装包方式](搭建Ubuntu环境及编译(安装包方式).md)的内容。 - -## 获取标准系统源码 - -### 前提条件 - -1. 注册码云gitee账号。 -2. 注册码云SSH公钥,请参考[码云帮助中心](https://gitee.com/help/articles/4191)。 -3. 安装[git客户端](http://git-scm.com/book/zh/v2/%E8%B5%B7%E6%AD%A5-%E5%AE%89%E8%A3%85-Git)和[git-lfs](https://gitee.com/vcs-all-in-one/git-lfs?_from=gitee_search#downloading))并配置用户信息。 - - ``` - git config --global user.name "yourname" - git config --global user.email "your-email-address" - git config --global credential.helper store - ``` - -4. 安装码云repo工具,可以执行如下命令。 - - ``` - curl -s https://gitee.com/oschina/repo/raw/fork_flow/repo-py3 > /usr/local/bin/repo #如果没有权限,可下载至其他目录,并将其配置到环境变量中 - chmod a+x /usr/local/bin/repo - pip3 install -i https://repo.huaweicloud.com/repository/pypi/simple requests - ``` - - -### 操作步骤 - -方式一(推荐):通过repo + ssh 下载(需注册公钥,请参考[码云帮助中心](https://gitee.com/help/articles/4191))。 - -``` -repo init -u git@gitee.com:openharmony/manifest.git -b master --no-repo-verify -repo sync -c -repo forall -c 'git lfs pull' -``` - -方式二:通过repo + https 下载。 - -``` -repo init -u https://gitee.com/openharmony/manifest.git -b master --no-repo-verify -repo sync -c -repo forall -c 'git lfs pull' -``` - -## 获取Docker环境 - -**方式一:从HuaweiCloud SWR上直接获取Docker镜像进行构建:** - -1. 获取Docker镜像。 - - ``` - docker pull swr.cn-south-1.myhuaweicloud.com/openharmony-docker/openharmony-docker-standard:0.0.1 - ``` - -2. 进入OpenHarmony代码根目录执行如下命令,从而进入Docker构建环境。 - - ``` - docker run -it -v $(pwd):/home/openharmony swr.cn-south-1.myhuaweicloud.com/openharmony-docker/openharmony-docker-standard:0.0.1 - ``` - - -**方式二:通过Dockerfile 构建本地Docker镜像进行构建** - -1. 获取Dockerfile脚本文件,用来构建本地Docker镜像。 - - ``` - git clone https://gitee.com/openharmony/docs.git - ``` - -2. 进入Dockerfile代码目录路径执行Docker镜像构建命令。 - - ``` - cd docs/docker/standard - ./build.sh - ``` - -3. 进入OpenHarmony代码根目录执行如下命令,从而进入Docker构建环境。 - - ``` - docker run -it -v $(pwd):/home/openharmony openharmony-docker-standard:0.0.1 - ``` - - -## 编译 - -1. 在源码的根目录执行预处理脚本。 - - ``` - ../scripts/prepare.sh - ``` - -2. 通过如下编译脚本启动标准系统类设备(参考内存≥128MB)的编译。 - - ``` - ./build.sh --product-name {product_name} - ``` - - \{product\_name\}为当前版本支持的平台,比如:Hi3516DV300 - - 编译所生成的文件都归档在out/ohos-arm-release/目录下,结果镜像输出在 out/ohos-arm-release/packages/phone/images/ 目录下。 - -3. 编译源码完成,请进行镜像烧录,具体请参见[镜像烧录](镜像烧录.md)。 - ->![](public_sys-resources/icon-note.gif) **说明:** ->退出Docker执行exit命令即可。 - diff --git "a/zh-cn/device-dev/quick-start/\346\220\255\345\273\272Ubuntu\347\216\257\345\242\203\345\217\212\347\274\226\350\257\221\357\274\210\345\256\211\350\243\205\345\214\205\346\226\271\345\274\217\357\274\211.md" "b/zh-cn/device-dev/quick-start/\346\220\255\345\273\272Ubuntu\347\216\257\345\242\203\345\217\212\347\274\226\350\257\221\357\274\210\345\256\211\350\243\205\345\214\205\346\226\271\345\274\217\357\274\211.md" deleted file mode 100644 index 92eb461fe7..0000000000 --- "a/zh-cn/device-dev/quick-start/\346\220\255\345\273\272Ubuntu\347\216\257\345\242\203\345\217\212\347\274\226\350\257\221\357\274\210\345\256\211\350\243\205\345\214\205\346\226\271\345\274\217\357\274\211.md" +++ /dev/null @@ -1,98 +0,0 @@ -# 搭建Ubuntu环境及编译(安装包方式) - -- [安装依赖工具](#section18431165519244) -- [获取标准系统源码](#section113751052102517) - - [前提条件](#section102871547153314) - - [操作步骤](#section429012478331) - -- [执行prebuilts](#section0495320152619) -- [编译](#section1664835963517) - -## 安装依赖工具 - -安装命令如下: - -``` -sudo apt-get update && sudo apt-get install binutils git git-lfs gnupg flex bison gperf build-essential zip curl zlib1g-dev gcc-multilib g++-multilib libc6-dev-i386 lib32ncurses5-dev x11proto-core-dev libx11-dev lib32z1-dev ccache libgl1-mesa-dev libxml2-utils xsltproc unzip m4 bc gnutls-bin python3.8 python3-pip -``` - ->![](public_sys-resources/icon-note.gif) **说明:** ->以上安装命令适用于Ubuntu18.04,其他版本请根据安装包名称采用对应的安装命令。 - -## 获取标准系统源码 - -### 前提条件 - -1. 注册码云gitee账号。 -2. 注册码云SSH公钥,请参考[码云帮助中心](https://gitee.com/help/articles/4191)。 -3. 安装[git客户端](http://git-scm.com/book/zh/v2/%E8%B5%B7%E6%AD%A5-%E5%AE%89%E8%A3%85-Git)和[git-lfs](https://gitee.com/vcs-all-in-one/git-lfs?_from=gitee_search#downloading))并配置用户信息。 - - ``` - git config --global user.name "yourname" - git config --global user.email "your-email-address" - git config --global credential.helper store - ``` - -4. 安装码云repo工具,可以执行如下命令。 - - ``` - curl -s https://gitee.com/oschina/repo/raw/fork_flow/repo-py3 > /usr/local/bin/repo #如果没有权限,可下载至其他目录,并将其配置到环境变量中 - chmod a+x /usr/local/bin/repo - pip3 install -i https://repo.huaweicloud.com/repository/pypi/simple requests - ``` - - -### 操作步骤 - -方式一(推荐):通过repo + ssh 下载(需注册公钥,请参考[码云帮助中心](https://gitee.com/help/articles/4191))。 - -``` -repo init -u git@gitee.com:openharmony/manifest.git -b master --no-repo-verify -repo sync -c -repo forall -c 'git lfs pull' -``` - -方式二:通过repo + https 下载。 - -``` -repo init -u https://gitee.com/openharmony/manifest.git -b master --no-repo-verify -repo sync -c -repo forall -c 'git lfs pull' -``` - -## 执行prebuilts - -在源码根目录下执行脚本,安装编译器及二进制工具。 - -``` -bash build/prebuilts_download.sh -``` - -下载的prebuilts二进制默认存放在与OpenHarmony同目录下的OpenHarmony\_2.0\_canary\_prebuilts下。 - -## 编译 - -在Linux环境进行如下操作: - -1. 进入源码根目录,执行如下命令进行版本编译。 - - ``` - ./build.sh --product-name {product_name} - ``` - - \{product\_name\}为当前版本支持的平台,比如:Hi3516DV300 - -2. 检查编译结果。编译完成后,log中显示如下: - - ``` - build system image successful. - =====build Hi3516DV300 successful. - ``` - - 编译所生成的文件都归档在out/ohos-arm-release/目录下,结果镜像输出在 out/ohos-arm-release/packages/phone/images/ 目录下。 - - >![](public_sys-resources/icon-note.gif) **说明:** - >其他模块化编译操作,可参见[编译构建指导](../subsystems/标准系统编译构建指导.md)。 - -3. 编译源码完成,请进行镜像烧录,具体请参见[镜像烧录](镜像烧录.md)。 - diff --git "a/zh-cn/device-dev/quick-start/\346\220\255\345\273\272\347\263\273\347\273\237\347\216\257\345\242\203.md" "b/zh-cn/device-dev/quick-start/\346\220\255\345\273\272\347\263\273\347\273\237\347\216\257\345\242\203.md" deleted file mode 100755 index 73a9d50f87..0000000000 --- "a/zh-cn/device-dev/quick-start/\346\220\255\345\273\272\347\263\273\347\273\237\347\216\257\345\242\203.md" +++ /dev/null @@ -1,11 +0,0 @@ -# 搭建系统环境 - -- **[概述](概述-0.md)** - -- **[Windows开发环境准备](Windows开发环境准备.md)** - -- **[Ubuntu编译环境准备](Ubuntu编译环境准备.md)** - -- **[常见问题](常见问题.md)** - - diff --git "a/zh-cn/device-dev/quick-start/\346\240\207\345\207\206\347\263\273\347\273\237\345\205\245\351\227\250.md" "b/zh-cn/device-dev/quick-start/\346\240\207\345\207\206\347\263\273\347\273\237\345\205\245\351\227\250.md" deleted file mode 100755 index 0281a27a47..0000000000 --- "a/zh-cn/device-dev/quick-start/\346\240\207\345\207\206\347\263\273\347\273\237\345\205\245\351\227\250.md" +++ /dev/null @@ -1,15 +0,0 @@ -# 标准系统入门 - -- **[入门介绍](入门介绍.md)** - -- **[Windows开发环境准备](Windows开发环境准备-7.md)** - -- **[搭建Ubuntu环境及编译(Docker方式)](搭建Ubuntu环境及编译(Docker方式).md)** - -- **[搭建Ubuntu环境及编译(安装包方式)](搭建Ubuntu环境及编译(安装包方式).md)** - -- **[镜像烧录](镜像烧录.md)** - -- **[常见问题](常见问题-8.md)** - - diff --git "a/zh-cn/device-dev/quick-start/\350\275\273\351\207\217\345\222\214\345\260\217\345\236\213\347\263\273\347\273\237\345\205\245\351\227\250.md" "b/zh-cn/device-dev/quick-start/\350\275\273\351\207\217\345\222\214\345\260\217\345\236\213\347\263\273\347\273\237\345\205\245\351\227\250.md" deleted file mode 100644 index a5446960eb..0000000000 --- "a/zh-cn/device-dev/quick-start/\350\275\273\351\207\217\345\222\214\345\260\217\345\236\213\347\263\273\347\273\237\345\205\245\351\227\250.md" +++ /dev/null @@ -1,11 +0,0 @@ -# 轻量和小型系统入门 - -- **[概述](概述.md)** - -- **[了解开发板](了解开发板.md)** - -- **[搭建系统环境](搭建系统环境.md)** - -- **[开发步骤](开发步骤.md)** - - diff --git "a/zh-cn/device-dev/quick-start/\350\277\220\350\241\214Hello-OHOS-5.md" "b/zh-cn/device-dev/quick-start/\350\277\220\350\241\214Hello-OHOS-5.md" deleted file mode 100644 index 51873c97ac..0000000000 --- "a/zh-cn/device-dev/quick-start/\350\277\220\350\241\214Hello-OHOS-5.md" +++ /dev/null @@ -1,262 +0,0 @@ -# 运行Hello OHOS - -- [新建应用程序](#section1550972416485) -- [编译](#section234175193114) -- [烧录](#section7609155824819) -- [镜像运行](#section17612105814480) -- [下一步学习](#section9712145420182) - -本节指导开发者在单板上运行第一个应用程序,其中包括新建应用程序、编译、烧写、运行等步骤,最终输出“Hello OHOS!”。 - -## 新建应用程序 - -1. 新建目录及源码 - - 新建**applications/sample/camera/apps/src/helloworld.c**目录及文件,代码如下所示,用户可以自定义修改打印内容(例如:修改OHOS为World)。当前应用程序可支持标准C及C++的代码开发。 - - ``` - #include - - int main(int argc, char **argv) - { - printf("\n************************************************\n"); - printf("\n\t\tHello OHOS!\n"); - printf("\n************************************************\n\n"); - - return 0; - } - ``` - -2. 新建编译组织文件 - - 新建**applications/sample/camera/apps/BUILD.gn**文件,内容如下所示: - - ``` - import("//build/lite/config/component/lite_component.gni") - lite_component("hello-OHOS") { - features = [ ":helloworld" ] - } - executable("helloworld") { - output_name = "helloworld" - sources = [ "src/helloworld.c" ] - include_dirs = [] - defines = [] - cflags_c = [] - ldflags = [] - } - ``` - -3. 添加新组件 - - 修改文件**build/lite/components/applications.json**,添加组件hello\_world\_app的配置,如下所示为applications.json文件片段,"\#\#start\#\#"和"\#\#end\#\#"之间为新增配置("\#\#start\#\#"和"\#\#end\#\#"仅用来标识位置,添加完配置后删除这两行): - - ``` - { - "components": [ - { - "component": "camera_sample_communication", - "description": "Communication related samples.", - "optional": "true", - "dirs": [ - "applications/sample/camera/communication" - ], - "targets": [ - "//applications/sample/camera/communication:sample" - ], - "rom": "", - "ram": "", - "output": [], - "adapted_kernel": [ "liteos_a" ], - "features": [], - "deps": { - "components": [], - "third_party": [] - } - }, - ##start## - { - "component": "hello_world_app", - "description": "Communication related samples.", - "optional": "true", - "dirs": [ - "applications/sample/camera/apps" - ], - "targets": [ - "//applications/sample/camera/apps:hello-OHOS" - ], - "rom": "", - "ram": "", - "output": [], - "adapted_kernel": [ "liteos_a" ], - "features": [], - "deps": { - "components": [], - "third_party": [] - } - }, - ##end## - { - "component": "camera_sample_app", - "description": "Camera related samples.", - "optional": "true", - "dirs": [ - "applications/sample/camera/launcher", - "applications/sample/camera/cameraApp", - "applications/sample/camera/setting", - "applications/sample/camera/gallery", - "applications/sample/camera/media" - ], - ``` - -4. 修改单板配置文件 - - 修改文件**vendor/hisilicon/hispark\_aries/config.json**,新增hello\_world\_app组件的条目,如下所示代码片段为applications子系统配置,"\#\#start\#\#"和"\#\#end\#\#"之间为新增条目("\#\#start\#\#"和"\#\#end\#\#"仅用来标识位置,添加完配置后删除这两行): - - ``` - { - "subsystem": "applications", - "components": [ - ##start## - { "component": "hello_world_app", "features":[] }, - ##end## - { "component": "camera_sample_app", "features":[] } - - ] - }, - ``` - - -## 编译 - -如果Linux编译环境通过Docker方式安装,具体编译过程请参见[Docker方式获取编译环境](../get-code/Docker编译环境.md)的编译操作。如果Linux编译环境通过软件包方式安装,进入源码根目录,执行如下命令进行编译: - -``` -hb set(设置编译路径) -.(选择当前路径) -选择ipcamera_hispark_aries@hisilicon并回车 -hb build -f(执行编译) -``` - -结果文件生成在out/hispark\_aries/ipcamera\_hispark\_aries目录下。 - -**图 1** 设置图例 -![](figures/设置图例-4.png "设置图例-4") - ->![](public_sys-resources/icon-notice.gif) **须知:** ->Hi3518EV300单板的U-boot文件获取路径:device/hisilicon/hispark\_aries/sdk\_liteos/uboot/out/boot/u-boot-hi3518ev300.bin - -## 烧录 - -Hi3518开发板的代码烧录仅支持USB烧录方式。 - -1. 请连接好电脑和待烧录开发板,以Hi3518EV300为例,需要同时连接串口和USB口,具体可参考[Hi3518开发板介绍](https://device.harmonyos.com/cn/docs/start/introduce/oem_minitinier_des_3518-0000001105201138)。 -2. 打开电脑的设备管理器,查看并记录对应的串口号。 - - >![](public_sys-resources/icon-note.gif) **说明:** - >如果对应的串口异常,请根据[Hi3516/Hi3518系列开发板串口驱动安装指导](https://device.harmonyos.com/cn/docs/ide/user-guides/hi3516_hi3518-drivers-0000001050743695)安装USB转串口的驱动程序。 - - ![](figures/zh-cn_image_0000001128470900.png) - -3. 打开DevEco Device Tool,在Projects中,点击**Settings**打开工程配置界面。 - - ![](figures/zh-cn_image_0000001174350649.png) - -4. 在“Partition Configuration”页签,设置待烧录文件信息,默认情况下,DevEco Device Tool已针对Hi3518系列开发板进行适配,无需单独修改。 -5. 在“hi3518ev300”页签,设置烧录选项,包括upload\_port、upload\_partitions和upload\_protocol。 - - - upload\_port:选择步骤[2](#zh-cn_topic_0000001057313128_li46411811196)中查询的串口号。 - - upload\_protocol:选择烧录协议,固定选择“hiburn-usb”。 - - upload\_partitions:选择待烧录的文件,默认情况下会同时烧录fastboot、kernel、rootfs和userfs。 - - ![](figures/zh-cn_image_0000001128311090.png) - -6. 所有的配置都修改完成后,在工程配置页签的顶部,点击**Save**进行保存。 -7. 打开工程文件,点击![](figures/2021-01-27_170334-5.png)图标,打开DevEco Device Tool界面,在“PROJECT TASKS”中,点击hi3518ev300\_fastboot下的**Erase**按钮,擦除U-Boot。 - - ![](figures/zh-cn_image_0000001174270731.png) - -8. 执行**Erase**擦除操作后,显示如下提示信息时,请重启开发板(下电再上电)。 - - ![](figures/zh-cn_image_0000001128311092.png) - -9. 重新上电后,显示如下信息时,表示擦除U-Boot成功。 - - ![](figures/zh-cn_image_0000001128311094.png) - -10. 擦除完成后,点击hi3518ev300下的**Upload**按钮,启动烧录。 - - ![](figures/zh-cn_image_0000001174350641.png) - -11. 启动烧录后,界面提示如下信息时,表示烧录成功。 - - ![](figures/zh-cn_image_0000001174350643.png) - - -## 镜像运行 - -1. 连接串口。 - - >![](public_sys-resources/icon-notice.gif) **须知:** - >若无法连接串口,请参考[常见问题](../quick-start/常见问题-6.md)进行排查。 - - **图 2** 连接串口图 - - - ![](figures/chuankou1-6.png) - - 1. 单击**Monitor**打开串口。 - 2. 连续输入回车直到串口显示"hisilicon"。 - 3. 单板初次启动或修改启动参数,请进入[步骤2](#li9441185382314),否则进入[步骤3](#li6442853122312)。 - -2. (初次烧写必选)修改U-boot的bootcmd及bootargs内容:该步骤为固化操作,可保存执行结果,但U-boot重新烧入,则需要再次执行下述步骤。 - - **表 1** U-boot修改命令 - - - - - - - - - - - - - - - - - - - - - - -

    执行命令

    -

    命令解释

    -

    setenv bootcmd "sf probe 0;sf read 0x40000000 0x100000 0x600000;go 0x40000000";

    -

    设置bootcmd内容,选择FLASH器件0,读取FLASH起始地址为0x100000,大小为0x600000字节的内容到0x40000000的内存地址,此处0x600000为6MB,与IDE中填写OHOS_Image.bin的文件大小必须相同

    -

    setenv bootargs "console=ttyAMA0,115200n8 root=flash fstype=jffs2 rw rootaddr=7M rootsize=8M";

    -

    表示设置bootargs参数为串口输出,波特率为115200,数据位8,rootfs挂载于FLASH上,文件系统类型为jffs2 rw,以支持可读写JFFS2文件系统。“rootaddr=7M rootsize=8M”处对应填入实际rootfs.img的烧写起始位置与长度,与IDE内所填大小必须相同

    -

    saveenv

    -

    表示保存当前配置。

    -

    reset

    -

    表示复位单板。

    -

    pri

    -

    表示查看显示参数。

    -
    - - >![](public_sys-resources/icon-notice.gif) **须知:** - >**“go 0x40000000”**为可选指令,默认配置已将该指令固化在启动参数中,单板复位后可自动启动。若想切换为手动启动,可在U-boot启动倒数阶段使用"回车"打断自动启动。 - -3. 若启动时显示**"hisilicon \#**字样,请输入**“reset”**指令,等待系统自启动进入系统,系统启动后,显示**“OHOS”**字样,输入**”./bin/helloworld”**并回车,显示成功结果如下图所示。 - - **图 3** 启动成功并执行应用程序图 - ![](figures/启动成功并执行应用程序图.png "启动成功并执行应用程序图") - - -## 下一步学习 - -恭喜您,已完成Hi3518的快速上手!建议您下一步进入[无屏摄像头产品开发](../guide/摄像头控制.md)的学习 。 - diff --git "a/zh-cn/device-dev/quick-start/\350\277\220\350\241\214Hello-OHOS.md" "b/zh-cn/device-dev/quick-start/\350\277\220\350\241\214Hello-OHOS.md" deleted file mode 100755 index d5f775c64f..0000000000 --- "a/zh-cn/device-dev/quick-start/\350\277\220\350\241\214Hello-OHOS.md" +++ /dev/null @@ -1,269 +0,0 @@ -# 运行Hello OHOS - -- [新建应用程序](#section204672145202) -- [编译](#section1077671315253) -- [烧录](#section1347011412201) -- [镜像运行](#section24721014162010) -- [执行应用程序](#section5276734182615) - -本节指导开发者在单板上运行第一个应用程序,其中包括新建应用程序、编译、烧写、运行等步骤,最终输出“Hello OHOS!”。 - -## 新建应用程序 - -1. 新建目录及源码 - - 新建**applications/sample/camera/apps/src/helloworld.c**目录及文件,代码如下所示,用户可以自定义修改打印内容(例如:修改OHOS为World)。当前应用程序可支持标准C及C++的代码开发。 - - ``` - #include - - int main(int argc, char **argv) - { - printf("\n************************************************\n"); - printf("\n\t\tHello OHOS!\n"); - printf("\n************************************************\n\n"); - - return 0; - } - ``` - -2. 新建编译组织文件 - - 新建**applications/sample/camera/apps/BUILD.gn**文件,内容如下所示: - - ``` - import("//build/lite/config/component/lite_component.gni") - lite_component("hello-OHOS") { - features = [ ":helloworld" ] - } - executable("helloworld") { - output_name = "helloworld" - sources = [ "src/helloworld.c" ] - include_dirs = [] - defines = [] - cflags_c = [] - ldflags = [] - } - ``` - -3. 添加新组件 - - 修改文件**build/lite/components/applications.json**,添加组件hello\_world\_app的配置,如下所示为applications.json文件片段,"\#\#start\#\#"和"\#\#end\#\#"之间为新增配置("\#\#start\#\#"和"\#\#end\#\#"仅用来标识位置,添加完配置后删除这两行): - - ``` - { - "components": [ - { - "component": "camera_sample_communication", - "description": "Communication related samples.", - "optional": "true", - "dirs": [ - "applications/sample/camera/communication" - ], - "targets": [ - "//applications/sample/camera/communication:sample" - ], - "rom": "", - "ram": "", - "output": [], - "adapted_kernel": [ "liteos_a" ], - "features": [], - "deps": { - "components": [], - "third_party": [] - } - }, - ##start## - { - "component": "hello_world_app", - "description": "Communication related samples.", - "optional": "true", - "dirs": [ - "applications/sample/camera/apps" - ], - "targets": [ - "//applications/sample/camera/apps:hello-OHOS" - ], - "rom": "", - "ram": "", - "output": [], - "adapted_kernel": [ "liteos_a" ], - "features": [], - "deps": { - "components": [], - "third_party": [] - } - }, - ##end## - { - "component": "camera_sample_app", - "description": "Camera related samples.", - "optional": "true", - "dirs": [ - "applications/sample/camera/launcher", - "applications/sample/camera/cameraApp", - "applications/sample/camera/setting", - "applications/sample/camera/gallery", - "applications/sample/camera/media" - ], - ``` - -4. 修改单板配置文件 - - 修改文件**vendor/hisilicon/hispark\_taurus/config.json**,新增hello\_world\_app组件的条目,如下所示代码片段为applications子系统配置,"\#\#start\#\#"和"\#\#end\#\#"之间为新增条目("\#\#start\#\#"和"\#\#end\#\#"仅用来标识位置,添加完配置后删除这两行): - - ``` - { - "subsystem": "applications", - "components": [ - { "component": "camera_sample_app", "features":[] }, - { "component": "camera_sample_ai", "features":[] }, - ##start## - { "component": "hello_world_app", "features":[] }, - ##end## - { "component": "camera_screensaver_app", "features":[] } - ] - }, - ``` - - -## 编译 - -如果Linux编译环境通过Docker方式安装,具体编译过程请参见[Docker方式获取编译环境](../get-code/Docker编译环境.md)的编译操作。如果Linux编译环境通过软件包方式安装,请进入源码根目录,执行如下命令进行编译: - -``` -hb set(设置编译路径) -.(选择当前路径) -选择ipcamera_hispark_taurus@hisilicon并回车 -hb build -f(执行编译) -``` - -**图 1** 设置图例 -![](figures/设置图例.png "设置图例") - -结果文件生成在out/hispark\_taurus/ipcamera\_hispark\_taurus目录下。 - ->![](public_sys-resources/icon-notice.gif) **须知:** ->Hi3516DV300单板的U-boot文件获取路径:device/hisilicon/hispark\_taurus/sdk\_liteos/uboot/out/boot/u-boot-hi3516dv300.bin - -## 烧录 - -Hi3516开发板的代码烧录支持USB烧录、网口烧录和串口烧录三种方式。此处仅以网口烧录为例进行说明。 - -1. 请连接好电脑和待烧录开发板,以Hi3516DV300为例,需要同时连接串口、网口和电源,具体可参考[Hi3516开发板介绍](https://device.harmonyos.com/cn/docs/start/introduce/oem_minitinier_des_3516-0000001152041033)。 -2. 打开电脑的设备管理器,查看并记录对应的串口号。 - - >![](public_sys-resources/icon-note.gif) **说明:** - >如果对应的串口异常,请根据[Hi3516/Hi3518系列开发板串口驱动安装指导](https://device.harmonyos.com/cn/docs/ide/user-guides/hi3516_hi3518-drivers-0000001050743695)安装USB转串口的驱动程序。 - - ![](figures/zh-cn_image_0000001174350647.png) - -3. 打开DevEco Device Tool,在Projects中,点击**Settings**打开工程配置界面。 - - ![](figures/2021-01-27_170334.png) - -4. 在“Partition Configuration”页签,设置待烧录文件信息,默认情况下,DevEco Device Tool已针对Hi3516系列开发板进行适配,无需单独修改。 -5. 在“hi3516dv300”页签,设置烧录选项,包括upload\_port、upload\_partitions和upload\_protocol。 - - - upload\_port:选择步骤[2](#zh-cn_topic_0000001056443961_li142386399535)中查询的串口号。 - - upload\_protocol:选择烧录协议,固定选择“hiburn-net”。 - - upload\_partitions:选择待烧录的文件,默认情况下会同时烧录fastboot、kernel、rootfs和userfs。 - - ![](figures/zh-cn_image_0000001128470904.png) - -6. 检查和设置连接开发板后的网络适配器的IP地址信息,设置方法请参考[设置Hi3516网口烧录的IP地址信息](https://device.harmonyos.com/cn/docs/ide/user-guides/set_ipaddress-0000001141825075)。 -7. 设置网口烧录的IP地址信息,设置如下选项: - - - upload\_net\_server\_ip:选择[6](#zh-cn_topic_0000001056443961_li1558813168234)中设置的IP地址信息。例如192.168.1.2 - - upload\_net\_client\_mask:设置开发板的子网掩码,工具会自动根据选择的upload\_net\_server\_ip进行设置。例如255.255.255.0 - - upload\_net\_client\_gw:设置开发板的网关,工具会自动根据选择的upload\_net\_server\_ip进行设置。例如192.168.1.1 - - upload\_net\_client\_ip:设置开发板的IP地址,工具会自动根据选择的upload\_net\_server\_ip进行设置。例如192.168.1.3 - - ![](figures/zh-cn_image_0000001174270733.png) - -8. 所有的配置都修改完成后,在工程配置页签的顶部,点击**Save**进行保存。 -9. 打开工程文件,点击![](figures/2021-01-27_170334-2.png)图标,打开DevEco Device Tool界面,在“PROJECT TASKS”中,点击hi3516dv300下的**Upload**按钮,启动烧录。 - - ![](figures/zh-cn_image_0000001174270729.png) - -10. 启动烧录后,显示如下提示信息时,请重启开发板(下电再上电)。 - - ![](figures/zh-cn_image_0000001128470906.png) - -11. 重新上电后,启动烧录,界面提示如下信息时,表示烧录成功。 - - ![](figures/zh-cn_image_0000001128311098.png) - - -## 镜像运行 - -1. 连接串口。 - - >![](public_sys-resources/icon-notice.gif) **须知:** - >若无法连接串口,请参考[常见问题](../quick-start/常见问题-3.md)进行排查。 - - **图 2** 连接串口图 - - - ![](figures/chuankou1.png) - - 1. 单击**Monitor**打开串口。 - 2. 连续输入回车直到串口显示"hisilicon"。 - 3. 单板初次启动或修改启动参数,请进入[步骤2](#l5b42e79a33ea4d35982b78a22913b0b1),否则进入[步骤3](#ld26f18828aa44c36bfa36be150e60e49)。 - -2. (单板初次启动必选)修改U-boot的bootcmd及bootargs内容:该步骤为固化操作,若不修改参数只需执行一次。每次复位单板均会自动进入系统。 - - >![](public_sys-resources/icon-notice.gif) **须知:** - >U-boot引导程序默认会有2秒的等待时间,用户可使用回车打断等待并显示"hisilicon",通过**reset**命令可再次启动系统。 - - **表 1** U-boot修改命令 - - - - - - - - - - - - - - - - - - - -

    执行命令

    -

    命令解释

    -

    setenv bootcmd "mmc read 0x0 0x80000000 0x800 0x4800; go 0x80000000";

    -

    读取FLASH起始地址为0x800(单位为512B,即1MB),大小为0x4800(单位为512B,即9MB)的内容到0x80000000的内存地址,该大小(9MB)与IDE中所填写OHOS_Image.bin文件大小必须相同

    -

    setenv bootargs "console=ttyAMA0,115200n8 root=emmc fstype=vfat rootaddr=10M rootsize=20M rw";

    -

    表示设置启动参数,输出模式为串口输出,波特率为115200,数据位8,rootfs挂载于emmc器件,文件系统类型为vfat,

    -

    “rootaddr=10M rootsize=20M rw”处对应填入rootfs.img的烧写起始位置与长度,此处与IDE中新增rootfs.img文件时所填大小必须相同

    -

    saveenv

    -

    表示保存当前配置。

    -

    reset

    -

    表示复位单板。

    -
    - - >![](public_sys-resources/icon-notice.gif) **须知:** - >**“go 0x80000000”**为可选指令,默认配置已将该指令固化在启动参数中,单板复位后可自动启动。若想切换为手动启动,可在U-boot启动倒数阶段使用"回车"打断自动启动。 - -3. 输入**“reset”**指令并回车,重启单板,启动成功如下图,输入回车串口显示OHOS字样。 - - **图 3** 系统启动图 - - - ![](figures/qi1.png) - - -## 执行应用程序 - -根目录下,在命令行输入指令“**./bin/helloworld**”执行写入的demo程序,显示成功结果如下图所示。 - -**图 4** 启动并成功执行应用程序图 -![](figures/启动并成功执行应用程序图.png "启动并成功执行应用程序图") - diff --git "a/zh-cn/device-dev/quick-start/\350\277\220\350\241\214Hello-World.md" "b/zh-cn/device-dev/quick-start/\350\277\220\350\241\214Hello-World.md" deleted file mode 100755 index f428ec411e..0000000000 --- "a/zh-cn/device-dev/quick-start/\350\277\220\350\241\214Hello-World.md" +++ /dev/null @@ -1,158 +0,0 @@ -# 运行Hello World - -- [修改源码](#section79601457101015) -- [调测验证](#section1621064881419) -- [printf打印](#section1246911301217) -- [根据asm文件进行问题定位](#section199621957141014) -- [运行结果](#section18115713118) -- [下一步学习](#section9712145420182) - -本示例将演示如何编写简单业务,输出“Hello World”,初步了解OpenHarmony 如何运行在开发板上。 - -## 修改源码 - -bugfix和新增业务两种情况,涉及源码修改。下面以新增业务(my\_first\_app)为例,向开发者介绍如何进行源码修改。 - -1. 确定目录结构。 - - 开发者编写业务时,务必先在./applications/sample/wifi-iot/app路径下新建一个目录(或一套目录结构),用于存放业务源码文件。 - - 例如:在app下新增业务my\_first\_app,其中hello\_world.c为业务代码,BUILD.gn为编译脚本,具体规划目录结构如下: - - ``` - . - └── applications - └── sample - └── wifi-iot - └── app - │── my_first_app - │ │── hello_world.c - │ └── BUILD.gn - └── BUILD.gn - ``` - -2. 编写业务代码。 - - 新建./applications/sample/wifi-iot/app/my\_first\_app下的hello\_world.c文件,在hello\_world.c中新建业务入口函数HelloWorld,并实现业务逻辑。并在代码最下方,使用OpenHarmony启动恢复模块接口SYS\_RUN\(\)启动业务。(SYS\_RUN定义在ohos\_init.h文件中) - - ``` - #include - #include "ohos_init.h" - #include "ohos_types.h" - - void HelloWorld(void) - { - printf("[DEMO] Hello world.\n"); - } - SYS_RUN(HelloWorld); - ``` - -3. 编写用于将业务构建成静态库的BUILD.gn文件。 - - 新建./applications/sample/wifi-iot/app/my\_first\_app下的BUILD.gn文件,并完成如下配置。 - - 如[步骤1](#li5479332115116)所述,BUILD.gn文件由三部分内容(目标、源文件、头文件路径)构成,需由开发者完成填写。 - - ``` - static_library("myapp") { - sources = [ - "hello_world.c" - ] - include_dirs = [ - "//utils/native/lite/include" - ] - } - ``` - - - static\_library中指定业务模块的编译结果,为静态库文件libmyapp.a,开发者根据实际情况完成填写。 - - sources中指定静态库.a所依赖的.c文件及其路径,若路径中包含"//"则表示绝对路径(此处为代码根路径),若不包含"//"则表示相对路径。 - - include\_dirs中指定source所需要依赖的.h文件路径。 - -4. 编写模块BUILD.gn文件,指定需参与构建的特性模块。 - - 配置./applications/sample/wifi-iot/app/BUILD.gn文件,在features字段中增加索引,使目标模块参与编译。features字段指定业务模块的路径和目标,以my\_first\_app举例,features字段配置如下。 - - ``` - import("//build/lite/config/component/lite_component.gni") - - lite_component("app") { - features = [ - "my_first_app:myapp", - ] - } - ``` - - - my\_first\_app是相对路径,指向./applications/sample/wifi-iot/app/my\_first\_app/BUILD.gn。 - - myapp是目标,指向./applications/sample/wifi-iot/app/my\_first\_app/BUILD.gn中的static\_library\("myapp"\)。 - - -## 调测验证 - -目前调试验证的方法有两种,分别为通过printf打印日志、通过asm文件定位panic问题,开发者可以根据具体业务情况选择。 - -由于本示例业务简单,采用printf打印日志的调试方式即可。下面开始介绍这两种调试手段的使用方法。 - -## printf打印 - -代码中增加printf维测,信息会直接打印到串口上。开发者可在业务关键路径或业务异常位置增加日志打印,如下所示。 - -``` -void HelloWorld(void) -{ - printf("[DEMO] Hello world.\n"); -} -``` - -## 根据asm文件进行问题定位 - -系统异常退出时,会在串口上打印异常退出原因调用栈信息,如下文所示。通过解析异常栈信息可以定位异常位置。 - -``` -=======KERNEL PANIC======= -**********************Call Stack********************* -Call Stack 0 -- 4860d8 addr:f784c -Call Stack 1 -- 47b2b2 addr:f788c -Call Stack 2 -- 3e562c addr:f789c -Call Stack 3 -- 4101de addr:f78ac -Call Stack 4 -- 3e5f32 addr:f78cc -Call Stack 5 -- 3f78c0 addr:f78ec -Call Stack 6 -- 3f5e24 addr:f78fc -********************Call Stack end******************* -``` - -为解析上述调用栈信息,需要使用到Hi3861\_wifiiot\_app.asm文件,该文件记录了代码中函数在Flash上的符号地址以及反汇编信息。asm文件会随版本大包一同构建输出,存放在./out/wifiiot/路径下。 - -1. 将调用栈CallStack信息保存到txt文档中,以便于编辑。(可选) -2. 打开asm文件,并搜索CallStack中的地址,列出对应的函数名 信息。通常只需找出前几个栈信息对应的函数,就可明确异常代码方向。 - - ``` - Call Stack 0 -- 4860d8 addr:f784c -- WadRecvCB - Call Stack 1 -- 47b2b2 addr:f788c -- wal_sdp_process_rx_data - Call Stack 2 -- 3e562c addr:f789c - Call Stack 3 -- 4101de addr:f78ac - Call Stack 4 -- 3e5f32 addr:f78cc - Call Stack 5 -- 3f78c0 addr:f78ec - Call Stack 6 -- 3f5e24 addr:f78fc - ``` - -3. 根据以上调用栈信息,可以定位WadRecvCB函数中出现了异常。 - - ![](figures/zh-cn_image_0000001174270737.png) - -4. 完成代码排查及修改。 - -## 运行结果 - -示例代码编译、烧录、运行、调测后,在串口界面会显示如下结果: - -``` -ready to OS start -FileSystem mount ok. -wifi init success! -[DEMO] Hello world. -``` - -## 下一步学习 - -恭喜,您已完成Hi3861 WLAN模组快速上手!建议您下一步进入[WLAN产品开发](../guide/概述.md)的学习 。 - diff --git "a/zh-cn/device-dev/quick-start/\351\225\234\345\203\217\347\203\247\345\275\225.md" "b/zh-cn/device-dev/quick-start/\351\225\234\345\203\217\347\203\247\345\275\225.md" deleted file mode 100644 index 3fca75cfcd..0000000000 --- "a/zh-cn/device-dev/quick-start/\351\225\234\345\203\217\347\203\247\345\275\225.md" +++ /dev/null @@ -1,201 +0,0 @@ -# 镜像烧录 - -- [下一步](#section5600113114323) - -标准系统烧录,在V2.2 Beta1及以上版本支持。 - -Hi3516DV300支持烧录标准系统,其烧录方式包括网口烧录和串口烧录三种方式,其中: - -- **Windows系统:支持网口烧录和串口烧录** -- **Linux系统:支持串口烧录和网口烧录。** - -同一种烧录方式(如网口烧录),在Windows和Linux环境下的烧录操作完全一致,区别仅在于DevEco Device Tool环境搭建不同。 - ->![](public_sys-resources/icon-note.gif) **说明:** ->当前Hi3516DV300开发板支持通过网口、USB、串口三种方式烧录OpenHarmony标准系统。本文以网口方式为例讲解烧录操作,其他两种烧录方式请参照[Hi3516DV300烧录指导](https://device.harmonyos.com/cn/docs/ide/user-guides/hi3516_upload-0000001052148681)。 - -### 前提条件 - -在DevEco Device Tool中[打开一个工程](https://device.harmonyos.com/cn/docs/ide/user-guides/open_project-0000001071680043),该工程文件夹选择待烧录文件所在文件夹即可。其中开发板类型固定选择Hi3516DV300,Framework选择“Hb”。 - -### 使用网口烧录 - -Hi3516DV300开发板使用网口录方式,支持Windows和Linux系统。 - -1. 请连接好电脑和待烧录开发板,需要同时连接串口、网口和电源,具体可参考[Hi3516DV300开发板介绍](https://device.harmonyos.com/cn/docs/start/introduce/oem_minitinier_des_3516-0000001152041033)。 -2. 打开电脑的设备管理器,查看并记录对应的串口号。 - - >![](public_sys-resources/icon-note.gif) **说明:** - >如果对应的串口异常,请根据[Hi3516DV300/Hi3518EV300开发板串口驱动安装指导](https://device.harmonyos.com/cn/docs/ide/user-guides/hi3516_hi3518-drivers-0000001050743695)安装USB转串口的驱动程序。 - - ![](figures/zh-cn_image_0000001114129428.png) - -3. 打开DevEco Device Tool,在Projects中,点击**Settings**打开工程配置界面。 - - ![](figures/2021-01-27_170334-17.png) - -4. 在**Partition Configuration**页签中,按照下表内容填写烧录文件信息,包括: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    Name

    -

    Binary

    -

    Memory

    -

    System

    -

    Address

    -

    Length

    -

    Board

    -

    Type

    -

    fastboot

    -

    选择“u-boot-hi3516dv300_emmc.bin”

    -

    emmc

    -

    none

    -

    0x000000

    -

    0x100000

    -

    固定选择“hi3516dv300”

    -

    NA

    -

    boot

    -

    选择“uImage”

    -

    emmc

    -

    none

    -

    0x100000

    -

    0xf00000

    -

    NA

    -

    updater

    -

    选择“updater.img”

    -

    emmc

    -

    ext3/4

    -

    0x1000000

    -

    0x1400000

    -

    NA

    -

    misc

    -

    空白,不用选择

    -

    emmc

    -

    none

    -

    0x2400000

    -

    0x100000

    -

    NA

    -

    system

    -

    选择“system.img”

    -

    emmc

    -

    ext3/4

    -

    0x2500000

    -

    0xceb00000

    -

    NA

    -

    vendor

    -

    选择“vendor.img”

    -

    emmc

    -

    ext3/4

    -

    0xd1000000

    -

    0x10000000

    -

    NA

    -

    userdata

    -

    选择“userdata.img”

    -

    emmc

    -

    ext3/4

    -

    0xe1000000

    -

    0x5b800000

    -

    NA

    -
    - - ![](figures/zh-cn_image_0000001130584312.png) - -5. 在“hi3516dv300”页签,设置烧录选项,包括upload\_port、upload\_partitions和upload\_protocol。 - - - upload\_port:选择步骤[2](#zh-cn_topic_0000001056443961_li1050616379507)中查询的串口号。 - - upload\_protocol:选择烧录协议,固定选择“hiburn-net”。 - - upload\_partitions:选择待烧录的文件,包括fastboot、boot、updater、misc、system、vendor和userdata。 - - ![](figures/zh-cn_image_0000001117621400.png) - -6. 检查和设置连接开发板后的网络适配器的IP地址信息,设置方法请参考[设置Hi3516DV300网口烧录的IP地址信息](https://device.harmonyos.com/cn/docs/ide/user-guides/set_ipaddress-0000001141825075)。 -7. 设置网口烧录的IP地址信息,设置如下选项: - - - upload\_net\_server\_ip:选择步骤6中设置的IP地址信息。例如192.168.1.2 - - upload\_net\_client\_mask:设置开发板的子网掩码,工具会自动根据选择的upload\_net\_server\_ip进行设置。例如255.255.255.0 - - upload\_net\_client\_gw:设置开发板的网关,工具会自动根据选择的upload\_net\_server\_ip进行设置。例如192.168.1.1 - - upload\_net\_client\_ip:设置开发板的IP地址,工具会自动根据选择的upload\_net\_server\_ip进行设置。例如192.168.1.3 - - ![](figures/zh-cn_image_0000001117463460.png) - -8. 所有的配置都修改完成后,在工程配置页签的顶部,点击**Save**进行保存。 -9. 启动烧录后,显示如下提示信息时,请重启开发板(下电再上电)。 - - ![](figures/zh-cn_image_0000001114129432.png) - -10. 重新上电后,启动烧录,界面提示如下信息时,表示烧录成功。 - - ![](figures/zh-cn_image_0000001113969542.png) - - -## 下一步 - -恭喜!您已经完成了OpenHarmony标准系统的快速入门,接下来可[开发一个小示例](../guide/时钟应用开发示例.md),进一步熟悉OpenHarmony的开发。 - diff --git "a/zh-cn/device-dev/quick-start/\351\251\261\345\212\250\345\274\200\345\217\221\347\244\272\344\276\213.md" "b/zh-cn/device-dev/quick-start/\351\251\261\345\212\250\345\274\200\345\217\221\347\244\272\344\276\213.md" deleted file mode 100755 index f9eb065a5d..0000000000 --- "a/zh-cn/device-dev/quick-start/\351\251\261\345\212\250\345\274\200\345\217\221\347\244\272\344\276\213.md" +++ /dev/null @@ -1,503 +0,0 @@ -# 驱动开发示例 - -- [驱动程序介绍](#s8efc1952ebfe4d1ea717182e108c29bb) -- [编译和烧写](#section660016185110) -- [镜像运行](#section333215226219) -- [下一步学习](#section9712145420182) - -本节指导开发者在单板上运行第一个驱动程序,其中包括驱动程序介绍、编译、烧写、运行等步骤。 - -## 驱动程序介绍 - -下面基于HDF框架,提供一个简单的UART(Universal Asynchronous Receiver/Transmitter)平台驱动开发样例,包含配置文件的添加,驱动代码的实现以及用户态程序和驱动交互的流程。驱动程序源码位于vendor/huawei/hdf/sample目录 - -1. 添加配置。 - - 在HDF框架的驱动配置文件(例如device/hisilicon/hi3516dv300/sdk\_liteos/config/uart/uart\_config.hcs)中添加该驱动的配置信息,如下所示: - - ``` - root { - platform { - uart_sample { - num = 5; // UART设备编号 - base = 0x120a0000; // UART 寄存器基地址 - irqNum = 38; - baudrate = 115200; - uartClk = 24000000; - wlen = 0x60; - parity = 0; - stopBit = 0; - match_attr = "sample_uart_5"; - } - } - } - ``` - - 在HDF框架的设备配置文件(例如vendor/hisilicon/ipcamera\_hi3516dv300\_liteos/config/device\_info/device\_info.hcs)中添加该驱动的设备节点信息,如下所示: - - ``` - root { - device_info { - platform :: host { - hostName = "platform_host"; - priority = 50; - device_uart :: device { - device5 :: deviceNode { - policy = 2; - priority = 10; - permission = 0660; - moduleName = "UART_SAMPLE"; - serviceName = "HDF_PLATFORM_UART_5"; - deviceMatchAttr = "sample_uart_5"; - } - } - } - } - } - ``` - - >![](public_sys-resources/icon-note.gif) **说明:** - >配置文件与UART驱动示例的源码在同一个路径,需要手动添加到Hi3516DV300单板路径下。 - -2. 注册UART驱动入口。 - - 基于HDF框架注册UART驱动的入口HdfDriverEntry,代码如下: - - ``` - // 绑定UART驱动接口到HDF框架 - static int32_t SampleUartDriverBind(struct HdfDeviceObject *device) - { - struct UartHost *uartHost = NULL; - - if (device == NULL) { - return HDF_ERR_INVALID_OBJECT; - } - HDF_LOGI("Enter %s:", __func__); - - uartHost = UartHostCreate(device); - if (uartHost == NULL) { - HDF_LOGE("%s: UartHostCreate failed", __func__); - return HDF_FAILURE; - } - uartHost->service.Dispatch = SampleDispatch; - return HDF_SUCCESS; - } - - // 从UART驱动的HCS中获取配置信息 - static uint32_t GetUartDeviceResource( - struct UartDevice *device, const struct DeviceResourceNode *resourceNode) - { - struct UartResource *resource = &device->resource; - struct DeviceResourceIface *dri = NULL; - dri = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE); - if (dri == NULL || dri->GetUint32 == NULL) { - HDF_LOGE("DeviceResourceIface is invalid"); - return HDF_FAILURE; - } - - if (dri->GetUint32(resourceNode, "num", &resource->num, 0) != HDF_SUCCESS) { - HDF_LOGE("uart config read num fail"); - return HDF_FAILURE; - } - if (dri->GetUint32(resourceNode, "base", &resource->base, 0) != HDF_SUCCESS) { - HDF_LOGE("uart config read base fail"); - return HDF_FAILURE; - } - resource->physBase = (unsigned long)OsalIoRemap(resource->base, 0x48); - if (resource->physBase == 0) { - HDF_LOGE("uart config fail to remap physBase"); - return HDF_FAILURE; - } - if (dri->GetUint32(resourceNode, "irqNum", &resource->irqNum, 0) != HDF_SUCCESS) { - HDF_LOGE("uart config read irqNum fail"); - return HDF_FAILURE; - } - if (dri->GetUint32(resourceNode, "baudrate", &resource->baudrate, 0) != HDF_SUCCESS) { - HDF_LOGE("uart config read baudrate fail"); - return HDF_FAILURE; - } - if (dri->GetUint32(resourceNode, "wlen", &resource->wlen, 0) != HDF_SUCCESS) { - HDF_LOGE("uart config read wlen fail"); - return HDF_FAILURE; - } - if (dri->GetUint32(resourceNode, "parity", &resource->parity, 0) != HDF_SUCCESS) { - HDF_LOGE("uart config read parity fail"); - return HDF_FAILURE; - } - if (dri->GetUint32(resourceNode, "stopBit", &resource->stopBit, 0) != HDF_SUCCESS) { - HDF_LOGE("uart config read stopBit fail"); - return HDF_FAILURE; - } - if (dri->GetUint32(resourceNode, "uartClk", &resource->uartClk, 0) != HDF_SUCCESS) { - HDF_LOGE("uart config read uartClk fail"); - return HDF_FAILURE; - } - return HDF_SUCCESS; - } - - // 将UART驱动的配置和接口附加到HDF驱动框架 - static int32_t AttachUartDevice(struct UartHost *host, struct HdfDeviceObject *device) - { - int32_t ret; - struct UartDevice *uartDevice = NULL; - if (device->property == NULL) { - HDF_LOGE("%s: property is NULL", __func__); - return HDF_FAILURE; - } - uartDevice = (struct UartDevice *)OsalMemCalloc(sizeof(struct UartDevice)); - if (uartDevice == NULL) { - HDF_LOGE("%s: OsalMemCalloc uartDevice error", __func__); - return HDF_ERR_MALLOC_FAIL; - } - ret = GetUartDeviceResource(uartDevice, device->property); - if (ret != HDF_SUCCESS) { - (void)OsalMemFree(uartDevice); - return HDF_FAILURE; - } - host->num = uartDevice->resource.num; - host->priv = uartDevice; - AddUartDevice(host); - return InitUartDevice(uartDevice); - } - - // 初始化UART驱动 - static int32_t SampleUartDriverInit(struct HdfDeviceObject *device) - { - int32_t ret; - struct UartHost *host = NULL; - - if (device == NULL) { - HDF_LOGE("%s: device is NULL", __func__); - return HDF_ERR_INVALID_OBJECT; - } - HDF_LOGI("Enter %s:", __func__); - host = UartHostFromDevice(device); - if (host == NULL) { - HDF_LOGE("%s: host is NULL", __func__); - return HDF_FAILURE; - } - ret = AttachUartDevice(host, device); - if (ret != HDF_SUCCESS) { - HDF_LOGE("%s: attach error", __func__); - return HDF_FAILURE; - } - host->method = &g_sampleUartHostMethod; - return ret; - } - - static void DeinitUartDevice(struct UartDevice *device) - { - struct UartRegisterMap *regMap = (struct UartRegisterMap *)device->resource.physBase; - /* wait for uart enter idle. */ - while (UartPl011IsBusy(regMap)); - UartPl011ResetRegisters(regMap); - uart_clk_cfg(0, false); - OsalIoUnmap((void *)device->resource.physBase); - device->state = UART_DEVICE_UNINITIALIZED; - } - - // 解绑并释放UART驱动 - static void DetachUartDevice(struct UartHost *host) - { - struct UartDevice *uartDevice = NULL; - - if (host->priv == NULL) { - HDF_LOGE("%s: invalid parameter", __func__); - return; - } - uartDevice = host->priv; - DeinitUartDevice(uartDevice); - (void)OsalMemFree(uartDevice); - host->priv = NULL; - } - - // 释放UART驱动 - static void SampleUartDriverRelease(struct HdfDeviceObject *device) - { - struct UartHost *host = NULL; - HDF_LOGI("Enter %s:", __func__); - - if (device == NULL) { - HDF_LOGE("%s: device is NULL", __func__); - return; - } - host = UartHostFromDevice(device); - if (host == NULL) { - HDF_LOGE("%s: host is NULL", __func__); - return; - } - if (host->priv != NULL) { - DetachUartDevice(host); - } - UartHostDestroy(host); - } - - struct HdfDriverEntry g_sampleUartDriverEntry = { - .moduleVersion = 1, - .moduleName = "UART_SAMPLE", - .Bind = SampleUartDriverBind, - .Init = SampleUartDriverInit, - .Release = SampleUartDriverRelease, - }; - - HDF_INIT(g_sampleUartDriverEntry); - ``` - -3. 注册UART驱动接口。 - - HDF框架提供了UART驱动接口的模板方法UartHostMethod,实现UART驱动接口的代码如下: - - ``` - static int32_t SampleUartHostInit(struct UartHost *host) - { - HDF_LOGI("%s: Enter", __func__); - if (host == NULL) { - HDF_LOGE("%s: invalid parameter", __func__); - return HDF_ERR_INVALID_PARAM; - } - return HDF_SUCCESS; - } - - static int32_t SampleUartHostDeinit(struct UartHost *host) - { - HDF_LOGI("%s: Enter", __func__); - if (host == NULL) { - HDF_LOGE("%s: invalid parameter", __func__); - return HDF_ERR_INVALID_PARAM; - } - return HDF_SUCCESS; - } - - // 向UART中写入数据 - static int32_t SampleUartHostWrite(struct UartHost *host, uint8_t *data, uint32_t size) - { - HDF_LOGI("%s: Enter", __func__); - uint32_t idx; - struct UartRegisterMap *regMap = NULL; - struct UartDevice *device = NULL; - - if (host == NULL || data == NULL || size == 0) { - HDF_LOGE("%s: invalid parameter", __func__); - return HDF_ERR_INVALID_PARAM; - } - device = (struct UartDevice *)host->priv; - if (device == NULL) { - HDF_LOGE("%s: device is NULL", __func__); - return HDF_ERR_INVALID_PARAM; - } - regMap = (struct UartRegisterMap *)device->resource.physBase; - for (idx = 0; idx < size; idx++) { - UartPl011Write(regMap, data[idx]); - } - return HDF_SUCCESS; - } - - // 设置UART的波特率 - static int32_t SampleUartHostSetBaud(struct UartHost *host, uint32_t baudRate) - { - HDF_LOGI("%s: Enter", __func__); - struct UartDevice *device = NULL; - struct UartRegisterMap *regMap = NULL; - UartPl011Error err; - - if (host == NULL) { - HDF_LOGE("%s: invalid parameter", __func__); - return HDF_ERR_INVALID_PARAM; - } - device = (struct UartDevice *)host->priv; - if (device == NULL) { - HDF_LOGE("%s: device is NULL", __func__); - return HDF_ERR_INVALID_PARAM; - } - regMap = (struct UartRegisterMap *)device->resource.physBase; - if (device->state != UART_DEVICE_INITIALIZED) { - return UART_PL011_ERR_NOT_INIT; - } - if (baudRate == 0) { - return UART_PL011_ERR_INVALID_BAUD; - } - err = UartPl011SetBaudrate(regMap, device->uartClk, baudRate); - if (err == UART_PL011_ERR_NONE) { - device->baudrate = baudRate; - } - return err; - } - - // 获取UART的波特率 - static int32_t SampleUartHostGetBaud(struct UartHost *host, uint32_t *baudRate) - { - HDF_LOGI("%s: Enter", __func__); - struct UartDevice *device = NULL; - - if (host == NULL) { - HDF_LOGE("%s: invalid parameter", __func__); - return HDF_ERR_INVALID_PARAM; - } - device = (struct UartDevice *)host->priv; - if (device == NULL) { - HDF_LOGE("%s: device is NULL", __func__); - return HDF_ERR_INVALID_PARAM; - } - *baudRate = device->baudrate; - return HDF_SUCCESS; - } - - // 在HdfUartSampleInit方法中绑定 - struct UartHostMethod g_sampleUartHostMethod = { - .Init = SampleUartHostInit, - .Deinit = SampleUartHostDeinit, - .Read = NULL, - .Write = SampleUartHostWrite, - .SetBaud = SampleUartHostSetBaud, - .GetBaud = SampleUartHostGetBaud, - .SetAttribute = NULL, - .GetAttribute = NULL, - .SetTransMode = NULL, - }; - ``` - - 在device/hisilicon/drivers/lite.mk编译脚本中增加示例UART驱动模块,代码如下: - - ``` - LITEOS_BASELIB += -lhdf_uart_sample - LIB_SUBDIRS += $(LITEOS_SOURCE_ROOT)/vendor/huawei/hdf/sample/platform/uart - ``` - -4. 用户程序和驱动交互代码。 - - UART驱动成功初始化后,会创建/dev/uartdev-5设备节点,通过设备节点与UART驱动交互的代码如下: - - ``` - #include - #include - #include - #include "hdf_log.h" - - #define HDF_LOG_TAG "hello_uart" - #define INFO_SIZE 16 - - int main(void) - { - int ret; - int fd; - const char info[INFO_SIZE] = {" HELLO UART! "}; - - fd = open("/dev/uartdev-5", O_RDWR); - if (fd < 0) { - HDF_LOGE("hello_uart uartdev-5 open failed %d", fd); - return -1; - } - ret = write(fd, info, INFO_SIZE); - if (ret != 0) { - HDF_LOGE("hello_uart write uartdev-5 ret is %d", ret); - } - ret = close(fd); - if (ret != 0) { - HDF_LOGE("hello_uart uartdev-5 close failed %d", fd); - return -1; - } - return ret; - } - ``` - - 在build/lite/components/drivers.json驱动配置中hdf\_hi3516dv300\_liteos\_a组件下的targets中增加hello\_uart\_sample组件,代码如下: - - ``` - { - "components": [ - { - "component": "hdf_hi3516dv300_liteos_a", - ... - "targets": [ - "//vendor/huawei/hdf/sample/platform/uart:hello_uart_sample" - ] - } - ] - } - ``` - - >![](public_sys-resources/icon-note.gif) **说明:** - >如上代码均为示例代码,完整代码可以在vendor/huawei/hdf/sample查看。 - >示例代码默认不参与编译,需要手动添加到编译脚本中。 - - -## 编译和烧写 - -参考示例1进行编译和烧写:[编译](../quick-start/驱动开发示例.md)、[烧录](../quick-start/驱动开发示例.md) - -## 镜像运行 - -1. 连接串口。 - - >![](public_sys-resources/icon-notice.gif) **须知:** - >若无法连接串口,请参考[常见问题](../quick-start/常见问题-3.md)进行排查。 - - **图 1** 连接串口图 - - - ![](figures/chuankou1.png) - - 1. 单击**Monitor**打开串口。 - 2. 连续输入回车直到串口显示"hisilicon"。 - 3. 单板初次启动或修改启动参数,请进入[步骤2](运行Hello-OHOS.md#l5b42e79a33ea4d35982b78a22913b0b1),否则进入[步骤3](运行Hello-OHOS.md#ld26f18828aa44c36bfa36be150e60e49)。 - -2. (单板初次启动必选)修改U-boot的bootcmd及bootargs内容:该步骤为固化操作,若不修改参数只需执行一次。每次复位单板均会自动进入系统。 - - >![](public_sys-resources/icon-notice.gif) **须知:** - >U-boot引导程序默认会有2秒的等待时间,用户可使用回车打断等待并显示"hisilicon",通过**reset**命令可再次启动系统。 - - **表 1** U-boot修改命令 - - - - - - - - - - - - - - - - - - - -

    执行命令

    -

    命令解释

    -

    setenv bootcmd "mmc read 0x0 0x80000000 0x800 0x4800; go 0x80000000";

    -

    读取FLASH起始地址为0x800(单位为512B,即1MB),大小为0x4800(单位为512B,即9MB)的内容到0x80000000的内存地址,该大小(9MB)与IDE中所填写OHOS_Image.bin文件大小必须相同

    -

    setenv bootargs "console=ttyAMA0,115200n8 root=emmc fstype=vfat rootaddr=10M rootsize=20M rw";

    -

    表示设置启动参数,输出模式为串口输出,波特率为115200,数据位8,rootfs挂载于emmc器件,文件系统类型为vfat,

    -

    “rootaddr=10M rootsize=20M rw”处对应填入rootfs.img的烧写起始位置与长度,此处与IDE中新增rootfs.img文件时所填大小必须相同

    -

    saveenv

    -

    表示保存当前配置。

    -

    reset

    -

    表示复位单板。

    -
    - - >![](public_sys-resources/icon-notice.gif) **须知:** - >**“go 0x80000000”**为可选指令,默认配置已将该指令固化在启动参数中,单板复位后可自动启动。若想切换为手动启动,可在U-boot启动倒数阶段使用"回车"打断自动启动。 - -3. 输入**“reset”**指令并回车,重启单板,启动成功如下图,输入回车串口显示OHOS字样。 - - **图 2** 系统启动图 - - - ![](figures/qi1.png) - -4. 根目录下,在命令行输入指令“**./bin/hello\_uart**”执行写入的demo程序,显示成功结果如下所示。 - - ``` - OHOS # ./bin/hello_uart - OHOS # HELLO UART! - ``` - - -## 下一步学习 - -恭喜,您已完成Hi3516 快速上手!建议您下一步进入[带屏摄像头产品开发](../guide/屏幕和摄像头控制.md)的学习 。 - diff --git a/zh-cn/device-dev/security/Readme-CN.md b/zh-cn/device-dev/security/Readme-CN.md index 3eb2062d71..9a8e221f7f 100755 --- a/zh-cn/device-dev/security/Readme-CN.md +++ b/zh-cn/device-dev/security/Readme-CN.md @@ -1,5 +1,5 @@ # 隐私与安全 -- [隐私保护](隐私保护.md) -- [安全指南](安全指南.md) +- [隐私保护](safety-protection-privacyguide.md) +- [安全指南](safety-safeguide-security.md) diff --git "a/zh-cn/device-dev/security/figures/1-\346\225\217\346\204\237\346\235\203\351\231\220\345\274\271\347\252\227.png" "b/zh-cn/device-dev/security/figure/1-\346\225\217\346\204\237\346\235\203\351\231\220\345\274\271\347\252\227.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/security/figures/1-\346\225\217\346\204\237\346\235\203\351\231\220\345\274\271\347\252\227.png" rename to "zh-cn/device-dev/security/figure/1-\346\225\217\346\204\237\346\235\203\351\231\220\345\274\271\347\252\227.png" diff --git "a/zh-cn/device-dev/security/figures/2-\345\272\224\347\224\250\345\220\257\345\212\250\351\242\204\346\216\210\346\235\203.png" "b/zh-cn/device-dev/security/figure/2-\345\272\224\347\224\250\345\220\257\345\212\250\351\242\204\346\216\210\346\235\203.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/security/figures/2-\345\272\224\347\224\250\345\220\257\345\212\250\351\242\204\346\216\210\346\235\203.png" rename to "zh-cn/device-dev/security/figure/2-\345\272\224\347\224\250\345\220\257\345\212\250\351\242\204\346\216\210\346\235\203.png" diff --git "a/zh-cn/device-dev/security/figures/3-\345\272\224\347\224\250\351\232\220\347\247\201\345\243\260\346\230\216.png" "b/zh-cn/device-dev/security/figure/3-\345\272\224\347\224\250\351\232\220\347\247\201\345\243\260\346\230\216.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/security/figures/3-\345\272\224\347\224\250\351\232\220\347\247\201\345\243\260\346\230\216.png" rename to "zh-cn/device-dev/security/figure/3-\345\272\224\347\224\250\351\232\220\347\247\201\345\243\260\346\230\216.png" diff --git "a/zh-cn/device-dev/security/figures/4-\351\232\220\347\247\201\345\243\260\346\230\216\345\217\230\346\233\264\351\200\232\347\237\245.png" "b/zh-cn/device-dev/security/figure/4-\351\232\220\347\247\201\345\243\260\346\230\216\345\217\230\346\233\264\351\200\232\347\237\245.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/security/figures/4-\351\232\220\347\247\201\345\243\260\346\230\216\345\217\230\346\233\264\351\200\232\347\237\245.png" rename to "zh-cn/device-dev/security/figure/4-\351\232\220\347\247\201\345\243\260\346\230\216\345\217\230\346\233\264\351\200\232\347\237\245.png" diff --git "a/zh-cn/device-dev/security/figures/5-\345\272\224\347\224\250\351\232\220\347\247\201\345\243\260\346\230\216\345\205\245\345\217\243.png" "b/zh-cn/device-dev/security/figure/5-\345\272\224\347\224\250\351\232\220\347\247\201\345\243\260\346\230\216\345\205\245\345\217\243.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/security/figures/5-\345\272\224\347\224\250\351\232\220\347\247\201\345\243\260\346\230\216\345\205\245\345\217\243.png" rename to "zh-cn/device-dev/security/figure/5-\345\272\224\347\224\250\351\232\220\347\247\201\345\243\260\346\230\216\345\205\245\345\217\243.png" diff --git "a/zh-cn/device-dev/security/figures/6-1-\351\232\220\347\247\201\345\243\260\346\230\216\346\222\244\351\224\200.png" "b/zh-cn/device-dev/security/figure/6-1-\351\232\220\347\247\201\345\243\260\346\230\216\346\222\244\351\224\200.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/security/figures/6-1-\351\232\220\347\247\201\345\243\260\346\230\216\346\222\244\351\224\200.png" rename to "zh-cn/device-dev/security/figure/6-1-\351\232\220\347\247\201\345\243\260\346\230\216\346\222\244\351\224\200.png" diff --git "a/zh-cn/device-dev/security/figures/6-2-\351\232\220\347\247\201\345\243\260\346\230\216\346\222\244\351\224\200.png" "b/zh-cn/device-dev/security/figure/6-2-\351\232\220\347\247\201\345\243\260\346\230\216\346\222\244\351\224\200.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/security/figures/6-2-\351\232\220\347\247\201\345\243\260\346\230\216\346\222\244\351\224\200.png" rename to "zh-cn/device-dev/security/figure/6-2-\351\232\220\347\247\201\345\243\260\346\230\216\346\222\244\351\224\200.png" diff --git "a/zh-cn/device-dev/security/figures/DAC\346\265\201\347\250\213\345\233\276.png" "b/zh-cn/device-dev/security/figure/DAC\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/security/figures/DAC\346\265\201\347\250\213\345\233\276.png" rename to "zh-cn/device-dev/security/figure/DAC\346\265\201\347\250\213\345\233\276.png" diff --git "a/zh-cn/device-dev/security/figures/HUKS\345\212\237\350\203\275\347\273\223\346\236\204\345\233\276.png" "b/zh-cn/device-dev/security/figure/HUKS\345\212\237\350\203\275\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/security/figures/HUKS\345\212\237\350\203\275\347\273\223\346\236\204\345\233\276.png" rename to "zh-cn/device-dev/security/figure/HUKS\345\212\237\350\203\275\347\273\223\346\236\204\345\233\276.png" diff --git "a/zh-cn/device-dev/security/figures/\345\256\211\345\205\250\344\277\235\351\232\234\347\244\272\346\204\217\345\233\276.png" "b/zh-cn/device-dev/security/figure/\345\256\211\345\205\250\344\277\235\351\232\234\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/security/figures/\345\256\211\345\205\250\344\277\235\351\232\234\347\244\272\346\204\217\345\233\276.png" rename to "zh-cn/device-dev/security/figure/\345\256\211\345\205\250\344\277\235\351\232\234\347\244\272\346\204\217\345\233\276.png" diff --git "a/zh-cn/device-dev/security/figures/\350\256\276\345\244\207\351\227\264\345\273\272\347\253\213\345\217\257\344\277\241\345\205\263\347\263\273\346\265\201\347\250\213\345\233\276.png" "b/zh-cn/device-dev/security/figure/\350\256\276\345\244\207\351\227\264\345\273\272\347\253\213\345\217\257\344\277\241\345\205\263\347\263\273\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/security/figures/\350\256\276\345\244\207\351\227\264\345\273\272\347\253\213\345\217\257\344\277\241\345\205\263\347\263\273\346\265\201\347\250\213\345\233\276.png" rename to "zh-cn/device-dev/security/figure/\350\256\276\345\244\207\351\227\264\345\273\272\347\253\213\345\217\257\344\277\241\345\205\263\347\263\273\346\265\201\347\250\213\345\233\276.png" diff --git a/zh-cn/device-dev/security/public_sys-resources/icon-caution.gif b/zh-cn/device-dev/security/public_sys-resources/icon-caution.gif deleted file mode 100755 index 6e90d7cfc2193e39e10bb58c38d01a23f045d571..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 580 zcmV-K0=xZ3Nk%w1VIu$?0Hp~4{QBgqmQ+MG9K51r{QB&)np^||1PlfQ%(86!{`~yv zv{XhUWKt}AZaiE{EOcHp{O-j3`t;<+eEiycJT4p@77X;(jQsMfB$R?oG%6hQ z+MMLZbQBH@)Vg&1^3?qHb(5!%>3r0+`eq=&V&E}0Dypi0000000000 z00000A^8LW000R9EC2ui03!e$000L5z=Uu}ED8YtqjJd<+B}(9bIOb$3-31_h|V>=0A{ z1Hh0#H30>fNT})^fRU_83uewx9oRr{f{Sx1Ml`t)EQ zGkHZ67&~y{W5Jpq4H_WfuLxp*3<7O}GEl;1ESe36fLNs=B0&LQM1Buf(R)qg(BRd`t1OPjI1m_q4 diff --git a/zh-cn/device-dev/security/public_sys-resources/icon-danger.gif b/zh-cn/device-dev/security/public_sys-resources/icon-danger.gif deleted file mode 100755 index 6e90d7cfc2193e39e10bb58c38d01a23f045d571..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 580 zcmV-K0=xZ3Nk%w1VIu$?0Hp~4{QBgqmQ+MG9K51r{QB&)np^||1PlfQ%(86!{`~yv zv{XhUWKt}AZaiE{EOcHp{O-j3`t;<+eEiycJT4p@77X;(jQsMfB$R?oG%6hQ z+MMLZbQBH@)Vg&1^3?qHb(5!%>3r0+`eq=&V&E}0Dypi0000000000 z00000A^8LW000R9EC2ui03!e$000L5z=Uu}ED8YtqjJd<+B}(9bIOb$3-31_h|V>=0A{ z1Hh0#H30>fNT})^fRU_83uewx9oRr{f{Sx1Ml`t)EQ zGkHZ67&~y{W5Jpq4H_WfuLxp*3<7O}GEl;1ESe36fLNs=B0&LQM1Buf(R)qg(BRd`t1OPjI1m_q4 diff --git a/zh-cn/device-dev/security/public_sys-resources/icon-note.gif b/zh-cn/device-dev/security/public_sys-resources/icon-note.gif deleted file mode 100755 index 6314297e45c1de184204098efd4814d6dc8b1cda..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 394 zcmZ?wbhEHblx7fPSjxcg=ii?@_wH=jwxy=7CMGH-B`L+l$wfv=#>UF#$gv|VY%C^b zCQFtrnKN(Bo_%|sJbO}7RAORe!otL&qo<>yq_Sq+8Xqqo5h0P3w3Lvb5E(g{p01vl zxR@)KuDH0l^z`+-dH3eaw=XqSH7aTIx{kzVBN;X&hha0dQSgWuiw0NWUvMRmkD|> diff --git a/zh-cn/device-dev/security/public_sys-resources/icon-notice.gif b/zh-cn/device-dev/security/public_sys-resources/icon-notice.gif deleted file mode 100755 index 86024f61b691400bea99e5b1f506d9d9aef36e27..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 406 zcmV;H0crk6Nk%w1VIu$@0J8u9|NsB@_xJDb@8;&_*4Ea}&d#;9wWXz{jEszHYim+c zQaU<1At50E0000000000A^8Le000gEEC2ui03!e%000R7038S%NU)&51O^i-Tu6`s z0)`MFE@;3YqD6xSC^kTNu_J>91{PH8XfZ(p1pp2-SU@u3#{mEUC}_}tg3+I#{z}{Ok@D_ZUDg- zt0stin4;pC8M{WLSlRH*1pzqEw1}3oOskyNN?j;7HD{BBZ*OEcv4HK!6Bk6beR+04 z&8}k>SkTusVTDmkyOz#5fCA$JTPGJVQvr3uZ?QzzPQFvD0rGf_PdrcF`pMs}p^BcF zKtKTd`0wipR%nKN&Wj+V}pX;WC3SdJV!a_8Qi zE7z`U*|Y^H0^}fB$R?oG%6hQ z+MMLZbQBH@)Vg&1^3?qHb(5!%>3r0+`eq=&V&E}0Dypi0000000000 z00000A^8LW000R9EC2ui03!e$000L5z=Uu}ED8YtqjJd<+B}(9bIOb$3-31_h|V>=0A{ z1Hh0#H30>fNT})^fRU_83uewx9oRr{f{Sx1Ml`t)EQ zGkHZ67&~y{W5Jpq4H_WfuLxp*3<7O}GEl;1ESe36fLNs=B0&LQM1Buf(R)qg(BRd`t1OPjI1m_q4 diff --git a/zh-cn/device-dev/security/safety-protection-privacyguide.md b/zh-cn/device-dev/security/safety-protection-privacyguide.md new file mode 100644 index 0000000000..95e5eccca8 --- /dev/null +++ b/zh-cn/device-dev/security/safety-protection-privacyguide.md @@ -0,0 +1,264 @@ +# 隐私保护 + +- [隐私保护概述](#section13200134331414) +- [数据分类分级](#section2371104991511) +- [通用隐私设计规则](#section10354102411162) +- [特殊品类要求](#section118861450201618) + +## 隐私保护概述 + +随着互联网及信息化的发展,个人数据在社会经济和日常生活中发挥着越来越重要的作用。与此同时,个人数据泄露的风险也在增加,消费者产品开发者需要更加有效的保护用户的个人数据,提高用户对产品的信任度。为了提升消费者的隐私体验,产品应默认设置较高级别隐私保护策略,达到保护消费者隐私的目的。 + +**基本概念** + +- **个人数据(Personal Data)** + + 与一个身份已被识别或者身份可被识别的自然人(“数据主体”)相关的任何信息;身份可识别的自然人是指其身份可以通过诸如姓名、身份证号、位置数据等识别码或者通过一个或多个与自然人的身体、生理、精神、经济、文化或者社会身份相关的特定因素来直接或者间接地被识别。个人数据包括:自然人的email地址、电话号码、生物特征(指纹)、位置数据、IP地址、医疗信息、宗教信仰、社保号、婚姻状态等。 + +- **敏感个人数据(Sensitive Personal Data)** + + 敏感个人数据是个人数据的一个重要子集,指的是涉及数据主体的最私密领域的信息或者一旦泄露可能会给数据主体造成重大不利影响的数据。欧盟等国家和地区法律定义的敏感个人数据包括种族、政治观点、宗教和哲学信仰、工会成员资格、基因数据、生物信息、健康和性生活状况、性取向等。 + + 根据业界最佳实践,敏感个人数据还包括可与自然人身份相关联的银行卡号、身份证号、护照号、口令等。敏感个人数据的处理需要更多更严格的保护措施。 + +- **公开个人数据(Public available Personal Data)** + + 数据主体主动公开的个人数据,或公开网页/应用上可访问的个人数据,包括论坛公开的发帖、评论等。 + +- **用户画像(User Profile)** + + 指对个人数据采取的任何自动化处理的方式,包括评估某个自然人特定方面的情况,尤其是为了分析和预测该自然人的工作表现、经济状况、健康、个人喜好、兴趣、可信度、行为举止、所在位置或行迹。 + +- **数据控制者(Data Controller)** + + 单独或者与他人共同确定个人数据处理的目的和手段的自然人、法人、公共机构、政府部门或其他机构。 + +- **数据处理者(Data Processor)** + + 指代表数据控制者处理个人数据的自然人、法人、公共机构、政府部门或其他机构。数据处理者必须按照数据控制者的要求对个人数据进行充分的保护。 + +- **明示同意(Explicit consent)** + + 如下几种情形GDPR法律提到可以通过数据主体明示同意的方式合法地处理数据: + + - 处理敏感个人数据。 + - 自动化决策,包括进行用户画像。 + - 向不具备充分保护水平的国家转移个人数据,并以同意作为合法性基础。 + + 实现明示同意的方式有: + + - 在收集特定数据时,弹出隐私声明告知个人数据处理相关事项,提供勾选框但不默认勾选,让数据主体勾选“我同意以上述方式处理我的个人数据”,或提供“我同意”的按钮让用户主动点击。 + - 以书面的方式明确表达同意,数据主体在书面陈述上签字。 + - 要求数据主体在系统中上传带有其签名的电子表格。 + - 采取双重验证的方式,要求数据主体邮件形式回复同意后,再次点击用于验证的邮件链接或是输入SMS验证码。 + - 用户主动输入的场景,例如用户主动输入身份证和银行卡号绑卡等场景。 + + +## 数据分类分级 + +基于数据保护目标及风险后果,即数据遭到泄露或者遭到破坏带来的法律风险对个人、组织或公众的影响对数据进行定级,分为极高、高、中、低、公开五个数据级别。 + +**表1** 数据分类分级标准 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    数据级别

    +

    隐私风险

    +

    隐私属性

    +

    典型示例

    +

    极高级

    +

    数据一旦识别或关联到特定个人或群体,其泄露或不当使用可能会给个人带来灾难性负面影响。

    +

    敏感个人数据

    +

    DNA、种族、宗教信仰、性取向;生物识别信息;原始通信内容;银行卡密码、磁道数据。

    +

    高级别

    +

    数据一旦识别或关联到特定个人或群体,其泄露或不当使用可能会给个人带来严重负面影响。

    +

    敏感个人数据

    +

    权威社会标识(身份证、护照等);网页浏览记录;轨迹信息;云空间上传的内容数据(图库/音频/视频等)。

    +

    中级别

    +

    数据一旦识别或关联到特定个人或群体,其泄露或不当使用可能会给个人带来重大负面影响。

    +

    一般个人数据

    +

    设备标识(IMEI, SN, OAID )、用户标识(user ID);个人基本信息(姓名,地址);手机号、邮箱等。

    +

    低级别

    +

    数据一旦识别或关联到特定个人或群体,其泄露或不当使用可能会给个人带来有限负面影响。

    +

    一般个人数据

    +

    操作系统设置信息(操作系统版本,国家/地区等);设备硬件信息(设备型号,屏幕尺寸,屏幕分辨率等);网络信息(网络连接状态,接入网络信息);设备状态(登录设备时间/时长)。

    +

    公开(无风险)

    +

    对个人或组织无不利影响的可公开数据

    +

    非个人数据

    +

    公开发布的产品介绍,公开的会议信息,外部开源的代码等。

    +
    + +备注:隐私保护和数据分类分级的相关定义参照GDPR中的相关内容。 + +## 通用隐私设计规则 + +为了指导厂商完成产品的隐私设计工作,我们整理了以下通用的隐私设计要求,作为OpenHarmony设备厂商产品隐私设计的指南和参考。 + +**数据收集及使用公开透明** + +采集个人数据时,应清晰、明确地告知用户,并确保告知用户的个人信息将被如何使用。 + +- 针对不同等级的个人数据需要制定针对性的隐私处理策略。 + - 敏感个人数据的采集需要获取数据主体明示同意。 + - 一般个人数据的采集需要数据主体同意或基于其他合法授权。 + - 非个人数据与中、高或极高级别个人数据关联采集,需要数据主体同意或其他合法授权,并在隐私声明中呈现。 + +- 应制定并遵从适当的隐私政策。在收集、使用留存和第三方分享用户个人数据时需要符合所有适用法律、政策和规定。如在收集个人数据前,需充分告知用户处理个人数据的种类、目的、处理方式、保留期限等,满足数据主体权利相关要求。 + + 根据以上要求,我们设计了正确示例以供参考。隐私通知/声明的参考示例如下: + + **图 1** 隐私通知/声明示例图 + + + ![](figure/2-应用启动预授权.png) ![](figure/3-应用隐私声明.png) + +- 个人数据应当基于具体、明确、合法的目的收集,不应与此目的不相符的方式作进一步处理。对于收集目的变更和用户撤销同意后再次重新使用的场景都需要用户重新同意。隐私声明变更和撤销的示例如下图: + + **图 2** 隐私通知/声明变更示例图 + + + ![](figure/4-隐私声明变更通知.png) + + **图 3** 撤销同意示例图 + + + ![](figure/6-1-隐私声明撤销.png) ![](figure/6-2-隐私声明撤销.png) + +- 需要提供用户查看隐私声明的入口。例如,可以在应用的“关于”界面提供查看隐私声明的入口,如示例图所示: + + **图 4** 隐私声明查看界面示例图 + + + ![](figure/5-应用隐私声明入口.png) + + +**数据收集及使用最小化** + +个人数据收集应与数据处理目的相关,且是适当、必要的。开发者应尽可能对个人数据进行匿名化或假名化处理,降低对数据主体的风险。仅可收集和处理与特定目的相关且必需的个人数据,不能进行与特定目的不相关的进一步处理。 + +- 敏感权限申请的时候要满足权限最小化的要求,在申请权限时,只申请获取必需的信息或资源所需要的权限。如应用不需要相机权限就能够实现其功能时,则不应该向用户申请相机权限。 +- 数据收集最小化:针对数据的收集要满足最小化要求,不收集与产品提供服务无关联的数据。如提供定位服务的产品,不应收集用户的网页浏览记录。 +- 数据使用的功能要求能够使用户受益,收集的数据不能用于一些与用户正常使用无关的功能。数据收集不能有其他与用户正常使用无关的功能存在。如不得将“生物特征”、“健康数据”等敏感个人数据用于服务改进、投放广告或营销等非业务核心功能。 +- 禁止在日志中打印敏感个人数据,如需要打印一般个人数据时,应对个人数据进行匿名化或假名化处理; + + 优先使用可以重置的标识符,如系统提供了NetworkID和DVID作为分布式场景下的设备标识符,广告业务场景下则建议使用[OAID](https://developer.huawei.com/consumer/cn/doc/development/HMSCore-Guides/oaid-0000001050783198),基于应用的分析则建议使用[ODID](https://developer.huawei.com/consumer/cn/doc/development/HMSCore-Guides/odid-0000001051063255)和[AAID](https://developer.huawei.com/consumer/cn/doc/development/HMSCore-Guides/aaid-0000001051142988),其他需要唯一标识符的场景可以使用UUID接口生成;可重置的标识符不能满足业务需求时,才选择序列号和MAC地址等永久性标识符。 + + +**数据处理选择和控制** + +对个人数据处理必须要征得用户的同意或遵守其他适用的法律法规,用户对其个人数据要有充分的控制权。 + +- 获取用户敏感权限的授权:产品弹窗提醒,向用户呈现需要获取的权限和权限使用目的,用户可通过选择决定是否进行授权及指定授权的方式,让用户对产品权限的授予和个人数据使用做到透明、可知、可控。如下图所示: + + **图 5** 敏感权限提示框示例图 + + + ![](figure/1-敏感权限弹窗.png) + +- 用户可以修改、取消授予的权限:当用户不同意某一权限或者数据收集时,应当允许用户使用与这部分权限和数据收集不相关的功能。如智慧屏产品上通信社交应用,用户可以拒绝授予相机权限,不应该影响与相机无关的功能操作,如语音通话。 +- 用户在产品使用过程中,针对录入个人数据的场景,需要给用户提供对个人数据的增加、删除、修改、查看的操作。 +- 需要给出硬件回收或返厂进行安全删除个人数据的机制或方法。 +- 对用户系统软件、应用软件的下载或升级,涉及修改用户隐私空间,用户对于这类行为需要有知情权和控制权,必须给用户提示,并提供给用户同意和取消的选项。 + +**数据安全** + +从技术上保证数据处理活动的安全性,包括个人数据的加密存储、安全传输等安全机制,系统应默认开启或采取安全保护措施。 + +- 对于个人数据的访问需要有保护机制,主要包括身份认证和访问控制。身份认证(如用户名、密码)限定只有经过认证的用户才能访问数据,可应用于多用户场景;访问控制(如[权限控制](safety-safeguide-security.md#li201725506375))可应用于对应用程序的限制。 +- 分布式设备个人数据安全存储要满足密钥管理和存储服务(HUKS:Huawei Universal Keystore)的要求,包括:密钥安全存储、数据安全存储。 +- 个人数据在分布式设备间传输要满足设备间的信任绑定关系和数据传输通道的安全性要求。详细信息可以参考[设备互联安全](safety-safeguide-security.md#section26153183616)。 +- 认证凭证数据(密码、口令、指纹等)须加密存储。 + +**本地化处理** + +用户数据优先在本设备进行处理,对于本设备无法处理的数据应尽可能在超级终端设备本地进行数据的处理,如果超级终端本地处理无法满足业务目的的,在数据离开超级终端设备本地时应尽可能选择匿名化。 + +**未成年人数据保护要求** + +产品专门给未成年人设计的,或者产品收集用户年龄从而可以识别到是在收集未成年人的个人数据,需结合目标市场国家的法律,专门分析未成年人个人数据保护的问题,收集未成年人数据前需要征得监护人的同意。 + +## 特殊品类要求 + +针对消费者硬件产品来说,除了满足以上的通用隐私要求以外,针对特殊品类的产品还有以下的特殊要求,在产品设计过程中参照执行。 + +**表2** 特殊品类隐私要求 + + + + + + + + + + + + + + + + + + + + + + + + + +

    产品品类

    +

    隐私保护特殊要求

    +

    智能家居

    +

    安防类产品涉及的指纹、声纹、面部识别、虹膜等个人生物识别信息以及用户密码信息,属于敏感个人数据,应采用技术措施处理后(例如提取个人生物识别信息的摘要)再进行加密保存在产品本地。

    +

    智能家居

    +

    安防类产品涉及的音视频和图片,设备厂家作为数据控制者时,必须提供独立的隐私通知、应用界面必须有设备厂家品牌标识;音视频数据的传输和存储必须加密,非用户本人访问安防产品的音视频数据,必须获得用户授权。

    +

    智能家居/影音娱乐

    +

    带有摄像头的产品建议提供物理上可关闭功能,通过隐藏、遮盖、转向让消费者感知摄像头处于关闭状态。

    +

    智能家居/影音娱乐

    +

    带有麦克风的产品建议提供显性显示录音的状态,如录音开启时状态灯闪烁,录音关闭时状态灯熄灭。

    +

    移动办公

    +

    用户数据跨设备显示、传输等场景需要获得消费者的明示同意,给予消费者对其个人数据有充分的控制权。

    +

    车机

    +

    1、隐私通知及权限设置

    +

    避免在驾驶态让用户阅读隐私政策和权限设置。

    +

    车机应用需要考虑车辆使用时的安全性,应避免让用户在驾驶过程中进行复杂的权限设置或阅读隐私政策,比如HiCar应用应该在手机端完成应用基本权限设置和隐私政策阅读后再进行使用。

    +

    隐私声明在确认用户身份后告知。

    +

    车辆的数据会涉及车主、驾驶员和乘客,应保证隐私声明通知到了数据主体本人。建议做法是在确认使用者的身份后进行隐私声明,如需要用户登录的应用,应在账号登录后弹出隐私声明而不是账号登录之前。

    +

    2、共享应用个人数据保护

    +

    共享应用在车机重启后应退出,并对当前用户个人数据进行清除或加密,应用还应提供对历史数据进行彻底删除的功能。

    +

    3、消息提示

    +

    考虑车机的开放环境,应用在车机上进行消息提醒时,应避免直接将消息内容显示在车机上,正确的做法是仅提示有新的消息需要查看。

    +
    + diff --git a/zh-cn/device-dev/security/safety-safeguide-security.md b/zh-cn/device-dev/security/safety-safeguide-security.md new file mode 100644 index 0000000000..63804f366b --- /dev/null +++ b/zh-cn/device-dev/security/safety-safeguide-security.md @@ -0,0 +1,275 @@ +# 安全指南 + +- [安全概述](#section1521410017353) +- [硬件安全](#section2558121318351) + - [安全机制](#section1399511541896) + - [推荐做法](#section948519243104) + +- [系统安全](#section87802111361) + - [安全机制](#section149107611118) + - [推荐做法](#section1364122019112) + +- [数据安全](#section2468927364) + - [安全机制](#section1378993720111) + - [推荐做法](#section1531735481112) + +- [设备互联安全](#section26153183616) +- [应用安全](#section852593153614) + - [安全机制](#section55012136125) + - [推荐做法](#section6341102610123) + + +## 安全概述 + +OpenHarmony操作系统是一个开放的系统,开发者可以通过OpenHarmony开发灵活的服务和应用,为开发者和使用者带来便利和价值。为了达到这一目的,OpenHarmony提供了一个可以有效保护应用和用户数据的执行环境。 + +在这个执行环境中,芯片的安全能力、系统的安全能力、以及上层的安全服务一起协作,从硬件安全、系统安全、数据安全、设备互联安全、应用安全、安全更新多个维度提供安全保障。 + +**图 1** 安全保障示意图 +![](figure/安全保障示意图.png "安全保障示意图") + +## 硬件安全 + +### 安全机制 + +- 启动可信根 + + OpenHarmony设备采用PKI(Public Key Infrastructure)体系保护软件完整性,确保设备运行来源合法、软件未被篡改。 + + 在设备启动流程中,逐级进行软件签名校验形成安全启动链,任何一个环节的签名校验不通过即终止设备启动;安全启动链中最初执行签名校验的软硬件实体,需确保自身的合法、未被篡改。该实体即为设备的启动可信根。启动可信根可为固化在ROM中的一段代码,这段代码在芯片制造环节固化到芯片中,芯片制造完成后软件不可更改,在设备上电初始化的过程中,最先执行这段ROM中的代码,并由这段ROM代码执行后续的软件签名校验。 + + ROM中的代码在执行签名校验时,需确保用于校验的PKI公钥的合法性,OpenHarmony设备可采用eFuse/OTP等存储介质来存储公钥(如公钥哈希值),来保护公钥自身的合法性。公钥一般在设备制造环节,烧录到设备的eFuse/OTP中。 + +- 硬件隔离可信环境 + + 硬件隔离的可信环境,遵循了可信计算系统的设计理念。可信环境内外形成了两个世界:可信世界与不可信世界,两者之间存在清晰而明确的隔离边界;OpenHarmony设备在可信环境中实现了核心敏感数据的保护机制,可确保即使不可信世界的操作系统存在漏洞且被利用,也依然能确保可信环境中敏感数据的安全。 + + OpenHarmony设备的可信环境,基于硬件的安全隔离机制构建,在不同的OpenHarmony设备上芯片隔离机制略有差异,较为通用的方法是采用ARM的TrustZone技术。在部分Risc-V芯片平台上,也可能采用独立安全核的形式来构建可信环境。 + + 可信环境中,运行特定的、精简的操作系统iTrustee lite,用于管理可信环境的资源和任务调度,给OpenHarmony设备提供安全服务。密钥管理及数据安全,是可信环境中最为常见的安全服务,设备在eFuse/OTP中存有硬件唯一根密钥,可信环境可基于该密钥结合业务上下文衍生出多种密钥,给应用提供密钥管理和数据加解密相关的服务;设备核心密钥生命周期不离开可信环境。可信环境同样可提供身份认证、系统状态监控、数据安全存储等安全服务,提高设备安全性。 + +- 硬件密钥引擎 + + 密码学是信息安全的基础。数据加解密对计算机设备的核心诉求是:高效、安全。硬件加解密技术利用计算机硬件辅助软件,甚至直接取代软件,来处理数据的加解密。相比由软件实现的加解密计算,硬件实现的加解密计算更高效、更安全。 + + 由硬件来实现加解密处理,意味着部分专用的硬件资源会用于处理加解密计算任务,当加解密引擎工作的时候CPU可以并发地继续执行其他计算任务,因此硬件加解密引擎可以带来极大的性能提升,同时降低CPU负载。此外,硬件密钥引擎可以带来更高的安全性,设计良好的硬件密钥引擎,哪怕软件被攻破也依然可保护密钥不泄露,甚至可对抗电磁、辐射等物理侧信道攻击。 + + OpenHarmony设备支持硬件密钥引擎,支撑OpenHarmony系统进行数据加解密、证书验签、哈希计算等计算任务,可支持AES/RSA等主流的密码学算法。 + + +### 推荐做法 + +- 启动可信根可由一段固化在芯片中的代码和设备根密钥组成,前者一般在芯片制造阶段写入,设备生命周期内不可更改,负责在启动阶段校验设备软件证书;后者则是用于设备证书签名的私钥相对应的公钥,证书签名私钥不出PKI签名服务器,而公钥则需写入设备。为防止攻击者篡改公钥从而达到绕过签名认证的目的,写入OpenHarmony设备的公钥须确保不可篡改,可将公钥信息写入如熔丝等介质;考虑到熔丝空间有限,可仅存储公钥的哈希值,并由启动代码校验公钥的合法性。 +- 可信执行环境较为通用的做法是基于ARM TrustZone技术构建,也可根据设备的实际形态选择其他隔离机制,如TrustZone-M、独立安全核等;可信执行环境中须部署TEE OS,用于管理可信执行环境的资源及任务调度。OpenHarmony系统提供iTrustee作为TEE OS的解决方案,开发者及设备商可基于iTrustee开发并部署安全业务。 + + 并非所有OpenHarmony设备都强制要求支持可信执行环境,部分运行低敏感业务的瘦资源设备可不做强制要求;可根据实际业务场景选择是否支持可信执行环境,以及实现怎样的可信执行环境。 + +- 硬件密钥引擎须提供真随机数、公钥、对称密钥、哈希等密钥算法能力,通过在OpenHarmony系统中部署相应的驱动程序,给应用提供统一的密钥管理及密钥算法服务。 + +## 系统安全 + +### 安全机制 + +对于128KB\~128MB内存的设备,推荐使用OpenHarmony轻内核组件,在该内核下: + +- 进程隔离 + + 进程隔离是为了防止A进程读写B进程内存数据的情况发生,进程的隔离技术,一般都采用虚拟地址空间映射方式,通过MMU配置,进程A的虚拟地址和进程B的虚拟地址映射各自不同的实际的物理地址段,这样A进程通过访问虚拟地址访问的实际内存数据在非共享内存的情况下,只属于A进程,B进程无法直接访问。 + + OpenHarmony由于资源有限,对于内核态和用户态的进程采用不同的方式:所有的内核态进程共享同一块VMM空间,即所有的内核态进程之间无隔离,系统启动时内核态创建两个基本进程KProcess和KIdle,KProcess进程为内核态进程的根进程,KIdle进程为KProcess进程的子进程;但是对于每一个用户态进程均拥有自己独立的VMM空间,相互之间不可见,实现进程间隔离。 + +- 自主访问控制 + + 自主访问控制DAC(Discretionary Access Control)的思想是文件权限由文件拥有者来决定其他角色的访问权限。权限管控粒度分为三类:user\(自身\), group\(组员\),other\(其他人\),即UGO。将任意用户分类为UGO中三者之一,并采取相应的管控策略,即完成了DAC权限校验流程。 + + DAC机制依赖于进程的uid、gid等属性,需要以此作为文件创建以及文件访问过程中的特征id。文件创建时,创建者将自身uid写入文件,文件访问时,又以此作为文件归属的分类依据。 + + 每一个应用,对应一个uid。应用在创建文件时,将自身uid信息加入被创建文件的元数据\(metadata\)中,并设置UGO三个组的权限。在文件访问过程中,将以访问者uid作为访问校验主体、以文件元数据中的uid权限信息作为客体,进行权限校验。 + + 下图描述了DAC在文件访问时的鉴权过程,首先匹配进程uid和文件uid属性,其次匹配进程gid和文件gid属性,最后都匹配失败的情况,判断文件other属性是否支持进程的读、写、执行操作。同时支持忽略DAC检测机制(读、写、执行)作为一组系统特权(Capability),支持高权限(如系统服务)对低权限(三方APP)的文件管理。 + + **图 2** DAC流程图 + ![](figure/DAC流程图.png "DAC流程图") + +- Capability机制 + + Capability机制实际上是对root权限的具体细分。在多用户计算机系统中,一般会有一个特殊的角色拥有系统的所有权限,这个角色一般是系统管理员\(root\)。对于OpenHarmony这种需要支持三方应用生态的内核,需要将系统中的特权访问进行管控。系统需要对用户层访问内核的特权级系统调用进行限制。仅允许部分高权限应用进行特权操作。具体实现方式是内核spawn第一个用户程序INIT,其包含全部的特权能力,此后,INIT拉起其他应用框架服务,拉起过程中,对各应用框架进行相应的降权操作,为各应用保留必须的特权能力。 当应用去调用特权接口时,内核态就会通过进程ID查看当前访问者是否有权限访问目标接口。 + +- 安全启动 + + 安全启动是整个系统安全的基础,通过采用数字签名和完整性校验机制,从芯片内部固化的可信启动根开始,逐级校验每一层软件的完整性和合法性,确保最终启动的操作系统软件是厂家提供的正确合法的软件,防止攻击者对系统软件做恶意的篡改和植入,为整个系统提供初始安全的基础运行环境。 + + 在芯片上电后,由于片上ROM代码本身不可更改,因此无需校验;片上ROM基于eFuse中的非对称算法公钥hash对bootloader进行校验。这些过程都基于硬件信任根来进行,是完全可信的。经过此过程校验通过的bootloader模块可以作为后续的信任基础,此过程就是启动信任链的构造过程。Bootloader通常首先对执行环境进行一定的初始化,主要是初始化DDR以及flash读写,为进一步加载后续模块以及执行更为复杂的逻辑进行准备。Bootloader完成初始化动作后,首先完成x509证书的完整性校验,然后利用x509证书的公钥对需要校验的镜像包(kernel.bin、teeOS.bin、rootfs.bin)进行校验。 + + +### 推荐做法 + +- 自主访问控制和Capability机制是控制资源被谁可以访问的机制,建议所有权限设置都采用最小权限原则。 +- 安全启动必须要开启,信任根必须是基于芯片的不可更改的形式存在,并且在有安全升级的情况下,必须考虑安全升级后对于安全启动的影响,也就是安全升级后必须要更新对应镜像文件的签名信息或者hash值。 + +## 数据安全 + +### 安全机制 + +HUKS(Huawei Universal Keystore Service),提供了密钥管理、证书管理服务,当前在OpenHarmony上主要提供密钥管理服务,用于支撑HiChain\(设备身份认证平台\)的基础设备认证。如下是HUKS的功能结构图: + +**图 3** HUKS功能结构图 +![](figure/HUKS功能结构图.png "HUKS功能结构图") + +支持算法包括: + +- 认证加密:AES-128/192/256-GCM +- 签名验签:ED25519 +- 密钥协商:X25519 +- 消息认证:HMAC-SHA256/512 +- 数据摘要:SHA256/512 + +HUKS在使用中有如下约束: + +- 密钥安全存储:密钥要求存储于安全存储区域,数据不可以修改,恢复出厂设置时出厂预置的密钥不能被删除。 +- 密钥访问安全:OpenHarmony通过将不同应用数据保存在不同的位置,来实现应用间数据的隔离。通过参数结构体中包含UID和进程ID,来实现不同应用间的数据隔离。 +- 不支持并发访问:HUKS本身不考虑多个应用同时调用的情况,因为HUKS只是一个lib库,也不考虑资源的互斥。如果有多个应用都会用到HUKS服务,那么应该由每个应用各自链接一份HUKS库,并由业务传入持久化数据存储的路径,以实现应用间的数据存储分开。数据存储在各应用各自存储目录下。 + +### 推荐做法 + +对于设备认证功能,建议使用HiChain来对接HUKS,HUKS可以向HiChain等应用提供密钥的产生、导入、导出、加密/解密、存储、销毁,证书的导入和查询,秘密信息的存储等能力。 + +## 设备互联安全 + +为了实现用户数据在设备互联场景下在各个设备之间的安全流转,需要保证设备之间相互正确可信,即设备和设备之间建立信任关系,并能够在验证信任关系后,搭建安全的连接通道,实现用户数据的安全传输。设备之间的信任关系在本文档中涉及IoT主控设备和IoT设备之间建立的可信关系。设备间可信关系建立的流程如下图所示: + +**图 4** 设备间建立可信关系流程图 +![](figure/设备间建立可信关系流程图.png "设备间建立可信关系流程图") + +- **IoT设备互联安全** + + 设备互联支持基于OpenHarmony的IoT设备(如AI音箱、智能家居、智能穿戴等设备)与IoT主控设备间建立点对点的信任关系,并在具备信任关系的设备间,搭建安全的连接通道,实现用户数据端到端加密传输。 + + +- **IoT主控设备的IoT业务身份标识** + + IoT主控设备为不同的IoT设备管理业务生成不同的身份标识,形成不同IoT管理业务间的隔离,该标识用于IoT主控设备与IoT设备之间的认证以及通信。IoT业务身份标识为椭圆曲线公私钥对(Ed25519公私钥对)。 + + +- **IoT设备身份标识** + + IoT设备会生成各自的设备身份标识,用来与IoT主控设备通信。该身份标识同样为椭圆曲线公私钥对(Ed25519公私钥对);IoT设备私钥不出IoT设备,设备每次恢复出厂设置,会重置这个公私钥对。 + + 上述身份标识可用于IoT主控设备与IoT设备间的安全通信:当IoT主控设备与IoT设备通过信任绑定流程交换业务身份标识或设备标识后,可以进行密钥协商并建立安全通信通道。 + + +- **设备间点对点的信任绑定** + + IoT主控设备和IoT设备建立点对点信任关系的过程,实际上是相互交换IoT设备的身份标识的过程。 + + 在点对点建立信任关系的过程中,用户需要在IoT主控设备上,输入IoT设备上提供的PIN码:对于有屏幕的设备,该PIN码动态生成;对于没有屏幕的设备,该PIN码由设备生产厂家预置;PIN码的展示形式,可以是一个用户可读的数字,也可以是一个二维码。随后,IoT主控设备和IoT设备间使用PAKE协议完成认证和会话密钥协商过程,并在此基础上,通过协商出的会话密钥加密传输通道用于交换双方设备的身份标识公钥。 + + +- **IoT主控设备与IoT设备间的通信安全** + + 当建立过信任关系的IoT主控设备与IoT设备间进行通信时,双方在完成上述信任关系绑定后,基于本地存储的对端身份公钥相互进行认证;在每次通信时基于STS协议完成双向身份认证以及会话密钥协商,之后设备使用此会话密钥加密双方设备间的传输通道。 + + +## 应用安全 + +### 安全机制 + +- 应用签名管控 + + OpenHarmony应用的安装需要首先对包的完整性进行校验,具体策略是在开发阶段完成开发和调试后对安装包进行签名,这个签名需要使用指定的私钥,这个私钥就是跟验签用的公钥是一对的,一般的做法是OEM厂商生成一对公私钥,然后将公钥信息预置到设备中,而私钥就放在一个不联网的本地服务器上,这样可以确保私钥被泄露的风险尽量小,而应用在完成开发后就可以通过外置设备(例如USB)上传安装包到存放私钥的服务器上计算签名并下载签名结果到外置设备上。而安装应用时首先计算包的Hash值,一般采用SHA256算法,然后使用hash值和签名信息以及预置公钥进行验签,只有验签通过的应用才能安装。 + + 除了要证明应用来自云端认证过的,还需要证明来源,即这个应用来自合法开发者开发的,具体做法是,开发者向云端申请开发证书,开发完成后,用开发证书进行自签名,设备端存放这个证书的上一级证书,所以安装过程中,对自签名信息做校验,确保开发者的合法性。 + +- 应用权限控制 + + 由于OpenHarmony系统允许安装三方应用,所以需要对三方应用的敏感权限调用进行管控,具体实现是应用在开发阶段就需要在profile.json中指明此应用在运行过程中可能会调用哪些敏感权限,这些权限包括静态权限和动态权限,静态权限表示只需要在安装阶段注册就可以,而动态权限一般表示获取用户的敏感信息,所以需要在运行时让用户确认才可以调用,授权方式包括系统设置应用手动授权等。除了运行时对应用调用敏感权限进行管控外,还需要利用应用签名管控手段确保应用安装包已经被设备厂商进行了确认。 + + **表 1** **OpenHarmony系统权限列表** + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    OpenHarmony系统权限

    +

    授权方式

    +

    权限说明

    +

    ohos.permission.LISTEN_BUNDLE_CHANGE

    +

    system_grant(静态权限)

    +

    允许该应用获取应用变化消息。

    +

    ohos.permission.GET_BUNDLE_INFO

    +

    system_grant(静态权限)

    +

    允许该应用获取应用信息。

    +

    ohos.permission.INSTALL_BUNDLE

    +

    system_grant(静态权限)

    +

    允许该应用安装应用。

    +

    ohos.permission.CAMERA

    +

    user_grant(动态权限)

    +

    此应用可随时使用相机拍摄照片和录制视频。

    +

    ohos.permission.MODIFY_AUDIO_SETTINGS

    +

    system_grant(静态权限)

    +

    允许该应用修改全局音频设置,例如音量和用于输出的扬声器。

    +

    ohos.permission.READ_MEDIA

    +

    user_grant(动态权限)

    +

    允许该应用读取您的视频收藏。

    +

    ohos.permission.MICROPHONE

    +

    user_grant(动态权限)

    +

    此应用可随时使用麦克风进行录音。

    +

    ohos.permission.WRITE_MEDIA

    +

    user_grant(动态权限)

    +

    允许该应用写入您的音乐收藏。

    +

    ohos.permission.DISTRIBUTED_DATASYNC

    +

    user_grant(动态权限)

    +

    管控分布式数据传输能力。

    +

    ohos.permission.DISTRIBUTED_VIRTUALDEVICE

    +

    user_grant(动态权限)

    +

    允许应用使用分布式虚拟能力

    +
    + + +### 推荐做法 + +开发者在开发过程中需明确后续应用在运行时需要运行哪些权限,并在profile.json中进行注册,然后需要对应用进行签名,确保设备在安装这些应用时能对应用的完整性和来源进行校验。 + diff --git a/zh-cn/device-dev/security/safety.md b/zh-cn/device-dev/security/safety.md new file mode 100644 index 0000000000..72bbe83ac0 --- /dev/null +++ b/zh-cn/device-dev/security/safety.md @@ -0,0 +1,7 @@ +# 隐私与安全 + +- **[隐私保护](safety-protection-privacyguide.md)** + +- **[安全指南](safety-safeguide-security.md)** + + diff --git "a/zh-cn/device-dev/security/\345\256\211\345\205\250\346\214\207\345\215\227.md" "b/zh-cn/device-dev/security/\345\256\211\345\205\250\346\214\207\345\215\227.md" deleted file mode 100755 index c387b9a68e..0000000000 --- "a/zh-cn/device-dev/security/\345\256\211\345\205\250\346\214\207\345\215\227.md" +++ /dev/null @@ -1,271 +0,0 @@ -# 安全指南 - -- [安全概述](#section1521410017353) -- [硬件安全](#section2558121318351) -- [安全机制](#section1312953842210) -- [推荐做法](#section37901319112311) -- [系统安全](#section87802111361) -- [安全机制](#section1654963052914) -- [推荐做法](#section45821048173613) -- [数据安全](#section2468927364) -- [安全机制](#section11192175813293) -- [推荐做法](#section174640713306) -- [设备互联安全](#section26153183616) -- [应用安全](#section852593153614) -- [安全机制](#section12125105014377) -- [推荐做法](#section1641420155381) - -## 安全概述 - -OpenHarmony操作系统是一个开放的系统,开发者可以通过OpenHarmony开发灵活的服务和应用,为开发者和使用者带来便利和价值。为了达到这一目的,OpenHarmony提供了一个可以有效保护应用和用户数据的执行环境。 - -在这个执行环境中,芯片的安全能力、系统的安全能力、以及上层的安全服务一起协作,从硬件安全、系统安全、数据安全、设备互联安全、应用安全、安全更新多个维度提供安全保障。 - -**图 1** 安全保障示意图 -![](figures/安全保障示意图.png "安全保障示意图") - -## 硬件安全 - -## 安全机制 - -- 启动可信根 - - OpenHarmony设备采用PKI(Public Key Infrastructure)体系保护软件完整性,确保设备运行来源合法、软件未被篡改。 - - 在设备启动流程中,逐级进行软件签名校验形成安全启动链,任何一个环节的签名校验不通过即终止设备启动;安全启动链中最初执行签名校验的软硬件实体,需确保自身的合法、未被篡改。该实体即为设备的启动可信根。启动可信根可为固化在ROM中的一段代码,这段代码在芯片制造环节固化到芯片中,芯片制造完成后软件不可更改,在设备上电初始化的过程中,最先执行这段ROM中的代码,并由这段ROM代码执行后续的软件签名校验。 - - ROM中的代码在执行签名校验时,需确保用于校验的PKI公钥的合法性,OpenHarmony设备可采用eFuse/OTP等存储介质来存储公钥(如公钥哈希值),来保护公钥自身的合法性。公钥一般在设备制造环节,烧录到设备的eFuse/OTP中。 - -- 硬件隔离可信环境 - - 硬件隔离的可信环境,遵循了可信计算系统的设计理念。可信环境内外形成了两个世界:可信世界与不可信世界,两者之间存在清晰而明确的隔离边界;OpenHarmony设备在可信环境中实现了核心敏感数据的保护机制,可确保即使不可信世界的操作系统存在漏洞且被利用,也依然能确保可信环境中敏感数据的安全。 - - OpenHarmony设备的可信环境,基于硬件的安全隔离机制构建,在不同的OpenHarmony设备上芯片隔离机制略有差异,较为通用的方法是采用ARM的TrustZone技术。在部分Risc-V芯片平台上,也可能采用独立安全核的形式来构建可信环境。 - - 可信环境中,运行特定的、精简的操作系统iTrustee lite,用于管理可信环境的资源和任务调度,给OpenHarmony设备提供安全服务。密钥管理及数据安全,是可信环境中最为常见的安全服务,设备在eFuse/OTP中存有硬件唯一根密钥,可信环境可基于该密钥结合业务上下文衍生出多种密钥,给应用提供密钥管理和数据加解密相关的服务;设备核心密钥生命周期不离开可信环境。可信环境同样可提供身份认证、系统状态监控、数据安全存储等安全服务,提高设备安全性。 - -- 硬件密钥引擎 - - 密码学是信息安全的基础。数据加解密对计算机设备的核心诉求是:高效、安全。硬件加解密技术利用计算机硬件辅助软件,甚至直接取代软件,来处理数据的加解密。相比由软件实现的加解密计算,硬件实现的加解密计算更高效、更安全。 - - 由硬件来实现加解密处理,意味着部分专用的硬件资源会用于处理加解密计算任务,当加解密引擎工作的时候CPU可以并发地继续执行其他计算任务,因此硬件加解密引擎可以带来极大的性能提升,同时降低CPU负载。此外,硬件密钥引擎可以带来更高的安全性,设计良好的硬件密钥引擎,哪怕软件被攻破也依然可保护密钥不泄露,甚至可对抗电磁、辐射等物理侧信道攻击。 - - OpenHarmony设备支持硬件密钥引擎,支撑OpenHarmony系统进行数据加解密、证书验签、哈希计算等计算任务,可支持AES/RSA等主流的密码学算法。 - - -## 推荐做法 - -- 启动可信根可由一段固化在芯片中的代码和设备根密钥组成,前者一般在芯片制造阶段写入,设备生命周期内不可更改,负责在启动阶段校验设备软件证书;后者则是用于设备证书签名的私钥相对应的公钥,证书签名私钥不出PKI签名服务器,而公钥则需写入设备。为防止攻击者篡改公钥从而达到绕过签名认证的目的,写入OpenHarmony设备的公钥须确保不可篡改,可将公钥信息写入如熔丝等介质;考虑到熔丝空间有限,可仅存储公钥的哈希值,并由启动代码校验公钥的合法性。 -- 可信执行环境较为通用的做法是基于ARM TrustZone技术构建,也可根据设备的实际形态选择其他隔离机制,如TrustZone-M、独立安全核等;可信执行环境中须部署TEE OS,用于管理可信执行环境的资源及任务调度。OpenHarmony系统提供iTrustee作为TEE OS的解决方案,开发者及设备商可基于iTrustee开发并部署安全业务。 - - 并非所有OpenHarmony设备都强制要求支持可信执行环境,部分运行低敏感业务的瘦资源设备可不做强制要求;可根据实际业务场景选择是否支持可信执行环境,以及实现怎样的可信执行环境。 - -- 硬件密钥引擎须提供真随机数、公钥、对称密钥、哈希等密钥算法能力,通过在OpenHarmony系统中部署相应的驱动程序,给应用提供统一的密钥管理及密钥算法服务。 - -## 系统安全 - -## 安全机制 - -对于128KB\~128MB内存的设备,推荐使用OpenHarmony轻内核组件,在该内核下: - -- 进程隔离 - - 进程隔离是为了防止A进程读写B进程内存数据的情况发生,进程的隔离技术,一般都采用虚拟地址空间映射方式,通过MMU配置,进程A的虚拟地址和进程B的虚拟地址映射各自不同的实际的物理地址段,这样A进程通过访问虚拟地址访问的实际内存数据在非共享内存的情况下,只属于A进程,B进程无法直接访问。 - - OpenHarmony由于资源有限,对于内核态和用户态的进程采用不同的方式:所有的内核态进程共享同一块VMM空间,即所有的内核态进程之间无隔离,系统启动时内核态创建两个基本进程KProcess和KIdle,KProcess进程为内核态进程的根进程,KIdle进程为KProcess进程的子进程;但是对于每一个用户态进程均拥有自己独立的VMM空间,相互之间不可见,实现进程间隔离。 - -- 自主访问控制 - - 自主访问控制DAC(Discretionary Access Control)的思想是文件权限由文件拥有者来决定其他角色的访问权限。权限管控粒度分为三类:user\(自身\), group\(组员\),other\(其他人\),即UGO。将任意用户分类为UGO中三者之一,并采取相应的管控策略,即完成了DAC权限校验流程。 - - DAC机制依赖于进程的uid、gid等属性,需要以此作为文件创建以及文件访问过程中的特征id。文件创建时,创建者将自身uid写入文件,文件访问时,又以此作为文件归属的分类依据。 - - 每一个应用,对应一个uid。应用在创建文件时,将自身uid信息加入被创建文件的元数据\(metadata\)中,并设置UGO三个组的权限。在文件访问过程中,将以访问者uid作为访问校验主体、以文件元数据中的uid权限信息作为客体,进行权限校验。 - - 下图描述了DAC在文件访问时的鉴权过程,首先匹配进程uid和文件uid属性,其次匹配进程gid和文件gid属性,最后都匹配失败的情况,判断文件other属性是否支持进程的读、写、执行操作。同时支持忽略DAC检测机制(读、写、执行)作为一组系统特权(Capability),支持高权限(如系统服务)对低权限(三方APP)的文件管理。 - - **图 2** DAC流程图 - ![](figures/DAC流程图.png "DAC流程图") - -- Capability机制 - - Capability机制实际上是对root权限的具体细分。在多用户计算机系统中,一般会有一个特殊的角色拥有系统的所有权限,这个角色一般是系统管理员\(root\)。对于OpenHarmony这种需要支持三方应用生态的内核,需要将系统中的特权访问进行管控。系统需要对用户层访问内核的特权级系统调用进行限制。仅允许部分高权限应用进行特权操作。具体实现方式是内核spawn第一个用户程序INIT,其包含全部的特权能力,此后,INIT拉起其他应用框架服务,拉起过程中,对各应用框架进行相应的降权操作,为各应用保留必须的特权能力。 当应用去调用特权接口时,内核态就会通过进程ID查看当前访问者是否有权限访问目标接口。 - -- 安全启动 - - 安全启动是整个系统安全的基础,通过采用数字签名和完整性校验机制,从芯片内部固化的可信启动根开始,逐级校验每一层软件的完整性和合法性,确保最终启动的操作系统软件是厂家提供的正确合法的软件,防止攻击者对系统软件做恶意的篡改和植入,为整个系统提供初始安全的基础运行环境。 - - 在芯片上电后,由于片上ROM代码本身不可更改,因此无需校验;片上ROM基于eFuse中的非对称算法公钥hash对bootloader进行校验。这些过程都基于硬件信任根来进行,是完全可信的。经过此过程校验通过的bootloader模块可以作为后续的信任基础,此过程就是启动信任链的构造过程。Bootloader通常首先对执行环境进行一定的初始化,主要是初始化DDR以及flash读写,为进一步加载后续模块以及执行更为复杂的逻辑进行准备。Bootloader完成初始化动作后,首先完成x509证书的完整性校验,然后利用x509证书的公钥对需要校验的镜像包(kernel.bin、teeOS.bin、rootfs.bin)进行校验。 - - -## 推荐做法 - -- 自主访问控制和Capability机制是控制资源被谁可以访问的机制,建议所有权限设置都采用最小权限原则。 -- 安全启动必须要开启,信任根必须是基于芯片的不可更改的形式存在,并且在有安全升级的情况下,必须考虑安全升级后对于安全启动的影响,也就是安全升级后必须要更新对应镜像文件的签名信息或者hash值。 - -## 数据安全 - -## 安全机制 - -HUKS(Huawei Universal Keystore Service),提供了密钥管理、证书管理服务,当前在OpenHarmony上主要提供密钥管理服务,用于支撑HiChain\(设备身份认证平台\)的基础设备认证。如下是HUKS的功能结构图: - -**图 3** HUKS功能结构图 -![](figures/HUKS功能结构图.png "HUKS功能结构图") - -支持算法包括: - -- 认证加密:AES-128/192/256-GCM -- 签名验签:ED25519 -- 密钥协商:X25519 -- 消息认证:HMAC-SHA256/512 -- 数据摘要:SHA256/512 - -HUKS在使用中有如下约束: - -- 密钥安全存储:密钥要求存储于安全存储区域,数据不可以修改,恢复出厂设置时出厂预置的密钥不能被删除。 -- 密钥访问安全:OpenHarmony通过将不同应用数据保存在不同的位置,来实现应用间数据的隔离。通过参数结构体中包含UID和进程ID,来实现不同应用间的数据隔离。 -- 不支持并发访问:HUKS本身不考虑多个应用同时调用的情况,因为HUKS只是一个lib库,也不考虑资源的互斥。如果有多个应用都会用到HUKS服务,那么应该由每个应用各自链接一份HUKS库,并由业务传入持久化数据存储的路径,以实现应用间的数据存储分开。数据存储在各应用各自存储目录下。 - -## 推荐做法 - -对于设备认证功能,建议使用HiChain来对接HUKS,HUKS可以向HiChain等应用提供密钥的产生、导入、导出、加密/解密、存储、销毁,证书的导入和查询,秘密信息的存储等能力。 - -## 设备互联安全 - -为了实现用户数据在设备互联场景下在各个设备之间的安全流转,需要保证设备之间相互正确可信,即设备和设备之间建立信任关系,并能够在验证信任关系后,搭建安全的连接通道,实现用户数据的安全传输。设备之间的信任关系在本文档中涉及IoT主控设备和IoT设备之间建立的可信关系。设备间可信关系建立的流程如下图所示: - -**图 4** 设备间建立可信关系流程图 -![](figures/设备间建立可信关系流程图.png "设备间建立可信关系流程图") - -- **IoT设备互联安全** - - 设备互联支持基于OpenHarmony的IoT设备(如AI音箱、智能家居、智能穿戴等设备)与IoT主控设备间建立点对点的信任关系,并在具备信任关系的设备间,搭建安全的连接通道,实现用户数据端到端加密传输。 - - -- **IoT主控设备的IoT业务身份标识** - - IoT主控设备为不同的IoT设备管理业务生成不同的身份标识,形成不同IoT管理业务间的隔离,该标识用于IoT主控设备与IoT设备之间的认证以及通信。IoT业务身份标识为椭圆曲线公私钥对(Ed25519公私钥对)。 - - -- **IoT设备身份标识** - - IoT设备会生成各自的设备身份标识,用来与IoT主控设备通信。该身份标识同样为椭圆曲线公私钥对(Ed25519公私钥对);IoT设备私钥不出IoT设备,设备每次恢复出厂设置,会重置这个公私钥对。 - - 上述身份标识可用于IoT主控设备与IoT设备间的安全通信:当IoT主控设备与IoT设备通过信任绑定流程交换业务身份标识或设备标识后,可以进行密钥协商并建立安全通信通道。 - - -- **设备间点对点的信任绑定** - - IoT主控设备和IoT设备建立点对点信任关系的过程,实际上是相互交换IoT设备的身份标识的过程。 - - 在点对点建立信任关系的过程中,用户需要在IoT主控设备上,输入IoT设备上提供的PIN码:对于有屏幕的设备,该PIN码动态生成;对于没有屏幕的设备,该PIN码由设备生产厂家预置;PIN码的展示形式,可以是一个用户可读的数字,也可以是一个二维码。随后,IoT主控设备和IoT设备间使用PAKE协议完成认证和会话密钥协商过程,并在此基础上,通过协商出的会话密钥加密传输通道用于交换双方设备的身份标识公钥。 - - -- **IoT主控设备与IoT设备间的通信安全** - - 当建立过信任关系的IoT主控设备与IoT设备间进行通信时,双方在完成上述信任关系绑定后,基于本地存储的对端身份公钥相互进行认证;在每次通信时基于STS协议完成双向身份认证以及会话密钥协商,之后设备使用此会话密钥加密双方设备间的传输通道。 - - -## 应用安全 - -## 安全机制 - -- 应用签名管控 - - OpenHarmony应用的安装需要首先对包的完整性进行校验,具体策略是在开发阶段完成开发和调试后对安装包进行签名,这个签名需要使用指定的私钥,这个私钥就是跟验签用的公钥是一对的,一般的做法是OEM厂商生成一对公私钥,然后将公钥信息预置到设备中,而私钥就放在一个不联网的本地服务器上,这样可以确保私钥被泄露的风险尽量小,而应用在完成开发后就可以通过外置设备(例如USB)上传安装包到存放私钥的服务器上计算签名并下载签名结果到外置设备上。而安装应用时首先计算包的Hash值,一般采用SHA256算法,然后使用hash值和签名信息以及预置公钥进行验签,只有验签通过的应用才能安装。 - - 除了要证明应用来自云端认证过的,还需要证明来源,即这个应用来自合法开发者开发的,具体做法是,开发者向云端申请开发证书,开发完成后,用开发证书进行自签名,设备端存放这个证书的上一级证书,所以安装过程中,对自签名信息做校验,确保开发者的合法性。 - -- 应用权限控制 - - 由于OpenHarmony系统允许安装三方应用,所以需要对三方应用的敏感权限调用进行管控,具体实现是应用在开发阶段就需要在profile.json中指明此应用在运行过程中可能会调用哪些敏感权限,这些权限包括静态权限和动态权限,静态权限表示只需要在安装阶段注册就可以,而动态权限一般表示获取用户的敏感信息,所以需要在运行时让用户确认才可以调用,授权方式包括系统设置应用手动授权等。除了运行时对应用调用敏感权限进行管控外,还需要利用应用签名管控手段确保应用安装包已经被设备厂商进行了确认。 - - **表 1** **OpenHarmony系统权限列表** - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    OpenHarmony系统权限

    -

    授权方式

    -

    权限说明

    -

    ohos.permission.LISTEN_BUNDLE_CHANGE

    -

    system_grant(静态权限)

    -

    允许该应用获取应用变化消息。

    -

    ohos.permission.GET_BUNDLE_INFO

    -

    system_grant(静态权限)

    -

    允许该应用获取应用信息。

    -

    ohos.permission.INSTALL_BUNDLE

    -

    system_grant(静态权限)

    -

    允许该应用安装应用。

    -

    ohos.permission.CAMERA

    -

    user_grant(动态权限)

    -

    此应用可随时使用相机拍摄照片和录制视频。

    -

    ohos.permission.MODIFY_AUDIO_SETTINGS

    -

    system_grant(静态权限)

    -

    允许该应用修改全局音频设置,例如音量和用于输出的扬声器。

    -

    ohos.permission.READ_MEDIA

    -

    user_grant(动态权限)

    -

    允许该应用读取您的视频收藏。

    -

    ohos.permission.MICROPHONE

    -

    user_grant(动态权限)

    -

    此应用可随时使用麦克风进行录音。

    -

    ohos.permission.WRITE_MEDIA

    -

    user_grant(动态权限)

    -

    允许该应用写入您的音乐收藏。

    -

    ohos.permission.DISTRIBUTED_DATASYNC

    -

    user_grant(动态权限)

    -

    管控分布式数据传输能力。

    -

    ohos.permission.DISTRIBUTED_VIRTUALDEVICE

    -

    user_grant(动态权限)

    -

    允许应用使用分布式虚拟能力

    -
    - - -## 推荐做法 - -开发者在开发过程中需明确后续应用在运行时需要运行哪些权限,并在profile.json中进行注册,然后需要对应用进行签名,确保设备在安装这些应用时能对应用的完整性和来源进行校验。 - diff --git "a/zh-cn/device-dev/security/\351\232\220\347\247\201\344\277\235\346\212\244.md" "b/zh-cn/device-dev/security/\351\232\220\347\247\201\344\277\235\346\212\244.md" deleted file mode 100755 index 3777685f3f..0000000000 --- "a/zh-cn/device-dev/security/\351\232\220\347\247\201\344\277\235\346\212\244.md" +++ /dev/null @@ -1,264 +0,0 @@ -# 隐私保护 - -- [隐私保护概述](#section13200134331414) -- [数据分类分级](#section2371104991511) -- [通用隐私设计规则](#section10354102411162) -- [特殊品类要求](#section118861450201618) - -## 隐私保护概述 - -随着互联网及信息化的发展,个人数据在社会经济和日常生活中发挥着越来越重要的作用。与此同时,个人数据泄露的风险也在增加,消费者产品开发者需要更加有效的保护用户的个人数据,提高用户对产品的信任度。为了提升消费者的隐私体验,产品应默认设置较高级别隐私保护策略,达到保护消费者隐私的目的。 - -**基本概念** - -- **个人数据(Personal Data)** - - 与一个身份已被识别或者身份可被识别的自然人(“数据主体”)相关的任何信息;身份可识别的自然人是指其身份可以通过诸如姓名、身份证号、位置数据等识别码或者通过一个或多个与自然人的身体、生理、精神、经济、文化或者社会身份相关的特定因素来直接或者间接地被识别。个人数据包括:自然人的email地址、电话号码、生物特征(指纹)、位置数据、IP地址、医疗信息、宗教信仰、社保号、婚姻状态等。 - -- **敏感个人数据(Sensitive Personal Data)** - - 敏感个人数据是个人数据的一个重要子集,指的是涉及数据主体的最私密领域的信息或者一旦泄露可能会给数据主体造成重大不利影响的数据。欧盟等国家和地区法律定义的敏感个人数据包括种族、政治观点、宗教和哲学信仰、工会成员资格、基因数据、生物信息、健康和性生活状况、性取向等。 - - 根据业界最佳实践,敏感个人数据还包括可与自然人身份相关联的银行卡号、身份证号、护照号、口令等。敏感个人数据的处理需要更多更严格的保护措施。 - -- **公开个人数据(Public available Personal Data)** - - 数据主体主动公开的个人数据,或公开网页/应用上可访问的个人数据,包括论坛公开的发帖、评论等。 - -- **用户画像(User Profile)** - - 指对个人数据采取的任何自动化处理的方式,包括评估某个自然人特定方面的情况,尤其是为了分析和预测该自然人的工作表现、经济状况、健康、个人喜好、兴趣、可信度、行为举止、所在位置或行迹。 - -- **数据控制者(Data Controller)** - - 单独或者与他人共同确定个人数据处理的目的和手段的自然人、法人、公共机构、政府部门或其他机构。 - -- **数据处理者(Data Processor)** - - 指代表数据控制者处理个人数据的自然人、法人、公共机构、政府部门或其他机构。数据处理者必须按照数据控制者的要求对个人数据进行充分的保护。 - -- **明示同意(Explicit consent)** - - 如下几种情形GDPR法律提到可以通过数据主体明示同意的方式合法地处理数据: - - - 处理敏感个人数据。 - - 自动化决策,包括进行用户画像。 - - 向不具备充分保护水平的国家转移个人数据,并以同意作为合法性基础。 - - 实现明示同意的方式有: - - - 在收集特定数据时,弹出隐私声明告知个人数据处理相关事项,提供勾选框但不默认勾选,让数据主体勾选“我同意以上述方式处理我的个人数据”,或提供“我同意”的按钮让用户主动点击。 - - 以书面的方式明确表达同意,数据主体在书面陈述上签字。 - - 要求数据主体在系统中上传带有其签名的电子表格。 - - 采取双重验证的方式,要求数据主体邮件形式回复同意后,再次点击用于验证的邮件链接或是输入SMS验证码。 - - 用户主动输入的场景,例如用户主动输入身份证和银行卡号绑卡等场景。 - - -## 数据分类分级 - -基于数据保护目标及风险后果,即数据遭到泄露或者遭到破坏带来的法律风险对个人、组织或公众的影响对数据进行定级,分为极高、高、中、低、公开五个数据级别。 - -**表1** 数据分类分级标准 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    数据级别

    -

    隐私风险

    -

    隐私属性

    -

    典型示例

    -

    极高级

    -

    数据一旦识别或关联到特定个人或群体,其泄露或不当使用可能会给个人带来灾难性负面影响。

    -

    敏感个人数据

    -

    DNA、种族、宗教信仰、性取向;生物识别信息;原始通信内容;银行卡密码、磁道数据。

    -

    高级别

    -

    数据一旦识别或关联到特定个人或群体,其泄露或不当使用可能会给个人带来严重负面影响。

    -

    敏感个人数据

    -

    权威社会标识(身份证、护照等);网页浏览记录;轨迹信息;云空间上传的内容数据(图库/音频/视频等)。

    -

    中级别

    -

    数据一旦识别或关联到特定个人或群体,其泄露或不当使用可能会给个人带来重大负面影响。

    -

    一般个人数据

    -

    设备标识(IMEI, SN, OAID )、用户标识(user ID);个人基本信息(姓名,地址);手机号、邮箱等。

    -

    低级别

    -

    数据一旦识别或关联到特定个人或群体,其泄露或不当使用可能会给个人带来有限负面影响。

    -

    一般个人数据

    -

    操作系统设置信息(操作系统版本,国家/地区等);设备硬件信息(设备型号,屏幕尺寸,屏幕分辨率等);网络信息(网络连接状态,接入网络信息);设备状态(登录设备时间/时长)。

    -

    公开(无风险)

    -

    对个人或组织无不利影响的可公开数据

    -

    非个人数据

    -

    公开发布的产品介绍,公开的会议信息,外部开源的代码等。

    -
    - -备注:隐私保护和数据分类分级的相关定义参照GDPR中的相关内容。 - -## 通用隐私设计规则 - -为了指导厂商完成产品的隐私设计工作,我们整理了以下通用的隐私设计要求,作为OpenHarmony设备厂商产品隐私设计的指南和参考。 - -**数据收集及使用公开透明** - -采集个人数据时,应清晰、明确地告知用户,并确保告知用户的个人信息将被如何使用。 - -- 针对不同等级的个人数据需要制定针对性的隐私处理策略。 - - 敏感个人数据的采集需要获取数据主体明示同意。 - - 一般个人数据的采集需要数据主体同意或基于其他合法授权。 - - 非个人数据与中、高或极高级别个人数据关联采集,需要数据主体同意或其他合法授权,并在隐私声明中呈现。 - -- 应制定并遵从适当的隐私政策。在收集、使用留存和第三方分享用户个人数据时需要符合所有适用法律、政策和规定。如在收集个人数据前,需充分告知用户处理个人数据的种类、目的、处理方式、保留期限等,满足数据主体权利相关要求。 - - 根据以上要求,我们设计了正确示例以供参考。隐私通知/声明的参考示例如下: - - **图 1** 隐私通知/声明示例图 - - - ![](figures/2-应用启动预授权.png) ![](figures/3-应用隐私声明.png) - -- 个人数据应当基于具体、明确、合法的目的收集,不应与此目的不相符的方式作进一步处理。对于收集目的变更和用户撤销同意后再次重新使用的场景都需要用户重新同意。隐私声明变更和撤销的示例如下图: - - **图 2** 隐私通知/声明变更示例图 - - - ![](figures/4-隐私声明变更通知.png) - - **图 3** 撤销同意示例图 - - - ![](figures/6-1-隐私声明撤销.png) ![](figures/6-2-隐私声明撤销.png) - -- 需要提供用户查看隐私声明的入口。例如,可以在应用的“关于”界面提供查看隐私声明的入口,如示例图所示: - - **图 4** 隐私声明查看界面示例图 - - - ![](figures/5-应用隐私声明入口.png) - - -**数据收集及使用最小化** - -个人数据收集应与数据处理目的相关,且是适当、必要的。开发者应尽可能对个人数据进行匿名化或假名化处理,降低对数据主体的风险。仅可收集和处理与特定目的相关且必需的个人数据,不能进行与特定目的不相关的进一步处理。 - -- 敏感权限申请的时候要满足权限最小化的要求,在申请权限时,只申请获取必需的信息或资源所需要的权限。如应用不需要相机权限就能够实现其功能时,则不应该向用户申请相机权限。 -- 数据收集最小化:针对数据的收集要满足最小化要求,不收集与产品提供服务无关联的数据。如提供定位服务的产品,不应收集用户的网页浏览记录。 -- 数据使用的功能要求能够使用户受益,收集的数据不能用于一些与用户正常使用无关的功能。数据收集不能有其他与用户正常使用无关的功能存在。如不得将“生物特征”、“健康数据”等敏感个人数据用于服务改进、投放广告或营销等非业务核心功能。 -- 禁止在日志中打印敏感个人数据,如需要打印一般个人数据时,应对个人数据进行匿名化或假名化处理; - - 优先使用可以重置的标识符,如系统提供了NetworkID和DVID作为分布式场景下的设备标识符,广告业务场景下则建议使用[OAID](https://developer.huawei.com/consumer/cn/doc/development/HMSCore-Guides/oaid-0000001050783198),基于应用的分析则建议使用[ODID](https://developer.huawei.com/consumer/cn/doc/development/HMSCore-Guides/odid-0000001051063255)和[AAID](https://developer.huawei.com/consumer/cn/doc/development/HMSCore-Guides/aaid-0000001051142988),其他需要唯一标识符的场景可以使用UUID接口生成;可重置的标识符不能满足业务需求时,才选择序列号和MAC地址等永久性标识符。 - - -**数据处理选择和控制** - -对个人数据处理必须要征得用户的同意或遵守其他适用的法律法规,用户对其个人数据要有充分的控制权。 - -- 获取用户敏感权限的授权:产品弹窗提醒,向用户呈现需要获取的权限和权限使用目的,用户可通过选择决定是否进行授权及指定授权的方式,让用户对产品权限的授予和个人数据使用做到透明、可知、可控。如下图所示: - - **图 5** 敏感权限提示框示例图 - - - ![](figures/1-敏感权限弹窗.png) - -- 用户可以修改、取消授予的权限:当用户不同意某一权限或者数据收集时,应当允许用户使用与这部分权限和数据收集不相关的功能。如智慧屏产品上通信社交应用,用户可以拒绝授予相机权限,不应该影响与相机无关的功能操作,如语音通话。 -- 用户在产品使用过程中,针对录入个人数据的场景,需要给用户提供对个人数据的增加、删除、修改、查看的操作。 -- 需要给出硬件回收或返厂进行安全删除个人数据的机制或方法。 -- 对用户系统软件、应用软件的下载或升级,涉及修改用户隐私空间,用户对于这类行为需要有知情权和控制权,必须给用户提示,并提供给用户同意和取消的选项。 - -**数据安全** - -从技术上保证数据处理活动的安全性,包括个人数据的加密存储、安全传输等安全机制,系统应默认开启或采取安全保护措施。 - -- 对于个人数据的访问需要有保护机制,主要包括身份认证和访问控制。身份认证(如用户名、密码)限定只有经过认证的用户才能访问数据,可应用于多用户场景;访问控制(如[权限控制](安全指南.md#li201725506375))可应用于对应用程序的限制。 -- 分布式设备个人数据安全存储要满足密钥管理和存储服务(HUKS:Huawei Universal Keystore)的要求,包括:密钥安全存储、数据安全存储。 -- 个人数据在分布式设备间传输要满足设备间的信任绑定关系和数据传输通道的安全性要求。详细信息可以参考[设备互联安全](安全指南.md#section26153183616)。 -- 认证凭证数据(密码、口令、指纹等)须加密存储。 - -**本地化处理** - -用户数据优先在本设备进行处理,对于本设备无法处理的数据应尽可能在超级终端设备本地进行数据的处理,如果超级终端本地处理无法满足业务目的的,在数据离开超级终端设备本地时应尽可能选择匿名化。 - -**未成年人数据保护要求** - -产品专门给未成年人设计的,或者产品收集用户年龄从而可以识别到是在收集未成年人的个人数据,需结合目标市场国家的法律,专门分析未成年人个人数据保护的问题,收集未成年人数据前需要征得监护人的同意。 - -## 特殊品类要求 - -针对消费者硬件产品来说,除了满足以上的通用隐私要求以外,针对特殊品类的产品还有以下的特殊要求,在产品设计过程中参照执行。 - -**表2** 特殊品类隐私要求 - - - - - - - - - - - - - - - - - - - - - - - - - -

    产品品类

    -

    隐私保护特殊要求

    -

    智能家居

    -

    安防类产品涉及的指纹、声纹、面部识别、虹膜等个人生物识别信息以及用户密码信息,属于敏感个人数据,应采用技术措施处理后(例如提取个人生物识别信息的摘要)再进行加密保存在产品本地。

    -

    智能家居

    -

    安防类产品涉及的音视频和图片,设备厂家作为数据控制者时,必须提供独立的隐私通知、应用界面必须有设备厂家品牌标识;音视频数据的传输和存储必须加密,非用户本人访问安防产品的音视频数据,必须获得用户授权。

    -

    智能家居/影音娱乐

    -

    带有摄像头的产品建议提供物理上可关闭功能,通过隐藏、遮盖、转向让消费者感知摄像头处于关闭状态。

    -

    智能家居/影音娱乐

    -

    带有麦克风的产品建议提供显性显示录音的状态,如录音开启时状态灯闪烁,录音关闭时状态灯熄灭。

    -

    移动办公

    -

    用户数据跨设备显示、传输等场景需要获得消费者的明示同意,给予消费者对其个人数据有充分的控制权。

    -

    车机

    -

    1、隐私通知及权限设置

    -

    避免在驾驶态让用户阅读隐私政策和权限设置。

    -

    车机应用需要考虑车辆使用时的安全性,应避免让用户在驾驶过程中进行复杂的权限设置或阅读隐私政策,比如HiCar应用应该在手机端完成应用基本权限设置和隐私政策阅读后再进行使用。

    -

    隐私声明在确认用户身份后告知。

    -

    车辆的数据会涉及车主、驾驶员和乘客,应保证隐私声明通知到了数据主体本人。建议做法是在确认使用者的身份后进行隐私声明,如需要用户登录的应用,应在账号登录后弹出隐私声明而不是账号登录之前。

    -

    2、共享应用个人数据保护

    -

    共享应用在车机重启后应退出,并对当前用户个人数据进行清除或加密,应用还应提供对历史数据进行彻底删除的功能。

    -

    3、消息提示

    -

    考虑车机的开放环境,应用在车机上进行消息提醒时,应避免直接将消息内容显示在车机上,正确的做法是仅提示有新的消息需要查看。

    -
    - diff --git "a/zh-cn/device-dev/subsystems/AI\345\274\225\346\223\216\346\241\206\346\236\266\345\274\200\345\217\221\346\214\207\345\215\227.md" "b/zh-cn/device-dev/subsystems/AI\345\274\225\346\223\216\346\241\206\346\236\266\345\274\200\345\217\221\346\214\207\345\215\227.md" deleted file mode 100755 index b0e0db5644..0000000000 --- "a/zh-cn/device-dev/subsystems/AI\345\274\225\346\223\216\346\241\206\346\236\266\345\274\200\345\217\221\346\214\207\345\215\227.md" +++ /dev/null @@ -1,9 +0,0 @@ -# AI引擎框架开发指南 - -AI业务子系统是OpenHarmony提供原生的分布式AI能力的子系统。AI业务子系统提供了统一的AI引擎框架,实现算法能力快速插件化集成。框架中主要包含插件管理、模块管理和通信管理等模块,完成对AI算法能力的生命周期管理和按需部署。插件管理主要实现插件的生命周期管理及插件的按需部署,快速集成AI能力插件;模块管理主要实现任务的调度及管理客户端的实例;通信管理主要实现客户端和服务端之间的跨进程通信及引擎与插件之间的数据传输。后续,会逐步定义统一的AI能力接口,便于AI能力的分布式调用。同时,提供适配不同推理框架层级的统一推理接口。AI引擎框架如下[图1](#fig143186187187)所示。 - -**图 1** AI引擎框架 - - -![](figures/zh-cn_image_0000001077727032.png) - diff --git "a/zh-cn/device-dev/subsystems/AI\346\241\206\346\236\266.md" "b/zh-cn/device-dev/subsystems/AI\346\241\206\346\236\266.md" deleted file mode 100755 index c4310aa764..0000000000 --- "a/zh-cn/device-dev/subsystems/AI\346\241\206\346\236\266.md" +++ /dev/null @@ -1,13 +0,0 @@ -# AI框架 - -- **[AI引擎框架开发指南](AI引擎框架开发指南.md)** - -- **[搭建环境](搭建环境.md)** - -- **[技术规范](技术规范.md)** - -- **[开发指导](开发指导.md)** - -- **[开发示例](开发示例.md)** - - diff --git a/zh-cn/device-dev/subsystems/DFX.md b/zh-cn/device-dev/subsystems/DFX.md deleted file mode 100755 index e5f00a7203..0000000000 --- a/zh-cn/device-dev/subsystems/DFX.md +++ /dev/null @@ -1,11 +0,0 @@ -# DFX - -- **[DFX概述](DFX概述.md)** - -- **[HiLog开发指导](HiLog开发指导.md)** - -- **[HiLog\_Lite开发指导](HiLog_Lite开发指导.md)** - -- **[HiSysEvent开发指导](HiSysEvent开发指导.md)** - - diff --git "a/zh-cn/device-dev/subsystems/OTA\345\215\207\347\272\247.md" "b/zh-cn/device-dev/subsystems/OTA\345\215\207\347\272\247.md" deleted file mode 100755 index 0423c0b612..0000000000 --- "a/zh-cn/device-dev/subsystems/OTA\345\215\207\347\272\247.md" +++ /dev/null @@ -1,358 +0,0 @@ -# OTA升级 - -- [约束与限制](#section691733275418) -- [生成公私钥对](#section94411533155010) -- [生成升级包](#section632383718539) -- [上传升级包](#section5772112473213) -- [下载升级包](#section251732474917) -- [厂商应用集成OTA能力](#section298217330534) -- [API应用场景-默认场景](#section7685171192916) - - [开发指导](#section0745926153017) - - [示例代码](#section1337111363306) - -- [API应用场景-定制场景](#section1686395317306) - - [开发指导](#section524515314317) - - [示例代码](#section525974743120) - -- [系统升级](#section151997114334) - -OTA(Over the Air)提供对设备远程升级的能力,可以让您的设备(如IP摄像头等),轻松支持远程升级能力。目前仅支持全量包升级,暂不支持差分包升级。全量包升级是将新系统全部内容做成升级包,进行升级;差分包升级是将新老系统的差异内容做成升级包,进行升级。 - -## 约束与限制 - -- 支持基于Hi3861/Hi3518EV300/Hi3516DV300芯片的开源套件。 -- 对Hi3518EV300/Hi3516DV300开源套件,设备需要支持SD卡(VFAT格式)。 - -## 生成公私钥对 - -1. 准备工作:在Windows PC 上,下载安装OpenSSL工具,并配置环境变量。OpenSSL下载路径: - - [http://slproweb.com/products/Win32OpenSSL.html](http://slproweb.com/products/Win32OpenSSL.html) - -2. 在tools\\update\_tools\\update\_pkg\_tools目录下,下载升级包制作工具,保存到Windows本地路径,例如D:\\ota\_tools。 -3. 如图,运行ota\_tools\\key下的Generate\_public\_private\_key.bat ,生成公钥Metis\_PUBLIC.key、私钥private.key和公钥对应的数组public\_arr.txt文件,请妥善保管私钥private.key。 - - **图 1** 生成公私钥对 - - - ![](figures/zh-cn_image_0000001060200050.png) - -4. 用public\_arr.txt里面的全部内容替换OTA模块base\\update\\ota\_lite\\frameworks\\source\\verify\\hota\_verify.c中的g\_pubKeyBuf 。 - - 示例,public\_arr.txt内容 - - ``` - 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, - ``` - - 示例,OTA模块的公钥 - - ``` - #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, - ``` - -5. 对Hi3518EV300/Hi3516DV300套件,在上一步的基础上,还需用public\_arr.txt里面的全部内容替换uboot模块device\\hisilicon\\third\_party\\uboot\\u-boot-2020.01\\product\\hiupdate\\verify\\update\_public\_key.c中的g\_pub\_key中的全部内容。 - - 示例,uboot模块的公钥 - - ``` - static unsigned char g_pub_key[PUBKEY_LEN] = { - 0x30, 0x82, 0x01, 0x0A, 0x02, 0x82, 0x01, 0x01, - 0x00, 0xBF, 0xAA, 0xA5, 0xB3, 0xC2, 0x78, 0x5E, - ``` - - -## 生成升级包 - -1. 在ota\_tools\\Components目录下,归放需要升级的文件。 - - **图 2** 原始镜像归放位置 - - - ![](figures/zh-cn_image_0000001061889268.png) - - **表 1** 升级包内的文件 - - - - - - - - - - - - - - - - - - - - - - -

    包内文件名

    -

    说明

    -

    u-boot.bin

    -

    将编译生成的u-boot-hi351XevX00.bin文件重命名后得到。

    -

    kernel.bin

    -

    将编译生成的liteos.bin/kernel文件重命名后得到。

    -

    rootfs.img

    -

    将编译生成的rootfs_xxxxx.img文件重命名后得到。

    -

    config

    -

    与开发板类型和内核类型相关,参考开源套件的SD卡烧写说明。

    -

    OTA.tag

    -

    共32字节,内容为:“package_type:otaA1S2D3F4G5H6J7K8”;其中后16字节为随机数,需要随版本变化。

    -
    - -2. 修改ota\_tools\\xml下的packet\_harmony.xml文件,配置compAddr分区名,对应ota\_tools\\Components\\的文件,其它项不需修改,作为扩展项预留。 - - 示例,配置组件信息 - - ``` - - - .\Components\rootfs_jffs2.img - .\Components\liteos.bin - .\Components\userfs_jffs2.img - - ``` - -3. 将生成的公私钥路径配置到ota\_tools\\xml路径下的packet\_harmony.xml中。 - - 示例,配置公私钥路径 - - ``` - - .\key\private.key - .\key\Metis_PUBLIC.key - - ``` - -4. 在ota\_tools\\VersionDefine.bat中设置产品名称、软件版本号(用于防回滚校验)。 - - 示例,配置产品名称和版本号 - - ``` - set FILE_PRODUCT_NAME=Hisi - - @rem 设置软件版本号 不要超过16位 - set SOFTWARE_VER=OpenHarmony 1.1 - ``` - -5. 执行ota\_tools下的Make\_Harmony\_PKG.bat,生成升级包Hisi\_OpenHarmony 1.1.bin。升级包通过SHA256+RSA2048方式签名,保证完整性和合法性。 - - **图 3** 升级包制作工具 - - - ![](figures/zh-cn_image_0000001059334449.png) - - -## 上传升级包 - -将升级包Hisi\_OpenHarmony 1.1.bin上传到厂商的OTA服务器。 - -## 下载升级包 - -1. 厂商应用从OTA服务器下载Hisi\_OpenHarmony 1.1.bin。 -2. 对Hi3518EV300/Hi3516DV300开源套件,需要插入SD卡\(容量\>100MBytes\)。 - -## 厂商应用集成OTA能力 - -- 调用OTA模块的动态库libhota.so,对应头文件位于:base\\update\\ota\_lite\\interfaces\\kits\\hota\_partition.h&hota\_updater.h; -- libhota.so对应的源码路径为base\\update\\ota\_lite\\frameworks\\source。 -- API的使用方法,见本文“API应用场景”和API文档的OTA接口章节。 -- 如果需要适配开发板,请参考HAL层头文件:base\\update\\ota\_lite\\hals\\hal\_hota\_board.h。 - -## API应用场景-默认场景 - -升级包是按照上文“生成公私钥对”和“生成升级包”章节制作的。 - -### **开发指导** - -1. 应用侧通过下载,获取当前设备升级包后,调用HotaInit接口初始化OTA模块。 -2. 调用HotaWrite接口传入升级包数据流,接口内部实现校验、解析及写入升级数据流。 -3. 写入完成后,调用HotaRestart接口重启系统。 - - 升级过程中,使用HotaCancel接口可以取消升级。 - - -### **示例代码** - -使用OpenHarmony的“升级包格式和校验方法“进行升级。 - -``` -int main(int argc, char **argv) -{ - printf("this is update print!\r\n"); - if (HotaInit(NULL, NULL) < 0) { - printf("ota update init fail!\r\n"); - return -1; - } - int fd = open(OTA_PKG_FILE, O_RDWR, S_IRUSR | S_IWUSR); - if (fd < 0) { - printf("file open failed, fd = %d\r\n", fd); - (void)HotaCancel(); - return -1; - } - int offset = 0; - int fileLen = lseek(fd, 0, SEEK_END); - int leftLen = fileLen; - while (leftLen > 0) { - if (lseek(fd, offset, SEEK_SET) < 0) { - close(fd); - printf("lseek fail!\r\n"); - (void)HotaCancel(); - return -1; - } - int tmpLen = leftLen >= READ_BUF_LEN ? READ_BUF_LEN : leftLen; - (void)memset_s(g_readBuf, READ_BUF_LEN, 0, READ_BUF_LEN); - if (read(fd, g_readBuf, tmpLen) < 0) { - close(fd); - printf("read fail!\r\n"); - (void)HotaCancel(); - return -1; - } - if (HotaWrite((unsigned char *)g_readBuf, offset, tmpLen) != 0) { - printf("ota write fail!\r\n"); - close(fd); - (void)HotaCancel(); - return -1; - } - offset += READ_BUF_LEN; - leftLen -= tmpLen; - } - close(fd); - printf("ota write finish!\r\n"); - printf("device will reboot in 10s...\r\n"); - sleep(10); - (void)HotaRestart(); - return 0; -} -``` - -## API应用场景-定制场景 - -升级包不是按照上文“生成公私钥对”和“生成升级包”章节制作的,是通过其它方式制作的。 - -### **开发指导** - -1. 应用侧通过下载,获取当前设备升级包后,调用HotaInit接口初始化。 -2. 使用HotaSetPackageType接口设置NOT\_USE\_DEFAULT\_PKG,使用"定制"流程。 -3. 调用HotaWrite接口传入升级包数据流,写入设备。 -4. 写入完成后,调用HotaRead接口读取数据,厂商可以自行校验升级包。 -5. 调用HotaSetBootSettings设置启动标记,在重启后需要进入uboot模式时使用(可选)。 -6. 调用HotaRestart接口,进行重启。 - - 升级过程中,使用HotaCancel接口可以取消升级。 - - -### **示例代码** - -使用非OpenHarmony的“升级包格式和校验方法“进行升级。 - -``` -int main(int argc, char **argv) -{ - printf("this is update print!\r\n"); - if (HotaInit(NULL, NULL) < 0) { - printf("ota update init fail!\r\n"); - (void)HotaCancel(); - return -1; - } - (void)HotaSetPackageType(NOT_USE_DEFAULT_PKG); - int fd = open(OTA_PKG_FILE, O_RDWR, S_IRUSR | S_IWUSR); - if (fd < 0) { - printf("file open failed, fd = %d\r\n", fd); - (void)HotaCancel(); - return -1; - } - int offset = 0; - int fileLen = lseek(fd, 0, SEEK_END); - int leftLen = fileLen; - while (leftLen > 0) { - if (lseek(fd, offset, SEEK_SET) < 0) { - close(fd); - printf("lseek fail!\r\n"); - (void)HotaCancel(); - return -1; - } - int tmpLen = leftLen >= READ_BUF_LEN ? READ_BUF_LEN : leftLen; - (void)memset_s(g_readBuf, READ_BUF_LEN, 0, READ_BUF_LEN); - if (read(fd, g_readBuf, tmpLen) < 0) { - close(fd); - printf("read fail!\r\n"); - (void)HotaCancel(); - return -1; - } - if (HotaWrite((unsigned char *)g_readBuf, offset, tmpLen) != 0) { - printf("ota write fail!\r\n"); - close(fd); - (void)HotaCancel(); - return -1; - } - offset += READ_BUF_LEN; - leftLen -= tmpLen; - } - close(fd); - printf("ota write finish!\r\n"); - leftLen = fileLen; - while (leftLen > 0) { - int tmpLen = leftLen >= READ_BUF_LEN ? READ_BUF_LEN : leftLen; - (void)memset_s(g_readBuf, READ_BUF_LEN, 0, READ_BUF_LEN); - if (HotaRead(offset, READ_BUF_LEN, (unsigned char *)g_readBuf) != 0) {} - printf("ota write fail!\r\n"); - (void)HotaCancel(); - return -1; - } - /* do your verify and parse */ - offset += READ_BUF_LEN; - leftLen -= tmpLen; - } - /* set your boot settings */ - (void)HotaSetBootSettings(); - printf("device will reboot in 10s...\r\n"); - sleep(10); - (void)HotaRestart(); - return 0; -} -``` - -## 系统升级 - -厂商应用调用OTA模块的API,OTA模块执行升级包的签名验证、版本防回滚、烧写落盘功能,升级完成后自动重启系统。 - -对Hi3518EV300/Hi3516DV300开源套件,在需要实现防回滚功能的版本中,需要增加LOCAL\_VERSION的值,如"ohos default 1.0"-\>"ohos default 1.1",LOCAL\_VERSION在device\\hisilicon\\third\_party\\uboot\\u-boot-2020.01\\product\\hiupdate\\ota\_update\\ota\_local\_info.c中。 - -示例,增加版本号 - -``` -const char *get_local_version(void) -{ -#if defined(CONFIG_TARGET_HI3516EV200) || \ - defined(CONFIG_TARGET_HI3516DV300) || \ - defined(CONFIG_TARGET_HI3518EV300) -#define LOCAL_VERSION "ohos default 1.0" /* increase: default release version */ -``` - diff --git a/zh-cn/device-dev/subsystems/Readme-CN.md b/zh-cn/device-dev/subsystems/Readme-CN.md index 3032d57b57..7dc0b03cfa 100755 --- a/zh-cn/device-dev/subsystems/Readme-CN.md +++ b/zh-cn/device-dev/subsystems/Readme-CN.md @@ -1,96 +1,78 @@ -# 子系统 - -- [编译构建](编译构建.md) - - [轻量和小型系统编译构建指导](轻量和小型系统编译构建指导.md) - - [编译构建概述](编译构建概述.md) - - [编译构建使用指导](编译构建使用指导.md) - - [编译构建常见问题](编译构建常见问题.md) - - - [标准系统编译构建指导](标准系统编译构建指导.md) - - [编译构建概述](编译构建概述-0.md) - - [编译构建使用指导](编译构建使用指导-1.md) - -- [分布式远程启动](分布式远程启动.md) -- [图形图像](图形图像.md) - - [图形图像概述](图形图像概述.md) - - [容器类组件开发指导](容器类组件开发指导.md) - - [布局容器类组件开发指导](布局容器类组件开发指导.md) - - [普通组件开发指导](普通组件开发指导.md) - - [动画开发指导](动画开发指导.md) - -- [媒体](媒体.md) - - [相机](相机.md) - - [相机开发概述](相机开发概述.md) - - [拍照开发指导](拍照开发指导.md) - - [录像开发指导](录像开发指导.md) - - [预览开发指导](预览开发指导.md) - - - [音视频](音视频.md) - - [音视频开发概述](音视频开发概述.md) - - [音视频播放开发指导](音视频播放开发指导.md) - - [音视频录制开发指导](音视频录制开发指导.md) - -- [公共基础](公共基础.md) - - [公共基础库概述](公共基础库概述.md) - - [公共基础库开发指导](公共基础库开发指导.md) - - [公共基础库常见问题](公共基础库常见问题.md) - -- [AI框架](AI框架.md) - - [AI引擎框架开发指南](AI引擎框架开发指南.md) - - [搭建环境](搭建环境.md) - - [技术规范](技术规范.md) - - [代码管理规范](代码管理规范.md) - - [命名规范](命名规范.md) - - [接口开发规范](接口开发规范.md) - - - [开发指导](开发指导.md) - - [SDK开发过程](SDK开发过程.md) - - [插件的开发过程](插件的开发过程.md) - - [配置文件的开发过程](配置文件的开发过程.md) - - - [开发示例](开发示例.md) - - [唤醒词识别SDK的开发示例](唤醒词识别SDK的开发示例.md) - - [唤醒词识别插件的开发示例](唤醒词识别插件的开发示例.md) - - [唤醒词识别配置文件的开发示例](唤醒词识别配置文件的开发示例.md) - -- [Sensor服务](Sensor服务.md) - - [Sensor服务子系概述](Sensor服务子系概述.md) - - [Sensor服务子系使用指导](Sensor服务子系使用指导.md) - - [Sensor服务子系使用实例](Sensor服务子系使用实例.md) - -- [用户程序框架](用户程序框架.md) - - [概述](概述.md) - - [搭建环境](搭建环境-2.md) - - [开发指导](开发指导-3.md) - - [开发实例](开发实例.md) - -- [OTA升级](OTA升级.md) - -- [安全](安全.md) - - [概述](概述-7.md) - - [应用验签开发指导](应用验签开发指导.md) - - [应用权限管理开发指导](应用权限管理开发指导.md) - - [IPC通信鉴权开发指导](IPC通信鉴权开发指导.md) - -- [启动恢复](启动恢复.md) - - [启动恢复子系统概述](启动恢复子系统概述.md) - - [init启动引导组件](init启动引导组件.md) - - [appspawn应用孵化组件](appspawn应用孵化组件.md) - - [bootstrap服务启动组件](bootstrap服务启动组件.md) - - [syspara系统属性组件](syspara系统属性组件.md) - - [常见问题](常见问题.md) - - [参考](参考.md) - -- [测试](测试.md) -- [DFX](DFX.md) - - [DFX概述](DFX概述.md) - - [HiLog开发指导](HiLog开发指导.md) - - [HiLog\_Lite开发指导](HiLog_Lite开发指导.md) - - [HiSysEvent开发指导](HiSysEvent开发指导.md) - -- [研发工具链](研发工具链.md) - - [bytrace使用指导](bytrace使用指导.md) - - [hdc\_std 使用指导](hdc_std-使用指导.md) - -- [XTS认证子系统开发指南](XTS认证子系统开发指南.md) +# 子系统开发指南 + +- [编译构建](subsys-build.md) + - [轻量和小型系统编译构建指导](subsys-build-mini-lite.md) + - [标准系统编译构建指导](subsys-build-standard-large.md) +- [分布式远程启动](subsys-remote-start.md) +- [图形图像](subsys-graphics.md) + - [图形图像概述](subsys-graphics-overview.md) + - [容器类组件开发指导](subsys-graphics-bundle-guide1.md) + - [布局容器类组件开发指导](subsys-graphics-bundle-guide2.md) + - [普通组件开发指导](subsys-graphics-bundle-guide3.md) + - [动画开发指导](subsys-graphics-animation-guide.md) +- [媒体](subsys-multimedia.md) + - [相机](subsys-multimedia-camera.md) + - [相机开发概述](subsys-multimedia-camera-overview.md) + - [拍照开发指导](subsys-multimedia-camera-photo-guide.md) + - [录像开发指导](subsys-multimedia-camera-record-guide.md) + - [预览开发指导](subsys-multimedia-camera-preview-guide.md) + + - [音视频](subsys-multimedia-video.md) + - [音视频开发概述](subsys-multimedia-video-overview.md) + - [音视频播放开发指导](subsys-multimedia-video-play-guide.md) + - [音视频录制开发指导](subsys-multimedia-video-record-guide.md) +- [公共基础](subsys-utils.md) + - [公共基础库概述](subsys-utils-overview.md) + - [公共基础库开发指导](subsys-utils-guide.md) + - [公共基础库常见问题](subsys-utils-faqs.md) +- [AI框架](subsys-aiframework.md) + - [AI引擎框架开发指南](subsys-aiframework-guide.md) + - [搭建环境](subsys-aiframework-envbuild.md) + - [技术规范](subsys-aiframework-tech.md) + - [代码管理规范](subsys-aiframework-tech-codemanage.md) + - [命名规范](subsys-aiframework-tech-name.md) + - [接口开发规范](subsys-aiframework-tech-interface.md) + + - [开发指导](subsys-aiframework-devguide.md) + - [SDK开发过程](subsys-aiframework-devguide-sdk.md) + - [插件的开发过程](subsys-aiframework-devguide-plugin.md) + - [配置文件的开发过程](subsys-aiframework-devguide-conf.md) + + - [开发示例](subsys-aiframework-demo.md) + - [唤醒词识别SDK的开发示例](subsys-aiframework-demo-sdk.md) + - [唤醒词识别插件的开发示例](subsys-aiframework-demo-plugin.md) + - [唤醒词识别配置文件的开发示例](subsys-aiframework-demo-conf.md) +- [Sensor服务](subsys-densor.md) + - [Sensor服务子系概述](subsys-densor-overview.md) + - [Sensor服务子系使用指导](subsys-densor-guide.md) + - [Sensor服务子系使用实例](subsys-densor-demo.md) +- [用户程序框架](subsys-application-framework.md) + - [概述](subsys-application-framework-overview.md) + - [搭建环境](subsys-application-framework-builden.md) + - [开发指导](subsys-application-framework-guide.md) + - [开发实例](subsys-application-framework-demo.md) +- [OTA升级](subsys-ota-guide.md) +- [安全](subsys-security.md) + - [概述](subsys-security-overview.md) + - [应用验签开发指导](subsys-security-sigverify.md) + - [应用权限管理开发指导](subsys-security-rightmanagement.md) + - [IPC通信鉴权开发指导](subsys-security-communicationverify.md) +- [启动恢复](subsys-boot.md) + - [启动恢复子系统概述](subsys-boot-overview.md) + - [init启动引导组件](subsys-boot-init.md) + - [appspawn应用孵化组件](subsys-boot-appspawn.md) + - [bootstrap服务启动组件](subsys-boot-bootstrap.md) + - [syspara系统属性组件](subsys-boot-syspara.md) + - [常见问题](subsys-boot-faqs.md) + - [参考](subsys-boot-ref.md) +- [测试](subsys-testguide-test.md) +- [DFX](subsys-dfx.md) + - [DFX概述](subsys-dfx-overview.md) + - [HiLog开发指导](subsys-dfx-hilog-rich.md) + - [HiLog\_Lite开发指导](subsys-dfx-hilog-lite.md) + - [HiSysEvent开发指导](subsys-dfx-hisysevent.md) +- [研发工具链](subsys-toolchain.md) + - [bytrace使用指导](subsys-toolchain-bytrace-guide.md) + - [hdc\_std 使用指导](subsys-toolchain-hdc-guide.md) +- [XTS认证子系统开发指南](subsys-xts-guide.md) diff --git "a/zh-cn/device-dev/subsystems/SDK\345\274\200\345\217\221\350\277\207\347\250\213.md" "b/zh-cn/device-dev/subsystems/SDK\345\274\200\345\217\221\350\277\207\347\250\213.md" deleted file mode 100755 index 83d933cdb5..0000000000 --- "a/zh-cn/device-dev/subsystems/SDK\345\274\200\345\217\221\350\277\207\347\250\213.md" +++ /dev/null @@ -1,162 +0,0 @@ -# SDK开发过程 - -SDK头文件的功能实现是基于对SDK的调用映射到对client的调用。Client端提供的接口如下[表1](#table203963834718)所示。 - -**表 1** Client端提供的接口 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    接口名

    -

    接口说明

    -

    参数要求

    -

    int AieClientInit(const ConfigInfo &configInfo, ClientInfo &clientInfo, const AlgorithmInfo &algorithmInfo, IServiceDeadCb *cb)

    -

    作用:链接并初始化引擎服务,激活跨进程调用。

    -

    返回值:0为成功,其他返回值失败。

    -

    configInfo(NOT NULL):引擎相关初始化配置数据;

    -

    clientInfo(NOT NULL):引擎客户端信息;

    -

    algorithmInfo(NOT NULL):调用算法信息;

    -

    cb(可为NULL):死亡回调 对象;

    -

    int AieClientPrepare(const ClientInfo &clientInfo, const AlgorithmInfo &algorithmInfo, const DataInfo &inputInfo, DataInfo &outputInfo, IClientCb *cb)

    -

    作用:加载算法插件。

    -

    返回值: 0为成功,其他返回值失败。

    -

    clientInfo(NOT NULL):引擎客户端信息;

    -

    algorithmInfo(NOT NULL):调用算法信息;

    -

    inputInfo(可为NULL):加载算法插件时输入所需信息;

    -

    outputInfo(可为NULL):加载算法插件之后如需返回信息则通过此出参返回;

    -

    cb:异步算法通过此回调返回运算结果,因此异步算法此结构体不能为空;若为同步算法,传入空值即可;

    -

    int AieClientAsyncProcess(const ClientInfo &clientInfo, const AlgorithmInfo &algorithmInfo, const DataInfo &inputInfo)

    -

    作用:执行异步算法。

    -

    返回值:0为成功,其他返回值失败。

    -

    clientInfo(NOT NULL):引擎客户端信息;

    -

    algorithmInfo(NOT NULL):调用算法信息;

    -

    inputInfo(可为NULL):算法运算入参;

    -

    int AieClientSyncProcess(const ClientInfo &clientInfo, const AlgorithmInfo &algorithmInfo, const DataInfo &inputInfo, DataInfo &outputInfo)

    -

    作用:执行同步算法。

    -

    返回值:0为成功,其他返回值失败。

    -

    clientInfo(NOT NULL):引擎客户端信息;

    -

    algorithmInfo(NOT NULL):调用算法信息;

    -

    inputInfo(可为NULL):算法运算入参;

    -

    outputInfo(可为NULL):同步算法运算结果出参;

    -

    int AieClientRelease(const ClientInfo &clientInfo, const AlgorithmInfo &algorithmInfo, const DataInfo &inputInfo)

    -

    作用:卸载算法插件。

    -

    返回值:0为成功,其他返回值失败。

    -

    clientInfo(NOT NULL):引擎客户端信息;

    -

    algorithmInfo(NOT NULL):卸载算法插件的相关信息;

    -

    inputInfo(可为NULL):调用卸载接口时的输入信息;

    -

    int AieClientDestroy(ClientInfo &clientInfo)

    -

    作用:断开与服务端的链接,释放相关缓存。

    -

    返回值:0为成功,其他返回值失败。

    -

    clientInfo(NOT NULL):所要销毁的引擎客户端信息;

    -

    int AieClientSetOption(const ClientInfo &clientInfo, int optionType, const DataInfo &inputInfo)

    -

    作用:设置配置项,可将一些算法的拓展信息通过此接口传入插件。

    -

    返回值:0为成功,其他返回值失败。

    -

    clientInfo(NOT NULL):引擎客户端信息;

    -

    optionType (NOT NULL):算法配置项,算法插件可根据需要利用此状态位;

    -

    inputInfo(可为NULL):插件可根据需要通过此入参设置算法参数信息;

    -

    int AieClientGetOption(const ClientInfo &clientInfo, int optionType, const DataInfo &inputInfo, DataInfo &outputInfo)

    -

    作用:给定特定的optionType和inputInfo,获取其对应的配置项信息。

    -

    返回值:0为成功,其他返回值失败。

    -

    clientInfo(NOT NULL):引擎客户端信息;

    -

    optionType(NOT NULL):所获取配置项信息的对应算法状态位;

    -

    inputInfo(可为NULL):所获取配置项信息的对应算法参数信息;

    -

    outputInfo(可为NULL):所要获取的配置项信息返回结果;

    -
    - -其中,ConfigInfo,ClientInfo,AlgorithmInfo,DataInfo的数据结构如下[表2](#table22154317482)所示。 - -**表 2** ConfigInfo,ClientInfo,AlgorithmInfo,DataInfo的数据结构 - - - - - - - - - - - - - - - - - - - - - - - - -

    结构体名称

    -

    说明

    -

    属性

    -

    ConfigInfo

    -

    算法配置项信息。

    -

    const char *description:配置项信息主体;

    -

    ClientInfo

    -

    客户端信息。

    -

    long long clientVersion:客户端设备版本号(当前还未启用);

    -

    int clientId:客户端ID;

    -

    int sessionId:会话ID;

    -

    uid_t serverUid:server端UID;

    -

    uid_t clientUid:client端UID;

    -

    int extendLen:拓展信息(extendMsg)长度;

    -

    unsigned char *extendMsg:拓展信息主体;

    -

    AlgorithmInfo

    -

    算法信息。

    -

    long long clientVersion:客户端设备版本号(当前还未启用);

    -

    bool isAsync:是否为异步执行;

    -

    int algorithmType:引擎框架根据插件加载顺序分配的算法类型ID;

    -

    long long algorithmVersion:算法版本号;

    -

    bool isCloud:是否上云(当前还未启用);

    -

    int operateId:执行ID(当前还未启用);

    -

    int requestId:请求ID,标识每次request,以对应执行结果;

    -

    int extendLen:拓展信息(extendMsg)长度;

    -

    unsigned char *extendMsg:拓展信息主体;

    -

    DataInfo

    -

    算法数据入参(inputInfo)、接口调用结果出参(outputInfo)。

    -

    unsigned char *data:数据主体;

    -

    int length:数据(data)长度;

    -
    - -具体开发过程可参考唤醒词识别SDK开发示例。 - diff --git "a/zh-cn/device-dev/subsystems/Sensor\346\234\215\345\212\241.md" "b/zh-cn/device-dev/subsystems/Sensor\346\234\215\345\212\241.md" deleted file mode 100755 index 35dd6eab91..0000000000 --- "a/zh-cn/device-dev/subsystems/Sensor\346\234\215\345\212\241.md" +++ /dev/null @@ -1,9 +0,0 @@ -# Sensor服务 - -- **[Sensor服务子系概述](Sensor服务子系概述.md)** - -- **[Sensor服务子系使用指导](Sensor服务子系使用指导.md)** - -- **[Sensor服务子系使用实例](Sensor服务子系使用实例.md)** - - diff --git "a/zh-cn/device-dev/subsystems/Sensor\346\234\215\345\212\241\345\255\220\347\263\273\344\275\277\347\224\250\346\214\207\345\257\274.md" "b/zh-cn/device-dev/subsystems/Sensor\346\234\215\345\212\241\345\255\220\347\263\273\344\275\277\347\224\250\346\214\207\345\257\274.md" deleted file mode 100755 index 99c7933449..0000000000 --- "a/zh-cn/device-dev/subsystems/Sensor\346\234\215\345\212\241\345\255\220\347\263\273\344\275\277\347\224\250\346\214\207\345\257\274.md" +++ /dev/null @@ -1,72 +0,0 @@ -# Sensor服务子系使用指导 - -- [使用步骤](#section18816105182315) - -下面使用步骤以sensorTypeId为0的传感器为例,其他类型的传感器使用方式类似。 - -## 使用步骤 - -1. 导入需要的包 - -``` -#include "sensor_agent.h" -#include "sensor_agent_type.h" -``` - -1. 创建传感器回调函数 - -``` -void SensorDataCallbackImpl(SensorEvent *event) -{ - if(event == NULL){ - return; - } - float *sensorData=(float *)event->data; -} -``` - ->![](public_sys-resources/icon-note.gif) **说明:** ->回调函数的格式为RecordSensorCallback类型。 - -1. 获取设备支持sensor列表 - -``` -SensorInfo *sensorInfo = (SensorInfo *)NULL; -int32_t count = 0; -int32_t ret = GetAllSensors(&sensorInfo, &count); -``` - -1. 创建的传感器用户 - -``` -SensorUser sensorUser; -sensorUser.callback = SensorDataCallbackImpl; //成员变量callback指向创建的回调方法 -``` - -1. 使能传感器 - -``` -int32_t ret = ActivateSensor(0, &sensorUser); -``` - -1. 订阅传感器数据 - -``` -int32_t ret = SubscribeSensor(0, &sensorUser); -``` - ->![](public_sys-resources/icon-note.gif) **说明:** ->到这步就可以在实现的回调方法中获取到传感器数据。 - -1. 取消传感器数据订阅 - -``` -int32_t ret = UnsubscribeSensor(0, &sensorUser); -``` - -1. 去使能一个传感器 - -``` -int32_t ret = DeactivateSensor(0, &sensorUser); -``` - diff --git "a/zh-cn/device-dev/subsystems/Sensor\346\234\215\345\212\241\345\255\220\347\263\273\346\246\202\350\277\260.md" "b/zh-cn/device-dev/subsystems/Sensor\346\234\215\345\212\241\345\255\220\347\263\273\346\246\202\350\277\260.md" deleted file mode 100755 index fa1d50d515..0000000000 --- "a/zh-cn/device-dev/subsystems/Sensor\346\234\215\345\212\241\345\255\220\347\263\273\346\246\202\350\277\260.md" +++ /dev/null @@ -1,99 +0,0 @@ -# Sensor服务子系概述 - -- [简介](#section667413271505) -- [接口说明](#section7255104114110) - -## 简介 - -Sensor服务子系统提供了轻量级传感器服务基础框架,您可以使用该框架接口实现传感器列表查询、传感器控制、传感器订阅去订阅等功能。轻量级传感器服务框架如下图所示: - -**图1** Sensor服务框架图 - -![](figures/zh-cn_image_0000001077724150.png) - -- Sensor API:提供传感器的基础API,主要包含查询传感器的列表、订阅/取消传感器数据、执行控制命令等,简化应用开发。 -- Sensor Framework:主要实现传感器的订阅管理、数据通道的创建、销毁等,实现与传感器服务层的通信。 -- Sensor Service:主要实现HDF层数据接收、解析、分发,对设备传感器的管理,数据上报管理以及传感器权限管控等。 - -## 接口说明 - -**表 1** Sensor服务框架API接口功能介绍 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    接口名

    -

    接口说明

    -

    参数要求

    -

    int32_t GetAllSensors(SensorInfo **sensorInfo, int32_t *count)

    -

    作用:获取系统中所有传感器的信息。

    -

    返回值:0表示成功,其他返回值表示失败。

    -

    sensorInfo(NOT NULL):输出系统中所有传感器的信息;

    -

    count(NOT NULL):输出系统中所有传感器的数量。

    -

    int32_t SubscribeSensor(int32_t sensorTypeId, SensorUser *user)

    -

    作用:订阅传感器数据,系统会将获取到的传感器数据上报给订阅者。

    -

    返回值: 0为成功,其他返回值表示失败。

    -

    sensorTypeId:唯一标识一个传感器类型;

    -

    user(NOT NULL):传感器的用户,用于从传感器获取数据,一般一个用户只属于一个传感器。

    -

    int32_t UnsubscribeSensor(int32_t sensorTypeId, SensorUser *user)

    -

    作用:去订阅传感器数据,系统将取消传感器数据上报给订阅者。

    -

    返回值:0为成功,其他返回值表示失败。

    -

    sensorTypeId:唯一标识一个传感器类型;

    -

    user(NOT NULL):传感器的用户,用于从传感器获取数据,一般一个用户只属于一个传感器。

    -

    int32_t SetBatch(int32_t sensorTypeId, SensorUser *user, int64_t samplingInterval, int64_t reportInterval)

    -

    作用:设置传感器的数据采样间隔和数据上报间隔

    -

    返回值:0为成功,其他返回值表示失败。

    -

    sensorTypeId:唯一标识一个传感器类型;

    -

    user(NOT NULL):传感器的用户,用于从传感器获取数据,一般一个用户只属于一个传感器;

    -

    samplingInterval:传感器数据采样间隔,单位纳秒;

    -

    reportInterval:传感器数据上报间隔,单位纳秒。

    -

    int32_t ActivateSensor(int32_t sensorTypeId, SensorUser *user)

    -

    作用:使能一个传感器订阅用户。

    -

    返回值:0为成功,其他返回值表示失败。

    -

    sensorTypeId:唯一标识一个传感器类型;

    -

    user(NOT NULL):传感器的用户,用于从传感器获取数据,一般一个用户只属于一个传感器。

    -

    int32_t DeactivateSensor(int32_t sensorTypeId, SensorUser *user)

    -

    作用:去使能一个传感器订阅用户

    -

    返回值:0为成功,其他返回值表示失败。

    -

    sensorTypeId:唯一标识一个传感器类型;

    -

    user(NOT NULL):传感器的用户,用于从传感器获取数据,一般一个用户只属于一个传感器。

    -

    int32_t SetMode(int32_t sensorTypeId, SensorUser *user, int32_t mode)

    -

    作用:设置传感器的工作模式

    -

    返回值:0为成功,其他返回值表示失败。

    -

    sensorTypeId:唯一标识一个传感器类型;

    -

    user(NOT NULL):传感器的用户,用于从传感器获取数据,一般一个用户只属于一个传感器;

    -

    mode:传感器的数据上报模式。

    -
    - diff --git "a/zh-cn/device-dev/subsystems/XTS\350\256\244\350\257\201\345\255\220\347\263\273\347\273\237\345\274\200\345\217\221\346\214\207\345\215\227.md" "b/zh-cn/device-dev/subsystems/XTS\350\256\244\350\257\201\345\255\220\347\263\273\347\273\237\345\274\200\345\217\221\346\214\207\345\215\227.md" deleted file mode 100755 index b5e511362a..0000000000 --- "a/zh-cn/device-dev/subsystems/XTS\350\256\244\350\257\201\345\255\220\347\263\273\347\273\237\345\274\200\345\217\221\346\214\207\345\215\227.md" +++ /dev/null @@ -1,648 +0,0 @@ -# XTS认证子系统开发指南 - -- [简介](#section465982318513) -- [系统类型](#section125090457443) -- [目录](#section161941989596) -- [约束](#section119744591305) -- [使用说明](#section137768191623) -- [用例开发指导](#section3695134065513) - - [C语言用例开发编译指导(适用于轻量系统产品用例开发)](#section198193336544) - - [C语言用例执行指导(适用于轻量系统产品用例开发)](#section13820233175418) - - [C++语言用例开发编译指导(适用于小型系统、标准系统用例开发)](#section3822123311540) - - [C++语言用例执行指导(适用于小型系统、标准系统用例开发)](#section128222336544) - - [JS语言用例开发指导(适用于标准系统)](#section159801435165220) - - [JS语言用例编译打包指导(适用于标准系统)](#section445519106559) - - -## 简介 - -XTS子系统是OpenHarmony生态认证测试套件的集合,当前包括acts(application compatibility test suite)应用兼容性测试套件,后续会拓展dcts(device compatibility test suite)设备兼容性测试套件等。 - -XTS子系统当前包括acts与tools软件包: - -- acts,存放acts相关测试用例源码与配置文件,其目的是帮助终端设备厂商尽早发现软件与OpenHarmony的不兼容性,确保软件在整个开发过程中满足OpenHarmony的兼容性要求。 -- tools,存放acts相关测试用例开发框架。 - -## 系统类型 - -OpenHarmony支持如下几种系统类型: - -- 轻量系统(mini system) - - 面向MCU类处理器例如Arm Cortex-M、RISC-V 32位的设备,硬件资源极其有限,支持的设备最小内存为128KiB,可以提供多种轻量级网络协议,轻量级的图形框架,以及丰富的IOT总线读写部件等。可支撑的产品如智能家居领域的连接类模组、传感器设备、穿戴类设备等。 - -- 小型系统(small system) - - 面向应用处理器例如Arm Cortex-A的设备,支持的设备最小内存为1MiB,可以提供更高的安全能力、标准的图形框架、视频编解码的多媒体能力。可支撑的产品如智能家居领域的IP Camera、电子猫眼、路由器以及智慧出行域的行车记录仪等。 - -- 标准系统(standard system) - - 面向应用处理器例如Arm Cortex-A的设备,支持的设备最小内存为128MiB,可以提供增强的交互能力、3D GPU以及硬件合成能力、更多控件以及动效更丰富的图形能力、完整的应用框架。可支撑的产品如高端的冰箱显示屏。 - - -## 目录 - -``` -/test/xts -├── acts # 测试代码存放目录 -│ └── subsystem # 标准系统子系统测试用例源码存放目录 -│ └── subsystem_lite # 轻量系统、小型系统子系统测试用例源码存放目录 -│ └── BUILD.gn # 标准系统测试用例编译配置 -│ └── build_lite # 轻量系统、小型系统测试用例编译配置存放目录 -│ └── BUILD.gn # 轻量系统、小型系统测试用例编译配置 -└── tools # 测试工具代码存放目录 -``` - -## 约束 - -轻量系统用例开发语言是C,小型系统用例开发语言是C++。 - -## 使用说明 - -**表 1** 用例级别说明 - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    级别名称

    -

    基本定义

    -

    测试范围

    -

    Level0

    -

    冒烟

    -

    验证关键功能点基本功能/最基本DFX属性在最常见输入下的表现,通过表示功能基本可运行。

    -

    Level1

    -

    基本

    -

    验证各功能点基本功能/基本DFX属性在常见输入下的表现,通过表示功能基本可测试。

    -

    Level2

    -

    重要

    -

    验证各功能点的基本功能/基本DFX属性在常规输入/常见异常情况下的表现,通过表示功能基本正常可用,可开展Beta。

    -

    Level3

    -

    一般

    -

    验证各功能点的全部功能/全部DFX属性在各种常规/非常规输入组合下,或各种正常/异常预置条件组合下的表现。

    -

    Level4

    -

    生僻

    -

    验证关键功能点在极端异常预置条件下、用户难以触及的异常输入组合下的表现。

    -
    - -**表 2** 用例粒度说明 - - - - - - - - - - - - - - - - - - - - -

    用例规模

    -

    被测试对象

    -

    测试环境

    -

    LargeTest

    -

    业务功能/全场景特性/整机及场景级DFX

    -

    尽量使用贴近真实的环境设备

    -

    MediumTest

    -

    模块/子系统集成至设备后的功能/DFX

    -

    使用真实的单设备进行验证,可进行消息模拟,尽量不对函数进行MOCK

    -

    SmallTest

    -

    模块/类/函数

    -

    在开发者个人环境进行测试,尽量不依赖其他模块,存在大量的MOCK

    -
    - -**表 3** 测试类型说明 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    测试类型名称

    -

    测试类型定义

    -

    Function

    -

    验证被测对象提供给用户的业务功能实现正确性的测试项,这里的“用户”可以是终端用户或开发者,功能包括业务功能及平台功能

    -

    Performance

    -

    验证被测对象在特定预置条件/负载模型下的处理能力的测试项,“处理能力”一般以单位时间内可处理的业务量来衡量,如呼叫/秒,帧率/秒,事件处理量/秒等

    -

    Power

    -

    验证被测对象在特定预置条件/负载模型下在一定时间内能源消耗量的测试项

    -

    Reliability

    -

    验证被测对象在正常/异常输入情况下,或业务量压力和长时间连续运行压力情况下业务表现的测试项,含稳定性、压力、故障注入、Monkey测试项

    -

    Security

    -

    验证系统对恶意威胁的防护能力,威胁包括但不限于未授权访问、使用、泄露、破坏、修改、毁灭,以保障信息的机密性、完整性和可用性; 验证系统对用户隐私的保护能力,保障用户的隐私数据被收集、使用、保有、披露和处置符合法律规范,保障用户的隐私权; 验证对各类安全规范的遵从情况,如安全设计规范、安全红线、工信部安全认证规范等,保障安全相关法律法规的合规。

    -

    Global

    -

    验证被测对象在是否具有国际化数据支持和本地化能力的测试项,包括语言显示、输入/输出习惯、时间显示、区域特性如货币时间禁忌等等

    -

    Compatibility

    -

    当被测对象为应用时,包括被测对象对于自身数据的后向兼容性、对于系统的前后向兼容性、对于不同用户数据(如播放器之音频文件格式/智能短信之用户短信内容)的兼容性测试项; 当被测对象为系统时,包括被测系统对于系统自身数据的后向兼容性、以及对于生态中常用应用的兼容性测试项;当被测对象为软件时,包括被测系统对于相关的硬件的兼容性;

    -

    User

    -

    验证被测对象在真实用户场景下的用户体验感受的测试项,注意此种情况下没有客观的“正确”与“失败”,所有的结论及评价都应该来自于用户

    -

    Standard

    -

    验证被测对象对于行业及公司内标准/协议/规范的遵从情况的测试项,注意此处的“标准”不包含任何安全标准,针对安全标准的测试项划归为“安全测试”类型

    -

    Safety

    -

    验证被测对象的Safety属性,避免产品可能对人身安全、健康以及产品本身带来的危害。

    -

    Resilience

    -

    验证被测对象的韧性属性,确保系统受攻击时承受并保持在有定义的运行状态(包括降级)、恢复并适应攻击以保障Mission达成。

    -
    - -## 用例开发指导 - -根据测试系统选择测试框架和对应测试用例语言。 - -**表 4** 系统和测试框架、开发语言对应关系 - - - - - - - - - - - - - - - - - - - - -

    系统

    -

    测试框架

    -

    语言

    -

    轻量系统

    -

    hctest

    -

    c

    -

    小型系统

    -

    hcpptest

    -

    c++

    -

    标准系统

    -

    HJSUnit、hcpptest

    -

    js、c++

    -
    - -### C语言用例开发编译指导(适用于轻量系统产品用例开发) - -**示例:轻量系统测试用例开发** - -当前使用的测试框架是hctest,hctest测试框架支持使用C语言编写测试用例,是在开源测试框架unity的基础上进行增强和适配。 - -1. 用例目录规范:测试用例存储到test/xts/acts仓中 - - ``` - ├── acts - │ └──subsystem_lite - │ │ └── module_hal - │ │ │ └── BUILD.gn - │ │ │ └── src - │ └──build_lite - │ │ └── BUILD.gn - ``` - -2. src目录下用例编写样例。 - - 1.引用测试框架 - - ``` - #include "hctest.h" - ``` - - 2. 使用宏定义LITE\_TEST\_SUIT定义子系统、模块、测试套件名称 - - ``` - /** - * @brief register a test suit named "IntTestSuite" - * @param test subsystem name - * @param example module name - * @param IntTestSuite test suit name - */ - LITE_TEST_SUIT(test, example, IntTestSuite); - ``` - - 3. 定义Setup与TearDown - - 命名方式:测试套件名称+Setup,测试套件名称+TearDown。 - - Setup与TearDown必须存在,可以为空函数。 - - 4. 使用宏定义LITE\_TEST\_CASE写测试用例 - - 包括三个参数:测试套件名称,测试用例名称,用例属性(测试类型、用例粒度、用例级别)。 - - ``` - LITE_TEST_CASE(IntTestSuite, TestCase001, Function | MediumTest | Level1) - { - //do something - }; - ``` - - 5. 使用宏定义 RUN\_TEST\_SUITE注册测试套件 - - ``` - RUN_TEST_SUITE(IntTestSuite); - ``` - -3. 测试模块的配置文件(BUILD.gn)样例: - - 在每个测试模块目录下新建BUILD.gn编译文件,用于指定编译后静态库的名称、依赖的头文件、依赖的库等;具体写法如下: - - ``` - import("//test/xts/tools/lite/build/suite_lite.gni") - hctest_suite("ActsDemoTest") { - suite_name = "acts" - sources = [ - "src/test_demo.c", - ] - include_dirs = [ ] - cflags = [ "-Wno-error" ] - } - ``` - -4. acts下BUILD.gn增加编译选项。 - - 需要将测试模块加入到acts目录下的编译脚本中,编译脚本路径:test/xts/acts/build\_lite/BUILD.gn。 - - ``` - lite_component("acts") { - ... - if(board_name == "liteos_m") { - features += [ - ... - "//xts/acts/subsystem_lite/module_hal:ActsDemoTest" - ] - } - } - ``` - -5. 测试套件编译命令。 - - 随版本编译,debug版本编译时会同步编译acts测试套件 - - >![](public_sys-resources/icon-note.gif) **说明:** - >acts测试套件编译中间件为静态库,最终链接到版本镜像中 。 - - -### C语言用例执行指导(适用于轻量系统产品用例开发) - -**示例:轻量系统测试用例执行** - -将版本镜像烧录进开发板。 - -**测试步骤** - -1. 使用串口工具登录开发板,并保存串口打印信息。 -2. 重启设备,查看串口日志。 - -**测试结果分析指导** - -基于串口打印日志进行分析; - -每个测试套件执行以Start to run test suite开始,以xx Tests xx Failures xx Ignored结束。 - -### C++语言用例开发编译指导(适用于小型系统、标准系统用例开发) - -**示例:小型系统测试用例开发**(标准参考具体样例目录:global/i18n\_standard) - -当前使用的测试框架是hcpptest,hcpptest测试框架是在开源的googletest测试框架的基础上进行的增强和适配。 - -1. 规范用例目录:测试用例存储到test/xts/acts仓中。 - - ``` - ├── acts - │ └──subsystem_lite - │ │ └── module_posix - │ │ │ └── BUILD.gn - │ │ │ └── src - │ └──build_lite - │ │ └── BUILD.gn - ``` - -2. 测试模块src下用例编写样例: - - 1. 引用测试框架: - - 需要引用gtest.h 如:\#include "gtest/gtest.h" - - ``` - #include "gtest/gtest.h" - ``` - - 2. 定义Setup与TearDown - - ``` - using namespace std; - using namespace testing::ext; - class TestSuite: public testing::Test { - protected: - // Preset action of the test suite, which is executed before the first test case - static void SetUpTestCase(void){ - } - // Test suite cleanup action, which is executed after the last test case - static void TearDownTestCase(void){ - } - // Preset action of the test case - virtual void SetUp() - { - } - // Cleanup action of the test case - virtual void TearDown() - { - } - }; - ``` - - 3. 使用宏定义HWTEST或HWTEST\_F写测试用例 - - 普通测试用例的定义:HWTEST(测试套名称, 测试用例名称, 用例标注)。 - - 包含SetUp和TearDown的测试用例的定义 :HWTEST\_F(测试套名称, 测试用例名称,用例标注)。 - - 宏定义包括三个参数:测试套件名称,测试用例名称,用例属性(测试类型、用例粒度、用例级别)。 - - ``` - HWTEST_F(TestSuite, TestCase_0001, Function | MediumTest | Level1) { - // do something - } - ``` - -3. 测试模块下用例配置文件(BUILD.gn)样例: - - 每个测试模块目录下新建BUILD.gn编译文件,用于指定编译后可执行文件的名称、依赖的头文件、依赖的库等;具体写法如下。每个测试模块将独立编译成.bin可执行文件, 该文件可直接push到单板上进行测试。 - - 举例: - - ``` - import("//test/xts/tools/lite/build/suite_lite.gni") - hcpptest_suite("ActsDemoTest") { - suite_name = "acts" - sources = [ - "src/TestDemo.cpp" - ] - - include_dirs = [ - "src", - ... - ] - deps = [ - ... - ] - cflags = [ "-Wno-error" ] - } - - ``` - -4. acts目录下增加编译选项(BUILD.gn)样例: - - 将测试模块加入到acts目录下的编译脚本中,编译脚本为:test/xts/acts/build\_lite/BUILD.gn。 - - ``` - lite_component("acts") { - ... - else if(board_name == "liteos_a") { - features += [ - ... - "//xts/acts/subsystem_lite/module_posix:ActsDemoTest" - ] - } - } - ``` - -5. 测试套件编译命令。 - - 随版本编译,debug版本编译时会同步编译acts测试套件 - - >![](public_sys-resources/icon-note.gif) **说明:** - >小型系统acts独立编译成可执行文件(bin格式), 在编译产物的suites\\acts目录下归档。 - - -### C++语言用例执行指导(适用于小型系统、标准系统用例开发) - -**示例:小型系统测试用例执行** - -目前的用例执行采用nfs共享的方式,mount到单板去执行。 - -**环境搭建** - -1. 使用有限网线或无线将开发板与PC进行连接。 -2. 开发板配置IP、子网掩码、网关,确保开发板与PC处于同一个网段。 -3. PC安装nfs服务器并完成注册,启动nfs服务。 -4. 开发板配置mount命令,确保开发板可以访问PC端的nfs共享文件。 - - 格式:mount \[nfs服务器IP\]:\[/nfs共享目录\] \[/开发板目录\] nfs - - 举例: - - ``` - mount 192.168.1.10:/nfs /nfs nfs - ``` - - -**用例执行** - -测试套件执行 ActsDemoTest.bin 触发用例执行,基于串口打印日志进行分析。 - -### JS语言用例开发指导(适用于标准系统) - -当前使用的测试框架是HJSUnit,用于支撑OpenHarmony application测试(特指基于JS应用框架使用 Javascript 语言开发的 APP)进行自动化测试。 - -**用例编写基础语法** - -测试用例为 js 语言,必须满足 JavaScript 语言编程规范: - -**表 5** - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    用例语法

    -

    描述

    -

    要求

    -

    beforeAll

    -

    测试套级别的预置条件,在所有测试用例开始前执行且仅执行一次,支持一个参数:预置动作函数

    -

    可选

    -

    afterAll

    -

    测试套级别的清理条件,在所有测试用例结束后执行且仅执行一次,支持一个参数:清理动作函数

    -

    可选

    -

    beforeEach

    -

    测试用例级别的预置条件,在每条测试用例开始前执行,执行次数与 it 定义的测试用例数一致,支持一个参数:预置动作函数

    -

    可选

    -

    afterEach

    -

    测试用例级别的清理条件,在每条测试用例结束后执行,执行次数与 it 定义的测试用例数一致,支持一个参数:清理动作函数

    -

    可选

    -

    describe

    -

    定义一个测试套,支持两个参数:测试套名称和测试套函数; describe 支持嵌套,每个 describe 内均可以定义 beforeAll 、beforeEach 、afterEach 和 afterAll

    -

    必选

    -

    it

    -

    定义一条测试用例,支持三个参数:用例名称,过滤参数和用例函数

    -

    备注:

    -

    过滤参数:过滤参数为一个 32 位的 Int 类型参数,0 位 置1表示不筛选、默认执行;0-10 位 置1表示测试用例类型;16-18 位 置1表示测试用例规模;24-28 位 置1表示测试层级

    -

    测试用例类型。置位0-10分别表示:FUNCTION 方法类测试、PERFORMANCE 性能类测试、POWER 功耗类测试、RELIABILITY 可靠性测试、SECURITY 安全合规测试、GLOBAL 整体性测试、COMPATIBILITY 兼容性测试、USER 用户测试、STANDARD 标准测试、SAFETY 安全特性测试,RESILIENCE 压力测试。

    -

    测试用例规模。置位16-18分别表示:SMALL 小型测试、MEDIUM 中型测试、LARGE 大型测试。

    -

    测试层级。置位24-28分别表示:LEVEL0-0 级测试、LEVEL1-1 级测试、LEVEL2-2 级测试、LEVEL3-3 级测试、LEVEL4-4 级测试。

    -

    必选

    -
    - -用例编写语法采用 jasmine 的标准语法,格式支持ES6格式。 - -1. 规范用例目录:测试用例存储到entry/src/main/js/test目录。 - - ``` - ├── BUILD.gn - │ └──entry - │ │ └──src - │ │ │ └──main - │ │ │ │ └──js - │ │ │ │ │ └──default - │ │ │ │ │ │ └──pages - │ │ │ │ │ │ │ └──index - │ │ │ │ │ │ │ │ └──index.js # 入口文件 - │ │ │ │ │ └──test # 测试代码存放目录 - │ │ │ └── resources # hap资源存放目录 - │ │ │ └── config.json # hap配置文件 - ``` - -2. index.js示例 - - ``` - // 拉起js测试框架,加载测试用例 - import {Core, ExpectExtend} from 'deccjsunit/index' - - export default { - data: { - title: "" - }, - onInit() { - this.title = this.$t('strings.world'); - }, - onShow() { - console.info('onShow finish') - const core = Core.getInstance() - const expectExtend = new ExpectExtend({ - 'id': 'extend' - }) - core.addService('expect', expectExtend) - core.init() - const configService = core.getDefaultService('config') - configService.setConfig(this) - require('../../../test/List.test') - core.execute() - }, - onReady() { - }, - } - ``` - -3. 单元测试用例示例 - - ``` - // Example1: 使用HJSUnit进行单元测试 - describe('appInfoTest', function () { - it('app_info_test_001', 0, function () { - var info = app.getInfo() - expect(info.versionName).assertEqual('1.0') - expect(info.versionCode).assertEqual('3') - }) - }) - ``` - - -### JS语言用例编译打包指导(适用于标准系统) - -hap包编译请参考[标准系统js应用开发指导](https://developer.harmonyos.com/cn/docs/documentation/doc-guides/build_overview-0000001055075201)。 - diff --git "a/zh-cn/device-dev/subsystems/bytrace\344\275\277\347\224\250\346\214\207\345\257\274.md" "b/zh-cn/device-dev/subsystems/bytrace\344\275\277\347\224\250\346\214\207\345\257\274.md" deleted file mode 100644 index 3933aebf5e..0000000000 --- "a/zh-cn/device-dev/subsystems/bytrace\344\275\277\347\224\250\346\214\207\345\257\274.md" +++ /dev/null @@ -1,119 +0,0 @@ -# bytrace使用指导 - -- [简介](#section11388623181619) -- [命令行开发指导](#section1595564317164) - - [bytrace命令](#section2344125731617) - - [bytrace命令使用举例](#section5402591174) - - -## 简介 - -bytrace是开发人员用于追踪进程轨迹、分析性能的一种工具,主要对内核ftrace进行了封装和扩展,来支持用户态的打点。通过该工具可以打开想要查看的用户态和内核label(通过下面命令行bytrace -l,查看支持的所有label),然后通过命令行进行抓取trace信息到指定文件中。 - -## 命令行开发指导 - -### bytrace命令 - -bytrace当前支持以下命令: - -**表 1** 命令行列表 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    Option

    -

    Description

    -

    -h,--help

    -

    查看option帮助

    -

    -b n,--buffer_size n

    -

    指定n(KB)内存大小用于存取trace日志,默认2048KB

    -

    -t n,--time n

    -

    用来指定trace运行的时间(单位:s),取决于需要分析过程的时间

    -

    --trace_clock clock

    -

    trace输出的时钟类型,一般设备支持boot、global、mono、uptime、perf等,默认为boot

    -

    --trace_begin

    -

    启动抓trace

    -

    --trace_dump

    -

    将数据输出到指定位置(默认控制台)

    -

    --trace_finish

    -

    停止抓trace,并将数据输出到指定位置(默认控制台)

    -

    -l,--list_categories

    -

    输出手机能支持的trace模块

    -

    --overwrite

    -

    当缓冲区满的时候,将丢弃最新的信息。(默认丢弃最老的日志)

    -

    -o filename,--output filename

    -

    指定输出的目标文件名称

    -

    -z

    -

    抓取trace后进行压缩

    -
    - -### bytrace命令使用举例 - -以下是常用bytrace命令示例,供开发者参考: - -- 查询支持的label。 - -``` -bytrace -l -``` - -或者 - -``` -bytrace --list_categories -``` - -- 设置4M缓存,抓取10秒,抓取label为ability的trace信息。 - -``` -bytrace -b 4096 -t 10 --overwrite ability > /data/mytrace.ftrace -``` - -- 设置trace的输出时钟为mono。 - -``` -bytrace --trace_clock mono -b 4096 -t 10 --overwrite ability > /data/mytrace.ftrace -``` - -- 抓取trace后进行压缩。 - -``` -bytrace -z -b 4096 -t 10 --overwrite ability > /data/mytrace.ftrace -``` - diff --git a/zh-cn/device-dev/subsystems/figures/20200721-223604(eSpace).gif b/zh-cn/device-dev/subsystems/figure/20200721-223604(eSpace).gif old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/subsystems/figures/20200721-223604(eSpace).gif rename to zh-cn/device-dev/subsystems/figure/20200721-223604(eSpace).gif diff --git "a/zh-cn/device-dev/subsystems/figures/Ability\344\270\216AbilitySlice\347\232\204\345\205\263\347\263\273\345\233\276.png" "b/zh-cn/device-dev/subsystems/figure/Ability\344\270\216AbilitySlice\347\232\204\345\205\263\347\263\273\345\233\276.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/subsystems/figures/Ability\344\270\216AbilitySlice\347\232\204\345\205\263\347\263\273\345\233\276.png" rename to "zh-cn/device-dev/subsystems/figure/Ability\344\270\216AbilitySlice\347\232\204\345\205\263\347\263\273\345\233\276.png" diff --git "a/zh-cn/device-dev/subsystems/figures/Ability\345\255\220\347\263\273\347\273\237\346\241\206\346\236\266\345\233\276.png" "b/zh-cn/device-dev/subsystems/figure/Ability\345\255\220\347\263\273\347\273\237\346\241\206\346\236\266\345\233\276.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/subsystems/figures/Ability\345\255\220\347\263\273\347\273\237\346\241\206\346\236\266\345\233\276.png" rename to "zh-cn/device-dev/subsystems/figure/Ability\345\255\220\347\263\273\347\273\237\346\241\206\346\236\266\345\233\276.png" diff --git "a/zh-cn/device-dev/subsystems/figures/Ability\347\256\241\347\220\206\346\234\215\345\212\241\345\222\214\345\214\205\347\256\241\347\220\206\346\234\215\345\212\241\345\220\257\345\212\250.png" "b/zh-cn/device-dev/subsystems/figure/Ability\347\256\241\347\220\206\346\234\215\345\212\241\345\222\214\345\214\205\347\256\241\347\220\206\346\234\215\345\212\241\345\220\257\345\212\250.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/subsystems/figures/Ability\347\256\241\347\220\206\346\234\215\345\212\241\345\222\214\345\214\205\347\256\241\347\220\206\346\234\215\345\212\241\345\220\257\345\212\250.png" rename to "zh-cn/device-dev/subsystems/figure/Ability\347\256\241\347\220\206\346\234\215\345\212\241\345\222\214\345\214\205\347\256\241\347\220\206\346\234\215\345\212\241\345\220\257\345\212\250.png" diff --git "a/zh-cn/device-dev/subsystems/figures/LiteOS-A\345\271\263\345\217\260dump\347\263\273\347\273\237\345\261\236\346\200\247\350\276\223\345\207\272.png" "b/zh-cn/device-dev/subsystems/figure/LiteOS-A\345\271\263\345\217\260dump\347\263\273\347\273\237\345\261\236\346\200\247\350\276\223\345\207\272.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/subsystems/figures/LiteOS-A\345\271\263\345\217\260dump\347\263\273\347\273\237\345\261\236\346\200\247\350\276\223\345\207\272.png" rename to "zh-cn/device-dev/subsystems/figure/LiteOS-A\345\271\263\345\217\260dump\347\263\273\347\273\237\345\261\236\346\200\247\350\276\223\345\207\272.png" diff --git "a/zh-cn/device-dev/subsystems/figures/LiteOS-M\345\271\263\345\217\260dump\347\263\273\347\273\237\345\261\236\346\200\247\350\276\223\345\207\272.png" "b/zh-cn/device-dev/subsystems/figure/LiteOS-M\345\271\263\345\217\260dump\347\263\273\347\273\237\345\261\236\346\200\247\350\276\223\345\207\272.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/subsystems/figures/LiteOS-M\345\271\263\345\217\260dump\347\263\273\347\273\237\345\261\236\346\200\247\350\276\223\345\207\272.png" rename to "zh-cn/device-dev/subsystems/figure/LiteOS-M\345\271\263\345\217\260dump\347\263\273\347\273\237\345\261\236\346\200\247\350\276\223\345\207\272.png" diff --git "a/zh-cn/device-dev/subsystems/figures/UIButton\347\202\271\345\207\273\346\225\210\346\236\234.gif" "b/zh-cn/device-dev/subsystems/figure/UIButton\347\202\271\345\207\273\346\225\210\346\236\234.gif" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/subsystems/figures/UIButton\347\202\271\345\207\273\346\225\210\346\236\234.gif" rename to "zh-cn/device-dev/subsystems/figure/UIButton\347\202\271\345\207\273\346\225\210\346\236\234.gif" diff --git "a/zh-cn/device-dev/subsystems/figures/ViewGroup\346\267\273\345\212\240view\345\256\236\344\276\213\346\225\210\346\236\234\345\233\276.png" "b/zh-cn/device-dev/subsystems/figure/ViewGroup\346\267\273\345\212\240view\345\256\236\344\276\213\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/subsystems/figures/ViewGroup\346\267\273\345\212\240view\345\256\236\344\276\213\346\225\210\346\236\234\345\233\276.png" rename to "zh-cn/device-dev/subsystems/figure/ViewGroup\346\267\273\345\212\240view\345\256\236\344\276\213\346\225\210\346\236\234\345\233\276.png" diff --git a/zh-cn/device-dev/subsystems/figures/unnaming.png b/zh-cn/device-dev/subsystems/figure/unnaming.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/subsystems/figures/unnaming.png rename to zh-cn/device-dev/subsystems/figure/unnaming.png diff --git a/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001051782526.png b/zh-cn/device-dev/subsystems/figure/zh-cn_image_0000001051782526.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001051782526.png rename to zh-cn/device-dev/subsystems/figure/zh-cn_image_0000001051782526.png diff --git a/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001052582522.png b/zh-cn/device-dev/subsystems/figure/zh-cn_image_0000001052582522.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001052582522.png rename to zh-cn/device-dev/subsystems/figure/zh-cn_image_0000001052582522.png diff --git a/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001052662559.png b/zh-cn/device-dev/subsystems/figure/zh-cn_image_0000001052662559.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001052662559.png rename to zh-cn/device-dev/subsystems/figure/zh-cn_image_0000001052662559.png diff --git a/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001052782555.png b/zh-cn/device-dev/subsystems/figure/zh-cn_image_0000001052782555.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001052782555.png rename to zh-cn/device-dev/subsystems/figure/zh-cn_image_0000001052782555.png diff --git a/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001052942531.png b/zh-cn/device-dev/subsystems/figure/zh-cn_image_0000001052942531.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001052942531.png rename to zh-cn/device-dev/subsystems/figure/zh-cn_image_0000001052942531.png diff --git a/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001053207924.gif b/zh-cn/device-dev/subsystems/figure/zh-cn_image_0000001053207924.gif old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001053207924.gif rename to zh-cn/device-dev/subsystems/figure/zh-cn_image_0000001053207924.gif diff --git a/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001053247975.gif b/zh-cn/device-dev/subsystems/figure/zh-cn_image_0000001053247975.gif old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001053247975.gif rename to zh-cn/device-dev/subsystems/figure/zh-cn_image_0000001053247975.gif diff --git a/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001054101094.png b/zh-cn/device-dev/subsystems/figure/zh-cn_image_0000001054101094.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001054101094.png rename to zh-cn/device-dev/subsystems/figure/zh-cn_image_0000001054101094.png diff --git a/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001054421113.png b/zh-cn/device-dev/subsystems/figure/zh-cn_image_0000001054421113.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001054421113.png rename to zh-cn/device-dev/subsystems/figure/zh-cn_image_0000001054421113.png diff --git a/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001059334449.png b/zh-cn/device-dev/subsystems/figure/zh-cn_image_0000001059334449.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001059334449.png rename to zh-cn/device-dev/subsystems/figure/zh-cn_image_0000001059334449.png diff --git a/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001060200050.png b/zh-cn/device-dev/subsystems/figure/zh-cn_image_0000001060200050.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001060200050.png rename to zh-cn/device-dev/subsystems/figure/zh-cn_image_0000001060200050.png diff --git a/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001061889268.png b/zh-cn/device-dev/subsystems/figure/zh-cn_image_0000001061889268.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001061889268.png rename to zh-cn/device-dev/subsystems/figure/zh-cn_image_0000001061889268.png diff --git a/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001062334618.png b/zh-cn/device-dev/subsystems/figure/zh-cn_image_0000001062334618.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001062334618.png rename to zh-cn/device-dev/subsystems/figure/zh-cn_image_0000001062334618.png diff --git a/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001062476933.png b/zh-cn/device-dev/subsystems/figure/zh-cn_image_0000001062476933.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001062476933.png rename to zh-cn/device-dev/subsystems/figure/zh-cn_image_0000001062476933.png diff --git a/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001062942690.png b/zh-cn/device-dev/subsystems/figure/zh-cn_image_0000001062942690.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001062942690.png rename to zh-cn/device-dev/subsystems/figure/zh-cn_image_0000001062942690.png diff --git a/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001063839940.png b/zh-cn/device-dev/subsystems/figure/zh-cn_image_0000001063839940.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001063839940.png rename to zh-cn/device-dev/subsystems/figure/zh-cn_image_0000001063839940.png diff --git a/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001077724150.png b/zh-cn/device-dev/subsystems/figure/zh-cn_image_0000001077724150.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001077724150.png rename to zh-cn/device-dev/subsystems/figure/zh-cn_image_0000001077724150.png diff --git a/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001077727032.png b/zh-cn/device-dev/subsystems/figure/zh-cn_image_0000001077727032.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001077727032.png rename to zh-cn/device-dev/subsystems/figure/zh-cn_image_0000001077727032.png diff --git a/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001119924146.gif b/zh-cn/device-dev/subsystems/figure/zh-cn_image_0000001119924146.gif similarity index 100% rename from zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001119924146.gif rename to zh-cn/device-dev/subsystems/figure/zh-cn_image_0000001119924146.gif diff --git a/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001166643927.jpg b/zh-cn/device-dev/subsystems/figure/zh-cn_image_0000001166643927.jpg similarity index 100% rename from zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001166643927.jpg rename to zh-cn/device-dev/subsystems/figure/zh-cn_image_0000001166643927.jpg diff --git "a/zh-cn/device-dev/subsystems/figures/\345\212\250\347\224\273\345\256\236\347\216\260\346\225\210\346\236\234\345\233\276.gif" "b/zh-cn/device-dev/subsystems/figure/\345\212\250\347\224\273\345\256\236\347\216\260\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/subsystems/figures/\345\212\250\347\224\273\345\256\236\347\216\260\346\225\210\346\236\234\345\233\276.gif" rename to "zh-cn/device-dev/subsystems/figure/\345\212\250\347\224\273\345\256\236\347\216\260\346\225\210\346\236\234\345\233\276.gif" diff --git "a/zh-cn/device-dev/subsystems/figures/\345\214\205\347\256\241\347\220\206\345\255\220\347\263\273\347\273\237\346\241\206\346\236\266\345\233\276.png" "b/zh-cn/device-dev/subsystems/figure/\345\214\205\347\256\241\347\220\206\345\255\220\347\263\273\347\273\237\346\241\206\346\236\266\345\233\276.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/subsystems/figures/\345\214\205\347\256\241\347\220\206\345\255\220\347\263\273\347\273\237\346\241\206\346\236\266\345\233\276.png" rename to "zh-cn/device-dev/subsystems/figure/\345\214\205\347\256\241\347\220\206\345\255\220\347\263\273\347\273\237\346\241\206\346\236\266\345\233\276.png" diff --git "a/zh-cn/device-dev/subsystems/figures/\345\233\276\347\211\2071.png" "b/zh-cn/device-dev/subsystems/figure/\345\233\276\347\211\2071.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/subsystems/figures/\345\233\276\347\211\2071.png" rename to "zh-cn/device-dev/subsystems/figure/\345\233\276\347\211\2071.png" diff --git "a/zh-cn/device-dev/subsystems/figures/\345\256\211\345\205\250\345\255\220\347\263\273\347\273\237.png" "b/zh-cn/device-dev/subsystems/figure/\345\256\211\345\205\250\345\255\220\347\263\273\347\273\237.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/subsystems/figures/\345\256\211\345\205\250\345\255\220\347\263\273\347\273\237.png" rename to "zh-cn/device-dev/subsystems/figure/\345\256\211\345\205\250\345\255\220\347\263\273\347\273\237.png" diff --git "a/zh-cn/device-dev/subsystems/figures/\345\271\263\351\223\272\346\250\241\345\274\217\345\233\276\347\211\207\346\225\210\346\236\234\345\233\276.png" "b/zh-cn/device-dev/subsystems/figure/\345\271\263\351\223\272\346\250\241\345\274\217\345\233\276\347\211\207\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/subsystems/figures/\345\271\263\351\223\272\346\250\241\345\274\217\345\233\276\347\211\207\346\225\210\346\236\234\345\233\276.png" rename to "zh-cn/device-dev/subsystems/figure/\345\271\263\351\223\272\346\250\241\345\274\217\345\233\276\347\211\207\346\225\210\346\236\234\345\233\276.png" diff --git "a/zh-cn/device-dev/subsystems/figures/\345\272\224\347\224\250\345\220\257\345\212\250\346\265\201\347\250\213.png" "b/zh-cn/device-dev/subsystems/figure/\345\272\224\347\224\250\345\220\257\345\212\250\346\265\201\347\250\213.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/subsystems/figures/\345\272\224\347\224\250\345\220\257\345\212\250\346\265\201\347\250\213.png" rename to "zh-cn/device-dev/subsystems/figure/\345\272\224\347\224\250\345\220\257\345\212\250\346\265\201\347\250\213.png" diff --git "a/zh-cn/device-dev/subsystems/figures/\346\217\222\344\273\266\344\276\235\350\265\226-(2).jpg" "b/zh-cn/device-dev/subsystems/figure/\346\217\222\344\273\266\344\276\235\350\265\226-(2).jpg" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/subsystems/figures/\346\217\222\344\273\266\344\276\235\350\265\226-(2).jpg" rename to "zh-cn/device-dev/subsystems/figure/\346\217\222\344\273\266\344\276\235\350\265\226-(2).jpg" diff --git "a/zh-cn/device-dev/subsystems/figures/\346\231\256\351\200\232\345\256\271\345\231\250\347\261\273\347\273\204\344\273\266\347\273\223\346\236\204.png" "b/zh-cn/device-dev/subsystems/figure/\346\231\256\351\200\232\345\256\271\345\231\250\347\261\273\347\273\204\344\273\266\347\273\223\346\236\204.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/subsystems/figures/\346\231\256\351\200\232\345\256\271\345\231\250\347\261\273\347\273\204\344\273\266\347\273\223\346\236\204.png" rename to "zh-cn/device-dev/subsystems/figure/\346\231\256\351\200\232\345\256\271\345\231\250\347\261\273\347\273\204\344\273\266\347\273\223\346\236\204.png" diff --git "a/zh-cn/device-dev/subsystems/figures/\346\231\256\351\200\232\347\273\204\344\273\266\346\240\221\347\273\223\346\236\204.png" "b/zh-cn/device-dev/subsystems/figure/\346\231\256\351\200\232\347\273\204\344\273\266\346\240\221\347\273\223\346\236\204.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/subsystems/figures/\346\231\256\351\200\232\347\273\204\344\273\266\346\240\221\347\273\223\346\236\204.png" rename to "zh-cn/device-dev/subsystems/figure/\346\231\256\351\200\232\347\273\204\344\273\266\346\240\221\347\273\223\346\236\204.png" diff --git "a/zh-cn/device-dev/subsystems/figures/\346\260\264\345\271\263-\345\236\202\347\233\264\346\226\271\345\220\221\345\217\257\346\273\221\345\212\250\346\225\210\346\236\234\345\233\276.gif" "b/zh-cn/device-dev/subsystems/figure/\346\260\264\345\271\263-\345\236\202\347\233\264\346\226\271\345\220\221\345\217\257\346\273\221\345\212\250\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/subsystems/figures/\346\260\264\345\271\263-\345\236\202\347\233\264\346\226\271\345\220\221\345\217\257\346\273\221\345\212\250\346\225\210\346\236\234\345\233\276.gif" rename to "zh-cn/device-dev/subsystems/figure/\346\260\264\345\271\263-\345\236\202\347\233\264\346\226\271\345\220\221\345\217\257\346\273\221\345\212\250\346\225\210\346\236\234\345\233\276.gif" diff --git "a/zh-cn/device-dev/subsystems/figures/\346\265\213\350\257\225\345\271\263\345\217\260\346\236\266\346\236\204.png" "b/zh-cn/device-dev/subsystems/figure/\346\265\213\350\257\225\345\271\263\345\217\260\346\236\266\346\236\204.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/subsystems/figures/\346\265\213\350\257\225\345\271\263\345\217\260\346\236\266\346\236\204.png" rename to "zh-cn/device-dev/subsystems/figure/\346\265\213\350\257\225\345\271\263\345\217\260\346\236\266\346\236\204.png" diff --git "a/zh-cn/device-dev/subsystems/figures/\346\265\213\350\257\225\345\271\263\345\217\260\350\277\220\350\241\214\346\227\266\345\272\217.png" "b/zh-cn/device-dev/subsystems/figure/\346\265\213\350\257\225\345\271\263\345\217\260\350\277\220\350\241\214\346\227\266\345\272\217.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/subsystems/figures/\346\265\213\350\257\225\345\271\263\345\217\260\350\277\220\350\241\214\346\227\266\345\272\217.png" rename to "zh-cn/device-dev/subsystems/figure/\346\265\213\350\257\225\345\271\263\345\217\260\350\277\220\350\241\214\346\227\266\345\272\217.png" diff --git "a/zh-cn/device-dev/subsystems/figures/\347\273\204\344\273\266\346\240\221\347\273\223\346\236\204\347\244\272\346\204\217\345\233\276.png" "b/zh-cn/device-dev/subsystems/figure/\347\273\204\344\273\266\346\240\221\347\273\223\346\236\204\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/subsystems/figures/\347\273\204\344\273\266\346\240\221\347\273\223\346\236\204\347\244\272\346\204\217\345\233\276.png" rename to "zh-cn/device-dev/subsystems/figure/\347\273\204\344\273\266\346\240\221\347\273\223\346\236\204\347\244\272\346\204\217\345\233\276.png" diff --git "a/zh-cn/device-dev/subsystems/figures/\347\274\226\350\257\221\346\236\204\345\273\272\346\265\201\347\250\213.jpg" "b/zh-cn/device-dev/subsystems/figure/\347\274\226\350\257\221\346\236\204\345\273\272\346\265\201\347\250\213.jpg" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/subsystems/figures/\347\274\226\350\257\221\346\236\204\345\273\272\346\265\201\347\250\213.jpg" rename to "zh-cn/device-dev/subsystems/figure/\347\274\226\350\257\221\346\236\204\345\273\272\346\265\201\347\250\213.jpg" diff --git "a/zh-cn/device-dev/subsystems/figures/\350\207\252\351\200\202\345\272\224\346\250\241\345\274\217\345\233\276\347\211\207\346\225\210\346\236\234\345\233\276.png" "b/zh-cn/device-dev/subsystems/figure/\350\207\252\351\200\202\345\272\224\346\250\241\345\274\217\345\233\276\347\211\207\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/subsystems/figures/\350\207\252\351\200\202\345\272\224\346\250\241\345\274\217\345\233\276\347\211\207\346\225\210\346\236\234\345\233\276.png" rename to "zh-cn/device-dev/subsystems/figure/\350\207\252\351\200\202\345\272\224\346\250\241\345\274\217\345\233\276\347\211\207\346\225\210\346\236\234\345\233\276.png" diff --git "a/zh-cn/device-dev/subsystems/figures/\350\256\276\347\275\2562-2\347\275\221\346\240\274\345\271\266\346\267\273\345\212\2404\344\270\252button\347\273\204\344\273\266\350\277\233\350\241\214\345\270\203\345\261\200.png" "b/zh-cn/device-dev/subsystems/figure/\350\256\276\347\275\2562-2\347\275\221\346\240\274\345\271\266\346\267\273\345\212\2404\344\270\252button\347\273\204\344\273\266\350\277\233\350\241\214\345\270\203\345\261\200.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/subsystems/figures/\350\256\276\347\275\2562-2\347\275\221\346\240\274\345\271\266\346\267\273\345\212\2404\344\270\252button\347\273\204\344\273\266\350\277\233\350\241\214\345\270\203\345\261\200.png" rename to "zh-cn/device-dev/subsystems/figure/\350\256\276\347\275\2562-2\347\275\221\346\240\274\345\271\266\346\267\273\345\212\2404\344\270\252button\347\273\204\344\273\266\350\277\233\350\241\214\345\270\203\345\261\200.png" diff --git a/zh-cn/device-dev/subsystems/figures/RIL-Adapter.png b/zh-cn/device-dev/subsystems/figures/RIL-Adapter.png deleted file mode 100644 index eb3a5f511cb246a0c250a0dc76150b8816f4394b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 24049 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 diff --git "a/zh-cn/device-dev/subsystems/hdc_std-\344\275\277\347\224\250\346\214\207\345\257\274.md" "b/zh-cn/device-dev/subsystems/hdc_std-\344\275\277\347\224\250\346\214\207\345\257\274.md" deleted file mode 100644 index d4993fb7b5..0000000000 --- "a/zh-cn/device-dev/subsystems/hdc_std-\344\275\277\347\224\250\346\214\207\345\257\274.md" +++ /dev/null @@ -1,658 +0,0 @@ -# hdc\_std 使用指导 - -- [环境准备](#section05992022154916) -- [注意事项](#section19543134915210) -- [全局option](#section618522925119) -- [查询设备列表](#section174891132104218) -- [服务进程相关命令](#section680531510497) -- [网络相关的命令](#section71176123212) -- [文件相关的命令](#section173133523013) -- [应用相关的命令](#section2072647133819) -- [调试相关的命令](#section112861250195015) - -hdc\_std(OpenHarmony Device Connector)是OpenHarmony为开发人员提供的用于调试的命令行工具,通过该工具可以在Windows/Linux等系统上与开发机或者模拟器进行交互。 - -下文将介绍hdc\_std的环境准备和常用命令及使用举例。 - -## 环境准备 - -**hdc\_std 工具获取方式:** - -从开源仓developtools\_hdc\_standard中获取,具体位置在该开源仓的prebuilt目录。 - -**使用举例:** - -下面以windows侧使用方式举例: - -从prebuilt/windows侧获取可执行文件hdc\_std.exe,放到磁盘某个位置即可使用。 - -## 注意事项 - -1、使用hdc\_std,如果出现异常,可以尝试通过hdc\_std kill命令杀掉hdc\_std服务,或者通过hdc\_std start -r命令重启服务进程进行解决。 - -2、如果出现hdc\_std list targets获取不到设备信息,通过任务管理器查看是否有hdc.exe进程存在,如果进程存在,可以通过杀掉该进程进行解决。 - -## 全局option - -全局option涉及以下命令: - -- **-h/help -v/version** - -用于显示hdc相关的帮助、版本信息。 - -**表 1** 命令说明 - - - - - - - - - - - - - - - -

    参数

    -

    参数说明

    -

    -h/help -v/version

    -

    -

    返回值

    -

    返回值说明

    -

    返回对应信息

    -

    帮助或者版本信息

    -
    - -使用方法: - -hdc\_std -h / hdc\_std help - -hdc\_std -v / hdc\_std version - -- **-t key** - -用于连接指定设备标识为key的设备。 - -**表 2** 命令说明 - - - - - - - - - - - - - - - -

    参数

    -

    参数说明

    -

    key

    -

    为tcp:port格式,或者USB序列号

    -

    返回值

    -

    返回值说明

    -

    ①error: device '***' not found

    -

    ②Nothing to do...

    -

    ①设备不存在

    -

    ②附加的命令不存在

    -
    - -使用方法: - -该option需要与具体的操作命令搭配使用,下面以shell命令举例: - -hdc\_std list targets (获取设备信息) - -hdc\_std -t _key_ shell (-t后面添加的_key_ 需要替换为上面查询的设备信息) - ->![](public_sys-resources/icon-note.gif) **说明:** ->一台开发机可支持多个设备连接,每个设备有其唯一的设备标识,如果通过网络与设备连接,其标识为tcp:port格式,如果通过usb连接则标识为设备sn号。该命令需要跟随具体操作命令。 - -## 查询设备列表 - -查询设备列表涉及以下命令: - -**list targets\[-v\]** - -显示所有已经连接的目标设备列表 - -**表 3** 命令说明 - - - - - - - - - - - - - - - -

    参数

    -

    参数说明

    -

    -v

    -

    添加-v选项,则会打印设备详细信息

    -

    返回值

    -

    返回值说明

    -

    ①返回设备信息

    -

    ②[Empty]

    -

    ①已经连接的设备列表信息

    -

    ②没有查询到设备信息

    -
    - -使用方法: - -hdc\_std list targets - -hdc\_std list targets -v - -## 服务进程相关命令 - -服务进程涉及以下命令: - -- **target mount** - -以读写模式挂载/system等分区。 - -**表 4** 命令说明 - - - - - - - - - - - - - - - -

    参数

    -

    参数说明

    -

    -

    -

    返回值

    -

    返回值说明

    -

    ①Mount finish

    -

    ②返回具体信息

    -

    ①成功情况下返回的信息

    -

    ②失败情况下的具体信息

    -
    - -使用方法: - -hdc\_std target mount - -- **smode \[off\]** - -授予后台服务进程root权限, 使用off参数取消授权。 - -使用方法: - -hdc\_std smode - -hdc\_std smode off - -- **kill \[-r\]** - -终止服务进程。 - -**表 5** 命令说明 - - - - - - - - - - - - - - - -

    参数

    -

    参数说明

    -

    -r

    -

    触发服务重启

    -

    返回值

    -

    返回值说明

    -

    ①Kill server finish

    -

    ②返回具体信息

    -

    ①成功情况下返回的信息

    -

    ②失败情况下的具体信息

    -
    - -使用方法: - -hdc\_std kill - -- **start \[-r\]** - -启动服务进程。 - -**表 6** 命令说明 - - - - - - - - - - - - - - - -

    参数

    -

    参数说明

    -

    -r

    -

    如果服务进程已经启动,-r选项会触发服务进程重新启动

    -

    返回值

    -

    返回值说明

    -

    -

    -
    - -使用方法: - -hdc\_std start - -## 网络相关的命令 - -网络部分涉及以下命令: - -- **tconn _host_\[:_port_\]\[-remove\]** - -通过【ip地址:端口号】来指定连接的设备 - -**表 7** 命令说明 - - - - - - - - - - - - - - - - - - -

    参数

    -

    参数说明

    -

    host[:port]

    -

    为tcp:port格式

    -

    -remove

    -

    表示断开与指定设备的连接

    -

    返回值

    -

    返回值说明

    -

    ①返回具体信息

    -

    ②无

    -

    ①失败情况下的具体信息

    -

    ②成功情况下无返回值

    -
    - -使用方法(举例): - -hdc\_std tconn 192.168.0.100:8710 - -- **tmode usb** - -执行后设备端对应daemon进程重启,并首先选用usb连接方式。 - -**表 8** 命令说明 - - - - - - - - - - - - - - - -

    参数

    -

    参数说明

    -

    -

    -

    返回值

    -

    返回值说明

    -

    ①返回具体信息

    -

    ②无

    -

    ①失败情况下的具体信息

    -

    ②成功情况下无返回值

    -
    - -使用方法: - -hdc\_std tmode usb - -- **tmode port _port-number_** - -执行后设备端对应daemon进程重启,并优先使用网络方式连接设备,如果连接设备再选择usb连接。 - -**表 9** 命令说明 - - - - - - - - - - - - - - - -

    参数

    -

    参数说明

    -

    port-number

    -

    listen连接的网络端口

    -

    返回值

    -

    返回值说明

    -

    ①返回具体信息

    -

    ②无

    -

    ①失败情况下的具体信息

    -

    ②成功情况下无返回值

    -
    - -使用方法: - -hdc\_std tmode port 8710 - ->![](public_sys-resources/icon-note.gif) **说明:** ->执行完毕后,远端daemon将会退出并重启,默认启用TCP连接,如果不加上listen端口则listen随机端口。 - -## 文件相关的命令 - -文件部分涉及以下命令: - -- **file send _local remote_** - -发送文件至远端设备。 - -**表 10** 命令说明 - - - - - - - - - - - - - - - - - - -

    参数

    -

    参数说明

    -

    local

    -

    本地待发送文件路径

    -

    remote

    -

    远程待接收文件路径

    -

    返回值

    -

    返回值说明

    -

    ①返回具体信息

    -

    ②返回传输结果

    -

    ①失败情况下的具体信息

    -

    ②成功传输的结果信息

    -
    - -使用方法(举例): - -hdc\_std file send E:\\a.txt /data/local/tmp/a.txt - -- **file recv \[-a\] _remote local_** - -从远端设备接收文件至本地。 - -**表 11** 命令说明 - - - - - - - - - - - - - - - - - - - - - -

    参数

    -

    参数说明

    -

    -a

    -

    文件保留时间戳模式

    -

    local

    -

    本地待接收文件路径

    -

    remote

    -

    远程待发送文件路径

    -

    返回值

    -

    返回值说明

    -

    ①返回具体信息

    -

    ②无

    -

    ①失败情况下的具体信息

    -

    ②成功情况下无返回值

    -
    - -使用方法(举例): - -hdc\_std file recv /data/local/tmp/a.txt ./a.txt - -## 应用相关的命令 - -应用部分涉及以下命令: - -- **install \[-r/-d/-g\] _package_** - -安装OpenHarmony package。 - -**表 12** 命令说明 - - - - - - - - - - - - - - - - - - - - - - - - -

    参数

    -

    参数说明

    -

    package

    -

    OpenHarmony应用安装包

    -

    -r

    -

    替换已存在应用

    -

    -d

    -

    允许降级安装

    -

    -g

    -

    动态授权

    -

    返回值

    -

    返回值说明

    -

    ①返回具体信息

    -

    ②无

    -

    ①失败情况下的具体信息

    -

    ②成功情况下无返回值

    -
    - -使用方法(举例): - -hdc\_std install _hwadmin.hap_ - -- **uninstall \[-k\] _package_** - -卸载OpenHarmony应用。 - -**表 13** 命令说明 - - - - - - - - - - - - - - - - - - -

    参数

    -

    参数说明

    -

    package

    -

    OpenHarmony应用安装包

    -

    -k

    -

    保留/data/cache

    -

    返回值

    -

    返回值说明

    -

    ①返回具体信息

    -

    ②无

    -

    ①失败情况下的具体信息

    -

    ②成功情况下无返回值

    -
    - -使用方法(举例): - -hdc\_std uninstall _package_ - -## 调试相关的命令 - -调试涉及以下命令: - -- **hilog** - -支持抓取log信息。 - -**表 14** 命令说明 - - - - - - - - - - - - - - - -

    参数

    -

    参数说明

    -

    -

    -

    返回值

    -

    返回值说明

    -

    返回具体信息

    -

    抓取的日志信息

    -
    - -使用方法: - -hdc\_std hilog - -- **shell \[_command_\]** - -远程执行命令或进入交互命令环境。 - -**表 15** 命令说明 - - - - - - - - - - - - - - - -

    参数

    -

    参数说明

    -

    command

    -

    需要执行的单次命令

    -

    返回值

    -

    返回值说明

    -

    返回具体信息

    -

    shell后面执行命令的结果信息

    -
    - -使用方法: - -hdc\_std shell - diff --git "a/zh-cn/device-dev/subsystems/hdc_std\345\270\270\350\247\201\351\227\256\351\242\230.md" "b/zh-cn/device-dev/subsystems/hdc_std\345\270\270\350\247\201\351\227\256\351\242\230.md" deleted file mode 100644 index 3f83fba3e9..0000000000 --- "a/zh-cn/device-dev/subsystems/hdc_std\345\270\270\350\247\201\351\227\256\351\242\230.md" +++ /dev/null @@ -1,39 +0,0 @@ -# hdc\_std常见问题 - -- [hdc\_std连接不到设备](#section1221016541119) -- [hdc\_std运行不了](#section219185710311) - -## hdc\_std连接不到设备 - -- **现象描述** - - 执行 "hdc\_std list targets"命令后结果为:\[Empty\] - -- **可能原因和解决方法** - 1. 设备没有被识别: - - 在设备管理器中查看是否有hdc设备,在通用串行总线设备中会有“HDC Device”信息。如果没有,hdc无法连接。此时需要插拔设备,或者烧写最新的镜像。 - - 2. hdc\_std工作异常: - - 可以执行"hdc kill"或者"hdc start -r"杀掉hdc服务或者重启hdc服务,然后再执行hdc list targets查看是否已经可以获取设备信息。 - - 如果一直获取不到设备信息,请在任务管理器中查询是否有adb进程,该进程可能会对hdc产生干扰,可以将其杀掉后重复执行上面的步骤。 - - 3. hdc\_std与设备不匹配: - - 如果设备烧写的是最新镜像,hdc\_std也需要使用最新版本。由于hdc\_std会持续更新,请从开源仓developtools\_hdc\_standard中获取,具体位置在该开源仓的prebuilt目录。 - - - -## hdc\_std运行不了 - -- **现象描述** - - 点击hdc\_std.exe文件无法运行。 - -- **可能原因和解决方法** - - hdc\_std.exe不需要安装,直接放到磁盘上就能使用,也可以添加到环境变量中。通过打开cmd执行hdc\_std命令直接使用。 - - diff --git a/zh-cn/device-dev/subsystems/public_sys-resources/icon-caution.gif b/zh-cn/device-dev/subsystems/public_sys-resources/icon-caution.gif deleted file mode 100755 index 6e90d7cfc2193e39e10bb58c38d01a23f045d571..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 580 zcmV-K0=xZ3Nk%w1VIu$?0Hp~4{QBgqmQ+MG9K51r{QB&)np^||1PlfQ%(86!{`~yv zv{XhUWKt}AZaiE{EOcHp{O-j3`t;<+eEiycJT4p@77X;(jQsMfB$R?oG%6hQ z+MMLZbQBH@)Vg&1^3?qHb(5!%>3r0+`eq=&V&E}0Dypi0000000000 z00000A^8LW000R9EC2ui03!e$000L5z=Uu}ED8YtqjJd<+B}(9bIOb$3-31_h|V>=0A{ z1Hh0#H30>fNT})^fRU_83uewx9oRr{f{Sx1Ml`t)EQ zGkHZ67&~y{W5Jpq4H_WfuLxp*3<7O}GEl;1ESe36fLNs=B0&LQM1Buf(R)qg(BRd`t1OPjI1m_q4 diff --git a/zh-cn/device-dev/subsystems/public_sys-resources/icon-danger.gif b/zh-cn/device-dev/subsystems/public_sys-resources/icon-danger.gif deleted file mode 100755 index 6e90d7cfc2193e39e10bb58c38d01a23f045d571..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 580 zcmV-K0=xZ3Nk%w1VIu$?0Hp~4{QBgqmQ+MG9K51r{QB&)np^||1PlfQ%(86!{`~yv zv{XhUWKt}AZaiE{EOcHp{O-j3`t;<+eEiycJT4p@77X;(jQsMfB$R?oG%6hQ z+MMLZbQBH@)Vg&1^3?qHb(5!%>3r0+`eq=&V&E}0Dypi0000000000 z00000A^8LW000R9EC2ui03!e$000L5z=Uu}ED8YtqjJd<+B}(9bIOb$3-31_h|V>=0A{ z1Hh0#H30>fNT})^fRU_83uewx9oRr{f{Sx1Ml`t)EQ zGkHZ67&~y{W5Jpq4H_WfuLxp*3<7O}GEl;1ESe36fLNs=B0&LQM1Buf(R)qg(BRd`t1OPjI1m_q4 diff --git a/zh-cn/device-dev/subsystems/public_sys-resources/icon-note.gif b/zh-cn/device-dev/subsystems/public_sys-resources/icon-note.gif deleted file mode 100755 index 6314297e45c1de184204098efd4814d6dc8b1cda..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 394 zcmZ?wbhEHblx7fPSjxcg=ii?@_wH=jwxy=7CMGH-B`L+l$wfv=#>UF#$gv|VY%C^b zCQFtrnKN(Bo_%|sJbO}7RAORe!otL&qo<>yq_Sq+8Xqqo5h0P3w3Lvb5E(g{p01vl zxR@)KuDH0l^z`+-dH3eaw=XqSH7aTIx{kzVBN;X&hha0dQSgWuiw0NWUvMRmkD|> diff --git a/zh-cn/device-dev/subsystems/public_sys-resources/icon-notice.gif b/zh-cn/device-dev/subsystems/public_sys-resources/icon-notice.gif deleted file mode 100755 index 86024f61b691400bea99e5b1f506d9d9aef36e27..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 406 zcmV;H0crk6Nk%w1VIu$@0J8u9|NsB@_xJDb@8;&_*4Ea}&d#;9wWXz{jEszHYim+c zQaU<1At50E0000000000A^8Le000gEEC2ui03!e%000R7038S%NU)&51O^i-Tu6`s z0)`MFE@;3YqD6xSC^kTNu_J>91{PH8XfZ(p1pp2-SU@u3#{mEUC}_}tg3+I#{z}{Ok@D_ZUDg- zt0stin4;pC8M{WLSlRH*1pzqEw1}3oOskyNN?j;7HD{BBZ*OEcv4HK!6Bk6beR+04 z&8}k>SkTusVTDmkyOz#5fCA$JTPGJVQvr3uZ?QzzPQFvD0rGf_PdrcF`pMs}p^BcF zKtKTd`0wipR%nKN&Wj+V}pX;WC3SdJV!a_8Qi zE7z`U*|Y^H0^}fB$R?oG%6hQ z+MMLZbQBH@)Vg&1^3?qHb(5!%>3r0+`eq=&V&E}0Dypi0000000000 z00000A^8LW000R9EC2ui03!e$000L5z=Uu}ED8YtqjJd<+B}(9bIOb$3-31_h|V>=0A{ z1Hh0#H30>fNT})^fRU_83uewx9oRr{f{Sx1Ml`t)EQ zGkHZ67&~y{W5Jpq4H_WfuLxp*3<7O}GEl;1ESe36fLNs=B0&LQM1Buf(R)qg(BRd`t1OPjI1m_q4 diff --git "a/zh-cn/device-dev/subsystems/\345\224\244\351\206\222\350\257\215\350\257\206\345\210\253\351\205\215\347\275\256\346\226\207\344\273\266\347\232\204\345\274\200\345\217\221\347\244\272\344\276\213.md" b/zh-cn/device-dev/subsystems/subsys-aiframework-demo-conf.md old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/subsystems/\345\224\244\351\206\222\350\257\215\350\257\206\345\210\253\351\205\215\347\275\256\346\226\207\344\273\266\347\232\204\345\274\200\345\217\221\347\244\272\344\276\213.md" rename to zh-cn/device-dev/subsystems/subsys-aiframework-demo-conf.md diff --git "a/zh-cn/device-dev/subsystems/\345\224\244\351\206\222\350\257\215\350\257\206\345\210\253\346\217\222\344\273\266\347\232\204\345\274\200\345\217\221\347\244\272\344\276\213.md" b/zh-cn/device-dev/subsystems/subsys-aiframework-demo-plugin.md old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/subsystems/\345\224\244\351\206\222\350\257\215\350\257\206\345\210\253\346\217\222\344\273\266\347\232\204\345\274\200\345\217\221\347\244\272\344\276\213.md" rename to zh-cn/device-dev/subsystems/subsys-aiframework-demo-plugin.md diff --git a/zh-cn/device-dev/subsystems/subsys-aiframework-demo-sdk.md b/zh-cn/device-dev/subsystems/subsys-aiframework-demo-sdk.md new file mode 100644 index 0000000000..795599d872 --- /dev/null +++ b/zh-cn/device-dev/subsystems/subsys-aiframework-demo-sdk.md @@ -0,0 +1,81 @@ +# 唤醒词识别SDK的开发示例 + +1. 在//foundation/ai/engine /interfaces/kits目录中添加唤醒词识别SDK的API接口定义,该接口可用三方应用的调用。如下代码片段即为唤醒词识别定义的API接口示例,其相关代码参考路径为://foundation/ai/engine /interfaces/kits/asr/keyword\_spotting。 + + ``` + class KWSSdk { + public: + KWSSdk(); + virtual ~KWSSdk(); + + // 定义了创建唤醒词检测工具包的方法 + int32_t Create(); + + // 定义了同步执行唤醒词检测任务的方法 + int32_t SyncExecute(const Array &audioInput); + + // 定义了设置唤醒词检测回调器的方法 + int32_t SetCallback(const std::shared_ptr &callback); + + // 定义了销毁唤醒词工具包的方法,释放与插件的会话信息。 + int32_t Destroy(); + }; + ``` + +2. 在//foundation/ai/engine/services/client/algorithm\_sdk的目录中增加SDK中API接口的具体实现,调用client端提供的接口,实现算法插件能力的使用。如下代码片段即为唤醒词识别的API接口中create方法的具体实现示例,更多详细代码可参考://foundation/ai/engine/services/client/algorithm\_sdk/asr/keyword\_spotting。 + + ``` + int32_t KWSSdk::KWSSdkImpl::Create() + { + if (kwsHandle_ != INVALID_KWS_HANDLE) { + HILOGE("[KWSSdkImpl]The SDK has been created"); + return KWS_RETCODE_FAILURE; + } + if (InitComponents() != RETCODE_SUCCESS) { + HILOGE("[KWSSdkImpl]Fail to init sdk components"); + return KWS_RETCODE_FAILURE; + } + // 调用client端提供的接口AieClientInit,实现初始化引擎服务,激活跨进程调用 + int32_t retCode = AieClientInit(configInfo_, clientInfo_, algorithmInfo_, nullptr); + if (retCode != RETCODE_SUCCESS) { + HILOGE("[KWSSdkImpl]AieClientInit failed. Error code[%d]", retCode); + return KWS_RETCODE_FAILURE; + } + if (clientInfo_.clientId == INVALID_CLIENT_ID) { + HILOGE("[KWSSdkImpl]Fail to allocate client id"); + return KWS_RETCODE_FAILURE; + } + DataInfo inputInfo = { + .data = nullptr, + .length = 0, + }; + DataInfo outputInfo = { + .data = nullptr, + .length = 0, + }; + // 调用client端提供的接口AieClientPrepare,实现加载算法插件 + retCode = AieClientPrepare(clientInfo_, algorithmInfo_, inputInfo, outputInfo, nullptr); + if (retCode != RETCODE_SUCCESS) { + HILOGE("[KWSSdkImpl]AieclientPrepare failed. Error code[%d]", retCode); + return KWS_RETCODE_FAILURE; + } + if (outputInfo.data == nullptr || outputInfo.length <= 0) { + HILOGE("[KWSSdkImpl]The data or length of output info is invalid"); + return KWS_RETCODE_FAILURE; + } + MallocPointerGuard pointerGuard(outputInfo.data); + retCode = PluginHelper::UnSerializeHandle(outputInfo, kwsHandle_); + if (retCode != RETCODE_SUCCESS) { + HILOGE("[KWSSdkImpl]Get handle from inputInfo failed"); + return KWS_RETCODE_FAILURE; + } + return KWS_RETCODE_SUCCESS; + } + ``` + + 上述代码为API接口的具体实现,从上述示例的代码中,SDK中create接口的具体实现即为下述示例代码中create方法,该方法调用了AI引擎框架client端开放接口AieClientInit,AieClientPrepare,从而实现与server端建立连接及加载算法模型的能力。 + + >![](../public_sys-resources/icon-note.gif) **说明:** + >SDK调用AI引擎client端接口顺序应遵循AieClientInit-\>AieClientPrepare-\>AieClientSyncProcess/AieClientAsyncProcess-\>AieClientRelease-\>AieClientDestroy,否则调用接口会返回错误码。 + + diff --git a/zh-cn/device-dev/subsystems/subsys-aiframework-demo.md b/zh-cn/device-dev/subsystems/subsys-aiframework-demo.md new file mode 100644 index 0000000000..054336dafd --- /dev/null +++ b/zh-cn/device-dev/subsystems/subsys-aiframework-demo.md @@ -0,0 +1,13 @@ +# 开发示例 + +以开发唤醒词识别为例,开发者可在Hi3516DV300开发板上,基于AI引擎框架开发唤醒词识别的sdk以及唤醒词识别的plugin,通过编译命令编出新的版本镜像并将其烧入版本。同时,开发者开发唤醒词识别的应用,该应用能够接收外部音频,将listen到的音频传入SDK中的接口,若音频中带有关键词,唤醒词识别的应用会识别出相应的词语,并打印在命令行中。 + +本示例中唤醒词识别的场景中唤醒词是固定的,当开发者传入的音频包含”Hi,小问“,启动的应用就会打印"\[Hi, xiaowen\]",当不包含时,会打印'\[UNKNOWN\]"。 + +- **[唤醒词识别SDK的开发示例](subsys-aiframework-demo-sdk.md)** + +- **[唤醒词识别插件的开发示例](subsys-aiframework-demo-plugin.md)** + +- **[唤醒词识别配置文件的开发示例](subsys-aiframework-demo-conf.md)** + + diff --git "a/zh-cn/device-dev/subsystems/\351\205\215\347\275\256\346\226\207\344\273\266\347\232\204\345\274\200\345\217\221\350\277\207\347\250\213.md" b/zh-cn/device-dev/subsystems/subsys-aiframework-devguide-conf.md old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/subsystems/\351\205\215\347\275\256\346\226\207\344\273\266\347\232\204\345\274\200\345\217\221\350\277\207\347\250\213.md" rename to zh-cn/device-dev/subsystems/subsys-aiframework-devguide-conf.md diff --git "a/zh-cn/device-dev/subsystems/\346\217\222\344\273\266\347\232\204\345\274\200\345\217\221\350\277\207\347\250\213.md" b/zh-cn/device-dev/subsystems/subsys-aiframework-devguide-plugin.md old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/subsystems/\346\217\222\344\273\266\347\232\204\345\274\200\345\217\221\350\277\207\347\250\213.md" rename to zh-cn/device-dev/subsystems/subsys-aiframework-devguide-plugin.md diff --git a/zh-cn/device-dev/subsystems/subsys-aiframework-devguide-sdk.md b/zh-cn/device-dev/subsystems/subsys-aiframework-devguide-sdk.md new file mode 100644 index 0000000000..ed8f624d68 --- /dev/null +++ b/zh-cn/device-dev/subsystems/subsys-aiframework-devguide-sdk.md @@ -0,0 +1,162 @@ +# SDK开发过程 + +SDK头文件的功能实现是基于对SDK的调用映射到对client的调用。Client端提供的接口如下[表1](#table203963834718)所示。 + +**表 1** Client端提供的接口 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    接口名

    +

    接口说明

    +

    参数要求

    +

    int AieClientInit(const ConfigInfo &configInfo, ClientInfo &clientInfo, const AlgorithmInfo &algorithmInfo, IServiceDeadCb *cb)

    +

    作用:链接并初始化引擎服务,激活跨进程调用。

    +

    返回值:0为成功,其他返回值失败。

    +

    configInfo(NOT NULL):引擎相关初始化配置数据;

    +

    clientInfo(NOT NULL):引擎客户端信息;

    +

    algorithmInfo(NOT NULL):调用算法信息;

    +

    cb(可为NULL):死亡回调 对象;

    +

    int AieClientPrepare(const ClientInfo &clientInfo, const AlgorithmInfo &algorithmInfo, const DataInfo &inputInfo, DataInfo &outputInfo, IClientCb *cb)

    +

    作用:加载算法插件。

    +

    返回值: 0为成功,其他返回值失败。

    +

    clientInfo(NOT NULL):引擎客户端信息;

    +

    algorithmInfo(NOT NULL):调用算法信息;

    +

    inputInfo(可为NULL):加载算法插件时输入所需信息;

    +

    outputInfo(可为NULL):加载算法插件之后如需返回信息则通过此出参返回;

    +

    cb:异步算法通过此回调返回运算结果,因此异步算法此结构体不能为空;若为同步算法,传入空值即可;

    +

    int AieClientAsyncProcess(const ClientInfo &clientInfo, const AlgorithmInfo &algorithmInfo, const DataInfo &inputInfo)

    +

    作用:执行异步算法。

    +

    返回值:0为成功,其他返回值失败。

    +

    clientInfo(NOT NULL):引擎客户端信息;

    +

    algorithmInfo(NOT NULL):调用算法信息;

    +

    inputInfo(可为NULL):算法运算入参;

    +

    int AieClientSyncProcess(const ClientInfo &clientInfo, const AlgorithmInfo &algorithmInfo, const DataInfo &inputInfo, DataInfo &outputInfo)

    +

    作用:执行同步算法。

    +

    返回值:0为成功,其他返回值失败。

    +

    clientInfo(NOT NULL):引擎客户端信息;

    +

    algorithmInfo(NOT NULL):调用算法信息;

    +

    inputInfo(可为NULL):算法运算入参;

    +

    outputInfo(可为NULL):同步算法运算结果出参;

    +

    int AieClientRelease(const ClientInfo &clientInfo, const AlgorithmInfo &algorithmInfo, const DataInfo &inputInfo)

    +

    作用:卸载算法插件。

    +

    返回值:0为成功,其他返回值失败。

    +

    clientInfo(NOT NULL):引擎客户端信息;

    +

    algorithmInfo(NOT NULL):卸载算法插件的相关信息;

    +

    inputInfo(可为NULL):调用卸载接口时的输入信息;

    +

    int AieClientDestroy(ClientInfo &clientInfo)

    +

    作用:断开与服务端的链接,释放相关缓存。

    +

    返回值:0为成功,其他返回值失败。

    +

    clientInfo(NOT NULL):所要销毁的引擎客户端信息;

    +

    int AieClientSetOption(const ClientInfo &clientInfo, int optionType, const DataInfo &inputInfo)

    +

    作用:设置配置项,可将一些算法的拓展信息通过此接口传入插件。

    +

    返回值:0为成功,其他返回值失败。

    +

    clientInfo(NOT NULL):引擎客户端信息;

    +

    optionType (NOT NULL):算法配置项,算法插件可根据需要利用此状态位;

    +

    inputInfo(可为NULL):插件可根据需要通过此入参设置算法参数信息;

    +

    int AieClientGetOption(const ClientInfo &clientInfo, int optionType, const DataInfo &inputInfo, DataInfo &outputInfo)

    +

    作用:给定特定的optionType和inputInfo,获取其对应的配置项信息。

    +

    返回值:0为成功,其他返回值失败。

    +

    clientInfo(NOT NULL):引擎客户端信息;

    +

    optionType(NOT NULL):所获取配置项信息的对应算法状态位;

    +

    inputInfo(可为NULL):所获取配置项信息的对应算法参数信息;

    +

    outputInfo(可为NULL):所要获取的配置项信息返回结果;

    +
    + +其中,ConfigInfo,ClientInfo,AlgorithmInfo,DataInfo的数据结构如下[表2](#table22154317482)所示。 + +**表 2** ConfigInfo,ClientInfo,AlgorithmInfo,DataInfo的数据结构 + + + + + + + + + + + + + + + + + + + + + + + + +

    结构体名称

    +

    说明

    +

    属性

    +

    ConfigInfo

    +

    算法配置项信息。

    +

    const char *description:配置项信息主体;

    +

    ClientInfo

    +

    客户端信息。

    +

    long long clientVersion:客户端设备版本号(当前还未启用);

    +

    int clientId:客户端ID;

    +

    int sessionId:会话ID;

    +

    uid_t serverUid:server端UID;

    +

    uid_t clientUid:client端UID;

    +

    int extendLen:拓展信息(extendMsg)长度;

    +

    unsigned char *extendMsg:拓展信息主体;

    +

    AlgorithmInfo

    +

    算法信息。

    +

    long long clientVersion:客户端设备版本号(当前还未启用);

    +

    bool isAsync:是否为异步执行;

    +

    int algorithmType:引擎框架根据插件加载顺序分配的算法类型ID;

    +

    long long algorithmVersion:算法版本号;

    +

    bool isCloud:是否上云(当前还未启用);

    +

    int operateId:执行ID(当前还未启用);

    +

    int requestId:请求ID,标识每次request,以对应执行结果;

    +

    int extendLen:拓展信息(extendMsg)长度;

    +

    unsigned char *extendMsg:拓展信息主体;

    +

    DataInfo

    +

    算法数据入参(inputInfo)、接口调用结果出参(outputInfo)。

    +

    unsigned char *data:数据主体;

    +

    int length:数据(data)长度;

    +
    + +具体开发过程可参考唤醒词识别SDK开发示例。 + diff --git a/zh-cn/device-dev/subsystems/subsys-aiframework-devguide.md b/zh-cn/device-dev/subsystems/subsys-aiframework-devguide.md new file mode 100644 index 0000000000..5de9fe721c --- /dev/null +++ b/zh-cn/device-dev/subsystems/subsys-aiframework-devguide.md @@ -0,0 +1,11 @@ +# 开发指导 + +为实现AI 引擎框架的接入,开发者需开发上述[图1](subsys-aiframework-guide.md#fig143186187187)中的SDK模块和Plugin模块,通过调用sdk提供的接口,基于AI引擎框架实现调用plugin中算法的能力,从而实现AI能力的生命周期管理和按需部署功能。 + +- **[SDK开发过程](subsys-aiframework-devguide-sdk.md)** + +- **[插件的开发过程](subsys-aiframework-devguide-plugin.md)** + +- **[配置文件的开发过程](subsys-aiframework-devguide-conf.md)** + + diff --git a/zh-cn/device-dev/subsystems/subsys-aiframework-envbuild.md b/zh-cn/device-dev/subsystems/subsys-aiframework-envbuild.md new file mode 100644 index 0000000000..50cd9a3f9c --- /dev/null +++ b/zh-cn/device-dev/subsystems/subsys-aiframework-envbuild.md @@ -0,0 +1,5 @@ +# 搭建环境 + +1. 准备开发板:Hi3516DV300,Hi3518EV300 +2. [下载源码](../get-code/sourcecode-acquire.md) + diff --git a/zh-cn/device-dev/subsystems/subsys-aiframework-guide.md b/zh-cn/device-dev/subsystems/subsys-aiframework-guide.md new file mode 100644 index 0000000000..c725c6de1d --- /dev/null +++ b/zh-cn/device-dev/subsystems/subsys-aiframework-guide.md @@ -0,0 +1,9 @@ +# AI引擎框架开发指南 + +AI业务子系统是OpenHarmony提供原生的分布式AI能力的子系统。AI业务子系统提供了统一的AI引擎框架,实现算法能力快速插件化集成。框架中主要包含插件管理、模块管理和通信管理等模块,完成对AI算法能力的生命周期管理和按需部署。插件管理主要实现插件的生命周期管理及插件的按需部署,快速集成AI能力插件;模块管理主要实现任务的调度及管理客户端的实例;通信管理主要实现客户端和服务端之间的跨进程通信及引擎与插件之间的数据传输。后续,会逐步定义统一的AI能力接口,便于AI能力的分布式调用。同时,提供适配不同推理框架层级的统一推理接口。AI引擎框架如下[图1](#fig143186187187)所示。 + +**图 1** AI引擎框架 + + +![](figure/zh-cn_image_0000001077727032.png) + diff --git a/zh-cn/device-dev/subsystems/subsys-aiframework-tech-codemanage.md b/zh-cn/device-dev/subsystems/subsys-aiframework-tech-codemanage.md new file mode 100644 index 0000000000..f93fcf62bb --- /dev/null +++ b/zh-cn/device-dev/subsystems/subsys-aiframework-tech-codemanage.md @@ -0,0 +1,40 @@ +# 代码管理规范 + +- [建议:插件与北向SDK在AI引擎指定的路径下进行代码开发](#section17176374131) +- [规则:插件提供的全部对外接口,统一存放在AI业务子系统interfaces/kits目录](#section2551029111312) +- [规则:插件编译输出路径必须是在/usr/lib](#section97021558121310) + +AI引擎框架包含client、server和common三个主要模块,其中client提供server端连接管理功能,北向SDK在算法对外接口中需封装调用client提供的公共接口;server提供插件加载以及任务管理等功能,各Plugin实现由server提供的插件接口,完成插件接入;common提供与平台相关的操作方法、引擎协议以及相关工具类,供其他各模块调用。 + +AI引擎框架各模块之间的代码依赖关系如下[图1](#fig171811112818)所示: + +**图 1** ****AI引擎代码依赖关系 + + +![](figure/插件依赖-(2).jpg) + +## 建议:插件与北向SDK在AI引擎指定的路径下进行代码开发 + +在AI引擎框架的整体规划中,北向SDK属于client端的一部分,插件由server端调用,属于server端的一部分,因此AI引擎框架为接入的插件与北向SDK规划的路径: + +- SDK代码路径://foundation/ai/engine/services/client/algorithm\_sdk + + e.g. //foundation/ai/engine/services/client/algorithm\_sdk/cv + + e.g. //foundation/ai/engine/services/client/algorithm\_sdk/nlu + +- 插件代码路径://foundation/ai/engine/services/server/plugin + + e.g. //foundation/ai/engine/services/server/plugin/cv + + e.g. //foundation/ai/engine/services/server/plugin/nlu + + +## 规则:插件提供的全部对外接口,统一存放在AI业务子系统interfaces/kits目录 + +北向SDK对外接口是AI业务子系统提供能力的对外暴露方式,按照OpenHarmony的接口管理要求,需统一存放在各子系统的interfaces/kits目录中。当前AI业务子系统插件对外接口路径为//foundation/ai/engine/interfaces/kits,不同插件可在该路径下添加目录,比如增加cv插件,则在路径//foundation/ai/engine/interfaces/kits/cv下面存放接口文件。 + +## 规则:插件编译输出路径必须是在/usr/lib + +server端加载插件是采用dlopen方式,只支持在/usr/lib路径进行,因此插件在编译so时,需要在编译配置文件中指定输出路径为/usr/lib。 + diff --git "a/zh-cn/device-dev/subsystems/\346\216\245\345\217\243\345\274\200\345\217\221\350\247\204\350\214\203.md" b/zh-cn/device-dev/subsystems/subsys-aiframework-tech-interface.md old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/subsystems/\346\216\245\345\217\243\345\274\200\345\217\221\350\247\204\350\214\203.md" rename to zh-cn/device-dev/subsystems/subsys-aiframework-tech-interface.md diff --git "a/zh-cn/device-dev/subsystems/\345\221\275\345\220\215\350\247\204\350\214\203.md" b/zh-cn/device-dev/subsystems/subsys-aiframework-tech-name.md old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/subsystems/\345\221\275\345\220\215\350\247\204\350\214\203.md" rename to zh-cn/device-dev/subsystems/subsys-aiframework-tech-name.md diff --git a/zh-cn/device-dev/subsystems/subsys-aiframework-tech.md b/zh-cn/device-dev/subsystems/subsys-aiframework-tech.md new file mode 100644 index 0000000000..486878e0b4 --- /dev/null +++ b/zh-cn/device-dev/subsystems/subsys-aiframework-tech.md @@ -0,0 +1,15 @@ +# 技术规范 + +**用词约定:** + +**规则:**必须准守的约定 + +**建议:**需要加以考虑的约定 + +- **[代码管理规范](subsys-aiframework-tech-codemanage.md)** + +- **[命名规范](subsys-aiframework-tech-name.md)** + +- **[接口开发规范](subsys-aiframework-tech-interface.md)** + + diff --git a/zh-cn/device-dev/subsystems/subsys-aiframework.md b/zh-cn/device-dev/subsystems/subsys-aiframework.md new file mode 100644 index 0000000000..77fa018ec4 --- /dev/null +++ b/zh-cn/device-dev/subsystems/subsys-aiframework.md @@ -0,0 +1,13 @@ +# AI框架 + +- **[AI引擎框架开发指南](subsys-aiframework-guide.md)** + +- **[搭建环境](subsys-aiframework-envbuild.md)** + +- **[技术规范](subsys-aiframework-tech.md)** + +- **[开发指导](subsys-aiframework-devguide.md)** + +- **[开发示例](subsys-aiframework-demo.md)** + + diff --git a/zh-cn/device-dev/subsystems/subsys-application-framework-builden.md b/zh-cn/device-dev/subsystems/subsys-application-framework-builden.md new file mode 100644 index 0000000000..182aea265b --- /dev/null +++ b/zh-cn/device-dev/subsystems/subsys-application-framework-builden.md @@ -0,0 +1,7 @@ +# 搭建环境 + +- 开发板:Hi3516DV300 + +- [下载源码](../get-code/sourcecode-acquire.md) +- [编译用户程序框架](https://gitee.com/openharmony/docs/blob/master/zh-cn/readme/%E7%94%A8%E6%88%B7%E7%A8%8B%E5%BA%8F%E6%A1%86%E6%9E%B6%E5%AD%90%E7%B3%BB%E7%BB%9F.md) + diff --git "a/zh-cn/device-dev/subsystems/\345\274\200\345\217\221\345\256\236\344\276\213.md" b/zh-cn/device-dev/subsystems/subsys-application-framework-demo.md old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/subsystems/\345\274\200\345\217\221\345\256\236\344\276\213.md" rename to zh-cn/device-dev/subsystems/subsys-application-framework-demo.md diff --git a/zh-cn/device-dev/subsystems/subsys-application-framework-guide.md b/zh-cn/device-dev/subsystems/subsys-application-framework-guide.md new file mode 100644 index 0000000000..b132c23b93 --- /dev/null +++ b/zh-cn/device-dev/subsystems/subsys-application-framework-guide.md @@ -0,0 +1,711 @@ +# 开发指导 + +- [场景介绍](#section93012287133) +- [接口说明](#section11821047161319) +- [开发步骤](#section10514141679) + - [创建Service类型的Ability](#section19921154214315) + - [包管理接口使用指导](#section1724016743217) + - [Hap包打包](#section171771212328) + + +## 场景介绍 + +- 带界面的Ability的应用,比如:新闻类的应用、视频类的应用、导航类的应用、支付类的应用等等,目前我们看到的大部分应用都是带有界面的用于人机交互的应用。 + +- 不带界面的Ability应用,比如:音乐播放器能在后台播放音乐、后台提供计算服务、导航服务的各类应用等。 + +- 不管是带界面的Ability应用还是不带界面的Ability应用,都要打包成Hap包,最终发布到应用市场,用户通过应用市场下载安装相应的应用。 + +## 接口说明 + +**表 1** Ability子系统的对外接口 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    接口名称

    +

    接口描述

    +

    Want *WantParseUri(const char *uri)

    +

    反序列化接口,由字符串生成Want对象。

    +

    const char *WantToUri(Want want)

    +

    序列化,把Want对象生成字符串。

    +

    void SetWantElement(Want *want, ElementName element);

    +

    设置ElementName对象。

    +

    void SetWantData(Want *want, const void *data, uint16_t dataLength)

    +

    设置数据。

    +

    bool SetWantSvcIdentity(Want *want, SvcIdentity sid)

    +

    设置SvcIdentity。

    +

    void ClearWant(Want *want)

    +

    清除Want的内部内存数据。

    +

    void SetMainRoute(const std::string &entry)

    +

    设置AbilitySlice主路由。

    +

    void SetUIContent(RootView *rootView)

    +

    设置布局资源。

    +

    void OnStart(const Want& intent)

    +

    Ability生命周期状态回调,Ability启动时被回调。

    +

    void OnStop()

    +

    Ability生命周期状态回调,Ability销毁时被回调。

    +

    void OnActive(const Want& intent)

    +

    Ability生命周期状态回调,Ability显示时被回调。

    +

    void OnInactive()

    +

    Ability生命周期状态回调,Ability隐藏时被回调。

    +

    void OnBackground()

    +

    Ability生命周期状态回调,Ability退到后台时被回调。

    +

    const SvcIdentity *OnConnect(const Want &want)

    +

    Service类型Ability第一次连接时被回调。

    +

    void OnDisconnect(const Want &want);

    +

    Service类型Ability断开连接被回调。

    +

    void MsgHandle(uint32_t funcId, IpcIo *request, IpcIo *reply);

    +

    Service类型Ability接收消息处理。

    +

    void Dump(const std::string &extra)

    +

    dump Ability信息。

    +

    void Present(AbilitySlice *abilitySlice, const Want &want)

    +

    发起AbilitySlice跳转。

    +

    void Terminate()

    +

    退出当前AbilitySlice。

    +

    void SetUIContent(RootView *rootView)

    +

    设置当前AbilitySlice所在Ability的布局资源。

    +

    void OnStart(const Want& want)

    +

    AbilitySlice生命周期状态回调,AbilitySlice启动时被回调。

    +

    void OnStop()

    +

    AbilitySlice生命周期状态回调,AbilitySlice销毁时被回调。

    +

    void OnActive(const Want& want)

    +

    AbilitySlice生命周期状态回调,AbilitySlice显示时被回调。

    +

    void OnInactive()

    +

    AbilitySlice生命周期状态回调,AbilitySlice隐藏时被回调。

    +

    void OnBackground()

    +

    AbilitySlice生命周期状态回调,AbilitySlice退到后台时被回调。

    +

    int StartAbility(const Want &want)

    +

    启动Ability。

    +

    int StopAbility(const Want &want)

    +

    停止Service类型的Ability。

    +

    int TerminateAbility()

    +

    销毁当前的Ability。

    +

    int ConnectAbility(const Want &want, const IAbilityConnection &conn, void *data);

    +

    绑定Service类型的Ability。

    +

    int DisconnectAbility(const IAbilityConnection &conn)

    +

    解绑Service类型的Ability。

    +

    const char *GetBundleName()

    +

    获取当前ability的对应应用的包名。

    +

    const char *GetSrcPath()

    +

    获取当前ability的对应应用的安装路径。

    +

    const char *GetDataPath()

    +

    获取当前ability的对应应用的数据路径。

    +

    int StartAbility(const Want *want)

    +

    启动Ability,该接口可以不需要在基于Ability开发的应用中使用。

    +

    int ConnectAbility(const Want *want, const IAbilityConnection *conn, void *data);

    +

    绑定Service类型的Ability,该接口可以不需要在基于Ability开发的应用中使用。

    +

    int DisconnectAbility(const IAbilityConnection *conn);

    +

    解绑Service类型的Ability,该接口可以不需要在基于Ability开发的应用中使用。

    +

    int StopAbility(const Want *want)

    +

    停止Service类型的Ability,该接口可以不需要在基于Ability开发的应用中使用。

    +

    void (*OnAbilityConnectDone)(ElementName *elementName, SvcIdentity *serviceSid, int resultCode, void *data)

    +

    绑定Service Ability的回调。

    +

    void (*OnAbilityDisconnectDone)(ElementName *elementName, int resultCode, void *data)

    +

    解绑Service Ability的回调。

    +

    void PostTask(const Task& task)

    +

    投递任务到异步线程进行处理。

    +

    void PostQuit()

    +

    退出当前线程的消息循环。

    +

    static AbilityEventHandler* GetCurrentHandler()

    +

    获取当前线程的事件处理器。

    +

    void Run()

    +

    执行当前线程的消息循环。

    +

    #define REGISTER_AA(className)

    +

    注册开发者的Ability到框架中。

    +

    #define REGISTER_AS(className)

    +

    注册开发者的AbilitySlice到框架中。

    +
    + +## 开发步骤 + +### 创建Service类型的Ability + +1. 在my\_service\_ability.h中创建Ability的子类MyServiceAbility。 + + ``` + class MyServiceAbility: public Ability { + protected: + void OnStart(const Want& want); + const SvcIdentity *OnConnect(const Want &want) override; + void MsgHandle(uint32_t funcId, IpcIo *request, IpcIo *reply) override; + }; + ``` + +2. 调用REGISTER\_AA宏将ServiceAbility注册到应用框架中,以便应用框架实例化开发者的MyServiceAbility。 + + ``` + #include "my_service_ability.h" + + REGISTER_AA(ServiceAbility) + + void MyServiceAbility::OnStart(const Want& want) + { + printf("ServiceAbility::OnStart\n"); + Ability::OnStart(want); + } + + const SvcIdentity *MyServiceAbility::OnConnect(const Want &want) + { + printf("ServiceAbility::OnConnect\n"); + return Ability::OnConnect(want); + } + + void MyServiceAbility::MsgHandle(uint32_t funcId, IpcIo *request, IpcIo *reply) + { + printf("ServiceAbility::MsgHandle, funcId is %u\n", funcId); + int result = 0; + if (funcId == 0) { + result = IpcIoPopInt32(request) + IpcIoPopInt32(request); + } + // push data + IpcIoPushInt32(reply, result); + } + ``` + +3. 实现Service相关的生命周期方法。Service也是一种Ability,Ability为服务提供了以下生命周期方法,用户可以重写这些方法来添加自己的处理。用户在重写的方法里,需要调用父类对应的方法。 + - OnStart\(\) + + 该方法在创建Service的时候调用,用于做一些Service初始化且耗时较短的工作,在Service的整个生命周期只会调用一次。 + + ``` + void MyServiceAbility::OnStart(const Want& want) + { + printf("ServiceAbility::OnStart\n"); + Ability::OnStart(want); + } + ``` + + - OnConnect​\(\) + + 在组件和服务连接时调用,该方法返回SvcIdentity,组件可以通过它,与服务交互。 + + ``` + const SvcIdentity *MyServiceAbility::OnConnect(const Want &want) + { + printf("ServiceAbility::OnConnect\n"); + return Ability::OnConnect(want); + } + ``` + + - OnDisconnect​\(\) + + 在组件与绑定的Service断开连接时调用。 + + - OnStop\(\) + + 在Service销毁时调用。Service应通过实现此方法来清理任何资源,如关闭线程、注册的侦听器等。 + + +4. 重写消息处理方法。 + + MsgHandle是Service用来处理客户端消息的方法。其中funcId是客户端传过来的消息类型,request是客户端传过来的序列化请求参数。如果用户在处理完成之后想要把结果传回去,需要把结果序列化后写入reply中。 + + ``` + void ServiceAbility::MsgHandle(uint32_t funcId, IpcIo *request, IpcIo *reply) + { + printf("ServiceAbility::MsgHandle, funcId is %d\n", funcId); + int result = 0; + if (funcId == PLUS) { + result = IpcIoPopInt32(request) + IpcIoPopInt32(request); + } + // push data + IpcIoPushInt32(reply, result); + } + ``` + +5. 注册Service。 + + Service也需要在应用清单文件config.json中进行注册,注册类型type需要设置为service。 + + ``` + "abilities": [{ + "name": "ServiceAbility", + "icon": "res/drawable/phone.png", + "label": "test app 2", + "launchType": "standard", + "type": "service", + "visible": true + } + ] + ``` + +6. 启动Service。 + - Ability为用户提供了StartAbility\(\)方法来启动另外一个Ability,因为Service也是Ability的一种,开发者同样可以通过将Want传递给该方法来启动Service。 + + 开发者可以通过Want的SetWantElement \(\)来设置目标服务信息。ElementName结构体的两个主要参数:第一个参数为包名称;第二个参数为目标Ability。 + + ``` + { + Want want = { nullptr }; + ElementName element = { nullptr }; + SetElementBundleName(&element, "com.company.appname"); + SetElementAbilityName(&element, "ServiceAbility"); + SetWantElement(&want, element); + StartAbility(want); + ClearElement(&element); + ClearWant(&want); + } + ``` + + StartAbility\(\) 方法会立即执行,如果Service尚未运行,则系统首先会调用OnStart\(\)。 + + - 停止Service。 + + Service一旦创建就会一直保持在后台运行,开发者可以通过调用StopAbility\(\)来停止Service。 + + +7. 连接Service。 + - 如果Service需要与Page Ability或其他应用组件中的Service进行交互,则应创建用于连接的Service。Service支持其他Ability通过ConnectAbility\(\)与其进行连接,ConnectAbility\(\)需要传入目标Service的Want,以及IAbilityConnection的实例来处理回调。IAbilityConnection提供了两个方法供用户实现,OnAbilityConnectDone\(\)用来处理连接的回调,OnAbilityDisconnectDone\(\)用来处理断开连接的回调。 + + ``` + { + // ability创建IAbilityConnection对象和定义IAbilityConnection的两个方法实现 + IAbilityConnection abilityConnection = new IAbilityConnection(); + abilityConnection->OnAbilityConnectDone = OnAbilityConnectDone; + abilityConnection->OnAbilityDisconnectDone = OnAbilityDisconnectDone; + + void OnAbilityConnectDone(ElementName *elementName, SvcIdentity *serviceSid, + int resultCode, void *data) + { + if (resultCode != 0) { + return; + } + // push data + IpcIo request; + char dataBuffer[IPC_IO_DATA_MAX]; + IpcIoInit(&request, dataBuffer, IPC_IO_DATA_MAX, 0); + IpcIoPushInt32(&request, 10); + IpcIoPushInt32(&request, 6); + + // send and getReply + IpcIo reply; + uintptr_t ptr = 0; + if (Transact(nullptr, *serviceSid, 0, &request, &reply, + LITEIPC_FLAG_DEFAULT, &ptr) != LITEIPC_OK) { + printf("transact error\n"); + return; + } + int result = IpcIoPopInt32(&reply); + printf("execute add method, result is %d\n", result); + if (ptr != 0) { + FreeBuffer(nullptr, reinterpret_cast(ptr)); + } + } + + void OnAbilityDisconnectDone(ElementName *elementName, + int resultCode, void *data) + { + printf("elementName is %s, %s\n", + elementName->bundleName, elementName->abilityName); + } + } + ``` + + - 发起connect和disconnect。 + + ``` + { + // ability发起connect + Want want = { nullptr }; + ElementName element = { nullptr }; + SetElementBundleName(&element, "com.company.appname"); + SetElementAbilityName(&element, "ServiceAbility"); + SetWantElement(&want, element); + ConnectAbility(want, *abilityConnection, this); + + // ability发起disconnect + DisconnectAbility(*abilityConnection); + } + ``` + + + +### 包管理接口使用指导 + +**安装应用** + +安装接口只能给内置的系统应用使用。根据应用的安装路径,可以在安装应用时进行选择: + +- 将应用安装到系统默认的文件目录/storage/app/。 +- 将应用安装到系统外挂的存储介质中,例如micro sdcard。 + +这两种选择可以在创建InstallParam实例的时候指定,当InstallParam的成员变量installLocation为 INSTALL\_LOCATION\_INTERNAL\_ONLY时,意味着应用将会被安装到/storage/app/目录下;当InstallParam的成员变量installLocation为INSTALL\_LOCATION\_PREFER\_EXTERNAL时,意味着应用将被安装到存储介质,其安装目录是/sdcard/app/。由于安装应用的过程是异步的,所以需要使用类似信号量的机制来确保安装的回调可以被执行。 + +安装应用的步骤如下(示例代码以安装到系统目录为例): + +1. 将经过安全签名的应用放置于指定的目录下。 +2. 创建InstallParam实例和信号量。 + + ``` + InstallParam installParam = { + .installLocation = INSTALL_LOCATION_INTERNAL_ONLY, // 安装到系统目录 + .keepData = false + }; + static sem_t g_sem; + ``` + +3. 定义回调函数。 + + ``` + static void InstallCallback(const uint8_t resultCode, const void *resultMessage) + { + std::string strMessage = reinterpret_cast(resultMessage); + if (!strMessage.empty()) { + printf("install resultMessage is %s, %d\n", strMessage.c_str(),resultCode); + } + sem_post(&g_sem); + } + ``` + +4. 调用Install接口。 + + ``` + const uint32_t WAIT_TIMEOUT = 30; + sem_init(&g_sem, 0, 0); + std::string installPath = “/storage/bundle/demo.hap”; // hap包的存储路径 + bool result = Install(installPath.c_str(), &installParam, InstallCallback); + struct timespec ts = {}; + clock_gettime(CLOCK_REALTIME, &ts); + ts.tv_sec += WAIT_TIMEOUT; // 超时即释放信号量 + sem_timedwait(&g_sem, &ts); + ``` + + +**卸载应用** + +卸载应用的时候可以选择是否保留应用的数据,开发者可以通过创建的InstallParam实例的成员变量keepData来确定。当keepData为true, 卸载应用之后将保留应用的数据,当keepData为false时,卸载应用之后将不会保留应用的数据。 + +1. 创建InstallParam实例和信号量。 + + ``` + static sem_t g_sem; + InstallParam installParam = { + .installLocation = 1, + .keepData = false // 不保留应用数据 + }; + ``` + +2. 定义回调函数。 + + ``` + static void UninstallCallback(const uint8_t resultCode, const void *resultMessage) + { + std::string strMessage = reinterpret_cast(resultMessage); + if (!strMessage.empty()) { + printf("uninstall resultMessage is %s\n", strMessage.c_str()); + g_resultMessage = strMessage; + } + g_resultCode = resultCode; + sem_post(&g_sem); + } + ``` + +3. 调用Uninstall接口。 + + ``` + sem_init(&g_sem, 0, 0); + const uint32_t WAIT_TIMEOUT = 30; + std::string BUNDLE_NAME = “com.huawei.demo”; // 卸载应用的包名 + Uninstall(BUNDLE_NAME.c_str(), &installParam, UninstallCallback); + struct timespec ts = {}; + clock_gettime(CLOCK_REALTIME, &ts); + ts.tv_sec += WAIT_TIMEOUT; + sem_timedwait(&g_sem, &ts); + ``` + + +**查询已安装应用的包信息** + +开发者可以利用BundleManager提供的接口GetBundleInfo来查询系统内已安装应用的包信息。 + +1. 创建以及初始化BundleInfo。 + + ``` + BundleInfo bundleInfo; + (void) memset_s(&bundleInfo, sizeof(BundleInfo), 0, sizeof(BundleInfo)); + ``` + +2. 调用GetBundleInfo接口,指定查询应用的包名,同时指定flag来确定获取的BundleInfo中是否含有元能力信息(实例代码以含有元能力信息为例)。 + + ``` + std::string BUNDLE_NAME = "com.huawei.demo"; + uint8_t ret = GetBundleInfo(BUNDLE_NAME.c_str(), 1, &bundleInfo); // flags = 1,获取包信息中含有元能力信息 + ``` + +3. 使用完获取的BundleInfo之后,要及时清理掉其内部所占用的内存空间避免内存泄漏。 + + ``` + ClearBundleInfo(&bundleInfo); + ``` + + +### Hap包打包 + +打包工具一般集成到开发工具或者ide中,开发者一般不涉及直接使用该工具,下面的介绍开发者可以作为了解。打包工具的jar包在开源代码中的位置:developtools/packing\_tool/jar。 + +- 打包命令行参数 + + **表 2** 打包所需要的资源文件描述 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    命令参数

    +

    对应的资源文件

    +

    说明

    +

    是否可缺省

    +

    --mode

    +

    -

    +

    为“hap”字段,打包生成hap

    +

    +

    --json-path

    +

    清单文件config.json

    +

    -

    +

    +

    --resources-path

    +

    资源文件resources

    +

    -

    +

    +

    --assets-path

    +

    资源文件assets

    +

    -

    +

    +

    --lib-path

    +

    依赖库文件

    +

    -

    +

    +

    --shared-libs-path

    +

    共享库文件

    +

    针对系统应用的共享库,特殊情况下使用

    +

    +

    --ability-so-path

    +

    主功能so文件

    +

    -

    +

    +

    --index-path

    +

    资源索引

    +

    资源索引文件由资源生成工具生成,由资源流水线会集成该工具

    +

    +

    --out-path

    +

    -

    +

    生成的hap包输出路径,默认为当前目录

    +

    +

    --force

    +

    -

    +

    是否覆盖原有同名文件,默认为false

    +

    +
    + +- 打包示例 + - 开发视图 + + ![](figure/zh-cn_image_0000001062942690.png) + + - 编译视图 + + ![](figure/zh-cn_image_0000001062334618.png) + + - 使用打包工具执行以下命令打包: + + ![](figure/zh-cn_image_0000001062476933.png) + + ``` + $ java -jar hmos_app_packing_tool.jar --mode hap --json-path ./config.json --assets-path ./assets/ --ability-so-path ./libentry.so --index-path ./resources.index --out-path out/entry.hap --force true + ``` + + + diff --git a/zh-cn/device-dev/subsystems/subsys-application-framework-overview.md b/zh-cn/device-dev/subsystems/subsys-application-framework-overview.md new file mode 100644 index 0000000000..a0ab8c2d1b --- /dev/null +++ b/zh-cn/device-dev/subsystems/subsys-application-framework-overview.md @@ -0,0 +1,141 @@ +# 概述 + +- [基本概念](#section72601941194812) +- [Ability子系统](#section14633111813374) +- [包管理子系统](#section1341146154412) +- [运作机制](#section94302021112717) +- [约束与限制](#section89534912527) + +用户程序框架是OpenHarmony为开发者提供开发OpenHarmony应用的开发框架,包含两个模块:Ability子系统和包管理子系统。 + +## 基本概念 + +开发者在开发前需要先了解以下基本概念,方便开发者更好的理解OpenHarmony用户程序框架。 + +## Ability子系统 + +Ability子系统是管理OpenHarmony应用运行状态的开发框架。 + +**图 1** Ability子系统框架图 +![](figure/Ability子系统框架图.png "Ability子系统框架图") + +- **Ability**:系统调度应用的最小单元,是能够完成一个独立功能的组件,一个应用可以包含一个或多个Ability。Ability分为两种类型:Page类型的Ability和Service类型的Ability。 + - **Page类型的Ability**:带有界面,为用户提供人机交互的能力。 + + - **Service类型的Ability**:不带界面,为用户提供后台任务机制。 + + + +- **AbilitySlice**:单个页面及其控制逻辑的总和,是Page类型Ability特有的组件,一个Page类型的Ability可以包含多个AbilitySlice,此时,这些页面提供的业务能力应当是高度相关的。 + + **图 2** Ability与AbilitySlice的关系图 + ![](figure/Ability与AbilitySlice的关系图.png "Ability与AbilitySlice的关系图") + +- **生命周期**:Ability被调度到启动、激活、隐藏和退出等各个状态的统称。 + + **图 3** Ability生命周期流转 + + + ![](figure/图片1.png) + + - **OnStart\(\)** + + 系统首次创建Page实例时触发该回调。对于一个Page实例,该回调在其生命周期过程中仅触发一次,Page在该逻辑后进入INACTIVE状态。开发者必须重写该方法,并在此配置默认展示的AbilitySlice。 + + - **OnActive\(\)** + + Page会在进入INACTIVE状态后来到前台,然后系统调用此回调。Page在此之后进入ACTIVE状态,该状态是应用与用户交互的状态。Page将保持在此状态,除非某类事件发生导致Page失去焦点,比如用户点击返回键或导航到其他Page。 + + 当此类事件发生时,会触发Page回到INACTIVE状态,系统将调用OnInactive\(\)回调。此后,Page可能重新回到ACTIVE状态,系统将再次调用OnActive\(\)回调。因此,开发者通常需要成对实现OnActive\(\)和OnInactive\(\),并在OnActive\(\)中获取在OnInactive\(\)中被释放的资源。 + + - **OnInactive\(\)** + + 当Page失去焦点时,系统将调用此回调,此后Page进入INACTIVE状态。开发者可以在此回调中实现Page失去焦点时应表现的恰当行为。 + + - **OnBackground\(\)** + + 如果Page不再对用户可见,系统将可能根据资源状况调用此回调,此后Page进入BACKGROUND状态。开发者应该在此回调中释放Page不可见时无用的资源,或在此回调中执行较为耗时的状态保存操作。 + + - **OnForeground\(\)** + + 处于BACKGROUND状态的Page仍然驻留在内存中,当重新回到前台时(比如用户重新导航到此Page),系统将先调用OnForeground\(\)回调使Page回到INACTIVE状态,然后调用OnActive\(\)回调使Page回到ACTIVE状态。开发者应当在此回调中重新申请在OnBackground\(\)中释放的资源。轻量化设备目前不支持该接口。 + + - **OnStop\(\)** + + 此回调表示系统正在销毁Page。销毁Page的可能原因包括: + + - 用户通过系统管理能力显式关闭Page,例如使用任务管理器关闭Page。 + - 用户行为触发Page的TerminateAbility\(\)方法调用,例如使用应用的退出功能。 + - 配置变更导致系统暂时销毁Page并重建。 + - 系统出于资源管理目的,自动触发对处于BACKGROUND状态Page的销毁。 + + +- **AbilityKit**:Ability框架提供给开发者的开发包,开发者基于该开发包可以开发出基于Ability组件的应用。基于Ability组件开发的应用有两种类型:基于Javascript语言开发的Ability(JS Ability)和基于C/C++语言开发的Ability(Native Ability)。JS应用开发框架是开发者开发JS Ability所用到框架,是在AbilityKit基础封装的包含js UI组件的一套方便开发者能够迅速开发Ability应用的框架。 +- **AbilityLoader**:负责注册和加载开发者Ability的模块。开发者开发的Ability先要调用AbilityLoader的注册接口注册到框架中,接着Ability启动时会被实例化。 + +- **AbilityManager:**负责AbilityKit和Ability管理服务进行IPC的通信。 + +- **EventHandler**:AbilityKit提供给开发者的用于在Ability中实现线程间通信的一个模块。 + +- **AbilityManagerService**:元能力运行管理服务。该服务用于协调各Ability运行关系、及生命周期进行调度的系统服务。其中,服务启动模块负责Ability管理服务的启动、注册等。服务接口管理模块负责Ability管理服务对外能力的管理。进程管理模块负责Ability应用所在进程的启动和销毁、及其进程信息维护等功能。Ability栈管理模块负责维护各个Ability之间跳转的先后关系。生命周期调度模块是Ability管理服务根据系统当前的操作调度Ability进入相应的状态的模块。连接管理模块是Ability管理服务对Service类型Ability连接管理的模块 + +- **AppSpawn**:负责创建Ability应用所在进程的系统服务,该服务有较高的权限,为Ability应用设置相应的权限,并预加载一些通用的模块,加速应用的启动。 + + +## 包管理子系统 + +包管理子系统是OpenHarmony为开发者提供的安装包管理框架。 + +**图 4** 包管理子系统框架图 +![](figure/包管理子系统框架图.png "包管理子系统框架图") + +- **BundleKit**:是包管理服务对外提供的接口,有安装/卸载接口、包信息查询接口、包状态变化listen接口。 +- **包扫描器**:用来解析本地预制或者安装的安装包,提取里面的各种信息,供管理子模块进行管理,持久化。 +- **包安装子模块**:安装,卸载,升级一个包;包安装服务是一个单独进程和包管理服务通过IPC进行通信,该服务用于创建、删除安装目录和数据目录等,具有较高的权限。 + +- **包管理子模块**:管理安装包相关的信息,存储持久化包信息。 + +- **包安全管理子模块**:签名检查、权限授予、权限管理。 + + +## 运作机制 + +Ability子系统的核心模块是Ability管理服务、包管理子系统的核心模块是包管理服务,这两个服务是系统级服务,借助系统服务框架Samgr实现服务的注册与发现,并对其他进程提供Ability管理服务和包管理服务。Ability管理服务和包管理服务通过AbilityKit和BundleKit以接口的形式向外提供服务。 + +**图 5** Ability管理服务和包管理服务启动 +![](figure/Ability管理服务和包管理服务启动.png "Ability管理服务和包管理服务启动") + +Ability管理服务和包管理服务启动后,就可以安装OpenHarmony应用和启动运行OpenHarmony应用。 + +**图 6** 应用启动流程 +![](figure/应用启动流程.png "应用启动流程") + +桌面为Ability管理服务启动的第一个OpenHarmony应用。桌面启动后,用户可以在桌面上点击安装的OpenHarmony应用并启动该应用。上图6为从桌面启动一个已安装应用的交互流程。 + +从图中可知,Ability管理服务负责协调Ability之间的显示隐藏,包管理服务负责Ability信息的存储查询。 + +## 约束与限制 + +- 语言版本 + + - C++11版本或以上 + + +- 框架针对不同的芯片平台和底层OS能力,规格有所区别 + + - Cortex-M RAM/ROM: + + - RAM:建议大于20K + + - ROM: \> 300K (包含JS应用开发框架,UIKit及引擎等强相关子系统) + + + - Cortex-A RAM/ROM: + + - RAM:建议大于2M + + - ROM:\> 2M (包含JS应用开发框架,UIKit及引擎等强相关子系统) + + + + diff --git a/zh-cn/device-dev/subsystems/subsys-application-framework.md b/zh-cn/device-dev/subsystems/subsys-application-framework.md new file mode 100644 index 0000000000..99997047ff --- /dev/null +++ b/zh-cn/device-dev/subsystems/subsys-application-framework.md @@ -0,0 +1,11 @@ +# 用户程序框架 + +- **[概述](subsys-application-framework-overview.md)** + +- **[搭建环境](subsys-application-framework-builden.md)** + +- **[开发指导](subsys-application-framework-guide.md)** + +- **[开发实例](subsys-application-framework-demo.md)** + + diff --git "a/zh-cn/device-dev/subsystems/appspawn\345\272\224\347\224\250\345\255\265\345\214\226\347\273\204\344\273\266.md" b/zh-cn/device-dev/subsystems/subsys-boot-appspawn.md old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/subsystems/appspawn\345\272\224\347\224\250\345\255\265\345\214\226\347\273\204\344\273\266.md" rename to zh-cn/device-dev/subsystems/subsys-boot-appspawn.md diff --git "a/zh-cn/device-dev/subsystems/bootstrap\346\234\215\345\212\241\345\220\257\345\212\250\347\273\204\344\273\266.md" b/zh-cn/device-dev/subsystems/subsys-boot-bootstrap.md old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/subsystems/bootstrap\346\234\215\345\212\241\345\220\257\345\212\250\347\273\204\344\273\266.md" rename to zh-cn/device-dev/subsystems/subsys-boot-bootstrap.md diff --git a/zh-cn/device-dev/subsystems/subsys-boot-faqs.md b/zh-cn/device-dev/subsystems/subsys-boot-faqs.md new file mode 100644 index 0000000000..196a586630 --- /dev/null +++ b/zh-cn/device-dev/subsystems/subsys-boot-faqs.md @@ -0,0 +1,56 @@ +# 常见问题 + +- [系统启动过程中打印“parse failed!”错误后停止启动](#section2041345718513) +- [系统启动过程未结束就自动重启,如此反复持续](#section57381816168) +- [参数正确的情况下调用SetParameter/GetParameter返回失败](#section129991227141512) + +## 系统启动过程中打印“parse failed!”错误后停止启动 + +**现象描述** + +系统启动过程中,打印“\[Init\] InitReadCfg, parse failed! please check file /etc/init.cfg format.”错误,启动过程停止,如下图所示: + +![](figure/zh-cn_image_0000001063839940.png) + +**可能原因** + +修改init.cfg文件时,漏掉或多加了逗号或括号等,导致init.cfg文件的json格式被破坏。 + +**解决办法** + +仔细检查init.cfg文件,确保其格式符合json格式要求。 + +## 系统启动过程未结束就自动重启,如此反复持续 + +**现象描述** + +镜像烧写完成后系统启动,启动过程未完成即自动重新启动,如此反复持续。 + +**可能原因** + +被init启动的服务都有一个叫做“importance”的属性(详见[第2章表3](subsys-boot-init.md#table14737791471)描述)。 + +- 当该属性为0时,表示若当前服务进程退出,init不需要重启单板。 +- 当该属性为1时,表示若当前服务进程退出,init需要重启单板。 + +因此出现上述现象的可能原因:有“importance”属性为1的服务在每次启动的过程中都会退出(可能是进程崩溃或出错自动退出),导致init进程自动重启单板。 + +**解决办法** + +1. 需要通过日志确认崩溃或报错退出的服务,并解决其崩溃/报错的问题,然后重新烧写镜像即可。 +2. 也可以将崩溃/报错退出的服务的“importance”属性改为0,然后重新烧写镜像,这样即使其退出,init也不会重启单板。 + +## 参数正确的情况下调用SetParameter/GetParameter返回失败 + +**现象描述** + +在各参数正确的情况下调用SetParameter/GetParameter返回失败。 + +**可能原因** + +程序对SetParameter/GetParameter这两个接口做了权限校验,在各参数正确的情况下调用SetParameter/GetParameter返回操作失败,很有可能是调用者的uid大于1000,没有调用权限。 + +**解决办法** + +无需处理 + diff --git "a/zh-cn/device-dev/subsystems/init\345\220\257\345\212\250\345\274\225\345\257\274\347\273\204\344\273\266.md" b/zh-cn/device-dev/subsystems/subsys-boot-init.md old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/subsystems/init\345\220\257\345\212\250\345\274\225\345\257\274\347\273\204\344\273\266.md" rename to zh-cn/device-dev/subsystems/subsys-boot-init.md diff --git a/zh-cn/device-dev/subsystems/subsys-boot-overview.md b/zh-cn/device-dev/subsystems/subsys-boot-overview.md new file mode 100644 index 0000000000..ee24488c41 --- /dev/null +++ b/zh-cn/device-dev/subsystems/subsys-boot-overview.md @@ -0,0 +1,66 @@ +# 启动恢复子系统概述 + +- [约束与限制](#section2029921310472) + +启动恢复子系统负责从内核启动之后到应用启动之前的系统关键服务进程的启动过程以及设备恢复出厂设置的功能。涉及以下组件: + +- init启动引导组件 + + init启动引导组件对应的进程为init进程,是内核完成初始化后启动的第一个用户态进程。init进程启动之后,读取init.cfg配置文件,根据解析结果,执行相应命令(见[第2章表2](subsys-boot-init.md#table122681439144112)描述)并依次启动各关键系统服务进程,在启动系统服务进程的同时设置其对应权限。 + +- appspawn应用孵化组件 + + 负责接收**用户程序框架**的命令孵化应用进程,设置新进程的权限,并调用应用程序框架的入口函数。 + +- bootstrap服务启动组件 + + 提供了各服务和功能的启动入口标识。在SAMGR启动时,会调用boostrap标识的入口函数,并启动系统服务。 + +- syspara系统属性组件 + + 系统属性组件,根据OpenHarmony产品兼容性规范提供获取设备信息的接口,如:产品名、品牌名、厂家名等,同时提供设置/读取系统属性的接口。 + + +## 约束与限制 + +启动恢复子系统源代码目录和适配平台: + +**表 1** 启动恢复子系统源代码目录和适配平台 + + + + + + + + + + + + + + + + + + + +

    名称

    +

    适配平台

    +

    base/startup/appspawn_lite

    +

    小型系统设备(参考内存≥1MB),如Hi3516DV300 、Hi3518EV300

    +

    base/startup/bootstrap_lite

    +

    轻量系统设备(参考内存≥128KB),如Hi3861V100

    +

    base/startup/init_lite

    +

    小型系统设备(参考内存≥1MB),如Hi3516DV300、Hi3518EV300

    +

    base/startup/syspara_lite

    +
    • 轻量系统设备(参考内存≥128KB),如Hi3861V100
    • 小型系统设备(参考内存≥1MB),如Hi3516DV300、Hi3518EV300
    +
    + +- init启动引导组件: + - 配置文件init.cfg烧写到单板之后变成只读模式,修改时必须重新打包和烧写rootfs镜像。 + - 配置文件init.cfg仅支持json格式。 + +- bootstrap服务启动组件:需要在链接脚本中配置zInit代码段。 +- syspara系统属性组件:SetParameter/GetParameter仅支持uid大于1000的应用调用。 + diff --git "a/zh-cn/device-dev/subsystems/\345\217\202\350\200\203.md" b/zh-cn/device-dev/subsystems/subsys-boot-ref.md old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/subsystems/\345\217\202\350\200\203.md" rename to zh-cn/device-dev/subsystems/subsys-boot-ref.md diff --git "a/zh-cn/device-dev/subsystems/syspara\347\263\273\347\273\237\345\261\236\346\200\247\347\273\204\344\273\266.md" b/zh-cn/device-dev/subsystems/subsys-boot-syspara.md old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/subsystems/syspara\347\263\273\347\273\237\345\261\236\346\200\247\347\273\204\344\273\266.md" rename to zh-cn/device-dev/subsystems/subsys-boot-syspara.md diff --git a/zh-cn/device-dev/subsystems/subsys-boot.md b/zh-cn/device-dev/subsystems/subsys-boot.md new file mode 100644 index 0000000000..a71c6ab862 --- /dev/null +++ b/zh-cn/device-dev/subsystems/subsys-boot.md @@ -0,0 +1,17 @@ +# 启动恢复 + +- **[启动恢复子系统概述](subsys-boot-overview.md)** + +- **[init启动引导组件](subsys-boot-init.md)** + +- **[appspawn应用孵化组件](subsys-boot-appspawn.md)** + +- **[bootstrap服务启动组件](subsys-boot-bootstrap.md)** + +- **[syspara系统属性组件](subsys-boot-syspara.md)** + +- **[常见问题](subsys-boot-faqs.md)** + +- **[参考](subsys-boot-ref.md)** + + diff --git a/zh-cn/device-dev/subsystems/subsys-build-mini-lite.md b/zh-cn/device-dev/subsystems/subsys-build-mini-lite.md new file mode 100644 index 0000000000..dc07da91d5 --- /dev/null +++ b/zh-cn/device-dev/subsystems/subsys-build-mini-lite.md @@ -0,0 +1,996 @@ +# 轻量和小型系统编译构建指导 + +- [概述](#section10958256161119) + - [基本概念](#section1732301411128) + - [目录结构](#section1588744014121) + - [构建流程](#section15761735134) + +- [配置规则](#section2345183962710) + - [组件](#section142532518308) + - [芯片解决方案](#section121501451143710) + - [产品解决方案](#section134549283435) + +- [使用指导](#section13754457192211) + - [前提条件](#section31651120233) + - [hb工具使用说明](#section1133304172313) + - [新增组件](#section167110415315) + - [新增芯片解决方案](#section1474718565412) + - [新增产品解决方案](#section1097623294220) + +- [常见问题](#section19909721104319) + - [ninja版本问题导致编译失败](#section138233464318) + - [ncurses库缺失导致编译失败](#section151033911442) + - [未安装mcopy导致编译失败](#section19811838104418) + - [权限问题导致编译失败](#section03111118451) + - [未安装Crypto导致编译失败](#section69981127125013) + - [编译环境为shell导致编译失败](#section967617530505) + + +## 概述 + +一个基于gn和ninja的构建系统,以支持OpenHarmony组件化开发为目标,提供以下基本功能: + +- 支持按组件拼装产品并编译。 + +- 独立构建芯片解决方案厂商源码。 +- 独立构建单个组件。 + +### 基本概念 + +在使用编译构建子系统前,应了解如下基本概念: + +- 子系统 + + 子系统是一个逻辑概念,它由一个或多个具体的组件组成。OpenHarmony整体遵从分层设计,从下向上依次为:内核层、系统服务层、框架层和应用层。系统功能按照“系统 \> 子系统 \> 组件”逐级展开,在多设备部署场景下,支持根据实际需求裁剪某些非必要的子系统或组件。 + + +- 组件 + + 系统最小的可复用、可配置、可裁剪的功能单元。组件具备目录独立可并行开发、可独立编译、可独立测试的特征。 + +- gn + + Generate ninja的缩写,用于产生ninja文件。 + +- ninja + + ninja是一个专注于速度的小型构建系统。 + +- hb + + OpenHarmony的命令行工具,用来执行编译命令。 + + +### 目录结构 + +``` +build/lite +├── components # 组件描述文件 +├── figures # readme中的图片 +├── hb # hb pip安装包源码 +├── make_rootfs # 文件系统镜像制作脚本 +├── config # 编译配置项 +│ ├── component # 组件相关的模板定义 +│ ├── kernel # 内核相关的编译配置 +│ └── subsystem # 子系统编译配置 +├── platform # ld脚本 +├── testfwk # 测试编译框架 +└── toolchain # 编译工具链配置,包括:编译器路径、编译选项、链接选项等 +``` + +### 构建流程 + +编译构建流程如[图1 ](#fig9744112715161)所示,主要分设置和编译两步: + +**图 1** 编译构建流程 +![](figure/编译构建流程.jpg "编译构建流程") + +1. hb set: 设置OpenHarmony源码目录和要编译的产品。 +2. hb build: 编译产品、开发板或者组件。编译主要过程如下: + - 读取编译配置:根据产品选择的开发板,读取开发板config.gni文件内容,主要包括编译工具链、编译链接命令和选项等。 + - 调用gn:调用gn gen命令,读取产品配置生成产品解决方案out目录和ninja文件。 + - 调用ninja:调用ninja -C out/board/product启动编译。 + - 系统镜像打包:将组件编译产物打包,设置文件属性和权限,制作文件系统镜像。 + + +## 配置规则 + +为了实现芯片解决方案、产品解决方案与OpenHarmony是解耦的、可插拔的,组件、芯片解决方案和产品解决方案的路径、目录树和配置需遵循一定的规则,具体如下: + +### **组件** + +组件源码路径命名规则为:**\{领域\}/\{子系统\}/\{组件\}**,组件目录树规则如下: + +>![](../public_sys-resources/icon-caution.gif) **注意:** +>组件的名称、源码路径、功能简介、是否必选、编译目标、RAM、ROM、编译输出、已适配的内核、可配置的特性和依赖等属性定义在build/lite/components目录下对应子系统的json文件中,新增组件时需要在对应子系统json文件中添加相应的组件定义。产品所配置的组件必须在某个子系统中被定义过,否则会校验失败。 + +``` +component +├── interfaces +│ ├── innerkits # 系统内接口,组件间使用 +│ └── kits # 应用接口,应用开发者使用 +├── frameworks # framework实现 +├── services # service实现 +└── BUILD.gn # 组件编译脚本 +``` + +以泛sensor子系统的sensor服务组件为例,组件属性定义描述文件字段说明如下: + +``` +{ + "components": [ + { + "component": "sensor_lite", # 组件名称 + "description": "Sensor services", # 组件一句话功能描述 + "optional": "true", # 组件是否为最小系统必选 + "dirs": [ # 组件源码路径 + "base/sensors/sensor_lite" + ], + "targets": [ # 组件编译入口 + "//base/sensors/sensor_lite/services:sensor_service" + ], + "rom": "92KB", # 组件ROM值 + "ram": "~200KB", # 组件RAM估值 + "output": [ "libsensor_frameworks.so" ], # 组件编译输出 + "adapted_kernel": [ "liteos_a" ], # 组件已适配的内核 + "features": [], # 组件可配置的特性 + "deps": { + "components": [ # 组件依赖的其他组件 + "samgr_lite", + "ipc_lite" + + ], + "third_party": [ # 组件依赖的三方开源软件 + "bounds_checking_function" + ] + } + } + ] +} +``` + +组件BUILD.gn的编写建议如下: + +- 编译目标名称与组件一致。 +- 组件对外可配置的特性变量需声明在该组件BUILD.gn中,特性变量命名规则:ohos\_\{subsystem\}\_\{component\}\_\{feature\}。特性在组件描述中也需要同步定义,在产品配置文件config.json中按需配置。 +- 宏定义规则:OHOS\_\{SUBSYSTEM\}\_\{COMPONENT\}\_\{FEATURE\} + + >![](../public_sys-resources/icon-note.gif) **说明:** + >组件的编译脚本语言为gn,gn的基本用法请见[gn快速入门](https://gn.googlesource.com/gn/+/master/docs/quick_start.md)。组件即为gn定义的编译目标,可以为静态库、动态库、可执行文件或group。 + + +以图形的UI组件为例,foundation/graphic/ui/BUILD.gn文件如下: + +``` + # 声明组件可配置的特性 + declare_args() { + enable_ohos_graphic_ui_animator = false # 动效特性开关 + ohos_ohos_graphic_ui_font = "vector" # 可配置的字体类型,vector或者bitmap + } + + # 组件基础功能 + shared_library("base") { + sources = [ + ...... + ] + include_dirs = [ + ...... + ] + } + + # 仅在animator开启时编译 + if(enable_ohos_graphic_ui_animator ) { + shared_library("animator") { + sources = [ + ...... + ] + include_dirs = [ + ...... + ] + deps = [ :base ] + } + } + ...... + # target名称建议与组件名称一致, 组件target类型可以是executable(bin文件),shared_library(动态库.so),static_library(静态库.a),group等等 + executable("ui") { + deps = [ + ":base" + ] + + # animator特性由产品配置 + if(enable_ohos_graphic_ui_animator ) { + deps += [ + "animator" + ] + } + } +``` + +### **芯片解决方案** + +- 芯片解决方案是指基于某款开发板的完整解决方案,包含驱动、设备侧接口适配、开发板sdk等。 +- 芯片解决方案是一个特殊的组件,源码路径规则为:**device/\{芯片解决方案厂商\}/\{开发板\}**。 +- 芯片解决方案组件会随产品选择的开发板默认编译。 + +芯片解决方案目录树规则如下: + +``` +device +└── company # 芯片解决方案厂商 + └── board # 开发板名称 + ├── BUILD.gn # 编译脚本 + ├── hals # OS南向接口适配 + ├── linux # 可选,linux内核版本 + │ └── config.gni # linux版本编译配置 + └── liteos_a # 可选,liteos内核版本 + └── config.gni # liteos_a版本编译配置 +``` + +>![](../public_sys-resources/icon-note.gif) **说明:** +>config.gni为开发板编译相关的配置,编译时会采用该配置文件中的参数编译所有OS组件,编译阶段系统全局可见。 + +config.gni的关键字段介绍如下: + +``` +kernel_type: 开发板使用的内核类型,例如:“liteos_a”, “liteos_m”, “linux”。 +kernel_version: 开发使用的内核版本,例如:“4.19”。 +board_cpu: 开发板CPU类型,例如:“cortex-a7”, “riscv32”。 +board_arch: 开发芯片arch, 例如: “armv7-a”, “rv32imac”。 +board_toolchain: 开发板自定义的编译工具链名称,例如:“gcc-arm-none-eabi”。若为空,则使用默认为ohos-clang。 +board_toolchain_prefix:编译工具链前缀,例如:“gcc-arm-none-eabi”。 +board_toolchain_type: 编译工具链类型,目前支持gcc和clang。例如:“gcc” ,“clang”。 +board_cflags: 开发板配置的c文件编译选项。 +board_cxx_flags: 开发板配置的cpp文件编译选项。 +board_ld_flags: 开发板配置的链接选项。 +``` + +### **产品解决方案** + +产品解决方案为基于开发板的完整产品,主要包含产品对OS的适配、组件拼装配置、启动配置和文件系统配置等。产品解决方案的源码路径规则为:**vendor/\{产品解决方案厂商\}/\{产品名称\}**_。_产品解决方案也是一个特殊的组件。 + +产品解决方案的目录树规则如下: + +``` +vendor +└── company # 产品解决方案厂商 + ├── product # 产品名称 + │ ├── init_configs + │ │ ├── etc # init进程启动配置(可选,仅linux内核需要) + │ │ └── init.cfg # 系统服务启动配置 + │ ├── hals # 产品解决方案OS适配 + │ ├── BUILD.gn # 产品编译脚本 + │ └── config.json # 产品配置文件 + │ └── fs.yml # 文件系统打包配置 + └── ...... +``` + +>![](../public_sys-resources/icon-caution.gif) **注意:** +>**新增产品须按如上的规则创建目录和文件,编译构建系统将按该规则扫描已配置的产品。** + +关键的目录和文件详细介绍如下: + +1. **vendor/company/product/init\_configs/etc** + + 该文件夹中包含rcS脚本,Sxxx脚本和fstab脚本。init进程在启动系统服务之前执行这些脚本。执行的流程为“rcS-\>fstab-\>S00-xxx“。Sxxx脚本中的内容与开发板和产品需要有关,主要包括设备节点的创建、创建目录、扫描设备节点、修改文件权限等等。这些文件在产品编译的BUILD.gn中按需拷贝到产品out目录中,最终打包到rootfs镜像中。 + +2. **vendor/company/product/init\_configs/init.cfg** + + init进程启动服务的配置文件,当前支持解析的命令有: + + - start: 启动某个服务 + - mkdir: 创建文件夹 + - chmod: 修改指定路径/文件的权限 + - chown: 修改指定路径/文件的属组 + - mount: 挂载命令 + + 该文件中的各个字段的解释如下: + + ``` + { + "jobs" : [{ # job数组,一个job对应一个命令集合。job的执行顺序:pre-init -> init -> post-init。 + "name" : "pre-init", + "cmds" : [ + "mkdir /storage/data", # 创建目录 + "chmod 0755 /storage/data", # 修改权限,权限值的格式为0xxx, 如0755 + "mkdir /storage/data/log", + "chmod 0755 /storage/data/log", + "chown 4 4 /storage/data/log", # 修改属组,第一个数字为uid, 第二个数字为gid + ...... + "mount vfat /dev/mmcblock0 /sdcard rw,umask=000" # 挂载,格式为: mount [文件系统类型] [source] [target] [flags] [data] + # 其中flags仅支持:nodev、noexec、nosuid和rdonly + ] + }, { + "name" : "init", + "cmds" : [ # 按cmds数组顺序启动启动服务 + "start shell", # 注意:start与服务名称之间有且只有一个空格 + ...... + "start service1" + ] + }, { + "name" : "post-init", # 最后执行的job, init进程启动完成后的处理(如驱动初始化后再mount设备) + "cmds" : [] + } + ], + "services" : [{ # service数组,一个service对应一个进程 + "name" : "shell", # 服务名称 + "path" : ["/sbin/getty", "-n", "-l", "/bin/sh", "-L", "115200", "ttyS000", "vt100"], # 可执行文件全路径,path必须为第一个元素 + "uid" : 0, # 进程的uid,须与二进制文件的uid保持一致 + "gid" : 0, # 进程的gid,须与二进制文件的gid保持一致 + "once" : 0, # 是否为一次性进程,1:进程退出后,init不在重新拉起。0:常驻进程,进程若退出,init将重新拉起 + "importance" : 0, # 是否为关键进程,1:是关键进程,若进程退出,init将会重启单板。0:非关键进程,若进程退出,init不会重启单板 + "caps" : [4294967295] + }, + ...... + ] + } + ``` + +3. **vendor/company/product/init\_configs/hals** + + 解决方案厂商对OS的适配,需要实现的接口请见各个组件的readme说明文档。 + +4. **vendor/company/product/config.json** + + config.json为编译构建的主入口,包含了开发板、OS组件和内核等配置信息。 + + 以基于hispark\_taurus开发板的ipcamera产品为例,配置文件如下: + + ``` + { + "product_name": "ipcamera", # 产品名称 + "ohos_version": "OpenHarmony 1.0", # 选择的OS版本 + "device_company": "hisilicon", # 芯片厂商 + "board": "hispark_taurus", # 开发板名称 + "kernel_type": "liteos_a", # 选择的内核类型 + "kernel_version": "3.0.0", # 选择的内核版本 + "subsystems": [ + { + "subsystem": "aafwk", # 选择的子系统 + "components": [ + { "component": "ability", "features":[ "enable_ohos_appexecfwk_feature_ability = true" ] } # 选择的组件和组件特性配置 + ] + }, + { + ...... + } + ...... + 更多子系统和组件 + } + } + ``` + +5. **vendor/company/product/fs.yml** + + 该文件用于配置文件系统镜像制作过程,将编译产物打包成文件系统镜像,比如用户态根文件系统rootfs.img和可读写的userfs.img。它由多个列表组成,每个列表对应一个文件系统。字段说明如下: + + ``` + fs_dir_name: 必填,声明文件系统文件名, 如rootfs、userfs + fs_dirs: 选填,配置out下文件目录与文件系统文件目录的映射关系,每个文件目录对应一个列表 + source_dir: 选填,out下目标文件目录,若缺失则将根据target_dir在文件系统下创建空目录 + target_dir: 必填,文件系统下对应文件目录 + ignore_files:选填,声明拷贝忽略文件 + dir_mode: 选填,文件目录权限,默认755 + file_mode: 选填,该文件目录下所有文件的权限,默认555 + fs_filemode: 选填,配置需要特殊声明权限的文件,每个文件对应一个列表 + file_dir: 必填,文件系统下具体文件路径 + file_mode: 必填,文件权限声明 + fs_symlink: 选填,配置文件系统软连接 + fs_make_cmd: 必填,配置需要制作文件系统脚本,OS提供的脚本在build/lite/make_rootfs下, 支持linux,liteos内核和ext4、jffs2、vfat格式。也支持芯片解决方案厂商自定义。 + fs_attr: 选填,根据配置项动态调整文件系统 + ``` + + 其中fs\_symlink、fs\_make\_cmd字段支持以下变量: + + - $\{root\_path\} + + 代码根目录,对应gn的$\{ohos\_root\_path\} + + - $\{out\_path\} + + 产品out目录,对应gn的$\{root\_out\_dir\} + + - $\{fs\_dir\} + + 文件系统目录,由以下变量拼接而成 + + - $\{root\_path\} + - $\{fs\_dir\_name\} + + + >![](../public_sys-resources/icon-note.gif) **说明:** + >fs.yml是可选的,对于没有文件系统的设备可不配置。 + +6. **vendor/company/product/BUILD.gn** + + 产品编译的入口,主要用于编译解决方案厂商源码和拷贝启动配置文件。如果某个产品被选择为要编译的产品,那么对应产品目录下的BUILD.gn会默认编译。一个典型的产品编译BUILD.gn应该如下: + + ``` + group("product") { # target名称需与product名称即三级目录名称一致 + deps = [] + # 拷贝init配置 + deps += [ "init_configs" ] + # 其他 + ...... + } + ``` + + +## 使用指导 + +### 前提条件 + +开发环境需安装gn、ninja构建工具、python 3.7.4及以上和hb。安装方法请见[搭建系统基础环境](../quick-start/quickstart-lite-env-setup.md)。 + +### hb工具使用说明 + +hb是OpenHarmony的命令行工具,用来执行编译命令。以下对hb的常用命令进行说明。 + +**hb set** + +``` +hb set -h +usage: hb set [-h] [-root [ROOT_PATH]] [-p] + +optional arguments: + -h, --help show this help message and exit + -root [ROOT_PATH], --root_path [ROOT_PATH] + Set OHOS root path + -p, --product Set OHOS board and kernel +``` + +- hb set 后无参数,进入默认设置流程 +- hb set -root dir可直接设置代码根目录 +- hb set -p设置要编译的产品 + +**hb env** + +查看当前设置信息 + +``` +hb env +[OHOS INFO] root path: xxx +[OHOS INFO] board: hispark_taurus +[OHOS INFO] kernel: liteos +[OHOS INFO] product: ipcamera +[OHOS INFO] product path: xxx/vendor/hisilicon/ipcamera +[OHOS INFO] device path: xxx/device/hisilicon/hispark_taurus/sdk_linux_4.19 +``` + +**hb build** + +``` +hb build -h +usage: hb build [-h] [-b BUILD_TYPE] [-c COMPILER] [-t [TEST [TEST ...]]] + [--dmverity] [--tee] [-p PRODUCT] [-f] [-n] + [-T [TARGET [TARGET ...]]] [-v] [-shs] [--patch] + [component [component ...]] + +positional arguments: + component name of the component + +optional arguments: + -h, --help show this help message and exit + -b BUILD_TYPE, --build_type BUILD_TYPE + release or debug version + -c COMPILER, --compiler COMPILER + specify compiler + -t [TEST [TEST ...]], --test [TEST [TEST ...]] + compile test suit + --dmverity Enable dmverity + --tee Enable tee + -p PRODUCT, --product PRODUCT + build a specified product with + {product_name}@{company}, eg: camera@huawei + -f, --full full code compilation + -n, --ndk compile ndk + -T [TARGET [TARGET ...]], --target [TARGET [TARGET ...]] + Compile single target + -v, --verbose show all command lines while building + -shs, --sign_haps_by_server + sign haps by server + --patch apply product patch before compiling + + --dmverity Enable dmverity + -p PRODUCT, --product PRODUCT + build a specified product with + {product_name}@{company}, eg: ipcamera@hisilcon + -f, --full full code compilation + -T [TARGET [TARGET ...]], --target [TARGET [TARGET ...]] + Compile single target +``` + +- hb build后无参数,会按照设置好的代码路径、产品进行编译,编译选项使用与之前保持一致。-f 选项将删除当前产品所有编译产品,等同于hb clean + hb build. +- hb build \{component\_name\}:基于设置好的产品对应的单板、内核,单独编译组件(e.g.:hb build kv\_store\)。 +- hb build -p ipcamera@hisilicon:免set编译产品,该命令可以跳过set步骤,直接编译产品。 +- 在device/device\_company/board下单独执行hb build会进入内核选择界面,选择完成后会根据当前路径的单板、选择的内核编译出仅包含内核、驱动的镜像。 + +**hb clean** + +清除out目录对应产品的编译产物,仅保留args.gn、build.log。清除指定路径可输入路径参数:hb clean out/board/product,默认将清除当前hb set的产品对应out路径。 + +``` +hb clean +usage: hb clean [-h] [out_path] + +positional arguments: + out_path clean a specified path. + +optional arguments: + -h, --help show this help message and exit +``` + +### 新增组件 + +本小节介绍如何新增一个组件,首先确定组件归属的子系统和组件名称,然后按如下步骤新增: + +1. 源码开发完成后,添加组件编译脚本。 + + 以编译组件hello\_world可执行文件为例,applications/sample/hello\_world/BUILD.gn可以写为: + + ``` + executable("hello_world") { + include_dirs = [ + "include", + ] + sources = [ + "src/hello_world.c" + ] + } + ``` + + 如上编译脚本,可编译出一个可在OpenHarmony上运行的名为hello\_world的可执行文件。 + + 单独编译该组件,hb set任意选择一款产品,然后使用-T选项单独编译组件: + + ``` + hb build -f -T //applications/sample/hello_world + ``` + + 组件在开发板上功能验证完成后,可按[步骤2\~4](#li11471037297)将组件配置到产品中。 + +2. 添加组件描述。 + + 组件描述位于build/lite/components下,新增的组件需加入对应子系统的json文件中。一个组件描述必选的字段有: + + - component:组件名称。 + - description:组件的一句话功能描述。 + - optional:组件是否为系统可选。 + - dirs:组件源码路径。 + - targets:组件编译入口。 + + 以将hello\_world组件加入应用子系统为例,在applications.json中添加hello\_world对象: + + ``` + { + "components": [ + { + "component": "hello_world", + "description": "Hello world.", + "optional": "true", + "dirs": [ + "applications/sample/hello_world" + ], + "targets": [ + "//applications/sample/hello_world" + ] + }, + ... + ] + } + ``` + +3. 将组件配置到产品。 + + 产品的配置文件config.json位于位于vendor/company/product/下,产品配置文件需包含产品名称、OpenHarmony版本号、device厂商、开发板、内核类型、内核版本号,以及配置的子系统和组件。以将hello\_world组件加入产品配置文件my\_product.json中为例,加入hello\_wolrd对象: + + ``` + { + "product_name": "hello_world_test", + "ohos_version": "OpenHarmony 1.0", + "device_company": "hisilicon", + "board": "hispark_taurus", + "kernel_type": "liteos_a", + "kernel_version": "1.0.0", + "subsystems": [ + { + "subsystem": "applications", + "components": [ + { "component": "hello_world", "features":[] } + ] + }, + ... + ] + } + ``` + +4. 编译产品。 + + 1. 代码根目录输入hb set选择对应产品。 + + 2. 执行hb build。 + + +### 新增芯片解决方案 + +编译构建支持添加新的芯片解决方案厂商,具体步骤如下: + +1. 创建芯片解决方案目录。 + + 按照[芯片解决方案配置规则](#section1625463413327)创建目录,以芯片厂商realtek的“rtl8720“开发板为例, 在代码根目录执行: + + ``` + mkdir -p device/realtek/rtl8720 + ``` + +2. 创建内核适配目录,并编写开发板编译配置config.gni文件。 + + 以realtek的“rtl8720“开发板的liteos\_m适配为例,device/realtek/rtl8720/liteos\_a/config.gni的内容如下: + + ``` + # Kernel type, e.g. "linux", "liteos_a", "liteos_m". + kernel_type = "liteos_a" + + # Kernel version. + kernel_version = "3.0.0" + + # Board CPU type, e.g. "cortex-a7", "riscv32". + board_cpu = "real-m300" + + # Board arch, e.g. "armv7-a", "rv32imac". + board_arch = "" + + # Toolchain name used for system compiling. + # E.g. gcc-arm-none-eabi, arm-linux-harmonyeabi-gcc, ohos-clang, riscv32-unknown-elf. + # Note: The default toolchain is "ohos-clang". It's not mandatory if you use the default toochain. + board_toolchain = "gcc-arm-none-eabi" + + # The toolchain path instatlled, it's not mandatory if you have added toolchian path to your ~/.bashrc. + board_toolchain_path = + rebase_path("//prebuilts/gcc/linux-x86/arm/gcc-arm-none-eabi/bin", + root_build_dir) + + # Compiler prefix. + board_toolchain_prefix = "gcc-arm-none-eabi-" + + # Compiler type, "gcc" or "clang". + board_toolchain_type = "gcc" + + # Board related common compile flags. + board_cflags = [] + board_cxx_flags = [] + board_ld_flags = [] + ``` + +3. 编写编译脚本。 + + 在开发板目录下创建BUILD.gn,target名称应与开发板名称一致。以realtek的rtl8720开发板为例,device/realtek/rtl8720/BUILD.gn内容可以是: + + ``` + group("rtl8720") { # target类型也可以shared_library, static_library, executable + # 具体内容 + ...... + } + ``` + +4. 编译芯片解决方案。 + + 在开发板目录下执行hb build,即可启动芯片解决方案的编译。 + + +### 新增产品解决方案 + +编译构建支持芯片解决方案和组件的灵活拼装,形成定制化的产品解决方案。具体步骤如下: + +1. 创建产品目录 + + 按照[产品解决方案配置规则](#section1625463413327)创建产品目录,以基于“rtl8720“开发板的wifiiot模组为例,在代码根目录执行: + + ``` + mkdir -p vendor/my_company/wifiiot + ``` + +2. 拼装产品 + + 在新建的产品目录下新建config.json文件,以步骤1中的wifiiot为例,vendor/my\_company/wifiiot/config.json可以是: + + ``` + { + "product_name": "wifiiot", # 产品名称 + "ohos_version": "OpenHarmony 1.0", # 使用的OS版本 + "device_company": "realtek", # 芯片解决方案厂商名称 + "board": "rtl8720", # 开发板名称 + "kernel_type": "liteos_m", # 选择的内核类型 + "kernel_version": "3.0.0", # 选择的内核版本 + "subsystems": [ + { + "subsystem": "kernel", # 选择的子系统 + "components": [ + { "component": "liteos_m", "features":[] } # 选择的组件和组件特性 + ] + }, + ... + { + 更多子系统和组件 + } + ] + } + ``` + + 注意:编译构建系统编译前会对device\_company,board,kernel\_type,kernel\_version、subsystem、component字段进行有效性检查,其中device\_company,board,kernel\_type,kernel\_version应与已知的芯片解决方案匹配,subsystem、component应与build/lite/components下的组件描述匹配。 + +3. 适配OS接口 + + 在产品目录下创建hals目录,并将产品解决方案对OS适配的源码和编译脚本放入该目录下。 + +4. 配置系统服务 + + 在产品目录下创建init\_configs目录,并在init\_configs目录下创建init.cfg文件,按需配置要启动的系统服务。 + +5. 配置init进程(仅linux内核需要) + + 在init\_configs目录下创建etc目录,然后在etc下创建init.d文件夹和fstab文件。最后按产品需求在init.d文件下创建并编辑rcS文件和Sxxx文件。 + +6. 配置文件系统镜像(可选,仅支持文件系统的开发板需要) + + 在产品目录下创建fs.yml文件。fs.yml需按产品实际情况配置,一个典型的fs.yml文件如下: + + ``` + - + fs_dir_name: rootfs # 镜像的名称 + fs_dirs: + - + # 将编译生成的out/my_board/my_product/bin目录下的文件拷贝到rootfs/bin中,并忽略测试bin + source_dir: bin + target_dir: bin + ignore_files: + - Test.bin + - TestSuite.bin + - + # 将编译生成的out/my_board/my_product/libs目录下的文件拷贝到rootfs/lib中,忽略所有.a文件,并设置文件和文件夹的权限为644和755 + source_dir: libs + target_dir: lib + ignore_files: + - .a + dir_mode: 755 + file_mode: 644 + - + source_dir: usr/lib + target_dir: usr/lib + ignore_files: + - .a + dir_mode: 755 + file_mode: 644 + - + source_dir: config + target_dir: etc + - + source_dir: system + target_dir: system + - + source_dir: sbin + target_dir: sbin + - + source_dir: usr/bin + target_dir: usr/bin + - + source_dir: usr/sbin + target_dir: usr/sbin + - + # 创建一个proc空目录 + target_dir: proc + - + target_dir: mnt + - + target_dir: opt + - + target_dir: tmp + - + target_dir: var + - + target_dir: sys + - + source_dir: etc + target_dir: etc + - + source_dir: vendor + target_dir: vendor + - + target_dir: storage + + fs_filemode: + - + file_dir: lib/ld-uClibc-0.9.33.2.so + file_mode: 555 + - + file_dir: lib/ld-2.24.so + file_mode: 555 + - + file_dir: etc/init.cfg + file_mode: 400 + fs_symlink: + - + # 在rootfs/lib下创建软连接ld-musl-arm.so.1 -> libc.so + source: libc.so + link_name: ${fs_dir}/lib/ld-musl-arm.so.1 + - + source: mksh + link_name: ${fs_dir}/bin/sh + - + source: mksh + link_name: ${fs_dir}/bin/shell + fs_make_cmd: + # 使用脚本将rootfs制作为ext4格式的image + - ${root_path}/build/lite/make_rootfs/rootfsimg_linux.sh ${fs_dir} ext4 + - + fs_dir_name: userfs + fs_dirs: + - + source_dir: storage/etc + target_dir: etc + - + source_dir: data + target_dir: data + fs_make_cmd: + - ${root_path}/build/lite/make_rootfs/rootfsimg_linux.sh ${fs_dir} ext4 + + ``` + +7. 配置产品Patch(可选,视产品涉及组件是否需要打补丁而定) + + 在产品目录下创建patch.yml文件。patch.yml需按产品实际情况配置,一个典型的patch.yml文件如下: + + ``` + # 需要打patch的路径 + foundation/communication/dsoftbus: + # 该路径下需要打的patch存放路径 + - foundation/communication/dsoftbus/1.patch + - foundation/communication/dsoftbus/2.patch + third_party/wpa_supplicant: + - third_party/wpa_supplicant/1.patch + - third_party/wpa_supplicant/2.patch + - third_party/wpa_supplicant/3.patch + ... + ``` + + 配置完成后,编译时增加--patch参数,即可在产品编译前将配置的Patch文件打到对应目录中,再进行编译: + + ``` + hb build -f --patch + ``` + +8. 编写编译脚本 + + 在产品目录下创建BUILD.gn文件,按产品实际情况编写脚本。以步骤1中的wifiiot为例,BUILD.gn示例如下: + + ``` + group("wifiiot") { # target名称与产品名一致 + deps = [] + # 拷贝init配置 + deps += [ "init_configs" ] + # 将hals加入编译 + deps += [ "hals" ] + # 其他 + ...... + } + ``` + +9. 编译产品。 + + 在代码根目录执行hb set按提示选择新增的产品,然后执行hb build即可启动编译。 + + +## 常见问题 + +### ninja版本问题导致编译失败 + +- **现象描述:** + + 编译失败,提示“usr/sbin/ninja: invalid option -- w”。 + +- **可能原因:** + + 编译环境中ninja版本太低,不支持--w选项。 + +- **解决办法:** + + 卸载环境中ninja和gn,按照HarmonyOS官网[获取工具](../get-code/gettools-ide.md)。 + + +### ncurses库缺失导致编译失败 + +- **现象描述:** + + 编译失败,提示“/usr/bin/ld: cannot find -lncurses”。 + +- **可能原因:** + + 编译环境ncurses库缺失。 + +- **解决办法:** + + ``` + sudo apt-get install lib32ncurses5-dev + ``` + + +### 未安装mcopy导致编译失败 + +- **现象描述:** + + ​编译失败,提示“line 77: mcopy: command not found”。 + +- **可能原因:** + + 编译环境未安装mcopy。 + +- **解决办法:** + + ``` + ​sudo apt-get install dosfstools mtools + ``` + + +### 权限问题导致编译失败 + +- **现象描述:** + + 编译失败,提示“riscv32-unknown-elf-gcc: error trying to exec 'cc1': execvp: No such file or directory”。 + +- ​**可能原因:** + + 当前用户对riscv编译器路径下的文件访问权限不够。 + +- ​**解决办法:** + + 查询gcc\_riscv32所在目录。 + + ``` + which riscv32-unknown-elf-gcc + ``` + + 使用chmod命令修改目录权限为755。 + + +### 未安装Crypto导致编译失败 + +- **现象描述:** + + 编译失败,提示“No module named 'Crypto'”。 + +- **可能原因:** + + python3未安装Crypto。 + +- **解决办法:** + 1. 查询Python版本号。 + + ``` + python3 --version + ``` + + 2. 需使用python3.7以上版本,然后安装pycryptodome。 + + ``` + sudo pip3 install pycryptodome + ``` + + + +### 编译环境为shell导致编译失败 + +- **现象描述:** + + 编译失败:“xx.sh \[: xx unexpected operator”。 + +- **可能原因:** + + 编译环境shell不是bash。 + +- **解决办法:** + + ``` + sudo rm -rf /bin/sh + sudo ln -s /bin/bash /bin/sh + ``` + + diff --git a/zh-cn/device-dev/subsystems/subsys-build-mini.md b/zh-cn/device-dev/subsystems/subsys-build-mini.md new file mode 100644 index 0000000000..df6e2e0c54 --- /dev/null +++ b/zh-cn/device-dev/subsystems/subsys-build-mini.md @@ -0,0 +1,5 @@ +# 轻量和小型系统编译构建指导 + +- **[编译构建子系统—轻量和小型系统](subsys-build-mini-lite.md)** + + diff --git a/zh-cn/device-dev/subsystems/subsys-build-standard-large.md b/zh-cn/device-dev/subsystems/subsys-build-standard-large.md new file mode 100644 index 0000000000..9259a8073d --- /dev/null +++ b/zh-cn/device-dev/subsystems/subsys-build-standard-large.md @@ -0,0 +1,235 @@ +# 标准系统编译构建指导 + +- [概述](#section17466112012244) + - [基本概念](#section445513507246) + - [运作机制](#section12541217142510) + - [约束与限制](#section886933762513) + +- [编译构建使用指导](#section16901215262) + - [目录结构](#section109065332264) + - [编译命令](#section123265539266) + - [开发步骤](#section591084422719) + + +## 概述 + +编译构建子系统提供了一个基于gn和ninja的编译构建框架。主要提供以下功能: + +- 构建不同芯片平台的产品。如:Hi3516DV300平台。 + +- 根据产品配置可以按照组件组装打包产品需要的能力。 + +### 基本概念 + +在了解编译构建子系统的能力前,应了解如下基本概念: + +- 平台 + + 开发板和内核的组合,不同平台支持的子系统和组件不同。 + +- 子系统 + + OpenHarmony整体遵从分层设计,从下向上依次为:内核层、系统服务层、框架层和应用层。系统功能按照“系统 \> 子系统 \> 组件”逐级展开,在多设备部署场景下,支持根据实际需求裁剪某些非必要的子系统或组件。子系统是一个逻辑概念,它具体由对应的组件构成。 + +- 组件 + + 对子系统的进一步拆分,可复用的软件单元,它包含源码、配置文件、资源文件和编译脚本;能独立构建,以二进制方式集成,具备独立验证能力的二进制单元。 + +- gn + + Generate ninja的缩写,用于产生ninja文件。 + +- ninja + + ninja是一个专注于速度的小型构建系统。 + + +### 运作机制 + +OpenHarmony侧的编译构建流程主要包括编译命令行解析,调用gn,执行ninja: + +- 命令行解析:解析待编译的产品名称,加载相关配置。 +- 调用gn: 根据命令行解析的产品名称和编译类型,配置编译工具链和全局的编译选项。 +- 执行ninja:启动编译并生成对应的产品版本。 + +### 约束与限制 + +- 需按照[源码获取](../get-code/sourcecode-acquire.md)指导下载全量源码(采用方式三获取)。 +- 编译环境需要Ubuntu18.04及以上版本。 +- 安装编译所需的程序包。 + + 安装命令: + + ``` + sudo apt-get install binutils git-core gnupg flex bison gperf build-essential zip curl zlib1g-dev gcc-multilib g++-multilib libc6-dev-i386 lib32ncurses5-dev x11proto-core-dev libx11-dev lib32z-dev ccache libgl1-mesa-dev libxml2-utils xsltproc unzip m4 + ``` + + +## 编译构建使用指导 + +### 目录结构 + +``` +/build # 编译构建主目录 +├── config # 编译相关的配置项 +├── core +│ └── gn # 编译入口BUILD.gn配置 +├── loader # 各个组件配置加载、模板生成 +├── ohos # OpenHarmony编译打包流程配置 +│ ├── kits # kits编译打包模板和处理流程 +│ ├── ndk # ndk模板和处理流程 +│ ├── notice # notice模板和处理流程 +│ ├── packages # 版本打包模板和处理流程 +│ ├── sa_profile # sa模板和处理流程 +│ ├── sdk # sdk模板和处理流程,包括sdk中包含的模块配置 +│ └── testfwk # 测试相关的处理 +├── scripts # 编译相关的python脚本 +├── templates # c/c++编译模板定义 +└── toolchain # 编译工具链配置 +``` + +### 编译命令 + +- 代码根目录下执行全量版本的编译命令: + + ``` + ./build.sh --product-name {product_name} + ``` + + \{product\_name\}为当前版本支持的平台。比如:Hi3516DV300等。 + + 编译完成后,结果镜像保存在 out/ohos-arm-release/packages/phone/images/ 目录下。 + +- 编译命令支持选项: + + ``` + --product-name # 必须 编译的产品名称,如:Hi3516DV300 + --build-target # 可选 指定编译目标,可以指定多个 + --gn-args # 可选 gn参数,支持指定多个 + --ccache # 可选 编译使用ccache,需要本地安装ccache + ``` + + +### 开发步骤 + +1. 添加组件。 + + 本节以添加一个自定义的组件为例,描述如何编译组件,编译库、编译可执行文件等。 + + 示例组件partA由feature1、feature2和feature3组成,feature1的编译目标为一个动态库,feature2的目标为一个可执行程序,feature3的目标为一个etc配置文件。 + + 示例组件partA的配置需要添加到一个子系统中,本次示例将添加到subsystem\_examples子系统中(subsystem\_examples子系统定义在test/examples/目录)。 + + 示例组件partA的完整目录结构如下: + + ``` + test/examples/partA + ├── feature1 + │ ├── BUILD.gn + │ ├── include + │ │ └── helloworld1.h + │ └── src + │ └── helloworld1.cpp + ├── feature2 + │ ├── BUILD.gn + │ ├── include + │ │ └── helloworld2.h + │ └── src + │ └── helloworld2.cpp + └── feature3 + ├── BUILD.gn + └── src + └── config.conf + ``` + + 示例1:编写动态库gn脚本test/examples/partA/feature1/BUILD.gn,示例如下: + + ``` + config("helloworld_lib_config") { + include_dirs = [ "include" ] + } + + ohos_shared_library("helloworld_lib") { + sources = [ + "include/helloworld1.h", + "src/helloworld1.cpp", + ] + public_configs = [ ":helloworld_lib_config" ] + part_name = "partA" + } + ``` + + 示例2:编写可执行文件gn脚本test/examples/partA/feature2/BUILD.gn,示例如下: + + ``` + ohos_executable("helloworld_bin") { + sources = [ + "src/helloworld2.cpp" + ] + include_dirs = [ "include" ] + deps = [ # 依赖组件内模块 + "../feature1:helloworld_lib" + ] + external_deps = [ "partB:module1" ] # (可选)如果有跨组件的依赖,格式为“组件名:模块名” + install_enable = true # 可执行程序缺省不安装,需要安装时需要指定 + part_name = "partA" + } + ``` + + 示例3:编写etc模块gn脚本test/examples/partA/feature3/BUILD.gn,示例如下: + + ``` + ohos_prebuilt_etc("feature3_etc") { + source = "src/config.conf" + relative_install_dir = "init" #可选,模块安装相对路径,相对于默认安装路径;默认在/system/etc目录 + part_name = "partA" + } + ``` + + 示例4:在子系统的ohos.build中添加组件配置:test/examples/ohos.build。每个子系统有一个ohos.build配置文件,在子系统的根目录下。示例如下: + + ``` + "partA": { + "module_list": [ + "//test/examples/partA/feature1:helloworld_lib", + "//test/examples/partA/feature2:helloworld_bin", + "//test/examples/partA/feature3:feature3_etc", + ], + "inner_kits": [ + + ], + "system_kits": [ + + ], + "test_list": [ + + ] + } + ``` + + 一个组件包含module\_list、inner\_kits、system\_kits、test\_list四个部分的声明,其中: + + - module\_list:组件所包含的模块列表; + - inner\_kits:组件提供给其它组件调用的接口,其他组件的模块可以在external\_deps中添加依赖的模块; + - system\_kits:组件提供给开发者开发应用的接口; + - test\_list:组件中对应模块的测试用例; + +2. 将组件添加到产品配置中。 + + 在产品的配置中添加组件,产品对应的配置文件:productdefine/common/products/\{product-name\}.json。 + + 在产品配置文件中添加 "subsystem\_examples:partA",表示该产品中会编译并打包partA到版本中。 + +3. 编译。 + + 以编译Hi3516DV300为例,编译命令如下: + + ``` + ./build.sh --product-name Hi3516DV300 --ccache + ``` + +4. 编译输出。 + + 编译所生成的文件都归档在out/ohos-arm-release/目录下,结果镜像输出在 out/ohos-arm-release/packages/phone/images/ 目录下。 + + diff --git a/zh-cn/device-dev/subsystems/subsys-build-standard.md b/zh-cn/device-dev/subsystems/subsys-build-standard.md new file mode 100644 index 0000000000..d5d5ce6278 --- /dev/null +++ b/zh-cn/device-dev/subsystems/subsys-build-standard.md @@ -0,0 +1,5 @@ +# 标准系统编译构建指导 + +- **[编译构建子系统—标准系统](subsys-build-standard-large.md)** + + diff --git a/zh-cn/device-dev/subsystems/subsys-build.md b/zh-cn/device-dev/subsystems/subsys-build.md new file mode 100644 index 0000000000..487b7bf7b2 --- /dev/null +++ b/zh-cn/device-dev/subsystems/subsys-build.md @@ -0,0 +1,7 @@ +# 编译构建 + +- **[轻量和小型系统编译构建指导](subsys-build-mini-lite.md)** + +- **[标准系统编译构建指导](subsys-build-standard-large.md)** + + diff --git "a/zh-cn/device-dev/subsystems/Sensor\346\234\215\345\212\241\345\255\220\347\263\273\344\275\277\347\224\250\345\256\236\344\276\213.md" b/zh-cn/device-dev/subsystems/subsys-densor-demo.md old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/subsystems/Sensor\346\234\215\345\212\241\345\255\220\347\263\273\344\275\277\347\224\250\345\256\236\344\276\213.md" rename to zh-cn/device-dev/subsystems/subsys-densor-demo.md diff --git a/zh-cn/device-dev/subsystems/subsys-densor-guide.md b/zh-cn/device-dev/subsystems/subsys-densor-guide.md new file mode 100644 index 0000000000..b8d7fa3101 --- /dev/null +++ b/zh-cn/device-dev/subsystems/subsys-densor-guide.md @@ -0,0 +1,72 @@ +# Sensor服务子系使用指导 + +- [使用步骤](#section18816105182315) + +下面使用步骤以sensorTypeId为0的传感器为例,其他类型的传感器使用方式类似。 + +## 使用步骤 + +1. 导入需要的包 + +``` +#include "sensor_agent.h" +#include "sensor_agent_type.h" +``` + +1. 创建传感器回调函数 + +``` +void SensorDataCallbackImpl(SensorEvent *event) +{ + if(event == NULL){ + return; + } + float *sensorData=(float *)event->data; +} +``` + +>![](../public_sys-resources/icon-note.gif) **说明:** +>回调函数的格式为RecordSensorCallback类型。 + +1. 获取设备支持sensor列表 + +``` +SensorInfo *sensorInfo = (SensorInfo *)NULL; +int32_t count = 0; +int32_t ret = GetAllSensors(&sensorInfo, &count); +``` + +1. 创建的传感器用户 + +``` +SensorUser sensorUser; +sensorUser.callback = SensorDataCallbackImpl; //成员变量callback指向创建的回调方法 +``` + +1. 使能传感器 + +``` +int32_t ret = ActivateSensor(0, &sensorUser); +``` + +1. 订阅传感器数据 + +``` +int32_t ret = SubscribeSensor(0, &sensorUser); +``` + +>![](../public_sys-resources/icon-note.gif) **说明:** +>到这步就可以在实现的回调方法中获取到传感器数据。 + +1. 取消传感器数据订阅 + +``` +int32_t ret = UnsubscribeSensor(0, &sensorUser); +``` + +1. 去使能一个传感器 + +``` +int32_t ret = DeactivateSensor(0, &sensorUser); +``` + diff --git a/zh-cn/device-dev/subsystems/subsys-densor-overview.md b/zh-cn/device-dev/subsystems/subsys-densor-overview.md new file mode 100644 index 0000000000..caee5f57ca --- /dev/null +++ b/zh-cn/device-dev/subsystems/subsys-densor-overview.md @@ -0,0 +1,99 @@ +# Sensor服务子系概述 + +- [简介](#section667413271505) +- [接口说明](#section7255104114110) + +## 简介 + +Sensor服务子系统提供了轻量级传感器服务基础框架,您可以使用该框架接口实现传感器列表查询、传感器控制、传感器订阅去订阅等功能。轻量级传感器服务框架如下图所示: + +**图1** Sensor服务框架图 + +![](figure/zh-cn_image_0000001077724150.png) + +- Sensor API:提供传感器的基础API,主要包含查询传感器的列表、订阅/取消传感器数据、执行控制命令等,简化应用开发。 +- Sensor Framework:主要实现传感器的订阅管理、数据通道的创建、销毁等,实现与传感器服务层的通信。 +- Sensor Service:主要实现HDF层数据接收、解析、分发,对设备传感器的管理,数据上报管理以及传感器权限管控等。 + +## 接口说明 + +**表 1** Sensor服务框架API接口功能介绍 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    接口名

    +

    接口说明

    +

    参数要求

    +

    int32_t GetAllSensors(SensorInfo **sensorInfo, int32_t *count)

    +

    作用:获取系统中所有传感器的信息。

    +

    返回值:0表示成功,其他返回值表示失败。

    +

    sensorInfo(NOT NULL):输出系统中所有传感器的信息;

    +

    count(NOT NULL):输出系统中所有传感器的数量。

    +

    int32_t SubscribeSensor(int32_t sensorTypeId, SensorUser *user)

    +

    作用:订阅传感器数据,系统会将获取到的传感器数据上报给订阅者。

    +

    返回值: 0为成功,其他返回值表示失败。

    +

    sensorTypeId:唯一标识一个传感器类型;

    +

    user(NOT NULL):传感器的用户,用于从传感器获取数据,一般一个用户只属于一个传感器。

    +

    int32_t UnsubscribeSensor(int32_t sensorTypeId, SensorUser *user)

    +

    作用:去订阅传感器数据,系统将取消传感器数据上报给订阅者。

    +

    返回值:0为成功,其他返回值表示失败。

    +

    sensorTypeId:唯一标识一个传感器类型;

    +

    user(NOT NULL):传感器的用户,用于从传感器获取数据,一般一个用户只属于一个传感器。

    +

    int32_t SetBatch(int32_t sensorTypeId, SensorUser *user, int64_t samplingInterval, int64_t reportInterval)

    +

    作用:设置传感器的数据采样间隔和数据上报间隔

    +

    返回值:0为成功,其他返回值表示失败。

    +

    sensorTypeId:唯一标识一个传感器类型;

    +

    user(NOT NULL):传感器的用户,用于从传感器获取数据,一般一个用户只属于一个传感器;

    +

    samplingInterval:传感器数据采样间隔,单位纳秒;

    +

    reportInterval:传感器数据上报间隔,单位纳秒。

    +

    int32_t ActivateSensor(int32_t sensorTypeId, SensorUser *user)

    +

    作用:使能一个传感器订阅用户。

    +

    返回值:0为成功,其他返回值表示失败。

    +

    sensorTypeId:唯一标识一个传感器类型;

    +

    user(NOT NULL):传感器的用户,用于从传感器获取数据,一般一个用户只属于一个传感器。

    +

    int32_t DeactivateSensor(int32_t sensorTypeId, SensorUser *user)

    +

    作用:去使能一个传感器订阅用户

    +

    返回值:0为成功,其他返回值表示失败。

    +

    sensorTypeId:唯一标识一个传感器类型;

    +

    user(NOT NULL):传感器的用户,用于从传感器获取数据,一般一个用户只属于一个传感器。

    +

    int32_t SetMode(int32_t sensorTypeId, SensorUser *user, int32_t mode)

    +

    作用:设置传感器的工作模式

    +

    返回值:0为成功,其他返回值表示失败。

    +

    sensorTypeId:唯一标识一个传感器类型;

    +

    user(NOT NULL):传感器的用户,用于从传感器获取数据,一般一个用户只属于一个传感器;

    +

    mode:传感器的数据上报模式。

    +
    + diff --git a/zh-cn/device-dev/subsystems/subsys-densor.md b/zh-cn/device-dev/subsystems/subsys-densor.md new file mode 100644 index 0000000000..2c5ea0dbbe --- /dev/null +++ b/zh-cn/device-dev/subsystems/subsys-densor.md @@ -0,0 +1,9 @@ +# Sensor服务 + +- **[Sensor服务子系概述](subsys-densor-overview.md)** + +- **[Sensor服务子系使用指导](subsys-densor-guide.md)** + +- **[Sensor服务子系使用实例](subsys-densor-demo.md)** + + diff --git "a/zh-cn/device-dev/subsystems/HiLog_Lite\345\274\200\345\217\221\346\214\207\345\257\274.md" b/zh-cn/device-dev/subsystems/subsys-dfx-hilog-lite.md old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/subsystems/HiLog_Lite\345\274\200\345\217\221\346\214\207\345\257\274.md" rename to zh-cn/device-dev/subsystems/subsys-dfx-hilog-lite.md diff --git "a/zh-cn/device-dev/subsystems/HiLog\345\274\200\345\217\221\346\214\207\345\257\274.md" b/zh-cn/device-dev/subsystems/subsys-dfx-hilog-rich.md old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/subsystems/HiLog\345\274\200\345\217\221\346\214\207\345\257\274.md" rename to zh-cn/device-dev/subsystems/subsys-dfx-hilog-rich.md diff --git "a/zh-cn/device-dev/subsystems/HiSysEvent\345\274\200\345\217\221\346\214\207\345\257\274.md" b/zh-cn/device-dev/subsystems/subsys-dfx-hisysevent.md old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/subsystems/HiSysEvent\345\274\200\345\217\221\346\214\207\345\257\274.md" rename to zh-cn/device-dev/subsystems/subsys-dfx-hisysevent.md diff --git a/zh-cn/device-dev/subsystems/subsys-dfx-hisyseventread.md b/zh-cn/device-dev/subsystems/subsys-dfx-hisyseventread.md new file mode 100644 index 0000000000..333dd112b4 --- /dev/null +++ b/zh-cn/device-dev/subsystems/subsys-dfx-hisyseventread.md @@ -0,0 +1,103 @@ +# HiSysEvent订阅指导 + +- [概述](#section315316685112) +- [接口说明](#section0342191810519) +- [开发实例](#section123181432175110) + +## 概述 + +HiSysEvent提供了跨进程订阅机制,用户可以通过注册订阅接口。 + +## 接口说明 + +**表 1** HiSysEvent订阅接口 + + + + + + + + + + + + + +

    接口名

    +

    描述

    +

    int ISysEventService::AddListener(in SysEventRule[] rules, in ISysEventCallback callback)

    +

    接口功能:订阅HiSysEvent事件。

    +

    输入参数:

    +
    • rules:事件订阅规则
    • callback:订阅回调对象
    +

    返回值:

    +
    • 0:订阅成功,重复订阅
    • 1:订阅成功,初次订阅
    • 其他返回值:订阅失败
    +

    void ISysEventCallback::Handle(in String domain, in String eventName, in int eventType, in String eventDetail)

    +

    接口功能:订阅事件的回调接口。

    +

    输入参数:

    +
    • domain:事件所属领域
    • eventName:事件的名称
    • eventType:事件类型
    • eventDetail:包含事件相关信息的字符串,以json的形式体现
    +

    返回值:无。

    +
    + +**表 2** SysEventRule订阅规则对象 + + + + + + + + + + + + + + + + +

    属性名称

    +

    描述

    +

    uint32_t ruleType

    +

    规则类型(匹配范围包括domain以及eventName):

    +
    • 1:全字符匹配
    • 2:前缀匹配
    • 3:正则表达式匹配
    • 其他值:无效的匹配方式
    +

    std::string domain;

    +
    • domain:事件所属领域,如果传入的是空字符串,则默认事件领域字段匹配成功
    +

    std::string eventName

    +
    • eventName:事件的名称,如果传入的是空字符串,则默认事件名称字段匹配成功
    +
    + +## 开发实例 + +1. 源代码开发: + + 引入对应的aidl文件,包括:ISysEventService.aidl、SysEventRule.aidl、ISysEventCallback.aidl。 + + 在相应的业务逻辑里面调用ISysEventService::AddListener\(in SysEventRule\[\] rules, in ISysEventCallback callback\)接口。 + + 实现对应的回调对象: + + ISysEventCallback::Handle\(in String domain, in String eventName, in int eventType, in String eventDetail\) + + +1. 源代码开发: + + 引入对应的aidl文件,包括:ISysEventService.aidl、SysEventRule.aidl、ISysEventCallback.aidl。 + + 在相应的业务逻辑里面调用ISysEventService::AddListener\(in SysEventRule\[\] rules, in ISysEventCallback callback\)接口。 + + 实现对应的回调对象: + + ISysEventCallback::Handle\(in String domain, in String eventName, in int eventType, in String eventDetail\) + +2. 编译设置: + +在编译子系统里面,需要依赖libbinder模块 + +aosp\_deps = \[ "shared\_library:libbinder", \] + +- **[bytrace使用指导](subsys-toolchain-bytrace-guide.md)** + +- **[hdc\_std 使用指导](subsys-toolchain-hdc-guide.md)** + + diff --git "a/zh-cn/device-dev/subsystems/DFX\346\246\202\350\277\260.md" b/zh-cn/device-dev/subsystems/subsys-dfx-overview.md old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/subsystems/DFX\346\246\202\350\277\260.md" rename to zh-cn/device-dev/subsystems/subsys-dfx-overview.md diff --git a/zh-cn/device-dev/subsystems/subsys-dfx.md b/zh-cn/device-dev/subsystems/subsys-dfx.md new file mode 100644 index 0000000000..e4538aa73f --- /dev/null +++ b/zh-cn/device-dev/subsystems/subsys-dfx.md @@ -0,0 +1,11 @@ +# DFX + +- **[DFX概述](subsys-dfx-overview.md)** + +- **[HiLog开发指导](subsys-dfx-hilog-rich.md)** + +- **[HiLog\_Lite开发指导](subsys-dfx-hilog-lite.md)** + +- **[HiSysEvent开发指导](subsys-dfx-hisysevent.md)** + + diff --git a/zh-cn/device-dev/subsystems/subsys-graphics-animation-guide.md b/zh-cn/device-dev/subsystems/subsys-graphics-animation-guide.md new file mode 100644 index 0000000000..8332aa22bd --- /dev/null +++ b/zh-cn/device-dev/subsystems/subsys-graphics-animation-guide.md @@ -0,0 +1,190 @@ +# 动画开发指导 + +- [使用场景](#section726685714018) +- [接口说明](#section85794718418) +- [开发步骤](#section14101161317435) + +## 使用场景 + +UI动画通过task处理机制每个tick调用一下用户设置的callback函数来实现,具体实现为AnimatorManager、Animator、AnimatorCallback三个类实现。 + +- AnimatorManager:AnimatorManager为单例,在Init函数执行时将自己注册到系统task回调函数中,系统task机制保证每个tick会调用一下AnimatorManager的callback函数,同时AnimatorManager用来管理Animator实例。 +- Animator:Animator中可以设置动画相关的属性,包括动画的起止时间,动画开始和停止,动画状态的设置和获取等。 +- AnimatorCallback:具体每一个tick动画所要做的内容在AnimatorCallback类中实现,开发者需要自己实现Callback方法,动画执行时在Callback实现相应功能。 + +## 接口说明 + +**表 1** 动画接口说明 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    子模块

    +

    方法

    +

    功能

    +

    Animator

    +

    void Start ()

    +

    动画开始

    +

    Animator

    +

    void Stop ()

    +

    动画停止

    +

    Animator

    +

    void Pause ()

    +

    动画暂停

    +

    Animator

    +

    void Resume ()

    +

    动画恢复

    +

    Animator

    +

    uint8_t GetState () const

    +

    获取动画当前状态

    +

    Animator

    +

    void SetState (uint8_t state)

    +

    设置动画当前状态

    +

    Animator

    +

    uint32_t GetTime () const

    +

    获取动画总持续时间

    +

    Animator

    +

    void SetTime (uint32_t time)

    +

    设置动画总持续时间

    +

    Animator

    +

    uint32_t GetRunTime () const

    +

    获取动画当前已经持续的时间

    +

    Animator

    +

    void SetRunTime (uint32_t runTime)

    +

    设置动画当前已经持续的时间

    +

    Animator

    +

    bool IsRepeat () const

    +

    获取动画是否循环播放

    +

    AnimatorCallback

    +

    virtual void Callback (UIView *view)=0

    +

    由用户实现,动画回调函数

    +

    AnimatorCallback

    +

    virtual void OnStop(UIView& view) {}

    +

    由用户实现,动画停止后的回调函数

    +

    AnimatorManager

    +

    static AnimatorManager* GetInstance()

    +

    获取AnimatorManager实例

    +

    AnimatorManager

    +

    void Add (Animator *animator)

    +

    添加动画

    +

    AnimatorManager

    +

    void Remove(const Animator* animator);

    +

    删除动画

    +
    + +## 开发步骤 + +1. 实现AnimatorCallback的回调函数。 + + ``` + class AnimatorCallbackDemo : public OHOS::AnimatorCallback { + public: + AnimatorCallbackDemo(int16_t startPos, int16_t endPos, uint16_t time) + : start_(startPos), end_(endPos), time_(time), curTime_(0) {} + + virtual void Callback(OHOS::UIView* view) + { + curTime_++; + int16_t pos = EasingEquation::CubicEaseIn(start_, end_, curTime_, time_); + view->Invalidate(); + view->SetPosition(pos, view->GetY()); + view->Invalidate(); + } + protected: + int16_t start_; + int16_t end_; + uint16_t time_; + uint16_t curTime_; + }; + ``` + +2. 将AnimatorCallback添加到Animator中。 + + ``` + UIImageView* image = new UIImageView(); + image->SetSrc("..\\config\\images\\A021_001.bin"); + image->SetPosition(0, 50); + AnimatorCallbackDemo* callback = new AnimatorCallbackDemo(0, 338, 60); + Animator* animator = new Animator(callback, image, 0, true); + ``` + +3. 将Animator添加到AnimatorManager中。 + + ``` + AnimatorManager::GetInstance()->Add(animator); + ``` + +4. 点击下图下方的按钮,检查对应的动画运行效果。 + + **图 1** 动画实现效果图 + ![](figure/动画实现效果图.gif "动画实现效果图") + + diff --git a/zh-cn/device-dev/subsystems/subsys-graphics-bundle-guide1.md b/zh-cn/device-dev/subsystems/subsys-graphics-bundle-guide1.md new file mode 100644 index 0000000000..52da564931 --- /dev/null +++ b/zh-cn/device-dev/subsystems/subsys-graphics-bundle-guide1.md @@ -0,0 +1,244 @@ +# 容器类组件开发指导 + +- [UIViewGroup](#section145471898812) +- [使用场景](#section0916112362216) +- [接口说明](#section12641756192212) +- [开发步骤](#section5412161692311) +- [UIScrollView](#section174961523161315) +- [使用场景](#section8937101902413) +- [接口说明](#section14789133142420) +- [开发步骤](#section1769754422417) + +容器类组件,指能包含其它UI组件的组件,容器类组件继承于UIViewGroup(带Add方法),基于实际组件的使用场景,将需要增加其他子组件的组件,放置到容器类继承结构下。如UIAnalogClock内,通常会Add需要的计步信息,时分秒图标等。 + +**图 1** 普通容器类组件结构 +![](figure/普通容器类组件结构.png "普通容器类组件结构") + +RootView、UIAbstractScroll、UIPicker组件从UIViewGroup继承,UIList、UIScrollView、UISwipeView组件从UIAbstractScroll继承。 + +## UIViewGroup + +## 使用场景 + +UIViewGroup是容器类组件基类,实现增加、删除、插入等操作,通过增加方法可以添加子组件。普通容器类组件子组件需要设置位置信息,位置信息为相对父组件的相对坐标。组件树结构如下图: + +**图 2** 组件树结构示意图 +![](figure/组件树结构示意图.png "组件树结构示意图") + +往根节点rootView里添加ViewGroup1容器组件和View1组件,往ViewGroup1容器组件里再添加View2组件和ViewGroup2容器组件,在View1之后添加View3组件。 + +- 关于渲染:容器类组件在渲染时会遍历所有子组件OnDraw方法,以达到刷新所有组件的目的。 +- 关于坐标:子组件位置信息为相对父组件的相对坐标,系统在渲染时计算绝对坐标并显示。 +- 关于树结构遍历:UIViewGroup提供如下方法实现遍历、查找、管理组件树。 + +## 接口说明 + +**表 1** ViewGroup接口说明 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    方法

    +

    功能

    +

    virtual void Add(UIView* view)

    +

    添加子组件

    +

    virtual void Insert(UIView* prevView, UIView* insertView)

    +

    插入子组件

    +

    virtual void Remove(UIView* view)

    +

    删除子组件

    +

    virtual void RemoveAll()

    +

    删除所有子组件

    +

    virtual void GetTargetView(const Point& point, UIView** last)

    +

    获取目标视图

    +

    virtual void MoveChildByOffset(int16_t x, int16_t y)

    +

    偏移子组件

    +

    UIView* GetChildrenHead() const

    +

    获取视图头节点

    +

    UIView* GetChildrenTail() const

    +

    获取视图最后那个节点

    +

    virtual UIView* GetChildById(const char* id) const override

    +

    通过id获取子视图

    +
    + +## 开发步骤 + +1. 构造button实例并设置坐标信息。 + + ``` + UILabelButton* btn1 = new UILabelButton(); + btn1->SetPosition(0, 0, 100, 50); + btn1->SetText("btn1"); + + UILabelButton* btn2 = new UILabelButton(); + btn2->SetPosition(50, 50, 100, 50); + btn2->SetText("btn2"); + + UILabelButton* btn3 = new UILabelButton(); + btn3->SetPosition(100, 100, 100, 50); + btn3->SetText("btn3"); + ``` + +2. 构造UIViewGroup实例,并设置坐标信息。 + + ``` + UIViewGroup* group = new UIViewGroup(); + group->SetPosition(0, 0, 300, 300); + ``` + +3. 使用Add方法添加Button实例到UIViewGroup。 + + ``` + group->Add(btn1); + group->Add(btn2); + group->Add(btn3); + ``` + +4. 检查ViewGroup效果如下图所示。 + + **图 3** ViewGroup添加view实例效果图 + ![](figure/ViewGroup添加view实例效果图.png "ViewGroup添加view实例效果图") + + +## UIScrollView + +## 使用场景 + +UIScrollView提供可滑动的容器类组件,子组件可在触摸事件驱动下上下、左右滑动,并提供水平和垂直方向的游标显示功能。 + +## 接口说明 + +**表 2** ScrollView接口说明 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    方法

    +

    功能

    +

    void ScrollBy(int16_t xDistance, int16_t yDistance)

    +

    移动视图

    +

    void SetScrollbarWidth(uint8_t width)

    +

    设置滑动条宽度

    +

    void SetHorizontalScrollState(bool state)

    +

    设置水平滑动状态

    +

    bool GetHorizontalScrollState() const

    +

    获取水平是否可滑动状态

    +

    void SetVerticalScrollState(bool state)

    +

    设置垂直滑动状态

    +

    bool GetVerticalScrollState() const

    +

    获取垂直是否可滑动状态

    +

    void SetXScrollBarVisible(bool state)

    +

    设置X轴滑动条是否可见

    +

    void SetYScrollBarVisible(bool state)

    +

    设置Y轴滑动条是否可见

    +

    void RegisterScrollListener(OnScrollListener* scrollListener)

    +

    注册滑动事件回调类

    +

    void RefreshScrollBar()

    +

    刷新滑动条

    +

    virtual void OnScrollStart() {}

    +

    滚动开始回调函数

    +

    virtual void OnScrollEnd() {}

    +

    滚动结束回调函数

    +

    uint8_t GetScrollState() const

    +

    获取滚动状态

    +

    void SetScrollState(uint8_t state)

    +

    设置滚动状态

    +
    + +## 开发步骤 + +添加两个button子组件,并显示水平、垂直方向游标。 + +``` +scrollView* scroll = new UIScrollView(); +scroll->SetStyle(STYLE_BACKGROUND_COLOR, Color::Red().full); +scroll->SetPosition(0,0, 200, 200); +scroll->SetXScrollBarVisible(true); +scroll->SetYScrollBarVisible(true); +UILabelButton* button1 = new UILabelButton(); +button1->SetText("button1"); +button1->SetPosition(0, 0, 300, 300); +UILabelButton* button2 = new UILabelButton(); +button2->SetText("button2"); +button2->SetPosition(0, 300, 300, 300); +scroll->Add(button1); +scroll->Add(button2); +``` + +**图 4** 水平、垂直方向可滑动效果图 +![](figure/水平-垂直方向可滑动效果图.gif "水平-垂直方向可滑动效果图") + diff --git a/zh-cn/device-dev/subsystems/subsys-graphics-bundle-guide2.md b/zh-cn/device-dev/subsystems/subsys-graphics-bundle-guide2.md new file mode 100644 index 0000000000..f03df38642 --- /dev/null +++ b/zh-cn/device-dev/subsystems/subsys-graphics-bundle-guide2.md @@ -0,0 +1,216 @@ +# 布局容器类组件开发指导 + +- [UISwipeView](#section13631719181717) +- [使用场景](#section11299120102617) +- [接口说明](#section767434119261) +- [开发步骤(水平滑动,不可循环)](#section111911175287) +- [开发步骤(水平滑动,可循环)](#section1976914915282) +- [GridLayout](#section46819199173) +- [使用场景](#section831618247294) +- [接口说明](#section597214622912) +- [开发步骤](#section1418253410306) + +布局类容器组件由视图基础类组成,通过直接设置视图位置,可以达到嵌套和重叠布局的目的;通过设置布局类型和边距达到规格化布局子组件的目的;通过调用相关接口可实现根据父组件及兄弟节点布局视图的目的。 + +## UISwipeView + +## 使用场景 + +UISwipeView继承UIViewGroup,除提供容器类组件Add、Remove、Insert等方法外还提供按页面滑动功能,滑动结束后当前页面居中对齐显示。该组件分为水平方向和垂直方向,通过Add方法添加的子组件会根据Add的顺序和UISwipeView方向自动水平对齐或则垂直对齐。 + +## 接口说明 + +**表 1** SwipeView接口说明 + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    方法

    +

    功能

    +

    void SetCurrentPage(uint16_t index);

    +

    设置当前页

    +

    uint16_t GetCurrentPage()

    +

    获取当前页

    +

    UIView* GetCurrentView() const

    +

    获取当前页组件

    +

    void SetOnSwipeListener(OnSwipeListener& onSwipeListener)

    +

    设置滑动回调类

    +

    void SetAnimatorTime(uint16_t time);

    +

    设置动画事件

    +

    void SetLoopState(bool loop)

    +

    设置是否循环

    +

    UIView* GetViewByIndex(uint16_t index);

    +

    通过index获取view

    +
    + +## 开发步骤(水平滑动,不可循环) + +1. 创建一个水平滑动的UISwipeView。 + + ``` + UISwipeView* swipe = new UISwipeView(UISwipeView::HORIZONTAL); + ``` + +2. 向UISwipeView中添加子组件。 + + ``` + UILabelButton* button1 = new UILabelButton(); + button1->SetPosition(0, 0, g_ButtonW, g_ButtonH); + button1->SetText("button1"); + swipe->Add(button1); + UILabelButton* button2 = new UILabelButton(); + button2->SetPosition(0, 0, g_ButtonW, g_ButtonH); + button2->SetText("button2"); + swipe->Add(button2); + UILabelButton* button3 = new UILabelButton(); + button3->SetPosition(0, 0, g_ButtonW, g_ButtonH); + button3->SetText("button3"); + swipe->Add(button3); + ``` + +3. 检查实现效果,水平滑动,不可循环。 + + **图 1** UISwipeView水平滑动效果图 + + + ![](figure/zh-cn_image_0000001053247975.gif) + + +## 开发步骤(水平滑动,可循环) + +1. 创建一个水平滑动的UISwipeView并添加子组件。 + + ``` + UISwipeView* swipe = new UISwipeView(UISwipeView::HORIZONTAL); + UILabelButton* button1 = new UILabelButton(); + button1->SetPosition(0, 0, g_ButtonW, g_ButtonH); + button1->SetText("button1"); + swipe->Add(button1); + UILabelButton* button2 = new UILabelButton(); + button2->SetPosition(0, 0, g_ButtonW, g_ButtonH); + button2->SetText("button2"); + swipe->Add(button2); + UILabelButton* button3 = new UILabelButton(); + button3->SetPosition(0, 0, g_ButtonW, g_ButtonH); + button3->SetText("button3"); + swipe->Add(button3); + ``` + +2. 设置UISwipeView循环滑动。 + + ``` + swipe->SetLoopState(true); + ``` + +3. 检查实现效果,水平循环滑动。 + + **图 2** UISwipeView水平滑动循环效果图 + + + ![](figure/zh-cn_image_0000001053207924.gif) + + +## GridLayout + +## 使用场景 + +提供基础布局能力,可设置网格行数和列数,通过Add方法添加的子组件在调用LayoutChildren\(\)方法后自动进行排列布局。 + +## 接口说明 + +**表 2** GridLayout接口说明 + + + + + + + + + + + + + + + + +

    方法

    +

    功能

    +

    void SetRows(const uint16_t& rows)

    +

    设置行数

    +

    void SetCols(const uint16_t& cols)

    +

    设置列数

    +

    void LayoutChildren(bool needInvalidate = false)

    +

    布局子组件

    +
    + +## 开发步骤 + +1. 构造GridLayout并设置位置、大小信息。 + + ``` + GridLayout* layout_ = new GridLayout(); + layout_->SetPosition(0, g_y, HROIZONTAL_RESOLUTION, 200); + layout_->SetLayoutDirection(LAYOUT_HOR); + layout_->SetRows(2); + layout_->SetCols(2); + ``` + +2. 构造子组件button。 + + ``` + UILabelButton* bt1 = new UILabelButton(); + bt1->SetPosition(0,0,100,50); + bt1->SetText("bt1"); + UILabelButton* bt2 = new UILabelButton(); + bt2->SetPosition(0, 0, 100, 50); + bt2->SetText("bt2"); + UILabelButton* bt3 = new UILabelButton(); + bt3->SetPosition(0, 0, 100, 50); + bt3->SetText("bt3"); + UILabelButton* bt4 = new UILabelButton(); + bt4->SetPosition(0, 0, 100, 50); + bt4->SetText("bt4"); + ``` + +3. 添加子组件并调用LayoutChildren\(\)。 + + ``` + layout_->Add(bt1); + layout_->Add(bt2); + layout_->Add(bt3); + layout_->Add(bt4); + layout_->LayoutChildren(); + ``` + +4. 检查button组件布局效果如下图所示。 + + **图 3** 设置2\*2网格并添加4个button组件进行布局 + ![](figure/设置2-2网格并添加4个button组件进行布局.png "设置2-2网格并添加4个button组件进行布局") + + diff --git a/zh-cn/device-dev/subsystems/subsys-graphics-bundle-guide3.md b/zh-cn/device-dev/subsystems/subsys-graphics-bundle-guide3.md new file mode 100644 index 0000000000..d9b0d48c87 --- /dev/null +++ b/zh-cn/device-dev/subsystems/subsys-graphics-bundle-guide3.md @@ -0,0 +1,555 @@ +# 普通组件开发指导 + +- [UIButton](#section145353310214) +- [使用场景](#section1169616141577) +- [接口说明](#section341211538315) +- [开发步骤](#section22501726193214) +- [UIImageView](#section19523161611259) +- [使用场景](#section1274484210400) +- [接口说明](#section74981992411) +- [开发步骤(自适应)](#section144341333134114) +- [开发步骤(平铺模式)](#section97178160421) +- [UILabel](#section16588132012911) +- [使用场景](#section6870195634218) +- [接口说明](#section2012714510433) +- [开发步骤(默认模式)](#section83221538114410) +- [开发步骤(背景色和透明度)](#section933360204510) +- [开发步骤(字符间距)](#section19447826124518) +- [开发步骤(大小自适应)](#section101711842154617) +- [开发步骤(省略号模式)](#section1249519410471) +- [开发步骤(滚动模式)](#section15643122618478) + +普通组件均继承于基类UIView,不可以添加子组件,常用的普通组件有button、image、label等。 + +**图 1** 普通组件树结构 +![](figure/普通组件树结构.png "普通组件树结构") + +UIView为基础类,UIAbstractProgress、UIArcLabel(旋转字体)、UIButton(按键)、UICanvas(画布)、UILabel(字体)、UIImageView(图片)从UIView继承。UIBoxProgress、UICircleProgress从UIAbstractProgress继承,UILabelButton和UIRepeatButton从UIButton继承,UIImageAnimatorView和UITextureMapper从UIImageView继承。 + +## UIButton + +## 使用场景 + +UIButton组件,提供可点击功能,同时可设置不同状态下样式。 + +## 接口说明 + +**表 1** button接口说明 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    方法

    +

    功能

    +

    void SetImageSrc (const char *defaultImgSrc, const char *triggeredImgSrc)

    +

    设置button图片

    +

    void SetImagePosition (const int16_t x, const int16_t y)

    +

    设置button图片位置

    +

    int16_t GetImageX () const

    +

    获取图片X坐标

    +

    int16_t GetImageY () const

    +

    获取图片Y坐标

    +

    const ImageInfo* GetCurImageSrc() const

    +

    获取当前状态图片

    +

    Style& GetStyleForState (ButtonState state)

    +

    设置button当前状态的style

    +

    voidSetStyleForState (const Style &style, ButtonState state)

    +

    设置button指定状态的style

    +

    void Disable ()

    +

    去使能button

    +

    void Enable ()

    +

    使能button

    +
    + +## 开发步骤 + +1. 实现点击事件。 + + ``` + class TestBtnOnClickListener : public OHOS::UIView::OnClickListener { + bool OnClick(UIView& view, const ClickEvent& event) override + { + int16_t width = view.GetWidth() + 10; + int16_t height = view.GetHeight() + 10; + view.Resize(width, height); + view.Invalidate(); + return true; + } + }; + ``` + +2. 创建一个UIButton。 + + ``` + UIButton* button = new UIButton(); + button->SetPosition(50, 50); + button->SetWidth(100); + button->SetHeight(50); + ``` + +3. 给UIButton注册点击事件回调。 + + ``` + button->SetOnClickListener(new TestBtnOnClickListener()); + ``` + +4. 检查Button点击效果如下图所示,Button逐渐变大。 + + **图 2** UIButton点击效果 + ![](figure/UIButton点击效果.gif "UIButton点击效果") + + +## UIImageView + +## 使用场景 + +图片组件,提供图片显示,透明度设置,图片旋转、缩放功能。支持的图片格式为RGB565、RGB888、RGBA8888、PNG、JPG。 + +## 接口说明 + +**表 2** image接口说明 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    方法

    +

    功能

    +

    void SetSrc (const char *src)

    +

    设置二进制图片路径

    +

    void SetSrc (const ImageInfo *src)

    +

    设置图片指针

    +

    void SetAutoEnable (bool enable)

    +

    设置组件大小跟随image大小变化

    +

    const void* GetSrcType () const

    +

    获取图片类型

    +

    bool GetAutoEnable () const

    +

    获取组件大小是否跟随image大小变化

    +

    void SetBlurLevel(BlurLevel level)

    +

    设置模糊等级

    +

    BlurLevel GetBlurLevel() const

    +

    获取模糊等级

    +

    void SetTransformAlgorithm(TransformAlgorithm algorithm)

    +

    设置旋转算法

    +

    TransformAlgorithm GetTransformAlgorithm() const

    +

    获取旋转算法

    +
    + +## 开发步骤(自适应) + +1. 创建一个UIImageView。 + + ``` + UIImageView* imageView = new UIImageView(); + imageView->SetPosition(0, 30); + ``` + +2. 设置二进制格式的图片。 + + ``` + imageView->SetSrc("..\\config\\images\\A021_001.bin"); + ``` + +3. 检查UIImageView控件大小与图片相同。 + + **图 3** 自适应模式图片效果图 + ![](figure/自适应模式图片效果图.png "自适应模式图片效果图") + + +## 开发步骤(平铺模式) + +1. 创建一个UIImageView。 + + ``` + UIImageView* imageView = new UIImageView(); + imageView->SetPosition(0, 30); + ``` + +2. 设置图片。 + + ``` + imageView->SetSrc("..\\config\\images\\A021_001.bin"); + ``` + +3. 取消图片自适应,设置图片大小,平铺显示效果。 + + ``` + imageView->SetAutoEnable(false); + imageView->Resize(454, 150); + ``` + +4. 检查UIImageView控件显示为平铺效果。 + + **图 4** 平铺模式图片效果图 + ![](figure/平铺模式图片效果图.png "平铺模式图片效果图") + + +## UILabel + +## 使用场景 + +标签(label)是在一块区域上显示文本字符串的组件,可设置区域背景色、文字的显示样式和长文本的显示效果等。 + +## 接口说明 + +**表 3** label接口说明 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    方法

    +

    功能

    +

    void SetText(const char* text);

    +

    设置文字

    +

    const char* GetText() const;

    +

    获取text

    +

    void SetLineBreakMode(const uint8_t lineBreakMode);

    +

    设置label模式,例如截断,自动扩展等。

    +

    uint8_t GetLineBreakMode() const

    +

    获取label模式

    +

    void SetTextColor(ColorType color)

    +

    设置文本颜色

    +

    ColorType GetTextColor() const

    +

    获取文本颜色

    +

    void SetAlign(UITextLanguageAlignment horizontalAlign,

    +

    UITextLanguageAlignment verticalAlign = TEXT_ALIGNMENT_TOP);

    +

    设置文本对齐方式

    +

    UITextLanguageAlignment GetHorAlign() const

    +

    获取文本水平对齐方式

    +

    UITextLanguageAlignment GetVerAlign() const

    +

    获取文本竖直对齐方式

    +

    void SetDirect(UITextLanguageDirect direct)

    +

    设置文本显示方向

    +

    UITextLanguageDirect GetDirect() const

    +

    获取文本显示方向

    +

    void SetFontId(uint8_t fontId);

    +

    设置动态字体id

    +

    uint8_t GetFontId() const

    +

    获取动态字体id

    +

    void SetFont(const char *name, uint8_t size);

    +

    设置字的名字和大小

    +

    void SetAnimatorSpeed(uint16_t animSpeed);

    +

    设置字体旋转的速度

    +

    uint16_t GetTextWidth();

    +

    获取字体的宽

    +

    uint16_t GetTextHeight();

    +

    获取字体的高

    +

    void SetRollStartPos(int16_t pos)

    +

    设置旋转的位置

    +

    int16_t GetRollStartPos() const

    +

    获取旋转的位置

    +

    void SetTextRotation(LabelRotateDegree angle)

    +

    设置文本旋转角度枚举值

    +

    LabelRotateDegree GetTextRotation() const

    +

    获取文本旋转角度枚举值

    +

    uint16_t GetTextRotateDegree() const

    +

    获取文本旋转角度数值

    +
    + +## 开发步骤(默认模式) + +1. 创建label,设置大小和位置信息。 + + ``` + UILabel* label = new UILabel(); + label->SetPosition(x, y); + label->Resize(width, height); + ``` + +2. 设置字形信息。 + + ``` + label->SetFont("SourceHanSansSC-Regular.otf", 30); + ``` + +3. 设置文本数据。 + + ``` + label->SetText("label"); + ``` + +4. 检查label大小和显示效果正常,如下图所示。 + + ![](figure/zh-cn_image_0000001051782526.png) + + +## 开发步骤(背景色和透明度) + +1. 创建label,设置大小和位置信息。 + + ``` + UILabel* label = new UILabel(); + label->SetPosition(x, y); + label->Resize(width, height); + ``` + +2. 设置字形信息。 + + ``` + label->SetFont("SourceHanSansSC-Regular.otf", 30); + ``` + +3. 设置背景颜色及透明度效果。 + + ``` + label->SetStyle(STYLE_BACKGROUND_COLOR, Color::Gray().full); + label->SetStyle(STYLE_BACKGROUND_OPA, 127); + label->SetText("Label"); + ``` + +4. 检查label背景色为Gray,如下图所示。 + + ![](figure/zh-cn_image_0000001052582522.png) + + +## 开发步骤(字符间距) + +1. 创建label,设置大小和位置信息。 + + ``` + UILabel* label = new UILabel(); + label->SetPosition(x, y); + label->Resize(width, height); + ``` + +2. 设置字形信息。 + + ``` + label->SetFont("SourceHanSansSC-Regular.otf", 30); + ``` + +3. 设置字体颜色和字间距效果。 + + ``` + label->SetStyle(STYLE_BACKGROUND_COLOR, Color::Gray().full); + label->SetStyle(STYLE_LETTER_SPACE, 5); + label->SetText("Label"); + ``` + +4. 检查label字符间距为5,如下图所示。 + + ![](figure/zh-cn_image_0000001052942531.png) + + +## 开发步骤(大小自适应) + +当文本过长时,可根据文本信息自动调整label组件大小,也可以设置文本截断或者文本滚动效果。 + +1. 创建label,设置大小和位置信息。 + + ``` + UILabel* label = new UILabel(); + label->SetPosition(x, y); + label->Resize(width, height); + ``` + +2. 设置字形信息。 + + ``` + label->SetFont("SourceHanSansSC-Regular.otf", 30); + ``` + +3. 设置字体颜色为Gray,组件大小自适应文本内容。 + + ``` + label->SetStyle(STYLE_BACKGROUND_COLOR, Color::Gray().full); + label->SetLineBreakMode(UILabel::LINE_BREAK_ADAPT); + label->SetText("123\n567890"); + ``` + +4. 检查label大小自适应文本内容,如下图所示。 + + ![](figure/zh-cn_image_0000001052782555.png) + + +## 开发步骤(省略号模式) + +省略号模式指文本内容显示不下时,在末尾显示省略号。 + +1. 创建label,设置大小和位置信息。 + + ``` + UILabel* label = new UILabel(); + label->SetPosition(x, y); + label->Resize(width, height); + ``` + +2. 设置字形信息。 + + ``` + label->SetFont("SourceHanSansSC-Regular.otf", 30); + ``` + +3. 设置换行模式为DOT模式 + + ``` + label->SetStyle(STYLE_BACKGROUND_COLOR, Color::Gray().full); + label->SetLineBreakMode(UILabel::LINE_BREAK_ELLIPSIS); + label->SetText("123567890"); + ``` + +4. 检查label DOT模式效果,如下图所示,末尾显示省略号。 + + ![](figure/zh-cn_image_0000001052662559.png) + + +## 开发步骤(滚动模式) + +文本滚动显示。 + +1. 创建label,设置大小和位置信息。 + + ``` + UILabel* label = new UILabel(); + label->SetPosition(x, y); + label->Resize(width, height); + ``` + +2. 设置字形信息。 + + ``` + label->SetFont("SourceHanSansSC-Regular.otf", 30); + ``` + +3. 设置换行模式为滚动模式 + + ``` + label->SetStyle(STYLE_BACKGROUND_COLOR, Color::Gray().full); + label->SetStyle(STYLE_BACKGROUND_OPA, 127); + label->SetLineBreakMode(UILabel::LINE_BREAK_MARQUEE); + label->SetText("123567890"); + ``` + +4. 检查label滚动模式效果,如下图所示。 + + ![](figure/20200721-223604(eSpace).gif) + + diff --git "a/zh-cn/device-dev/subsystems/\345\233\276\345\275\242\345\233\276\345\203\217\346\246\202\350\277\260.md" b/zh-cn/device-dev/subsystems/subsys-graphics-overview.md old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/subsystems/\345\233\276\345\275\242\345\233\276\345\203\217\346\246\202\350\277\260.md" rename to zh-cn/device-dev/subsystems/subsys-graphics-overview.md diff --git a/zh-cn/device-dev/subsystems/subsys-graphics.md b/zh-cn/device-dev/subsystems/subsys-graphics.md new file mode 100644 index 0000000000..bb255fa159 --- /dev/null +++ b/zh-cn/device-dev/subsystems/subsys-graphics.md @@ -0,0 +1,13 @@ +# 图形图像 + +- **[图形图像概述](subsys-graphics-overview.md)** + +- **[容器类组件开发指导](subsys-graphics-bundle-guide1.md)** + +- **[布局容器类组件开发指导](subsys-graphics-bundle-guide2.md)** + +- **[普通组件开发指导](subsys-graphics-bundle-guide3.md)** + +- **[动画开发指导](subsys-graphics-animation-guide.md)** + + diff --git a/zh-cn/device-dev/subsystems/subsys-multimedia-camera-overview.md b/zh-cn/device-dev/subsystems/subsys-multimedia-camera-overview.md new file mode 100644 index 0000000000..75b2033e9c --- /dev/null +++ b/zh-cn/device-dev/subsystems/subsys-multimedia-camera-overview.md @@ -0,0 +1,116 @@ +# 相机开发概述 + +- [基本概念](#section175012297491) +- [运作机制](#section193961322175011) + +## 基本概念 + +相机是OpenHarmony多媒体进程提供的服务之一,提供了相机的录像、预览、拍照功能,支持多用户并发取流。 + +在进行应用的开发前,开发者应了解以下基本概念: + +- 视频帧 + + 视频流指的是将一系列图片数据按照固定时间间隔排列形成的数据流,每一张图片数据成为一帧,这样的一帧称为视频帧。 + +- 帧速率\(FPS: Frames Per Second\) + + 视频播放每秒钟刷新图片的速度,或是视频每秒的帧数,帧速率越高,视频的观感越流畅。 + +- 分辨率 + + 每一帧的图片信息都是由像素点组成的,分辨率描述了一张图片中像素点的个数。例如1920\*1080\(1080P\),是指图片宽1920像素,高1080像素。 + + +## 运作机制 + +- 多媒体服务进程 + + 多媒体服务作为系统服务,在系统启动时由Init进程拉起,并初始化和分配媒体硬件资源(内存/显示硬件/图像传感器/编解码器等)。初始化过程解析配置文件,确定了多媒体各个服务的能力和资源上限,通常由OEM厂商通过配置文件进行配置。相机服务在多媒体进程初始化时有以下配置项: + + - 内存池:所有媒体服务依赖于内存池中的内存轮转运行 + - 图像传感器:包括了传感器类型、分辨率、ISP等 + - 图像处理器:分辨率、码率、图像翻转等 + - 图像编码器:编码格式、码率、分辨率等 + + +- 关键类的解释 + + 应用通过持有下面4个类,配置和使用Camera的功能,包括了Camera类和它的三个异步回调类,三类回调分别对应了不同类型的异步处理场景,详见[表1](#table486418149411)。 + + **表 1** 关键类的解释 + + + + + + + + + + + + + + + + + + + + + + + + +

    对象

    +

    用途

    +

    举例

    +

    Camera

    +

    对相机进行静态配置(通过配置类),触发相机基本功能

    +

    拍照/录像/预览

    +

    CameraDeviceCallback

    +

    处理相机硬件状态变化

    +

    可用/不可用

    +

    CameraStateCallback

    +

    处理camera自身状态变化

    +

    创建/释放

    +

    FrameStateCallback

    +

    处理帧状态的变化

    +

    拍照开始和结束/帧率发生变化

    +
    + +- 流的传递 + + Surface是多媒体传递音视频的基本数据结构,Camera一般作为Surface中数据的生产者,在不同的场景下有特定的消费者。 + + 相机的预览和录像输出均为视频流,拍照输出为图像帧,二者均通过Surface类进行传递。Surface类可以屏蔽进程内/跨进程的场景,进行多媒体信息流的传递。 + + 以录像为例,用户首先创建Recorder实例,并从Recorder中获取对应Surface,再将此Surface传递给Camera实例,此时Camera将作为生产者向Surface注入视频流,而Recorder作为消费者从Surface中取出视频流进行保存,用户的行为类似桥接,把二者通过Surface连接起来。 + + 类似的,用户也可以自行创建Surface传递给Camera实例,并实现消费者逻辑(例如通过网络传输视频流,或是将拍照的帧数据保存成图片文件)。 + + 图形图像模块也通过Surface从Camera获取流资源,具体步骤详见[图形图像开发指导](subsys-graphics-overview.md)。 + +- 相机运行流程 + 1. Camera创建流程 + + 本进程通过CameraManager创建Camera实例,并从服务端绑定camera设备,创建成功后异步通知developer。类之间的时序图如下: + + **图 1** Camera创建时序图 + + + ![](figure/zh-cn_image_0000001054101094.png) + + + 1. Camera录像/预览流程 + + 开发者首先通过CameraKit创建Camera,然后FrameConfig类对录像或者预览帧属性进行配置。录像/预览时序如下: + + **图 2** Camera录像/预览时序图 + + + ![](figure/zh-cn_image_0000001054421113.png) + + + diff --git a/zh-cn/device-dev/subsystems/subsys-multimedia-camera-photo-guide.md b/zh-cn/device-dev/subsystems/subsys-multimedia-camera-photo-guide.md new file mode 100644 index 0000000000..0e1ebbfecf --- /dev/null +++ b/zh-cn/device-dev/subsystems/subsys-multimedia-camera-photo-guide.md @@ -0,0 +1,396 @@ +# 拍照开发指导 + +- [使用场景](#section1963312376119) +- [接口说明](#section56549532016) +- [约束与限制](#section1165911177314) +- [开发步骤](#section138543918214) + +## 使用场景 + +使用Camera产生图片帧(拍照)。 + +## 接口说明 + +**表 1** API列表 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    类名

    +

    接口名

    +

    描述

    +

    CameraKit

    +

    int32_t GetCameraIds(std::list<string> cameraList)

    +

    获取cameraId列表

    +

    CameraKit

    +

    CameraAbility& GetCameraAbility(string cameraId)

    +

    获取指定camera的能力

    +

    CameraKit

    +

    void RegisterCameraDeviceCallback(CameraDeviceCallback* callback, EventHandler* handler)

    +

    注册camera设备状态回调

    +

    CameraKit

    +

    void UnregisterCameraDeviceCallback(CameraDeviceCallback* callback)

    +

    去注册camera设备状态回调

    +

    CameraKit

    +

    void CreateCamera(string cameraId, CameraStateCallback* callback, EventHandler* handler)

    +

    创建camera实例

    +

    Camera

    +

    string GetCameraId()

    +

    获取cameraID

    +

    Camera

    +

    CameraConfig& GetCameraConfig()

    +

    获取camera配置信息

    +

    Camera

    +

    FrameConfig& GetFrameConfig(int32_t type)

    +

    获取捕获帧类型

    +

    Camera

    +

    void Configure(CameraConfig& config)

    +

    配置camera

    +

    Camera

    +

    void Release()

    +

    释放camera

    +

    Camera

    +

    int TriggerLoopingCapture(FrameConfig& frameConfig)

    +

    开始循环帧捕获

    +

    Camera

    +

    void StopLoopingCapture()

    +

    停止循环帧捕获

    +

    Camera

    +

    int32_t TriggerSingleCapture(FrameConfig& frameConfig)

    +

    抓图

    +

    CameraConfig

    +

    void SetFrameStateCallback(FrameStateCallback* callback, EventHandler* handler);

    +

    设置帧状态回调

    +

    CameraConfig

    +

    static CameraConfig* CreateCameraConfig()

    +

    创建camera配置信息实例

    +

    CameraAbility

    +

    std::list<Size> GetSupportedSizes(int format)

    +

    根据类型获取支持输出图像尺寸大小

    +

    CameraAbility

    +

    std::list<T> GetParameterRange(uint32_t key)

    +

    获取支持的参数范围

    +

    CameraDevice

    +

    CameraDeviceCallback()

    +

    camera设备回调类构造函数

    +

    CameraDevice

    +

    void OnCameraStatus​(std::string cameraId, int32_t status)

    +

    camera设备状态变化时的回调

    +

    CameraStateCallback

    +

    CameraStateCallback​()

    +

    camera状态回调类构造函数

    +

    CameraStateCallback

    +

    void OnConfigured​(Camera& camera)

    +

    camera配置成功回调

    +

    CameraStateCallback

    +

    void OnConfigureFailed​(Camera& camera,int32_t errorCode)

    +

    camera配置失败回调

    +

    CameraStateCallback

    +

    void OnCreated​(Camera& camera)

    +

    camera创建成功回调

    +

    CameraStateCallback

    +

    void OnCreateFailed​(std::string cameraId,int32_t errorCode)

    +

    camera创建失败回调

    +

    CameraStateCallback

    +

    void OnReleased​(Camera& camera)

    +

    camera释放回调

    +

    FrameStateCallback

    +

    FrameStateCallback​()

    +

    帧状态回调类构造函数

    +

    FrameStateCallback

    +

    void OnFrameFinished(Camera& camera, FrameConfig& frameConfig, FrameResult& frameResult)

    +

    拍照帧完成回调

    +

    FrameStateCallback

    +

    void OnFrameError​(Camera& camera, FrameConfig& frameConfig, int32_t errorCode, FrameResult& frameResult)

    +

    拍照帧异常回调

    +

    FrameConfig

    +

    int32_t GetFrameConfigType()

    +

    获取帧配置类型

    +

    FrameConfig

    +

    std::list<OHOS::Surface> GetSurfaces()

    +

    获取帧配置的surface

    +

    FrameConfig

    +

    void AddSurface(OHOS::AGP::UISurface& surface);

    +

    添加surface

    +

    FrameConfig

    +

    void RemoveSurface(OHOS::AGP::UISurface& surface);

    +

    删除surface

    +
    + +## 约束与限制 + +无。 + +## 开发步骤 + +1. 实现设备状态回调的派生类,用户在设备状态发生变更(如新插入相机设备/相机掉线)时,自定义操作。 + + ``` + class SampleCameraDeviceCallback : public CameraDeviceCallback { + void OnCameraStatus(std::string cameraId, int32_t status) override + { + //do something when camera is available/unavailable + } + }; + ``` + +2. 实现帧事件回调的派生类,这里在拿到帧数据以后将其转存为文件。 + + ``` + static void SampleSaveCapture(const char *p, uint32_t size) + { + cout << "Start saving picture" << endl; + struct timeval tv; + gettimeofday(&tv, NULL); + struct tm *ltm = localtime(&tv.tv_sec); + if (ltm != nullptr) { + ostringstream ss("Capture_"); + ss << "Capture" << ltm->tm_hour << "-" << ltm->tm_min << "-" << ltm->tm_sec << ".jpg"; + + ofstream pic("/sdcard/" + ss.str(), ofstream::out | ofstream::trunc); + cout << "write " << size << " bytes" << endl; + pic.write(p, size); + cout << "Saving picture end" << endl; + } + } + + class TestFrameStateCallback : public FrameStateCallback { + void OnFrameFinished(Camera &camera, FrameConfig &fc, FrameResult &result) override + { + cout << "Receive frame complete inform." << endl; + if (fc.GetFrameConfigType() == FRAME_CONFIG_CAPTURE) { + cout << "Capture frame received." << endl; + list surfaceList = fc.GetSurfaces(); + for (Surface *surface : surfaceList) { + SurfaceBuffer *buffer = surface->AcquireBuffer(); + if (buffer != nullptr) { + char *virtAddr = static_cast(buffer->GetVirAddr()); + if (virtAddr != nullptr) { + SampleSaveCapture(virtAddr, buffer->GetSize()); + } + surface->ReleaseBuffer(buffer); + } + delete surface; + } + delete &fc; + } + } + }; + ``` + +3. 实现相机状态回调的派生类,当相机状态发生变化(配置成功/失败,创建成功/失败\)时,自定义操作。 + + ``` + class SampleCameraStateMng : public CameraStateCallback { + public: + SampleCameraStateMng() = delete; + SampleCameraStateMng(EventHandler &eventHdlr) : eventHdlr_(eventHdlr) {} + ~SampleCameraStateMng() + { + if (recordFd_ != -1) { + close(recordFd_); + } + } + void OnCreated(Camera &c) override + { + cout << "Sample recv OnCreate camera." << endl; + auto config = CameraConfig::CreateCameraConfig(); + config->SetFrameStateCallback(&fsCb_, &eventHdlr_); + c.Configure(*config); + cam_ = &c; + } + void OnCreateFailed(const std::string cameraId, int32_t errorCode) override {} + void OnReleased(Camera &c) override {} + }; + ``` + +4. 创建CameraKit,用于创建和获取camera信息。 + + ``` + CameraKit *camKit = CameraKit::GetInstance(); + list camList = camKit->GetCameraIds(); + string camId; + for (auto &cam : camList) { + cout << "camera name:" << cam << endl; + const CameraAbility *ability = camKit->GetCameraAbility(cam); + /* find camera which fits user's ability */ + list sizeList = ability->GetSupportedSizes(0); + if (find(sizeList.begin(), sizeList.end(), CAM_PIC_1080P) != sizeList.end()) { + camId = cam; + break; + } + } + ``` + +5. 创建Camera实例。 + + ``` + EventHandler eventHdlr; // Create a thread to handle callback events + SampleCameraStateMng CamStateMng(eventHdlr); + + camKit->CreateCamera(camId, CamStateMng, eventHdlr); + ``` + +6. 根据[步骤1](#li378084192111)、[步骤2](#li8716104682913)、[步骤3](#li6671035102514)中的回调设计,camera实例创建成功后会进行配置操作,主流程中app需要设计同步机制。 + + ``` + void OnCreated(Camera &c) override + { + cout << "Sample recv OnCreate camera." << endl; + auto config = CameraConfig::CreateCameraConfig(); + config->SetFrameStateCallback(&fsCb_, &eventHdlr_); + c.Configure(*config); + cam_ = &c; + } + + void Capture() + { + if (cam_ == nullptr) { + cout << "Camera is not ready." << endl; + return; + } + FrameConfig *fc = new FrameConfig(FRAME_CONFIG_CAPTURE); + Surface *surface = Surface::CreateSurface(); + if (surface == nullptr) { + delete fc; + return; + } + surface->SetWidthAndHeight(1920, 1080); /* 1920:width,1080:height */ + fc->AddSurface(*surface); + cam_->TriggerSingleCapture(*fc); + } + ``` + + diff --git "a/zh-cn/device-dev/subsystems/\351\242\204\350\247\210\345\274\200\345\217\221\346\214\207\345\257\274.md" b/zh-cn/device-dev/subsystems/subsys-multimedia-camera-preview-guide.md old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/subsystems/\351\242\204\350\247\210\345\274\200\345\217\221\346\214\207\345\257\274.md" rename to zh-cn/device-dev/subsystems/subsys-multimedia-camera-preview-guide.md diff --git "a/zh-cn/device-dev/subsystems/\345\275\225\345\203\217\345\274\200\345\217\221\346\214\207\345\257\274.md" b/zh-cn/device-dev/subsystems/subsys-multimedia-camera-record-guide.md old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/subsystems/\345\275\225\345\203\217\345\274\200\345\217\221\346\214\207\345\257\274.md" rename to zh-cn/device-dev/subsystems/subsys-multimedia-camera-record-guide.md diff --git a/zh-cn/device-dev/subsystems/subsys-multimedia-camera.md b/zh-cn/device-dev/subsystems/subsys-multimedia-camera.md new file mode 100644 index 0000000000..ad7796b692 --- /dev/null +++ b/zh-cn/device-dev/subsystems/subsys-multimedia-camera.md @@ -0,0 +1,11 @@ +# 相机 + +- **[相机开发概述](subsys-multimedia-camera-overview.md)** + +- **[拍照开发指导](subsys-multimedia-camera-photo-guide.md)** + +- **[录像开发指导](subsys-multimedia-camera-record-guide.md)** + +- **[预览开发指导](subsys-multimedia-camera-preview-guide.md)** + + diff --git "a/zh-cn/device-dev/subsystems/\351\237\263\350\247\206\351\242\221\345\274\200\345\217\221\346\246\202\350\277\260.md" b/zh-cn/device-dev/subsystems/subsys-multimedia-video-overview.md old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/subsystems/\351\237\263\350\247\206\351\242\221\345\274\200\345\217\221\346\246\202\350\277\260.md" rename to zh-cn/device-dev/subsystems/subsys-multimedia-video-overview.md diff --git "a/zh-cn/device-dev/subsystems/\351\237\263\350\247\206\351\242\221\346\222\255\346\224\276\345\274\200\345\217\221\346\214\207\345\257\274.md" b/zh-cn/device-dev/subsystems/subsys-multimedia-video-play-guide.md old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/subsystems/\351\237\263\350\247\206\351\242\221\346\222\255\346\224\276\345\274\200\345\217\221\346\214\207\345\257\274.md" rename to zh-cn/device-dev/subsystems/subsys-multimedia-video-play-guide.md diff --git "a/zh-cn/device-dev/subsystems/\351\237\263\350\247\206\351\242\221\345\275\225\345\210\266\345\274\200\345\217\221\346\214\207\345\257\274.md" b/zh-cn/device-dev/subsystems/subsys-multimedia-video-record-guide.md old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/subsystems/\351\237\263\350\247\206\351\242\221\345\275\225\345\210\266\345\274\200\345\217\221\346\214\207\345\257\274.md" rename to zh-cn/device-dev/subsystems/subsys-multimedia-video-record-guide.md diff --git a/zh-cn/device-dev/subsystems/subsys-multimedia-video.md b/zh-cn/device-dev/subsystems/subsys-multimedia-video.md new file mode 100644 index 0000000000..2a59765280 --- /dev/null +++ b/zh-cn/device-dev/subsystems/subsys-multimedia-video.md @@ -0,0 +1,9 @@ +# 音视频 + +- **[音视频开发概述](subsys-multimedia-video-overview.md)** + +- **[音视频播放开发指导](subsys-multimedia-video-play-guide.md)** + +- **[音视频录制开发指导](subsys-multimedia-video-record-guide.md)** + + diff --git a/zh-cn/device-dev/subsystems/subsys-multimedia.md b/zh-cn/device-dev/subsystems/subsys-multimedia.md new file mode 100644 index 0000000000..50fb9b91f2 --- /dev/null +++ b/zh-cn/device-dev/subsystems/subsys-multimedia.md @@ -0,0 +1,7 @@ +# 媒体 + +- **[相机](subsys-multimedia-camera.md)** + +- **[音视频](subsys-multimedia-video.md)** + + diff --git a/zh-cn/device-dev/subsystems/subsys-ota-guide.md b/zh-cn/device-dev/subsystems/subsys-ota-guide.md new file mode 100644 index 0000000000..8b79784683 --- /dev/null +++ b/zh-cn/device-dev/subsystems/subsys-ota-guide.md @@ -0,0 +1,358 @@ +# OTA升级 + +- [约束与限制](#section691733275418) +- [生成公私钥对](#section94411533155010) +- [生成升级包](#section632383718539) +- [上传升级包](#section5772112473213) +- [下载升级包](#section251732474917) +- [厂商应用集成OTA能力](#section298217330534) +- [API应用场景-默认场景](#section7685171192916) + - [开发指导](#section0745926153017) + - [示例代码](#section1337111363306) + +- [API应用场景-定制场景](#section1686395317306) + - [开发指导](#section524515314317) + - [示例代码](#section525974743120) + +- [系统升级](#section151997114334) + +OTA(Over the Air)提供对设备远程升级的能力,可以让您的设备(如IP摄像头等),轻松支持远程升级能力。目前仅支持全量包升级,暂不支持差分包升级。全量包升级是将新系统全部内容做成升级包,进行升级;差分包升级是将新老系统的差异内容做成升级包,进行升级。 + +## 约束与限制 + +- 支持基于Hi3861/Hi3518EV300/Hi3516DV300芯片的开源套件。 +- 对Hi3518EV300/Hi3516DV300开源套件,设备需要支持SD卡(VFAT格式)。 + +## 生成公私钥对 + +1. 准备工作:在Windows PC 上,下载安装OpenSSL工具,并配置环境变量。OpenSSL下载路径: + + [http://slproweb.com/products/Win32OpenSSL.html](http://slproweb.com/products/Win32OpenSSL.html) + +2. 在tools\\update\_tools\\update\_pkg\_tools目录下,下载升级包制作工具,保存到Windows本地路径,例如D:\\ota\_tools。 +3. 如图,运行ota\_tools\\key下的Generate\_public\_private\_key.bat ,生成公钥Metis\_PUBLIC.key、私钥private.key和公钥对应的数组public\_arr.txt文件,请妥善保管私钥private.key。 + + **图 1** 生成公私钥对 + + + ![](figure/zh-cn_image_0000001060200050.png) + +4. 用public\_arr.txt里面的全部内容替换OTA模块base\\update\\ota\_lite\\frameworks\\source\\verify\\hota\_verify.c中的g\_pubKeyBuf 。 + + 示例,public\_arr.txt内容 + + ``` + 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, + ``` + + 示例,OTA模块的公钥 + + ``` + #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, + ``` + +5. 对Hi3518EV300/Hi3516DV300套件,在上一步的基础上,还需用public\_arr.txt里面的全部内容替换uboot模块device\\hisilicon\\third\_party\\uboot\\u-boot-2020.01\\product\\hiupdate\\verify\\update\_public\_key.c中的g\_pub\_key中的全部内容。 + + 示例,uboot模块的公钥 + + ``` + static unsigned char g_pub_key[PUBKEY_LEN] = { + 0x30, 0x82, 0x01, 0x0A, 0x02, 0x82, 0x01, 0x01, + 0x00, 0xBF, 0xAA, 0xA5, 0xB3, 0xC2, 0x78, 0x5E, + ``` + + +## 生成升级包 + +1. 在ota\_tools\\Components目录下,归放需要升级的文件。 + + **图 2** 原始镜像归放位置 + + + ![](figure/zh-cn_image_0000001061889268.png) + + **表 1** 升级包内的文件 + + + + + + + + + + + + + + + + + + + + + + +

    包内文件名

    +

    说明

    +

    u-boot.bin

    +

    将编译生成的u-boot-hi351XevX00.bin文件重命名后得到。

    +

    kernel.bin

    +

    将编译生成的liteos.bin/kernel文件重命名后得到。

    +

    rootfs.img

    +

    将编译生成的rootfs_xxxxx.img文件重命名后得到。

    +

    config

    +

    与开发板类型和内核类型相关,参考开源套件的SD卡烧写说明。

    +

    OTA.tag

    +

    共32字节,内容为:“package_type:otaA1S2D3F4G5H6J7K8”;其中后16字节为随机数,需要随版本变化。

    +
    + +2. 修改ota\_tools\\xml下的packet\_harmony.xml文件,配置compAddr分区名,对应ota\_tools\\Components\\的文件,其它项不需修改,作为扩展项预留。 + + 示例,配置组件信息 + + ``` + + + .\Components\rootfs_jffs2.img + .\Components\liteos.bin + .\Components\userfs_jffs2.img + + ``` + +3. 将生成的公私钥路径配置到ota\_tools\\xml路径下的packet\_harmony.xml中。 + + 示例,配置公私钥路径 + + ``` + + .\key\private.key + .\key\Metis_PUBLIC.key + + ``` + +4. 在ota\_tools\\VersionDefine.bat中设置产品名称、软件版本号(用于防回滚校验)。 + + 示例,配置产品名称和版本号 + + ``` + set FILE_PRODUCT_NAME=Hisi + + @rem 设置软件版本号 不要超过16位 + set SOFTWARE_VER=OpenHarmony 1.1 + ``` + +5. 执行ota\_tools下的Make\_Harmony\_PKG.bat,生成升级包Hisi\_OpenHarmony 1.1.bin。升级包通过SHA256+RSA2048方式签名,保证完整性和合法性。 + + **图 3** 升级包制作工具 + + + ![](figure/zh-cn_image_0000001059334449.png) + + +## 上传升级包 + +将升级包Hisi\_OpenHarmony 1.1.bin上传到厂商的OTA服务器。 + +## 下载升级包 + +1. 厂商应用从OTA服务器下载Hisi\_OpenHarmony 1.1.bin。 +2. 对Hi3518EV300/Hi3516DV300开源套件,需要插入SD卡\(容量\>100MBytes\)。 + +## 厂商应用集成OTA能力 + +- 调用OTA模块的动态库libhota.so,对应头文件位于:base\\update\\ota\_lite\\interfaces\\kits\\hota\_partition.h&hota\_updater.h; +- libhota.so对应的源码路径为base\\update\\ota\_lite\\frameworks\\source。 +- API的使用方法,见本文“API应用场景”和API文档的OTA接口章节。 +- 如果需要适配开发板,请参考HAL层头文件:base\\update\\ota\_lite\\hals\\hal\_hota\_board.h。 + +## API应用场景-默认场景 + +升级包是按照上文“生成公私钥对”和“生成升级包”章节制作的。 + +### **开发指导** + +1. 应用侧通过下载,获取当前设备升级包后,调用HotaInit接口初始化OTA模块。 +2. 调用HotaWrite接口传入升级包数据流,接口内部实现校验、解析及写入升级数据流。 +3. 写入完成后,调用HotaRestart接口重启系统。 + + 升级过程中,使用HotaCancel接口可以取消升级。 + + +### **示例代码** + +使用OpenHarmony的“升级包格式和校验方法“进行升级。 + +``` +int main(int argc, char **argv) +{ + printf("this is update print!\r\n"); + if (HotaInit(NULL, NULL) < 0) { + printf("ota update init fail!\r\n"); + return -1; + } + int fd = open(OTA_PKG_FILE, O_RDWR, S_IRUSR | S_IWUSR); + if (fd < 0) { + printf("file open failed, fd = %d\r\n", fd); + (void)HotaCancel(); + return -1; + } + int offset = 0; + int fileLen = lseek(fd, 0, SEEK_END); + int leftLen = fileLen; + while (leftLen > 0) { + if (lseek(fd, offset, SEEK_SET) < 0) { + close(fd); + printf("lseek fail!\r\n"); + (void)HotaCancel(); + return -1; + } + int tmpLen = leftLen >= READ_BUF_LEN ? READ_BUF_LEN : leftLen; + (void)memset_s(g_readBuf, READ_BUF_LEN, 0, READ_BUF_LEN); + if (read(fd, g_readBuf, tmpLen) < 0) { + close(fd); + printf("read fail!\r\n"); + (void)HotaCancel(); + return -1; + } + if (HotaWrite((unsigned char *)g_readBuf, offset, tmpLen) != 0) { + printf("ota write fail!\r\n"); + close(fd); + (void)HotaCancel(); + return -1; + } + offset += READ_BUF_LEN; + leftLen -= tmpLen; + } + close(fd); + printf("ota write finish!\r\n"); + printf("device will reboot in 10s...\r\n"); + sleep(10); + (void)HotaRestart(); + return 0; +} +``` + +## API应用场景-定制场景 + +升级包不是按照上文“生成公私钥对”和“生成升级包”章节制作的,是通过其它方式制作的。 + +### **开发指导** + +1. 应用侧通过下载,获取当前设备升级包后,调用HotaInit接口初始化。 +2. 使用HotaSetPackageType接口设置NOT\_USE\_DEFAULT\_PKG,使用"定制"流程。 +3. 调用HotaWrite接口传入升级包数据流,写入设备。 +4. 写入完成后,调用HotaRead接口读取数据,厂商可以自行校验升级包。 +5. 调用HotaSetBootSettings设置启动标记,在重启后需要进入uboot模式时使用(可选)。 +6. 调用HotaRestart接口,进行重启。 + + 升级过程中,使用HotaCancel接口可以取消升级。 + + +### **示例代码** + +使用非OpenHarmony的“升级包格式和校验方法“进行升级。 + +``` +int main(int argc, char **argv) +{ + printf("this is update print!\r\n"); + if (HotaInit(NULL, NULL) < 0) { + printf("ota update init fail!\r\n"); + (void)HotaCancel(); + return -1; + } + (void)HotaSetPackageType(NOT_USE_DEFAULT_PKG); + int fd = open(OTA_PKG_FILE, O_RDWR, S_IRUSR | S_IWUSR); + if (fd < 0) { + printf("file open failed, fd = %d\r\n", fd); + (void)HotaCancel(); + return -1; + } + int offset = 0; + int fileLen = lseek(fd, 0, SEEK_END); + int leftLen = fileLen; + while (leftLen > 0) { + if (lseek(fd, offset, SEEK_SET) < 0) { + close(fd); + printf("lseek fail!\r\n"); + (void)HotaCancel(); + return -1; + } + int tmpLen = leftLen >= READ_BUF_LEN ? READ_BUF_LEN : leftLen; + (void)memset_s(g_readBuf, READ_BUF_LEN, 0, READ_BUF_LEN); + if (read(fd, g_readBuf, tmpLen) < 0) { + close(fd); + printf("read fail!\r\n"); + (void)HotaCancel(); + return -1; + } + if (HotaWrite((unsigned char *)g_readBuf, offset, tmpLen) != 0) { + printf("ota write fail!\r\n"); + close(fd); + (void)HotaCancel(); + return -1; + } + offset += READ_BUF_LEN; + leftLen -= tmpLen; + } + close(fd); + printf("ota write finish!\r\n"); + leftLen = fileLen; + while (leftLen > 0) { + int tmpLen = leftLen >= READ_BUF_LEN ? READ_BUF_LEN : leftLen; + (void)memset_s(g_readBuf, READ_BUF_LEN, 0, READ_BUF_LEN); + if (HotaRead(offset, READ_BUF_LEN, (unsigned char *)g_readBuf) != 0) {} + printf("ota write fail!\r\n"); + (void)HotaCancel(); + return -1; + } + /* do your verify and parse */ + offset += READ_BUF_LEN; + leftLen -= tmpLen; + } + /* set your boot settings */ + (void)HotaSetBootSettings(); + printf("device will reboot in 10s...\r\n"); + sleep(10); + (void)HotaRestart(); + return 0; +} +``` + +## 系统升级 + +厂商应用调用OTA模块的API,OTA模块执行升级包的签名验证、版本防回滚、烧写落盘功能,升级完成后自动重启系统。 + +对Hi3518EV300/Hi3516DV300开源套件,在需要实现防回滚功能的版本中,需要增加LOCAL\_VERSION的值,如"ohos default 1.0"-\>"ohos default 1.1",LOCAL\_VERSION在device\\hisilicon\\third\_party\\uboot\\u-boot-2020.01\\product\\hiupdate\\ota\_update\\ota\_local\_info.c中。 + +示例,增加版本号 + +``` +const char *get_local_version(void) +{ +#if defined(CONFIG_TARGET_HI3516EV200) || \ + defined(CONFIG_TARGET_HI3516DV300) || \ + defined(CONFIG_TARGET_HI3518EV300) +#define LOCAL_VERSION "ohos default 1.0" /* increase: default release version */ +``` + diff --git "a/zh-cn/device-dev/subsystems/\345\210\206\345\270\203\345\274\217\350\277\234\347\250\213\345\220\257\345\212\250.md" b/zh-cn/device-dev/subsystems/subsys-remote-start.md old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/subsystems/\345\210\206\345\270\203\345\274\217\350\277\234\347\250\213\345\220\257\345\212\250.md" rename to zh-cn/device-dev/subsystems/subsys-remote-start.md diff --git "a/zh-cn/device-dev/subsystems/IPC\351\200\232\344\277\241\351\211\264\346\235\203\345\274\200\345\217\221\346\214\207\345\257\274.md" b/zh-cn/device-dev/subsystems/subsys-security-communicationverify.md old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/subsystems/IPC\351\200\232\344\277\241\351\211\264\346\235\203\345\274\200\345\217\221\346\214\207\345\257\274.md" rename to zh-cn/device-dev/subsystems/subsys-security-communicationverify.md diff --git a/zh-cn/device-dev/subsystems/subsys-security-overview.md b/zh-cn/device-dev/subsystems/subsys-security-overview.md new file mode 100644 index 0000000000..5c47b30808 --- /dev/null +++ b/zh-cn/device-dev/subsystems/subsys-security-overview.md @@ -0,0 +1,76 @@ +# 概述 + +- [基本概念](#section175012297491) +- [约束与限制](#section2029921310472) + +OpenHarmony安全子系统目前提供给开发者的安全能力主要包含应用可信、权限管理、设备可信。涉及以下几个模块: + +- 应用验签 + + 为了确保应用内容的完整性,系统通过应用签名和Profile对应用的来源进行管控,同时对于调试应用,还可通过验签接口验证应用和设备的UDID是否匹配,确保应用安装在了正确的设备上。 + +- 应用权限管理 + + 应用权限是管理应用访问系统资源和使用系统能力的一种通用方式,应用在开发阶段需要在profile.json中指明此应用在运行过程中可能会调用哪些权限,其中静态权限表示只需要在安装阶段注册就可以,而动态权限一般表示涉及到敏感信息,所以需要用户进行动态授权。 + +- IPC通信鉴权 + + 系统服务通过IPC暴露接口给其他进程访问,这些接口需要配置相应的访问策略,当其他进程访问这些接口时,将会触发IPC通信鉴权机制校验访问进程是否拥有权限访问该接口,若无权限,则拒绝访问该接口。 + +- 可信设备群组管理 + + 提供基于群组概念的同华为账号群组、点对点群组(如二维码、碰一碰等)的设备安全可信关系的创建和查询,分布式应用可基于该能力进行设备间的可信认证,然后向分布式软总线请求设备间安全会话。 + + +## 基本概念 + +在进行依赖验签组件的应用开发前,开发者应了解以下基本概念: + +- Samgr + + Samgr\(System Ability Manager\)系统能力管理,在OpenHarmony上作为一个管理系统能力的模块,详见系统服务框架子系统。 + + +- BMS + + BMS\(Bundle Manager Service\)包管理管理,在OpenHarmony上主要负责应用的安装、卸载和数据管理。 + + +- 描述文件 + + 本文中的描述文件,指HarmonyAppProvision,简称profile。HarmonyAppProvision采用json文件格式进行描述。 + + +- 叶子证书 + + 最终用于为整包或profile签名的证书称为叶子证书,位于数字证书链的最末端。 + + +- 调试应用 + + 指开发者从应用市场申请调试证书与调试描述文件,并以此签名的hap包。 + + +- 待上架应用 + + 指开发者从应用市场申请发布证书与发布描述文件,以此签名,未通过应用市场正式发布的hap包。 + + +- 发布应用 + + 指开发者从应用市场申请发布证书与发布描述文件,以此签名的hap包,上传至应用市场,并由应用市场正式发布的hap包。 + + +- OpenHarmony自签名应用 + + 当开发者自行编译OpenHarmony系统应用后,采用原应用描述文件,以及公开的OpenHarmony公私钥对和证书进行自签名产生的hap包。 + + +## 约束与限制 + +- 仅支持以下三类应用的验签:应用市场调试应用、应用市场发布应用、OpenHarmony自签名应用的验签。 +- 若对应用市场调试应用验签,则本机UDID需要在描述文件包含的UDID列表中。 +- 待上架应用无法验签通过。 +- 验签组件提供的接口都位于security\_interfaces\_innerkits\_app\_verify仓[app\_verify\_pub.h](https://gitee.com/fork_ohos_wj/security_interfaces_innerkits_app_verify/blob/master/app_verify_pub.h)中,仅支持系统应用开发者调用。 +- 可信设备群组管理接口,目前只对系统签名权限才可以使用。 + diff --git a/zh-cn/device-dev/subsystems/subsys-security-rightmanagement.md b/zh-cn/device-dev/subsystems/subsys-security-rightmanagement.md new file mode 100644 index 0000000000..37f3cdbbf7 --- /dev/null +++ b/zh-cn/device-dev/subsystems/subsys-security-rightmanagement.md @@ -0,0 +1,228 @@ +# 应用权限管理开发指导 + +- [运作机制](#section193961322175011) +- [场景介绍](#section18502174174019) +- [接口说明](#section1633115419401) +- [开发步骤](#section022611498210) + +## 运作机制 + +由于OpenHarmony允许安装三方应用,所以需要对三方应用的敏感权限调用进行管控,具体实现是应用在开发阶段就需要在profile.json中指明此应用在运行过程中可能会调用哪些敏感权限,这些权限包括静态权限和动态权限,静态权限表示只需要在安装阶段注册就可以,而动态权限一般表示获取用户的敏感信息,所以需要在运行时让用户确认才可以调用,授权方式包括系统设置应用手动授权等。除了运行时对应用调用敏感权限进行管控外,还需要利用应用签名管控手段确保应用安装包已经被设备厂商进行了确认。 + +**表 1** OpenHarmony权限列表 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    OpenHarmony权限

    +

    授权方式

    +

    权限说明

    +

    ohos.permission.LISTEN_BUNDLE_CHANGE

    +

    system_grant(静态权限)

    +

    允许该应用获取应用变化消息。

    +

    ohos.permission.GET_BUNDLE_INFO

    +

    system_grant(静态权限)

    +

    允许该应用获取应用信息。

    +

    ohos.permission.INSTALL_BUNDLE

    +

    system_grant(静态权限)

    +

    允许该应用安装应用。

    +

    ohos.permission.CAMERA

    +

    user_grant(动态权限)

    +

    此应用可随时使用相机拍摄照片和录制视频。

    +

    ohos.permission.MODIFY_AUDIO_SETTINGS

    +

    system_grant(静态权限)

    +

    允许该应用修改全局音频设置,例如音量和用于输出的扬声器。

    +

    ohos.permission.READ_MEDIA

    +

    user_grant(动态权限)

    +

    允许该应用读取您的视频收藏。

    +

    ohos.permission.MICROPHONE

    +

    user_grant(动态权限)

    +

    此应用可随时使用麦克风进行录音。

    +

    ohos.permission.WRITE_MEDIA

    +

    user_grant(动态权限)

    +

    允许该应用写入您的音乐收藏。

    +

    ohos.permission.DISTRIBUTED_DATASYNC

    +

    user_grant(动态权限)

    +

    管控分布式数据传输能力。

    +

    ohos.permission.DISTRIBUTED_VIRTUALDEVICE

    +

    user_grant(动态权限)

    +

    允许应用使用分布式虚拟能力

    +
    + +>![](../public_sys-resources/icon-note.gif) **说明:** +>静态权限:应用安装时由系统授予的权限,对应于权限敏感级别的system\_grant +>动态权限:应用在运行过程中需要用户授权的权限,对应于权限敏感级别的user\_grant + +## 场景介绍 + +应用权限是软件用来访问系统资源和使用系统能力的一种通行方式。在涉及用户隐私相关功能和数据的场景,例如:访问个人设备的硬件特性,如摄像头、麦克风,以及读写媒体文件等,OpenHarmony通过应用权限管理组件来保护这些数据以及能力。 + +在系统应用开发过程中,如果应用要使用敏感权限,开发者可以调用应用权限管理组件接口检查待访问权限是否被授权,如果未授权,操作不允许。 + +## 接口说明 + +应用权限管理提供的API接口,当前仅供系统应用和系统服务调用,具体API接口如下。 + +**表 2** 应用权限管理API接口功能介绍 + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    接口名

    +

    描述

    +

    int CheckPermission(int uid, const char *permissionName)

    +

    检查指定UID的应用进程是否具有访问系统服务API的权限

    +

    int CheckSelfPermission(const char *permissionName)

    +

    检查调用者是否具有访问系统服务API的权限

    +

    int QueryPermission(const char *identifier, PermissionSaved **permissions, int *permNum)

    +

    查询应用申请的所有权限,并检查权限是否被授予

    +

    int GrantPermission(const char *identifier, const char *permName)

    +

    将指定权限授予应用程序

    +

    int RevokePermission(const char *identifier, const char *permName)

    +

    收回应用程序的指定权限

    +

    int GrantRuntimePermission(int uid, const char *permissionName)

    +

    应用运行时动态授予指定权限

    +

    int RevokeRuntimePermission(int uid, const char *permissionName)

    +

    应用运行时动态撤销指定权限

    +
    + +## 开发步骤 + +本部分以包管理器的应用权限开发为例进行讲解。开发过程中,首先需要明确涉及的敏感权限,并在config.json中声明该权限,在安装应用程序时,包管理器会调用应用权限管理组件的接口检查该权限是否被授予,若授予,安装流程正常进行,否则安装失败。 + +1. 在开发过程中,包管理器明确需要安装应用的权限(ohos.permission.INSTALL\_BUNDLE),并在config.json中声明该权限; + + ``` + { + ... + "module": { + "package": "com.huawei.kitframework", + "deviceType": [ + "phone", "tv","tablet", "pc","car","smartWatch","sportsWatch","smartCamera", "smartVision" + ], + "reqPermissions": [{ + // 声明需要的权限:安装应用程序的权限名 + "name": "ohos.permission.INSTALL_BUNDLE", + "reason": "install bundle", + "usedScene": { + "ability": [ + "KitFramework" + ], + "when": "always" + } + }, + { + "name": "ohos.permission.LISTEN_BUNDLE_CHANGE", + "reason": "install bundle", + "usedScene": { + "ability": [ + "KitFramework" + ], + "when": "always" + } + }, + { + "name": "ohos.permission.GET_BUNDLE_INFO", + "reason": "install bundle", + "usedScene": { + "ability": [ + "KitFramework" + ], + "when": "always" + } + } + ], + ... + } + ``` + +2. 当包管理器开发应用安装功能接口时,会调用权限管理相关接口检查自身是否具有安装应用程序的权限,例如:以安装应用的权限名"ohos.permission.INSTALL\_BUNDLE"作为入参,调用CheckPermission接口检查包管理器是否具有安装应用的权限,如果有权限,安装流程继续执行,否则返回安装失败; + + ``` + constexpr static char PERMISSION_INSTALL_BUNDLE[] = "ohos.permission.INSTALL_BUNDLE"; + + bool Install(const char *hapPath, const InstallParam *installParam, InstallerCallback installerCallback) + { + if ((hapPath == nullptr) || (installerCallback == nullptr) || (installParam == nullptr)) { + HILOG_ERROR(HILOG_MODULE_APP, "BundleManager install failed due to nullptr parameters"); + return false; + } + // 检查ohos.permission.INSTALL_BUNDLE权限是否被授予 + if (CheckPermission(0, static_cast(PERMISSION_INSTALL_BUNDLE)) != GRANTED) { + HILOG_ERROR(HILOG_MODULE_APP, "BundleManager install failed due to permission denied"); + return false; // 返回安装失败 + } + // 安装流程 + ... + } + ``` + + diff --git a/zh-cn/device-dev/subsystems/subsys-security-sigverify.md b/zh-cn/device-dev/subsystems/subsys-security-sigverify.md new file mode 100644 index 0000000000..a7e2f85b64 --- /dev/null +++ b/zh-cn/device-dev/subsystems/subsys-security-sigverify.md @@ -0,0 +1,272 @@ +# 应用验签开发指导 + +- [场景介绍](#section18502174174019) +- [验签流程](#section554632717226) +- [接口说明](#section1633115419401) +- [开发步骤(场景一)](#section4207112818418) + - [验签指导](#section11470123816297) + - [生成OpenHarmony自签名应用](#section167151429133312) + - [开发示例](#section174318361353) + +- [开发步骤(场景二)](#section81272563427) + - [验签指导](#section07028210442) + - [开发示例](#section1930711345445) + +- [调测验证](#section427316292411) + +## 场景介绍 + +当需要验证调试应用、发布应用,OpenHarmony自签名应用的完整性是否被破坏时,可以调用验签组件的接口进行验证。如有需要还可通过验签接口获取部分描述文件信息,如appid。对于调试应用,还可通过验签接口验证应用和设备的UDID是否匹配,确保应用安装在了正确的设备上。 + +## 验签流程 + +未经签名的Hap包的压缩方式是ZIP格式,简单分为文件块,中心目录(Central directory)块,中心目录结尾(EOCD,End of central directory record)块。 + +经过签名的Hap包,在文件块,和中心目录块之间,插入了签名块。签名块由文件签名数据块(data sign block)、描述文件签名数据块(profile sign block)和签名头(sign head)组成,如下图所示。 + +**图 1** 经过签名的Hap包结构 + + +![](figure/安全子系统.png) + +整个验签流程,主要分为三部分:整包验签、描述文件签名块验签,以及描述文件内容校验。 + +**整包验签** + +用设备的预置根证书,通过证书链来证明叶子证书本身是可信的,然后用叶子证书的公钥解密出的摘要证明整包是未篡改的。 + +具体操作步骤如下: + +1. 对文件签名数据块中的证书链进行校验,确定其叶子证书是可信的。 +2. 用叶子证书中的公钥对文件签名块进行验签,证明其未被篡改。 +3. 计算并合并文件块,中心目录块和中心目录结尾块的摘要。然后将计算结果,再与签名块中的描述文件签名块的摘要合并,将最终合并的摘要与文件签名块中包含的摘要对比,如果两者相等,则整包验签通过。 + +**描述文件签名块验签** + +首先判断文件签名的签发单位,如果是应用市场签发的发布应用,则无需对描述文件进行验签,直接信任,否则要对其验签。先取出整个描述文件签名块,然后验证证书链,最后用叶子证书对描述文件数据块验签,证明其未被篡改。 + +**描述文件内容校验** + +取出描述文件,并对其内容进行合法性检查。其中若hap包为调试应用,则会比对本机UDID与描述文件中包含的UDID列表,如果本机UDID在描述文件的UDID列表中包含,则验证通过。比较描述文件中包含的证书(如果是应用市场发布应用或OpenHarmony自签名则无需比较),和整包校验时使用的叶子证书,如果相同,认为整个验签流程完成。 + +## 接口说明 + +验签组件当前提供innerkits接口,仅供系统应用调用,相关接口及功能描述如下: + +**表 1** 验签组件API接口功能介绍 + + + + + + + + + + + + + + + + +

    接口名

    +

    描述

    +

    int APPVERI_AppVerify(const char *filePath, VerifyResult *verifyRst)

    +

    主入口函数,输入文件路径,进行验签,并将从描述文件中获取的数据通过verifyRst返回给调用者

    +

    int APPVERI_SetDebugMode(bool mode)

    +

    设置测试模式,设置mode为true,则支持基于测试根密钥的证书链校验,设置mode为false,则关闭基于测试根密钥的证书链校验。

    +

    注:当前没有基于现有测试根密钥的证书,开发者可根据自身需要,替换测试根密钥并进行相关验证。

    +

    void APPVERI_FreeVerifyRst(VerifyResult *verifyRst)

    +

    释放verifyRst中申请的内存

    +
    + +## 开发步骤(场景一) + +### 验签指导 + +对应用市场发布应用、基于应用市场调试证书签发的调试应用、OpenHarmony自签名应用的校验。 + +1. 定义出参结构体变量VerifyResult; + + ``` + VerifyResult verifyResult = {0}; + ``` + +2. 以文件路径及VerifyResult为入参,调用APPVERI\_AppVerify进行文件校验; + + ``` + int32_t ret = APPVERI_AppVerify(hapFilepath.c_str(), &verifyResult); + ``` + +3. 判断返回结果,如果校验通过的话,获取VerifyResult中的数据,进行业务处理; + + ``` + signatureInfo.appId = verifyResult.profile.appid; + signatureInfo.provisionBundleName = verifyResult.profile.bundleInfo.bundleName; + ``` + +4. 调用APPVERI\_FreeVerifyRst,释放VerifyResult中申请的内存。 + + ``` + APPVERI_FreeVerifyRst(&verifyResult); + ``` + + +### 生成OpenHarmony自签名应用 + +如果是OpenHarmony自签名应用的校验,开发者可通过以下方式生成OpenHarmony自签名应用。 + +1. 材料备齐。 + + 生成自签名应用需要的材料有:签名工具、系统应用hap包、系统应用profile文件\(\*.p7b\)、签名证书\(\*.cer\)、签名公私钥对\(\*.jks\)。 + +2. 将所有材料放在同一个目录下,打开shell。 +3. 根据应用、描述文件的实际名称修改指令,并在shell中输入,完成签名。 + + ``` + java -jar hapsigntoolv2.jar sign -mode localjks -privatekey "OpenHarmony Software Signature" -inputFile camera.hap -outputFile signed_camera.hap -signAlg SHA256withECDSA -keystore OpenHarmony.jks -keystorepasswd 123456 -keyaliaspasswd 123456 -profile camera_release.p7b -certpath OpenHarmony.cer -profileSigned 1 + ``` + + 关键字段说明: + + -jar:签名工具,[hapsigntool](https://repo.huaweicloud.com/harmonyos/develop_tools/hapsigntoolv2.jar) + + -mode:本地签名标记位,固定为localjks + + -privatekey:密钥对别名,签名公私钥对的别名为OpenHarmony Software Signature + + -inputFile:待签名应用,通过编译产生 + + -outputFile:签名后应用,最终输出 + + -signAlg:签名算法,当前固定为SHA256withECDSA + + -keystore:公私钥对,使用签名公私钥对,位于开源库security\_services\_app\_verify仓中OpenHarmonyCer目录下,[OpenHarmony.jks](https://gitee.com/openharmony/security_appverify/blob/master/interfaces/innerkits/appverify_lite/OpenHarmonyCer/OpenHarmony.jks)。默认密码为123456 ,用户可采用工具\(例如keytool\)更改默认密码 + + -keystorepasswd:公私钥对密码,默认签名公私钥对密码为123456 + + -keyaliaspasswd:公私钥对别名密码,默认签名公私钥对别名密码为123456 + + -profile:描述文件,应用的描述文件位于对应源代码目录中 + + -certpath:使用签名证书,位于开源库security\_services\_app\_verify仓中OpenHarmonyCer目录下,[OpenHarmony.cer](https://gitee.com/openharmony/security_appverify/blob/master/interfaces/innerkits/appverify_lite/OpenHarmonyCer/OpenHarmony.cer) + + -profileSigned:签名块中是否包含描述文件\(profile\)。固定为1(包含) + + +### 开发示例 + +以应用管理框架组件在应用安装时进行验签的实际调用为例: + +``` +uint8_t HapSignVerify::VerifySignature(const std::string &hapFilepath, SignatureInfo &signatureInfo) +{ + bool mode = ManagerService::GetInstance().IsDebugMode(); + HILOG_INFO(HILOG_MODULE_APP, "current mode is %d!", mode); + // 定义结果结构体 + VerifyResult verifyResult = {0}; + // 输入待验签文件路径进行验签 + int32_t ret = APPVERI_AppVerify(hapFilepath.c_str(), &verifyResult); + uint8_t errorCode = SwitchErrorCode(ret); + if (errorCode != ERR_OK) { + return errorCode; + } + // 从结果结构体中获取appid + signatureInfo.appId = verifyResult.profile.appid; + // 从结果结构体中获取描述文件中书写的应用名 + signatureInfo.provisionBundleName = verifyResult.profile.bundleInfo.bundleName; + int32_t restricNum = verifyResult.profile.permission.restricNum; + for (int32_t i = 0; i < restricNum; i++) { + signatureInfo.restrictedPermissions.emplace_back((verifyResult.profile.permission.restricPermission)[i]); + } + // 释放结果结构体中申请的内存 + APPVERI_FreeVerifyRst(&verifyResult); + return ERR_OK; +} +``` + +## 开发步骤(场景二) + +### 验签指导 + +对采用基于测试根密钥证书签名的应用的校验。 + +1. 调用APPVERI\_SetDebugMode\(true\)开启测试模式; + + ``` + ManagerService::SetDebugMode(true); + ... + uint8_t ManagerService::SetDebugMode(bool enable) + { + int32_t ret = APPVERI_SetDebugMode(enable); + if (ret < 0) { + HILOG_ERROR(HILOG_MODULE_APP, "set signature debug mode failed"); + return ERR_APPEXECFWK_SET_DEBUG_MODE_ERROR; + } + isDebugMode_ = enable; + HILOG_INFO(HILOG_MODULE_APP, "current sign debug mode is %d", isDebugMode_); + return ERR_OK; + } + ``` + +2. 同场景一中步骤一至四,定义结构体,校验、释放结构体; +3. 调用APPVERI\_SetDebugMode\(false\)关闭测试模式。 + + ``` + ManagerService::SetDebugMode(false); + ``` + + +### 开发示例 + +完整开发示例如下(在场景一代码示例的基础上进行补充): + +``` +uint8_t ManagerService::SetDebugMode(bool enable) +{ + int32_t ret = APPVERI_SetDebugMode(enable); + if (ret < 0) { + HILOG_ERROR(HILOG_MODULE_APP, "set signature debug mode failed"); + return ERR_APPEXECFWK_SET_DEBUG_MODE_ERROR; + } + isDebugMode_ = enable; + HILOG_INFO(HILOG_MODULE_APP, "current sign debug mode is %d", isDebugMode_); + return ERR_OK; +} +uint8_t HapSignVerify::VerifySignature(const std::string &hapFilepath, SignatureInfo &signatureInfo) +{ + // 开启支持测试服务器签名应用验证 + ManagerService::SetDebugMode(true); + bool mode = ManagerService::GetInstance().IsDebugMode(); + HILOG_INFO(HILOG_MODULE_APP, "current mode is %d!", mode); + // 定义结果结构体 + VerifyResult verifyResult = {0}; + // 输入待验签文件路径进行验签 + int32_t ret = APPVERI_AppVerify(hapFilepath.c_str(), &verifyResult); + uint8_t errorCode = SwitchErrorCode(ret); + if (errorCode != ERR_OK) { + return errorCode; + } + // 从结果结构体中获取appid + signatureInfo.appId = verifyResult.profile.appid; + // 从结果结构体中获取描述文件中书写的应用名 + signatureInfo.provisionBundleName = verifyResult.profile.bundleInfo.bundleName; + int32_t restricNum = verifyResult.profile.permission.restricNum; + for (int32_t i = 0; i < restricNum; i++) { + signatureInfo.restrictedPermissions.emplace_back((verifyResult.profile.permission.restricPermission)[i]); + } + // 释放结果结构体中申请的内存 + APPVERI_FreeVerifyRst(&verifyResult); + // 关闭支持测试服务器签名应用验证 + ManagerService::SetDebugMode(false); + return ERR_OK; +} +``` + +## 调测验证 + +1. 选取一个在OpenHarmony上能够正常安装的应用A。 +2. 根据开发指导开发。 +3. 对应用A,采用自开发程序进行验签,验签通过,能获取到appid。即为开发成功。 + diff --git a/zh-cn/device-dev/subsystems/subsys-security.md b/zh-cn/device-dev/subsystems/subsys-security.md new file mode 100644 index 0000000000..1a0b0eb101 --- /dev/null +++ b/zh-cn/device-dev/subsystems/subsys-security.md @@ -0,0 +1,11 @@ +# 安全 + +- **[概述](subsys-security-overview.md)** + +- **[应用验签开发指导](subsys-security-sigverify.md)** + +- **[应用权限管理开发指导](subsys-security-rightmanagement.md)** + +- **[IPC通信鉴权开发指导](subsys-security-communicationverify.md)** + + diff --git a/zh-cn/device-dev/subsystems/subsys-testguide-test.md b/zh-cn/device-dev/subsystems/subsys-testguide-test.md new file mode 100644 index 0000000000..2403929934 --- /dev/null +++ b/zh-cn/device-dev/subsystems/subsys-testguide-test.md @@ -0,0 +1,989 @@ +# 测试 + +- [概述](#section12403172115920) + - [基本概念](#section53632272090) + - [运作机制](#section2394431106) + +- [约束与限制](#section2029921310472) +- [搭建环境](#section175012297491) + - [环境要求](#section935055691014) + - [安装环境](#section6511193210111) + - [检验环境是否搭建成功](#section1899144517117) + +- [开发指导](#section16741101301210) + - [场景介绍](#section93782214124) + - [接口说明](#section54131732101218) + - [开发步骤](#section53541946111218) + +- [开发实例](#section7477121918136) +- [测试平台使用](#section76401945124810) +- [包结构说明](#section1875515364133) + +## 概述 + +### 基本概念 + +测试子系统提供基于python开发的一键式的开发者自测试平台,支持跨平台使用以及三方测试框架拓展,主要包括测试用例编译、测试用例管理、测试用例调度分发、测试用例执行、测试结果收集、测试报告生成、测试用例模板、测试环境管理等模块。 + +在测试子系统开发前,开发者应先了解以下概念: + +- 测试用例编译 + + 支持将测试用例源代码编译成可在被测设备侧执行的二进制文件。 + +- 测试用例调度分发 + + 支持将测试用例通过网口通道或者串口通道分发到不同的被测设备上,并且为每一个测试用例分配特定的测试用例执行器。 + +- 测试用例执行器 + + 负责测试用例的预处理,用例执行,结果记录等执行逻辑。 + +- 测试用例模板 + + 定义了测试用例以及用例编译配置GN文件的统一格式。 + +- 测试平台kit + + 测试平台运行过程中公共方法,如提供测试用例目录向被测设备挂载文件系统,测试用例推送到被测设备,或者从被测设备获取测试结果等操作。 + +- 测试报告生成 + + 定义开发者自测试报告模板,生成web测试报告。 + +- 测试环境管理 + + 支持通过USB、串口等方式管理被测设备,功能包括设备发现,设备状态查询等。 + + +### 运作机制 + +- 测试平台架构图如下: + +**图 1** 测试平台架构 +![](figure/测试平台架构.png "测试平台架构") + +- 测试平台运行时序图如下: + +**图 2** 测试平台运行时序 +![](figure/测试平台运行时序.png "测试平台运行时序") + +- 测试平台运行原理 + +测试平台通过shell脚本启动,以命令行方式支持一系列的测试指令执行,通过命令行输出测试结果。 + +## 约束与限制 + +- 功能使用范围:开发自测试平台仅支持代码级的测试用例开发和验证,如单元测试,模块测试。 +- 规格限制:当前测试框架的适用范围仅支持白盒测试。 +- 操作限制:一台测试设备上仅支持启动单个测试平台。 + +## 搭建环境 + +### 环境要求 + +**表 1** **环境要求** + + + + + + + + + + + + + + + + +

    项目

    +

    测试设备

    +

    被测设备

    +

    硬件

    +
    • 内存:8G及以上
    • 硬盘:100G及以上
    • 硬件架构:X86或ARM64
    +
    • Hi3516 DV300开发板
    • Hi3518 EV300开发板
    +

    软件

    +
    • 操作系统:Windows 10 64位 或 Ubuntu 18.04

      系统组件(Linux): libreadline-dev

      +
    • Python:3.7.5及以上
    • Python插件:pyserial3.3及以上、paramiko2.7.1及以上、setuptools40.8.0及以上,rsa4.0及以上
    • NFS Server:haneWIN NFS Server1.2.50及以上或者 NFSv4及以上
    +
    • 系统软件:版本不低于OpenHarmony 1.0
    • 内核类型:LiteOS-A或者Linux
    +
    + +### 安装环境 + +1. 如测试环境为Linux,需要安装系统组件readline,命令如下: + + ``` + sudo apt-get install libreadline-dev + ``` + + 安装成功提示如下: + + ``` + Reading package lists... Done + Building dependency tree + Reading state information... Done + libreadline-dev is already the newest version (7.0-3). + 0 upgraded, 0 newly installed, 0 to remove and 11 not upgraded. + ``` + +2. 安装Python扩展组件setuptools、(rsa、paramiko、以及pyserial,设备仅支持串口时安装),命令如下: + + 1、安装setuptools,安装命令如下: + + ``` + pip install setuptools + ``` + + 安装成功提示如下: + + ``` + Requirement already satisfied: setuptools in d:\programs\python37\lib\site-packages (41.2.0) + ``` + + 2、安装rsa,安装命令如下: + + ``` + pip install rsa + ``` + + 安装成功提示如下: + + ``` + Installing collected packages: pyasn1, rsa + Successfully installed pyasn1-0.4.8 rsa-4.7 + ``` + + 3、安装Paramiko,安装命令如下: + + ``` + pip install paramiko + ``` + + 安装成功提示如下: + + ``` + Installing collected packages: pycparser, cffi, pynacl, bcrypt, cryptography, paramiko + Successfully installed bcrypt-3.2.0 cffi-1.14.4 cryptography-3.3.1 paramiko-2.7.2 pycparser-2.20 pynacl-1.4.0 + ``` + + 4、安装pyserial(被测设备仅支持串口时安装),安装命令如下: + + ``` + pip install pyserial + ``` + + 安装成功提示如下: + + ``` + Requirement already satisfied: pyserial in d:\programs\python37\lib\site-packages\pyserial-3.4-py3.7.egg (3.4) + ``` + +3. 安装NFS server(被测设备仅支持串口时安装)。 + + **Windows环境安装** + + 下载并安装haneWIN NFS Server1.2.50,地址:https://www.hanewin.net/nfs-e.htm + + **Linux环境下安装** + + ``` + sudo apt install nfs-kernel-server + ``` + + 所有环境配置安装完成,即可在IDE中进行测试平台代码开发调试,推荐的IDE为 DevEco Studio。 + + +### 检验环境是否搭建成功 + +**表 2** **检验环境** + + + + + + + + + + + + + + + + + + + + +

    检查项

    +

    操作

    +

    满足条件

    +

    检查python安装与否,版本是否满足要求。

    +

    命令行窗口执行命令:python --version。

    +

    版本不小于3.7.5即可。

    +

    检查python扩展插件安装与否。

    +

    打开test/xdevice目录,执行run.bat或run.sh。

    +

    可进入提示符“>>>”界面即可。

    +

    检查NFS Server启动状态(被测设备仅支持串口时检测)。

    +

    通过串口登录开发板,执行mount命令挂载NFS。

    +

    可正常挂载文件目录即可。

    +
    + +## 开发指导 + +### 场景介绍 + +针对对开发的业务代码进行白盒测试验证。 + +### 接口说明 + +测试框架集成了开源的单元测试框架,并对测试用例的宏定义做了扩展,具体框架说明详见开源官方文档。 + +**表 3** 测试框架扩展宏定义说明 + + + + + + + + + + + + + + + + +

    宏定义

    +

    描述

    +

    HWTEST

    +

    测试用例执行不依赖Setup&Teardown。HWTEST对TEST增加了“用例级别”参数“TestSize.Level1”,例如HWTEST(CalculatorAddTest, TestPoint_001, TestSize.Level1)。

    +

    HWTEST_F

    +

    测试用例(不带参数)执行依赖Setup&Teardown。HWTEST_F对TEST_F增加了“用例级别”参数“ TestSize.Level1”,例如HWTEST_F(CalculatorAddTest, TestPoint_001, TestSize.Level1)。

    +

    HWTEST_P

    +

    测试用例(带参数)执行依赖Setup&Teardown。HWTEST_P对TEST_P增加了“用例级别”参数“ TestSize.Level1”,例如HWTEST_P(CalculatorAddTest, TestPoint_001, TestSize.Level1)。

    +
    + +### 开发步骤 + +1. 按照开发者测试用例目录规划定义测试套文件,需要继承testing::Test类,命名以被测特性+Test命名,示例代码路径:test/developertest/examples/lite/cxx\_demo/test/unittest/common/calc\_subtraction\_test.cpp + + ``` + /* + * Copyright (c) 2020 OpenHarmony. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + #include + + using namespace std; + using namespace testing::ext; + + class CalcSubtractionTest : public testing::Test { + public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + }; + ``` + + >![](../public_sys-resources/icon-note.gif) **说明:** + >测试用例规范 + >- 命名规范 + > 测试用例源文件名称和测试套内容保持一致,测试套与用例之间关系1:N,测试套与测试源文件之间关系1:1,每个源文件全局唯一,格式:\[特性\]\_\[功能\]\_\[子功能1\]\_\[子功能1.1\],子功能支持向下细分。 + > 文件命名采用全小写+下划线方式命名,以test结尾,如demo用例:developertest/examples/lite/cxx\_demo + >- 测试用例编码规范 + > 开发者测试用例原则上与特性代码编码规范保持一致,另外需要添加必要的用例描述信息,详见[•自测试用例模板](#li2069415903917)。 + >- 测试用例编译配置规范 + > 测试用例采用GN方式编译,配置遵循本开源项目的[编译指导](subsys-build-mini-lite.md)。 + >- 测试用例模板 + > 详见测试demo用例:developertest/examples/lite/cxx\_demo/test/unittest/common/calc\_subtraction\_test.cpp + +2. 实现测试套执行过程需要的预处理操作和后处理操作,即实现SetUp和TearDown方法。 + + ``` + void CalcSubtractionTest::SetUpTestCase(void) + { + // step 1: input testsuite setup step + } + + void CalcSubtractionTest::TearDownTestCase(void) + { + // step 2: input testsuite teardown step + } + + void CalcSubtractionTest::SetUp(void) + { + // step 3: input testcase setup step + } + + void CalcSubtractionTest::TearDown(void) + { + // step 4: input testcase teardown step + } + ``` + +3. 针对被测对象的特性编写测试用例,以使用HWTEST\_F为例说明。 + + ``` + /** + * @tc.name: integer_sub_001 + * @tc.desc: Test Calculator + * @tc.type: FUNC + * @tc.require: AR00000000 SR00000000 + */ + HWTEST_F(CalcSubtractionTest, integer_sub_001, TestSize.Level1) + { + EXPECT_EQ(0, Subtraction(1, 0)); + } + ``` + + >![](../public_sys-resources/icon-note.gif) **说明:** + >- @tc.name:用例名称,对测试目的简要描述。 + >- @tc.desc:描述用例详细描述,包括测试目的、测试步骤、期望结果等。 + >- @tc.type:测试属性分类(FUNC、PERF、SECU、RELI)。 + >- @tc.require:需求编号或者issue编号,用来将修改与用例关联。 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    序号

    +

    测试类型名称

    +

    缩写

    +

    测试类型描述

    +

    1

    +

    功能测试(functionality)

    +

    FUNC

    +

    验证软件各个功能满足功能设计与规格。

    +

    2

    +

    性能测试(performance)

    +

    PERF

    +

    验证软件是否满足性能设计指标。包含负载测试容量测试,压力测试等。

    +

    3

    +

    安全性测试(security)

    +

    SECU

    +

    验证软件在生命周期内符合安全需求定义和相关法规。

    +

    4

    +

    可靠性测试(reliability)

    +

    RELI

    +

    在规定的条件下,在规定的时间内,软件不引起系统失效的概率,这里也包含稳定性。

    +
    + +4. 编写用例编译GN文件,其中包括定义用例编译目标,添加编译配置依赖,源文件等,举例说明: + + 示例文件路径:test/developertest/examples/lite/cxx\_demo/test/unittest/common/BUILD.gn)。 + + ``` + import("//build/lite/config/test.gni") + + unittest("CalcSubTest") { + output_extension = "bin" + sources = [ + "calc_subtraction_test.cpp" + ] + include_dirs = [] + deps = [] + } + ``` + +5. 将用例编译目标添加到子系统编译配置中,保证用例随版本一起编译,举例说明: + 1. 支持hdc连接的设备,编译配置示例路径:test/developertest/examples/ohos.build。 + + ``` + { + "subsystem": "subsystem_examples", + "parts": { + "subsystem_examples": { + "module_list": [ + "//test/developertest/examples/detector:detector", + ... ... + ], + "test_list": [ + "//test/developertest/examples/detector/test:unittest", + ... ... + ] + }, + ... ... + } + ``` + + 2. 仅支持串口的设备,编译配置示例路径:test/developertest/examples/lite/BUILD.gn。 + + ``` + import("//build/lite/config/test.gni") + + subsystem_test("test") { + test_components = [] + if(ohos_kernel_type == "liteos_riscv") { + features += [ + ] + }else if(ohos_kernel_type == "liteos_a") { + test_components += [ + "//test/developertest/examples/lite/cxx_demo/test/unittest/common:CalcSubTest" + ] + } + } + ``` + + +6. 编写测试用例资源配置,当测试用例需要使用静态测试资源文件时使用该配置。 + 1. 在部件或者模块的test目录下创建resource目录。 + 2. 在resource目录下创建形态目录,如phone。 + 3. 在设备形态目录下创建一个以模块名命名的文件夹,如testmodule。 + 4. 在模块目录下创建一个ohos\_test.xml文件,文件内容格式如下: + + ``` + + + + + + + + ``` + + 5. 在测试用例的编译配置文件中定义resource\_config\_file,用来指定对应的资源文件ohos\_test.xml。 + + >![](../public_sys-resources/icon-note.gif) **说明:** + >如上资源文件功能:将resource目录下的test.txt文件通过hdc push命令推送到被测设备的/data/test/resource目录下。 + + +7. 以上步骤完成即完成测试用例编写,即可执行测试用例。 + + >![](../public_sys-resources/icon-note.gif) **说明:** + >- 支持hdc连接的设备,测试用例支持单独编译。 + >- 仅支持串口连接的设备,在代码根路径下执行编译debug版本的命令,即可编译测试用例。 + > 测试用例用例的执行详见[测试平台使用](#section76401945124810)。 + + +## 开发实例 + +测试子系统代码仓提供了完整demo用例,demo用例路径:test/developertest/examples/。以一个减法运算方法编写测试用例举例说明: + +- 被测代码如下: + + ``` + static int Subtraction(int a, int b) + { + return a - b; + } + ``` + +- 测试用例代码如下: + + ``` + /** + * @tc.name: integer_sub_002 + * @tc.desc: Verify the Subtraction function. + * @tc.type: FUNC + * @tc.require: AR00000000 SR00000000 + */ + HWTEST_F(CalcSubtractionTest, integer_sub_002, TestSize.Level1) + { + EXPECT_EQ(1, Subtraction(2, 1)); + } + ``` + + +## 测试平台使用 + +1. (可选)安装xdevice组件。安装xdevice后,xdevice组件可以作为python的扩展包使用。 + + 打开xdevice安装目录:test/xdevice,执行如下命令: + + ``` + python setup.py install + ``` + + 安装成功提示如下: + + ``` + ... ... + Installed d:\programs\python37\lib\site-packages\xdevice-0.0.0-py3.7.egg + Processing dependencies for xdevice==0.0.0 + Searching for pyserial==3.4 + Best match: pyserial 3.4 + Processing pyserial-3.4-py3.7.egg + pyserial 3.4 is already the active version in easy-install.pth + Installing miniterm.py script to D:\Programs\Python37\Scripts + + Using d:\programs\python37\lib\site-packages\pyserial-3.4-py3.7.egg + Finished processing dependencies for xdevice==0.0.0 + ``` + +2. 修改developertest/config/user\_config.xml 文件配置developertest组件。 + 1. 测试框架通用配置。 + + \[build\] \# 配置测试用例的编译参数,例如: + + ``` + + false + false + true + ... ... + + ``` + + >![](../public_sys-resources/icon-note.gif) **说明:** + >测试用例的编译参数说明如下: + >example:是否编译测试用例示例,默认false。 + >version:是否编译测试版本,默认false。 + >testcase:是否编译测试用例,默认true。 + + 2. 支持hdc连接的被测设备。 + + \[device\] \# 配置标签为usb-hdc的环境信息,测试设备的IP地址和hdc映射的端口号,例如: + + ``` + + 192.168.1.1 + 9111 + + + ``` + + 3. 仅支持串口的被测设备。 + + \[board\_info\] \# 开发板配置信息,例如: + + ``` + + hispark + taurus + ipcamera + hb build + + ``` + + >![](../public_sys-resources/icon-note.gif) **说明:** + >开发板配置信息如下: + >board\_series:开发板系列,默认hispark。 + >board\_type:开发板类型,默认taurus。 + >board\_product:目标产品,默认ipcamera。 + >build\_command:测试版本和用例的编译命令,默认hb build。 + + \[device\] \# 配置标签为ipcamera的串口信息,COM口和波特率,例如: + + ``` + + + COM1 + cmd + 115200 + 8 + 1 + 1 + + + ``` + + +3. (可选)修改developertest组件配置。如果测试用例已完成编译,可以直接指定测试用例的编译输出路径,测试平台执行用例时即不会重新编译测试用例。 + + 配置文件:config/user\_config.xml + + 1. \[test\_cases\] \# 指定测试用例的输出路径,编译输出目录,例如: + + ``` + +

    /home/opencode/out/release/tests + + ``` + + 2. \[NFS\] \# 被测设备仅支持串口时配置,指定NFS的映射路径,host\_dir为PC侧的NFS目录,board\_dir为板侧创建的目录,例如: + + ``` + + D:\nfs + user + + ``` + + +4. (可选)测试环境准备。当被测设备仅支持串口时,需要检查。 + - 系统镜像与文件系统已烧录进开发板,开发板上系统正常运行,在系统模式下,如使用shell登录时,设备提示符是“OHOS\#”。 + - 开发主机和开发板串口连接正常,网口连接正常。 + - 开发主机IP与开发板IP处在同一小网网段,相互可以ping通。 + - 开发主机侧创建空目录用于开发板通过NFS挂载测试用例,并且NFS服务启动正常。 + +5. (必选)启动测试平台,执行测试用例。 + - 启动测试框架,打开test/developertest目录,执行启动脚本。 + 1. Windows环境启动测试框架,执行如下脚本: + + ``` + start.bat + ``` + + 2. Linux环境启动测试框架。 + + ``` + ./start.sh + ``` + + + - 设备形态选择。 + + 根据实际的开发板选择,设备形态配置:developertest/config/framework\_config.xml。 + + - 执行测试指令。 + 1. 查询测试用例支持的子系统,模块,产品形态以及测试类型,使用show命令,示例如下: + + ``` + usage: + show productlist Querying Supported Product Forms + show typelist Querying the Supported Test Type + show subsystemlist Querying Supported Subsystems + show modulelist Querying Supported Modules + ``` + + 2. 执行测试指令,其中-t为必选,-ss和-tm为可选字段,示例如下: + + ``` + run -t ut -ss subsystem_examples -tm calculator + ``` + + 3. 参数说明:指定参数可以执行特定特性、模块对应的测试套。 + + ``` + usage: run [-h] [-p PRODUCTFORM] [-t [TESTTYPE [TESTTYPE ...]]] + [-ss SUBSYSTEM] [-tm TESTMODULE] [-ts TESTSUIT] + [-tc TESTCASE] [-tl TESTLEVEL] + + optional arguments: + -h, --help show this help message and exit + -p PRODUCTFORM, --productform PRODUCTFORM Specified product form + -t [TESTTYPE [TESTTYPE ...]], --testtype [TESTTYPE [TESTTYPE ...]] + Specify test type(UT,MST,ST,PERF,ALL) + -ss SUBSYSTEM, --subsystem SUBSYSTEM Specify test subsystem + -tm TESTMODULE, --testmodule TESTMODULE Specified test module + -ts TESTSUIT, --testsuite TESTSUIT Specify test suite + -tc TESTCASE, --testcase TESTCASE Specify test case + -tl TESTLEVEL, --testlevel TESTLEVEL Specify test level + ``` + + + - 测试框架帮助。 + + 帮助指令,用于查询测试平台支持哪些测试指令,如下: + + ``` + help + ``` + + - 退出自测试平台。 + + 退出自测试平台,使用如下命令退出测试平台,如下: + + ``` + quit + ``` + + +6. (必选)查看测试结果与日志,通过在测试平台中执行测试指令,即可在developertest/reports目录下生成测试日志和测试报告。 + - 测试用例的结果会直接显示在控制台上,执行一次的测试结果根路径如下: + + ``` + reports/xxxx-xx-xx-xx-xx-xx + ``` + + - 测试用例格式化结果目录如下: + + ``` + result/ + ``` + + - 测试用例日志目录如下: + + ``` + log/plan_log_xxxx-xx-xx-xx-xx-xx.log + ``` + + - 测试报告汇总: + + ``` + summary_report.html + ``` + + - 测试报告详情: + + ``` + details_report.html + ``` + + + - 测试平台日志目录如下: + + ``` + reports/platform_log_xxxx-xx-xx-xx-xx-xx.log + ``` + + + +## 包结构说明 + +开发者测试平台xdevice组件包结构说明,代码目录test/xdevice,详见下表所示: + +**表 4** xdevice组件包结构说明 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    名称

    +

    功能描述

    +

    xdevice

    +

    测试平台基础组件。

    +

    xdevice/src/xdevice

    +

    基础测试框架源码。

    +

    xdevice/config

    +

    基础测试框架配置文件定义。

    +

    xdevice/src/xdevice/__main__.py

    +

    基础测试框架内部入口。

    +

    xdevice/src/xdevice/__init__.py

    +

    包依赖定义,插件依赖。

    +

    xdevice/src/xdevice/variables.py

    +

    全局变量定义。

    +

    xdevice/src/xdevice/_core/command

    +

    用例输入的命令行处理。

    +

    xdevice/src/xdevice/_core/config

    +

    基础测试框架的配置管理。

    +

    xdevice/src/xdevice/_core/environment

    +

    基础测试框架的环境管理,包括设备管理。

    +

    xdevice/src/xdevice/_core/executor

    +

    基础测试框架用例调度和分发。

    +

    xdevice/src/xdevice/_core/driver

    +

    基础测试框架测试执行器。

    +

    xdevice/src/xdevice/_core/resource

    +

    基础测试框架资源文件以及测试报告模板。

    +

    xdevice/src/xdevice/_core/testkit

    +

    基础测试框架公共操作,包括NFS文件系统挂载等。

    +

    xdevice/src/xdevice/_core/logger.py

    +

    基础测试框架日志管理。

    +

    xdevice/src/xdevice/_core/plugin.py

    +

    基础测试框架插件管理。

    +

    xdevice/src/xdevice/_core/interface.py

    +

    基础测试框架插件接口定义。

    +

    xdevice/setup.py

    +

    基础测试框架的安装脚本。

    +

    xdevice/run.bat

    +

    基础测试框架启动脚本(Windows)。

    +

    xdevice/run.sh

    +

    基础测试框架启动脚本(Linux)。

    +
    + +开发者测试平台developertest组件包结构说明,代码目录test/developertest,详见下表所示: + +**表 5** developertest组件包结构说明 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    名称

    +

    描述

    +

    developertest

    +

    开发测试框架。

    +

    developertest/src

    +

    测试框架源码。

    +

    developertest/src/core

    +

    测试执行器。

    +

    developertest/src/core/build

    +

    测试用例编译。

    +

    developertest/src/core/command

    +

    对用户输入的命令行处理。

    +

    developertest/src/core/config

    +

    测试框架配置管理。

    +

    developertest/src/core/driver

    +

    测试框架驱动执行器。

    +

    developertest/src/core/resource

    +

    测试框架配置文件。

    +

    developertest/src/core/testcase

    +

    测试用例管理。

    +

    developertest/src/core/common.py

    +

    测试框架公共操作。

    +

    developertest/src/core/constants.py

    +

    测试框架全局常量。

    +

    developertest/src/core/exception.py

    +

    测试框架异常定义。

    +

    developertest/src/core/utils.py

    +

    测试框架工具方法。

    +

    developertest/src/main

    +

    测试框架平台。

    +

    developertest/src/main/__main__.py

    +

    测试框架内部入口。

    +

    developertest/examples

    +

    测试框架demo用例。

    +

    developertest/third_party

    +

    测试框架依赖第三方组件适配。

    +

    developertest/BUILD.gn

    +

    测试子系统编译配置。

    +

    developertest/start.bat

    +

    开发者测试入口(Windows)。

    +

    developertest/start.sh

    +

    开发者测试入口(Linux)。

    +
    + diff --git a/zh-cn/device-dev/subsystems/subsys-toolchain-bytrace-guide.md b/zh-cn/device-dev/subsystems/subsys-toolchain-bytrace-guide.md new file mode 100644 index 0000000000..2c443396ac --- /dev/null +++ b/zh-cn/device-dev/subsystems/subsys-toolchain-bytrace-guide.md @@ -0,0 +1,115 @@ +# bytrace使用指导 + +- [简介](#section11388623181619) +- [开发指导](#section1595564317164) +- [使用实例](#section667273201818) + +## 简介 + +bytrace是开发人员用于追踪进程轨迹、分析性能的一种工具,主要对内核ftrace进行了封装和扩展,来支持用户态的打点。通过该工具可以打开想要查看的用户态和内核label(通过下面命令行bytrace -l,查看支持的所有label),然后通过命令行进行抓取trace信息到指定文件中。 + +## 开发指导 + +bytrace当前支持以下命令: + +**表 1** 命令行列表 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    Option

    +

    Description

    +

    -h,--help

    +

    查看option帮助

    +

    -b n,--buffer_size n

    +

    指定n(KB)内存大小用于存取trace日志,默认2048KB

    +

    -t n,--time n

    +

    用来指定trace运行的时间(单位:s),取决于需要分析过程的时间

    +

    --trace_clock clock

    +

    trace输出的时钟类型,一般设备支持boot、global、mono、uptime、perf等,默认为boot

    +

    --trace_begin

    +

    启动抓trace

    +

    --trace_dump

    +

    将数据输出到指定位置(默认控制台)

    +

    --trace_finish

    +

    停止抓trace,并将数据输出到指定位置(默认控制台)

    +

    -l,--list_categories

    +

    输出手机能支持的trace模块

    +

    --overwrite

    +

    当缓冲区满的时候,将丢弃最新的信息。(默认丢弃最老的日志)

    +

    -o filename,--output filename

    +

    指定输出的目标文件名称

    +

    -z

    +

    抓取trace后进行压缩

    +
    + +## 使用实例 + +以下是常用bytrace命令示例,供开发者参考: + +- 查询支持的label。 + +``` +bytrace -l +``` + +或者 + +``` +bytrace --list_categories +``` + +- 设置4M缓存,抓取10秒,抓取label为ability的trace信息。 + +``` +bytrace -b 4096 -t 10 --overwrite ability > /data/mytrace.ftrace +``` + +- 设置trace的输出时钟为mono。 + +``` +bytrace --trace_clock mono -b 4096 -t 10 --overwrite ability > /data/mytrace.ftrace +``` + +- 抓取trace后进行压缩。 + +``` +bytrace -z -b 4096 -t 10 --overwrite ability > /data/mytrace.ftrace +``` + diff --git a/zh-cn/device-dev/subsystems/subsys-toolchain-hdc-guide.md b/zh-cn/device-dev/subsystems/subsys-toolchain-hdc-guide.md new file mode 100644 index 0000000000..93b7653893 --- /dev/null +++ b/zh-cn/device-dev/subsystems/subsys-toolchain-hdc-guide.md @@ -0,0 +1,685 @@ +# hdc\_std 使用指导 + +- [环境准备](#section05992022154916) +- [注意事项](#section19543134915210) +- [option相关的命令](#section618522925119) +- [查询设备列表的命令](#section174891132104218) +- [服务进程相关命令](#section680531510497) +- [网络相关的命令](#section71176123212) +- [文件相关的命令](#section173133523013) +- [应用相关的命令](#section2072647133819) +- [调试相关的命令](#section112861250195015) +- [常见问题](#section592920255582) + - [hdc\_std连接不到设备](#section74019384588) + - [hdc\_std运行不了](#section63291491267) + + +hdc\_std(OpenHarmony Device Connector)是OpenHarmony为开发人员提供的用于调试的命令行工具,通过该工具可以在Windows/Linux等系统上与开发机或者模拟器进行交互。 + +下文将介绍hdc\_std的环境准备和常用命令及使用举例。 + +## 环境准备 + +**hdc\_std 工具获取方式:** + +从开源仓developtools\_hdc\_standard中获取,具体位置在该开源仓的prebuilt目录。 + +**使用举例:** + +下面以windows侧使用方式举例: + +从prebuilt/windows侧获取可执行文件hdc\_std.exe,放到磁盘某个位置即可使用。 + +## 注意事项 + +- 使用hdc\_std,如果出现异常,可以尝试通过hdc\_std kill命令杀掉hdc\_std服务,或者通过hdc\_std start -r命令重启服务进程进行解决。 +- 如果出现hdc\_std list targets获取不到设备信息,通过任务管理器查看是否有hdc.exe进程存在,如果进程存在,可以通过杀掉该进程进行解决。 + +## option相关的命令 + +option涉及以下命令: + +**-h/help -v/version** + +用于显示hdc相关的帮助、版本信息。 + +**表 1** 命令说明 + + + + + + + + + +

    返回值

    +

    返回值说明

    +

    返回对应信息

    +

    帮助或者版本信息

    +
    + +使用方法: + +hdc\_std -h / hdc\_std help + +hdc\_std -v / hdc\_std version + +**-t key** + +用于连接指定设备标识为key的设备。 + +**表 2** 命令说明 + + + + + + + + + + + + + + + +

    参数

    +

    参数说明

    +

    key

    +

    为tcp:port格式,或者USB序列号

    +

    返回值

    +

    返回值说明

    +

    ①error: device '***' not found

    +

    ②Nothing to do...

    +

    ①设备不存在

    +

    ②附加的命令不存在

    +
    + +使用方法: + +该option需要与具体的操作命令搭配使用,下面以shell命令举例: + +hdc\_std list targets (获取设备信息) + +hdc\_std -t _key_ shell (-t后面添加的_key_ 需要替换为上面查询的设备信息) + +>![](../public_sys-resources/icon-note.gif) **说明:** +>一台开发机可支持多个设备连接,每个设备有其唯一的设备标识,如果通过网络与设备连接,其标识为tcp:port格式,如果通过usb连接则标识为设备sn号。该命令需要跟随具体操作命令。 + +## 查询设备列表的命令 + +查询设备列表涉及以下命令: + +**list targets\[-v\]** + +显示所有已经连接的目标设备列表 + +**表 3** 命令说明 + + + + + + + + + + + + + + + +

    参数

    +

    参数说明

    +

    -v

    +

    添加-v选项,则会打印设备详细信息

    +

    返回值

    +

    返回值说明

    +

    ①返回设备信息

    +

    ②[Empty]

    +

    ①已经连接的设备列表信息

    +

    ②没有查询到设备信息

    +
    + +使用方法: + +hdc\_std list targets + +hdc\_std list targets -v + +## 服务进程相关命令 + +服务进程涉及以下命令: + +**target mount** + +以读写模式挂载/system等分区。 + +**表 4** 命令说明 + + + + + + + + + + + + + + + +

    参数

    +

    参数说明

    +

    +

    +

    返回值

    +

    返回值说明

    +

    ①Mount finish

    +

    ②返回具体信息

    +

    ①成功情况下返回的信息

    +

    ②失败情况下的具体信息

    +
    + +使用方法: + +hdc\_std target mount + +**smode \[off\]** + +授予后台服务进程root权限, 使用off参数取消授权。 + +使用方法: + +hdc\_std smode + +hdc\_std smode off + +**kill \[-r\]** + +终止服务进程。 + +**表 5** 命令说明 + + + + + + + + + + + + + + + +

    参数

    +

    参数说明

    +

    -r

    +

    触发服务重启

    +

    返回值

    +

    返回值说明

    +

    ①Kill server finish

    +

    ②返回具体信息

    +

    ①成功情况下返回的信息

    +

    ②失败情况下的具体信息

    +
    + +使用方法: + +hdc\_std kill + +**start \[-r\]** + +启动服务进程。 + +**表 6** 命令说明 + + + + + + + + + + + + + + + +

    参数

    +

    参数说明

    +

    -r

    +

    如果服务进程已经启动,-r选项会触发服务进程重新启动

    +

    返回值

    +

    返回值说明

    +

    +

    +
    + +使用方法: + +hdc\_std start + +## 网络相关的命令 + +网络部分涉及以下命令: + +**tconn host\[:port\]\[-remove\]** + +通过【ip地址:端口号】来指定连接的设备 + +**表 7** 命令说明 + + + + + + + + + + + + + + + + + + +

    参数

    +

    参数说明

    +

    host[:port]

    +

    为tcp:port格式

    +

    -remove

    +

    表示断开与指定设备的连接

    +

    返回值

    +

    返回值说明

    +

    ①返回具体信息

    +

    ②无

    +

    ①失败情况下的具体信息

    +

    ②成功情况下无返回值

    +
    + +使用方法(举例): + +hdc\_std tconn 192.168.0.100:8710 + +**tmode usb** + +执行后设备端对应daemon进程重启,并首先选用usb连接方式。 + +**表 8** 命令说明 + + + + + + + + + + + + + + + +

    参数

    +

    参数说明

    +

    +

    +

    返回值

    +

    返回值说明

    +

    ①返回具体信息

    +

    ②无

    +

    ①失败情况下的具体信息

    +

    ②成功情况下无返回值

    +
    + +使用方法: + +hdc\_std tmode usb + +**tmode port port-number** + +执行后设备端对应daemon进程重启,并优先使用网络方式连接设备,如果连接设备再选择usb连接。 + +**表 9** 命令说明 + + + + + + + + + + + + + + + +

    参数

    +

    参数说明

    +

    port-number

    +

    listen连接的网络端口

    +

    返回值

    +

    返回值说明

    +

    ①返回具体信息

    +

    ②无

    +

    ①失败情况下的具体信息

    +

    ②成功情况下无返回值

    +
    + +使用方法: + +hdc\_std tmode port 8710 + +>![](../public_sys-resources/icon-note.gif) **说明:** +>执行完毕后,远端daemon将会退出并重启,默认启用TCP连接,如果不加上listen端口则listen随机端口。 + +## 文件相关的命令 + +文件部分涉及以下命令: + +**file send local remote** + +发送文件至远端设备。 + +**表 10** 命令说明 + + + + + + + + + + + + + + + + + + +

    参数

    +

    参数说明

    +

    local

    +

    本地待发送文件路径

    +

    remote

    +

    远程待接收文件路径

    +

    返回值

    +

    返回值说明

    +

    ①返回具体信息

    +

    ②返回传输结果

    +

    ①失败情况下的具体信息

    +

    ②成功传输的结果信息

    +
    + +使用方法(举例): + +hdc\_std file send E:\\a.txt /data/local/tmp/a.txt + +**file recv \[-a\] remote local** + +从远端设备接收文件至本地。 + +**表 11** 命令说明 + + + + + + + + + + + + + + + + + + + + + +

    参数

    +

    参数说明

    +

    -a

    +

    文件保留时间戳模式

    +

    local

    +

    本地待接收文件路径

    +

    remote

    +

    远程待发送文件路径

    +

    返回值

    +

    返回值说明

    +

    ①返回具体信息

    +

    ②无

    +

    ①失败情况下的具体信息

    +

    ②成功情况下无返回值

    +
    + +使用方法(举例): + +hdc\_std file recv /data/local/tmp/a.txt ./a.txt + +## 应用相关的命令 + +应用部分涉及以下命令: + +**install \[-r/-d/-g\] _package_** + +安装OpenHarmony package。 + +**表 12** 命令说明 + + + + + + + + + + + + + + + + + + + + + + + + +

    参数

    +

    参数说明

    +

    package

    +

    OpenHarmony应用安装包

    +

    -r

    +

    替换已存在应用

    +

    -d

    +

    允许降级安装

    +

    -g

    +

    动态授权

    +

    返回值

    +

    返回值说明

    +

    ①返回具体信息

    +

    ②无

    +

    ①失败情况下的具体信息

    +

    ②成功情况下无返回值

    +
    + +使用方法(举例): + +hdc\_std install _hwadmin.hap_ + +**uninstall \[-k\] package** + +卸载OpenHarmony应用。 + +**表 13** 命令说明 + + + + + + + + + + + + + + + + + + +

    参数

    +

    参数说明

    +

    package

    +

    OpenHarmony应用安装包

    +

    -k

    +

    保留/data/cache

    +

    返回值

    +

    返回值说明

    +

    ①返回具体信息

    +

    ②无

    +

    ①失败情况下的具体信息

    +

    ②成功情况下无返回值

    +
    + +使用方法(举例): + +hdc\_std uninstall _package_ + +## 调试相关的命令 + +调试涉及以下命令: + +**hilog** + +支持抓取log信息。 + +**表 14** 命令说明 + + + + + + + + + + + + + + + +

    参数

    +

    参数说明

    +

    +

    +

    返回值

    +

    返回值说明

    +

    返回具体信息

    +

    抓取的日志信息

    +
    + +使用方法: + +hdc\_std hilog + +**shell \[_command_\]** + +远程执行命令或进入交互命令环境。 + +**表 15** 命令说明 + + + + + + + + + + + + + + + +

    参数

    +

    参数说明

    +

    command

    +

    需要执行的单次命令

    +

    返回值

    +

    返回值说明

    +

    返回具体信息

    +

    shell后面执行命令的结果信息

    +
    + +使用方法: + +hdc\_std shell + +## 常见问题 + +### hdc\_std连接不到设备 + +- **现象描述** + + 执行 "hdc\_std list targets"命令后结果为:\[Empty\] + +- **解决方法** + 1. 设备没有被识别: + + 在设备管理器中查看是否有hdc设备,在通用串行总线设备中会有“HDC Device”信息。如果没有,hdc无法连接。此时需要插拔设备,或者烧写最新的镜像。 + + 2. hdc\_std工作异常: + + 可以执行"hdc kill"或者"hdc start -r"杀掉hdc服务或者重启hdc服务,然后再执行hdc list targets查看是否已经可以获取设备信息。 + + 3. hdc\_std与设备不匹配: + + 如果设备烧写的是最新镜像,hdc\_std也需要使用最新版本。由于hdc\_std会持续更新,请从开源仓developtools\_hdc\_standard中获取,具体位置在该开源仓的prebuilt目录。 + + + +### hdc\_std运行不了 + +- **现象描述** + + 点击hdc\_std.exe文件无法运行。 + +- **解决方法** + + hdc\_std.exe不需要安装,直接放到磁盘上就能使用,也可以添加到环境变量中。通过打开cmd执行hdc\_std命令直接使用。 + + diff --git a/zh-cn/device-dev/subsystems/subsys-toolchain.md b/zh-cn/device-dev/subsystems/subsys-toolchain.md new file mode 100644 index 0000000000..fcf4e3ed14 --- /dev/null +++ b/zh-cn/device-dev/subsystems/subsys-toolchain.md @@ -0,0 +1,6 @@ +# 研发工具链 + +- [bytrace使用指导](subsys-toolchain-bytrace-guide.md) +- [hdc\_std 使用指导](subsys-toolchain-hdc-guide.md) + + diff --git "a/zh-cn/device-dev/subsystems/\345\205\254\345\205\261\345\237\272\347\241\200\345\272\223\345\270\270\350\247\201\351\227\256\351\242\230.md" b/zh-cn/device-dev/subsystems/subsys-utils-faqs.md old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/subsystems/\345\205\254\345\205\261\345\237\272\347\241\200\345\272\223\345\270\270\350\247\201\351\227\256\351\242\230.md" rename to zh-cn/device-dev/subsystems/subsys-utils-faqs.md diff --git a/zh-cn/device-dev/subsystems/subsys-utils-guide.md b/zh-cn/device-dev/subsystems/subsys-utils-guide.md new file mode 100644 index 0000000000..1cabae5734 --- /dev/null +++ b/zh-cn/device-dev/subsystems/subsys-utils-guide.md @@ -0,0 +1,298 @@ +# 公共基础库开发指导 + +- [接口说明](#section1633115419401) +- [开发步骤](#section17450172710292) + - [LiteOS-A内核\(Hi3516、Hi3518平台\)KV存储的native应用开发步骤:](#section258354119295) + - [Dump系统属性在LiteOS-M内核平台使用指南:](#section9179161863014) + - [Dump系统属性在LiteOS-A内核平台使用指南:](#section3179121853017) + + +## 接口说明 + +**表 1** 文件操作接口说明 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    接口名

    +

    描述

    +

    int UtilsFileOpen(const char* path, int oflag, int mode)

    +

    打开或创建文件

    +

    int UtilsFileClose(int fd)

    +

    关闭文件

    +

    int UtilsFileRead(int fd, char *buf, unsigned int len)

    +

    读取特定长度的文件数据

    +

    int UtilsFileWrite(int fd, const char *buf, unsigned int len)

    +

    向文件写入特定大小的数据

    +

    int UtilsFileDelete(const char *path)

    +

    删除指定文件

    +

    int UtilsFileStat(const char *path, unsigned int *fileSize)

    +

    获取文件大小

    +

    int UtilsFileSeek(int fd, int offset, unsigned int whence)

    +

    重新定位文件读/写偏移量

    +

    int UtilsFileCopy(const char* src, const char* dest)

    +

    将源文件复制一份并存储到目标文件

    +

    int UtilsFileMove(const char* src, const char* dest)

    +

    将源文件移动到指定目标文件

    +
    + +文件操作使用示例: + +``` +// open && write +char fileName[] = "testfile"; +static const char def[] = "utils_file_operation implement."; +int fd = UtilsFileOpen(fileName, O_RDWR_FS | O_CREAT_FS | O_TRUNC_FS, 0); +printf("file handle = %d\n", fd); +int ret = UtilsFileWrite(fd, def, strlen(def)); +printf("write ret = %d\n", ret); + +// seek +ret = UtilsFileSeek(fd, 5, SEEK_SET_FS); +printf("lseek ret = %d\n", ret); + +// read && close +char buf[64] = {0}; +int readLen = UtilsFileRead(fd, buf, 64); +ret = UtilsFileClose(fd); +printf("read len = %d : buf = %s\n", readLen, buf); + +// stat +int fileLen = 0; +ret = UtilsFileStat(fileName, &fileLen); +printf("file size = %d\n", fileLen); + +// delete +ret = UtilsFileDelete(fileName); +printf("delete ret = %d\n", ret); +``` + +**表 2** KV存储接口说明 + + + + + + + + + + + + + + + + +

    接口名

    +

    描述

    +

    int UtilsGetValue(const char* key, char* value, unsigned int len)

    +

    提供给上层应用根据key获取对应数据项

    +

    int UtilsSetValue(const char* key, const char* value)

    +

    提供给上层应用用于存储/更新key对应数据项

    +

    int UtilsDeleteValue(const char* key)

    +

    提供给上层应用删除key对应数据项

    +
    + +KV存储使用示例: + +``` +// set +char key[] = "rw.sys.version_100"; +char value[] = "Hello kv operation implement!"; +int ret = UtilsSetValue(key, value); +printf("UtilsSetValue set ret = %d\n", ret); + +// get +char temp[128] = {0}; +ret = UtilsGetValue(key, temp, 128); +printf("UtilsGetValue get ret = %d, temp = %s\n", ret, temp); + +// delete +ret = UtilsDeleteValue(key); +printf("UtilsDeleteValue delete ret = %d\n", ret); +``` + + + + +
    + +## 开发步骤 + +### LiteOS-A内核\(Hi3516、Hi3518平台\)KV存储的native应用开发步骤: + +1. 基于AbilityKit开发KV存储的native应用。 + - 基于KV存储提供的接口编写用户程序,并编译出so(libLauncher.so)文件。 + + ``` + // set + char key[] = "rw.sys.version_100"; + char value[] = "Hello kv operation implement!"; + int ret = UtilsSetValue(key, value); + printf("UtilsSetValue set ret = %d\n", ret); + + // get + char temp[128] = {0}; + ret = UtilsGetValue(key, temp, 128); + printf("UtilsGetValue get ret = %d, temp = %s\n", ret, temp); + + // delete + ret = UtilsDeleteValue(key); + printf("UtilsDeleteValue delete ret = %d\n", ret); + ``` + + - 编写config.json文件,内容如下: + + ``` + { + "app": { + "bundleName": "com.huawei.launcher", + "vendor": "huawei", + "version": { + "code": 1, + "name": "1.0" + } + }, + "deviceConfig": { + "default": { + "reqSdk": { + "compatible": "zsdk 1.0.0", + "target": "zsdk 1.0.1" + }, + "keepAlive": false + }, + "smartCamera": { + "reqSdk": { + "compatible": "zsdk 1.0.0", + "target": "zsdk 1.0.1" + }, + "keepAlive": false + } + }, + "module": { + "package": "com.huawei.launcher", + "name": ".MyHarmonyAbilityPackage", + "deviceType": [ + "phone", "tv","tablet", "pc","car","smartWatch","sportsWatch","smartCamera" + ], + "distro": { + "deliveryWithInstall": true, + "moduleName": "Launcher", + "moduleType": "entry" + }, + "abilities": [{ + "name": "MainAbility", + "icon": "res/drawable/phone.png", + "label": "test app 1", + "launchType": "standard", + "type": "page" + }, + { + "name": "SecondAbility", + "icon": "res/drawable/phone.png", + "label": "test app 2", + "launchType": "standard", + "type": "page" + }, + { + "name": "ServiceAbility", + "icon": "res/drawable/phone.png", + "label": "test app 2", + "launchType": "standard", + "type": "service" + } + ] + } + } + ``` + + + - 生成hap包。 + + - 按照如下目录结构存放文件,res/drawable下面放置资源文件: + + ![](figure/unnaming.png) + + - 将上述文件打包生成zip包,修改后缀为.hap,例如Launcher.hap + + +2. 连接单板,通过串口向单板发送安装KV存储native应用的命令。 + + ``` + ./nfs/dev_tools/bin/bm install -p /nfs/Launcher.hap + ``` + +3. 通过串口向单板发送运行KV存储native应用的命令。 + + ``` + ./nfs/dev_tools/bin/aa start -p com.huawei.launcher -n ServiceAbility + ``` + + +### Dump系统属性在LiteOS-M内核平台使用指南: + +1. 连接单板,通过串口向单板发送AT+SYSPARA命令。 + + ``` + AT+SYSPARA + ``` + + **图 1** LiteOS-M平台dump系统属性输出 + ![](figure/LiteOS-M平台dump系统属性输出.png "LiteOS-M平台dump系统属性输出") + + +### Dump系统属性在LiteOS-A内核平台使用指南: + +1. 连接单板,运行bin路径下的os\_dump加参数--help,查看os\_dump使用指导。 + + ``` + ./bin/os_dump --help + ``` + +2. os\_dump加参数-l,查看当前系统有哪些模块支持获取属性。 + + ``` + ./bin/os_dump -l + ``` + +3. os\_dump加参数syspara,查看当前系统属性 + + ``` + ./bin/os_dump syspara + ``` + + **图 2** LiteOS-A平台dump系统属性输出 + ![](figure/LiteOS-A平台dump系统属性输出.png "LiteOS-A平台dump系统属性输出") + + diff --git "a/zh-cn/device-dev/subsystems/\345\205\254\345\205\261\345\237\272\347\241\200\345\272\223\346\246\202\350\277\260.md" b/zh-cn/device-dev/subsystems/subsys-utils-overview.md old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/subsystems/\345\205\254\345\205\261\345\237\272\347\241\200\345\272\223\346\246\202\350\277\260.md" rename to zh-cn/device-dev/subsystems/subsys-utils-overview.md diff --git a/zh-cn/device-dev/subsystems/subsys-utils.md b/zh-cn/device-dev/subsystems/subsys-utils.md new file mode 100644 index 0000000000..28a5d910c2 --- /dev/null +++ b/zh-cn/device-dev/subsystems/subsys-utils.md @@ -0,0 +1,9 @@ +# 公共基础 + +- **[公共基础库概述](subsys-utils-overview.md)** + +- **[公共基础库开发指导](subsys-utils-guide.md)** + +- **[公共基础库常见问题](subsys-utils-faqs.md)** + + diff --git a/zh-cn/device-dev/subsystems/subsys-xts-guide.md b/zh-cn/device-dev/subsystems/subsys-xts-guide.md new file mode 100644 index 0000000000..1240c60b9d --- /dev/null +++ b/zh-cn/device-dev/subsystems/subsys-xts-guide.md @@ -0,0 +1,715 @@ +# XTS认证子系统开发指南 + +- [简介](#section465982318513) +- [系统类型](#section125090457443) +- [目录](#section161941989596) +- [约束](#section119744591305) +- [使用说明](#section137768191623) +- [用例开发指导](#section3695134065513) + - [C语言用例开发编译指导(适用于轻量系统产品用例开发)](#section198193336544) + - [C语言用例执行指导(适用于轻量系统产品用例开发)](#section13820233175418) + - [C++语言用例开发编译指导(适用于小型系统、标准系统用例开发)](#section3822123311540) + - [C++语言用例执行指导(适用于小型系统、标准系统用例开发)](#section128222336544) + - [JS语言用例开发指导(适用于标准系统)](#section159801435165220) + - [JS语言用例编译打包指导(适用于标准系统)](#section445519106559) + - [\#ZH-CN\_TOPIC\_0000001126156429/section191521423950](#section191521423950) + +- [全量编译指导(适用于标准系统)](#section1519992743415) +- [全量用例执行指导(适用于小型系统、标准系统)](#section118149111426) + +## 简介 + +XTS子系统是OpenHarmony生态认证测试套件的集合,当前包括acts(application compatibility test suite)应用兼容性测试套件,后续会拓展dcts(device compatibility test suite)设备兼容性测试套件等。 + +XTS子系统当前包括acts与tools软件包: + +- acts,存放acts相关测试用例源码与配置文件,其目的是帮助终端设备厂商尽早发现软件与OpenHarmony的不兼容性,确保软件在整个开发过程中满足OpenHarmony的兼容性要求。 +- tools,存放acts相关测试用例开发框架。 + +## 系统类型 + +OpenHarmony支持如下几种系统类型: + +- 轻量系统(mini system) + + 面向MCU类处理器例如Arm Cortex-M、RISC-V 32位的设备,硬件资源极其有限,支持的设备最小内存为128KiB,可以提供多种轻量级网络协议,轻量级的图形框架,以及丰富的IOT总线读写部件等。可支撑的产品如智能家居领域的连接类模组、传感器设备、穿戴类设备等。 + +- 小型系统(small system) + + 面向应用处理器例如Arm Cortex-A的设备,支持的设备最小内存为1MiB,可以提供更高的安全能力、标准的图形框架、视频编解码的多媒体能力。可支撑的产品如智能家居领域的IP Camera、电子猫眼、路由器以及智慧出行域的行车记录仪等。 + +- 标准系统(standard system) + + 面向应用处理器例如Arm Cortex-A的设备,支持的设备最小内存为128MiB,可以提供增强的交互能力、3D GPU以及硬件合成能力、更多控件以及动效更丰富的图形能力、完整的应用框架。可支撑的产品如高端的冰箱显示屏。 + + +## 目录 + +``` +/test/xts +├── acts # 测试代码存放目录 +│ └── subsystem # 标准系统子系统测试用例源码存放目录 +│ └── subsystem_lite # 轻量系统、小型系统子系统测试用例源码存放目录 +│ └── BUILD.gn # 标准系统测试用例编译配置 +│ └── build_lite # 轻量系统、小型系统测试用例编译配置存放目录 +│ └── BUILD.gn # 轻量系统、小型系统测试用例编译配置 +└── tools # 测试工具代码存放目录 +``` + +## 约束 + +轻量系统用例开发语言是C,小型系统用例开发语言是C++。 + +## 使用说明 + +**表 1** 用例级别说明 + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    级别名称

    +

    基本定义

    +

    测试范围

    +

    Level0

    +

    冒烟

    +

    验证关键功能点基本功能/最基本DFX属性在最常见输入下的表现,通过表示功能基本可运行。

    +

    Level1

    +

    基本

    +

    验证各功能点基本功能/基本DFX属性在常见输入下的表现,通过表示功能基本可测试。

    +

    Level2

    +

    重要

    +

    验证各功能点的基本功能/基本DFX属性在常规输入/常见异常情况下的表现,通过表示功能基本正常可用,可开展Beta。

    +

    Level3

    +

    一般

    +

    验证各功能点的全部功能/全部DFX属性在各种常规/非常规输入组合下,或各种正常/异常预置条件组合下的表现。

    +

    Level4

    +

    生僻

    +

    验证关键功能点在极端异常预置条件下、用户难以触及的异常输入组合下的表现。

    +
    + +**表 2** 用例粒度说明 + + + + + + + + + + + + + + + + + + + + +

    用例规模

    +

    被测试对象

    +

    测试环境

    +

    LargeTest

    +

    业务功能/全场景特性/整机及场景级DFX

    +

    尽量使用贴近真实的环境设备

    +

    MediumTest

    +

    模块/子系统集成至设备后的功能/DFX

    +

    使用真实的单设备进行验证,可进行消息模拟,尽量不对函数进行MOCK

    +

    SmallTest

    +

    模块/类/函数

    +

    在开发者个人环境进行测试,尽量不依赖其他模块,存在大量的MOCK

    +
    + +**表 3** 测试类型说明 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    测试类型名称

    +

    测试类型定义

    +

    Function

    +

    验证被测对象提供给用户的业务功能实现正确性的测试项,这里的“用户”可以是终端用户或开发者,功能包括业务功能及平台功能

    +

    Performance

    +

    验证被测对象在特定预置条件/负载模型下的处理能力的测试项,“处理能力”一般以单位时间内可处理的业务量来衡量,如呼叫/秒,帧率/秒,事件处理量/秒等

    +

    Power

    +

    验证被测对象在特定预置条件/负载模型下在一定时间内能源消耗量的测试项

    +

    Reliability

    +

    验证被测对象在正常/异常输入情况下,或业务量压力和长时间连续运行压力情况下业务表现的测试项,含稳定性、压力、故障注入、Monkey测试项

    +

    Security

    +

    验证系统对恶意威胁的防护能力,威胁包括但不限于未授权访问、使用、泄露、破坏、修改、毁灭,以保障信息的机密性、完整性和可用性; 验证系统对用户隐私的保护能力,保障用户的隐私数据被收集、使用、保有、披露和处置符合法律规范,保障用户的隐私权; 验证对各类安全规范的遵从情况,如安全设计规范、安全红线、工信部安全认证规范等,保障安全相关法律法规的合规。

    +

    Global

    +

    验证被测对象在是否具有国际化数据支持和本地化能力的测试项,包括语言显示、输入/输出习惯、时间显示、区域特性如货币时间禁忌等等

    +

    Compatibility

    +

    当被测对象为应用时,包括被测对象对于自身数据的后向兼容性、对于系统的前后向兼容性、对于不同用户数据(如播放器之音频文件格式/智能短信之用户短信内容)的兼容性测试项; 当被测对象为系统时,包括被测系统对于系统自身数据的后向兼容性、以及对于生态中常用应用的兼容性测试项;当被测对象为软件时,包括被测系统对于相关的硬件的兼容性;

    +

    User

    +

    验证被测对象在真实用户场景下的用户体验感受的测试项,注意此种情况下没有客观的“正确”与“失败”,所有的结论及评价都应该来自于用户

    +

    Standard

    +

    验证被测对象对于行业及公司内标准/协议/规范的遵从情况的测试项,注意此处的“标准”不包含任何安全标准,针对安全标准的测试项划归为“安全测试”类型

    +

    Safety

    +

    验证被测对象的Safety属性,避免产品可能对人身安全、健康以及产品本身带来的危害。

    +

    Resilience

    +

    验证被测对象的韧性属性,确保系统受攻击时承受并保持在有定义的运行状态(包括降级)、恢复并适应攻击以保障Mission达成。

    +
    + +## 用例开发指导 + +根据测试系统选择测试框架和对应测试用例语言。 + +**表 4** 系统和测试框架、开发语言对应关系 + + + + + + + + + + + + + + + + + + + + +

    系统

    +

    测试框架

    +

    语言

    +

    轻量系统

    +

    hctest

    +

    c

    +

    小型系统

    +

    hcpptest

    +

    c++

    +

    标准系统

    +

    HJSUnit、hcpptest

    +

    js、c++

    +
    + +### C语言用例开发编译指导(适用于轻量系统产品用例开发) + +**示例:轻量系统测试用例开发** + +当前使用的测试框架是hctest,hctest测试框架支持使用C语言编写测试用例,是在开源测试框架unity的基础上进行增强和适配。 + +1. 用例目录规范:测试用例存储到test/xts/acts仓中 + + ``` + ├── acts + │ └──subsystem_lite + │ │ └── module_hal + │ │ │ └── BUILD.gn + │ │ │ └── src + │ └──build_lite + │ │ └── BUILD.gn + ``` + +2. src目录下用例编写样例。 + + 1.引用测试框架 + + ``` + #include "hctest.h" + ``` + + 2. 使用宏定义LITE\_TEST\_SUIT定义子系统、模块、测试套件名称 + + ``` + /** + * @brief register a test suit named "IntTestSuite" + * @param test subsystem name + * @param example module name + * @param IntTestSuite test suit name + */ + LITE_TEST_SUIT(test, example, IntTestSuite); + ``` + + 3. 定义Setup与TearDown + + 命名方式:测试套件名称+Setup,测试套件名称+TearDown。 + + Setup与TearDown必须存在,可以为空函数。 + + 4. 使用宏定义LITE\_TEST\_CASE写测试用例 + + 包括三个参数:测试套件名称,测试用例名称,用例属性(测试类型、用例粒度、用例级别)。 + + ``` + LITE_TEST_CASE(IntTestSuite, TestCase001, Function | MediumTest | Level1) + { + //do something + }; + ``` + + 5. 使用宏定义 RUN\_TEST\_SUITE注册测试套件 + + ``` + RUN_TEST_SUITE(IntTestSuite); + ``` + +3. 测试模块的配置文件(BUILD.gn)样例: + + 在每个测试模块目录下新建BUILD.gn编译文件,用于指定编译后静态库的名称、依赖的头文件、依赖的库等;具体写法如下: + + ``` + import("//test/xts/tools/lite/build/suite_lite.gni") + hctest_suite("ActsDemoTest") { + suite_name = "acts" + sources = [ + "src/test_demo.c", + ] + include_dirs = [ ] + cflags = [ "-Wno-error" ] + } + ``` + +4. acts下BUILD.gn增加编译选项。 + + 需要将测试模块加入到acts目录下的编译脚本中,编译脚本路径:test/xts/acts/build\_lite/BUILD.gn。 + + ``` + lite_component("acts") { + ... + if(board_name == "liteos_m") { + features += [ + ... + "//xts/acts/subsystem_lite/module_hal:ActsDemoTest" + ] + } + } + ``` + +5. 测试套件编译命令。 + + 随版本编译,debug版本编译时会同步编译acts测试套件 + + >![](../public_sys-resources/icon-note.gif) **说明:** + >acts测试套件编译中间件为静态库,最终链接到版本镜像中 。 + + +### C语言用例执行指导(适用于轻量系统产品用例开发) + +**示例:轻量系统测试用例执行** + +将版本镜像烧录进开发板。 + +**测试步骤** + +1. 使用串口工具登录开发板,并保存串口打印信息。 +2. 重启设备,查看串口日志。 + +**测试结果分析指导** + +基于串口打印日志进行分析; + +每个测试套件执行以Start to run test suite开始,以xx Tests xx Failures xx Ignored结束。 + +### C++语言用例开发编译指导(适用于小型系统、标准系统用例开发) + +**示例:小型系统测试用例开发**(标准参考具体样例目录:global/i18n\_standard) + +当前使用的测试框架是hcpptest,hcpptest测试框架是在开源的googletest测试框架的基础上进行的增强和适配。 + +1. 规范用例目录:测试用例存储到test/xts/acts仓中。 + + ``` + ├── acts + │ └──subsystem_lite + │ │ └── module_posix + │ │ │ └── BUILD.gn + │ │ │ └── src + │ └──build_lite + │ │ └── BUILD.gn + ``` + +2. 测试模块src下用例编写样例: + + 1. 引用测试框架: + + 需要引用gtest.h 如:\#include "gtest/gtest.h" + + ``` + #include "gtest/gtest.h" + ``` + + 2. 定义Setup与TearDown + + ``` + using namespace std; + using namespace testing::ext; + class TestSuite: public testing::Test { + protected: + // Preset action of the test suite, which is executed before the first test case + static void SetUpTestCase(void){ + } + // Test suite cleanup action, which is executed after the last test case + static void TearDownTestCase(void){ + } + // Preset action of the test case + virtual void SetUp() + { + } + // Cleanup action of the test case + virtual void TearDown() + { + } + }; + ``` + + 3. 使用宏定义HWTEST或HWTEST\_F写测试用例 + + 普通测试用例的定义:HWTEST(测试套名称, 测试用例名称, 用例标注)。 + + 包含SetUp和TearDown的测试用例的定义 :HWTEST\_F(测试套名称, 测试用例名称,用例标注)。 + + 宏定义包括三个参数:测试套件名称,测试用例名称,用例属性(测试类型、用例粒度、用例级别)。 + + ``` + HWTEST_F(TestSuite, TestCase_0001, Function | MediumTest | Level1) { + // do something + } + ``` + +3. 测试模块下用例配置文件(BUILD.gn)样例: + + 每个测试模块目录下新建BUILD.gn编译文件,用于指定编译后可执行文件的名称、依赖的头文件、依赖的库等;具体写法如下。每个测试模块将独立编译成.bin可执行文件, 该文件可直接push到单板上进行测试。 + + 举例: + + ``` + import("//test/xts/tools/lite/build/suite_lite.gni") + hcpptest_suite("ActsDemoTest") { + suite_name = "acts" + sources = [ + "src/TestDemo.cpp" + ] + + include_dirs = [ + "src", + ... + ] + deps = [ + ... + ] + cflags = [ "-Wno-error" ] + } + + ``` + +4. acts目录下增加编译选项(BUILD.gn)样例: + + 将测试模块加入到acts目录下的编译脚本中,编译脚本为:test/xts/acts/build\_lite/BUILD.gn。 + + ``` + lite_component("acts") { + ... + else if(board_name == "liteos_a") { + features += [ + ... + "//xts/acts/subsystem_lite/module_posix:ActsDemoTest" + ] + } + } + ``` + +5. 测试套件编译命令。 + + 随版本编译,debug版本编译时会同步编译acts测试套件 + + >![](../public_sys-resources/icon-note.gif) **说明:** + >小型系统acts独立编译成可执行文件(bin格式), 在编译产物的suites\\acts目录下归档。 + + +### C++语言用例执行指导(适用于小型系统、标准系统用例开发) + +**示例:小型系统测试用例执行** + +目前的用例执行采用nfs共享的方式,mount到单板去执行。 + +**环境搭建** + +1. 使用有限网线或无线将开发板与PC进行连接。 +2. 开发板配置IP、子网掩码、网关,确保开发板与PC处于同一个网段。 +3. PC安装nfs服务器并完成注册,启动nfs服务。 +4. 开发板配置mount命令,确保开发板可以访问PC端的nfs共享文件。 + + 格式:mount \[nfs服务器IP\]:\[/nfs共享目录\] \[/开发板目录\] nfs + + 举例: + + ``` + mount 192.168.1.10:/nfs /nfs nfs + ``` + + +**用例执行** + +测试套件执行 ActsDemoTest.bin 触发用例执行,基于串口打印日志进行分析。 + +### JS语言用例开发指导(适用于标准系统) + +当前使用的测试框架是HJSUnit,用于支撑OpenHarmony application测试(特指基于JS应用框架使用 Javascript 语言开发的 APP)进行自动化测试。 + +**用例编写基础语法** + +测试用例为 js 语言,必须满足 JavaScript 语言编程规范: + +**表 5** + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    用例语法

    +

    描述

    +

    要求

    +

    beforeAll

    +

    测试套级别的预置条件,在所有测试用例开始前执行且仅执行一次,支持一个参数:预置动作函数

    +

    可选

    +

    afterAll

    +

    测试套级别的清理条件,在所有测试用例结束后执行且仅执行一次,支持一个参数:清理动作函数

    +

    可选

    +

    beforeEach

    +

    测试用例级别的预置条件,在每条测试用例开始前执行,执行次数与 it 定义的测试用例数一致,支持一个参数:预置动作函数

    +

    可选

    +

    afterEach

    +

    测试用例级别的清理条件,在每条测试用例结束后执行,执行次数与 it 定义的测试用例数一致,支持一个参数:清理动作函数

    +

    可选

    +

    describe

    +

    定义一个测试套,支持两个参数:测试套名称和测试套函数; describe 支持嵌套,每个 describe 内均可以定义 beforeAll 、beforeEach 、afterEach 和 afterAll

    +

    必选

    +

    it

    +

    定义一条测试用例,支持三个参数:用例名称,过滤参数和用例函数

    +

    备注:

    +

    过滤参数:过滤参数为一个 32 位的 Int 类型参数,0 位 置1表示不筛选、默认执行;0-10 位 置1表示测试用例类型;16-18 位 置1表示测试用例规模;24-28 位 置1表示测试层级

    +

    测试用例类型。置位0-10分别表示:FUNCTION 方法类测试、PERFORMANCE 性能类测试、POWER 功耗类测试、RELIABILITY 可靠性测试、SECURITY 安全合规测试、GLOBAL 整体性测试、COMPATIBILITY 兼容性测试、USER 用户测试、STANDARD 标准测试、SAFETY 安全特性测试,RESILIENCE 压力测试。

    +

    测试用例规模。置位16-18分别表示:SMALL 小型测试、MEDIUM 中型测试、LARGE 大型测试。

    +

    测试层级。置位24-28分别表示:LEVEL0-0 级测试、LEVEL1-1 级测试、LEVEL2-2 级测试、LEVEL3-3 级测试、LEVEL4-4 级测试。

    +

    必选

    +
    + +用例编写语法采用 jasmine 的标准语法,格式支持ES6格式。 + +1. 规范用例目录:测试用例存储到entry/src/main/js/test目录。 + + ``` + ├── BUILD.gn + │ └──entry + │ │ └──src + │ │ │ └──main + │ │ │ │ └──js + │ │ │ │ │ └──default + │ │ │ │ │ │ └──pages + │ │ │ │ │ │ │ └──index + │ │ │ │ │ │ │ │ └──index.js # 入口文件 + │ │ │ │ │ └──test # 测试代码存放目录 + │ │ │ └── resources # hap资源存放目录 + │ │ │ └── config.json # hap配置文件 + ``` + +2. index.js示例 + + ``` + // 拉起js测试框架,加载测试用例 + import {Core, ExpectExtend} from 'deccjsunit/index' + + export default { + data: { + title: "" + }, + onInit() { + this.title = this.$t('strings.world'); + }, + onShow() { + console.info('onShow finish') + const core = Core.getInstance() + const expectExtend = new ExpectExtend({ + 'id': 'extend' + }) + core.addService('expect', expectExtend) + core.init() + const configService = core.getDefaultService('config') + configService.setConfig(this) + require('../../../test/List.test') + core.execute() + }, + onReady() { + }, + } + ``` + +3. 单元测试用例示例 + + ``` + // Example1: 使用HJSUnit进行单元测试 + describe('appInfoTest', function () { + it('app_info_test_001', 0, function () { + var info = app.getInfo() + expect(info.versionName).assertEqual('1.0') + expect(info.versionCode).assertEqual('3') + }) + }) + ``` + + +### JS语言用例编译打包指导(适用于标准系统) + +hap包编译请参考[标准系统js应用开发指导](https://developer.harmonyos.com/cn/docs/documentation/doc-guides/build_overview-0000001055075201)。 + +## 全量编译指导(适用于标准系统) + +1. 全量编译 + + **命令**: + + ``` + ./build.sh suite=acts system_size=standard + ``` + + **测试用例输出目录**:out/release/suites/acts/testcases + + **测试框架&用例整体输出目录:**out/release/suites/acts(编译用例时会同步编译测试套执行框架) + + +## 全量用例执行指导(适用于小型系统、标准系统) + +**搭建测试环境** + +Windows工作台下安装python3.7及以上版本,确保工作台和测试设备正常连接。 + +**测试执行目录**(对应编译生成的out/release/suites/acts目录) + +``` +├── testcase # 测试套文件存放目录 +│ └──xxx.hap # 测试套可执行hap文件 +│ └──xxx.json # 测试套对应执行配置文件 +├── tools # 测试框架工具目录 +├── run.bat # window平台测试套启动执行文件 +├── report # 测试报告生成目录 +``` + +**用例执行** + +1. 在Windows工作台上,找到从Linux服务器上拷贝下来的测试套件用例目录\(对应编译生成的out/release/suites/acts目录\),在Windows命令窗口进入对应目录,直接执行acts\\run.bat。 + +1. 界面启动后,输入用例执行指令。 + + - 全量执行 + + ``` + run acts + ``` + + ![](figure/zh-cn_image_0000001119924146.gif) + + + - 模块执行\(具体模块可以查看\\acts\\testcases\\\) + + ``` + run –l ActsSamgrTest + ``` + + ![](figure/zh-cn_image_0000001166643927.jpg) + + + 等待执行完成。 + + +1. 查看测试报告。 + + 进入acts\\reports\\,获取当前的执行记录,打开“summary\_report.html”可以获取到测试报告。 + + diff --git a/zh-cn/device-dev/subsystems/subsys.md b/zh-cn/device-dev/subsystems/subsys.md new file mode 100644 index 0000000000..d4d4822436 --- /dev/null +++ b/zh-cn/device-dev/subsystems/subsys.md @@ -0,0 +1,33 @@ +# 子系统开发指南 + +- **[编译构建](subsys-build.md)** + +- **[分布式远程启动](subsys-remote-start.md)** + +- **[图形图像](subsys-graphics.md)** + +- **[媒体](subsys-multimedia.md)** + +- **[公共基础](subsys-utils.md)** + +- **[AI框架](subsys-aiframework.md)** + +- **[Sensor服务](subsys-densor.md)** + +- **[用户程序框架](subsys-application-framework.md)** + +- **[OTA升级](subsys-ota-guide.md)** + +- **[安全](subsys-security.md)** + +- **[启动恢复](subsys-boot.md)** + +- **[测试](subsys-testguide-test.md)** + +- **[DFX](subsys-dfx.md)** + +- **[HiSysEvent订阅指导](subsys-dfx-hisyseventread.md)** + +- **[XTS认证子系统开发指南](subsys-xts-guide.md)** + + diff --git "a/zh-cn/device-dev/subsystems/\344\273\243\347\240\201\347\256\241\347\220\206\350\247\204\350\214\203.md" "b/zh-cn/device-dev/subsystems/\344\273\243\347\240\201\347\256\241\347\220\206\350\247\204\350\214\203.md" deleted file mode 100755 index 25dde0bbc8..0000000000 --- "a/zh-cn/device-dev/subsystems/\344\273\243\347\240\201\347\256\241\347\220\206\350\247\204\350\214\203.md" +++ /dev/null @@ -1,40 +0,0 @@ -# 代码管理规范 - -- [建议:插件与北向SDK在AI引擎指定的路径下进行代码开发](#section17176374131) -- [规则:插件提供的全部对外接口,统一存放在AI业务子系统interfaces/kits目录](#section2551029111312) -- [规则:插件编译输出路径必须是在/usr/lib](#section97021558121310) - -AI引擎框架包含client、server和common三个主要模块,其中client提供server端连接管理功能,北向SDK在算法对外接口中需封装调用client提供的公共接口;server提供插件加载以及任务管理等功能,各Plugin实现由server提供的插件接口,完成插件接入;common提供与平台相关的操作方法、引擎协议以及相关工具类,供其他各模块调用。 - -AI引擎框架各模块之间的代码依赖关系如下[图1](#fig171811112818)所示: - -**图 1** ****AI引擎代码依赖关系 - - -![](figures/插件依赖-(2).jpg) - -## 建议:插件与北向SDK在AI引擎指定的路径下进行代码开发 - -在AI引擎框架的整体规划中,北向SDK属于client端的一部分,插件由server端调用,属于server端的一部分,因此AI引擎框架为接入的插件与北向SDK规划的路径: - -- SDK代码路径://foundation/ai/engine/services/client/algorithm\_sdk - - e.g. //foundation/ai/engine/services/client/algorithm\_sdk/cv - - e.g. //foundation/ai/engine/services/client/algorithm\_sdk/nlu - -- 插件代码路径://foundation/ai/engine/services/server/plugin - - e.g. //foundation/ai/engine/services/server/plugin/cv - - e.g. //foundation/ai/engine/services/server/plugin/nlu - - -## 规则:插件提供的全部对外接口,统一存放在AI业务子系统interfaces/kits目录 - -北向SDK对外接口是AI业务子系统提供能力的对外暴露方式,按照OpenHarmony的接口管理要求,需统一存放在各子系统的interfaces/kits目录中。当前AI业务子系统插件对外接口路径为//foundation/ai/engine/interfaces/kits,不同插件可在该路径下添加目录,比如增加cv插件,则在路径//foundation/ai/engine/interfaces/kits/cv下面存放接口文件。 - -## 规则:插件编译输出路径必须是在/usr/lib - -server端加载插件是采用dlopen方式,只支持在/usr/lib路径进行,因此插件在编译so时,需要在编译配置文件中指定输出路径为/usr/lib。 - diff --git "a/zh-cn/device-dev/subsystems/\345\205\254\345\205\261\345\237\272\347\241\200.md" "b/zh-cn/device-dev/subsystems/\345\205\254\345\205\261\345\237\272\347\241\200.md" deleted file mode 100755 index 5a9dc69874..0000000000 --- "a/zh-cn/device-dev/subsystems/\345\205\254\345\205\261\345\237\272\347\241\200.md" +++ /dev/null @@ -1,9 +0,0 @@ -# 公共基础 - -- **[公共基础库概述](公共基础库概述.md)** - -- **[公共基础库开发指导](公共基础库开发指导.md)** - -- **[公共基础库常见问题](公共基础库常见问题.md)** - - diff --git "a/zh-cn/device-dev/subsystems/\345\205\254\345\205\261\345\237\272\347\241\200\345\272\223\345\274\200\345\217\221\346\214\207\345\257\274.md" "b/zh-cn/device-dev/subsystems/\345\205\254\345\205\261\345\237\272\347\241\200\345\272\223\345\274\200\345\217\221\346\214\207\345\257\274.md" deleted file mode 100755 index 38a64bb9eb..0000000000 --- "a/zh-cn/device-dev/subsystems/\345\205\254\345\205\261\345\237\272\347\241\200\345\272\223\345\274\200\345\217\221\346\214\207\345\257\274.md" +++ /dev/null @@ -1,298 +0,0 @@ -# 公共基础库开发指导 - -- [接口说明](#section1633115419401) -- [开发步骤](#section17450172710292) - - [LiteOS-A内核\(Hi3516、Hi3518平台\)KV存储的native应用开发步骤:](#section258354119295) - - [Dump系统属性在LiteOS-M内核平台使用指南:](#section9179161863014) - - [Dump系统属性在LiteOS-A内核平台使用指南:](#section3179121853017) - - -## 接口说明 - -**表 1** 文件操作接口说明 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    接口名

    -

    描述

    -

    int UtilsFileOpen(const char* path, int oflag, int mode)

    -

    打开或创建文件

    -

    int UtilsFileClose(int fd)

    -

    关闭文件

    -

    int UtilsFileRead(int fd, char *buf, unsigned int len)

    -

    读取特定长度的文件数据

    -

    int UtilsFileWrite(int fd, const char *buf, unsigned int len)

    -

    向文件写入特定大小的数据

    -

    int UtilsFileDelete(const char *path)

    -

    删除指定文件

    -

    int UtilsFileStat(const char *path, unsigned int *fileSize)

    -

    获取文件大小

    -

    int UtilsFileSeek(int fd, int offset, unsigned int whence)

    -

    重新定位文件读/写偏移量

    -

    int UtilsFileCopy(const char* src, const char* dest)

    -

    将源文件复制一份并存储到目标文件

    -

    int UtilsFileMove(const char* src, const char* dest)

    -

    将源文件移动到指定目标文件

    -
    - -文件操作使用示例: - -``` -// open && write -char fileName[] = "testfile"; -static const char def[] = "utils_file_operation implement."; -int fd = UtilsFileOpen(fileName, O_RDWR_FS | O_CREAT_FS | O_TRUNC_FS, 0); -printf("file handle = %d\n", fd); -int ret = UtilsFileWrite(fd, def, strlen(def)); -printf("write ret = %d\n", ret); - -// seek -ret = UtilsFileSeek(fd, 5, SEEK_SET_FS); -printf("lseek ret = %d\n", ret); - -// read && close -char buf[64] = {0}; -int readLen = UtilsFileRead(fd, buf, 64); -ret = UtilsFileClose(fd); -printf("read len = %d : buf = %s\n", readLen, buf); - -// stat -int fileLen = 0; -ret = UtilsFileStat(fileName, &fileLen); -printf("file size = %d\n", fileLen); - -// delete -ret = UtilsFileDelete(fileName); -printf("delete ret = %d\n", ret); -``` - -**表 2** KV存储接口说明 - - - - - - - - - - - - - - - - -

    接口名

    -

    描述

    -

    int UtilsGetValue(const char* key, char* value, unsigned int len)

    -

    提供给上层应用根据key获取对应数据项

    -

    int UtilsSetValue(const char* key, const char* value)

    -

    提供给上层应用用于存储/更新key对应数据项

    -

    int UtilsDeleteValue(const char* key)

    -

    提供给上层应用删除key对应数据项

    -
    - -KV存储使用示例: - -``` -// set -char key[] = "rw.sys.version_100"; -char value[] = "Hello kv operation implement!"; -int ret = UtilsSetValue(key, value); -printf("UtilsSetValue set ret = %d\n", ret); - -// get -char temp[128] = {0}; -ret = UtilsGetValue(key, temp, 128); -printf("UtilsGetValue get ret = %d, temp = %s\n", ret, temp); - -// delete -ret = UtilsDeleteValue(key); -printf("UtilsDeleteValue delete ret = %d\n", ret); -``` - - - - -
    - -## 开发步骤 - -### LiteOS-A内核\(Hi3516、Hi3518平台\)KV存储的native应用开发步骤: - -1. 基于AbilityKit开发KV存储的native应用。 - - 基于KV存储提供的接口编写用户程序,并编译出so(libLauncher.so)文件。 - - ``` - // set - char key[] = "rw.sys.version_100"; - char value[] = "Hello kv operation implement!"; - int ret = UtilsSetValue(key, value); - printf("UtilsSetValue set ret = %d\n", ret); - - // get - char temp[128] = {0}; - ret = UtilsGetValue(key, temp, 128); - printf("UtilsGetValue get ret = %d, temp = %s\n", ret, temp); - - // delete - ret = UtilsDeleteValue(key); - printf("UtilsDeleteValue delete ret = %d\n", ret); - ``` - - - 编写config.json文件,内容如下: - - ``` - { - "app": { - "bundleName": "com.huawei.launcher", - "vendor": "huawei", - "version": { - "code": 1, - "name": "1.0" - } - }, - "deviceConfig": { - "default": { - "reqSdk": { - "compatible": "zsdk 1.0.0", - "target": "zsdk 1.0.1" - }, - "keepAlive": false - }, - "smartCamera": { - "reqSdk": { - "compatible": "zsdk 1.0.0", - "target": "zsdk 1.0.1" - }, - "keepAlive": false - } - }, - "module": { - "package": "com.huawei.launcher", - "name": ".MyHarmonyAbilityPackage", - "deviceType": [ - "phone", "tv","tablet", "pc","car","smartWatch","sportsWatch","smartCamera" - ], - "distro": { - "deliveryWithInstall": true, - "moduleName": "Launcher", - "moduleType": "entry" - }, - "abilities": [{ - "name": "MainAbility", - "icon": "res/drawable/phone.png", - "label": "test app 1", - "launchType": "standard", - "type": "page" - }, - { - "name": "SecondAbility", - "icon": "res/drawable/phone.png", - "label": "test app 2", - "launchType": "standard", - "type": "page" - }, - { - "name": "ServiceAbility", - "icon": "res/drawable/phone.png", - "label": "test app 2", - "launchType": "standard", - "type": "service" - } - ] - } - } - ``` - - - - 生成hap包。 - - - 按照如下目录结构存放文件,res/drawable下面放置资源文件: - - ![](figures/unnaming.png) - - - 将上述文件打包生成zip包,修改后缀为.hap,例如Launcher.hap - - -2. 连接单板,通过串口向单板发送安装KV存储native应用的命令。 - - ``` - ./nfs/dev_tools/bin/bm install -p /nfs/Launcher.hap - ``` - -3. 通过串口向单板发送运行KV存储native应用的命令。 - - ``` - ./nfs/dev_tools/bin/aa start -p com.huawei.launcher -n ServiceAbility - ``` - - -### Dump系统属性在LiteOS-M内核平台使用指南: - -1. 连接单板,通过串口向单板发送AT+SYSPARA命令。 - - ``` - AT+SYSPARA - ``` - - **图 1** LiteOS-M平台dump系统属性输出 - ![](figures/LiteOS-M平台dump系统属性输出.png "LiteOS-M平台dump系统属性输出") - - -### Dump系统属性在LiteOS-A内核平台使用指南: - -1. 连接单板,运行bin路径下的os\_dump加参数--help,查看os\_dump使用指导。 - - ``` - ./bin/os_dump --help - ``` - -2. os\_dump加参数-l,查看当前系统有哪些模块支持获取属性。 - - ``` - ./bin/os_dump -l - ``` - -3. os\_dump加参数syspara,查看当前系统属性 - - ``` - ./bin/os_dump syspara - ``` - - **图 2** LiteOS-A平台dump系统属性输出 - ![](figures/LiteOS-A平台dump系统属性输出.png "LiteOS-A平台dump系统属性输出") - - diff --git "a/zh-cn/device-dev/subsystems/\345\212\250\347\224\273\345\274\200\345\217\221\346\214\207\345\257\274.md" "b/zh-cn/device-dev/subsystems/\345\212\250\347\224\273\345\274\200\345\217\221\346\214\207\345\257\274.md" deleted file mode 100755 index e58aed68c0..0000000000 --- "a/zh-cn/device-dev/subsystems/\345\212\250\347\224\273\345\274\200\345\217\221\346\214\207\345\257\274.md" +++ /dev/null @@ -1,190 +0,0 @@ -# 动画开发指导 - -- [使用场景](#section726685714018) -- [接口说明](#section85794718418) -- [开发步骤](#section14101161317435) - -## 使用场景 - -UI动画通过task处理机制每个tick调用一下用户设置的callback函数来实现,具体实现为AnimatorManager、Animator、AnimatorCallback三个类实现。 - -- AnimatorManager:AnimatorManager为单例,在Init函数执行时将自己注册到系统task回调函数中,系统task机制保证每个tick会调用一下AnimatorManager的callback函数,同时AnimatorManager用来管理Animator实例。 -- Animator:Animator中可以设置动画相关的属性,包括动画的起止时间,动画开始和停止,动画状态的设置和获取等。 -- AnimatorCallback:具体每一个tick动画所要做的内容在AnimatorCallback类中实现,开发者需要自己实现Callback方法,动画执行时在Callback实现相应功能。 - -## 接口说明 - -**表 1** 动画接口说明 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    子模块

    -

    方法

    -

    功能

    -

    Animator

    -

    void Start ()

    -

    动画开始

    -

    Animator

    -

    void Stop ()

    -

    动画停止

    -

    Animator

    -

    void Pause ()

    -

    动画暂停

    -

    Animator

    -

    void Resume ()

    -

    动画恢复

    -

    Animator

    -

    uint8_t GetState () const

    -

    获取动画当前状态

    -

    Animator

    -

    void SetState (uint8_t state)

    -

    设置动画当前状态

    -

    Animator

    -

    uint32_t GetTime () const

    -

    获取动画总持续时间

    -

    Animator

    -

    void SetTime (uint32_t time)

    -

    设置动画总持续时间

    -

    Animator

    -

    uint32_t GetRunTime () const

    -

    获取动画当前已经持续的时间

    -

    Animator

    -

    void SetRunTime (uint32_t runTime)

    -

    设置动画当前已经持续的时间

    -

    Animator

    -

    bool IsRepeat () const

    -

    获取动画是否循环播放

    -

    AnimatorCallback

    -

    virtual void Callback (UIView *view)=0

    -

    由用户实现,动画回调函数

    -

    AnimatorCallback

    -

    virtual void OnStop(UIView& view) {}

    -

    由用户实现,动画停止后的回调函数

    -

    AnimatorManager

    -

    static AnimatorManager* GetInstance()

    -

    获取AnimatorManager实例

    -

    AnimatorManager

    -

    void Add (Animator *animator)

    -

    添加动画

    -

    AnimatorManager

    -

    void Remove(const Animator* animator);

    -

    删除动画

    -
    - -## 开发步骤 - -1. 实现AnimatorCallback的回调函数。 - - ``` - class AnimatorCallbackDemo : public OHOS::AnimatorCallback { - public: - AnimatorCallbackDemo(int16_t startPos, int16_t endPos, uint16_t time) - : start_(startPos), end_(endPos), time_(time), curTime_(0) {} - - virtual void Callback(OHOS::UIView* view) - { - curTime_++; - int16_t pos = EasingEquation::CubicEaseIn(start_, end_, curTime_, time_); - view->Invalidate(); - view->SetPosition(pos, view->GetY()); - view->Invalidate(); - } - protected: - int16_t start_; - int16_t end_; - uint16_t time_; - uint16_t curTime_; - }; - ``` - -2. 将AnimatorCallback添加到Animator中。 - - ``` - UIImageView* image = new UIImageView(); - image->SetSrc("..\\config\\images\\A021_001.bin"); - image->SetPosition(0, 50); - AnimatorCallbackDemo* callback = new AnimatorCallbackDemo(0, 338, 60); - Animator* animator = new Animator(callback, image, 0, true); - ``` - -3. 将Animator添加到AnimatorManager中。 - - ``` - AnimatorManager::GetInstance()->Add(animator); - ``` - -4. 点击下图下方的按钮,检查对应的动画运行效果。 - - **图 1** 动画实现效果图 - ![](figures/动画实现效果图.gif "动画实现效果图") - - diff --git "a/zh-cn/device-dev/subsystems/\345\220\257\345\212\250\346\201\242\345\244\215.md" "b/zh-cn/device-dev/subsystems/\345\220\257\345\212\250\346\201\242\345\244\215.md" deleted file mode 100755 index 0514d4bd50..0000000000 --- "a/zh-cn/device-dev/subsystems/\345\220\257\345\212\250\346\201\242\345\244\215.md" +++ /dev/null @@ -1,17 +0,0 @@ -# 启动恢复 - -- **[启动恢复子系统概述](启动恢复子系统概述.md)** - -- **[init启动引导组件](init启动引导组件.md)** - -- **[appspawn应用孵化组件](appspawn应用孵化组件.md)** - -- **[bootstrap服务启动组件](bootstrap服务启动组件.md)** - -- **[syspara系统属性组件](syspara系统属性组件.md)** - -- **[常见问题](常见问题.md)** - -- **[参考](参考.md)** - - diff --git "a/zh-cn/device-dev/subsystems/\345\220\257\345\212\250\346\201\242\345\244\215\345\255\220\347\263\273\347\273\237\346\246\202\350\277\260.md" "b/zh-cn/device-dev/subsystems/\345\220\257\345\212\250\346\201\242\345\244\215\345\255\220\347\263\273\347\273\237\346\246\202\350\277\260.md" deleted file mode 100755 index 1287b4212d..0000000000 --- "a/zh-cn/device-dev/subsystems/\345\220\257\345\212\250\346\201\242\345\244\215\345\255\220\347\263\273\347\273\237\346\246\202\350\277\260.md" +++ /dev/null @@ -1,66 +0,0 @@ -# 启动恢复子系统概述 - -- [约束与限制](#section2029921310472) - -启动恢复子系统负责从内核启动之后到应用启动之前的系统关键服务进程的启动过程以及设备恢复出厂设置的功能。涉及以下组件: - -- init启动引导组件 - - init启动引导组件对应的进程为init进程,是内核完成初始化后启动的第一个用户态进程。init进程启动之后,读取init.cfg配置文件,根据解析结果,执行相应命令(见[第2章表2](init启动引导组件.md#table122681439144112)描述)并依次启动各关键系统服务进程,在启动系统服务进程的同时设置其对应权限。 - -- appspawn应用孵化组件 - - 负责接收**用户程序框架**的命令孵化应用进程,设置新进程的权限,并调用应用程序框架的入口函数。 - -- bootstrap服务启动组件 - - 提供了各服务和功能的启动入口标识。在SAMGR启动时,会调用boostrap标识的入口函数,并启动系统服务。 - -- syspara系统属性组件 - - 系统属性组件,根据OpenHarmony产品兼容性规范提供获取设备信息的接口,如:产品名、品牌名、厂家名等,同时提供设置/读取系统属性的接口。 - - -## 约束与限制 - -启动恢复子系统源代码目录和适配平台: - -**表 1** 启动恢复子系统源代码目录和适配平台 - - - - - - - - - - - - - - - - - - - -

    名称

    -

    适配平台

    -

    base/startup/appspawn_lite

    -

    小型系统设备(参考内存≥1MB),如Hi3516DV300 、Hi3518EV300

    -

    base/startup/bootstrap_lite

    -

    轻量系统设备(参考内存≥128KB),如Hi3861V100

    -

    base/startup/init_lite

    -

    小型系统设备(参考内存≥1MB),如Hi3516DV300、Hi3518EV300

    -

    base/startup/syspara_lite

    -
    • 轻量系统设备(参考内存≥128KB),如Hi3861V100
    • 小型系统设备(参考内存≥1MB),如Hi3516DV300、Hi3518EV300
    -
    - -- init启动引导组件: - - 配置文件init.cfg烧写到单板之后变成只读模式,修改时必须重新打包和烧写rootfs镜像。 - - 配置文件init.cfg仅支持json格式。 - -- bootstrap服务启动组件:需要在链接脚本中配置zInit代码段。 -- syspara系统属性组件:SetParameter/GetParameter仅支持uid大于1000的应用调用。 - diff --git "a/zh-cn/device-dev/subsystems/\345\224\244\351\206\222\350\257\215\350\257\206\345\210\253SDK\347\232\204\345\274\200\345\217\221\347\244\272\344\276\213.md" "b/zh-cn/device-dev/subsystems/\345\224\244\351\206\222\350\257\215\350\257\206\345\210\253SDK\347\232\204\345\274\200\345\217\221\347\244\272\344\276\213.md" deleted file mode 100755 index c8f592b80c..0000000000 --- "a/zh-cn/device-dev/subsystems/\345\224\244\351\206\222\350\257\215\350\257\206\345\210\253SDK\347\232\204\345\274\200\345\217\221\347\244\272\344\276\213.md" +++ /dev/null @@ -1,81 +0,0 @@ -# 唤醒词识别SDK的开发示例 - -1. 在//foundation/ai/engine /interfaces/kits目录中添加唤醒词识别SDK的API接口定义,该接口可用三方应用的调用。如下代码片段即为唤醒词识别定义的API接口示例,其相关代码参考路径为://foundation/ai/engine /interfaces/kits/asr/keyword\_spotting。 - - ``` - class KWSSdk { - public: - KWSSdk(); - virtual ~KWSSdk(); - - // 定义了创建唤醒词检测工具包的方法 - int32_t Create(); - - // 定义了同步执行唤醒词检测任务的方法 - int32_t SyncExecute(const Array &audioInput); - - // 定义了设置唤醒词检测回调器的方法 - int32_t SetCallback(const std::shared_ptr &callback); - - // 定义了销毁唤醒词工具包的方法,释放与插件的会话信息。 - int32_t Destroy(); - }; - ``` - -2. 在//foundation/ai/engine/services/client/algorithm\_sdk的目录中增加SDK中API接口的具体实现,调用client端提供的接口,实现算法插件能力的使用。如下代码片段即为唤醒词识别的API接口中create方法的具体实现示例,更多详细代码可参考://foundation/ai/engine/services/client/algorithm\_sdk/asr/keyword\_spotting。 - - ``` - int32_t KWSSdk::KWSSdkImpl::Create() - { - if (kwsHandle_ != INVALID_KWS_HANDLE) { - HILOGE("[KWSSdkImpl]The SDK has been created"); - return KWS_RETCODE_FAILURE; - } - if (InitComponents() != RETCODE_SUCCESS) { - HILOGE("[KWSSdkImpl]Fail to init sdk components"); - return KWS_RETCODE_FAILURE; - } - // 调用client端提供的接口AieClientInit,实现初始化引擎服务,激活跨进程调用 - int32_t retCode = AieClientInit(configInfo_, clientInfo_, algorithmInfo_, nullptr); - if (retCode != RETCODE_SUCCESS) { - HILOGE("[KWSSdkImpl]AieClientInit failed. Error code[%d]", retCode); - return KWS_RETCODE_FAILURE; - } - if (clientInfo_.clientId == INVALID_CLIENT_ID) { - HILOGE("[KWSSdkImpl]Fail to allocate client id"); - return KWS_RETCODE_FAILURE; - } - DataInfo inputInfo = { - .data = nullptr, - .length = 0, - }; - DataInfo outputInfo = { - .data = nullptr, - .length = 0, - }; - // 调用client端提供的接口AieClientPrepare,实现加载算法插件 - retCode = AieClientPrepare(clientInfo_, algorithmInfo_, inputInfo, outputInfo, nullptr); - if (retCode != RETCODE_SUCCESS) { - HILOGE("[KWSSdkImpl]AieclientPrepare failed. Error code[%d]", retCode); - return KWS_RETCODE_FAILURE; - } - if (outputInfo.data == nullptr || outputInfo.length <= 0) { - HILOGE("[KWSSdkImpl]The data or length of output info is invalid"); - return KWS_RETCODE_FAILURE; - } - MallocPointerGuard pointerGuard(outputInfo.data); - retCode = PluginHelper::UnSerializeHandle(outputInfo, kwsHandle_); - if (retCode != RETCODE_SUCCESS) { - HILOGE("[KWSSdkImpl]Get handle from inputInfo failed"); - return KWS_RETCODE_FAILURE; - } - return KWS_RETCODE_SUCCESS; - } - ``` - - 上述代码为API接口的具体实现,从上述示例的代码中,SDK中create接口的具体实现即为下述示例代码中create方法,该方法调用了AI引擎框架client端开放接口AieClientInit,AieClientPrepare,从而实现与server端建立连接及加载算法模型的能力。 - - >![](public_sys-resources/icon-note.gif) **说明:** - >SDK调用AI引擎client端接口顺序应遵循AieClientInit-\>AieClientPrepare-\>AieClientSyncProcess/AieClientAsyncProcess-\>AieClientRelease-\>AieClientDestroy,否则调用接口会返回错误码。 - - diff --git "a/zh-cn/device-dev/subsystems/\345\233\276\345\275\242\345\233\276\345\203\217.md" "b/zh-cn/device-dev/subsystems/\345\233\276\345\275\242\345\233\276\345\203\217.md" deleted file mode 100755 index 08422282d6..0000000000 --- "a/zh-cn/device-dev/subsystems/\345\233\276\345\275\242\345\233\276\345\203\217.md" +++ /dev/null @@ -1,13 +0,0 @@ -# 图形图像 - -- **[图形图像概述](图形图像概述.md)** - -- **[容器类组件开发指导](容器类组件开发指导.md)** - -- **[布局容器类组件开发指导](布局容器类组件开发指导.md)** - -- **[普通组件开发指导](普通组件开发指导.md)** - -- **[动画开发指导](动画开发指导.md)** - - diff --git "a/zh-cn/device-dev/subsystems/\345\252\222\344\275\223.md" "b/zh-cn/device-dev/subsystems/\345\252\222\344\275\223.md" deleted file mode 100755 index c76c3a1f71..0000000000 --- "a/zh-cn/device-dev/subsystems/\345\252\222\344\275\223.md" +++ /dev/null @@ -1,7 +0,0 @@ -# 媒体 - -- **[相机](相机.md)** - -- **[音视频](音视频.md)** - - diff --git "a/zh-cn/device-dev/subsystems/\345\256\211\345\205\250.md" "b/zh-cn/device-dev/subsystems/\345\256\211\345\205\250.md" deleted file mode 100755 index 88ce479aa0..0000000000 --- "a/zh-cn/device-dev/subsystems/\345\256\211\345\205\250.md" +++ /dev/null @@ -1,13 +0,0 @@ -# 安全 - -- **[概述](概述-7.md)** - -- **[应用验签开发指导](应用验签开发指导.md)** - -- **[应用权限管理开发指导](应用权限管理开发指导.md)** - -- **[IPC通信鉴权开发指导](IPC通信鉴权开发指导.md)** - -- **[可信设备群组管理开发指导](可信设备群组管理开发指导.md)** - - diff --git "a/zh-cn/device-dev/subsystems/\345\256\271\345\231\250\347\261\273\347\273\204\344\273\266\345\274\200\345\217\221\346\214\207\345\257\274.md" "b/zh-cn/device-dev/subsystems/\345\256\271\345\231\250\347\261\273\347\273\204\344\273\266\345\274\200\345\217\221\346\214\207\345\257\274.md" deleted file mode 100755 index 507ad3b118..0000000000 --- "a/zh-cn/device-dev/subsystems/\345\256\271\345\231\250\347\261\273\347\273\204\344\273\266\345\274\200\345\217\221\346\214\207\345\257\274.md" +++ /dev/null @@ -1,244 +0,0 @@ -# 容器类组件开发指导 - -- [UIViewGroup](#section145471898812) -- [使用场景](#section0916112362216) -- [接口说明](#section12641756192212) -- [开发步骤](#section5412161692311) -- [UIScrollView](#section174961523161315) -- [使用场景](#section8937101902413) -- [接口说明](#section14789133142420) -- [开发步骤](#section1769754422417) - -容器类组件,指能包含其它UI组件的组件,容器类组件继承于UIViewGroup(带Add方法),基于实际组件的使用场景,将需要增加其他子组件的组件,放置到容器类继承结构下。如UIAnalogClock内,通常会Add需要的计步信息,时分秒图标等。 - -**图 1** 普通容器类组件结构 -![](figures/普通容器类组件结构.png "普通容器类组件结构") - -RootView、UIAbstractScroll、UIPicker组件从UIViewGroup继承,UIList、UIScrollView、UISwipeView组件从UIAbstractScroll继承。 - -## UIViewGroup - -## 使用场景 - -UIViewGroup是容器类组件基类,实现增加、删除、插入等操作,通过增加方法可以添加子组件。普通容器类组件子组件需要设置位置信息,位置信息为相对父组件的相对坐标。组件树结构如下图: - -**图 2** 组件树结构示意图 -![](figures/组件树结构示意图.png "组件树结构示意图") - -往根节点rootView里添加ViewGroup1容器组件和View1组件,往ViewGroup1容器组件里再添加View2组件和ViewGroup2容器组件,在View1之后添加View3组件。 - -- 关于渲染:容器类组件在渲染时会遍历所有子组件OnDraw方法,以达到刷新所有组件的目的。 -- 关于坐标:子组件位置信息为相对父组件的相对坐标,系统在渲染时计算绝对坐标并显示。 -- 关于树结构遍历:UIViewGroup提供如下方法实现遍历、查找、管理组件树。 - -## 接口说明 - -**表 1** ViewGroup接口说明 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    方法

    -

    功能

    -

    virtual void Add(UIView* view)

    -

    添加子组件

    -

    virtual void Insert(UIView* prevView, UIView* insertView)

    -

    插入子组件

    -

    virtual void Remove(UIView* view)

    -

    删除子组件

    -

    virtual void RemoveAll()

    -

    删除所有子组件

    -

    virtual void GetTargetView(const Point& point, UIView** last)

    -

    获取目标视图

    -

    virtual void MoveChildByOffset(int16_t x, int16_t y)

    -

    偏移子组件

    -

    UIView* GetChildrenHead() const

    -

    获取视图头节点

    -

    UIView* GetChildrenTail() const

    -

    获取视图最后那个节点

    -

    virtual UIView* GetChildById(const char* id) const override

    -

    通过id获取子视图

    -
    - -## 开发步骤 - -1. 构造button实例并设置坐标信息。 - - ``` - UILabelButton* btn1 = new UILabelButton(); - btn1->SetPosition(0, 0, 100, 50); - btn1->SetText("btn1"); - - UILabelButton* btn2 = new UILabelButton(); - btn2->SetPosition(50, 50, 100, 50); - btn2->SetText("btn2"); - - UILabelButton* btn3 = new UILabelButton(); - btn3->SetPosition(100, 100, 100, 50); - btn3->SetText("btn3"); - ``` - -2. 构造UIViewGroup实例,并设置坐标信息。 - - ``` - UIViewGroup* group = new UIViewGroup(); - group->SetPosition(0, 0, 300, 300); - ``` - -3. 使用Add方法添加Button实例到UIViewGroup。 - - ``` - group->Add(btn1); - group->Add(btn2); - group->Add(btn3); - ``` - -4. 检查ViewGroup效果如下图所示。 - - **图 3** ViewGroup添加view实例效果图 - ![](figures/ViewGroup添加view实例效果图.png "ViewGroup添加view实例效果图") - - -## UIScrollView - -## 使用场景 - -UIScrollView提供可滑动的容器类组件,子组件可在触摸事件驱动下上下、左右滑动,并提供水平和垂直方向的游标显示功能。 - -## 接口说明 - -**表 2** ScrollView接口说明 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    方法

    -

    功能

    -

    void ScrollBy(int16_t xDistance, int16_t yDistance)

    -

    移动视图

    -

    void SetScrollbarWidth(uint8_t width)

    -

    设置滑动条宽度

    -

    void SetHorizontalScrollState(bool state)

    -

    设置水平滑动状态

    -

    bool GetHorizontalScrollState() const

    -

    获取水平是否可滑动状态

    -

    void SetVerticalScrollState(bool state)

    -

    设置垂直滑动状态

    -

    bool GetVerticalScrollState() const

    -

    获取垂直是否可滑动状态

    -

    void SetXScrollBarVisible(bool state)

    -

    设置X轴滑动条是否可见

    -

    void SetYScrollBarVisible(bool state)

    -

    设置Y轴滑动条是否可见

    -

    void RegisterScrollListener(OnScrollListener* scrollListener)

    -

    注册滑动事件回调类

    -

    void RefreshScrollBar()

    -

    刷新滑动条

    -

    virtual void OnScrollStart() {}

    -

    滚动开始回调函数

    -

    virtual void OnScrollEnd() {}

    -

    滚动结束回调函数

    -

    uint8_t GetScrollState() const

    -

    获取滚动状态

    -

    void SetScrollState(uint8_t state)

    -

    设置滚动状态

    -
    - -## 开发步骤 - -添加两个button子组件,并显示水平、垂直方向游标。 - -``` -scrollView* scroll = new UIScrollView(); -scroll->SetStyle(STYLE_BACKGROUND_COLOR, Color::Red().full); -scroll->SetPosition(0,0, 200, 200); -scroll->SetXScrollBarVisible(true); -scroll->SetYScrollBarVisible(true); -UILabelButton* button1 = new UILabelButton(); -button1->SetText("button1"); -button1->SetPosition(0, 0, 300, 300); -UILabelButton* button2 = new UILabelButton(); -button2->SetText("button2"); -button2->SetPosition(0, 300, 300, 300); -scroll->Add(button1); -scroll->Add(button2); -``` - -**图 4** 水平、垂直方向可滑动效果图 -![](figures/水平-垂直方向可滑动效果图.gif "水平-垂直方向可滑动效果图") - diff --git "a/zh-cn/device-dev/subsystems/\345\270\203\345\261\200\345\256\271\345\231\250\347\261\273\347\273\204\344\273\266\345\274\200\345\217\221\346\214\207\345\257\274.md" "b/zh-cn/device-dev/subsystems/\345\270\203\345\261\200\345\256\271\345\231\250\347\261\273\347\273\204\344\273\266\345\274\200\345\217\221\346\214\207\345\257\274.md" deleted file mode 100755 index 4f8653aad5..0000000000 --- "a/zh-cn/device-dev/subsystems/\345\270\203\345\261\200\345\256\271\345\231\250\347\261\273\347\273\204\344\273\266\345\274\200\345\217\221\346\214\207\345\257\274.md" +++ /dev/null @@ -1,216 +0,0 @@ -# 布局容器类组件开发指导 - -- [UISwipeView](#section13631719181717) -- [使用场景](#section11299120102617) -- [接口说明](#section767434119261) -- [开发步骤(水平滑动,不可循环)](#section111911175287) -- [开发步骤(水平滑动,可循环)](#section1976914915282) -- [GridLayout](#section46819199173) -- [使用场景](#section831618247294) -- [接口说明](#section597214622912) -- [开发步骤](#section1418253410306) - -布局类容器组件由视图基础类组成,通过直接设置视图位置,可以达到嵌套和重叠布局的目的;通过设置布局类型和边距达到规格化布局子组件的目的;通过调用相关接口可实现根据父组件及兄弟节点布局视图的目的。 - -## UISwipeView - -## 使用场景 - -UISwipeView继承UIViewGroup,除提供容器类组件Add、Remove、Insert等方法外还提供按页面滑动功能,滑动结束后当前页面居中对齐显示。该组件分为水平方向和垂直方向,通过Add方法添加的子组件会根据Add的顺序和UISwipeView方向自动水平对齐或则垂直对齐。 - -## 接口说明 - -**表 1** SwipeView接口说明 - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    方法

    -

    功能

    -

    void SetCurrentPage(uint16_t index);

    -

    设置当前页

    -

    uint16_t GetCurrentPage()

    -

    获取当前页

    -

    UIView* GetCurrentView() const

    -

    获取当前页组件

    -

    void SetOnSwipeListener(OnSwipeListener& onSwipeListener)

    -

    设置滑动回调类

    -

    void SetAnimatorTime(uint16_t time);

    -

    设置动画事件

    -

    void SetLoopState(bool loop)

    -

    设置是否循环

    -

    UIView* GetViewByIndex(uint16_t index);

    -

    通过index获取view

    -
    - -## 开发步骤(水平滑动,不可循环) - -1. 创建一个水平滑动的UISwipeView。 - - ``` - UISwipeView* swipe = new UISwipeView(UISwipeView::HORIZONTAL); - ``` - -2. 向UISwipeView中添加子组件。 - - ``` - UILabelButton* button1 = new UILabelButton(); - button1->SetPosition(0, 0, g_ButtonW, g_ButtonH); - button1->SetText("button1"); - swipe->Add(button1); - UILabelButton* button2 = new UILabelButton(); - button2->SetPosition(0, 0, g_ButtonW, g_ButtonH); - button2->SetText("button2"); - swipe->Add(button2); - UILabelButton* button3 = new UILabelButton(); - button3->SetPosition(0, 0, g_ButtonW, g_ButtonH); - button3->SetText("button3"); - swipe->Add(button3); - ``` - -3. 检查实现效果,水平滑动,不可循环。 - - **图 1** UISwipeView水平滑动效果图 - - - ![](figures/zh-cn_image_0000001053247975.gif) - - -## 开发步骤(水平滑动,可循环) - -1. 创建一个水平滑动的UISwipeView并添加子组件。 - - ``` - UISwipeView* swipe = new UISwipeView(UISwipeView::HORIZONTAL); - UILabelButton* button1 = new UILabelButton(); - button1->SetPosition(0, 0, g_ButtonW, g_ButtonH); - button1->SetText("button1"); - swipe->Add(button1); - UILabelButton* button2 = new UILabelButton(); - button2->SetPosition(0, 0, g_ButtonW, g_ButtonH); - button2->SetText("button2"); - swipe->Add(button2); - UILabelButton* button3 = new UILabelButton(); - button3->SetPosition(0, 0, g_ButtonW, g_ButtonH); - button3->SetText("button3"); - swipe->Add(button3); - ``` - -2. 设置UISwipeView循环滑动。 - - ``` - swipe->SetLoopState(true); - ``` - -3. 检查实现效果,水平循环滑动。 - - **图 2** UISwipeView水平滑动循环效果图 - - - ![](figures/zh-cn_image_0000001053207924.gif) - - -## GridLayout - -## 使用场景 - -提供基础布局能力,可设置网格行数和列数,通过Add方法添加的子组件在调用LayoutChildren\(\)方法后自动进行排列布局。 - -## 接口说明 - -**表 2** GridLayout接口说明 - - - - - - - - - - - - - - - - -

    方法

    -

    功能

    -

    void SetRows(const uint16_t& rows)

    -

    设置行数

    -

    void SetCols(const uint16_t& cols)

    -

    设置列数

    -

    void LayoutChildren(bool needInvalidate = false)

    -

    布局子组件

    -
    - -## 开发步骤 - -1. 构造GridLayout并设置位置、大小信息。 - - ``` - GridLayout* layout_ = new GridLayout(); - layout_->SetPosition(0, g_y, HROIZONTAL_RESOLUTION, 200); - layout_->SetLayoutDirection(LAYOUT_HOR); - layout_->SetRows(2); - layout_->SetCols(2); - ``` - -2. 构造子组件button。 - - ``` - UILabelButton* bt1 = new UILabelButton(); - bt1->SetPosition(0,0,100,50); - bt1->SetText("bt1"); - UILabelButton* bt2 = new UILabelButton(); - bt2->SetPosition(0, 0, 100, 50); - bt2->SetText("bt2"); - UILabelButton* bt3 = new UILabelButton(); - bt3->SetPosition(0, 0, 100, 50); - bt3->SetText("bt3"); - UILabelButton* bt4 = new UILabelButton(); - bt4->SetPosition(0, 0, 100, 50); - bt4->SetText("bt4"); - ``` - -3. 添加子组件并调用LayoutChildren\(\)。 - - ``` - layout_->Add(bt1); - layout_->Add(bt2); - layout_->Add(bt3); - layout_->Add(bt4); - layout_->LayoutChildren(); - ``` - -4. 检查button组件布局效果如下图所示。 - - **图 3** 设置2\*2网格并添加4个button组件进行布局 - ![](figures/设置2-2网格并添加4个button组件进行布局.png "设置2-2网格并添加4个button组件进行布局") - - diff --git "a/zh-cn/device-dev/subsystems/\345\270\270\350\247\201\351\227\256\351\242\230.md" "b/zh-cn/device-dev/subsystems/\345\270\270\350\247\201\351\227\256\351\242\230.md" deleted file mode 100755 index c81824514a..0000000000 --- "a/zh-cn/device-dev/subsystems/\345\270\270\350\247\201\351\227\256\351\242\230.md" +++ /dev/null @@ -1,56 +0,0 @@ -# 常见问题 - -- [系统启动过程中打印“parse failed!”错误后停止启动](#section2041345718513) -- [系统启动过程未结束就自动重启,如此反复持续](#section57381816168) -- [参数正确的情况下调用SetParameter/GetParameter返回失败](#section129991227141512) - -## 系统启动过程中打印“parse failed!”错误后停止启动 - -**现象描述** - -系统启动过程中,打印“\[Init\] InitReadCfg, parse failed! please check file /etc/init.cfg format.”错误,启动过程停止,如下图所示: - -![](figures/zh-cn_image_0000001063839940.png) - -**可能原因** - -修改init.cfg文件时,漏掉或多加了逗号或括号等,导致init.cfg文件的json格式被破坏。 - -**解决办法** - -仔细检查init.cfg文件,确保其格式符合json格式要求。 - -## 系统启动过程未结束就自动重启,如此反复持续 - -**现象描述** - -镜像烧写完成后系统启动,启动过程未完成即自动重新启动,如此反复持续。 - -**可能原因** - -被init启动的服务都有一个叫做“importance”的属性(详见[第2章表3](init启动引导组件.md#table14737791471)描述)。 - -- 当该属性为0时,表示若当前服务进程退出,init不需要重启单板。 -- 当该属性为1时,表示若当前服务进程退出,init需要重启单板。 - -因此出现上述现象的可能原因:有“importance”属性为1的服务在每次启动的过程中都会退出(可能是进程崩溃或出错自动退出),导致init进程自动重启单板。 - -**解决办法** - -1. 需要通过日志确认崩溃或报错退出的服务,并解决其崩溃/报错的问题,然后重新烧写镜像即可。 -2. 也可以将崩溃/报错退出的服务的“importance”属性改为0,然后重新烧写镜像,这样即使其退出,init也不会重启单板。 - -## 参数正确的情况下调用SetParameter/GetParameter返回失败 - -**现象描述** - -在各参数正确的情况下调用SetParameter/GetParameter返回失败。 - -**可能原因** - -程序对SetParameter/GetParameter这两个接口做了权限校验,在各参数正确的情况下调用SetParameter/GetParameter返回操作失败,很有可能是调用者的uid大于1000,没有调用权限。 - -**解决办法** - -无需处理 - diff --git "a/zh-cn/device-dev/subsystems/\345\272\224\347\224\250\346\235\203\351\231\220\347\256\241\347\220\206\345\274\200\345\217\221\346\214\207\345\257\274.md" "b/zh-cn/device-dev/subsystems/\345\272\224\347\224\250\346\235\203\351\231\220\347\256\241\347\220\206\345\274\200\345\217\221\346\214\207\345\257\274.md" deleted file mode 100755 index 127a7f1756..0000000000 --- "a/zh-cn/device-dev/subsystems/\345\272\224\347\224\250\346\235\203\351\231\220\347\256\241\347\220\206\345\274\200\345\217\221\346\214\207\345\257\274.md" +++ /dev/null @@ -1,228 +0,0 @@ -# 应用权限管理开发指导 - -- [运作机制](#section193961322175011) -- [场景介绍](#section18502174174019) -- [接口说明](#section1633115419401) -- [开发步骤](#section022611498210) - -## 运作机制 - -由于OpenHarmony允许安装三方应用,所以需要对三方应用的敏感权限调用进行管控,具体实现是应用在开发阶段就需要在profile.json中指明此应用在运行过程中可能会调用哪些敏感权限,这些权限包括静态权限和动态权限,静态权限表示只需要在安装阶段注册就可以,而动态权限一般表示获取用户的敏感信息,所以需要在运行时让用户确认才可以调用,授权方式包括系统设置应用手动授权等。除了运行时对应用调用敏感权限进行管控外,还需要利用应用签名管控手段确保应用安装包已经被设备厂商进行了确认。 - -**表 1** OpenHarmony权限列表 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    OpenHarmony权限

    -

    授权方式

    -

    权限说明

    -

    ohos.permission.LISTEN_BUNDLE_CHANGE

    -

    system_grant(静态权限)

    -

    允许该应用获取应用变化消息。

    -

    ohos.permission.GET_BUNDLE_INFO

    -

    system_grant(静态权限)

    -

    允许该应用获取应用信息。

    -

    ohos.permission.INSTALL_BUNDLE

    -

    system_grant(静态权限)

    -

    允许该应用安装应用。

    -

    ohos.permission.CAMERA

    -

    user_grant(动态权限)

    -

    此应用可随时使用相机拍摄照片和录制视频。

    -

    ohos.permission.MODIFY_AUDIO_SETTINGS

    -

    system_grant(静态权限)

    -

    允许该应用修改全局音频设置,例如音量和用于输出的扬声器。

    -

    ohos.permission.READ_MEDIA

    -

    user_grant(动态权限)

    -

    允许该应用读取您的视频收藏。

    -

    ohos.permission.MICROPHONE

    -

    user_grant(动态权限)

    -

    此应用可随时使用麦克风进行录音。

    -

    ohos.permission.WRITE_MEDIA

    -

    user_grant(动态权限)

    -

    允许该应用写入您的音乐收藏。

    -

    ohos.permission.DISTRIBUTED_DATASYNC

    -

    user_grant(动态权限)

    -

    管控分布式数据传输能力。

    -

    ohos.permission.DISTRIBUTED_VIRTUALDEVICE

    -

    user_grant(动态权限)

    -

    允许应用使用分布式虚拟能力

    -
    - ->![](public_sys-resources/icon-note.gif) **说明:** ->静态权限:应用安装时由系统授予的权限,对应于权限敏感级别的system\_grant ->动态权限:应用在运行过程中需要用户授权的权限,对应于权限敏感级别的user\_grant - -## 场景介绍 - -应用权限是软件用来访问系统资源和使用系统能力的一种通行方式。在涉及用户隐私相关功能和数据的场景,例如:访问个人设备的硬件特性,如摄像头、麦克风,以及读写媒体文件等,OpenHarmony通过应用权限管理组件来保护这些数据以及能力。 - -在系统应用开发过程中,如果应用要使用敏感权限,开发者可以调用应用权限管理组件接口检查待访问权限是否被授权,如果未授权,操作不允许。 - -## 接口说明 - -应用权限管理提供的API接口,当前仅供系统应用和系统服务调用,具体API接口如下。 - -**表 2** 应用权限管理API接口功能介绍 - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    接口名

    -

    描述

    -

    int CheckPermission(int uid, const char *permissionName)

    -

    检查指定UID的应用进程是否具有访问系统服务API的权限

    -

    int CheckSelfPermission(const char *permissionName)

    -

    检查调用者是否具有访问系统服务API的权限

    -

    int QueryPermission(const char *identifier, PermissionSaved **permissions, int *permNum)

    -

    查询应用申请的所有权限,并检查权限是否被授予

    -

    int GrantPermission(const char *identifier, const char *permName)

    -

    将指定权限授予应用程序

    -

    int RevokePermission(const char *identifier, const char *permName)

    -

    收回应用程序的指定权限

    -

    int GrantRuntimePermission(int uid, const char *permissionName)

    -

    应用运行时动态授予指定权限

    -

    int RevokeRuntimePermission(int uid, const char *permissionName)

    -

    应用运行时动态撤销指定权限

    -
    - -## 开发步骤 - -本部分以包管理器的应用权限开发为例进行讲解。开发过程中,首先需要明确涉及的敏感权限,并在config.json中声明该权限,在安装应用程序时,包管理器会调用应用权限管理组件的接口检查该权限是否被授予,若授予,安装流程正常进行,否则安装失败。 - -1. 在开发过程中,包管理器明确需要安装应用的权限(ohos.permission.INSTALL\_BUNDLE),并在config.json中声明该权限; - - ``` - { - ... - "module": { - "package": "com.huawei.kitframework", - "deviceType": [ - "phone", "tv","tablet", "pc","car","smartWatch","sportsWatch","smartCamera", "smartVision" - ], - "reqPermissions": [{ - // 声明需要的权限:安装应用程序的权限名 - "name": "ohos.permission.INSTALL_BUNDLE", - "reason": "install bundle", - "usedScene": { - "ability": [ - "KitFramework" - ], - "when": "always" - } - }, - { - "name": "ohos.permission.LISTEN_BUNDLE_CHANGE", - "reason": "install bundle", - "usedScene": { - "ability": [ - "KitFramework" - ], - "when": "always" - } - }, - { - "name": "ohos.permission.GET_BUNDLE_INFO", - "reason": "install bundle", - "usedScene": { - "ability": [ - "KitFramework" - ], - "when": "always" - } - } - ], - ... - } - ``` - -2. 当包管理器开发应用安装功能接口时,会调用权限管理相关接口检查自身是否具有安装应用程序的权限,例如:以安装应用的权限名"ohos.permission.INSTALL\_BUNDLE"作为入参,调用CheckPermission接口检查包管理器是否具有安装应用的权限,如果有权限,安装流程继续执行,否则返回安装失败; - - ``` - constexpr static char PERMISSION_INSTALL_BUNDLE[] = "ohos.permission.INSTALL_BUNDLE"; - - bool Install(const char *hapPath, const InstallParam *installParam, InstallerCallback installerCallback) - { - if ((hapPath == nullptr) || (installerCallback == nullptr) || (installParam == nullptr)) { - HILOG_ERROR(HILOG_MODULE_APP, "BundleManager install failed due to nullptr parameters"); - return false; - } - // 检查ohos.permission.INSTALL_BUNDLE权限是否被授予 - if (CheckPermission(0, static_cast(PERMISSION_INSTALL_BUNDLE)) != GRANTED) { - HILOG_ERROR(HILOG_MODULE_APP, "BundleManager install failed due to permission denied"); - return false; // 返回安装失败 - } - // 安装流程 - ... - } - ``` - - diff --git "a/zh-cn/device-dev/subsystems/\345\272\224\347\224\250\351\252\214\347\255\276\345\274\200\345\217\221\346\214\207\345\257\274.md" "b/zh-cn/device-dev/subsystems/\345\272\224\347\224\250\351\252\214\347\255\276\345\274\200\345\217\221\346\214\207\345\257\274.md" deleted file mode 100755 index 8c5e78070f..0000000000 --- "a/zh-cn/device-dev/subsystems/\345\272\224\347\224\250\351\252\214\347\255\276\345\274\200\345\217\221\346\214\207\345\257\274.md" +++ /dev/null @@ -1,272 +0,0 @@ -# 应用验签开发指导 - -- [场景介绍](#section18502174174019) -- [验签流程](#section554632717226) -- [接口说明](#section1633115419401) -- [开发步骤(场景一)](#section4207112818418) - - [验签指导](#section11470123816297) - - [生成OpenHarmony自签名应用](#section167151429133312) - - [开发示例](#section174318361353) - -- [开发步骤(场景二)](#section81272563427) - - [验签指导](#section07028210442) - - [开发示例](#section1930711345445) - -- [调测验证](#section427316292411) - -## 场景介绍 - -当需要验证调试应用、发布应用,OpenHarmony自签名应用的完整性是否被破坏时,可以调用验签组件的接口进行验证。如有需要还可通过验签接口获取部分描述文件信息,如appid。对于调试应用,还可通过验签接口验证应用和设备的UDID是否匹配,确保应用安装在了正确的设备上。 - -## 验签流程 - -未经签名的Hap包的压缩方式是ZIP格式,简单分为文件块,中心目录(Central directory)块,中心目录结尾(EOCD,End of central directory record)块。 - -经过签名的Hap包,在文件块,和中心目录块之间,插入了签名块。签名块由文件签名数据块(data sign block)、描述文件签名数据块(profile sign block)和签名头(sign head)组成,如下图所示。 - -**图 1** 经过签名的Hap包结构 - - -![](figures/安全子系统.png) - -整个验签流程,主要分为三部分:整包验签、描述文件签名块验签,以及描述文件内容校验。 - -**整包验签** - -用设备的预置根证书,通过证书链来证明叶子证书本身是可信的,然后用叶子证书的公钥解密出的摘要证明整包是未篡改的。 - -具体操作步骤如下: - -1. 对文件签名数据块中的证书链进行校验,确定其叶子证书是可信的。 -2. 用叶子证书中的公钥对文件签名块进行验签,证明其未被篡改。 -3. 计算并合并文件块,中心目录块和中心目录结尾块的摘要。然后将计算结果,再与签名块中的描述文件签名块的摘要合并,将最终合并的摘要与文件签名块中包含的摘要对比,如果两者相等,则整包验签通过。 - -**描述文件签名块验签** - -首先判断文件签名的签发单位,如果是应用市场签发的发布应用,则无需对描述文件进行验签,直接信任,否则要对其验签。先取出整个描述文件签名块,然后验证证书链,最后用叶子证书对描述文件数据块验签,证明其未被篡改。 - -**描述文件内容校验** - -取出描述文件,并对其内容进行合法性检查。其中若hap包为调试应用,则会比对本机UDID与描述文件中包含的UDID列表,如果本机UDID在描述文件的UDID列表中包含,则验证通过。比较描述文件中包含的证书(如果是应用市场发布应用或OpenHarmony自签名则无需比较),和整包校验时使用的叶子证书,如果相同,认为整个验签流程完成。 - -## 接口说明 - -验签组件当前提供innerkits接口,仅供系统应用调用,相关接口及功能描述如下: - -**表 1** 验签组件API接口功能介绍 - - - - - - - - - - - - - - - - -

    接口名

    -

    描述

    -

    int APPVERI_AppVerify(const char *filePath, VerifyResult *verifyRst)

    -

    主入口函数,输入文件路径,进行验签,并将从描述文件中获取的数据通过verifyRst返回给调用者

    -

    int APPVERI_SetDebugMode(bool mode)

    -

    设置测试模式,设置mode为true,则支持基于测试根密钥的证书链校验,设置mode为false,则关闭基于测试根密钥的证书链校验。

    -

    注:当前没有基于现有测试根密钥的证书,开发者可根据自身需要,替换测试根密钥并进行相关验证。

    -

    void APPVERI_FreeVerifyRst(VerifyResult *verifyRst)

    -

    释放verifyRst中申请的内存

    -
    - -## 开发步骤(场景一) - -### 验签指导 - -对应用市场发布应用、基于应用市场调试证书签发的调试应用、OpenHarmony自签名应用的校验。 - -1. 定义出参结构体变量VerifyResult; - - ``` - VerifyResult verifyResult = {0}; - ``` - -2. 以文件路径及VerifyResult为入参,调用APPVERI\_AppVerify进行文件校验; - - ``` - int32_t ret = APPVERI_AppVerify(hapFilepath.c_str(), &verifyResult); - ``` - -3. 判断返回结果,如果校验通过的话,获取VerifyResult中的数据,进行业务处理; - - ``` - signatureInfo.appId = verifyResult.profile.appid; - signatureInfo.provisionBundleName = verifyResult.profile.bundleInfo.bundleName; - ``` - -4. 调用APPVERI\_FreeVerifyRst,释放VerifyResult中申请的内存。 - - ``` - APPVERI_FreeVerifyRst(&verifyResult); - ``` - - -### 生成OpenHarmony自签名应用 - -如果是OpenHarmony自签名应用的校验,开发者可通过以下方式生成OpenHarmony自签名应用。 - -1. 材料备齐。 - - 生成自签名应用需要的材料有:签名工具、系统应用hap包、系统应用profile文件\(\*.p7b\)、签名证书\(\*.cer\)、签名公私钥对\(\*.jks\)。 - -2. 将所有材料放在同一个目录下,打开shell。 -3. 根据应用、描述文件的实际名称修改指令,并在shell中输入,完成签名。 - - ``` - java -jar hapsigntoolv2.jar sign -mode localjks -privatekey "OpenHarmony Software Signature" -inputFile camera.hap -outputFile signed_camera.hap -signAlg SHA256withECDSA -keystore OpenHarmony.jks -keystorepasswd 123456 -keyaliaspasswd 123456 -profile camera_release.p7b -certpath OpenHarmony.cer -profileSigned 1 - ``` - - 关键字段说明: - - -jar:签名工具,[hapsigntool](https://repo.huaweicloud.com/harmonyos/develop_tools/hapsigntoolv2.jar) - - -mode:本地签名标记位,固定为localjks - - -privatekey:密钥对别名,签名公私钥对的别名为OpenHarmony Software Signature - - -inputFile:待签名应用,通过编译产生 - - -outputFile:签名后应用,最终输出 - - -signAlg:签名算法,当前固定为SHA256withECDSA - - -keystore:公私钥对,使用签名公私钥对,位于开源库security\_services\_app\_verify仓中OpenHarmonyCer目录下,[OpenHarmony.jks](https://gitee.com/openharmony/security_appverify/blob/master/interfaces/innerkits/appverify_lite/OpenHarmonyCer/OpenHarmony.jks)。默认密码为123456 ,用户可采用工具\(例如keytool\)更改默认密码 - - -keystorepasswd:公私钥对密码,默认签名公私钥对密码为123456 - - -keyaliaspasswd:公私钥对别名密码,默认签名公私钥对别名密码为123456 - - -profile:描述文件,应用的描述文件位于对应源代码目录中 - - -certpath:使用签名证书,位于开源库security\_services\_app\_verify仓中OpenHarmonyCer目录下,[OpenHarmony.cer](https://gitee.com/openharmony/security_appverify/blob/master/interfaces/innerkits/appverify_lite/OpenHarmonyCer/OpenHarmony.cer) - - -profileSigned:签名块中是否包含描述文件\(profile\)。固定为1(包含) - - -### 开发示例 - -以应用管理框架组件在应用安装时进行验签的实际调用为例: - -``` -uint8_t HapSignVerify::VerifySignature(const std::string &hapFilepath, SignatureInfo &signatureInfo) -{ - bool mode = ManagerService::GetInstance().IsDebugMode(); - HILOG_INFO(HILOG_MODULE_APP, "current mode is %d!", mode); - // 定义结果结构体 - VerifyResult verifyResult = {0}; - // 输入待验签文件路径进行验签 - int32_t ret = APPVERI_AppVerify(hapFilepath.c_str(), &verifyResult); - uint8_t errorCode = SwitchErrorCode(ret); - if (errorCode != ERR_OK) { - return errorCode; - } - // 从结果结构体中获取appid - signatureInfo.appId = verifyResult.profile.appid; - // 从结果结构体中获取描述文件中书写的应用名 - signatureInfo.provisionBundleName = verifyResult.profile.bundleInfo.bundleName; - int32_t restricNum = verifyResult.profile.permission.restricNum; - for (int32_t i = 0; i < restricNum; i++) { - signatureInfo.restrictedPermissions.emplace_back((verifyResult.profile.permission.restricPermission)[i]); - } - // 释放结果结构体中申请的内存 - APPVERI_FreeVerifyRst(&verifyResult); - return ERR_OK; -} -``` - -## 开发步骤(场景二) - -### 验签指导 - -对采用基于测试根密钥证书签名的应用的校验。 - -1. 调用APPVERI\_SetDebugMode\(true\)开启测试模式; - - ``` - ManagerService::SetDebugMode(true); - ... - uint8_t ManagerService::SetDebugMode(bool enable) - { - int32_t ret = APPVERI_SetDebugMode(enable); - if (ret < 0) { - HILOG_ERROR(HILOG_MODULE_APP, "set signature debug mode failed"); - return ERR_APPEXECFWK_SET_DEBUG_MODE_ERROR; - } - isDebugMode_ = enable; - HILOG_INFO(HILOG_MODULE_APP, "current sign debug mode is %d", isDebugMode_); - return ERR_OK; - } - ``` - -2. 同场景一中步骤一至四,定义结构体,校验、释放结构体; -3. 调用APPVERI\_SetDebugMode\(false\)关闭测试模式。 - - ``` - ManagerService::SetDebugMode(false); - ``` - - -### 开发示例 - -完整开发示例如下(在场景一代码示例的基础上进行补充): - -``` -uint8_t ManagerService::SetDebugMode(bool enable) -{ - int32_t ret = APPVERI_SetDebugMode(enable); - if (ret < 0) { - HILOG_ERROR(HILOG_MODULE_APP, "set signature debug mode failed"); - return ERR_APPEXECFWK_SET_DEBUG_MODE_ERROR; - } - isDebugMode_ = enable; - HILOG_INFO(HILOG_MODULE_APP, "current sign debug mode is %d", isDebugMode_); - return ERR_OK; -} -uint8_t HapSignVerify::VerifySignature(const std::string &hapFilepath, SignatureInfo &signatureInfo) -{ - // 开启支持测试服务器签名应用验证 - ManagerService::SetDebugMode(true); - bool mode = ManagerService::GetInstance().IsDebugMode(); - HILOG_INFO(HILOG_MODULE_APP, "current mode is %d!", mode); - // 定义结果结构体 - VerifyResult verifyResult = {0}; - // 输入待验签文件路径进行验签 - int32_t ret = APPVERI_AppVerify(hapFilepath.c_str(), &verifyResult); - uint8_t errorCode = SwitchErrorCode(ret); - if (errorCode != ERR_OK) { - return errorCode; - } - // 从结果结构体中获取appid - signatureInfo.appId = verifyResult.profile.appid; - // 从结果结构体中获取描述文件中书写的应用名 - signatureInfo.provisionBundleName = verifyResult.profile.bundleInfo.bundleName; - int32_t restricNum = verifyResult.profile.permission.restricNum; - for (int32_t i = 0; i < restricNum; i++) { - signatureInfo.restrictedPermissions.emplace_back((verifyResult.profile.permission.restricPermission)[i]); - } - // 释放结果结构体中申请的内存 - APPVERI_FreeVerifyRst(&verifyResult); - // 关闭支持测试服务器签名应用验证 - ManagerService::SetDebugMode(false); - return ERR_OK; -} -``` - -## 调测验证 - -1. 选取一个在OpenHarmony上能够正常安装的应用A。 -2. 根据开发指导开发。 -3. 对应用A,采用自开发程序进行验签,验签通过,能获取到appid。即为开发成功。 - diff --git "a/zh-cn/device-dev/subsystems/\345\274\200\345\217\221\345\256\236\344\276\213-6.md" "b/zh-cn/device-dev/subsystems/\345\274\200\345\217\221\345\256\236\344\276\213-6.md" deleted file mode 100755 index 39c2377cd4..0000000000 --- "a/zh-cn/device-dev/subsystems/\345\274\200\345\217\221\345\256\236\344\276\213-6.md" +++ /dev/null @@ -1,112 +0,0 @@ -# 开发实例 - -- [去电开发实例](#section286643718507) -- [来电开发实例](#section3205350105014) - -## 去电开发实例 - -去电的调用流程示例如下图所示: - -**图 1** 去电调用流程图 - - -![](figures/去电.png) - -当应用触发去电动作时,RIL Adapter会接收到拨打电话的请求,OnRequest\(\)会根据拨打电话请求ID调用拨打电话的接口。在该接口里会把电话服务传过来的数据封装为对应的AT指令发送到Modem,Modem执行完拨号命令后通过OnRequestResponse\(\)接口把响应结果上报给RIL Adapter。 - -``` -#include -#include -#include -#include -#include "atchannel.h" -#include "at_tok.h" -#include "hdf_log.h" -#include "ril.h" - -static void OnRequest(int request, void *data, size_t datalen, RIL_Token token) -{ - HDF_LOGI("OnRequest request = %{public}d start \n", request); - switch (request) { - case HREQ_CALL_DIAL: - SendDialRequest(data, datalen, token); - break; - …… - default: - break; - } -} - -// 将去电ID和参数转换成对应的AT命令,通过send_at_request发送给Modem -static void SendDialRequest(void *data, size_t datalen __unused, RIL_Token token) -{ - char *atCmd; - const char *clir; - int ret; - DialInfo *pDial; - pDial = (DialInfo *) data; - - if (!strncmp(pDial->address, "*31#", 4)) { - HDF_LOGI("clir suppression"); - clir = "i"; - num = (char *)&(pDial->address[4]); - } else if (!strncmp(pDial->address, "#31#", 4)) { - HDF_LOGI("clir invocation"); - clir = "I"; - num = (char *)&(pDial->address[4]); - } else { - HDF_LOGI("set clir state to default"); - clir = ""; - num = (char *)pDial->number; - } - - asprintf(&atCmd, "ATD%s%s;", pDial->address, clir); - ret = send_at_request(atCmd, NULL); - free(atCmd); - // 命令执行完成后调用该接口,将Modem执行的结果反馈给RIL Adapter - OnRequestResponse(t, RIL_RESULT_SUCCESS, NULL, 0); -} -``` - -## 来电开发实例 - -来电的调用流程示例如下图所示: - -**图 2** 来电调用流程图 - - -![](figures/来电.png) - -Modem设备节点读取线程s\_tid\_read会循环读取Modem上报的消息,当Modem接收到来电时会主动上报来电相关的信息; - -当该线程通过调用OnNotificationResponse\(\)解析到Modem上报的数据是以"+CRING"、"RING"等字符开头时,表示有来电事件,然后通过OnRadioEventNotify\(HNOTI\_CALL\_STATUS, NULL, 0\)上报给RIL Adapter完成来电事件上报。 - -``` -#include -#include "atchannel.h" -#include "at_tok.h" -#include "hdf_log.h" -#include "ril.h" - -bool IsCallStatusUpdated(const char *s) -{ - return (StrBeginWith(s, "+CRING:") - || StrBeginWith(s, "RING") - || StrBeginWith(s, "NO CARRIER") - || StrBeginWith(s, "+CCWA")); -} - -// 将Modem上报数据解析为对应的Modem事件 -static void OnNotificationResponse(const char *s, const char *sms_pdu) -{ - char *line = NULL, *p; - HDF_LOGI("OnNotificationResponse = %{public}s sState = %{public}d", s, sState); - // 解析到以"+CRING:"等字符开头的数据时,转换为来电事件 - if (IsCallStatusUpdated(s)) { - // 通知RIL Adapter有来电事件 - OnRadioEventNotify(HNOTI_CALL_STATUS, NULL, 0); - } - …… -} -``` - diff --git "a/zh-cn/device-dev/subsystems/\345\274\200\345\217\221\346\214\207\345\257\274-3.md" "b/zh-cn/device-dev/subsystems/\345\274\200\345\217\221\346\214\207\345\257\274-3.md" deleted file mode 100644 index 6a68dfe23f..0000000000 --- "a/zh-cn/device-dev/subsystems/\345\274\200\345\217\221\346\214\207\345\257\274-3.md" +++ /dev/null @@ -1,711 +0,0 @@ -# 开发指导 - -- [场景介绍](#section93012287133) -- [接口说明](#section11821047161319) -- [开发步骤](#section10514141679) - - [创建Service类型的Ability](#section19921154214315) - - [包管理接口使用指导](#section1724016743217) - - [Hap包打包](#section171771212328) - - -## 场景介绍 - -- 带界面的Ability的应用,比如:新闻类的应用、视频类的应用、导航类的应用、支付类的应用等等,目前我们看到的大部分应用都是带有界面的用于人机交互的应用。 - -- 不带界面的Ability应用,比如:音乐播放器能在后台播放音乐、后台提供计算服务、导航服务的各类应用等。 - -- 不管是带界面的Ability应用还是不带界面的Ability应用,都要打包成Hap包,最终发布到应用市场,用户通过应用市场下载安装相应的应用。 - -## 接口说明 - -**表 1** Ability子系统的对外接口 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    接口名称

    -

    接口描述

    -

    Want *WantParseUri(const char *uri)

    -

    反序列化接口,由字符串生成Want对象。

    -

    const char *WantToUri(Want want)

    -

    序列化,把Want对象生成字符串。

    -

    void SetWantElement(Want *want, ElementName element);

    -

    设置ElementName对象。

    -

    void SetWantData(Want *want, const void *data, uint16_t dataLength)

    -

    设置数据。

    -

    bool SetWantSvcIdentity(Want *want, SvcIdentity sid)

    -

    设置SvcIdentity。

    -

    void ClearWant(Want *want)

    -

    清除Want的内部内存数据。

    -

    void SetMainRoute(const std::string &entry)

    -

    设置AbilitySlice主路由。

    -

    void SetUIContent(RootView *rootView)

    -

    设置布局资源。

    -

    void OnStart(const Want& intent)

    -

    Ability生命周期状态回调,Ability启动时被回调。

    -

    void OnStop()

    -

    Ability生命周期状态回调,Ability销毁时被回调。

    -

    void OnActive(const Want& intent)

    -

    Ability生命周期状态回调,Ability显示时被回调。

    -

    void OnInactive()

    -

    Ability生命周期状态回调,Ability隐藏时被回调。

    -

    void OnBackground()

    -

    Ability生命周期状态回调,Ability退到后台时被回调。

    -

    const SvcIdentity *OnConnect(const Want &want)

    -

    Service类型Ability第一次连接时被回调。

    -

    void OnDisconnect(const Want &want);

    -

    Service类型Ability断开连接被回调。

    -

    void MsgHandle(uint32_t funcId, IpcIo *request, IpcIo *reply);

    -

    Service类型Ability接收消息处理。

    -

    void Dump(const std::string &extra)

    -

    dump Ability信息。

    -

    void Present(AbilitySlice *abilitySlice, const Want &want)

    -

    发起AbilitySlice跳转。

    -

    void Terminate()

    -

    退出当前AbilitySlice。

    -

    void SetUIContent(RootView *rootView)

    -

    设置当前AbilitySlice所在Ability的布局资源。

    -

    void OnStart(const Want& want)

    -

    AbilitySlice生命周期状态回调,AbilitySlice启动时被回调。

    -

    void OnStop()

    -

    AbilitySlice生命周期状态回调,AbilitySlice销毁时被回调。

    -

    void OnActive(const Want& want)

    -

    AbilitySlice生命周期状态回调,AbilitySlice显示时被回调。

    -

    void OnInactive()

    -

    AbilitySlice生命周期状态回调,AbilitySlice隐藏时被回调。

    -

    void OnBackground()

    -

    AbilitySlice生命周期状态回调,AbilitySlice退到后台时被回调。

    -

    int StartAbility(const Want &want)

    -

    启动Ability。

    -

    int StopAbility(const Want &want)

    -

    停止Service类型的Ability。

    -

    int TerminateAbility()

    -

    销毁当前的Ability。

    -

    int ConnectAbility(const Want &want, const IAbilityConnection &conn, void *data);

    -

    绑定Service类型的Ability。

    -

    int DisconnectAbility(const IAbilityConnection &conn)

    -

    解绑Service类型的Ability。

    -

    const char *GetBundleName()

    -

    获取当前ability的对应应用的包名。

    -

    const char *GetSrcPath()

    -

    获取当前ability的对应应用的安装路径。

    -

    const char *GetDataPath()

    -

    获取当前ability的对应应用的数据路径。

    -

    int StartAbility(const Want *want)

    -

    启动Ability,该接口可以不需要在基于Ability开发的应用中使用。

    -

    int ConnectAbility(const Want *want, const IAbilityConnection *conn, void *data);

    -

    绑定Service类型的Ability,该接口可以不需要在基于Ability开发的应用中使用。

    -

    int DisconnectAbility(const IAbilityConnection *conn);

    -

    解绑Service类型的Ability,该接口可以不需要在基于Ability开发的应用中使用。

    -

    int StopAbility(const Want *want)

    -

    停止Service类型的Ability,该接口可以不需要在基于Ability开发的应用中使用。

    -

    void (*OnAbilityConnectDone)(ElementName *elementName, SvcIdentity *serviceSid, int resultCode, void *data)

    -

    绑定Service Ability的回调。

    -

    void (*OnAbilityDisconnectDone)(ElementName *elementName, int resultCode, void *data)

    -

    解绑Service Ability的回调。

    -

    void PostTask(const Task& task)

    -

    投递任务到异步线程进行处理。

    -

    void PostQuit()

    -

    退出当前线程的消息循环。

    -

    static AbilityEventHandler* GetCurrentHandler()

    -

    获取当前线程的事件处理器。

    -

    void Run()

    -

    执行当前线程的消息循环。

    -

    #define REGISTER_AA(className)

    -

    注册开发者的Ability到框架中。

    -

    #define REGISTER_AS(className)

    -

    注册开发者的AbilitySlice到框架中。

    -
    - -## 开发步骤 - -### 创建Service类型的Ability - -1. 在my\_service\_ability.h中创建Ability的子类MyServiceAbility。 - - ``` - class MyServiceAbility: public Ability { - protected: - void OnStart(const Want& want); - const SvcIdentity *OnConnect(const Want &want) override; - void MsgHandle(uint32_t funcId, IpcIo *request, IpcIo *reply) override; - }; - ``` - -2. 调用REGISTER\_AA宏将ServiceAbility注册到应用框架中,以便应用框架实例化开发者的MyServiceAbility。 - - ``` - #include "my_service_ability.h" - - REGISTER_AA(ServiceAbility) - - void MyServiceAbility::OnStart(const Want& want) - { - printf("ServiceAbility::OnStart\n"); - Ability::OnStart(want); - } - - const SvcIdentity *MyServiceAbility::OnConnect(const Want &want) - { - printf("ServiceAbility::OnConnect\n"); - return Ability::OnConnect(want); - } - - void MyServiceAbility::MsgHandle(uint32_t funcId, IpcIo *request, IpcIo *reply) - { - printf("ServiceAbility::MsgHandle, funcId is %u\n", funcId); - int result = 0; - if (funcId == 0) { - result = IpcIoPopInt32(request) + IpcIoPopInt32(request); - } - // push data - IpcIoPushInt32(reply, result); - } - ``` - -3. 实现Service相关的生命周期方法。Service也是一种Ability,Ability为服务提供了以下生命周期方法,用户可以重写这些方法来添加自己的处理。用户在重写的方法里,需要调用父类对应的方法。 - - OnStart\(\) - - 该方法在创建Service的时候调用,用于做一些Service初始化且耗时较短的工作,在Service的整个生命周期只会调用一次。 - - ``` - void MyServiceAbility::OnStart(const Want& want) - { - printf("ServiceAbility::OnStart\n"); - Ability::OnStart(want); - } - ``` - - - OnConnect​\(\) - - 在组件和服务连接时调用,该方法返回SvcIdentity,组件可以通过它,与服务交互。 - - ``` - const SvcIdentity *MyServiceAbility::OnConnect(const Want &want) - { - printf("ServiceAbility::OnConnect\n"); - return Ability::OnConnect(want); - } - ``` - - - OnDisconnect​\(\) - - 在组件与绑定的Service断开连接时调用。 - - - OnStop\(\) - - 在Service销毁时调用。Service应通过实现此方法来清理任何资源,如关闭线程、注册的侦听器等。 - - -4. 重写消息处理方法。 - - MsgHandle是Service用来处理客户端消息的方法。其中funcId是客户端传过来的消息类型,request是客户端传过来的序列化请求参数。如果用户在处理完成之后想要把结果传回去,需要把结果序列化后写入reply中。 - - ``` - void ServiceAbility::MsgHandle(uint32_t funcId, IpcIo *request, IpcIo *reply) - { - printf("ServiceAbility::MsgHandle, funcId is %d\n", funcId); - int result = 0; - if (funcId == PLUS) { - result = IpcIoPopInt32(request) + IpcIoPopInt32(request); - } - // push data - IpcIoPushInt32(reply, result); - } - ``` - -5. 注册Service。 - - Service也需要在应用清单文件config.json中进行注册,注册类型type需要设置为service。 - - ``` - "abilities": [{ - "name": "ServiceAbility", - "icon": "res/drawable/phone.png", - "label": "test app 2", - "launchType": "standard", - "type": "service", - "visible": true - } - ] - ``` - -6. 启动Service。 - - Ability为用户提供了StartAbility\(\)方法来启动另外一个Ability,因为Service也是Ability的一种,开发者同样可以通过将Want传递给该方法来启动Service。 - - 开发者可以通过Want的SetWantElement \(\)来设置目标服务信息。ElementName结构体的两个主要参数:第一个参数为包名称;第二个参数为目标Ability。 - - ``` - { - Want want = { nullptr }; - ElementName element = { nullptr }; - SetElementBundleName(&element, "com.company.appname"); - SetElementAbilityName(&element, "ServiceAbility"); - SetWantElement(&want, element); - StartAbility(want); - ClearElement(&element); - ClearWant(&want); - } - ``` - - StartAbility\(\) 方法会立即执行,如果Service尚未运行,则系统首先会调用OnStart\(\)。 - - - 停止Service。 - - Service一旦创建就会一直保持在后台运行,开发者可以通过调用StopAbility\(\)来停止Service。 - - -7. 连接Service。 - - 如果Service需要与Page Ability或其他应用组件中的Service进行交互,则应创建用于连接的Service。Service支持其他Ability通过ConnectAbility\(\)与其进行连接,ConnectAbility\(\)需要传入目标Service的Want,以及IAbilityConnection的实例来处理回调。IAbilityConnection提供了两个方法供用户实现,OnAbilityConnectDone\(\)用来处理连接的回调,OnAbilityDisconnectDone\(\)用来处理断开连接的回调。 - - ``` - { - // ability创建IAbilityConnection对象和定义IAbilityConnection的两个方法实现 - IAbilityConnection abilityConnection = new IAbilityConnection(); - abilityConnection->OnAbilityConnectDone = OnAbilityConnectDone; - abilityConnection->OnAbilityDisconnectDone = OnAbilityDisconnectDone; - - void OnAbilityConnectDone(ElementName *elementName, SvcIdentity *serviceSid, - int resultCode, void *data) - { - if (resultCode != 0) { - return; - } - // push data - IpcIo request; - char dataBuffer[IPC_IO_DATA_MAX]; - IpcIoInit(&request, dataBuffer, IPC_IO_DATA_MAX, 0); - IpcIoPushInt32(&request, 10); - IpcIoPushInt32(&request, 6); - - // send and getReply - IpcIo reply; - uintptr_t ptr = 0; - if (Transact(nullptr, *serviceSid, 0, &request, &reply, - LITEIPC_FLAG_DEFAULT, &ptr) != LITEIPC_OK) { - printf("transact error\n"); - return; - } - int result = IpcIoPopInt32(&reply); - printf("execute add method, result is %d\n", result); - if (ptr != 0) { - FreeBuffer(nullptr, reinterpret_cast(ptr)); - } - } - - void OnAbilityDisconnectDone(ElementName *elementName, - int resultCode, void *data) - { - printf("elementName is %s, %s\n", - elementName->bundleName, elementName->abilityName); - } - } - ``` - - - 发起connect和disconnect。 - - ``` - { - // ability发起connect - Want want = { nullptr }; - ElementName element = { nullptr }; - SetElementBundleName(&element, "com.company.appname"); - SetElementAbilityName(&element, "ServiceAbility"); - SetWantElement(&want, element); - ConnectAbility(want, *abilityConnection, this); - - // ability发起disconnect - DisconnectAbility(*abilityConnection); - } - ``` - - - -### 包管理接口使用指导 - -**安装应用** - -安装接口只能给内置的系统应用使用。根据应用的安装路径,可以在安装应用时进行选择: - -- 将应用安装到系统默认的文件目录/storage/app/。 -- 将应用安装到系统外挂的存储介质中,例如micro sdcard。 - -这两种选择可以在创建InstallParam实例的时候指定,当InstallParam的成员变量installLocation为 INSTALL\_LOCATION\_INTERNAL\_ONLY时,意味着应用将会被安装到/storage/app/目录下;当InstallParam的成员变量installLocation为INSTALL\_LOCATION\_PREFER\_EXTERNAL时,意味着应用将被安装到存储介质,其安装目录是/sdcard/app/。由于安装应用的过程是异步的,所以需要使用类似信号量的机制来确保安装的回调可以被执行。 - -安装应用的步骤如下(示例代码以安装到系统目录为例): - -1. 将经过安全签名的应用放置于指定的目录下。 -2. 创建InstallParam实例和信号量。 - - ``` - InstallParam installParam = { - .installLocation = INSTALL_LOCATION_INTERNAL_ONLY, // 安装到系统目录 - .keepData = false - }; - static sem_t g_sem; - ``` - -3. 定义回调函数。 - - ``` - static void InstallCallback(const uint8_t resultCode, const void *resultMessage) - { - std::string strMessage = reinterpret_cast(resultMessage); - if (!strMessage.empty()) { - printf("install resultMessage is %s, %d\n", strMessage.c_str(),resultCode); - } - sem_post(&g_sem); - } - ``` - -4. 调用Install接口。 - - ``` - const uint32_t WAIT_TIMEOUT = 30; - sem_init(&g_sem, 0, 0); - std::string installPath = “/storage/bundle/demo.hap”; // hap包的存储路径 - bool result = Install(installPath.c_str(), &installParam, InstallCallback); - struct timespec ts = {}; - clock_gettime(CLOCK_REALTIME, &ts); - ts.tv_sec += WAIT_TIMEOUT; // 超时即释放信号量 - sem_timedwait(&g_sem, &ts); - ``` - - -**卸载应用** - -卸载应用的时候可以选择是否保留应用的数据,开发者可以通过创建的InstallParam实例的成员变量keepData来确定。当keepData为true, 卸载应用之后将保留应用的数据,当keepData为false时,卸载应用之后将不会保留应用的数据。 - -1. 创建InstallParam实例和信号量。 - - ``` - static sem_t g_sem; - InstallParam installParam = { - .installLocation = 1, - .keepData = false // 不保留应用数据 - }; - ``` - -2. 定义回调函数。 - - ``` - static void UninstallCallback(const uint8_t resultCode, const void *resultMessage) - { - std::string strMessage = reinterpret_cast(resultMessage); - if (!strMessage.empty()) { - printf("uninstall resultMessage is %s\n", strMessage.c_str()); - g_resultMessage = strMessage; - } - g_resultCode = resultCode; - sem_post(&g_sem); - } - ``` - -3. 调用Uninstall接口。 - - ``` - sem_init(&g_sem, 0, 0); - const uint32_t WAIT_TIMEOUT = 30; - std::string BUNDLE_NAME = “com.huawei.demo”; // 卸载应用的包名 - Uninstall(BUNDLE_NAME.c_str(), &installParam, UninstallCallback); - struct timespec ts = {}; - clock_gettime(CLOCK_REALTIME, &ts); - ts.tv_sec += WAIT_TIMEOUT; - sem_timedwait(&g_sem, &ts); - ``` - - -**查询已安装应用的包信息** - -开发者可以利用BundleManager提供的接口GetBundleInfo来查询系统内已安装应用的包信息。 - -1. 创建以及初始化BundleInfo。 - - ``` - BundleInfo bundleInfo; - (void) memset_s(&bundleInfo, sizeof(BundleInfo), 0, sizeof(BundleInfo)); - ``` - -2. 调用GetBundleInfo接口,指定查询应用的包名,同时指定flag来确定获取的BundleInfo中是否含有元能力信息(实例代码以含有元能力信息为例)。 - - ``` - std::string BUNDLE_NAME = "com.huawei.demo"; - uint8_t ret = GetBundleInfo(BUNDLE_NAME.c_str(), 1, &bundleInfo); // flags = 1,获取包信息中含有元能力信息 - ``` - -3. 使用完获取的BundleInfo之后,要及时清理掉其内部所占用的内存空间避免内存泄漏。 - - ``` - ClearBundleInfo(&bundleInfo); - ``` - - -### Hap包打包 - -打包工具一般集成到开发工具或者ide中,开发者一般不涉及直接使用该工具,下面的介绍开发者可以作为了解。打包工具的jar包在开源代码中的位置:developtools/packing\_tool/jar。 - -- 打包命令行参数 - - **表 2** 打包所需要的资源文件描述 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    命令参数

    -

    对应的资源文件

    -

    说明

    -

    是否可缺省

    -

    --mode

    -

    -

    -

    为“hap”字段,打包生成hap

    -

    -

    --json-path

    -

    清单文件config.json

    -

    -

    -

    -

    --resources-path

    -

    资源文件resources

    -

    -

    -

    -

    --assets-path

    -

    资源文件assets

    -

    -

    -

    -

    --lib-path

    -

    依赖库文件

    -

    -

    -

    -

    --shared-libs-path

    -

    共享库文件

    -

    针对系统应用的共享库,特殊情况下使用

    -

    -

    --ability-so-path

    -

    主功能so文件

    -

    -

    -

    -

    --index-path

    -

    资源索引

    -

    资源索引文件由资源生成工具生成,由资源流水线会集成该工具

    -

    -

    --out-path

    -

    -

    -

    生成的hap包输出路径,默认为当前目录

    -

    -

    --force

    -

    -

    -

    是否覆盖原有同名文件,默认为false

    -

    -
    - -- 打包示例 - - 开发视图 - - ![](figures/zh-cn_image_0000001062942690.png) - - - 编译视图 - - ![](figures/zh-cn_image_0000001062334618.png) - - - 使用打包工具执行以下命令打包: - - ![](figures/zh-cn_image_0000001062476933.png) - - ``` - $ java -jar hmos_app_packing_tool.jar --mode hap --json-path ./config.json --assets-path ./assets/ --ability-so-path ./libentry.so --index-path ./resources.index --out-path out/entry.hap --force true - ``` - - - diff --git "a/zh-cn/device-dev/subsystems/\345\274\200\345\217\221\346\214\207\345\257\274.md" "b/zh-cn/device-dev/subsystems/\345\274\200\345\217\221\346\214\207\345\257\274.md" deleted file mode 100755 index 4ef866ea11..0000000000 --- "a/zh-cn/device-dev/subsystems/\345\274\200\345\217\221\346\214\207\345\257\274.md" +++ /dev/null @@ -1,11 +0,0 @@ -# 开发指导 - -为实现AI 引擎框架的接入,开发者需开发上述[图1](AI引擎框架开发指南.md#fig143186187187)中的SDK模块和Plugin模块,通过调用sdk提供的接口,基于AI引擎框架实现调用plugin中算法的能力,从而实现AI能力的生命周期管理和按需部署功能。 - -- **[SDK开发过程](SDK开发过程.md)** - -- **[插件的开发过程](插件的开发过程.md)** - -- **[配置文件的开发过程](配置文件的开发过程.md)** - - diff --git "a/zh-cn/device-dev/subsystems/\345\274\200\345\217\221\347\244\272\344\276\213.md" "b/zh-cn/device-dev/subsystems/\345\274\200\345\217\221\347\244\272\344\276\213.md" deleted file mode 100755 index 346b8a084a..0000000000 --- "a/zh-cn/device-dev/subsystems/\345\274\200\345\217\221\347\244\272\344\276\213.md" +++ /dev/null @@ -1,13 +0,0 @@ -# 开发示例 - -以开发唤醒词识别为例,开发者可在Hi3516DV300开发板上,基于AI引擎框架开发唤醒词识别的sdk以及唤醒词识别的plugin,通过编译命令编出新的版本镜像并将其烧入版本。同时,开发者开发唤醒词识别的应用,该应用能够接收外部音频,将listen到的音频传入SDK中的接口,若音频中带有关键词,唤醒词识别的应用会识别出相应的词语,并打印在命令行中。 - -本示例中唤醒词识别的场景中唤醒词是固定的,当开发者传入的音频包含”Hi,小问“,启动的应用就会打印"\[Hi, xiaowen\]",当不包含时,会打印'\[UNKNOWN\]"。 - -- **[唤醒词识别SDK的开发示例](唤醒词识别SDK的开发示例.md)** - -- **[唤醒词识别插件的开发示例](唤醒词识别插件的开发示例.md)** - -- **[唤醒词识别配置文件的开发示例](唤醒词识别配置文件的开发示例.md)** - - diff --git "a/zh-cn/device-dev/subsystems/\346\212\200\346\234\257\350\247\204\350\214\203.md" "b/zh-cn/device-dev/subsystems/\346\212\200\346\234\257\350\247\204\350\214\203.md" deleted file mode 100755 index e2497a9e38..0000000000 --- "a/zh-cn/device-dev/subsystems/\346\212\200\346\234\257\350\247\204\350\214\203.md" +++ /dev/null @@ -1,15 +0,0 @@ -# 技术规范 - -**用词约定:** - -**规则:**必须准守的约定 - -**建议:**需要加以考虑的约定 - -- **[代码管理规范](代码管理规范.md)** - -- **[命名规范](命名规范.md)** - -- **[接口开发规范](接口开发规范.md)** - - diff --git "a/zh-cn/device-dev/subsystems/\346\213\215\347\205\247\345\274\200\345\217\221\346\214\207\345\257\274.md" "b/zh-cn/device-dev/subsystems/\346\213\215\347\205\247\345\274\200\345\217\221\346\214\207\345\257\274.md" deleted file mode 100755 index 2b37619913..0000000000 --- "a/zh-cn/device-dev/subsystems/\346\213\215\347\205\247\345\274\200\345\217\221\346\214\207\345\257\274.md" +++ /dev/null @@ -1,395 +0,0 @@ -# 拍照开发指导 - -- [使用场景](#section1963312376119) -- [接口说明](#section56549532016) -- [约束与限制](#section1165911177314) -- [开发步骤](#section138543918214) - -## 使用场景 - -使用Camera产生图片帧(拍照)。 - -## 接口说明 - -**表 1** API列表 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    类名

    -

    接口名

    -

    描述

    -

    CameraKit

    -

    int32_t GetCameraIds(std::list<string> cameraList)

    -

    获取cameraId列表

    -

    CameraKit

    -

    CameraAbility& GetCameraAbility(string cameraId)

    -

    获取指定camera的能力

    -

    CameraKit

    -

    void RegisterCameraDeviceCallback(CameraDeviceCallback* callback, EventHandler* handler)

    -

    注册camera设备状态回调

    -

    CameraKit

    -

    void UnregisterCameraDeviceCallback(CameraDeviceCallback* callback)

    -

    去注册camera设备状态回调

    -

    CameraKit

    -

    void CreateCamera(string cameraId, CameraStateCallback* callback, EventHandler* handler)

    -

    创建camera实例

    -

    Camera

    -

    string GetCameraId()

    -

    获取cameraID

    -

    Camera

    -

    CameraConfig& GetCameraConfig()

    -

    获取camera配置信息

    -

    Camera

    -

    FrameConfig& GetFrameConfig(int32_t type)

    -

    获取捕获帧类型

    -

    Camera

    -

    void Configure(CameraConfig& config)

    -

    配置camera

    -

    Camera

    -

    void Release()

    -

    释放camera

    -

    Camera

    -

    int TriggerLoopingCapture(FrameConfig& frameConfig)

    -

    开始循环帧捕获

    -

    Camera

    -

    void StopLoopingCapture()

    -

    停止循环帧捕获

    -

    Camera

    -

    int32_t TriggerSingleCapture(FrameConfig& frameConfig)

    -

    抓图

    -

    CameraConfig

    -

    void SetFrameStateCallback(FrameStateCallback* callback, EventHandler* handler);

    -

    设置帧状态回调

    -

    CameraConfig

    -

    static CameraConfig* CreateCameraConfig()

    -

    创建camera配置信息实例

    -

    CameraAbility

    -

    std::list<Size> GetSupportedSizes(int format)

    -

    根据类型获取支持输出图像尺寸大小

    -

    CameraAbility

    -

    std::list<T> GetParameterRange(uint32_t key)

    -

    获取支持的参数范围

    -

    CameraDevice

    -

    CameraDeviceCallback()

    -

    camera设备回调类构造函数

    -

    CameraDevice

    -

    void OnCameraStatus​(std::string cameraId, int32_t status)

    -

    camera设备状态变化时的回调

    -

    CameraStateCallback

    -

    CameraStateCallback​()

    -

    camera状态回调类构造函数

    -

    CameraStateCallback

    -

    void OnConfigured​(Camera& camera)

    -

    camera配置成功回调

    -

    CameraStateCallback

    -

    void OnConfigureFailed​(Camera& camera,int32_t errorCode)

    -

    camera配置失败回调

    -

    CameraStateCallback

    -

    void OnCreated​(Camera& camera)

    -

    camera创建成功回调

    -

    CameraStateCallback

    -

    void OnCreateFailed​(std::string cameraId,int32_t errorCode)

    -

    camera创建失败回调

    -

    CameraStateCallback

    -

    void OnReleased​(Camera& camera)

    -

    camera释放回调

    -

    FrameStateCallback

    -

    FrameStateCallback​()

    -

    帧状态回调类构造函数

    -

    FrameStateCallback

    -

    void OnFrameFinished(Camera& camera, FrameConfig& frameConfig, FrameResult& frameResult)

    -

    拍照帧完成回调

    -

    FrameStateCallback

    -

    void OnFrameError​(Camera& camera, FrameConfig& frameConfig, int32_t errorCode, FrameResult& frameResult)

    -

    拍照帧异常回调

    -

    FrameConfig

    -

    int32_t GetFrameConfigType()

    -

    获取帧配置类型

    -

    FrameConfig

    -

    std::list<OHOS::Surface> GetSurfaces()

    -

    获取帧配置的surface

    -

    FrameConfig

    -

    void AddSurface(OHOS::AGP::UISurface& surface);

    -

    添加surface

    -

    FrameConfig

    -

    void RemoveSurface(OHOS::AGP::UISurface& surface);

    -

    删除surface

    -
    - -## 约束与限制 - -无。 - -## 开发步骤 - -1. 实现设备状态回调的派生类,用户在设备状态发生变更(如新插入相机设备/相机掉线)时,自定义操作。 - - ``` - class SampleCameraDeviceCallback : public CameraDeviceCallback { - void OnCameraStatus(std::string cameraId, int32_t status) override - { - //do something when camera is available/unavailable - } - }; - ``` - -2. 实现帧事件回调的派生类,这里在拿到帧数据以后将其转存为文件。 - - ``` - static void SampleSaveCapture(const char *p, uint32_t size) - { - cout << "Start saving picture" << endl; - struct timeval tv; - gettimeofday(&tv, NULL); - struct tm *ltm = localtime(&tv.tv_sec); - if (ltm != nullptr) { - ostringstream ss("Capture_"); - ss << "Capture" << ltm->tm_hour << "-" << ltm->tm_min << "-" << ltm->tm_sec << ".jpg"; - - ofstream pic("/sdcard/" + ss.str(), ofstream::out | ofstream::trunc); - cout << "write " << size << " bytes" << endl; - pic.write(p, size); - cout << "Saving picture end" << endl; - } - } - - class TestFrameStateCallback : public FrameStateCallback { - void OnFrameFinished(Camera &camera, FrameConfig &fc, FrameResult &result) override - { - cout << "Receive frame complete inform." << endl; - if (fc.GetFrameConfigType() == FRAME_CONFIG_CAPTURE) { - cout << "Capture frame received." << endl; - list surfaceList = fc.GetSurfaces(); - for (Surface *surface : surfaceList) { - SurfaceBuffer *buffer = surface->AcquireBuffer(); - if (buffer != nullptr) { - char *virtAddr = static_cast(buffer->GetVirAddr()); - if (virtAddr != nullptr) { - SampleSaveCapture(virtAddr, buffer->GetSize()); - } - surface->ReleaseBuffer(buffer); - } - delete surface; - } - delete &fc; - } - } - }; - ``` - -3. 实现相机状态回调的派生类,当相机状态发生变化(配置成功/失败,创建成功/失败\)时,自定义操作。 - - ``` - class SampleCameraStateMng : public CameraStateCallback { - public: - SampleCameraStateMng() = delete; - SampleCameraStateMng(EventHandler &eventHdlr) : eventHdlr_(eventHdlr) {} - ~SampleCameraStateMng() - { - if (recordFd_ != -1) { - close(recordFd_); - } - } - void OnCreated(Camera &c) override - { - cout << "Sample recv OnCreate camera." << endl; - auto config = CameraConfig::CreateCameraConfig(); - config->SetFrameStateCallback(&fsCb_, &eventHdlr_); - c.Configure(*config); - cam_ = &c; - } - void OnCreateFailed(const std::string cameraId, int32_t errorCode) override {} - void OnReleased(Camera &c) override {} - }; - ``` - -4. 创建CameraKit,用于创建和获取camera信息。 - - ``` - CameraKit *camKit = CameraKit::GetInstance(); - list camList = camKit->GetCameraIds(); - string camId; - for (auto &cam : camList) { - cout << "camera name:" << cam << endl; - const CameraAbility *ability = camKit->GetCameraAbility(cam); - /* find camera which fits user's ability */ - list sizeList = ability->GetSupportedSizes(0); - if (find(sizeList.begin(), sizeList.end(), CAM_PIC_1080P) != sizeList.end()) { - camId = cam; - break; - } - } - ``` - -5. 创建Camera实例。 - - ``` - EventHandler eventHdlr; // Create a thread to handle callback events - SampleCameraStateMng CamStateMng(eventHdlr); - - camKit->CreateCamera(camId, CamStateMng, eventHdlr); - ``` - -6. 根据[步骤1](#li378084192111)、[步骤2](#li8716104682913)、[步骤3](#li6671035102514)中的回调设计,camera实例创建成功后会进行配置操作,主流程中app需要设计同步机制。 - - ``` - void OnCreated(Camera &c) override - { - cout << "Sample recv OnCreate camera." << endl; - auto config = CameraConfig::CreateCameraConfig(); - config->SetFrameStateCallback(&fsCb_, &eventHdlr_); - c.Configure(*config); - cam_ = &c; - } - - void Capture() - { - if (cam_ == nullptr) { - cout << "Camera is not ready." << endl; - return; - } - FrameConfig *fc = new FrameConfig(FRAME_CONFIG_CAPTURE); - Surface *surface = Surface::CreateSurface(); - if (surface == nullptr) { - delete fc; - } - surface->SetWidthAndHeight(1920, 1080); /* 1920:width,1080:height */ - fc->AddSurface(*surface); - cam_->TriggerSingleCapture(*fc); - } - ``` - - diff --git "a/zh-cn/device-dev/subsystems/\346\220\255\345\273\272\347\216\257\345\242\203-2.md" "b/zh-cn/device-dev/subsystems/\346\220\255\345\273\272\347\216\257\345\242\203-2.md" deleted file mode 100755 index 272f027942..0000000000 --- "a/zh-cn/device-dev/subsystems/\346\220\255\345\273\272\347\216\257\345\242\203-2.md" +++ /dev/null @@ -1,7 +0,0 @@ -# 搭建环境 - -- 开发板:Hi3516DV300 - -- [下载源码](../get-code/源码获取.md) -- [编译用户程序框架](https://gitee.com/openharmony/docs/blob/master/zh-cn/readme/%E7%94%A8%E6%88%B7%E7%A8%8B%E5%BA%8F%E6%A1%86%E6%9E%B6%E5%AD%90%E7%B3%BB%E7%BB%9F.md) - diff --git "a/zh-cn/device-dev/subsystems/\346\220\255\345\273\272\347\216\257\345\242\203.md" "b/zh-cn/device-dev/subsystems/\346\220\255\345\273\272\347\216\257\345\242\203.md" deleted file mode 100755 index 47fefd5333..0000000000 --- "a/zh-cn/device-dev/subsystems/\346\220\255\345\273\272\347\216\257\345\242\203.md" +++ /dev/null @@ -1,5 +0,0 @@ -# 搭建环境 - -1. 准备开发板:Hi3516DV300,Hi3518EV300 -2. [下载源码](https://device.harmonyos.com/cn/docs/start/get-code/oem_sourcecode_guide-0000001050769927#ZH-CN_TOPIC_0000001050769927__section1186691118430) - diff --git "a/zh-cn/device-dev/subsystems/\346\231\256\351\200\232\347\273\204\344\273\266\345\274\200\345\217\221\346\214\207\345\257\274.md" "b/zh-cn/device-dev/subsystems/\346\231\256\351\200\232\347\273\204\344\273\266\345\274\200\345\217\221\346\214\207\345\257\274.md" deleted file mode 100755 index 2c417f20a4..0000000000 --- "a/zh-cn/device-dev/subsystems/\346\231\256\351\200\232\347\273\204\344\273\266\345\274\200\345\217\221\346\214\207\345\257\274.md" +++ /dev/null @@ -1,555 +0,0 @@ -# 普通组件开发指导 - -- [UIButton](#section145353310214) -- [使用场景](#section1169616141577) -- [接口说明](#section341211538315) -- [开发步骤](#section22501726193214) -- [UIImageView](#section19523161611259) -- [使用场景](#section1274484210400) -- [接口说明](#section74981992411) -- [开发步骤(自适应)](#section144341333134114) -- [开发步骤(平铺模式)](#section97178160421) -- [UILabel](#section16588132012911) -- [使用场景](#section6870195634218) -- [接口说明](#section2012714510433) -- [开发步骤(默认模式)](#section83221538114410) -- [开发步骤(背景色和透明度)](#section933360204510) -- [开发步骤(字符间距)](#section19447826124518) -- [开发步骤(大小自适应)](#section101711842154617) -- [开发步骤(省略号模式)](#section1249519410471) -- [开发步骤(滚动模式)](#section15643122618478) - -普通组件均继承于基类UIView,不可以添加子组件,常用的普通组件有button、image、label等。 - -**图 1** 普通组件树结构 -![](figures/普通组件树结构.png "普通组件树结构") - -UIView为基础类,UIAbstractProgress、UIArcLabel(旋转字体)、UIButton(按键)、UICanvas(画布)、UILabel(字体)、UIImageView(图片)从UIView继承。UIBoxProgress、UICircleProgress从UIAbstractProgress继承,UILabelButton和UIRepeatButton从UIButton继承,UIImageAnimatorView和UITextureMapper从UIImageView继承。 - -## UIButton - -## 使用场景 - -UIButton组件,提供可点击功能,同时可设置不同状态下样式。 - -## 接口说明 - -**表 1** button接口说明 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    方法

    -

    功能

    -

    void SetImageSrc (const char *defaultImgSrc, const char *triggeredImgSrc)

    -

    设置button图片

    -

    void SetImagePosition (const int16_t x, const int16_t y)

    -

    设置button图片位置

    -

    int16_t GetImageX () const

    -

    获取图片X坐标

    -

    int16_t GetImageY () const

    -

    获取图片Y坐标

    -

    const ImageInfo* GetCurImageSrc() const

    -

    获取当前状态图片

    -

    Style& GetStyleForState (ButtonState state)

    -

    设置button当前状态的style

    -

    voidSetStyleForState (const Style &style, ButtonState state)

    -

    设置button指定状态的style

    -

    void Disable ()

    -

    去使能button

    -

    void Enable ()

    -

    使能button

    -
    - -## 开发步骤 - -1. 实现点击事件。 - - ``` - class TestBtnOnClickListener : public OHOS::UIView::OnClickListener { - bool OnClick(UIView& view, const ClickEvent& event) override - { - int16_t width = view.GetWidth() + 10; - int16_t height = view.GetHeight() + 10; - view.Resize(width, height); - view.Invalidate(); - return true; - } - }; - ``` - -2. 创建一个UIButton。 - - ``` - UIButton* button = new UIButton(); - button->SetPosition(50, 50); - button->SetWidth(100); - button->SetHeight(50); - ``` - -3. 给UIButton注册点击事件回调。 - - ``` - button->SetOnClickListener(new TestBtnOnClickListener()); - ``` - -4. 检查Button点击效果如下图所示,Button逐渐变大。 - - **图 2** UIButton点击效果 - ![](figures/UIButton点击效果.gif "UIButton点击效果") - - -## UIImageView - -## 使用场景 - -图片组件,提供图片显示,透明度设置,图片旋转、缩放功能。支持的图片格式为RGB565、RGB888、RGBA8888、PNG、JPG。 - -## 接口说明 - -**表 2** image接口说明 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    方法

    -

    功能

    -

    void SetSrc (const char *src)

    -

    设置二进制图片路径

    -

    void SetSrc (const ImageInfo *src)

    -

    设置图片指针

    -

    void SetAutoEnable (bool enable)

    -

    设置组件大小跟随image大小变化

    -

    const void* GetSrcType () const

    -

    获取图片类型

    -

    bool GetAutoEnable () const

    -

    获取组件大小是否跟随image大小变化

    -

    void SetBlurLevel(BlurLevel level)

    -

    设置模糊等级

    -

    BlurLevel GetBlurLevel() const

    -

    获取模糊等级

    -

    void SetTransformAlgorithm(TransformAlgorithm algorithm)

    -

    设置旋转算法

    -

    TransformAlgorithm GetTransformAlgorithm() const

    -

    获取旋转算法

    -
    - -## 开发步骤(自适应) - -1. 创建一个UIImageView。 - - ``` - UIImageView* imageView = new UIImageView(); - imageView->SetPosition(0, 30); - ``` - -2. 设置二进制格式的图片。 - - ``` - imageView->SetSrc("..\\config\\images\\A021_001.bin"); - ``` - -3. 检查UIImageView控件大小与图片相同。 - - **图 3** 自适应模式图片效果图 - ![](figures/自适应模式图片效果图.png "自适应模式图片效果图") - - -## 开发步骤(平铺模式) - -1. 创建一个UIImageView。 - - ``` - UIImageView* imageView = new UIImageView(); - imageView->SetPosition(0, 30); - ``` - -2. 设置图片。 - - ``` - imageView->SetSrc("..\\config\\images\\A021_001.bin"); - ``` - -3. 取消图片自适应,设置图片大小,平铺显示效果。 - - ``` - imageView->SetAutoEnable(false); - imageView->Resize(454, 150); - ``` - -4. 检查UIImageView控件显示为平铺效果。 - - **图 4** 平铺模式图片效果图 - ![](figures/平铺模式图片效果图.png "平铺模式图片效果图") - - -## UILabel - -## 使用场景 - -标签(label)是在一块区域上显示文本字符串的组件,可设置区域背景色、文字的显示样式和长文本的显示效果等。 - -## 接口说明 - -**表 3** label接口说明 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    方法

    -

    功能

    -

    void SetText(const char* text);

    -

    设置文字

    -

    const char* GetText() const;

    -

    获取text

    -

    void SetLineBreakMode(const uint8_t lineBreakMode);

    -

    设置label模式,例如截断,自动扩展等。

    -

    uint8_t GetLineBreakMode() const

    -

    获取label模式

    -

    void SetTextColor(ColorType color)

    -

    设置文本颜色

    -

    ColorType GetTextColor() const

    -

    获取文本颜色

    -

    void SetAlign(UITextLanguageAlignment horizontalAlign,

    -

    UITextLanguageAlignment verticalAlign = TEXT_ALIGNMENT_TOP);

    -

    设置文本对齐方式

    -

    UITextLanguageAlignment GetHorAlign() const

    -

    获取文本水平对齐方式

    -

    UITextLanguageAlignment GetVerAlign() const

    -

    获取文本竖直对齐方式

    -

    void SetDirect(UITextLanguageDirect direct)

    -

    设置文本显示方向

    -

    UITextLanguageDirect GetDirect() const

    -

    获取文本显示方向

    -

    void SetFontId(uint8_t fontId);

    -

    设置动态字体id

    -

    uint8_t GetFontId() const

    -

    获取动态字体id

    -

    void SetFont(const char *name, uint8_t size);

    -

    设置字的名字和大小

    -

    void SetAnimatorSpeed(uint16_t animSpeed);

    -

    设置字体旋转的速度

    -

    uint16_t GetTextWidth();

    -

    获取字体的宽

    -

    uint16_t GetTextHeight();

    -

    获取字体的高

    -

    void SetRollStartPos(int16_t pos)

    -

    设置旋转的位置

    -

    int16_t GetRollStartPos() const

    -

    获取旋转的位置

    -

    void SetTextRotation(LabelRotateDegree angle)

    -

    设置文本旋转角度枚举值

    -

    LabelRotateDegree GetTextRotation() const

    -

    获取文本旋转角度枚举值

    -

    uint16_t GetTextRotateDegree() const

    -

    获取文本旋转角度数值

    -
    - -## 开发步骤(默认模式) - -1. 创建label,设置大小和位置信息。 - - ``` - UILabel* label = new UILabel(); - label->SetPosition(x, y); - label->Resize(width, height); - ``` - -2. 设置字形信息。 - - ``` - label->SetFont("SourceHanSansSC-Regular.otf", 30); - ``` - -3. 设置文本数据。 - - ``` - label->SetText("label"); - ``` - -4. 检查label大小和显示效果正常,如下图所示。 - - ![](figures/zh-cn_image_0000001051782526.png) - - -## 开发步骤(背景色和透明度) - -1. 创建label,设置大小和位置信息。 - - ``` - UILabel* label = new UILabel(); - label->SetPosition(x, y); - label->Resize(width, height); - ``` - -2. 设置字形信息。 - - ``` - label->SetFont("SourceHanSansSC-Regular.otf", 30); - ``` - -3. 设置背景颜色及透明度效果。 - - ``` - label->SetStyle(STYLE_BACKGROUND_COLOR, Color::Gray().full); - label->SetStyle(STYLE_BACKGROUND_OPA, 127); - label->SetText("Label"); - ``` - -4. 检查label背景色为Gray,如下图所示。 - - ![](figures/zh-cn_image_0000001052582522.png) - - -## 开发步骤(字符间距) - -1. 创建label,设置大小和位置信息。 - - ``` - UILabel* label = new UILabel(); - label->SetPosition(x, y); - label->Resize(width, height); - ``` - -2. 设置字形信息。 - - ``` - label->SetFont("SourceHanSansSC-Regular.otf", 30); - ``` - -3. 设置字体颜色和字间距效果。 - - ``` - label->SetStyle(STYLE_BACKGROUND_COLOR, Color::Gray().full); - label->SetStyle(STYLE_LETTER_SPACE, 5); - label->SetText("Label"); - ``` - -4. 检查label字符间距为5,如下图所示。 - - ![](figures/zh-cn_image_0000001052942531.png) - - -## 开发步骤(大小自适应) - -当文本过长时,可根据文本信息自动调整label组件大小,也可以设置文本截断或者文本滚动效果。 - -1. 创建label,设置大小和位置信息。 - - ``` - UILabel* label = new UILabel(); - label->SetPosition(x, y); - label->Resize(width, height); - ``` - -2. 设置字形信息。 - - ``` - label->SetFont("SourceHanSansSC-Regular.otf", 30); - ``` - -3. 设置字体颜色为Gray,组件大小自适应文本内容。 - - ``` - label->SetStyle(STYLE_BACKGROUND_COLOR, Color::Gray().full); - label->SetLineBreakMode(UILabel::LINE_BREAK_ADAPT); - label->SetText("123\n567890"); - ``` - -4. 检查label大小自适应文本内容,如下图所示。 - - ![](figures/zh-cn_image_0000001052782555.png) - - -## 开发步骤(省略号模式) - -省略号模式指文本内容显示不下时,在末尾显示省略号。 - -1. 创建label,设置大小和位置信息。 - - ``` - UILabel* label = new UILabel(); - label->SetPosition(x, y); - label->Resize(width, height); - ``` - -2. 设置字形信息。 - - ``` - label->SetFont("SourceHanSansSC-Regular.otf", 30); - ``` - -3. 设置换行模式为DOT模式 - - ``` - label->SetStyle(STYLE_BACKGROUND_COLOR, Color::Gray().full); - label->SetLineBreakMode(UILabel::LINE_BREAK_ELLIPSIS); - label->SetText("123567890"); - ``` - -4. 检查label DOT模式效果,如下图所示,末尾显示省略号。 - - ![](figures/zh-cn_image_0000001052662559.png) - - -## 开发步骤(滚动模式) - -文本滚动显示。 - -1. 创建label,设置大小和位置信息。 - - ``` - UILabel* label = new UILabel(); - label->SetPosition(x, y); - label->Resize(width, height); - ``` - -2. 设置字形信息。 - - ``` - label->SetFont("SourceHanSansSC-Regular.otf", 30); - ``` - -3. 设置换行模式为滚动模式 - - ``` - label->SetStyle(STYLE_BACKGROUND_COLOR, Color::Gray().full); - label->SetStyle(STYLE_BACKGROUND_OPA, 127); - label->SetLineBreakMode(UILabel::LINE_BREAK_MARQUEE); - label->SetText("123567890"); - ``` - -4. 检查label滚动模式效果,如下图所示。 - - ![](figures/20200721-223604(eSpace).gif) - - diff --git "a/zh-cn/device-dev/subsystems/\346\240\207\345\207\206\347\263\273\347\273\237\347\274\226\350\257\221\346\236\204\345\273\272\346\214\207\345\257\274.md" "b/zh-cn/device-dev/subsystems/\346\240\207\345\207\206\347\263\273\347\273\237\347\274\226\350\257\221\346\236\204\345\273\272\346\214\207\345\257\274.md" deleted file mode 100644 index 6c6cf03332..0000000000 --- "a/zh-cn/device-dev/subsystems/\346\240\207\345\207\206\347\263\273\347\273\237\347\274\226\350\257\221\346\236\204\345\273\272\346\214\207\345\257\274.md" +++ /dev/null @@ -1,7 +0,0 @@ -# 标准系统编译构建指导 - -- **[编译构建概述](编译构建概述-0.md)** - -- **[编译构建使用指导](编译构建使用指导-1.md)** - - diff --git "a/zh-cn/device-dev/subsystems/\346\246\202\350\277\260-7.md" "b/zh-cn/device-dev/subsystems/\346\246\202\350\277\260-7.md" deleted file mode 100644 index 45d0d32676..0000000000 --- "a/zh-cn/device-dev/subsystems/\346\246\202\350\277\260-7.md" +++ /dev/null @@ -1,76 +0,0 @@ -# 概述 - -- [基本概念](#section175012297491) -- [约束与限制](#section2029921310472) - -OpenHarmony安全子系统目前提供给开发者的安全能力主要包含应用可信、权限管理、设备可信。涉及以下几个模块: - -- 应用验签 - - 为了确保应用内容的完整性,系统通过应用签名和Profile对应用的来源进行管控,同时对于调试应用,还可通过验签接口验证应用和设备的UDID是否匹配,确保应用安装在了正确的设备上。 - -- 应用权限管理 - - 应用权限是管理应用访问系统资源和使用系统能力的一种通用方式,应用在开发阶段需要在profile.json中指明此应用在运行过程中可能会调用哪些权限,其中静态权限表示只需要在安装阶段注册就可以,而动态权限一般表示涉及到敏感信息,所以需要用户进行动态授权。 - -- IPC通信鉴权 - - 系统服务通过IPC暴露接口给其他进程访问,这些接口需要配置相应的访问策略,当其他进程访问这些接口时,将会触发IPC通信鉴权机制校验访问进程是否拥有权限访问该接口,若无权限,则拒绝访问该接口。 - -- 可信设备群组管理 - - 提供基于群组概念的同华为账号群组、点对点群组(如二维码、碰一碰等)的设备安全可信关系的创建和查询,分布式应用可基于该能力进行设备间的可信认证,然后向分布式软总线请求设备间安全会话。 - - -## 基本概念 - -在进行依赖验签组件的应用开发前,开发者应了解以下基本概念: - -- Samgr - - Samgr\(System Ability M2anager\)系统能力管理,在OpenHarmony上作为一个管理系统能力的模块,详见系统服务框架子系统。 - - -- BMS - - BMS\(Bundle Manager Service\)包管理管理,在OpenHarmony上主要负责应用的安装、卸载和数据管理。 - - -- 描述文件 - - 本文中的描述文件,指HarmonyAppProvision,简称profile。HarmonyAppProvision采用json文件格式进行描述。 - - -- 叶子证书 - - 最终用于为整包或profile签名的证书称为叶子证书,位于数字证书链的最末端。 - - -- 调试应用 - - 指开发者从应用市场申请调试证书与调试描述文件,并以此签名的hap包。 - - -- 待上架应用 - - 指开发者从应用市场申请发布证书与发布描述文件,以此签名,未通过应用市场正式发布的hap包。 - - -- 发布应用 - - 指开发者从应用市场申请发布证书与发布描述文件,以此签名的hap包,上传至应用市场,并由应用市场正式发布的hap包。 - - -- OpenHarmony自签名应用 - - 当开发者自行编译OpenHarmony系统应用后,采用原应用描述文件,以及公开的OpenHarmony公私钥对和证书进行自签名产生的hap包。 - - -## 约束与限制 - -- 仅支持以下三类应用的验签:应用市场调试应用、应用市场发布应用、OpenHarmony自签名应用的验签。 -- 若对应用市场调试应用验签,则本机UDID需要在描述文件包含的UDID列表中。 -- 待上架应用无法验签通过。 -- 验签组件提供的接口都位于security\_interfaces\_innerkits\_app\_verify仓[app\_verify\_pub.h](https://gitee.com/fork_ohos_wj/security_interfaces_innerkits_app_verify/blob/master/app_verify_pub.h)中,仅支持系统应用开发者调用。 -- 可信设备群组管理接口,目前只对系统签名权限才可以使用。 - diff --git "a/zh-cn/device-dev/subsystems/\346\246\202\350\277\260.md" "b/zh-cn/device-dev/subsystems/\346\246\202\350\277\260.md" deleted file mode 100755 index 63ee16f94c..0000000000 --- "a/zh-cn/device-dev/subsystems/\346\246\202\350\277\260.md" +++ /dev/null @@ -1,141 +0,0 @@ -# 概述 - -- [基本概念](#section72601941194812) -- [Ability子系统](#section14633111813374) -- [包管理子系统](#section1341146154412) -- [运作机制](#section94302021112717) -- [约束与限制](#section89534912527) - -用户程序框架是OpenHarmony为开发者提供开发OpenHarmony应用的开发框架,包含两个模块:Ability子系统和包管理子系统。 - -## 基本概念 - -开发者在开发前需要先了解以下基本概念,方便开发者更好的理解OpenHarmony用户程序框架。 - -## Ability子系统 - -Ability子系统是管理OpenHarmony应用运行状态的开发框架。 - -**图 1** Ability子系统框架图 -![](figures/Ability子系统框架图.png "Ability子系统框架图") - -- **Ability**:系统调度应用的最小单元,是能够完成一个独立功能的组件,一个应用可以包含一个或多个Ability。Ability分为两种类型:Page类型的Ability和Service类型的Ability。 - - **Page类型的Ability**:带有界面,为用户提供人机交互的能力。 - - - **Service类型的Ability**:不带界面,为用户提供后台任务机制。 - - - -- **AbilitySlice**:单个页面及其控制逻辑的总和,是Page类型Ability特有的组件,一个Page类型的Ability可以包含多个AbilitySlice,此时,这些页面提供的业务能力应当是高度相关的。 - - **图 2** Ability与AbilitySlice的关系图 - ![](figures/Ability与AbilitySlice的关系图.png "Ability与AbilitySlice的关系图") - -- **生命周期**:Ability被调度到启动、激活、隐藏和退出等各个状态的统称。 - - **图 3** Ability生命周期流转 - - - ![](figures/图片1.png) - - - **OnStart\(\)** - - 系统首次创建Page实例时触发该回调。对于一个Page实例,该回调在其生命周期过程中仅触发一次,Page在该逻辑后进入INACTIVE状态。开发者必须重写该方法,并在此配置默认展示的AbilitySlice。 - - - **OnActive\(\)** - - Page会在进入INACTIVE状态后来到前台,然后系统调用此回调。Page在此之后进入ACTIVE状态,该状态是应用与用户交互的状态。Page将保持在此状态,除非某类事件发生导致Page失去焦点,比如用户点击返回键或导航到其他Page。 - - 当此类事件发生时,会触发Page回到INACTIVE状态,系统将调用OnInactive\(\)回调。此后,Page可能重新回到ACTIVE状态,系统将再次调用OnActive\(\)回调。因此,开发者通常需要成对实现OnActive\(\)和OnInactive\(\),并在OnActive\(\)中获取在OnInactive\(\)中被释放的资源。 - - - **OnInactive\(\)** - - 当Page失去焦点时,系统将调用此回调,此后Page进入INACTIVE状态。开发者可以在此回调中实现Page失去焦点时应表现的恰当行为。 - - - **OnBackground\(\)** - - 如果Page不再对用户可见,系统将可能根据资源状况调用此回调,此后Page进入BACKGROUND状态。开发者应该在此回调中释放Page不可见时无用的资源,或在此回调中执行较为耗时的状态保存操作。 - - - **OnForeground\(\)** - - 处于BACKGROUND状态的Page仍然驻留在内存中,当重新回到前台时(比如用户重新导航到此Page),系统将先调用OnForeground\(\)回调使Page回到INACTIVE状态,然后调用OnActive\(\)回调使Page回到ACTIVE状态。开发者应当在此回调中重新申请在OnBackground\(\)中释放的资源。轻量化设备目前不支持该接口。 - - - **OnStop\(\)** - - 此回调表示系统正在销毁Page。销毁Page的可能原因包括: - - - 用户通过系统管理能力显式关闭Page,例如使用任务管理器关闭Page。 - - 用户行为触发Page的TerminateAbility\(\)方法调用,例如使用应用的退出功能。 - - 配置变更导致系统暂时销毁Page并重建。 - - 系统出于资源管理目的,自动触发对处于BACKGROUND状态Page的销毁。 - - -- **AbilityKit**:Ability框架提供给开发者的开发包,开发者基于该开发包可以开发出基于Ability组件的应用。基于Ability组件开发的应用有两种类型:基于Javascript语言开发的Ability(JS Ability)和基于C/C++语言开发的Ability(Native Ability)。JS应用开发框架是开发者开发JS Ability所用到框架,是在AbilityKit基础封装的包含js UI组件的一套方便开发者能够迅速开发Ability应用的框架。 -- **AbilityLoader**:负责注册和加载开发者Ability的模块。开发者开发的Ability先要调用AbilityLoader的注册接口注册到框架中,接着Ability启动时会被实例化。 - -- **AbilityManager**:负责AbilityKit和Ability管理服务进行IPC的通信。 - -- **EventHandler**:AbilityKit提供给开发者的用于在Ability中实现线程间通信的一个模块。 - -- **AbilityManagerService**:元能力运行管理服务。该服务用于协调各Ability运行关系、及生命周期进行调度的系统服务。其中,服务启动模块负责Ability管理服务的启动、注册等。服务接口管理模块负责Ability管理服务对外能力的管理。进程管理模块负责Ability应用所在进程的启动和销毁、及其进程信息维护等功能。Ability栈管理模块负责维护各个Ability之间跳转的先后关系。生命周期调度模块是Ability管理服务根据系统当前的操作调度Ability进入相应的状态的模块。连接管理模块是Ability管理服务对Service类型Ability连接管理的模块 - -- **AppSpawn**:负责创建Ability应用所在进程的系统服务,该服务有较高的权限,为Ability应用设置相应的权限,并预加载一些通用的模块,加速应用的启动。 - - -## 包管理子系统 - -包管理子系统是OpenHarmony为开发者提供的安装包管理框架。 - -**图 4** 包管理子系统框架图 -![](figures/包管理子系统框架图.png "包管理子系统框架图") - -- **BundleKit**:是包管理服务对外提供的接口,有安装/卸载接口、包信息查询接口、包状态变化listen接口。 -- **包扫描器**:用来解析本地预制或者安装的安装包,提取里面的各种信息,供管理子模块进行管理,持久化。 -- **包安装子模块**:安装,卸载,升级一个包;包安装服务是一个单独进程和包管理服务通过IPC进行通信,该服务用于创建、删除安装目录和数据目录等,具有较高的权限。 - -- **包管理子模块**:管理安装包相关的信息,存储持久化包信息。 - -- **包安全管理子模块**:签名检查、权限授予、权限管理。 - - -## 运作机制 - -Ability子系统的核心模块是Ability管理服务、包管理子系统的核心模块是包管理服务,这两个服务是系统级服务,借助系统服务框架Samgr实现服务的注册与发现,并对其他进程提供Ability管理服务和包管理服务。Ability管理服务和包管理服务通过AbilityKit和BundleKit以接口的形式向外提供服务。 - -**图 5** Ability管理服务和包管理服务启动 -![](figures/Ability管理服务和包管理服务启动.png "Ability管理服务和包管理服务启动") - -Ability管理服务和包管理服务启动后,就可以安装OpenHarmony应用和启动运行OpenHarmony应用。 - -**图 6** 应用启动流程 -![](figures/应用启动流程.png "应用启动流程") - -桌面为Ability管理服务启动的第一个OpenHarmony应用。桌面启动后,用户可以在桌面上点击安装的OpenHarmony应用并启动该应用。上图6为从桌面启动一个已安装应用的交互流程。 - -从图中可知,Ability管理服务负责协调Ability之间的显示隐藏,包管理服务负责Ability信息的存储查询。 - -## 约束与限制 - -- 语言版本 - - - C++11版本或以上 - - -- 框架针对不同的芯片平台和底层OS能力,规格有所区别 - - - Cortex-M RAM/ROM: - - - RAM:建议大于20K - - - ROM: \> 300K (包含JS应用开发框架,UIKit及引擎等强相关子系统) - - - - Cortex-A RAM/ROM: - - - RAM:建议大于2M - - - ROM:\> 2M (包含JS应用开发框架,UIKit及引擎等强相关子系统) - - - - diff --git "a/zh-cn/device-dev/subsystems/\346\265\213\350\257\225.md" "b/zh-cn/device-dev/subsystems/\346\265\213\350\257\225.md" deleted file mode 100755 index ee62074e9b..0000000000 --- "a/zh-cn/device-dev/subsystems/\346\265\213\350\257\225.md" +++ /dev/null @@ -1,989 +0,0 @@ -# 测试 - -- [概述](#section12403172115920) - - [基本概念](#section53632272090) - - [运作机制](#section2394431106) - -- [约束与限制](#section2029921310472) -- [搭建环境](#section175012297491) - - [环境要求](#section935055691014) - - [安装环境](#section6511193210111) - - [检验环境是否搭建成功](#section1899144517117) - -- [开发指导](#section16741101301210) - - [场景介绍](#section93782214124) - - [接口说明](#section54131732101218) - - [开发步骤](#section53541946111218) - -- [开发实例](#section7477121918136) -- [测试平台使用](#section76401945124810) -- [包结构说明](#section1875515364133) - -## 概述 - -### 基本概念 - -测试子系统提供基于python开发的一键式的开发者自测试平台,支持跨平台使用以及三方测试框架拓展,主要包括测试用例编译、测试用例管理、测试用例调度分发、测试用例执行、测试结果收集、测试报告生成、测试用例模板、测试环境管理等模块。 - -在测试子系统开发前,开发者应先了解以下概念: - -- 测试用例编译 - - 支持将测试用例源代码编译成可在被测设备侧执行的二进制文件。 - -- 测试用例调度分发 - - 支持将测试用例通过网口通道或者串口通道分发到不同的被测设备上,并且为每一个测试用例分配特定的测试用例执行器。 - -- 测试用例执行器 - - 负责测试用例的预处理,用例执行,结果记录等执行逻辑。 - -- 测试用例模板 - - 定义了测试用例以及用例编译配置GN文件的统一格式。 - -- 测试平台kit - - 测试平台运行过程中公共方法,如提供测试用例目录向被测设备挂载文件系统,测试用例推送到被测设备,或者从被测设备获取测试结果等操作。 - -- 测试报告生成 - - 定义开发者自测试报告模板,生成web测试报告。 - -- 测试环境管理 - - 支持通过USB、串口等方式管理被测设备,功能包括设备发现,设备状态查询等。 - - -### 运作机制 - -- 测试平台架构图如下: - -**图 1** 测试平台架构 -![](figures/测试平台架构.png "测试平台架构") - -- 测试平台运行时序图如下: - -**图 2** 测试平台运行时序 -![](figures/测试平台运行时序.png "测试平台运行时序") - -- 测试平台运行原理 - -测试平台通过shell脚本启动,以命令行方式支持一系列的测试指令执行,通过命令行输出测试结果。 - -## 约束与限制 - -- 功能使用范围:开发自测试平台仅支持代码级的测试用例开发和验证,如单元测试,模块测试。 -- 规格限制:当前测试框架的适用范围仅支持白盒测试。 -- 操作限制:一台测试设备上仅支持启动单个测试平台。 - -## 搭建环境 - -### 环境要求 - -**表 1** **环境要求** - - - - - - - - - - - - - - - - -

    项目

    -

    测试设备

    -

    被测设备

    -

    硬件

    -
    • 内存:8G及以上
    • 硬盘:100G及以上
    • 硬件架构:X86或ARM64
    -
    • Hi3516 DV300开发板
    • Hi3518 EV300开发板
    -

    软件

    -
    • 操作系统:Windows 10 64位 或 Ubuntu 18.04

      系统组件(Linux): libreadline-dev

      -
    • Python:3.7.5及以上
    • Python插件:pyserial3.3及以上、paramiko2.7.1及以上、setuptools40.8.0及以上,rsa4.0及以上
    • NFS Server:haneWIN NFS Server1.2.50及以上或者 NFSv4及以上
    -
    • 系统软件:版本不低于OpenHarmony 1.0
    • 内核类型:LiteOS-A或者Linux
    -
    - -### 安装环境 - -1. 如测试环境为Linux,需要安装系统组件readline,命令如下: - - ``` - sudo apt-get install libreadline-dev - ``` - - 安装成功提示如下: - - ``` - Reading package lists... Done - Building dependency tree - Reading state information... Done - libreadline-dev is already the newest version (7.0-3). - 0 upgraded, 0 newly installed, 0 to remove and 11 not upgraded. - ``` - -2. 安装Python扩展组件setuptools、(rsa、paramiko、以及pyserial,设备仅支持串口时安装),命令如下: - - 1、安装setuptools,安装命令如下: - - ``` - pip install setuptools - ``` - - 安装成功提示如下: - - ``` - Requirement already satisfied: setuptools in d:\programs\python37\lib\site-packages (41.2.0) - ``` - - 2、安装rsa,安装命令如下: - - ``` - pip install rsa - ``` - - 安装成功提示如下: - - ``` - Installing collected packages: pyasn1, rsa - Successfully installed pyasn1-0.4.8 rsa-4.7 - ``` - - 3、安装Paramiko,安装命令如下: - - ``` - pip install paramiko - ``` - - 安装成功提示如下: - - ``` - Installing collected packages: pycparser, cffi, pynacl, bcrypt, cryptography, paramiko - Successfully installed bcrypt-3.2.0 cffi-1.14.4 cryptography-3.3.1 paramiko-2.7.2 pycparser-2.20 pynacl-1.4.0 - ``` - - 4、安装pyserial(被测设备仅支持串口时安装),安装命令如下: - - ``` - pip install pyserial - ``` - - 安装成功提示如下: - - ``` - Requirement already satisfied: pyserial in d:\programs\python37\lib\site-packages\pyserial-3.4-py3.7.egg (3.4) - ``` - -3. 安装NFS server(被测设备仅支持串口时安装)。 - - **Windows环境安装** - - 下载并安装haneWIN NFS Server1.2.50,地址:https://www.hanewin.net/nfs-e.htm - - **Linux环境下安装** - - ``` - sudo apt install nfs-kernel-server - ``` - - 所有环境配置安装完成,即可在IDE中进行测试平台代码开发调试,推荐的IDE为 DevEco Studio。 - - -### 检验环境是否搭建成功 - -**表 2** **检验环境** - - - - - - - - - - - - - - - - - - - - -

    检查项

    -

    操作

    -

    满足条件

    -

    检查python安装与否,版本是否满足要求。

    -

    命令行窗口执行命令:python --version。

    -

    版本不小于3.7.5即可。

    -

    检查python扩展插件安装与否。

    -

    打开test/xdevice目录,执行run.bat或run.sh。

    -

    可进入提示符“>>>”界面即可。

    -

    检查NFS Server启动状态(被测设备仅支持串口时检测)。

    -

    通过串口登录开发板,执行mount命令挂载NFS。

    -

    可正常挂载文件目录即可。

    -
    - -## 开发指导 - -### 场景介绍 - -针对对开发的业务代码进行白盒测试验证。 - -### 接口说明 - -测试框架集成了开源的单元测试框架,并对测试用例的宏定义做了扩展,具体框架说明详见开源官方文档。 - -**表 3** 测试框架扩展宏定义说明 - - - - - - - - - - - - - - - - -

    宏定义

    -

    描述

    -

    HWTEST

    -

    测试用例执行不依赖Setup&Teardown。HWTEST对TEST增加了“用例级别”参数“TestSize.Level1”,例如HWTEST(CalculatorAddTest, TestPoint_001, TestSize.Level1)。

    -

    HWTEST_F

    -

    测试用例(不带参数)执行依赖Setup&Teardown。HWTEST_F对TEST_F增加了“用例级别”参数“ TestSize.Level1”,例如HWTEST_F(CalculatorAddTest, TestPoint_001, TestSize.Level1)。

    -

    HWTEST_P

    -

    测试用例(带参数)执行依赖Setup&Teardown。HWTEST_P对TEST_P增加了“用例级别”参数“ TestSize.Level1”,例如HWTEST_P(CalculatorAddTest, TestPoint_001, TestSize.Level1)。

    -
    - -### 开发步骤 - -1. 按照开发者测试用例目录规划定义测试套文件,需要继承testing::Test类,命名以被测特性+Test命名,示例代码路径:test/developertest/examples/lite/cxx\_demo/test/unittest/common/calc\_subtraction\_test.cpp - - ``` - /* - * Copyright (c) 2020 OpenHarmony. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - #include - - using namespace std; - using namespace testing::ext; - - class CalcSubtractionTest : public testing::Test { - public: - static void SetUpTestCase(void); - static void TearDownTestCase(void); - void SetUp(); - void TearDown(); - }; - ``` - - >![](public_sys-resources/icon-note.gif) **说明:** - >测试用例规范 - >- 命名规范 - > 测试用例源文件名称和测试套内容保持一致,测试套与用例之间关系1:N,测试套与测试源文件之间关系1:1,每个源文件全局唯一,格式:\[特性\]\_\[功能\]\_\[子功能1\]\_\[子功能1.1\],子功能支持向下细分。 - > 文件命名采用全小写+下划线方式命名,以test结尾,如demo用例:developertest/examples/lite/cxx\_demo - >- 测试用例编码规范 - > 开发者测试用例原则上与特性代码编码规范保持一致,另外需要添加必要的用例描述信息,详见[•自测试用例模板](#li2069415903917)。 - >- 测试用例编译配置规范 - > 测试用例采用GN方式编译,配置遵循本开源项目的[编译指导](../quick-start/概述.md)。 - >- 测试用例模板 - > 详见测试demo用例:developertest/examples/lite/cxx\_demo/test/unittest/common/calc\_subtraction\_test.cpp - -2. 实现测试套执行过程需要的预处理操作和后处理操作,即实现SetUp和TearDown方法。 - - ``` - void CalcSubtractionTest::SetUpTestCase(void) - { - // step 1: input testsuite setup step - } - - void CalcSubtractionTest::TearDownTestCase(void) - { - // step 2: input testsuite teardown step - } - - void CalcSubtractionTest::SetUp(void) - { - // step 3: input testcase setup step - } - - void CalcSubtractionTest::TearDown(void) - { - // step 4: input testcase teardown step - } - ``` - -3. 针对被测对象的特性编写测试用例,以使用HWTEST\_F为例说明。 - - ``` - /** - * @tc.name: integer_sub_001 - * @tc.desc: Test Calculator - * @tc.type: FUNC - * @tc.require: AR00000000 SR00000000 - */ - HWTEST_F(CalcSubtractionTest, integer_sub_001, TestSize.Level1) - { - EXPECT_EQ(0, Subtraction(1, 0)); - } - ``` - - >![](public_sys-resources/icon-note.gif) **说明:** - >- @tc.name:用例名称,对测试目的简要描述。 - >- @tc.desc:描述用例详细描述,包括测试目的、测试步骤、期望结果等。 - >- @tc.type:测试属性分类(FUNC、PERF、SECU、RELI)。 - >- @tc.require:需求编号或者issue编号,用来将修改与用例关联。 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    序号

    -

    测试类型名称

    -

    缩写

    -

    测试类型描述

    -

    1

    -

    功能测试(functionality)

    -

    FUNC

    -

    验证软件各个功能满足功能设计与规格。

    -

    2

    -

    性能测试(performance)

    -

    PERF

    -

    验证软件是否满足性能设计指标。包含负载测试容量测试,压力测试等。

    -

    3

    -

    安全性测试(security)

    -

    SECU

    -

    验证软件在生命周期内符合安全需求定义和相关法规。

    -

    4

    -

    可靠性测试(reliability)

    -

    RELI

    -

    在规定的条件下,在规定的时间内,软件不引起系统失效的概率,这里也包含稳定性。

    -
    - -4. 编写用例编译GN文件,其中包括定义用例编译目标,添加编译配置依赖,源文件等,举例说明: - - 示例文件路径:test/developertest/examples/lite/cxx\_demo/test/unittest/common/BUILD.gn)。 - - ``` - import("//build/lite/config/test.gni") - - unittest("CalcSubTest") { - output_extension = "bin" - sources = [ - "calc_subtraction_test.cpp" - ] - include_dirs = [] - deps = [] - } - ``` - -5. 将用例编译目标添加到子系统编译配置中,保证用例随版本一起编译,举例说明: - 1. 支持hdc连接的设备,编译配置示例路径:test/developertest/examples/ohos.build。 - - ``` - { - "subsystem": "subsystem_examples", - "parts": { - "subsystem_examples": { - "module_list": [ - "//test/developertest/examples/detector:detector", - ... ... - ], - "test_list": [ - "//test/developertest/examples/detector/test:unittest", - ... ... - ] - }, - ... ... - } - ``` - - 2. 仅支持串口的设备,编译配置示例路径:test/developertest/examples/lite/BUILD.gn。 - - ``` - import("//build/lite/config/test.gni") - - subsystem_test("test") { - test_components = [] - if(ohos_kernel_type == "liteos_riscv") { - features += [ - ] - }else if(ohos_kernel_type == "liteos_a") { - test_components += [ - "//test/developertest/examples/lite/cxx_demo/test/unittest/common:CalcSubTest" - ] - } - } - ``` - - -6. 编写测试用例资源配置,当测试用例需要使用静态测试资源文件时使用该配置。 - 1. 在部件或者模块的test目录下创建resource目录。 - 2. 在resource目录下创建形态目录,如phone。 - 3. 在设备形态目录下创建一个以模块名命名的文件夹,如testmodule。 - 4. 在模块目录下创建一个ohos\_test.xml文件,文件内容格式如下: - - ``` - - - - - - - - ``` - - 5. 在测试用例的编译配置文件中定义resource\_config\_file,用来指定对应的资源文件ohos\_test.xml。 - - >![](public_sys-resources/icon-note.gif) **说明:** - >如上资源文件功能:将resource目录下的test.txt文件通过hdc push命令推送到被测设备的/data/test/resource目录下。 - - -7. 以上步骤完成即完成测试用例编写,即可执行测试用例。 - - >![](public_sys-resources/icon-note.gif) **说明:** - >- 支持hdc连接的设备,测试用例支持单独编译。 - >- 仅支持串口连接的设备,在代码根路径下执行编译debug版本的命令,即可编译测试用例。 - > 测试用例用例的执行详见[测试平台使用](#section76401945124810)。 - - -## 开发实例 - -测试子系统代码仓提供了完整demo用例,demo用例路径:test/developertest/examples/。以一个减法运算方法编写测试用例举例说明: - -- 被测代码如下: - - ``` - static int Subtraction(int a, int b) - { - return a - b; - } - ``` - -- 测试用例代码如下: - - ``` - /** - * @tc.name: integer_sub_002 - * @tc.desc: Verify the Subtraction function. - * @tc.type: FUNC - * @tc.require: AR00000000 SR00000000 - */ - HWTEST_F(CalcSubtractionTest, integer_sub_002, TestSize.Level1) - { - EXPECT_EQ(1, Subtraction(2, 1)); - } - ``` - - -## 测试平台使用 - -1. (可选)安装xdevice组件。安装xdevice后,xdevice组件可以作为python的扩展包使用。 - - 打开xdevice安装目录:test/xdevice,执行如下命令: - - ``` - python setup.py install - ``` - - 安装成功提示如下: - - ``` - ... ... - Installed d:\programs\python37\lib\site-packages\xdevice-0.0.0-py3.7.egg - Processing dependencies for xdevice==0.0.0 - Searching for pyserial==3.4 - Best match: pyserial 3.4 - Processing pyserial-3.4-py3.7.egg - pyserial 3.4 is already the active version in easy-install.pth - Installing miniterm.py script to D:\Programs\Python37\Scripts - - Using d:\programs\python37\lib\site-packages\pyserial-3.4-py3.7.egg - Finished processing dependencies for xdevice==0.0.0 - ``` - -2. 修改developertest/config/user\_config.xml 文件配置developertest组件。 - 1. 测试框架通用配置。 - - \[build\] \# 配置测试用例的编译参数,例如: - - ``` - - false - false - true - ... ... - - ``` - - >![](public_sys-resources/icon-note.gif) **说明:** - >测试用例的编译参数说明如下: - >example:是否编译测试用例示例,默认false。 - >version:是否编译测试版本,默认false。 - >testcase:是否编译测试用例,默认true。 - - 2. 支持hdc连接的被测设备。 - - \[device\] \# 配置标签为usb-hdc的环境信息,测试设备的IP地址和hdc映射的端口号,例如: - - ``` - - 192.168.1.1 - 9111 - - - ``` - - 3. 仅支持串口的被测设备。 - - \[board\_info\] \# 开发板配置信息,例如: - - ``` - - hispark - taurus - ipcamera - hb build - - ``` - - >![](public_sys-resources/icon-note.gif) **说明:** - >开发板配置信息如下: - >board\_series:开发板系列,默认hispark。 - >board\_type:开发板类型,默认taurus。 - >board\_product:目标产品,默认ipcamera。 - >build\_command:测试版本和用例的编译命令,默认hb build。 - - \[device\] \# 配置标签为ipcamera的串口信息,COM口和波特率,例如: - - ``` - - - COM1 - cmd - 115200 - 8 - 1 - 1 - - - ``` - - -3. (可选)修改developertest组件配置。如果测试用例已完成编译,可以直接指定测试用例的编译输出路径,测试平台执行用例时即不会重新编译测试用例。 - - 配置文件:config/user\_config.xml - - 1. \[test\_cases\] \# 指定测试用例的输出路径,编译输出目录,例如: - - ``` - - /home/opencode/out/release/tests - - ``` - - 2. \[NFS\] \# 被测设备仅支持串口时配置,指定NFS的映射路径,host\_dir为PC侧的NFS目录,board\_dir为板侧创建的目录,例如: - - ``` - - D:\nfs - user - - ``` - - -4. (可选)测试环境准备。当被测设备仅支持串口时,需要检查。 - - 系统镜像与文件系统已烧录进开发板,开发板上系统正常运行,在系统模式下,如使用shell登录时,设备提示符是“OHOS\#”。 - - 开发主机和开发板串口连接正常,网口连接正常。 - - 开发主机IP与开发板IP处在同一小网网段,相互可以ping通。 - - 开发主机侧创建空目录用于开发板通过NFS挂载测试用例,并且NFS服务启动正常。 - -5. (必选)启动测试平台,执行测试用例。 - - 启动测试框架,打开test/developertest目录,执行启动脚本。 - 1. Windows环境启动测试框架,执行如下脚本: - - ``` - start.bat - ``` - - 2. Linux环境启动测试框架。 - - ``` - ./start.sh - ``` - - - - 设备形态选择。 - - 根据实际的开发板选择,设备形态配置:developertest/config/framework\_config.xml。 - - - 执行测试指令。 - 1. 查询测试用例支持的子系统,模块,产品形态以及测试类型,使用show命令,示例如下: - - ``` - usage: - show productlist Querying Supported Product Forms - show typelist Querying the Supported Test Type - show subsystemlist Querying Supported Subsystems - show modulelist Querying Supported Modules - ``` - - 2. 执行测试指令,其中-t为必选,-ss和-tm为可选字段,示例如下: - - ``` - run -t ut -ss subsystem_examples -tm calculator - ``` - - 3. 参数说明:指定参数可以执行特定特性、模块对应的测试套。 - - ``` - usage: run [-h] [-p PRODUCTFORM] [-t [TESTTYPE [TESTTYPE ...]]] - [-ss SUBSYSTEM] [-tm TESTMODULE] [-ts TESTSUIT] - [-tc TESTCASE] [-tl TESTLEVEL] - - optional arguments: - -h, --help show this help message and exit - -p PRODUCTFORM, --productform PRODUCTFORM Specified product form - -t [TESTTYPE [TESTTYPE ...]], --testtype [TESTTYPE [TESTTYPE ...]] - Specify test type(UT,MST,ST,PERF,ALL) - -ss SUBSYSTEM, --subsystem SUBSYSTEM Specify test subsystem - -tm TESTMODULE, --testmodule TESTMODULE Specified test module - -ts TESTSUIT, --testsuite TESTSUIT Specify test suite - -tc TESTCASE, --testcase TESTCASE Specify test case - -tl TESTLEVEL, --testlevel TESTLEVEL Specify test level - ``` - - - - 测试框架帮助。 - - 帮助指令,用于查询测试平台支持哪些测试指令,如下: - - ``` - help - ``` - - - 退出自测试平台。 - - 退出自测试平台,使用如下命令退出测试平台,如下: - - ``` - quit - ``` - - -6. (必选)查看测试结果与日志,通过在测试平台中执行测试指令,即可在developertest/reports目录下生成测试日志和测试报告。 - - 测试用例的结果会直接显示在控制台上,执行一次的测试结果根路径如下: - - ``` - reports/xxxx-xx-xx-xx-xx-xx - ``` - - - 测试用例格式化结果目录如下: - - ``` - result/ - ``` - - - 测试用例日志目录如下: - - ``` - log/plan_log_xxxx-xx-xx-xx-xx-xx.log - ``` - - - 测试报告汇总: - - ``` - summary_report.html - ``` - - - 测试报告详情: - - ``` - details_report.html - ``` - - - - 测试平台日志目录如下: - - ``` - reports/platform_log_xxxx-xx-xx-xx-xx-xx.log - ``` - - - -## 包结构说明 - -开发者测试平台xdevice组件包结构说明,代码目录test/xdevice,详见下表所示: - -**表 4** xdevice组件包结构说明 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    名称

    -

    功能描述

    -

    xdevice

    -

    测试平台基础组件。

    -

    xdevice/src/xdevice

    -

    基础测试框架源码。

    -

    xdevice/config

    -

    基础测试框架配置文件定义。

    -

    xdevice/src/xdevice/__main__.py

    -

    基础测试框架内部入口。

    -

    xdevice/src/xdevice/__init__.py

    -

    包依赖定义,插件依赖。

    -

    xdevice/src/xdevice/variables.py

    -

    全局变量定义。

    -

    xdevice/src/xdevice/_core/command

    -

    用例输入的命令行处理。

    -

    xdevice/src/xdevice/_core/config

    -

    基础测试框架的配置管理。

    -

    xdevice/src/xdevice/_core/environment

    -

    基础测试框架的环境管理,包括设备管理。

    -

    xdevice/src/xdevice/_core/executor

    -

    基础测试框架用例调度和分发。

    -

    xdevice/src/xdevice/_core/driver

    -

    基础测试框架测试执行器。

    -

    xdevice/src/xdevice/_core/resource

    -

    基础测试框架资源文件以及测试报告模板。

    -

    xdevice/src/xdevice/_core/testkit

    -

    基础测试框架公共操作,包括NFS文件系统挂载等。

    -

    xdevice/src/xdevice/_core/logger.py

    -

    基础测试框架日志管理。

    -

    xdevice/src/xdevice/_core/plugin.py

    -

    基础测试框架插件管理。

    -

    xdevice/src/xdevice/_core/interface.py

    -

    基础测试框架插件接口定义。

    -

    xdevice/setup.py

    -

    基础测试框架的安装脚本。

    -

    xdevice/run.bat

    -

    基础测试框架启动脚本(Windows)。

    -

    xdevice/run.sh

    -

    基础测试框架启动脚本(Linux)。

    -
    - -开发者测试平台developertest组件包结构说明,代码目录test/developertest,详见下表所示: - -**表 5** developertest组件包结构说明 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    名称

    -

    描述

    -

    developertest

    -

    开发测试框架。

    -

    developertest/src

    -

    测试框架源码。

    -

    developertest/src/core

    -

    测试执行器。

    -

    developertest/src/core/build

    -

    测试用例编译。

    -

    developertest/src/core/command

    -

    对用户输入的命令行处理。

    -

    developertest/src/core/config

    -

    测试框架配置管理。

    -

    developertest/src/core/driver

    -

    测试框架驱动执行器。

    -

    developertest/src/core/resource

    -

    测试框架配置文件。

    -

    developertest/src/core/testcase

    -

    测试用例管理。

    -

    developertest/src/core/common.py

    -

    测试框架公共操作。

    -

    developertest/src/core/constants.py

    -

    测试框架全局常量。

    -

    developertest/src/core/exception.py

    -

    测试框架异常定义。

    -

    developertest/src/core/utils.py

    -

    测试框架工具方法。

    -

    developertest/src/main

    -

    测试框架平台。

    -

    developertest/src/main/__main__.py

    -

    测试框架内部入口。

    -

    developertest/examples

    -

    测试框架demo用例。

    -

    developertest/third_party

    -

    测试框架依赖第三方组件适配。

    -

    developertest/BUILD.gn

    -

    测试子系统编译配置。

    -

    developertest/start.bat

    -

    开发者测试入口(Windows)。

    -

    developertest/start.sh

    -

    开发者测试入口(Linux)。

    -
    - diff --git "a/zh-cn/device-dev/subsystems/\347\224\250\346\210\267\347\250\213\345\272\217\346\241\206\346\236\266.md" "b/zh-cn/device-dev/subsystems/\347\224\250\346\210\267\347\250\213\345\272\217\346\241\206\346\236\266.md" deleted file mode 100755 index 14552d89af..0000000000 --- "a/zh-cn/device-dev/subsystems/\347\224\250\346\210\267\347\250\213\345\272\217\346\241\206\346\236\266.md" +++ /dev/null @@ -1,11 +0,0 @@ -# 用户程序框架 - -- **[概述](概述.md)** - -- **[搭建环境](搭建环境-2.md)** - -- **[开发指导](开发指导-3.md)** - -- **[开发实例](开发实例.md)** - - diff --git "a/zh-cn/device-dev/subsystems/\347\233\270\346\234\272.md" "b/zh-cn/device-dev/subsystems/\347\233\270\346\234\272.md" deleted file mode 100755 index 3b86f53b9b..0000000000 --- "a/zh-cn/device-dev/subsystems/\347\233\270\346\234\272.md" +++ /dev/null @@ -1,11 +0,0 @@ -# 相机 - -- **[相机开发概述](相机开发概述.md)** - -- **[拍照开发指导](拍照开发指导.md)** - -- **[录像开发指导](录像开发指导.md)** - -- **[预览开发指导](预览开发指导.md)** - - diff --git "a/zh-cn/device-dev/subsystems/\347\233\270\346\234\272\345\274\200\345\217\221\346\246\202\350\277\260.md" "b/zh-cn/device-dev/subsystems/\347\233\270\346\234\272\345\274\200\345\217\221\346\246\202\350\277\260.md" deleted file mode 100755 index 65801b39bc..0000000000 --- "a/zh-cn/device-dev/subsystems/\347\233\270\346\234\272\345\274\200\345\217\221\346\246\202\350\277\260.md" +++ /dev/null @@ -1,116 +0,0 @@ -# 相机开发概述 - -- [基本概念](#section175012297491) -- [运作机制](#section193961322175011) - -## 基本概念 - -相机是OpenHarmony多媒体进程提供的服务之一,提供了相机的录像、预览、拍照功能,支持多用户并发取流。 - -在进行应用的开发前,开发者应了解以下基本概念: - -- 视频帧 - - 视频流指的是将一系列图片数据按照固定时间间隔排列形成的数据流,每一张图片数据成为一帧,这样的一帧称为视频帧。 - -- 帧速率\(FPS: Frames Per Second\) - - 视频播放每秒钟刷新图片的速度,或是视频每秒的帧数,帧速率越高,视频的观感越流畅。 - -- 分辨率 - - 每一帧的图片信息都是由像素点组成的,分辨率描述了一张图片中像素点的个数。例如1920\*1080\(1080P\),是指图片宽1920像素,高1080像素。 - - -## 运作机制 - -- 多媒体服务进程 - - 多媒体服务作为系统服务,在系统启动时由Init进程拉起,并初始化和分配媒体硬件资源(内存/显示硬件/图像传感器/编解码器等)。初始化过程解析配置文件,确定了多媒体各个服务的能力和资源上限,通常由OEM厂商通过配置文件进行配置。相机服务在多媒体进程初始化时有以下配置项: - - - 内存池:所有媒体服务依赖于内存池中的内存轮转运行 - - 图像传感器:包括了传感器类型、分辨率、ISP等 - - 图像处理器:分辨率、码率、图像翻转等 - - 图像编码器:编码格式、码率、分辨率等 - - -- 关键类的解释 - - 应用通过持有下面4个类,配置和使用Camera的功能,包括了Camera类和它的三个异步回调类,三类回调分别对应了不同类型的异步处理场景,详见[表1](#table486418149411)。 - - **表 1** 关键类的解释 - - - - - - - - - - - - - - - - - - - - - - - - -

    对象

    -

    用途

    -

    举例

    -

    Camera

    -

    对相机进行静态配置(通过配置类),触发相机基本功能

    -

    拍照/录像/预览

    -

    CameraDeviceCallback

    -

    处理相机硬件状态变化

    -

    可用/不可用

    -

    CameraStateCallback

    -

    处理camera自身状态变化

    -

    创建/释放

    -

    FrameStateCallback

    -

    处理帧状态的变化

    -

    拍照开始和结束/帧率发生变化

    -
    - -- 流的传递 - - Surface是多媒体传递音视频的基本数据结构,Camera一般作为Surface中数据的生产者,在不同的场景下有特定的消费者。 - - 相机的预览和录像输出均为视频流,拍照输出为图像帧,二者均通过Surface类进行传递。Surface类可以屏蔽进程内/跨进程的场景,进行多媒体信息流的传递。 - - 以录像为例,用户首先创建Recorder实例,并从Recorder中获取对应Surface,再将此Surface传递给Camera实例,此时Camera将作为生产者向Surface注入视频流,而Recorder作为消费者从Surface中取出视频流进行保存,用户的行为类似桥接,把二者通过Surface连接起来。 - - 类似的,用户也可以自行创建Surface传递给Camera实例,并实现消费者逻辑(例如通过网络传输视频流,或是将拍照的帧数据保存成图片文件)。 - - 图形图像模块也通过Surface从Camera获取流资源,具体步骤详见[图形图像开发指导](图形图像概述.md)。 - -- 相机运行流程 - 1. Camera创建流程 - - 本进程通过CameraManager创建Camera实例,并从服务端绑定camera设备,创建成功后异步通知developer。类之间的时序图如下: - - **图 1** Camera创建时序图 - - - ![](figures/zh-cn_image_0000001054101094.png) - - - 1. Camera录像/预览流程 - - 开发者首先通过CameraKit创建Camera,然后FrameConfig类对录像或者预览帧属性进行配置。录像/预览时序如下: - - **图 2** Camera录像/预览时序图 - - - ![](figures/zh-cn_image_0000001054421113.png) - - - diff --git "a/zh-cn/device-dev/subsystems/\347\240\224\345\217\221\345\267\245\345\205\267\351\223\276.md" "b/zh-cn/device-dev/subsystems/\347\240\224\345\217\221\345\267\245\345\205\267\351\223\276.md" deleted file mode 100644 index 5c490a8cfb..0000000000 --- "a/zh-cn/device-dev/subsystems/\347\240\224\345\217\221\345\267\245\345\205\267\351\223\276.md" +++ /dev/null @@ -1,9 +0,0 @@ -# 研发工具链 - -- **[bytrace使用指导](bytrace使用指导.md)** - -- **[hdc\_std 使用指导](hdc_std-使用指导.md)** - -- **[hdc\_std常见问题](hdc_std常见问题.md)** - - diff --git "a/zh-cn/device-dev/subsystems/\347\274\226\350\257\221\346\236\204\345\273\272.md" "b/zh-cn/device-dev/subsystems/\347\274\226\350\257\221\346\236\204\345\273\272.md" deleted file mode 100755 index b59e4b2a18..0000000000 --- "a/zh-cn/device-dev/subsystems/\347\274\226\350\257\221\346\236\204\345\273\272.md" +++ /dev/null @@ -1,7 +0,0 @@ -# 编译构建 - -- **[轻量和小型系统编译构建指导](轻量和小型系统编译构建指导.md)** - -- **[标准系统编译构建指导](标准系统编译构建指导.md)** - - diff --git "a/zh-cn/device-dev/subsystems/\347\274\226\350\257\221\346\236\204\345\273\272\344\275\277\347\224\250\346\214\207\345\257\274-1.md" "b/zh-cn/device-dev/subsystems/\347\274\226\350\257\221\346\236\204\345\273\272\344\275\277\347\224\250\346\214\207\345\257\274-1.md" deleted file mode 100755 index 661ff10cf6..0000000000 --- "a/zh-cn/device-dev/subsystems/\347\274\226\350\257\221\346\236\204\345\273\272\344\275\277\347\224\250\346\214\207\345\257\274-1.md" +++ /dev/null @@ -1,176 +0,0 @@ -# 编译构建使用指导 - -- [目录结构](#section56731811102915) -- [编译](#section1069873833818) - - [编译命令](#section2740182614395) - -- [开发步骤](#section4207112818418) - -## 目录结构 - -``` -/build # 编译构建主目录 -├── config # 编译相关的配置项 -├── core -│ └── gn # 编译入口BUILD.gn配置 -├── loader # 各个组件配置加载、模板生成 -├── ohos # OpenHarmony编译打包流程配置 -│ ├── kits # kits编译打包模板和处理流程 -│ ├── ndk # ndk模板和处理流程 -│ ├── notice # notice模板和处理流程 -│ ├── packages # 版本打包模板和处理流程 -│ ├── sa_profile # sa模板和处理流程 -│ ├── sdk # sdk模板和处理流程,包括sdk中包含的模块配置 -│ └── testfwk # 测试相关的处理 -├── scripts # 编译相关的python脚本 -├── templates # c/c++编译模板定义 -└── toolchain # 编译工具链配置 -``` - -## 编译 - -### 编译命令 - -- 代码根目录下执行全量版本的编译命令: - - ``` - ./build.sh --product-name {product_name} - ``` - - \{product\_name\}为当前版本支持的平台。比如:Hi3516DV300等。 - - 编译完成后,结果镜像保存在 out/ohos-arm-release/packages/phone/images/ 目录下。 - -- 编译命令支持选项: - - ``` - --product-name # 必须 编译的产品名称,如:Hi3516DV300 - --build-target # 可选 指定编译目标,可以指定多个 - --gn-args # 可选 gn参数,支持指定多个 - --ccache # 可选 编译使用ccache,需要本地安装ccache - ``` - - -## 开发步骤 - -1. 添加组件。 - - 本节以添加一个自定义的组件为例,描述如何编译组件,编译库、编译可执行文件等。 - - 示例组件partA由feature1、feature2和feature3组成,feature1的编译目标为一个动态库,feature2的目标为一个可执行程序,feature3的目标为一个etc配置文件。 - - 示例组件partA的配置需要添加到一个子系统中,本次示例将添加到subsystem\_examples子系统中(subsystem\_examples子系统定义在test/examples/目录)。 - - 示例组件partA的完整目录结构如下: - - ``` - test/examples/partA - ├── feature1 - │ ├── BUILD.gn - │ ├── include - │ │ └── helloworld1.h - │ └── src - │ └── helloworld1.cpp - ├── feature2 - │ ├── BUILD.gn - │ ├── include - │ │ └── helloworld2.h - │ └── src - │ └── helloworld2.cpp - └── feature3 - ├── BUILD.gn - └── src - └── config.conf - ``` - - 示例1:编写动态库gn脚本test/examples/partA/feature1/BUILD.gn,示例如下: - - ``` - config("helloworld_lib_config") { - include_dirs = [ "include" ] - } - - ohos_shared_library("helloworld_lib") { - sources = [ - "include/helloworld1.h", - "src/helloworld1.cpp", - ] - public_configs = [ ":helloworld_lib_config" ] - part_name = "partA" - } - ``` - - 示例2:编写可执行文件gn脚本test/examples/partA/feature2/BUILD.gn,示例如下: - - ``` - ohos_executable("helloworld_bin") { - sources = [ - "src/helloworld2.cpp" - ] - include_dirs = [ "include" ] - deps = [ # 依赖组件内模块 - "../feature1:helloworld_lib" - ] - external_deps = [ "partB:module1" ] # (可选)如果有跨组件的依赖,格式为“组件名:模块名” - install_enable = true # 可执行程序缺省不安装,需要安装时需要指定 - part_name = "partA" - } - ``` - - 示例3:编写etc模块gn脚本test/examples/partA/feature3/BUILD.gn,示例如下: - - ``` - ohos_prebuilt_etc("feature3_etc") { - source = "src/config.conf" - relative_install_dir = "init" #可选,模块安装相对路径,相对于默认安装路径;默认在/system/etc目录 - part_name = "partA" - } - ``` - - 示例4:在子系统的ohos.build中添加组件配置:test/examples/ohos.build。每个子系统有一个ohos.build配置文件,在子系统的根目录下。示例如下: - - ``` - "partA": { - "module_list": [ - "//test/examples/partA/feature1:helloworld_lib", - "//test/examples/partA/feature2:helloworld_bin", - "//test/examples/partA/feature3:feature3_etc", - ], - "inner_kits": [ - - ], - "system_kits": [ - - ], - "test_list": [ - - ] - } - ``` - - 一个组件包含module\_list、inner\_kits、system\_kits、test\_list四个部分的声明,其中: - - - module\_list:组件所包含的模块列表; - - inner\_kits:组件提供给其它组件调用的接口,其他组件的模块可以在external\_deps中添加依赖的模块; - - system\_kits:组件提供给开发者开发应用的接口; - - test\_list:组件中对应模块的测试用例; - -2. 将组件添加到产品配置中。 - - 在产品的配置中添加组件,产品对应的配置文件:productdefine/common/products/\{product-name\}.json。 - - 在产品配置文件中添加 "subsystem\_examples:partA",表示该产品中会编译并打包partA到版本中。 - -3. 编译。 - - 以编译Hi3516DV300为例,编译命令如下: - - ``` - ./build.sh --product-name Hi3516DV300 --ccache - ``` - -4. 编译输出。 - - 编译所生成的文件都归档在out/ohos-arm-release/目录下,结果镜像输出在 out/ohos-arm-release/packages/phone/images/ 目录下。 - - diff --git "a/zh-cn/device-dev/subsystems/\347\274\226\350\257\221\346\236\204\345\273\272\344\275\277\347\224\250\346\214\207\345\257\274.md" "b/zh-cn/device-dev/subsystems/\347\274\226\350\257\221\346\236\204\345\273\272\344\275\277\347\224\250\346\214\207\345\257\274.md" deleted file mode 100755 index 8d5f276817..0000000000 --- "a/zh-cn/device-dev/subsystems/\347\274\226\350\257\221\346\236\204\345\273\272\344\275\277\347\224\250\346\214\207\345\257\274.md" +++ /dev/null @@ -1,431 +0,0 @@ -# 编译构建使用指导 - -- [前提条件](#section13333171022312) -- [hb命令行工具使用](#section477242204612) -- [新增组件](#section4207112818418) -- [新增芯片解决方案](#section2737141421917) -- [新增产品解决方案](#section720881917199) - -## 前提条件 - -开发环境需安装gn、ninja构建工具、python 3.7.4及以上和hb。安装方法请见[搭建系统基础环境](../quick-start/搭建系统环境.md)。 - -## hb命令行工具使用 - -hb是OpenHarmony的命令行工具,用来执行编译命令。以下对hb的常用命令进行说明。 - -1. **hb set** - - ``` - hb set -h - usage: hb set [-h] [-root [ROOT_PATH]] [-p] - - optional arguments: - -h, --help show this help message and exit - -root [ROOT_PATH], --root_path [ROOT_PATH] - Set OHOS root path - -p, --product Set OHOS board and kernel - ``` - - - hb set 后无参数,进入默认设置流程 - - hb set -root dir可直接设置代码根目录 - - hb set -p设置要编译的产品 - -2. **hb env** - - 查看当前设置信息 - - ``` - hb env - [OHOS INFO] root path: xxx - [OHOS INFO] board: hispark_taurus - [OHOS INFO] kernel: liteos - [OHOS INFO] product: ipcamera - [OHOS INFO] product path: xxx/vendor/hisilicon/ipcamera - [OHOS INFO] device path: xxx/device/hisilicon/hispark_taurus/sdk_linux_4.19 - ``` - -3. **hb build** - - ``` - hb build -h - usage: hb build [-h] [-b BUILD_TYPE] [-c COMPILER] [-t [TEST [TEST ...]]] - [--dmverity] [-p PRODUCT] [-f] [-n] - [component [component ...]] - - positional arguments: - component name of the component - - optional arguments: - -h, --help show this help message and exit - -b BUILD_TYPE, --build_type BUILD_TYPE - release or debug version - -t [TEST [TEST ...]], --test [TEST [TEST ...]] - compile test suit - --dmverity Enable dmverity - -p PRODUCT, --product PRODUCT - build a specified product with - {product_name}@{company}, eg: ipcamera@hisilcon - -f, --full full code compilation - -T [TARGET [TARGET ...]], --target [TARGET [TARGET ...]] - Compile single target - ``` - - - hb build后无参数,会按照设置好的代码路径、产品进行编译,编译选项使用与之前保持一致。-f 选项将删除当前产品所有编译产品,等同于hb clean + hb build. - - hb build \{component\_name\}:基于设置好的产品对应的单板、内核,单独编译组件(e.g.:hb build kv\_store\)。 - - hb build -p ipcamera@hisilicon:免set编译产品,该命令可以跳过set步骤,直接编译产品。 - - 在device/device\_company/board下单独执行hb build会进入内核选择界面,选择完成后会根据当前路径的单板、选择的内核编译出仅包含内核、驱动的镜像。 - -4. **hb clean** - - 清除out目录对应产品的编译产物,仅保留args.gn、build.log。清除指定路径可输入路径参数:hb clean out/board/product,默认将清除当前hb set的产品对应out路径。 - - ``` - hb clean - usage: hb clean [-h] [out_path] - - positional arguments: - out_path clean a specified path. - - optional arguments: - -h, --help show this help message and exit - ``` - - -## 新增组件 - -本小节介绍如何新增一个组件,首先确定组件归属的子系统和组件名称,然后按如下步骤新增: - -1. 源码开发完成后,添加组件编译脚本。 - - 以编译组件hello\_world可执行文件为例,applications/sample/hello\_world/BUILD.gn可以写为: - - ``` - executable("hello_world") { - include_dirs = [ - "include", - ] - sources = [ - "src/hello_world.c" - ] - } - ``` - - 如上编译脚本,可编译出一个可在OpenHarmony上运行的名为hello\_world的可执行文件。 - - 单独编译该组件,hb set任意选择一款产品,然后使用-T选项单独编译组件: - - ``` - hb build -f -T //applications/sample/hello_world - ``` - - 组件在开发板上功能验证完成后,可按步骤2\~5将组件配置到产品中。 - -2. 添加组件描述。 - - 组件描述位于build/lite/components下,新增的组件需加入对应子系统的json文件中。一个组件描述必选的字段有: - - - component:组件名称。 - - description:组件的一句话功能描述。 - - optional:组件是否为系统可选。 - - dirs:组件源码路径。 - - targets:组件编译入口。 - - 以将hello\_world组件加入应用子系统为例,在applications.json中添加hello\_world对象: - - ``` - { - "components": [ - { - "component": "hello_world", - "description": "Hello world.", - "optional": "true", - "dirs": [ - "applications/sample/hello_world" - ], - "targets": [ - "//applications/sample/hello_world" - ] - }, - ... - ] - } - ``` - -3. 将组件配置到产品。 - - 产品的配置文件config.json位于位于vendor/company/product/下,产品配置文件需包含产品名称、OpenHarmony版本号、device厂商、开发板、内核类型、内核版本号,以及配置的子系统和组件。以将hello\_world组件加入产品配置文件my\_product.json中为例,加入hello\_wolrd对象: - - ``` - { - "product_name": "hello_world_test", - "ohos_version": "OpenHarmony 1.0", - "device_company": "hisilicon", - "board": "hispark_taurus", - "kernel_type": "liteos_a", - "kernel_version": "1.0.0", - "subsystems": [ - { - "subsystem": "applications", - "components": [ - { "component": "hello_world", "features":[] } - ] - }, - ... - ] - } - ``` - -4. 编译产品。 - - 1. 代码根目录输入hb set选择对应产品。 - - 2. 执行hb build。 - - -## 新增芯片解决方案 - -编译构建支持添加新的芯片解决方案厂商,具体步骤如下: - -1. 创建芯片解决方案目录。 - - 按照[芯片解决方案配置规则](编译构建概述.md#section1625463413327)创建目录,以芯片厂商realtek的“rtl8720“开发板为例, 在代码根目录执行: - - ``` - mkdir -p device/realtek/rtl8720 - ``` - -2. 创建内核适配目录,并编写开发板编译配置config.gni文件。 - - 以realtek的“rtl8720“开发板的liteos\_m适配为例,device/realtek/rtl8720/liteos\_a/config.gni的内容如下: - - ``` - # Kernel type, e.g. "linux", "liteos_a", "liteos_m". - kernel_type = "liteos_a" - - # Kernel version. - kernel_version = "3.0.0" - - # Board CPU type, e.g. "cortex-a7", "riscv32". - board_cpu = "real-m300" - - # Board arch, e.g. "armv7-a", "rv32imac". - board_arch = "" - - # Toolchain name used for system compiling. - # E.g. gcc-arm-none-eabi, arm-linux-harmonyeabi-gcc, ohos-clang, riscv32-unknown-elf. - # Note: The default toolchain is "ohos-clang". It's not mandatory if you use the default toochain. - board_toolchain = "gcc-arm-none-eabi" - - # The toolchain path instatlled, it's not mandatory if you have added toolchian path to your ~/.bashrc. - board_toolchain_path = - rebase_path("//prebuilts/gcc/linux-x86/arm/gcc-arm-none-eabi/bin", - root_build_dir) - - # Compiler prefix. - board_toolchain_prefix = "gcc-arm-none-eabi-" - - # Compiler type, "gcc" or "clang". - board_toolchain_type = "gcc" - - # Board related common compile flags. - board_cflags = [] - board_cxx_flags = [] - board_ld_flags = [] - ``` - -3. 编写编译脚本。 - - 在开发板目录下创建BUILD.gn,target名称应与开发板名称一致。以realtek的rtl8720开发板为例,device/realtek/rtl8720/BUILD.gn内容可以是: - - ``` - group("rtl8720") { # target类型也可以shared_library, static_library, executable - # 具体内容 - ...... - } - ``` - -4. 编译芯片解决方案。 - - 在开发板目录下执行hb build,即可启动芯片解决方案的编译。 - - -## 新增产品解决方案 - -编译构建支持芯片解决方案和组件的灵活拼装,形成定制化的产品解决方案。具体步骤如下: - -1. 创建产品目录 - - 按照[产品解决方案配置规则](编译构建概述.md#section1625463413327)创建产品目录,以基于“rtl8720“开发板的wifiiot模组为例,在代码根目录执行: - - ``` - mkdir -p vendor/my_company/wifiiot - ``` - -2. 拼装产品 - - 在新建的产品目录下新建config.json文件,以步骤1中的wifiiot为例,vendor/my\_company/wifiiot/config.json可以是: - - ``` - { - "product_name": "wifiiot", # 产品名称 - "ohos_version": "OpenHarmony 1.0", # 使用的OS版本 - "device_company": "realtek", # 芯片解决方案厂商名称 - "board": "rtl8720", # 开发板名称 - "kernel_type": "liteos_m", # 选择的内核类型 - "kernel_version": "3.0.0", # 选择的内核版本 - "subsystems": [ - { - "subsystem": "kernel", # 选择的子系统 - "components": [ - { "component": "liteos_m", "features":[] } # 选择的组件和组件特性 - ] - }, - ... - { - 更多子系统和组件 - } - ] - } - ``` - - 注意:编译构建系统编译前会对device\_company,board,kernel\_type,kernel\_version、subsystem、component字段进行有效性检查,其中device\_company,board,kernel\_type,kernel\_version应与已知的芯片解决方案匹配,subsystem、component应与build/lite/components下的组件描述匹配。 - -3. 适配OS接口 - - 在产品目录下创建hals目录,并将产品解决方案对OS适配的源码和编译脚本放入该目录下。 - -4. 配置系统服务 - - 在产品目录下创建init\_configs目录,并在init\_configs目录下创建init.cfg文件,按需配置要启动的系统服务。 - -5. 配置init进程(仅linux内核需要) - - 在init\_configs目录下创建etc目录,然后在etc下创建init.d文件夹和fstab文件。最后按产品需求在init.d文件下创建并编辑rcS文件和Sxxx文件。 - -6. 配置文件系统镜像(可选,仅支持文件系统的开发板需要) - - 在产品目录下创建fs.yml文件。fs.yml需按产品实际情况配置,一个典型的fs.yml文件如下: - - ``` - - - fs_dir_name: rootfs # 镜像的名称 - fs_dirs: - - - # 将编译生成的out/my_board/my_product/bin目录下的文件拷贝到rootfs/bin中,并忽略测试bin - source_dir: bin - target_dir: bin - ignore_files: - - Test.bin - - TestSuite.bin - - - # 将编译生成的out/my_board/my_product/libs目录下的文件拷贝到rootfs/lib中,忽略所有.a文件,并设置文件和文件夹的权限为644和755 - source_dir: libs - target_dir: lib - ignore_files: - - .a - dir_mode: 755 - file_mode: 644 - - - source_dir: usr/lib - target_dir: usr/lib - ignore_files: - - .a - dir_mode: 755 - file_mode: 644 - - - source_dir: config - target_dir: etc - - - source_dir: system - target_dir: system - - - source_dir: sbin - target_dir: sbin - - - source_dir: usr/bin - target_dir: usr/bin - - - source_dir: usr/sbin - target_dir: usr/sbin - - - # 创建一个proc空目录 - target_dir: proc - - - target_dir: mnt - - - target_dir: opt - - - target_dir: tmp - - - target_dir: var - - - target_dir: sys - - - source_dir: etc - target_dir: etc - - - source_dir: vendor - target_dir: vendor - - - target_dir: storage - - fs_filemode: - - - file_dir: lib/ld-uClibc-0.9.33.2.so - file_mode: 555 - - - file_dir: lib/ld-2.24.so - file_mode: 555 - - - file_dir: etc/init.cfg - file_mode: 400 - fs_symlink: - - - # 在rootfs/lib下创建软连接ld-musl-arm.so.1 -> libc.so - source: libc.so - link_name: ${fs_dir}/lib/ld-musl-arm.so.1 - - - source: mksh - link_name: ${fs_dir}/bin/sh - - - source: mksh - link_name: ${fs_dir}/bin/shell - fs_make_cmd: - # 使用脚本将rootfs制作为ext4格式的image - - ${root_path}/build/lite/make_rootfs/rootfsimg_linux.sh ${fs_dir} ext4 - - - fs_dir_name: userfs - fs_dirs: - - - source_dir: storage/etc - target_dir: etc - - - source_dir: data - target_dir: data - fs_make_cmd: - - ${root_path}/build/lite/make_rootfs/rootfsimg_linux.sh ${fs_dir} ext4 - - ``` - -7. 编写编译脚本 - - 在产品目录下创建BUILD.gn文件,按产品实际情况编写脚本。以步骤1中的wifiiot为例,BUILD.gn示例如下: - - ``` - group("wifiiot") { # target名称与产品名一致 - deps = [] - # 拷贝init配置 - deps += [ "init_configs" ] - # 将hals加入编译 - deps += [ "hals" ] - # 其他 - ...... - } - ``` - -8. 编译产品。 - - 在代码根目录执行hb set按提示选择新增的产品,然后执行hb build即可启动编译。 - - diff --git "a/zh-cn/device-dev/subsystems/\347\274\226\350\257\221\346\236\204\345\273\272\345\270\270\350\247\201\351\227\256\351\242\230.md" "b/zh-cn/device-dev/subsystems/\347\274\226\350\257\221\346\236\204\345\273\272\345\270\270\350\247\201\351\227\256\351\242\230.md" deleted file mode 100755 index ca00b24285..0000000000 --- "a/zh-cn/device-dev/subsystems/\347\274\226\350\257\221\346\236\204\345\273\272\345\270\270\350\247\201\351\227\256\351\242\230.md" +++ /dev/null @@ -1,121 +0,0 @@ -# 编译构建常见问题 - -- [由于ninja版本问题导致编译失败](#section1019152312222) -- [由于ncurses库缺失导致编译失败](#section21449422618) -- [由于未安装mcopy导致编译失败](#section12477184992615) -- [由于权限问题导致编译失败](#section178451337202716) -- [由于未安装Crypto导致编译失败](#section1241481172819) -- [由于编译环境为shell导致编译失败](#section3691222152919) - -## 由于ninja版本问题导致编译失败 - -- **现象描述:** - - 编译失败,提示“usr/sbin/ninja: invalid option -- w”。 - -- **可能原因:** - - 编译环境中ninja版本太低,不支持--w选项。 - -- **解决办法:** - - 卸载环境中ninja和gn,按照HarmonyOS官网[获取工具](../get-code/获取工具.md)。 - - -## 由于ncurses库缺失导致编译失败 - -- **现象描述:** - - 编译失败,提示“/usr/bin/ld: cannot find -lncurses”。 - -- **可能原因:** - - 编译环境ncurses库缺失。 - -- **解决办法:** - - ``` - sudo apt-get install lib32ncurses5-dev - ``` - - -## 由于未安装mcopy导致编译失败 - -- **现象描述:** - - ​编译失败,提示“line 77: mcopy: command not found”。 - -- **可能原因:** - - 编译环境未安装mcopy。 - -- **解决办法:** - - ``` - ​sudo apt-get install dosfstools mtools - ``` - - -## 由于权限问题导致编译失败 - -- **现象描述:** - - 编译失败,提示“riscv32-unknown-elf-gcc: error trying to exec 'cc1': execvp: No such file or directory”。 - -- ​**可能原因:** - - 当前用户对riscv编译器路径下的文件访问权限不够。 - -- ​**解决办法:** - 1. 查询gcc\_riscv32所在目录。 - - ``` - which riscv32-unknown-elf-gcc - ``` - - 2. 使用chmod命令修改目录权限为755。 - - -## 由于未安装Crypto导致编译失败 - -- **现象描述:** - - 编译失败,提示“No module named 'Crypto'”。 - -- **可能原因:** - - python3未安装Crypto。 - -- **解决办法:** - 1. 查询Python版本号。 - - ``` - python3 --version - ``` - - 2. 需使用python3.7以上版本,然后安装pycryptodome。 - - ``` - sudo pip3 install pycryptodome - ``` - - - -## 由于编译环境为shell导致编译失败 - -- **现象描述:** - - 编译失败:“xx.sh \[: xx unexpected operator”。 - -- **可能原因:** - - 编译环境shell不是bash。 - -- **解决办法:** - - ``` - sudo rm -rf /bin/sh - sudo ln -s /bin/bash /bin/sh - ``` - - diff --git "a/zh-cn/device-dev/subsystems/\347\274\226\350\257\221\346\236\204\345\273\272\346\246\202\350\277\260-0.md" "b/zh-cn/device-dev/subsystems/\347\274\226\350\257\221\346\236\204\345\273\272\346\246\202\350\277\260-0.md" deleted file mode 100755 index 1bd7dd28d9..0000000000 --- "a/zh-cn/device-dev/subsystems/\347\274\226\350\257\221\346\236\204\345\273\272\346\246\202\350\277\260-0.md" +++ /dev/null @@ -1,58 +0,0 @@ -# 编译构建概述 - -- [基本概念](#section175012297491) -- [运作机制](#section193961322175011) -- [约束与限制](#section2029921310472) - -编译构建子系统提供了一个基于gn和ninja的编译构建框架。主要提供以下功能: - -- 构建不同芯片平台的产品。如:Hi3516DV300平台。 - -- 根据产品配置可以按照组件组装打包产品需要的能力。 - -## 基本概念 - -在了解编译构建子系统的能力前,应了解如下基本概念: - -- 平台 - - 开发板和内核的组合,不同平台支持的子系统和组件不同。 - -- 子系统 - - OpenHarmony整体遵从分层设计,从下向上依次为:内核层、系统服务层、框架层和应用层。系统功能按照“系统 \> 子系统 \> 组件”逐级展开,在多设备部署场景下,支持根据实际需求裁剪某些非必要的子系统或组件。子系统是一个逻辑概念,它具体由对应的组件构成。 - -- 组件 - - 对子系统的进一步拆分,可复用的软件单元,它包含源码、配置文件、资源文件和编译脚本;能独立构建,以二进制方式集成,具备独立验证能力的二进制单元。 - -- gn - - Generate ninja的缩写,用于产生ninja文件。 - -- ninja - - ninja是一个专注于速度的小型构建系统。 - - -## 运作机制 - -OpenHarmony侧的编译构建流程主要包括编译命令行解析,调用gn,执行ninja: - -- 命令行解析:解析待编译的产品名称,加载相关配置。 -- 调用gn: 根据命令行解析的产品名称和编译类型,配置编译工具链和全局的编译选项。 -- 执行ninja:启动编译并生成对应的产品版本。 - -## 约束与限制 - -- 需按照[源码获取](../get-code/源码获取.md)指导下载全量源码(采用方式三获取)。 -- 编译环境需要Ubuntu18.04及以上版本。 -- 安装编译所需的程序包。 - - 安装命令: - - ``` - sudo apt-get install binutils git-core gnupg flex bison gperf build-essential zip curl zlib1g-dev gcc-multilib g++-multilib libc6-dev-i386 lib32ncurses5-dev x11proto-core-dev libx11-dev lib32z-dev ccache libgl1-mesa-dev libxml2-utils xsltproc unzip m4 - ``` - - diff --git "a/zh-cn/device-dev/subsystems/\347\274\226\350\257\221\346\236\204\345\273\272\346\246\202\350\277\260.md" "b/zh-cn/device-dev/subsystems/\347\274\226\350\257\221\346\236\204\345\273\272\346\246\202\350\277\260.md" deleted file mode 100755 index 83423cbe1c..0000000000 --- "a/zh-cn/device-dev/subsystems/\347\274\226\350\257\221\346\236\204\345\273\272\346\246\202\350\277\260.md" +++ /dev/null @@ -1,381 +0,0 @@ -# 编译构建概述 - -- [基本概念](#section175012297491) -- [目录结构](#section3267040205617) -- [构建流程](#section193961322175011) -- [组件、芯片解决方案和产品解决方案配置规则](#section1625463413327) - -一个基于gn和ninja的构建系统,以支持OpenHarmony组件化开发为目标,提供以下基本功能: - -- 支持按组件拼装产品并编译。 - -- 独立构建芯片解决方案厂商源码。 -- 独立构建单个组件。 - -## 基本概念 - -在使用编译构建子系统前,应了解如下基本概念: - -- 子系统 - - 子系统是一个逻辑概念,它由一个或多个具体的组件组成。OpenHarmony整体遵从分层设计,从下向上依次为:内核层、系统服务层、框架层和应用层。系统功能按照“系统 \> 子系统 \> 组件”逐级展开,在多设备部署场景下,支持根据实际需求裁剪某些非必要的子系统或组件。 - - -- 组件 - - 系统最小的可复用、可配置、可裁剪的功能单元。组件具备目录独立可并行开发、可独立编译、可独立测试的特征。 - -- gn - - Generate ninja的缩写,用于产生ninja文件。 - -- ninja - - ninja是一个专注于速度的小型构建系统。 - -- hb - - OpenHarmony的命令行工具,用来执行编译命令。 - - -## 目录结构 - -``` -build/lite -├── components # 组件描述文件 -├── figures # readme中的图片 -├── hb # hb pip安装包源码 -├── make_rootfs # 文件系统镜像制作脚本 -├── config # 编译配置项 -│ ├── component # 组件相关的模板定义 -│ ├── kernel # 内核相关的编译配置 -│ └── subsystem # 子系统编译配置 -├── platform # ld脚本 -├── testfwk # 测试编译框架 -└── toolchain # 编译工具链配置,包括:编译器路径、编译选项、链接选项等 -``` - -## 构建流程 - -编译构建流程如[图1 ](#fig9744112715161)所示,主要分设置和编译两步: - -**图 1** 编译构建流程 -![](figures/编译构建流程.jpg "编译构建流程") - -1. hb set: 设置OpenHarmony源码目录和要编译的产品。 -2. hb build: 编译产品、开发板或者组件。编译主要过程如下: - - 读取编译配置:根据产品选择的开发板,读取开发板config.gni文件内容,主要包括编译工具链、编译链接命令和选项等。 - - 调用gn:调用gn gen命令,读取产品配置生成产品解决方案out目录和ninja文件。 - - 调用ninja:调用ninja -C out/board/product启动编译。 - - 系统镜像打包:将组件编译产物打包,设置文件属性和权限,制作文件系统镜像。 - - -## 组件、芯片解决方案和产品解决方案配置规则 - -为了实现芯片解决方案、产品解决方案与OpenHarmony是解耦的、可插拔的,组件、芯片解决方案和产品解决方案的路径、目录树和配置需遵循一定的规则,具体如下: - -- **组件** - -组件源码路径命名规则为:_\{领域\}/\{子系统\}/\{组件\}_,组件目录树规则如下: - -``` -component -├── interfaces -│ ├── innerkits # 系统内接口,组件间使用 -│ └── kits # 应用接口,应用开发者使用 -├── frameworks # framework实现 -├── services # service实现 -└── BUILD.gn # 组件编译脚本 -``` - -组件的名称、源码路径、功能简介、是否必选、编译目标、RAM、ROM、编译输出、已适配的内核、可配置的特性和依赖等属性定义在build/lite/components目录下对应子系统的json文件中,新增组件时需要在对应子系统json文件中添加相应的组件定义。产品所配置的组件必须在某个子系统中被定义过,否则会校验失败。 - -以泛sensor子系统的sensor服务组件为例,组件属性定义描述文件字段说明如下: - -``` -{ - "components": [ - { - "component": "sensor_lite", # 组件名称 - "description": "Sensor services", # 组件一句话功能描述 - "optional": "true", # 组件是否为最小系统必选 - "dirs": [ # 组件源码路径 - "base/sensors/sensor_lite" - ], - "targets": [ # 组件编译入口 - "//base/sensors/sensor_lite/services:sensor_service" - ], - "rom": "92KB", # 组件ROM值 - "ram": "~200KB", # 组件RAM估值 - "output": [ "libsensor_frameworks.so" ], # 组件编译输出 - "adapted_kernel": [ "liteos_a" ], # 组件已适配的内核 - "features": [], # 组件可配置的特性 - "deps": { - "components": [ # 组件依赖的其他组件 - "samgr_lite", - "ipc_lite" - - ], - "third_party": [ # 组件依赖的三方开源软件 - "bounds_checking_function" - ] - } - } - ] -} -``` - -组件的编译脚本语言为gn,gn的基本用法请见[gn快速入门](https://gn.googlesource.com/gn/+/master/docs/quick_start.md)。组件即为gn定义的编译目标,可以为静态库、动态库、可执行文件或group。组件BUILD.gn的编写建议如下: - -1)编译目标名称与组件一致。 - -2)组件对外可配置的特性变量需声明在该组件BUILD.gn中,特性变量命名规则:ohos\_\{subsystem\}\_\{component\}\_\{feature\}。特性在组件描述中也需要同步定义,在产品配置文件config.json中按需配置。 - -3)宏定义规则:OHOS\_\{SUBSYSTEM\}\_\{COMPONENT\}\_\{FEATURE\} - -以图形的UI组件为例,foundation/graphic/ui/BUILD.gn文件如下: - -``` - # 声明组件可配置的特性 - declare_args() { - enable_ohos_graphic_ui_animator = false # 动效特性开关 - ohos_ohos_graphic_ui_font = "vector" # 可配置的字体类型,vector或者bitmap - } - - # 组件基础功能 - shared_library("base") { - sources = [ - ...... - ] - include_dirs = [ - ...... - ] - } - - # 仅在animator开启时编译 - if(enable_ohos_graphic_ui_animator ) { - shared_library("animator") { - sources = [ - ...... - ] - include_dirs = [ - ...... - ] - deps = [ :base ] - } - } - ...... - # target名称建议与组件名称一致, 组件target类型可以是executable(bin文件),shared_library(动态库.so),static_library(静态库.a),group等等 - executable("ui") { - deps = [ - ":base" - ] - - # animator特性由产品配置 - if(enable_ohos_graphic_ui_animator ) { - deps += [ - "animator" - ] - } - } -``` - -- **芯片解决方案** - -芯片解决方案是指基于某款开发板的完整解决方案,包含驱动、设备侧接口适配、开发板sdk等。芯片解决方案是一个特殊的组件,源码路径规则为:_device/\{芯片解决方案厂商\}/\{开发板\}_。芯片解决方案组件会随产品选择的开发板默认编译。芯片解决方案目录树规则如下: - -``` -device -└── company # 芯片解决方案厂商 - └── board # 开发板名称 - ├── BUILD.gn # 编译脚本 - ├── hals # OS南向接口适配 - ├── linux # 可选,linux内核版本 - │ └── config.gni # linux版本编译配置 - └── liteos_a # 可选,liteos内核版本 - └── config.gni # liteos_a版本编译配置 -``` - -config.gni为开发板编译相关的配置。编译时会采用该配置文件中的参数选择编译相应的OS组件,编译阶段系统全局可见。关键字段介绍如下: - -``` -kernel_type: 开发板使用的内核类型,例如:“liteos_a”, “liteos_m”, “linux”。 -kernel_version: 开发使用的内核版本,例如:“4.19”。 -board_cpu: 开发板CPU类型,例如:“cortex-a7”, “riscv32”。 -board_arch: 开发芯片arch, 例如: “armv7-a”, “rv32imac”。 -board_toolchain: 开发板自定义的编译工具链名称,例如:“gcc-arm-none-eabi”。若为空,则使用默认为ohos-clang。 -board_toolchain_prefix:编译工具链前缀,例如:“gcc-arm-none-eabi”。 -board_toolchain_type: 编译工具链类型,目前支持gcc和clang。例如:“gcc” ,“clang”。 -board_cflags: 开发板配置的c文件编译选项。 -board_cxx_flags: 开发板配置的cpp文件编译选项。 -board_ld_flags: 开发板配置的链接选项。 -``` - -- **产品解决方案** - -产品解决方案为基于开发板的完整产品,主要包含产品对OS的适配、组件拼装配置、启动配置和文件系统配置等。源码路径规则为:_vendor/\{产品解决方案厂商\}/\{产品名称\}。_产品解决方案也是一个特殊的组件,目录树规则如下: - -``` -vendor -└── company # 产品解决方案厂商 - ├── product # 产品名称 - │ ├── init_configs - │ │ ├── etc # init进程启动配置(可选,仅linux内核需要) - │ │ └── init.cfg # 系统服务启动配置 - │ ├── hals # 产品解决方案OS适配 - │ ├── BUILD.gn # 产品编译脚本 - │ └── config.json # 产品配置文件 - │ └── fs.yml # 文件系统打包配置 - └── ...... -``` - -新增产品须按如上的规则创建目录和文件,编译构建系统将按该规则扫描已配置的产品。关键的目录和文件详细介绍如下: - -1. vendor/company/product/init\_configs/etc - - 该文件夹中包含rcS脚本,Sxxx脚本和fstab脚本,init进程在启动系统服务之前执行这些脚本。执行的流程为“rcS-\>fstab-\>S00-xxx“,Sxxx脚本中的内容与开发板和产品需要有关,主要包括设备节点的创建、创建目录、扫描设备节点、修改文件权限等等。这些文件在产品编译的BUILD.gn中按需拷贝到产品out目录中,最终打包到rootfs镜像中。 - -2. vendor/company/product/init\_configs/init.cfg - - init进程启动服务的配置文件,当前支持解析的命令有: - - 1\) start: 启动某个服务 - - 2\) mkdir: 创建文件夹 - - 3)chmod: 修改指定路径/文件的权限 - - 4\) chown: 修改指定路径/文件的属组 - - 5\) mount: 挂载命令 - - 该文件中的各个字段的解释如下: - - ``` - { - "jobs" : [{ # job数组,一个job对应一个命令集合。job的执行顺序:pre-init -> init -> post-init。 - "name" : "pre-init", - "cmds" : [ - "mkdir /storage/data", # 创建目录 - "chmod 0755 /storage/data", # 修改权限,权限值的格式为0xxx, 如0755 - "mkdir /storage/data/log", - "chmod 0755 /storage/data/log", - "chown 4 4 /storage/data/log", # 修改属组,第一个数字为uid, 第二个数字为gid - ...... - "mount vfat /dev/mmcblock0 /sdcard rw,umask=000" # 挂载,格式为: mount [文件系统类型] [source] [target] [flags] [data] - # 其中flags仅支持:nodev、noexec、nosuid和rdonly - ] - }, { - "name" : "init", - "cmds" : [ # 按cmds数组顺序启动启动服务 - "start shell", # 注意:start与服务名称之间有且只有一个空格 - ...... - "start service1" - ] - }, { - "name" : "post-init", # 最后别执行的job, init进程启动完成后的处理(如驱动初始化后再mount设备) - "cmds" : [] - } - ], - "services" : [{ # service数组,一个service对应一个进程 - "name" : "shell", # 服务名称 - "path" : ["/sbin/getty", "-n", "-l", "/bin/sh", "-L", "115200", "ttyS000", "vt100"], # 可执行文件全路径,path必须为第一个元素 - "uid" : 0, # 进程的uid,须与二进制文件的uid保持一致 - "gid" : 0, # 进程的gid,须与二进制文件的gid保持一致 - "once" : 0, # 是否为一次性进程,1:进程退出后,init不在重新拉起。0:常驻进程,进程若退出,init将重新拉起 - "importance" : 0, # 是否为关键进程,1:是关键进程,若进程退出,init将会重启单板。0:非关键进程,若进程退出,init不会重启单板 - "caps" : [4294967295] - }, - ...... - ] - } - ``` - -3. vendor/company/product/init\_configs/hals - - 解决方案厂商对OS的适配,需要实现的接口请见各个组件的readme说明文档。 - -4. vendor/company/product/config.json - - config.json为编译构建的主入口,包含了开发板、OS组件和内核等配置信息。以基于hispark\_taurus开发板的ipcamera产品为例,配置文件如下: - - ``` - { - "product_name": "ipcamera", # 产品名称 - "ohos_version": "OpenHarmony 1.0", # 选择的OS版本 - "device_company": "hisilicon", # 芯片厂商 - "board": "hispark_taurus", # 开发板名称 - "kernel_type": "liteos_a", # 选择的内核类型 - "kernel_version": "3.0.0", # 选择的内核版本 - "subsystems": [ - { - "subsystem": "aafwk", # 选择的子系统 - "components": [ - { "component": "ability", "features":[ "enable_ohos_appexecfwk_feature_ability = true" ] } # 选择的组件和组件特性配置 - ] - }, - { - ...... - } - ...... - 更多子系统和组件 - } - } - ``` - -5. vendor/company/product/fs.yml - - 该文件用于配置文件系统镜像制作过程,将编译产物打包成文件系统镜像,比如用户态根文件系统rootfs.img和可读写的userfs.img。它由多个列表组成,每个列表对应一个文件系统。字段说明如下: - - ``` - fs_dir_name: 必填,声明文件系统文件名, 如rootfs、userfs - fs_dirs: 选填,配置out下文件目录与文件系统文件目录的映射关系,每个文件目录对应一个列表 - source_dir: 选填,out下目标文件目录,若缺失则将根据target_dir在文件系统下创建空目录 - target_dir: 必填,文件系统下对应文件目录 - ignore_files:选填,声明拷贝忽略文件 - dir_mode: 选填,文件目录权限,默认755 - file_mode: 选填,该文件目录下所有文件的权限,默认555 - fs_filemode: 选填,配置需要特殊声明权限的文件,每个文件对应一个列表 - file_dir: 必填,文件系统下具体文件路径 - file_mode: 必填,文件权限声明 - fs_symlink: 选填,配置文件系统软连接 - fs_make_cmd: 必填,配置需要制作文件系统脚本,OS提供的脚本在build/lite/make_rootfs下, 支持linux,liteos内核和ext4、jffs2、vfat格式。也支持芯片解决方案厂商自定义。 - fs_attr: 选填,根据配置项动态调整文件系统 - ``` - - 其中fs\_symlink、fs\_make\_cmd字段支持以下变量: - - - $\{root\_path\} - - 代码根目录,对应gn的$\{ohos\_root\_path\} - - - $\{out\_path\} - - 产品out目录,对应gn的$\{root\_out\_dir\} - - - $\{fs\_dir\} - - 文件系统目录,由以下变量拼接而成 - - - $\{root\_path\} - - $\{fs\_dir\_name\} - - - >![](public_sys-resources/icon-note.gif) **说明:** - >fs.yml是可选的,对于没有文件系统的设备可不配置。 - -6. vendor/company/product/BUILD.gn - - 产品编译的入口,主要用于编译解决方案厂商源码和拷贝启动配置文件。如果某个产品被选择为要编译的产品,那么对应产品目录下的BUILD.gn会默认编译。一个典型的产品编译BUILD.gn应该如下: - - ``` - group("product") { # target名称需与product名称即三级目录名称一致 - deps = [] - # 拷贝init配置 - deps += [ "init_configs" ] - # 其他 - ...... - } - ``` - - diff --git "a/zh-cn/device-dev/subsystems/\350\275\273\351\207\217\345\222\214\345\260\217\345\236\213\347\263\273\347\273\237\347\274\226\350\257\221\346\236\204\345\273\272\346\214\207\345\257\274.md" "b/zh-cn/device-dev/subsystems/\350\275\273\351\207\217\345\222\214\345\260\217\345\236\213\347\263\273\347\273\237\347\274\226\350\257\221\346\236\204\345\273\272\346\214\207\345\257\274.md" deleted file mode 100755 index e85c33895c..0000000000 --- "a/zh-cn/device-dev/subsystems/\350\275\273\351\207\217\345\222\214\345\260\217\345\236\213\347\263\273\347\273\237\347\274\226\350\257\221\346\236\204\345\273\272\346\214\207\345\257\274.md" +++ /dev/null @@ -1,9 +0,0 @@ -# 轻量和小型系统编译构建指导 - -- **[编译构建概述](编译构建概述.md)** - -- **[编译构建使用指导](编译构建使用指导.md)** - -- **[编译构建常见问题](编译构建常见问题.md)** - - diff --git "a/zh-cn/device-dev/subsystems/\351\237\263\350\247\206\351\242\221.md" "b/zh-cn/device-dev/subsystems/\351\237\263\350\247\206\351\242\221.md" deleted file mode 100755 index 5f32b5fe50..0000000000 --- "a/zh-cn/device-dev/subsystems/\351\237\263\350\247\206\351\242\221.md" +++ /dev/null @@ -1,9 +0,0 @@ -# 音视频 - -- **[音视频开发概述](音视频开发概述.md)** - -- **[音视频播放开发指导](音视频播放开发指导.md)** - -- **[音视频录制开发指导](音视频录制开发指导.md)** - - diff --git "a/zh-cn/device-dev/\345\257\274\350\257\273.md" "b/zh-cn/device-dev/\345\257\274\350\257\273.md" index c49e621b91..44b738359b 100644 --- "a/zh-cn/device-dev/\345\257\274\350\257\273.md" +++ "b/zh-cn/device-dev/\345\257\274\350\257\273.md" @@ -48,49 +48,49 @@ OpenHarmony也提供了一系列可选的系统组件,方便设备开发者按

    整体认知OpenHarmony

    - +

    获取开发资源

    准备开发前相关资源

    - +

    快速入门

    快速熟悉OpenHarmony环境搭建、编译、烧录、调测、运行。

    -

    轻量和小型系统入门

    +

    轻量和小型系统快速入门

    基础能力使用

    使用OpenHarmony提供的基础能力

    - +

    进阶开发

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

    - +

    移植适配

    • 针对特定芯片做移植适配
    • 对三方库进行移植适配
    - +

    贡献组件

    OpenHarmony贡献功能组件

    - +

    参考

    @@ -118,49 +118,49 @@ OpenHarmony也提供了一系列可选的系统组件,方便设备开发者按

    整体认知OpenHarmony

    - +

    获取开发资源

    准备开发前相关资源

    - +

    快速入门

    快速熟悉OpenHarmony环境搭建、编译、烧录、调测、运行。

    -

    标准系统入门

    +

    标准系统快速入门

    基础能力使用

    使用OpenHarmony提供的基础能力

    - +

    进阶开发

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

    - +

    移植适配

    对三方库进行移植适配

    -

    三方库移植指导

    +

    三方库移植指导

    贡献组件

    OpenHarmony贡献功能组件

    - +

    参考

    diff --git a/zh-cn/readme.md b/zh-cn/readme.md index 5d67c93e32..15528919ed 100644 --- a/zh-cn/readme.md +++ b/zh-cn/readme.md @@ -4,54 +4,55 @@ ## 文档目录结构 -- [Openharmony概述](OpenHarmony-Overview_zh.md) -- 轻量和小型系统开发指导(参考内存<128MB) +- [Openharmony概述](OpenHarmony-Overview_zh.md) +- 轻量和小型系统开发指导(参考内存<128MB) - 设备开发 - overview:[设备开发导读](device-dev/导读.md) - quick-start:[快速入门](device-dev/quick-start/Readme-CN.md)(搭建环境、获取源码、编译、烧录等) - - 开发基础能力 - - Kernel:[轻量和小型系统内核](device-dev/kernel/轻量和小型系统内核.md) + - Basic Capability:开发基础能力 + - Kernel:[轻量和小型系统内核](device-dev/kernel/kernel-lite.md) - Drivers:[驱动](device-dev/driver/Readme-CN.md) - Subsystems:[子系统](device-dev/subsystems/Readme-CN.md)(编译构建、图形图像、DFX、XTS等子系统) - Security:[隐私与安全](device-dev/security/Readme-CN.md) - - guide:[开发示例](device-dev/guide/Readme-CN.md) - - [WLAN连接类产品](device-dev/guide/WLAN连接类产品.md)(LED外设控制、集成三方SDK) - - [无屏摄像头类产品](device-dev/guide/无屏摄像头类产品.md)(摄像头控制) - - [带屏摄像头类产品](device-dev/guide/带屏摄像头类产品.md)(屏幕和摄像头控制、视觉应用开发) + - guide:开发示例 + - [WLAN连接类产品](device-dev/guide/device-wifi.md)(LED外设控制、集成三方SDK) + - [无屏摄像头类产品](device-dev/guide/device-iotcamera-control.md)(摄像头控制) + - [带屏摄像头类产品](device-dev/guide/device-camera.md)(屏幕和摄像头控制、视觉应用开发) - - porting:[移植适配](device-dev/porting/Readme-CN.md) - - [三方芯片移植指导](device-dev/porting/三方芯片移植指导.md) - - [三方库移植指导](device-dev/porting/三方库移植指导.md) + - porting:移植适配 + - [三方库移植指导](device-dev/porting/transplant-thirdparty.md) + - [轻量系统芯片移植指导](device-dev/porting/transplant-minichip.md) + - [小型系统芯片移植指导](device-dev/porting/transplant-smallchip.md) - - bundles:[组件开发](device-dev/bundles/Readme-CN.md) - - [组件开发规范](device-dev/bundles/组件开发规范.md) - - [组件开发指南](device-dev/bundles/组件开发指南.md) - - [组件开发示例](device-dev/bundles/组件开发示例.md) + - bundles:组件开发 + - [组件开发规范](device-dev/bundles/bundles-standard-rules.md) + - [组件开发指南](device-dev/bundles/bundles-guide.md) + - [组件开发示例](device-dev/bundles/bundles-demo.md) -- 标准系统开发指导(参考内存≥128MB) +- 标准系统开发指导(参考内存≥128MB) - 设备开发 - overview:[设备开发导读](device-dev/导读.md) - - quick-start:[快速入门](device-dev/quick-start/Readme-CN.md)(搭建环境、获取源码、编译、烧录等) - - 开发基础能力 - - Kernel:[标准系统内核](device-dev/kernel/标准系统内核.md) + - quick-start:[快速入门](device-dev/quick-start/quickstart-standard.md)(搭建环境、获取源码、编译、烧录等) + - Basic Capability:开发基础能力 + - Kernel:[标准系统内核](device-dev/kernel/kernel-standard.md) - Drivers:[驱动](device-dev/driver/Readme-CN.md) - Subsystems:[子系统](device-dev/subsystems/Readme-CN.md)(编译构建、图形图像、DFX、XTS等子系统) - Security:[隐私与安全](device-dev/security/Readme-CN.md) - - guide:[开发示例](device-dev/guide/Readme-CN.md) - - [时钟应用](device-dev/guide/时钟应用开发示例.md) - - [平台驱动](device-dev/guide/平台驱动开发示例.md) - - [外设驱动](device-dev/guide/外设驱动开发示例.md) + - guide:开发示例 + - [时钟应用](device-dev/guide/device-clock-guide.md) + - [平台驱动](device-dev/guide/device-drive-demo.md) + - [外设驱动](device-dev/guide/device-outerdrive-demo.md) - - porting:[移植适配](device-dev/porting/Readme-CN.md) + - porting:移植适配 - [三方库移植指导](device-dev/porting/三方库移植指导.md) + [三方库移植指导](device-dev/porting/transplant-thirdparty.md) - - bundles:[组件开发](device-dev/bundles/Readme-CN.md) - - [组件开发规范](device-dev/bundles/组件开发规范.md) - - [组件开发指南](device-dev/bundles/组件开发指南.md) - - [组件开发示例](device-dev/bundles/组件开发示例.md) + - bundles:组件开发 + - [组件开发规范](device-dev/bundles/bundles-standard-rules.md) + - [组件开发指南](device-dev/bundles/bundles-guide.md) + - [组件开发示例](device-dev/bundles/bundles-demo.md) - 应用开发 @@ -61,7 +62,8 @@ - media:[媒体](application-dev/media/Readme-CN.md) - connectivity:[网络与连接](application-dev/connectivity/Readme-CN.md) - js-reference:[JS参考规范](application-dev/js-reference/Readme-CN.md) -- glossary:[术语](device-dev/glossary/术语.md) +- 许可证及版权信息检查工具:[开源合规审查工具](https://gitee.com/openharmony-sig/tools_oat) +- glossary:[术语](device-dev/glossary/glossary.md) ## 版本更新 -- GitLab

    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 FKL8U%JnaAg diff --git a/zh-cn/device-dev/kernel/format.md b/zh-cn/device-dev/kernel/format.md deleted file mode 100755 index ecddf4e031..0000000000 --- a/zh-cn/device-dev/kernel/format.md +++ /dev/null @@ -1,69 +0,0 @@ -# format - -- [命令功能](#section1922331919169) -- [命令格式](#section249226169) -- [参数说明](#section985173416177) -- [使用指南](#section1510162714162) -- [使用实例](#section25691431161611) -- [输出说明](#section17368112365920) - -## 命令功能 - -format指令用于格式化磁盘。 - -## 命令格式 - -format <_dev\_inodename_\> <_sectors_\> <_option_\> \[_label_\] - -## 参数说明 - -**表 1** 参数说明 - - - - - - - - - - - - - - - - - - - -

    参数

    -

    参数说明

    -

    dev_inodename

    -

    设备名。

    -

    sectors

    -

    分配的单元内存或扇区大小,如果输入0表示参数为空。(取值必须为0或2的幂,fat32下最大值为128,取值0表示自动选择合适的簇大小,不同size的分区,可用的簇大小范围不同,错误的簇大小指定可能导致格式化失败)。

    -

    option

    -
    格式化选项,用来选择文件系统的类型,有如下几种参数选择:
    • 0x01:FMT_FAT
    • 0x02:FMT_FAT32
    • 0x07:FMT_ANY
    • 0x08:FMT_ERASE (USB不支持该选项)
    -
    -

    传入其他值皆为非法值,将由系统自动选择格式化方式。若格式化U盘时低格位为 1,会出现错误打印。

    -

    label

    -

    该参数为可选参数,输入值应为字符串,用来指定卷标名。当输入字符串"null"时,则把之前设置的卷标名清空。

    -
    - -## 使用指南 - -- format指令用于格式化磁盘,设备名可以在dev目录下查找。format时必须安装存储卡。 -- format只能格式化U盘、sd和mmc卡,对Nand flash和Nor flash格式化不起作用。 -- sectors参数必须传入合法值,传入非法参数可能引发异常。 - -## 使用实例 - -举例:输入format /dev/mmcblk0 128 2 - -## 输出说明 - -结果如下 - -![](figures/zh-cn_image_0000001052370307.png) - diff --git a/zh-cn/device-dev/kernel/free.md b/zh-cn/device-dev/kernel/free.md deleted file mode 100755 index 56734efb79..0000000000 --- a/zh-cn/device-dev/kernel/free.md +++ /dev/null @@ -1,119 +0,0 @@ -# free - -- [命令功能](#section175151514841) -- [命令格式](#section8488721749) -- [参数说明](#section27272181949) -- [使用指南](#section148661259410) -- [使用实例](#section68081530242) -- [输出说明](#section171235517543) - -## 命令功能 - -free命令可显示系统内存的使用情况,同时显示系统的text段、data段、rodata段、bss段大小。 - -## 命令格式 - -free \[_-k | -m_\] - -## 参数说明 - -**表 1** 参数说明 - - - - - - - - - - - - - - - - - - - - -

    参数

    -

    参数说明

    -

    取值范围

    -

    无参数

    -

    以Byte为单位显示。

    -

    N/A

    -

    -k

    -

    以KB为单位显示。

    -

    N/A

    -

    -m

    -

    以MB为单位显示。

    -

    N/A

    -
    - -## 使用指南 - -无。 - -## 使用实例 - -举例:分别输入free、free -k、free -m. - -## 输出说明 - -**图 1** 以三种方式显示内存使用情况 -![](figures/以三种方式显示内存使用情况.png "以三种方式显示内存使用情况") - -**表 2** 输出说明 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    输出

    -

    说明

    -

    total

    -

    表示系统动态内存池总量。

    -

    used

    -

    表示已使用内存总量。

    -

    free

    -

    表示未被分配的内存大小。

    -

    heap

    -

    表示已分配堆大小。

    -

    text

    -

    表示代码段大小。

    -

    data

    -

    表示数据段大小。

    -

    rodata

    -

    表示只读数据段大小。

    -

    bss

    -

    表示未初始化全局变量占用内存大小。

    -
    - diff --git a/zh-cn/device-dev/kernel/hwi.md b/zh-cn/device-dev/kernel/hwi.md deleted file mode 100755 index d2ab70ddb3..0000000000 --- a/zh-cn/device-dev/kernel/hwi.md +++ /dev/null @@ -1,94 +0,0 @@ -# hwi - -- [命令功能](#section445335110416) -- [命令格式](#section1795712553416) -- [参数说明](#section92544592410) -- [使用指南](#section104151141252) -- [使用实例](#section11545171957) -- [输出说明](#section075617368542) - -## 命令功能 - -hwi命令查询当前中断信息 - -## 命令格式 - -hwi - -## 参数说明 - -无。 - -## 使用指南 - -- 输入hwi即显示当前中断号、中断次数及注册中断名称。 -- 若开关LOSCFG\_CPUP\_INCLUDE\_IRQ打开,则还会显示各个中断的处理时间(cycles)、CPU占用率以及中断类型。 - -## 使用实例 - -举例:输入hwi - -## 输出说明 - -1. 显示中断信息(LOSCFG\_CPUP\_INCLUDE\_IRQ关闭) - - ![](figures/zh-cn_image_0000001053826366.png) - -2. 显示中断信息(LOSCFG\_CPUP\_INCLUDE\_IRQ打开) - - ![](figures/zh-cn_image_0000001052810304.png) - - **表 1** 输出说明 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    输出

    -

    说明

    -

    InterruptNo

    -

    中断号。

    -

    Count

    -

    中断次数。

    -

    Name

    -

    注册中断名称。

    -

    CYCLECOST

    -

    中断的处理时间(cycles)。

    -

    CPUUSE

    -

    CPU占用率。

    -

    CPUUSE10s

    -

    最近10s CPU占用率。

    -

    CPUUSE1s

    -

    最近1s CPU占用率。

    -

    mode

    -

    中断类型:

    -
    • normal: 非共享中断。
    • shared: 共享中断。
    -
    - - diff --git a/zh-cn/device-dev/kernel/kernel-lite-basic-mini-time.md b/zh-cn/device-dev/kernel/kernel-lite-basic-mini-time.md new file mode 100644 index 0000000000..1cded0a67f --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-basic-mini-time.md @@ -0,0 +1,7 @@ +# 时间管理 + +- **[基本概念](kernel-lite-mini-basic-time-basic.md)** + +- **[开发指导](kernel-lite-mini-basic-time-guide.md)** + + diff --git "a/zh-cn/device-dev/kernel/\345\206\205\346\240\270\347\274\226\347\240\201\350\247\204\350\214\203.md" b/zh-cn/device-dev/kernel/kernel-lite-mini-app-code.md similarity index 100% rename from "zh-cn/device-dev/kernel/\345\206\205\346\240\270\347\274\226\347\240\201\350\247\204\350\214\203.md" rename to zh-cn/device-dev/kernel/kernel-lite-mini-app-code.md diff --git a/zh-cn/device-dev/kernel/kernel-lite-mini-app-data-list.md b/zh-cn/device-dev/kernel/kernel-lite-mini-app-data-list.md new file mode 100644 index 0000000000..d219cc86b0 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-mini-app-data-list.md @@ -0,0 +1,191 @@ +# 双向链表 + +- [基本概念](#section1990715203418) +- [功能说明](#section848334511411) +- [开发流程](#section01781261552) +- [编程实例](#section67569495514) + - [实例描述](#section48761994551) + - [示例代码](#section1280202685519) + - [结果验证](#section5811249105512) + + +## 基本概念 + +双向链表是指含有往前和往后两个方向的链表,即每个结点中除存放下一个节点指针外,还增加一个指向前一个节点的指针。其头指针head是唯一确定的。 + +从双向链表中的任意一个结点开始,都可以很方便地访问它的前驱结点和后继结点,这种数据结构形式使得双向链表在查找时更加方便,特别是大量数据的遍历。由于双向链表具有对称性,能方便地完成各种插入、删除等操作,但需要注意前后方向的操作。 + +## 功能说明 + +双向链表模块为用户提供下面几种功能,接口详细信息可以查看API参考。 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    功能分类

    +

    接口名

    +

    描述

    +

    初始化链表

    +

    LOS_ListInit

    +

    将指定双向链表节点初始化为双向链表

    +

    LOS_DL_LIST_HEAD

    +

    定义一个双向链表节点并以该节点初始化为双向链表

    +

    增加节点

    +

    LOS_ListAdd

    +

    将指定节点插入到双向链表头端

    +

    LOS_ListTailInsert

    +

    将指定节点插入到双向链表尾端

    +

    删除节点

    +

    LOS_ListDelete

    +

    将指定节点从链表中删除

    +

    LOS_ListDelInit

    +

    将指定节点从链表中删除,并使用该节点初始化链表

    +

    判断双向链表是否为空

    +

    LOS_ListEmpty

    +

    判断链表是否为空

    +

    获取结构体信息

    +

    LOS_DL_LIST_ENTRY

    +

    获取包含链表的结构体地址,接口的第一个入参表示的是链表中的某个节点,第二个入参是要获取的结构体名称,第三个入参是链表在该结构体中的名称

    +

    LOS_OFF_SET_OF

    +

    获取指定结构体内的成员相对于结构体起始地址的偏移量

    +

    遍历双向链表

    +

    LOS_DL_LIST_FOR_EACH

    +

    遍历双向链表

    +

    LOS_DL_LIST_FOR_EACH_SAFE

    +

    遍历双向链表,并存储当前节点的后继节点用于安全校验

    +

    遍历包含双向链表的结构体

    +

    LOS_DL_LIST_FOR_EACH_ENTRY

    +

    遍历指定双向链表,获取包含该链表节点的结构体地址

    +

    LOS_DL_LIST_FOR_EACH_ENTRY_SAFE

    +

    遍历指定双向链表,获取包含该链表节点的结构体地址,并存储包含当前节点的后继节点的结构体地址

    +
    + +## 开发流程 + +双向链表的典型开发流程: + +1. 调用LOS\_ListInit/LOS\_DL\_LIST\_HEAD初始双向链表。 +2. 调用LOS\_ListAdd向链表插入节点。 +3. 调用LOS\_ListTailInsert向链表尾部插入节点。 +4. 调用LOS\_ListDelete删除指定节点。 +5. 调用LOS\_ListEmpty判断链表是否为空。 +6. 调用LOS\_ListDelInit删除指定节点并以此节点初始化链表。 + +>![](../public_sys-resources/icon-note.gif) **说明:** +>- 需要注意节点指针前后方向的操作。 +>- 链表操作接口,为底层接口,不对入参进行判空,需要使用者确保传参合法。 +>- 如果链表节点的内存是动态申请的,删除节点时,要注意释放内存。 + +## 编程实例 + +### 实例描述 + +本实例实现如下功能: + +1. 初始化双向链表。 +2. 增加节点。 +3. 删除节点。 +4. 测试操作是否成功。 + +### 示例代码 + +示例代码如下: + +``` +#include "stdio.h" +#include "los_list.h" + +static UINT32 ListSample(VOID) +{ + LOS_DL_LIST listHead = {NULL,NULL}; + LOS_DL_LIST listNode1 = {NULL,NULL}; + LOS_DL_LIST listNode2 = {NULL,NULL}; + + //首先初始化链表 + printf("Initial head\n"); + LOS_ListInit(&listHead); + + //添加节点1和节点2,并校验他们的相互关系 + LOS_ListAdd(&listHead, &listNode1); + if (listNode1.pstNext == &listHead && listNode1.pstPrev == &listHead) { + printf("Add listNode1 success\n"); + } + + LOS_ListTailInsert(&listHead, &listNode2); + if (listNode2.pstNext == &listHead && listNode2.pstPrev == &listNode1) { + printf("Tail insert listNode2 success\n"); + } + + //删除两个节点 + LOS_ListDelete(&listNode1); + LOS_ListDelete(&listNode2); + + //确认链表为空 + if (LOS_ListEmpty(&listHead)) { + printf("Delete success\n"); + } + + return LOS_OK; +} +``` + +### 结果验证 + +编译运行得到的结果为: + +``` +Initial head +Add listNode1 success +Tail insert listNode2 success +Delete success +``` + diff --git a/zh-cn/device-dev/kernel/kernel-lite-mini-app-data.md b/zh-cn/device-dev/kernel/kernel-lite-mini-app-data.md new file mode 100644 index 0000000000..78fda11861 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-mini-app-data.md @@ -0,0 +1,5 @@ +# 基本数据结构 + +- **[双向链表](kernel-lite-mini-app-data-list.md)** + + diff --git a/zh-cn/device-dev/kernel/kernel-lite-mini-app-lib-cmsis.md b/zh-cn/device-dev/kernel/kernel-lite-mini-app-lib-cmsis.md new file mode 100644 index 0000000000..fb77b08629 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-mini-app-lib-cmsis.md @@ -0,0 +1,487 @@ +# CMSIS支持 + +- [基本概念](#section131091144111615) +- [开发指导](#section57653573161) + - [接口说明](#section1795910417173) + - [开发流程](#section48301225131720) + - [编程实例](#section524434761713) + + +## 基本概念 + +[CMSIS](https://developer.arm.com/tools-and-software/embedded/cmsis)是Cortex Microcontroller Software Interface Standard(Cortex微控制器软件接口标准)的缩写,是对于那些基于ARM Cortex处理器的微控制器独立于供应商的硬件抽象层。它包含多个组件层,其中之一是RTOS层,该层定义了一套通用及标准化的RTOS API接口,减少了应用开发者对特定RTOS的依赖,方便用户软件的移植重用。该套API有2个版本,分别为版本1(CMSIS-RTOS v1)和版本2(CMSIS-RTOS v2),OpenHarmony LiteOS-M仅提供其版本2的实现。 + +## 开发指导 + +### 接口说明 + +CMSIS-RTOS v2提供下面几种功能,接口详细信息可以查看API参考。 + +**表 1** CMSIS-RTOS v2接口 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    功能分类

    +

    接口名

    +

    描述

    +

    内核信息与控制

    +

    osKernelGetInfo

    +

    获取RTOS内核信息。

    +

    osKernelGetState

    +

    获取当前的RTOS内核状态。

    +

    osKernelGetSysTimerCount

    +

    获取RTOS内核系统计时器计数。

    +

    osKernelGetSysTimerFreq

    +

    获取RTOS内核系统计时器频率。

    +

    osKernelInitialize

    +

    初始化RTOS内核。

    +

    osKernelLock

    +

    锁定RTOS内核调度程序。

    +

    osKernelUnlock

    +

    解锁RTOS内核调度程序。

    +

    osKernelRestoreLock

    +

    恢复RTOS内核调度程序锁定状态。

    +

    osKernelResume

    +

    恢复RTOS内核调度程序。(暂未实现)

    +

    osKernelStart

    +

    启动RTOS内核调度程序。

    +

    osKernelSuspend

    +

    挂起RTOS内核调度程序。(暂未实现)

    +

    osKernelGetTickCount

    +

    获取RTOS内核滴答计数。

    +

    osKernelGetTickFreq

    +

    获取RTOS内核滴答频率。

    +

    线程管理

    +

    osThreadDetach

    +

    分离线程(线程终止时可以回收线程存储)。(暂未实现)

    +

    osThreadEnumerate

    +

    枚举活动线程。(暂未实现)

    +

    osThreadExit

    +

    终止当前正在运行的线程的执行。

    +

    osThreadGetCount

    +

    获取活动线程的数量。

    +

    osThreadGetId

    +

    返回当前正在运行的线程的线程ID。

    +

    osThreadGetName

    +

    获取线程的名称。

    +

    osThreadGetPriority

    +

    获取线程的当前优先级。

    +

    osThreadGetStackSize

    +

    获取线程的堆栈大小。

    +

    osThreadGetStackSpace

    +

    根据执行期间的堆栈水印记录获取线程的可用堆栈空间。

    +

    osThreadGetState

    +

    获取线程的当前线程状态。

    +

    osThreadJoin

    +

    等待指定线程终止。(暂未实现)

    +

    osThreadNew

    +

    创建一个线程并将其添加到活动线程中。

    +

    osThreadResume

    +

    恢复线程的执行。

    +

    osThreadSetPriority

    +

    更改线程的优先级。

    +

    osThreadSuspend

    +

    暂停执行线程。

    +

    osThreadTerminate

    +

    终止线程的执行。

    +

    osThreadYield

    +

    将控制权传递给处于就绪状态的下一个线程。

    +

    线程标志

    +

    osThreadFlagsSet

    +

    设置线程的指定线程标志。(暂未实现)

    +

    osThreadFlagsClear

    +

    清除当前正在运行的线程的指定线程标志。(暂未实现)

    +

    osThreadFlagsGet

    +

    获取当前正在运行的线程的当前线程标志。(暂未实现)

    +

    osThreadFlagsWait

    +

    等待当前正在运行的线程的一个或多个线程标志发出信号。(暂未实现)

    +

    事件标志

    +

    osEventFlagsGetName

    +

    获取事件标志对象的名称。(暂未实现)

    +

    osEventFlagsNew

    +

    创建并初始化事件标志对象。

    +

    osEventFlagsDelete

    +

    删除事件标志对象。

    +

    osEventFlagsSet

    +

    设置指定的事件标志。

    +

    osEventFlagsClear

    +

    清除指定的事件标志。

    +

    osEventFlagsGet

    +

    获取当前事件标志。

    +

    osEventFlagsWait

    +

    等待一个或多个事件标志被发出信号。

    +

    通用等待函数

    +

    osDelay

    +

    等待超时(时间延迟)。

    +

    osDelayUntil

    +

    等到指定时间。

    +

    计时器管理

    +

    osTimerDelete

    +

    删除计时器。

    +

    osTimerGetName

    +

    获取计时器的名称。(暂未实现)

    +

    osTimerIsRunning

    +

    检查计时器是否正在运行。

    +

    osTimerNew

    +

    创建和初始化计时器。

    +

    osTimerStart

    +

    启动或重新启动计时器。

    +

    osTimerStop

    +

    停止计时器。

    +

    互斥管理

    +

    osMutexAcquire

    +

    获取互斥或超时(如果已锁定)。

    +

    osMutexDelete

    +

    删除互斥对象。

    +

    osMutexGetName

    +

    获取互斥对象的名称。(暂未实现)

    +

    osMutexGetOwner

    +

    获取拥有互斥对象的线程。

    +

    osMutexNew

    +

    创建并初始化Mutex对象。

    +

    osMutexRelease

    +

    释放由osMutexAcquire获取的Mutex。

    +

    信号量

    +

    osSemaphoreAcquire

    +

    获取信号量令牌或超时(如果没有可用的令牌)。

    +

    osSemaphoreDelete

    +

    删除一个信号量对象。

    +

    osSemaphoreGetCount

    +

    获取当前信号量令牌计数。

    +

    osSemaphoreGetName

    +

    获取信号量对象的名称。(暂未实现)

    +

    osSemaphoreNew

    +

    创建并初始化一个信号量对象。

    +

    osSemaphoreRelease

    +

    释放信号量令牌,直到初始最大计数。

    +

    内存池

    +

    osMemoryPoolAlloc

    +

    从内存池分配一个内存块。

    +

    osMemoryPoolDelete

    +

    删除内存池对象。

    +

    osMemoryPoolFree

    +

    将分配的内存块返回到内存池。

    +

    osMemoryPoolGetBlockSize

    +

    获取内存池中的内存块大小。

    +

    osMemoryPoolGetCapacity

    +

    获取内存池中最大的内存块数。

    +

    osMemoryPoolGetCount

    +

    获取内存池中使用的内存块数。

    +

    osMemoryPoolGetName

    +

    获取内存池对象的名称。

    +

    osMemoryPoolGetSpace

    +

    获取内存池中可用的内存块数。

    +

    osMemoryPoolNew

    +

    创建并初始化一个内存池对象。

    +

    消息队列

    +

    osMessageQueueDelete

    +

    删除消息队列对象。

    +

    osMessageQueueGet

    +

    从队列获取消息,或者如果队列为空,则从超时获取消息。

    +

    osMessageQueueGetCapacity

    +

    获取消息队列中的最大消息数。

    +

    osMessageQueueGetCount

    +

    获取消息队列中排队的消息数。

    +

    osMessageQueueGetMsgSize

    +

    获取内存池中的最大消息大小。

    +

    osMessageQueueGetName

    +

    获取消息队列对象的名称。(暂未实现)

    +

    osMessageQueueGetSpace

    +

    获取消息队列中消息的可用插槽数。

    +

    osMessageQueueNew

    +

    创建和初始化消息队列对象。

    +

    osMessageQueuePut

    +

    如果队列已满,则将消息放入队列或超时。

    +

    osMessageQueueReset

    +

    将消息队列重置为初始空状态。(暂未实现)

    +
    + +### 开发流程 + +CMSIS-RTOS2组件可以作为库或源代码提供(下图显示了库)。通过添加CMSIS-RTOS2组件(通常是一些配置文件),可以将基于CMSIS的应用程序扩展为具有RTOS功能。只需包含cmsis\_os2.h头文件就可以访问RTOS API函数,这使用户应用程序能够处理RTOS内核相关事件,而在更换内核时无需重新编译源代码。 + +静态对象分配需要访问RTOS对象控制块定义。特定于实现的头文件(下图中的os\_xx .h)提供对此类控制块定义的访问。对于OpenHarmony LiteOS-M内核,由文件名以los\_开头的头文件提供,这些文件包含OpenHarmony LiteOS-M内核的这些定义。 + +![](figure/zh-cn_image_0000001132778524.png) + +### 编程实例 + +``` +#include ... +#include "cmsis_os2.h" + +/*---------------------------------------------------------------------------- + * 应用程序主线程 + *---------------------------------------------------------------------------*/ +void app_main (void *argument) { + // ... + for (;;) {} +} + +int main (void) { + // 系统初始化 + MySystemInit(); + // ... + + osKernelInitialize(); // 初始化CMSIS-RTOS + osThreadNew(app_main, NULL, NULL); // 创建应用程序主线程 + osKernelStart(); // 开始执行线程 + for (;;) {} +} +``` + diff --git "a/zh-cn/device-dev/kernel/POSIX\346\224\257\346\214\201.md" b/zh-cn/device-dev/kernel/kernel-lite-mini-app-lib-posix.md similarity index 100% rename from "zh-cn/device-dev/kernel/POSIX\346\224\257\346\214\201.md" rename to zh-cn/device-dev/kernel/kernel-lite-mini-app-lib-posix.md diff --git a/zh-cn/device-dev/kernel/kernel-lite-mini-app-lib.md b/zh-cn/device-dev/kernel/kernel-lite-mini-app-lib.md new file mode 100644 index 0000000000..b2f157ae19 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-mini-app-lib.md @@ -0,0 +1,7 @@ +# 标准库支持 + +- **[CMSIS支持](kernel-lite-mini-app-lib-cmsis.md)** + +- **[POSIX支持](kernel-lite-mini-app-lib-posix.md)** + + diff --git a/zh-cn/device-dev/kernel/kernel-lite-mini-app.md b/zh-cn/device-dev/kernel/kernel-lite-mini-app.md new file mode 100644 index 0000000000..1d46fa1186 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-mini-app.md @@ -0,0 +1,9 @@ +# 附录 + +- **[内核编码规范](kernel-lite-mini-app-code.md)** + +- **[基本数据结构](kernel-lite-mini-app-data.md)** + +- **[标准库支持](kernel-lite-mini-app-lib.md)** + + diff --git "a/zh-cn/device-dev/kernel/\345\237\272\346\234\254\346\246\202\345\277\265.md" b/zh-cn/device-dev/kernel/kernel-lite-mini-basic-interrupt-concept.md similarity index 100% rename from "zh-cn/device-dev/kernel/\345\237\272\346\234\254\346\246\202\345\277\265.md" rename to zh-cn/device-dev/kernel/kernel-lite-mini-basic-interrupt-concept.md diff --git a/zh-cn/device-dev/kernel/kernel-lite-mini-basic-interrupt-guide.md b/zh-cn/device-dev/kernel/kernel-lite-mini-basic-interrupt-guide.md new file mode 100644 index 0000000000..346332358b --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-mini-basic-interrupt-guide.md @@ -0,0 +1,130 @@ +# 开发指导 + +- [接口说明](#section158501652121514) +- [开发流程](#section11841123033618) +- [编程实例](#section460018317164) + - [结果验证](#section1048572415182) + + +当产生中断请求时,CPU暂停当前的任务,转而去响应外设请求。用户可以根据需要注册对应的中断处理程序,指定CPU响应中断请求时所执行的具体操作。 + +## 接口说明 + +OpenHarmony LiteOS-M内核的中断模块提供下面几种功能,接口详细信息可以查看API参考。 + +**表 1** 中断模块接口 + + + + + + + + + + + + + + + + + + + + + + + + + +

    功能分类

    +

    接口名

    +

    描述

    +

    创建、删除中断

    +

    HalHwiCreate

    +

    中断创建,注册中断号、中断触发模式、中断优先级、中断处理程序。中断被触发时,会调用该中断处理程序。

    +

    HalHwiDelete

    +

    根据指定的中断号,删除中断。

    +

    打开、关闭中断

    +

    LOS_IntUnLock

    +

    开中断,使能当前处理器所有中断响应。

    +

    LOS_IntLock

    +

    关中断,关闭当前处理器所有中断响应。

    +

    LOS_IntRestore

    +

    恢复到使用LOS_IntLock、LOS_IntUnLock操作之前的中断状态。

    +
    + +## 开发流程 + +1. 调用中断创建接口HalHwiCreate创建中断。 +2. 调用TestHwiTrigger接口触发指定中断(该接口在测试套中定义,通过写中断控制器的相关寄存器模拟外部中断,一般的外设设备,不需要执行这一步)。 +3. 调用HalHwiDelete接口删除指定中断,此接口根据实际情况使用,判断是否需要删除中断。 + +>![](../public_sys-resources/icon-note.gif) **说明:** +>- 根据具体硬件,配置支持的最大中断数及可设置的中断优先级个数。 +>- 中断处理程序耗时不能过长,否则会影响CPU对中断的及时响应。 +>- 中断响应过程中不能直接、间接执行引起调度的LOS\_Schedule等函数。 +>- 中断恢复LOS\_IntRestore\(\)的入参必须是与之对应的LOS\_IntLock\(\)的返回值(即关中断之前的CPSR值)。Cortex-M系列处理器中0-15中断为内部使用,因此不建议用户去申请和创建。 + +## 编程实例 + +本实例实现如下功能: + +1. 创建中断。 +2. 触发中断。 +3. 删除中断。 + +代码实现如下,演示如何创建中断和删除中断,当指定的中断号HWI\_NUM\_TEST产生中断时,会调用中断处理函数: + +``` +#include "los_interrupt.h" + +/*创建中断*/ +#define HWI_NUM_TEST 7 + +STATIC VOID HwiUsrIrq(VOID) +{ + printf("in the func HwiUsrIrq \n"); +} + +static UINT32 Example_Interrupt(VOID) +{ + UINT32 ret; + HWI_PRIOR_T hwiPrio = 3; + HWI_MODE_T mode = 0; + HWI_ARG_T arg = 0; + + /*创建中断*/ + ret = HalHwiCreate(HWI_NUM_TEST, hwiPrio, mode, (HWI_PROC_FUNC)HwiUsrIrq, arg); + if(ret == LOS_OK){ + printf("Hwi create success!\n"); + } else { + printf("Hwi create failed!\n"); + return LOS_NOK; + } + + /* 延时50个Ticks, 当有硬件中断发生时,会调用函数HwiUsrIrq*/ + LOS_TaskDelay(50); + + /*删除中断*/ + ret = HalHwiDelete(HWI_NUM_TEST); + if(ret == LOS_OK){ + printf("Hwi delete success!\n"); + } else { + printf("Hwi delete failed!\n"); + return LOS_NOK; + } + return LOS_OK; +} +``` + +### 结果验证 + +编译运行得到的结果为: + +``` +Hwi create success! +Hwi delete success!. +``` + diff --git a/zh-cn/device-dev/kernel/kernel-lite-mini-basic-interrupt.md b/zh-cn/device-dev/kernel/kernel-lite-mini-basic-interrupt.md new file mode 100644 index 0000000000..3b10c0482f --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-mini-basic-interrupt.md @@ -0,0 +1,7 @@ +# 中断管理 + +- **[基本概念](kernel-lite-mini-basic-interrupt-concept.md)** + +- **[开发指导](kernel-lite-mini-basic-interrupt-guide.md)** + + diff --git a/zh-cn/device-dev/kernel/kernel-lite-mini-basic-ipc-event-basic.md b/zh-cn/device-dev/kernel/kernel-lite-mini-basic-ipc-event-basic.md new file mode 100644 index 0000000000..91a6c20c0e --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-mini-basic-ipc-event-basic.md @@ -0,0 +1,194 @@ +# 开发指导 + +- [接口说明](#section158501652121514) +- [开发流程](#section783435801510) +- [编程实例](#section460018317164) + - [实例描述](#section896412438910) + - [示例代码](#section149077554912) + - [结果验证](#section4461439172017) + + +## 接口说明 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    功能分类

    +

    接口名

    +

    描述

    +

    事件检测

    +

    LOS_EventPoll

    +

    根据eventID,eventMask(事件掩码),mode(事件读取模式),检查用户期待的事件是否发生。

    +
    须知:

    当mode含LOS_WAITMODE_CLR,且用户期待的事件发生时,此时eventID中满足要求的事件会被清零,这种情况下eventID既是入参也是出参。其他情况eventID只作为入参。

    +
    +

    初始化

    +

    LOS_EventInit

    +

    事件控制块初始化。

    +

    事件读

    +

    LOS_EventRead

    +

    读事件(等待事件),任务会根据timeOut(单位:tick)进行阻塞等待;

    +

    未读取到事件时,返回值为0;

    +

    正常读取到事件时,返回正值(事件发生的集合);

    +

    其他情况返回特定错误码。

    +

    事件写

    +

    LOS_EventWrite

    +

    写一个特定的事件到事件控制块。

    +

    事件清除

    +

    LOS_EventClear

    +

    根据events掩码,清除事件控制块中的事件。

    +

    事件销毁

    +

    LOS_EventDestroy

    +

    事件控制块销毁。

    +
    + +## 开发流程 + +事件的典型开发流程: + +1. 初始化事件控制块 +2. 阻塞读事件控制块 +3. 写入相关事件 +4. 阻塞任务被唤醒,读取事件并检查是否满足要求 +5. 处理事件控制块 +6. 事件控制块销毁 + +>![](../public_sys-resources/icon-note.gif) **说明:** +>- 进行事件读写操作时,事件的第25位为保留位,不可以进行位设置。 +>- 对同一事件反复写入,算作一次写入。 + +## 编程实例 + +### 实例描述 + +示例中,任务Example\_TaskEntry创建一个任务Example\_Event,Example\_Event读事件阻塞,Example\_TaskEntry向该任务写事件。可以通过示例日志中打印的先后顺序理解事件操作时伴随的任务切换。 + +1. 在任务Example\_TaskEntry创建任务Example\_Event,其中任务Example\_Event优先级高于Example\_TaskEntry。 +2. 在任务Example\_Event中读事件0x00000001,阻塞,发生任务切换,执行任务Example\_TaskEntry。 +3. 在任务Example\_TaskEntry向任务Example\_Event写事件0x00000001,发生任务切换,执行任务Example\_Event。 +4. Example\_Event得以执行,直到任务结束。 +5. Example\_TaskEntry得以执行,直到任务结束。 + +### 示例代码 + +示例代码如下: + +``` +#include "los_event.h" +#include "los_task.h" +#include "securec.h" + +/* 任务ID */ +UINT32 g_testTaskId; + +/* 事件控制结构体 */ +EVENT_CB_S g_exampleEvent; + +/* 等待的事件类型 */ +#define EVENT_WAIT 0x00000001 + +/* 用例任务入口函数 */ +VOID Example_Event(VOID) +{ + UINT32 ret; + UINT32 event; + + /* 超时等待方式读事件,超时时间为100 ticks, 若100 ticks后未读取到指定事件,读事件超时,任务直接唤醒 */ + printf("Example_Event wait event 0x%x \n", EVENT_WAIT); + + event = LOS_EventRead(&g_exampleEvent, EVENT_WAIT, LOS_WAITMODE_AND, 100); + if (event == EVENT_WAIT) { + printf("Example_Event,read event :0x%x\n", event); + } else { + printf("Example_Event,read event timeout\n"); + } +} + +UINT32 Example_TaskEntry(VOID) +{ + UINT32 ret; + TSK_INIT_PARAM_S task1; + + /* 事件初始化 */ + ret = LOS_EventInit(&g_exampleEvent); + if (ret != LOS_OK) { + printf("init event failed .\n"); + return -1; + } + + /* 创建任务 */ + (VOID)memset_s(&task1, sizeof(TSK_INIT_PARAM_S), 0, sizeof(TSK_INIT_PARAM_S)); + task1.pfnTaskEntry = (TSK_ENTRY_FUNC)Example_Event; + task1.pcName = "EventTsk1"; + task1.uwStackSize = OS_TSK_DEFAULT_STACK_SIZE; + task1.usTaskPrio = 5; + ret = LOS_TaskCreate(&g_testTaskId, &task1); + if (ret != LOS_OK) { + printf("task create failed.\n"); + return LOS_NOK; + } + + /* 写g_testTaskId 等待事件 */ + printf("Example_TaskEntry write event.\n"); + + ret = LOS_EventWrite(&g_exampleEvent, EVENT_WAIT); + if (ret != LOS_OK) { + printf("event write failed.\n"); + return LOS_NOK; + } + + /* 清标志位 */ + printf("EventMask:%d\n", g_exampleEvent.uwEventID); + LOS_EventClear(&g_exampleEvent, ~g_exampleEvent.uwEventID); + printf("EventMask:%d\n", g_exampleEvent.uwEventID); + + /* 删除任务 */ + ret = LOS_TaskDelete(g_testTaskId); + if (ret != LOS_OK) { + printf("task delete failed.\n"); + return LOS_NOK; + } + + return LOS_OK; +} +``` + +### 结果验证 + +编译运行得到的结果为: + +``` +Example_Event wait event 0x1 +Example_TaskEntry write event. +Example_Event,read event :0x1 +EventMask:1 +EventMask:0 +``` + diff --git a/zh-cn/device-dev/kernel/kernel-lite-mini-basic-ipc-event-guide.md b/zh-cn/device-dev/kernel/kernel-lite-mini-basic-ipc-event-guide.md new file mode 100644 index 0000000000..47befc6223 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-mini-basic-ipc-event-guide.md @@ -0,0 +1,52 @@ +# 基本概念 + +- [运行机制](#section1735611583011) + - [事件控制块](#section1161415384467) + - [事件运作原理](#section187761153144617) + + +事件(Event)是一种任务间的通信机制,可用于任务间的同步操作。事件的特点是: + +- 任务间的事件同步,可以一对多,也可以多对多。一对多表示一个任务可以等待多个事件,多对多表示多个任务可以等待多个事件。但是一次写事件最多触发一个任务从阻塞中醒来。 +- 事件读超时机制。 +- 只做任务间同步,不传输具体数据。 + +提供了事件初始化、事件读写、事件清零、事件销毁等接口。 + +## 运行机制 + +### 事件控制块 + +``` +/** + * 事件控制块数据结构 + */ +typedef struct tagEvent { + UINT32 uwEventID; /* 事件集合,表示已经处理(写入和清零)的事件集合 */ + LOS_DL_LIST stEventList; /* 等待特定事件的任务链表 */ +} EVENT_CB_S, *PEVENT_CB_S; +``` + +### 事件运作原理 + +**事件初始化:**会创建一个事件控制块,该控制块维护一个已处理的事件集合,以及等待特定事件的任务链表。 + +**写事件:**会向事件控制块写入指定的事件,事件控制块更新事件集合,并遍历任务链表,根据任务等待具体条件满足情况决定是否唤醒相关任务。 + +**读事件:**如果读取的事件已存在时,会直接同步返回。其他情况会根据超时时间以及事件触发情况,来决定返回时机:等待的事件条件在超时时间耗尽之前到达,阻塞任务会被直接唤醒,否则超时时间耗尽该任务才会被唤醒。 + +读事件条件满足与否取决于入参eventMask和mode,eventMask即需要关注的事件。mode是具体处理方式,分以下三种情况: + +LOS\_WAITMODE\_AND:表示eventMask中所有事件都发生时,才返回。 + +LOS\_WAITMODE\_OR:表示eventMask中任何事件发生时,就返回。 + +LOS\_WAITMODE\_CLR:事件读取成功后,对应读取到的事件会被清零。需要配合LOS\_WAITMODE\_AND或者LOS\_WAITMODE\_OR来使用。 + +**事件清零:**根据指定掩码,去对事件控制块的事件集合进行清零操作。当掩码为0时,表示将事件集合全部清零。当掩码为0xffff时,表示不清除任何事件,保持事件集合原状。 + +**事件销毁:**销毁指定的事件控制块。 + +**图 1** 事件运作原理图 +![](figure/事件运作原理图.png "事件运作原理图") + diff --git a/zh-cn/device-dev/kernel/kernel-lite-mini-basic-ipc-event.md b/zh-cn/device-dev/kernel/kernel-lite-mini-basic-ipc-event.md new file mode 100644 index 0000000000..4f18b01922 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-mini-basic-ipc-event.md @@ -0,0 +1,7 @@ +# 事件 + +- **[基本概念](kernel-lite-mini-basic-ipc-event-guide.md)** + +- **[开发指导](kernel-lite-mini-basic-ipc-event-basic.md)** + + diff --git a/zh-cn/device-dev/kernel/kernel-lite-mini-basic-ipc-mutex-basic.md b/zh-cn/device-dev/kernel/kernel-lite-mini-basic-ipc-mutex-basic.md new file mode 100644 index 0000000000..1d29734624 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-mini-basic-ipc-mutex-basic.md @@ -0,0 +1,19 @@ +# 基本概念 + +- [运行机制](#section115161649726) + +互斥锁又称互斥型信号量,是一种特殊的二值性信号量,用于实现对共享资源的独占式处理。 + +任意时刻互斥锁的状态只有两种,开锁或闭锁。当有任务持有时,互斥锁处于闭锁状态,这个任务获得该互斥锁的所有权。当该任务释放它时,该互斥锁被开锁,任务失去该互斥锁的所有权。当一个任务持有互斥锁时,其他任务将不能再对该互斥锁进行开锁或持有。 + +多任务环境下往往存在多个任务竞争同一共享资源的应用场景,互斥锁可被用于对共享资源的保护从而实现独占式访问。另外互斥锁可以解决信号量存在的优先级翻转问题。 + +## 运行机制 + +多任务环境下会存在多个任务访问同一公共资源的场景,而有些公共资源是非共享的,需要任务进行独占式处理。互斥锁怎样来避免这种冲突呢? + +用互斥锁处理非共享资源的同步访问时,如果有任务访问该资源,则互斥锁为加锁状态。此时其他任务如果想访问这个公共资源则会被阻塞,直到互斥锁被持有该锁的任务释放后,其他任务才能重新访问该公共资源,此时互斥锁再次上锁,如此确保同一时刻只有一个任务正在访问这个公共资源,保证了公共资源操作的完整性。 + +**图 1** 互斥锁运作示意图 +![](figure/互斥锁运作示意图.png "互斥锁运作示意图") + diff --git a/zh-cn/device-dev/kernel/kernel-lite-mini-basic-ipc-mutex-guide.md b/zh-cn/device-dev/kernel/kernel-lite-mini-basic-ipc-mutex-guide.md new file mode 100644 index 0000000000..053174daa3 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-mini-basic-ipc-mutex-guide.md @@ -0,0 +1,205 @@ +# 开发指导 + +- [接口说明](#section158501652121514) +- [开发流程](#section783435801510) +- [编程实例](#section1426719434114) + - [实例描述](#section896412438910) + - [示例代码](#section149077554912) + - [结果验证](#section2059413981311) + + +## 接口说明 + +**表 1** 互斥锁模块接口 + + + + + + + + + + + + + + + + + + + + + + +

    功能分类

    +

    接口名

    +

    描述

    +

    互斥锁的创建和删除

    +

    LOS_MuxCreate

    +

    创建互斥锁

    +

    LOS_MuxDelete

    +

    删除指定的互斥锁

    +

    互斥锁的申请和释放

    +

    LOS_MuxPend

    +

    申请指定的互斥锁

    +

    LOS_MuxPost

    +

    释放指定的互斥锁

    +
    + +## 开发流程 + +互斥锁典型场景的开发流程: + +1. 创建互斥锁LOS\_MuxCreate。 +2. 申请互斥锁LOS\_MuxPend。 + + 申请模式有三种:无阻塞模式、永久阻塞模式、定时阻塞模式。 + + - 无阻塞模式:任务需要申请互斥锁,若该互斥锁当前没有任务持有,或者持有该互斥锁的任务和申请该互斥锁的任务为同一个任务,则申请成功。 + - 永久阻塞模式:任务需要申请互斥锁,若该互斥锁当前没有被占用,则申请成功。否则,该任务进入阻塞态,系统切换到就绪任务中优先级高者继续执行。任务进入阻塞态后,直到有其他任务释放该互斥锁,阻塞任务才会重新得以执行。 + - 定时阻塞模式:任务需要申请互斥锁,若该互斥锁当前没有被占用,则申请成功。否则该任务进入阻塞态,系统切换到就绪任务中优先级高者继续执行。任务进入阻塞态后,指定时间超时前有其他任务释放该互斥锁,或者用户指定时间超时后,阻塞任务才会重新得以执行。 + +3. 释放互斥锁LOS\_MuxPost。 + - 如果有任务阻塞于指定互斥锁,则唤醒被阻塞任务中优先级高的,该任务进入就绪态,并进行任务调度; + - 如果没有任务阻塞于指定互斥锁,则互斥锁释放成功。 + +4. 删除互斥锁LOS\_MuxDelete。 + +>![](../public_sys-resources/icon-note.gif) **说明:** +>- 两个任务不能对同一把互斥锁加锁。如果某任务对已被持有的互斥锁加锁,则该任务会被挂起,直到持有该锁的任务对互斥锁解锁,才能执行对这把互斥锁的加锁操作。 +>- 互斥锁不能在中断服务程序中使用。 +>- LiteOS-M内核作为实时操作系统需要保证任务调度的实时性,尽量避免任务的长时间阻塞,因此在获得互斥锁之后,应该尽快释放互斥锁。 +>- 持有互斥锁的过程中,不得再调用LOS\_TaskPriSet等接口更改持有互斥锁任务的优先级。 + +## 编程实例 + +### 实例描述 + +本实例实现如下流程。 + +1. 任务Example\_TaskEntry创建一个互斥锁,锁任务调度,创建两个任务Example\_MutexTask1、Example\_MutexTask2。Example\_MutexTask2优先级高于Example\_MutexTask1,解锁任务调度。 +2. Example\_MutexTask2被调度,以永久阻塞模式申请互斥锁,并成功获取到该互斥锁,然后任务休眠100Tick,Example\_MutexTask2挂起,Example\_MutexTask1被唤醒。 +3. Example\_MutexTask1以定时阻塞模式申请互斥锁,等待时间为10Tick,因互斥锁仍被Example\_MutexTask2持有,Example\_MutexTask1挂起。10Tick超时时间到达后,Example\_MutexTask1被唤醒,以永久阻塞模式申请互斥锁,因互斥锁仍被Example\_MutexTask2持有,Example\_MutexTask1挂起。 +4. 100Tick休眠时间到达后,Example\_MutexTask2被唤醒, 释放互斥锁,唤醒Example\_MutexTask1。Example\_MutexTask1成功获取到互斥锁后,释放,删除互斥锁。 + +### 示例代码 + +示例代码如下: + +``` +#include +#include "los_mux.h" + +/* 互斥锁句柄id */ +UINT32 g_testMux; +/* 任务ID */ +UINT32 g_testTaskId01; +UINT32 g_testTaskId02; + +VOID Example_MutexTask1(VOID) +{ + UINT32 ret; + + printf("task1 try to get mutex, wait 10 ticks.\n"); + /* 申请互斥锁 */ + ret = LOS_MuxPend(g_testMux, 10); + + if (ret == LOS_OK) { + printf("task1 get mutex g_testMux.\n"); + /* 释放互斥锁 */ + LOS_MuxPost(g_testMux); + return; + } + if (ret == LOS_ERRNO_MUX_TIMEOUT ) { + printf("task1 timeout and try to get mutex, wait forever.\n"); + /* 申请互斥锁 */ + ret = LOS_MuxPend(g_testMux, LOS_WAIT_FOREVER); + if (ret == LOS_OK) { + printf("task1 wait forever, get mutex g_testMux.\n"); + /* 释放互斥锁 */ + LOS_MuxPost(g_testMux); + /* 删除互斥锁 */ + LOS_MuxDelete(g_testMux); + printf("task1 post and delete mutex g_testMux.\n"); + return; + } + } + return; +} + +VOID Example_MutexTask2(VOID) +{ + printf("task2 try to get mutex, wait forever.\n"); + /* 申请互斥锁 */ + (VOID)LOS_MuxPend(g_testMux, LOS_WAIT_FOREVER); + + printf("task2 get mutex g_testMux and suspend 100 ticks.\n"); + + /* 任务休眠100Ticks */ + LOS_TaskDelay(100); + + printf("task2 resumed and post the g_testMux\n"); + /* 释放互斥锁 */ + LOS_MuxPost(g_testMux); + return; +} + +UINT32 Example_TaskEntry(VOID) +{ + UINT32 ret; + TSK_INIT_PARAM_S task1; + TSK_INIT_PARAM_S task2; + + /* 创建互斥锁 */ + LOS_MuxCreate(&g_testMux); + + /* 锁任务调度 */ + LOS_TaskLock(); + + /* 创建任务1 */ + memset(&task1, 0, sizeof(TSK_INIT_PARAM_S)); + task1.pfnTaskEntry = (TSK_ENTRY_FUNC)Example_MutexTask1; + task1.pcName = "MutexTsk1"; + task1.uwStackSize = LOSCFG_BASE_CORE_TSK_DEFAULT_STACK_SIZE; + task1.usTaskPrio = 5; + ret = LOS_TaskCreate(&g_testTaskId01, &task1); + if (ret != LOS_OK) { + printf("task1 create failed.\n"); + return LOS_NOK; + } + + /* 创建任务2 */ + memset(&task2, 0, sizeof(TSK_INIT_PARAM_S)); + task2.pfnTaskEntry = (TSK_ENTRY_FUNC)Example_MutexTask2; + task2.pcName = "MutexTsk2"; + task2.uwStackSize = LOSCFG_BASE_CORE_TSK_DEFAULT_STACK_SIZE; + task2.usTaskPrio = 4; + ret = LOS_TaskCreate(&g_testTaskId02, &task2); + if (ret != LOS_OK) { + printf("task2 create failed.\n"); + return LOS_NOK; + } + + /* 解锁任务调度 */ + LOS_TaskUnlock(); + + return LOS_OK; +} +``` + +### 结果验证 + +编译运行得到的结果为: + +``` +task2 try to get mutex, wait forever. +task2 get mutex g_testMux and suspend 100 ticks. +task1 try to get mutex, wait 10 ticks. +task1 timeout and try to get mutex, wait forever. +task2 resumed and post the g_testMux +task1 wait forever, get mutex g_testMux. +task1 post and delete mutex g_testMux. +``` + diff --git a/zh-cn/device-dev/kernel/kernel-lite-mini-basic-ipc-mutex.md b/zh-cn/device-dev/kernel/kernel-lite-mini-basic-ipc-mutex.md new file mode 100644 index 0000000000..e081c41544 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-mini-basic-ipc-mutex.md @@ -0,0 +1,7 @@ +# 互斥锁 + +- **[基本概念](kernel-lite-mini-basic-ipc-mutex-basic.md)** + +- **[开发指导](kernel-lite-mini-basic-ipc-mutex-guide.md)** + + diff --git a/zh-cn/device-dev/kernel/kernel-lite-mini-basic-ipc-queue-basic.md b/zh-cn/device-dev/kernel/kernel-lite-mini-basic-ipc-queue-basic.md new file mode 100644 index 0000000000..06f38749de --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-mini-basic-ipc-queue-basic.md @@ -0,0 +1,67 @@ +# 基本概念 + +- [运行机制](#section1582619446311) + - [队列控制块](#section1648304614720) + - [队列运作原理](#section15384012164811) + + +队列又称消息队列,是一种常用于任务间通信的数据结构。队列接收来自任务或中断的不固定长度消息,并根据不同的接口确定传递的消息是否存放在队列空间中。 + +任务能够从队列里面读取消息,当队列中的消息为空时,挂起读取任务;当队列中有新消息时,挂起的读取任务被唤醒并处理新消息。任务也能够往队列里写入消息,当队列已经写满消息时,挂起写入任务;当队列中有空闲消息节点时,挂起的写入任务被唤醒并写入消息。 + +可以通过调整读队列和写队列的超时时间来调整读写接口的阻塞模式,如果将读队列和写队列的超时时间设置为0,就不会挂起任务,接口会直接返回,这就是非阻塞模式。反之,如果将都队列和写队列的超时时间设置为大于0的时间,就会以阻塞模式运行。 + +消息队列提供了异步处理机制,允许将一个消息放入队列,但不立即处理。同时队列还有缓冲消息的作用,可以使用队列实现任务异步通信,队列具有如下特性: + +- 消息以先进先出的方式排队,支持异步读写。 +- 读队列和写队列都支持超时机制。 +- 每读取一条消息,就会将该消息节点设置为空闲。 +- 发送消息类型由通信双方约定,可以允许不同长度(不超过队列的消息节点大小)的消息。 +- 一个任务能够从任意一个消息队列接收和发送消息。 +- 多个任务能够从同一个消息队列接收和发送消息。 +- 创建队列时所需的队列空间,接口内系统自行动态申请内存。 + +## 运行机制 + +### 队列控制块 + +``` +/** + * 队列控制块数据结构 + */ +typedef struct +{ + UINT8 *queue; /* 队列消息内存空间的指针 */ + UINT16 queueState; /* 队列状态 */ + UINT16 queueLen; /* 队列中消息节点个数,即队列长度 */ + UINT16 queueSize; /* 消息节点大小 */ + UINT16 queueID; /* 队列ID */ + UINT16 queueHead; /* 消息头节点位置(数组下标)*/ + UINT16 queueTail; /* 消息尾节点位置(数组下标)*/ + UINT16 readWriteableCnt[OS_READWRITE_LEN]; /* 数组下标0的元素表示队列中可读消息数, + 数组下标1的元素表示队列中可写消息数 */ + LOS_DL_LIST readWriteList[OS_READWRITE_LEN]; /* 读取或写入消息的任务等待链表, + 下标0:读取链表,下标1:写入链表 */ + LOS_DL_LIST memList; /* 内存块链表 */ +} LosQueueCB; +``` + +每个队列控制块中都含有队列状态,表示该队列的使用情况: + +- OS\_QUEUE\_UNUSED:队列未被使用。 +- OS\_QUEUE\_INUSED:队列被使用中。 + +### 队列运作原理 + +- 创建队列时,创建队列成功会返回队列ID。 +- 在队列控制块中维护着一个消息头节点位置Head和一个消息尾节点位置Tail,用于表示当前队列中消息的存储情况。Head表示队列中被占用的消息节点的起始位置。Tail表示被占用的消息节点的结束位置,也是空闲消息节点的起始位置。队列刚创建时,Head和Tail均指向队列起始位置。 +- 写队列时,根据readWriteableCnt\[1\]判断队列是否可以写入,不能对已满(readWriteableCnt\[1\]为0)队列进行写操作。写队列支持两种写入方式:向队列尾节点写入,也可以向队列头节点写入。尾节点写入时,根据Tail找到起始空闲消息节点作为数据写入对象,如果Tail已经指向队列尾部则采用回卷方式。头节点写入时,将Head的前一个节点作为数据写入对象,如果Head指向队列起始位置则采用回卷方式。 +- 读队列时,根据readWriteableCnt\[0\]判断队列是否有消息需要读取,对全部空闲(readWriteableCnt\[0\]为0)队列进行读操作会引起任务挂起。如果队列可以读取消息,则根据Head找到最先写入队列的消息节点进行读取。如果Head已经指向队列尾部则采用回卷方式。 +- 删除队列时,根据队列ID找到对应队列,把队列状态置为未使用,把队列控制块置为初始状态,并释放队列所占内存。 + +图 1 队列读写数据操作示意图 + +![](figure/zh-cn_image_0000001132935054.png) + +上图对读写队列做了示意,图中只画了尾节点写入方式,没有画头节点写入,但是两者是类似的。 + diff --git a/zh-cn/device-dev/kernel/kernel-lite-mini-basic-ipc-queue-guide.md b/zh-cn/device-dev/kernel/kernel-lite-mini-basic-ipc-queue-guide.md new file mode 100644 index 0000000000..6c161853b6 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-mini-basic-ipc-queue-guide.md @@ -0,0 +1,199 @@ +# 开发指导 + +- [接口说明](#section158501652121514) +- [开发流程](#section783435801510) +- [编程实例](#section460018317164) + - [实例描述](#section2148236125814) + - [示例代码](#section121451047155716) + - [结果验证](#section2742182082117) + + +## 接口说明 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    功能分类

    +

    接口名

    +

    描述

    +

    创建/删除消息队列

    +

    LOS_QueueCreate

    +

    创建一个消息队列,由系统动态申请队列空间。

    +

    LOS_QueueDelete

    +

    根据队列ID删除一个指定队列。

    +

    读/写队列(不带拷贝)

    +

    LOS_QueueRead

    +

    读取指定队列头节点中的数据(队列节点中的数据实际上是一个地址)。

    +

    LOS_QueueWrite

    +

    向指定队列尾节点中写入入参bufferAddr的值(即buffer的地址)。

    +

    LOS_QueueWriteHead

    +

    向指定队列头节点中写入入参bufferAddr的值(即buffer的地址)。

    +

    读/写队列(带拷贝)

    +

    LOS_QueueReadCopy

    +

    读取指定队列头节点中的数据。

    +

    LOS_QueueWriteCopy

    +

    向指定队列尾节点中写入入参bufferAddr中保存的数据。

    +

    LOS_QueueWriteHeadCopy

    +

    向指定队列头节点中写入入参bufferAddr中保存的数据。

    +

    获取队列信息

    +

    LOS_QueueInfoGet

    +

    获取指定队列的信息,包括队列ID、队列长度、消息节点大小、头节点、尾节点、可读节点数量、可写节点数量、等待读操作的任务、等待写操作的任务。

    +
    + +## 开发流程 + +1. 用LOS\_QueueCreate创建队列。创建成功后,可以得到队列ID。 +2. 通过LOS\_QueueWrite或者LOS\_QueueWriteCopy写队列。 +3. 通过LOS\_QueueRead或者LOS\_QueueReadCopy读队列。 +4. 通过LOS\_QueueInfoGet获取队列信息。 +5. 通过LOS\_QueueDelete删除队列。 + +>![](../public_sys-resources/icon-note.gif) **说明:** +>- 系统支持的最大队列数是指:整个系统的队列资源总个数,而非用户能使用的个数。例如:系统软件定时器多占用一个队列资源,那么用户能使用的队列资源就会减少一个。 +>- 创建队列时传入的队列名和flags暂时未使用,作为以后的预留参数。 +>- 队列接口函数中的入参timeOut是相对时间。 +>- LOS\_QueueReadCopy和LOS\_QueueWriteCopy及LOS\_QueueWriteHeadCopy是一组接口,LOS\_QueueRead和LOS\_QueueWrite及LOS\_QueueWriteHead是一组接口,每组接口需要配套使用。 +>- 鉴于LOS\_QueueWrite和LOS\_QueueWriteHead和LOS\_QueueRead这组接口实际操作的是数据地址,用户必须保证调用LOS\_QueueRead获取到的指针所指向的内存区域在读队列期间没有被异常修改或释放,否则可能导致不可预知的后果。 +>- 鉴于LOS\_QueueWrite和LOS\_QueueWriteHead和LOS\_QueueRead这组接口实际操作的是数据地址,也就意味着实际写和读的消息长度仅仅是一个指针数据,因此用户使用这组接口之前,需确保创建队列时的消息节点大小,为一个指针的长度,避免不必要的浪费和读取失败。 + +## 编程实例 + +### 实例描述 + +创建一个队列,两个任务。任务1调用写队列接口发送消息,任务2通过读队列接口接收消息。 + +1. 通过LOS\_TaskCreate创建任务1和任务2。 +2. 通过LOS\_QueueCreate创建一个消息队列。 +3. 在任务1 SendEntry中发送消息。 +4. 在任务2 RecvEntry中接收消息。 +5. 通过LOS\_QueueDelete删除队列。 + +### 示例代码 + +示例代码如下: + +``` +#include "los_task.h" +#include "los_queue.h" +static UINT32 g_queue; +#define BUFFER_LEN 50 + +VOID SendEntry(VOID) +{ + UINT32 ret = 0; + CHAR abuf[] = "test message"; + UINT32 len = sizeof(abuf); + + ret = LOS_QueueWriteCopy(g_queue, abuf, len, 0); + if(ret != LOS_OK) { + printf("send message failure, error: %x\n", ret); + } +} + +VOID RecvEntry(VOID) +{ + UINT32 ret = 0; + CHAR readBuf[BUFFER_LEN] = {0}; + UINT32 readLen = BUFFER_LEN; + + //休眠1s + usleep(1000000); + ret = LOS_QueueReadCopy(g_queue, readBuf, &readLen, 0); + if(ret != LOS_OK) { + printf("recv message failure, error: %x\n", ret); + } + + printf("recv message: %s\n", readBuf); + + ret = LOS_QueueDelete(g_queue); + if(ret != LOS_OK) { + printf("delete the queue failure, error: %x\n", ret); + } + + printf("delete the queue success!\n"); +} + +UINT32 ExampleQueue(VOID) +{ + printf("start queue example\n"); + UINT32 ret = 0; + UINT32 task1, task2; + TSK_INIT_PARAM_S initParam = {0}; + + initParam.pfnTaskEntry = (TSK_ENTRY_FUNC)SendEntry; + initParam.usTaskPrio = 9; + initParam.uwStackSize = LOSCFG_BASE_CORE_TSK_DEFAULT_STACK_SIZE; + initParam.pcName = "SendQueue"; + + LOS_TaskLock(); + ret = LOS_TaskCreate(&task1, &initParam); + if(ret != LOS_OK) { + printf("create task1 failed, error: %x\n", ret); + return ret; + } + + initParam.pcName = "RecvQueue"; + initParam.pfnTaskEntry = (TSK_ENTRY_FUNC)RecvEntry; + ret = LOS_TaskCreate(&task2, &initParam); + if(ret != LOS_OK) { + printf("create task2 failed, error: %x\n", ret); + return ret; + } + + ret = LOS_QueueCreate("queue", 5, &g_queue, 0, 50); + if(ret != LOS_OK) { + printf("create queue failure, error: %x\n", ret); + } + + printf("create the queue success!\n"); + LOS_TaskUnlock(); + return ret; +} +``` + +### 结果验证 + +编译运行得到的结果为: + +``` +start test example +create the queue success! +recv message: test message +delete the queue success! +``` + diff --git a/zh-cn/device-dev/kernel/kernel-lite-mini-basic-ipc-queue.md b/zh-cn/device-dev/kernel/kernel-lite-mini-basic-ipc-queue.md new file mode 100644 index 0000000000..a278033961 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-mini-basic-ipc-queue.md @@ -0,0 +1,7 @@ +# 消息队列 + +- **[基本概念](kernel-lite-mini-basic-ipc-queue-basic.md)** + +- **[开发指导](kernel-lite-mini-basic-ipc-queue-guide.md)** + + diff --git a/zh-cn/device-dev/kernel/kernel-lite-mini-basic-ipc-sem-basic.md b/zh-cn/device-dev/kernel/kernel-lite-mini-basic-ipc-sem-basic.md new file mode 100644 index 0000000000..79c4d7e6f5 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-mini-basic-ipc-sem-basic.md @@ -0,0 +1,53 @@ +# 基本概念 + +- [运行机制](#section1794010261861) + - [信号量控制块](#section11372149164815) + - [信号量运作原理](#section139726510491) + + +信号量(Semaphore)是一种实现任务间通信的机制,可以实现任务间同步或共享资源的互斥访问。 + +一个信号量的数据结构中,通常有一个计数值,用于对有效资源数的计数,表示剩下的可被使用的共享资源数,其值的含义分两种情况: + +- 0,表示该信号量当前不可获取,因此可能存在正在等待该信号量的任务。 +- 正值,表示该信号量当前可被获取。 + +以同步为目的的信号量和以互斥为目的的信号量在使用上有如下不同: + +- 用作互斥时,初始信号量计数值不为0,表示可用的共享资源个数。在需要使用共享资源前,先获取信号量,然后使用一个共享资源,使用完毕后释放信号量。这样在共享资源被取完,即信号量计数减至0时,其他需要获取信号量的任务将被阻塞,从而保证了共享资源的互斥访问。另外,当共享资源数为1时,建议使用二值信号量,一种类似于互斥锁的机制。 +- 用作同步时,初始信号量计数值为0。任务1获取信号量而阻塞,直到任务2或者某中断释放信号量,任务1才得以进入Ready或Running态,从而达到了任务间的同步。 + +## 运行机制 + +### 信号量控制块 + +``` +/** + * 信号量控制块数据结构 + */ +typedef struct { + UINT16 semStat; /* 信号量状态 */ + UINT16 semType; /* 信号量类型 */ + UINT16 semCount; /* 信号量计数 */ + UINT16 semId; /* 信号量索引号 */ + LOS_DL_LIST semList; /* 挂接阻塞于该信号量的任务 */ +} LosSemCB; +``` + +### 信号量运作原理 + +信号量初始化,为配置的N个信号量申请内存(N值可以由用户自行配置,通过LOSCFG\_BASE\_IPC\_SEM\_LIMIT宏实现),并把所有信号量初始化成未使用,加入到未使用链表中供系统使用。 + +信号量创建,从未使用的信号量链表中获取一个信号量,并设定初值。 + +信号量申请,若其计数器值大于0,则直接减1返回成功。否则任务阻塞,等待其它任务释放该信号量,等待的超时时间可设定。当任务被一个信号量阻塞时,将该任务挂到信号量等待任务队列的队尾。 + +信号量释放,若没有任务等待该信号量,则直接将计数器加1返回。否则唤醒该信号量等待任务队列上的第一个任务。 + +信号量删除,将正在使用的信号量置为未使用信号量,并挂回到未使用链表。 + +信号量允许多个任务在同一时刻访问共享资源,但会限制同一时刻访问此资源的最大任务数目。当访问资源的任务数达到该资源允许的最大数量时,会阻塞其他试图获取该资源的任务,直到有任务释放该信号量。 + +**图 1** 信号量运作示意图 +![](figure/信号量运作示意图.png "信号量运作示意图") + diff --git a/zh-cn/device-dev/kernel/kernel-lite-mini-basic-ipc-sem-guide.md b/zh-cn/device-dev/kernel/kernel-lite-mini-basic-ipc-sem-guide.md new file mode 100644 index 0000000000..81715063b3 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-mini-basic-ipc-sem-guide.md @@ -0,0 +1,206 @@ +# 开发指导 + +- [接口说明](#section158501652121514) +- [开发流程](#section783435801510) +- [编程实例](#section460018317164) + - [实例描述](#section22061718111412) + - [示例代码](#section1775922321416) + - [结果验证](#section160404016213) + + +## 接口说明 + + + + + + + + + + + + + + + + + + + + + + + + + +

    功能分类

    +

    接口名

    +

    描述

    +

    创建/删除信号量

    +

    LOS_SemCreate

    +

    创建信号量,返回信号量ID

    +

    LOS_BinarySemCreate

    +

    创建二值信号量,其计数值最大为1

    +

    LOS_SemDelete

    +

    删除指定的信号量

    +

    申请/释放信号量

    +

    LOS_SemPend

    +

    申请指定的信号量,并设置超时时间

    +

    LOS_SemPost

    +

    释放指定的信号量

    +
    + +## 开发流程 + +1. 创建信号量LOS\_SemCreate,若要创建二值信号量则调用LOS\_BinarySemCreate。 +2. 申请信号量LOS\_SemPend。 +3. 释放信号量LOS\_SemPost。 +4. 删除信号量LOS\_SemDelete。 + +>![](../public_sys-resources/icon-note.gif) **说明:** +>由于中断不能被阻塞,因此不能在中断中使用阻塞模式申请信号量。 + +## 编程实例 + +### 实例描述 + +本实例实现如下功能: + +1. 测试任务ExampleSem创建一个信号量,锁任务调度,创建两个任务ExampleSemTask1、ExampleSemTask2, ExampleSemTask2优先级高于ExampleSemTask1,两个任务中申请同一信号量,解锁任务调度后两任务阻塞,测试任务ExampleSem释放信号量。 +2. ExampleSemTask2得到信号量,被调度,然后任务休眠20Tick,ExampleSemTask2延迟,ExampleSemTask1被唤醒。 +3. ExampleSemTask1定时阻塞模式申请信号量,等待时间为10Tick,因信号量仍被ExampleSemTask2持有,ExampleSemTask1挂起,10Tick后仍未得到信号量,ExampleSemTask1被唤醒,试图以永久阻塞模式申请信号量,ExampleSemTask1挂起。 +4. 20Tick后ExampleSemTask2唤醒, 释放信号量后,ExampleSemTask1得到信号量被调度运行,最后释放信号量。 +5. ExampleSemTask1执行完,40Tick后任务ExampleSem被唤醒,执行删除信号量。 + +### 示例代码 + +示例代码如下: + +``` +#include "los_sem.h" +#include "securec.h" + +/* 任务ID */ +static UINT32 g_testTaskId01; +static UINT32 g_testTaskId02; + +/* 测试任务优先级 */ +#define TASK_PRIO_TEST 5 + +/* 信号量结构体id */ +static UINT32 g_semId; + +VOID ExampleSemTask1(VOID) +{ + UINT32 ret; + + printf("ExampleSemTask1 try get sem g_semId, timeout 10 ticks.\n"); + + /* 定时阻塞模式申请信号量,定时时间为10ticks */ + ret = LOS_SemPend(g_semId, 10); + + /* 申请到信号量 */ + if (ret == LOS_OK) { + LOS_SemPost(g_semId); + return; + } + /* 定时时间到,未申请到信号量 */ + if (ret == LOS_ERRNO_SEM_TIMEOUT) { + printf("ExampleSemTask1 timeout and try get sem g_semId wait forever.\n"); + + /*永久阻塞模式申请信号量*/ + ret = LOS_SemPend(g_semId, LOS_WAIT_FOREVER); + printf("ExampleSemTask1 wait_forever and get sem g_semId.\n"); + if (ret == LOS_OK) { + LOS_SemPost(g_semId); + return; + } + } +} + +VOID ExampleSemTask2(VOID) +{ + UINT32 ret; + printf("ExampleSemTask2 try get sem g_semId wait forever.\n"); + + /* 永久阻塞模式申请信号量 */ + ret = LOS_SemPend(g_semId, LOS_WAIT_FOREVER); + + if (ret == LOS_OK) { + printf("ExampleSemTask2 get sem g_semId and then delay 20 ticks.\n"); + } + + /* 任务休眠20 ticks */ + LOS_TaskDelay(20); + + printf("ExampleSemTask2 post sem g_semId.\n"); + /* 释放信号量 */ + LOS_SemPost(g_semId); + return; +} + +UINT32 ExampleSem(VOID) +{ + UINT32 ret; + TSK_INIT_PARAM_S task1; + TSK_INIT_PARAM_S task2; + + /* 创建信号量 */ + LOS_SemCreate(0, &g_semId); + + /* 锁任务调度 */ + LOS_TaskLock(); + + /* 创建任务1 */ + (VOID)memset_s(&task1, sizeof(TSK_INIT_PARAM_S), 0, sizeof(TSK_INIT_PARAM_S)); + task1.pfnTaskEntry = (TSK_ENTRY_FUNC)ExampleSemTask1; + task1.pcName = "TestTask1"; + task1.uwStackSize = LOSCFG_BASE_CORE_TSK_DEFAULT_STACK_SIZE; + task1.usTaskPrio = TASK_PRIO_TEST; + ret = LOS_TaskCreate(&g_testTaskId01, &task1); + if (ret != LOS_OK) { + printf("task1 create failed .\n"); + return LOS_NOK; + } + + /* 创建任务2 */ + (VOID)memset_s(&task2, sizeof(TSK_INIT_PARAM_S), 0, sizeof(TSK_INIT_PARAM_S)); + task2.pfnTaskEntry = (TSK_ENTRY_FUNC)ExampleSemTask2; + task2.pcName = "TestTask2"; + task2.uwStackSize = LOSCFG_BASE_CORE_TSK_DEFAULT_STACK_SIZE; + task2.usTaskPrio = (TASK_PRIO_TEST - 1); + ret = LOS_TaskCreate(&g_testTaskId02, &task2); + if (ret != LOS_OK) { + printf("task2 create failed.\n"); + return LOS_NOK; + } + + /* 解锁任务调度 */ + LOS_TaskUnlock(); + + ret = LOS_SemPost(g_semId); + + /* 任务休眠400 ticks */ + LOS_TaskDelay(400); + + /* 删除信号量 */ + LOS_SemDelete(g_semId); + return LOS_OK; +} +``` + +### 结果验证 + +编译运行得到的结果为: + +``` +ExampleSemTask2 try get sem g_semId wait forever. +ExampleSemTask2 get sem g_semId and then delay 20 ticks. +ExampleSemTask1 try get sem g_semId, timeout 10 ticks. + +ExampleSemTask1 timeout and try get sem g_semId wait forever. +ExampleSemTask2 post sem g_semId. +ExampleSemTask1 wait_forever and get sem g_semId. +``` + diff --git a/zh-cn/device-dev/kernel/kernel-lite-mini-basic-ipc-sem.md b/zh-cn/device-dev/kernel/kernel-lite-mini-basic-ipc-sem.md new file mode 100644 index 0000000000..1b1afc6945 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-mini-basic-ipc-sem.md @@ -0,0 +1,7 @@ +# 信号量 + +- **[基本概念](kernel-lite-mini-basic-ipc-sem-basic.md)** + +- **[开发指导](kernel-lite-mini-basic-ipc-sem-guide.md)** + + diff --git a/zh-cn/device-dev/kernel/kernel-lite-mini-basic-ipc.md b/zh-cn/device-dev/kernel/kernel-lite-mini-basic-ipc.md new file mode 100644 index 0000000000..2acba70e2f --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-mini-basic-ipc.md @@ -0,0 +1,11 @@ +# 内核通信机制 + +- **[事件](kernel-lite-mini-basic-ipc-event.md)** + +- **[互斥锁](kernel-lite-mini-basic-ipc-mutex.md)** + +- **[消息队列](kernel-lite-mini-basic-ipc-queue.md)** + +- **[信号量](kernel-lite-mini-basic-ipc-sem.md)** + + diff --git "a/zh-cn/device-dev/kernel/\345\237\272\346\234\254\346\246\202\345\277\265-4.md" b/zh-cn/device-dev/kernel/kernel-lite-mini-basic-memory-basic.md similarity index 100% rename from "zh-cn/device-dev/kernel/\345\237\272\346\234\254\346\246\202\345\277\265-4.md" rename to zh-cn/device-dev/kernel/kernel-lite-mini-basic-memory-basic.md diff --git a/zh-cn/device-dev/kernel/kernel-lite-mini-basic-memory-dynamic.md b/zh-cn/device-dev/kernel/kernel-lite-mini-basic-memory-dynamic.md new file mode 100644 index 0000000000..c9f32f97ad --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-mini-basic-memory-dynamic.md @@ -0,0 +1,227 @@ +# 动态内存 + +- [运行机制](#section328282013571) +- [开发指导](#section7921151015814) + - [使用场景](#section326917198583) + - [接口说明](#section1032331584) + - [开发流程](#section07271773592) + - [编程实例](#section84931234145913) + - [结果验证](#section165233233917) + + +## 运行机制 + +动态内存管理,即在内存资源充足的情况下,根据用户需求,从系统配置的一块比较大的连续内存(内存池,也是堆内存)中分配任意大小的内存块。当用户不需要该内存块时,又可以释放回系统供下一次使用。与静态内存相比,动态内存管理的优点是按需分配,缺点是内存池中容易出现碎片。 + +OpenHarmony LiteOS-M动态内存在TLSF算法的基础上,对区间的划分进行了优化,获得更优的性能,降低了碎片率。动态内存核心算法框图如下: + +**图 1** 动态内存核心算法 +![](figure/动态内存核心算法.png "动态内存核心算法") + +根据空闲内存块的大小,使用多个空闲链表来管理。根据内存空闲块大小分为两个部分:\[4, 127\]和\[27, 231\],如上图size class所示: + +1. 对\[4,127\]区间的内存进行等分,如上图绿色部分所示,分为31个小区间,每个小区间对应内存块大小为4字节的倍数。每个小区间对应一个空闲内存链表和用于标记对应空闲内存链表是否为空的一个比特位,值为1时,空闲链表非空。\[4,127\]区间的31个小区间内存对应31个比特位进行标记链表是否为空。 +2. 大于127字节的空闲内存块,按照2的次幂区间大小进行空闲链表管理。总共分为24个小区间,每个小区间又等分为8个二级小区间,见上图蓝色的Size Class和Size SubClass部分。每个二级小区间对应一个空闲链表和用于标记对应空闲内存链表是否为空的一个比特位。总共24\*8=192个二级小区间,对应192个空闲链表和192个比特位进行标记链表是否为空。 + +例如,当有40字节的空闲内存需要插入空闲链表时,对应小区间\[40,43\],第10个空闲链表,位图标记的第10比特位。把40字节的空闲内存挂载第10个空闲链表上,并判断是否需要更新位图标记。当需要申请40字节的内存时,根据位图标记获取存在满足申请大小的内存块的空闲链表,从空闲链表上获取空闲内存节点。如果分配的节点大于需要申请的内存大小,进行分割节点操作,剩余的节点重新挂载到相应的空闲链表上。当有580字节的空闲内存需要插入空闲链表时,对应二级小区间\[2^9,2^9+2^6\],第31+2\*8=47个空闲链表,并使用位图的第47个比特位来标记链表是否为空。把580字节的空闲内存挂载第47个空闲链表上,并判断是否需要更新位图标记。当需要申请580字节的内存时,根据位图标记获取存在满足申请大小的内存块的空闲链表,从空闲链表上获取空闲内存节点。如果分配的节点大于需要申请的内存大小,进行分割节点操作,剩余的节点重新挂载到相应的空闲链表上。如果对应的空闲链表为空,则向更大的内存区间去查询是否有满足条件的空闲链表,实际计算时,会一次性查找到满足申请大小的空闲链表。 + +内存管理结构如下图所示: + +**图 2** 动态内存管理结构图 +![](figure/动态内存管理结构图.png "动态内存管理结构图") + +- 内存池池头部分 + + 内存池池头部分包含内存池信息、位图标记数组和空闲链表数组。内存池信息包含内存池起始地址及堆区域总大小,内存池属性。位图标记数组有7个32位无符号整数组成,每个比特位标记对应的空闲链表是否挂载空闲内存块节点。空闲内存链表包含223个空闲内存头节点信息,每个空闲内存头节点信息维护内存节点头和空闲链表中的前驱、后继空闲内存节点。 + +- 内存池节点部分 + + 包含3种类型节点:未使用空闲内存节点,已使用内存节点和尾节点。每个内存节点维护一个前序指针,指向内存池中上一个内存节点,还维护内存节点的大小和使用标记。空闲内存节点和已使用内存节点后面的内存区域是数据域,尾节点没有数据域。 + + +## 开发指导 + +### 使用场景 + +动态内存管理的主要工作是动态分配并管理用户申请到的内存区间。动态内存管理主要用于用户需要使用大小不等的内存块的场景,当用户需要使用内存时,可以通过操作系统的动态内存申请函数索取指定大小的内存块,一旦使用完毕,通过动态内存释放函数归还所占用内存,使之可以重复使用。 + +### 接口说明 + +OpenHarmony LiteOS-M的动态内存管理主要为用户提供以下功能,接口详细信息可以查看API参考。 + +**表 1** 动态内存模块接口 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    功能分类

    +

    接口名

    +

    描述

    +

    初始化和删除内存池

    +

    LOS_MemInit

    +

    初始化一块指定的动态内存池,大小为size。

    +

    LOS_MemDeInit

    +

    删除指定内存池,仅打开LOSCFG_MEM_MUL_POOL时有效。

    +

    申请、释放动态内存

    +

    LOS_MemAlloc

    +

    从指定动态内存池中申请size长度的内存。

    +

    LOS_MemFree

    +

    释放从指定动态内存中申请的内存。

    +

    LOS_MemRealloc

    +

    按size大小重新分配内存块,并将原内存块内容拷贝到新内存块。如果新内存块申请成功,则释放原内存块。

    +

    LOS_MemAllocAlign

    +

    从指定动态内存池中申请长度为size且地址按boundary字节对齐的内存。

    +

    获取内存池信息

    +

    LOS_MemPoolSizeGet

    +

    获取指定动态内存池的总大小。

    +

    LOS_MemTotalUsedGet

    +

    获取指定动态内存池的总使用量大小。

    +

    LOS_MemInfoGet

    +

    获取指定内存池的内存结构信息,包括空闲内存大小、已使用内存大小、空闲内存块数量、已使用的内存块数量、最大的空闲内存块大小。

    +

    LOS_MemPoolList

    +

    打印系统中已初始化的所有内存池,包括内存池的起始地址、内存池大小、空闲内存总大小、已使用内存总大小、最大的空闲内存块大小、空闲内存块数量、已使用的内存块数量。仅打开LOSCFG_MEM_MUL_POOL时有效。

    +

    获取内存块信息

    +

    LOS_MemFreeNodeShow

    +

    打印指定内存池的空闲内存块的大小及数量。

    +

    LOS_MemUsedNodeShow

    +

    打印指定内存池的已使用内存块的大小及数量。

    +

    检查指定内存池的完整性

    +

    LOS_MemIntegrityCheck

    +

    对指定内存池做完整性检查,仅打开LOSCFG_BASE_MEM_NODE_INTEGRITY_CHECK时有效。

    +
    + +>![](../public_sys-resources/icon-note.gif) **说明:** +>- 由于动态内存管理需要管理控制块数据结构来管理内存,这些数据结构会额外消耗内存,故实际用户可使用内存总量小于配置项OS\_SYS\_MEM\_SIZE的大小。 +>- 对齐分配内存接口LOS\_MemAllocAlign/LOS\_MemMallocAlign因为要进行地址对齐,可能会额外消耗部分内存,故存在一些遗失内存,当系统释放该对齐内存时,同时回收由于对齐导致的遗失内存。 + +### 开发流程 + +本节介绍使用动态内存的典型场景开发流程。 + +1. 初始化LOS\_MemInit。 + + 初始一个内存池后生成一个内存池控制头、尾节点EndNode,剩余的内存被标记为FreeNode内存节点。注:EndNode作为内存池末尾的节点,size为0。 + + +1. 申请任意大小的动态内存LOS\_MemAlloc。 + + 判断动态内存池中是否存在大于申请量大小的空闲内存块空间,若存在,则划出一块内存块,以指针形式返回,若不存在,返回NULL。如果空闲内存块大于申请量,需要对内存块进行分割,剩余的部分作为空闲内存块挂载到空闲内存链表上。 + + +1. 释放动态内存LOS\_MemFree。 + + 回收内存块,供下一次使用。调用LOS\_MemFree释放内存块,则会回收内存块,并且将其标记为FreeNode。在回收内存块时,相邻的FreeNode会自动合并。 + + +### 编程实例 + +本实例执行以下步骤: + +1. 初始化一个动态内存池。 +2. 从动态内存池中申请一个内存块。 +3. 在内存块中存放一个数据。 +4. 打印出内存块中的数据。 +5. 释放该内存块。 + +示例代码如下: + +``` +#include "los_memory.h" + +VOID Example_DynMem(VOID) +{ + UINT32 *mem = NULL; + UINT32 ret; + + /*初始化内存池*/ + ret = LOS_MemInit(g_testPool, TEST_POOL_SIZE); + if (LOS_OK == ret) { + printf("Mem init success!\n"); + } else { + printf("Mem init failed!\n"); + return; + } + + /*分配内存*/ + mem = (UINT32 *)LOS_MemAlloc(g_testPool, 4); + if (NULL == mem) { + printf("Mem alloc failed!\n"); + return; + } + printf("Mem alloc success!\n"); + + /*赋值*/ + *mem = 828; + printf("*mem = %d\n", *mem); + + /*释放内存*/ + ret = LOS_MemFree(g_testPool, mem); + if (LOS_OK == ret) { + printf("Mem free success!\n"); + } else { + printf("Mem free failed!\n"); + } + + return; +} +``` + +### 结果验证 + +输出结果如下: + +``` +Mem init success! +Mem alloc success! +*mem = 828 +Mem free success! +``` + diff --git a/zh-cn/device-dev/kernel/kernel-lite-mini-basic-memory-static.md b/zh-cn/device-dev/kernel/kernel-lite-mini-basic-memory-static.md new file mode 100644 index 0000000000..b52510e80b --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-mini-basic-memory-static.md @@ -0,0 +1,182 @@ +# 静态内存 + +- [运行机制](#section165473517522) +- [开发指导](#section57511620165218) + - [使用场景](#section215474911529) + - [接口说明](#section79231214539) + - [开发流程](#section1388511316548) + - [编程实例](#section17801515105519) + - [结果验证](#section11818154112319) + + +## 运行机制 + +静态内存实质上是一个静态数组,静态内存池内的块大小在初始化时设定,初始化后块大小不可变更。 + +静态内存池由一个控制块LOS\_MEMBOX\_INFO和若干相同大小的内存块LOS\_MEMBOX\_NODE构成。控制块位于内存池头部,用于内存块管理,包含内存块大小uwBlkSize,内存块数量uwBlkNum,已分配使用的内存块数量uwBlkCnt和空闲内存块链表stFreeList。内存块的申请和释放以块大小为粒度,每个内存块包含指向下一个内存块的指针pstNext。 + +**图 1** 静态内存示意图 +![](figure/静态内存示意图.png "静态内存示意图") + +## 开发指导 + +### 使用场景 + +当用户需要使用固定长度的内存时,可以通过静态内存分配的方式获取内存,一旦使用完毕,通过静态内存释放函数归还所占用内存,使之可以重复使用。 + +### 接口说明 + +OpenHarmony LiteOS-M的静态内存管理主要为用户提供以下功能,接口详细信息可以查看API参考。 + +**表 1** 静态内存模块接口 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    功能分类

    +

    接口名

    +

    描述

    +

    初始化静态内存池

    +

    LOS_MemboxInit

    +

    初始化一个静态内存池,根据入参设定其起始地址、总大小及每个内存块大小。

    +

    清除静态内存块内容

    +

    LOS_MemboxClr

    +

    清零从静态内存池中申请的静态内存块的内容。

    +

    申请、释放静态内存

    +

    LOS_MemboxAlloc

    +

    从指定的静态内存池中申请一块静态内存块。

    +

    LOS_MemboxFree

    +

    释放从静态内存池中申请的一块静态内存块。

    +

    获取、打印静态内存池信息

    +

    LOS_MemboxStatisticsGet

    +

    获取指定静态内存池的信息,包括内存池中总内存块数量、已经分配出去的内存块数量、每个内存块的大小。

    +

    LOS_ShowBox

    +

    打印指定静态内存池所有节点信息(打印等级是LOS_INFO_LEVEL),包括内存池起始地址、内存块大小、总内存块数量、每个空闲内存块的起始地址、所有内存块的起始地址。

    +
    + +>![](../public_sys-resources/icon-note.gif) **说明:** +>初始化后的内存池的内存块数量,不等于总大小除于内存块大小,因为内存池的控制块和每个内存块的控制头,都存在内存开销,设置总大小时,需要将这些因素考虑进去。 + +### 开发流程 + +本节介绍使用静态内存的典型场景开发流程。 + +1. 规划一片内存区域作为静态内存池。 +2. 调用LOS\_MemboxInit初始化静态内存池。 + + 初始化会将入参指定的内存区域分割为N块(N值取决于静态内存总大小和块大小),将所有内存块挂到空闲链表,在内存起始处放置控制头。 + +3. 调用LOS\_MemboxAlloc接口分配静态内存。 + + 系统将会从空闲链表中获取第一个空闲块,并返回该内存块的起始地址。 + +4. 调用LOS\_MemboxClr接口。 + + 将入参地址对应的内存块清零。 + +5. 调用LOS\_MemboxFree接口。 + + 将该内存块加入空闲链表。 + + +### 编程实例 + +本实例执行以下步骤: + +1. 初始化一个静态内存池。 +2. 从静态内存池中申请一块静态内存。 +3. 在内存块存放一个数据。 +4. 打印出内存块中的数据。 +5. 清除内存块中的数据。 +6. 释放该内存块。 + + 示例代码如下: + + +``` +#include "los_membox.h" + +VOID Example_StaticMem(VOID) +{ + UINT32 *mem = NULL; + UINT32 blkSize = 10; + UINT32 boxSize = 100; + UINT32 boxMem[1000]; + UINT32 ret; + + /*内存池初始化*/ + ret = LOS_MemboxInit(&boxMem[0], boxSize, blkSize); + if(ret != LOS_OK) { + printf("Membox init failed!\n"); + return; + } else { + printf("Membox init success!\n"); + } + + /*申请内存块*/ + mem = (UINT32 *)LOS_MemboxAlloc(boxMem); + if (NULL == mem) { + printf("Mem alloc failed!\n"); + return; + } + printf("Mem alloc success!\n"); + + /*赋值*/ + *mem = 828; + printf("*mem = %d\n", *mem); + + /*清除内存内容*/ + LOS_MemboxClr(boxMem, mem); + printf("Mem clear success \n *mem = %d\n", *mem); + + /*释放内存*/ + ret = LOS_MemboxFree(boxMem, mem); + if (LOS_OK == ret) { + printf("Mem free success!\n"); + } else { + printf("Mem free failed!\n"); + } + + return; +} +``` + +### 结果验证 + +输出结果如下: + +``` +Membox init success! +Mem alloc success! +*mem = 828 +Mem clear success +*mem = 0 +Mem free success! +``` + diff --git a/zh-cn/device-dev/kernel/kernel-lite-mini-basic-memory.md b/zh-cn/device-dev/kernel/kernel-lite-mini-basic-memory.md new file mode 100644 index 0000000000..e0f1da7e35 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-mini-basic-memory.md @@ -0,0 +1,9 @@ +# 内存管理 + +- **[基本概念](kernel-lite-mini-basic-memory-basic.md)** + +- **[静态内存](kernel-lite-mini-basic-memory-static.md)** + +- **[动态内存](kernel-lite-mini-basic-memory-dynamic.md)** + + diff --git "a/zh-cn/device-dev/kernel/\345\237\272\346\234\254\346\246\202\345\277\265-15.md" b/zh-cn/device-dev/kernel/kernel-lite-mini-basic-soft-basic.md similarity index 100% rename from "zh-cn/device-dev/kernel/\345\237\272\346\234\254\346\246\202\345\277\265-15.md" rename to zh-cn/device-dev/kernel/kernel-lite-mini-basic-soft-basic.md diff --git a/zh-cn/device-dev/kernel/kernel-lite-mini-basic-soft-guide.md b/zh-cn/device-dev/kernel/kernel-lite-mini-basic-soft-guide.md new file mode 100644 index 0000000000..0e9f963c0c --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-mini-basic-soft-guide.md @@ -0,0 +1,218 @@ +# 开发指导 + +- [接口说明](#section158501652121514) +- [开发流程](#section783435801510) +- [编程实例](#section460018317164) + - [实例描述](#section3741753191918) + - [示例代码](#section20760101182016) + - [结果验证](#section11244112818172) + + +## 接口说明 + +OpenHarmony LiteOS-M内核的软件定时器模块提供下面几种功能,接口详细信息可以查看API参考。 + +**表 1** 软件定时器接口 + + + + + + + + + + + + + + + + + + + + + + + + + + +

    功能分类

    +

    接口名

    +

    描述

    +

    创建、删除定时器

    +

    LOS_SwtmrCreate

    +

    创建定时器

    +

    LOS_SwtmrDelete

    +

    删除定时器

    +

    启动、停止定时器

    +

    LOS_SwtmrStart

    +

    启动定时器

    +

    LOS_SwtmrStop

    +

    停止定时器

    +

    获得软件定时器剩余Tick数

    +

    LOS_SwtmrTimeGet

    +

    获得软件定时器剩余Tick数

    +
    + +## 开发流程 + +软件定时器的典型开发流程: + +1. 配置软件定时器。 + - 确认配置项LOSCFG\_BASE\_CORE\_SWTMR和LOSCFG\_BASE\_IPC\_QUEUE为1打开状态; + - 配置LOSCFG\_BASE\_CORE\_SWTMR\_LIMIT最大支持的软件定时器数; + - 配置OS\_SWTMR\_HANDLE\_QUEUE\_SIZE软件定时器队列最大长度; + +2. 创建定时器LOS\_SwtmrCreate。 + - 创建一个指定计时时长、指定超时处理函数、指定触发模式的软件定时器; + - 返回函数运行结果,成功或失败; + +3. 启动定时器LOS\_SwtmrStart。 +4. 获得软件定时器剩余Tick数LOS\_SwtmrTimeGet。 +5. 停止定时器LOS\_SwtmrStop。 +6. 删除定时器LOS\_SwtmrDelete。 + +>![](../public_sys-resources/icon-note.gif) **说明:** +>- 软件定时器的回调函数中不要做过多操作,不要使用可能引起任务挂起或者阻塞的接口或操作。 +>- 软件定时器使用了系统的一个队列和一个任务资源,软件定时器任务的优先级设定为0,且不允许修改 。 +>- 系统可配置的软件定时器资源个数是指:整个系统可使用的软件定时器资源总个数,而并非是用户可使用的软件定时器资源个数。例如:系统软件定时器多占用一个软件定时器资源数,那么用户能使用的软件定时器资源就会减少一个。 +>- 创建单次软件定时器,该定时器超时执行完回调函数后,系统会自动删除该软件定时器,并回收资源。 +>- 创建单次不自删除属性的定时器,用户需要调用定时器删除接口删除定时器,回收定时器资源,避免资源泄露。 + +## 编程实例 + +### 实例描述 + +在下面的例子中,演示如下功能: + +1. 软件定时器创建、启动、删除、暂停、重启操作。 +2. 单次软件定时器,周期软件定时器使用方法。 + +### 示例代码 + +前提条件: + +- 在los\_config.h中,将LOSCFG\_BASE\_CORE\_SWTMR配置项打开。 +- 在los\_config.h中,将LOSCFG\_BASE\_CORE\_SWTMR\_ALIGN配置项关闭,示例代码中演示代码不涉及定时器对齐。 +- 配置好LOSCFG\_BASE\_CORE\_SWTMR\_LIMIT最大支持的软件定时器数。 +- 配置好OS\_SWTMR\_HANDLE\_QUEUE\_SIZE软件定时器队列最大长度。 + +代码实现如下: + +``` +#include "los_swtmr.h" + +/* Timer count */ +UINT32 g_timerCount1 = 0; +UINT32 g_timerCount2 = 0; + +/* 任务ID */ +UINT32 g_testTaskId01; + +void Timer1_Callback(UINT32 arg) // 回调函数1 +{ + UINT32 tick_last1; + g_timerCount1++; + tick_last1=(UINT32)LOS_TickCountGet(); // 获取当前Tick数 + printf("g_timerCount1=%d, tick_last1=%d\n", g_timerCount1, tick_last1); +} + +void Timer2_Callback(UINT32 arg) // 回调函数2 +{ + UINT32 tick_last2; + tick_last2=(UINT32)LOS_TickCountGet(); + g_timerCount2++; + printf("g_timerCount2=%d tick_last2=%d\n", g_timerCount2, tick_last2); +} + +void Timer_example(void) +{ + UINT32 id1; // timer id + UINT32 id2; // timer id + UINT32 uwTick; + + /*创建单次软件定时器,Tick数为1000,启动到1000Tick数时执行回调函数1 */ + LOS_SwtmrCreate (1000, LOS_SWTMR_MODE_ONCE, Timer1_Callback, &id1, 1); + + /*创建周期性软件定时器,每100Tick数执行回调函数2 */ + LOS_SwtmrCreate(100, LOS_SWTMR_MODE_PERIOD, Timer2_Callback, &id2, 1); + printf("create Timer1 success\n"); + + LOS_SwtmrStart (id1); //启动单次软件定时器 + printf("start Timer1 sucess\n"); + + LOS_TaskDelay(200); //延时200Tick数 + LOS_SwtmrTimeGet(id1, &uwTick); // 获得单次软件定时器剩余Tick数 + printf("uwTick =%d\n", uwTick); + + LOS_SwtmrStop(id1); // 停止软件定时器 + printf("stop Timer1 sucess\n"); + + LOS_SwtmrStart(id1); + LOS_TaskDelay(1000); + + LOS_SwtmrDelete(id1); // 删除软件定时器 + printf("delete Timer1 sucess\n"); + + LOS_SwtmrStart(id2); // 启动周期性软件定时器 + printf("start Timer2\n"); + + LOS_TaskDelay(1000); + LOS_SwtmrStop(id2); + LOS_SwtmrDelete(id2); +} + +UINT32 Example_TaskEntry(VOID) +{ + UINT32 ret; + TSK_INIT_PARAM_S task1; + + /* 锁任务调度 */ + LOS_TaskLock(); + + /* 创建任务1 */ + memset(&task1, 0, sizeof(TSK_INIT_PARAM_S)); + task1.pfnTaskEntry = (TSK_ENTRY_FUNC)Timer_example; + task1.pcName = "TimerTsk"; + task1.uwStackSize = LOSCFG_BASE_CORE_TSK_DEFAULT_STACK_SIZE; + task1.usTaskPrio = 5; + ret = LOS_TaskCreate(&g_testTaskId01, &task1); + if (ret != LOS_OK) { + printf("TimerTsk create failed.\n"); + return LOS_NOK; + } + + /* 解锁任务调度 */ + LOS_TaskUnlock(); + + return LOS_OK; +} +``` + +### 结果验证 + +编译烧录运行,输出结果如下: + +``` +create Timer1 success +start Timer1 sucess +uwTick =798 +stop Timer1 sucess +g_timerCount1=1, tick_last1=1208 +delete Timer1 sucess +start Timer2 +g_timerCount2=1 tick_last2=1313 +g_timerCount2=2 tick_last2=1413 +g_timerCount2=3 tick_last2=1513 +g_timerCount2=4 tick_last2=1613 +g_timerCount2=5 tick_last2=1713 +g_timerCount2=6 tick_last2=1813 +g_timerCount2=7 tick_last2=1913 +g_timerCount2=8 tick_last2=2013 +g_timerCount2=9 tick_last2=2113 +g_timerCount2=10 tick_last2=2213 +``` + diff --git a/zh-cn/device-dev/kernel/kernel-lite-mini-basic-soft.md b/zh-cn/device-dev/kernel/kernel-lite-mini-basic-soft.md new file mode 100644 index 0000000000..0aef797145 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-mini-basic-soft.md @@ -0,0 +1,7 @@ +# 软件定时器 + +- **[基本概念](kernel-lite-mini-basic-soft-basic.md)** + +- **[开发指导](kernel-lite-mini-basic-soft-guide.md)** + + diff --git a/zh-cn/device-dev/kernel/kernel-lite-mini-basic-task-basic.md b/zh-cn/device-dev/kernel/kernel-lite-mini-basic-task-basic.md new file mode 100644 index 0000000000..074596f401 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-mini-basic-task-basic.md @@ -0,0 +1,96 @@ +# 基本概念 + +- [任务相关概念](#section673132352511) +- [任务运行机制](#section176294469251) + +从系统角度看,任务是竞争系统资源的最小运行单元。任务可以使用或等待CPU、使用内存空间等系统资源,并独立于其它任务运行。 + +OpenHarmony LiteOS-M的任务模块可以给用户提供多个任务,实现任务间的切换,帮助用户管理业务程序流程。任务模块具有如下特性: + +- 支持多任务。 +- 一个任务表示一个线程。 +- 抢占式调度机制,高优先级的任务可打断低优先级任务,低优先级任务必须在高优先级任务阻塞或结束后才能得到调度。 +- 相同优先级任务支持时间片轮转调度方式。 +- 共有32个优先级\[0-31\],最高优先级为0,最低优先级为31。 + +## 任务相关概念 + +**任务状态** + +任务有多种运行状态。系统初始化完成后,创建的任务就可以在系统中竞争一定的资源,由内核进行调度。 + +任务状态通常分为以下四种: + +- 就绪(Ready):该任务在就绪队列中,只等待CPU。 +- 运行(Running):该任务正在执行。 +- 阻塞(Blocked):该任务不在就绪队列中。包含任务被挂起(suspend状态)、任务被延时(delay状态)、任务正在等待信号量、读写队列或者等待事件等。 +- 退出态(Dead):该任务运行结束,等待系统回收资源。 + +**任务状态迁移** + +**图 1** 任务状态示意图 +![](figure/任务状态示意图.png "任务状态示意图") + +**任务状态迁移说明:** + +- 就绪态→运行态 + + 任务创建后进入就绪态,发生任务切换时,就绪队列中最高优先级的任务被执行,从而进入运行态,同时该任务从就绪队列中移出。 + +- 运行态→阻塞态 + + 正在运行的任务发生阻塞(挂起、延时、读信号量等)时,该任务会从就绪队列中删除,任务状态由运行态变成阻塞态,然后发生任务切换,运行就绪队列中最高优先级任务。 + +- 阻塞态→就绪态(阻塞态→运行态) + + 阻塞的任务被恢复后(任务恢复、延时时间超时、读信号量超时或读到信号量等),此时被恢复的任务会被加入就绪队列,从而由阻塞态变成就绪态;此时如果被恢复任务的优先级高于正在运行任务的优先级,则会发生任务切换,该任务由就绪态变成运行态。 + +- 就绪态→阻塞态 + + 任务也有可能在就绪态时被阻塞(挂起),此时任务状态由就绪态变为阻塞态,该任务从就绪队列中删除,不会参与任务调度,直到该任务被恢复。 + +- 运行态→就绪态 + + 有更高优先级任务创建或者恢复后,会发生任务调度,此刻就绪队列中最高优先级任务变为运行态,那么原先运行的任务由运行态变为就绪态,依然在就绪队列中。 + +- 运行态→退出态 + + 运行中的任务运行结束,任务状态由运行态变为退出态。退出态包含任务运行结束的正常退出状态以及Invalid状态。例如,任务运行结束但是没有自删除,对外呈现的就是Invalid状态,即退出态。 + +- 阻塞态→退出态 + + 阻塞的任务调用删除接口,任务状态由阻塞态变为退出态。 + + +**任务ID** + +任务ID,在任务创建时通过参数返回给用户,是任务的重要标识。系统中的ID号是唯一的。用户可以通过任务ID对指定任务进行任务挂起、任务恢复、查询任务名等操作。 + +**任务优先级** + +优先级表示任务执行的优先顺序。任务的优先级决定了在发生任务切换时即将要执行的任务,就绪队列中最高优先级的任务将得到执行。 + +**任务入口函数** + +新任务得到调度后将执行的函数。该函数由用户实现,在任务创建时,通过任务创建结构体设置。 + +**任务栈** + +每个任务都拥有一个独立的栈空间,我们称为任务栈。栈空间里保存的信息包含局部变量、寄存器、函数参数、函数返回地址等。 + +**任务上下文** + +任务在运行过程中使用的一些资源,如寄存器等,称为任务上下文。当这个任务挂起时,其他任务继续执行,可能会修改寄存器等资源中的值。如果任务切换时没有保存任务上下文,可能会导致任务恢复后出现未知错误。因此在任务切换时会将切出任务的任务上下文信息,保存在自身的任务栈中,以便任务恢复后,从栈空间中恢复挂起时的上下文信息,从而继续执行挂起时被打断的代码。 + +**任务控制块TCB** + +每个任务都含有一个任务控制块\(TCB\)。TCB包含了任务上下文栈指针(stack pointer)、任务状态、任务优先级、任务ID、任务名、任务栈大小等信息。TCB可以反映出每个任务运行情况。 + +**任务切换** + +任务切换包含获取就绪队列中最高优先级任务、切出任务上下文保存、切入任务上下文恢复等动作。 + +## 任务运行机制 + +用户创建任务时,系统会初始化任务栈,预置上下文。此外,系统还会将“任务入口函数”地址放在相应位置。这样在任务第一次启动进入运行态时,将会执行“任务入口函数”。 + diff --git a/zh-cn/device-dev/kernel/kernel-lite-mini-basic-task-guide.md b/zh-cn/device-dev/kernel/kernel-lite-mini-basic-task-guide.md new file mode 100644 index 0000000000..6b42cf5b4a --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-mini-basic-task-guide.md @@ -0,0 +1,306 @@ +# 开发指导 + +- [接口说明](#section158501652121514) +- [开发流程](#section783435801510) +- [编程实例](#section460018317164) + - [结果验证](#section189023104457) + + +任务创建后,内核可以执行锁任务调度,解锁任务调度,挂起,恢复,延时等操作,同时也可以设置任务优先级,获取任务优先级。 + +## 接口说明 + +OpenHarmony LiteOS-M内核的任务管理模块提供下面几种功能,接口详细信息可以查看API参考。 + +**表 1** 任务管理模块接口 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    功能分类

    +

    接口名

    +

    描述

    +

    创建和删除任务

    +

    LOS_TaskCreateOnly

    +

    创建任务,并使该任务进入suspend状态,不对该任务进行调度。如果需要调度,可以调用LOS_TaskResume使该任务进入ready状态。

    +

    LOS_TaskCreate

    +

    创建任务,并使该任务进入ready状态,如果就绪队列中没有更高优先级的任务,则运行该任务。

    +

    LOS_TaskDelete

    +

    删除指定的任务。

    +

    控制任务状态

    +

    LOS_TaskResume

    +

    恢复挂起的任务,使该任务进入ready状态。

    +

    LOS_TaskSuspend

    +

    挂起指定的任务,然后切换任务

    +

    LOS_TaskDelay

    +

    任务延时等待,释放CPU,等待时间到期后该任务会重新进入ready状态。传入参数为Tick数目。

    +

    LOS_Msleep

    +

    传入参数为毫秒数,转换为Tick数目,调用LOS_TaskDelay。

    +

    LOS_TaskYield

    +

    当前任务时间片设置为0,释放CPU,触发调度运行就绪任务队列中优先级最高的任务。

    +

    控制任务调度

    +

    LOS_TaskLock

    +

    锁任务调度,但任务仍可被中断打断。

    +

    LOS_TaskUnlock

    +

    解锁任务调度。

    +

    LOS_Schedule

    +

    触发任务调度。

    +

    控制任务优先级

    +

    LOS_CurTaskPriSet

    +

    设置当前任务的优先级。

    +

    LOS_TaskPriSet

    +

    设置指定任务的优先级。

    +

    LOS_TaskPriGet

    +

    获取指定任务的优先级。

    +

    获取任务信息

    +

    LOS_CurTaskIDGet

    +

    获取当前任务的ID。

    +

    LOS_NextTaskIDGet

    +

    获取任务就绪队列中优先级最高的任务的ID。

    +

    LOS_NewTaskIDGet

    +

    等同LOS_NextTaskIDGet。

    +

    LOS_CurTaskNameGet

    +

    获取当前任务的名称。

    +

    LOS_TaskNameGet

    +

    获取指定任务的名称。

    +

    LOS_TaskStatusGet

    +

    获取指定任务的状态。

    +

    LOS_TaskInfoGet

    +

    获取指定任务的信息,包括任务状态、优先级、任务栈大小、栈顶指针SP、任务入口函数、已使用的任务栈大小等。

    +

    LOS_TaskIsRunning

    +

    获取任务模块是否已经开始调度运行。

    +

    任务信息维测

    +

    LOS_TaskSwitchInfoGet

    +

    获取任务切换信息,需要开启宏LOSCFG_BASE_CORE_EXC_TSK_SWITCH。

    +
    + +## 开发流程 + +以创建任务为例,讲解开发流程。 + +1. 锁任务调度LOS\_TaskLock,防止高优先级任务调度。 +2. 创建任务LOS\_TaskCreate。 +3. 解锁任务LOS\_TaskUnlock,让任务按照优先级进行调度。 +4. 延时任务LOS\_TaskDelay,任务延时等待。 +5. 挂起指定的任务LOS\_TaskSuspend,任务挂起等待恢复操作。 +6. 恢复挂起的任务LOS\_TaskResume。 + +>![](../public_sys-resources/icon-note.gif) **说明:** +>- 执行Idle任务时,会对待回收链表中的任务控制块和任务栈进行回收。 +>- 任务名是指针,并没有分配空间,在设置任务名时,禁止将局部变量的地址赋值给任务名指针。 +>- 任务栈的大小按8字节大小对齐。确定任务栈大小的原则是,够用就行,多了浪费,少了任务栈溢出。 +>- 挂起当前任务时,如果已经锁任务调度,则无法挂起。 +>- Idle任务及软件定时器任务不能被挂起或者删除。 +>- 在中断处理函数中或者在锁任务的情况下,执行LOS\_TaskDelay会失败。 +>- 锁任务调度,并不关中断,因此任务仍可被中断打断。 +>- 锁任务调度必须和解锁任务调度配合使用。 +>- 设置任务优先级时可能会发生任务调度。 +>- 可配置的系统最大任务数是指:整个系统的任务总个数,而非用户能使用的任务个数。例如:系统软件定时器多占用一个任务资源,那么用户能使用的任务资源就会减少一个。 +>- LOS\_CurTaskPriSet和LOS\_TaskPriSet接口不能在中断中使用,也不能用于修改软件定时器任务的优先级。 +>- LOS\_TaskPriGet接口传入的task ID对应的任务未创建或者超过最大任务数,统一返回-1。 +>- 在删除任务时要保证任务申请的资源(如互斥锁、信号量等)已被释放。 + +## 编程实例 + +本实例介绍基本的任务操作方法,包含2个不同优先级任务的创建、任务延时、任务锁与解锁调度、挂起和恢复等操作,阐述任务优先级调度的机制以及各接口的应用。示例代码如下: + +``` +UINT32 g_taskHiId; +UINT32 g_taskLoId; +#define TSK_PRIOR_HI 4 +#define TSK_PRIOR_LO 5 + +UINT32 Example_TaskHi(VOID) +{ + UINT32 ret; + + printf("Enter TaskHi Handler.\n"); + + /* 延时100个Ticks,延时后该任务会挂起,执行剩余任务中最高优先级的任务(TaskLo任务) */ + ret = LOS_TaskDelay(100); + if (ret != LOS_OK) { + printf("Delay TaskHi Failed.\n"); + return LOS_NOK; + } + + /* 100个Ticks时间到了后,该任务恢复,继续执行 */ + printf("TaskHi LOS_TaskDelay Done.\n"); + + /* 挂起自身任务 */ + ret = LOS_TaskSuspend(g_taskHiId); + if (ret != LOS_OK) { + printf("Suspend TaskHi Failed.\n"); + return LOS_NOK; + } + printf("TaskHi LOS_TaskResume Success.\n"); + return ret; +} + +/* 低优先级任务入口函数 */ +UINT32 Example_TaskLo(VOID) +{ + UINT32 ret; + + printf("Enter TaskLo Handler.\n"); + + /* 延时100个Ticks,延时后该任务会挂起,执行剩余任务中最高优先级的任务 */ + ret = LOS_TaskDelay(100); + if (ret != LOS_OK) { + printf("Delay TaskLo Failed.\n"); + return LOS_NOK; + } + + printf("TaskHi LOS_TaskSuspend Success.\n"); + + /* 恢复被挂起的任务g_taskHiId */ + ret = LOS_TaskResume(g_taskHiId); + if (ret != LOS_OK) { + printf("Resume TaskHi Failed.\n"); + return LOS_NOK; + } + return ret; +} + +/* 任务测试入口函数,创建两个不同优先级的任务 */ +UINT32 Example_TskCaseEntry(VOID) +{ + UINT32 ret; + TSK_INIT_PARAM_S initParam; + + /* 锁任务调度,防止新创建的任务比本任务高而发生调度 */ + LOS_TaskLock(); + + printf("LOS_TaskLock() Success!\n"); + + initParam.pfnTaskEntry = (TSK_ENTRY_FUNC)Example_TaskHi; + initParam.usTaskPrio = TSK_PRIOR_HI; + initParam.pcName = "TaskHi"; + initParam.uwStackSize = LOSCFG_BASE_CORE_TSK_DEFAULT_STACK_SIZE; + + /* 创建高优先级任务,由于锁任务调度,任务创建成功后不会马上执行 */ + ret = LOS_TaskCreate(&g_taskHiId, &initParam); + if (ret != LOS_OK) { + LOS_TaskUnlock(); + + printf("Example_TaskHi create Failed!\n"); + return LOS_NOK; + } + + printf("Example_TaskHi create Success!\n"); + + initParam.pfnTaskEntry = (TSK_ENTRY_FUNC)Example_TaskLo; + initParam.usTaskPrio = TSK_PRIOR_LO; + initParam.pcName = "TaskLo"; + initParam.uwStackSize = LOSCFG_BASE_CORE_TSK_DEFAULT_STACK_SIZE; + + /* 创建低优先级任务,由于锁任务调度,任务创建成功后不会马上执行 */ + ret = LOS_TaskCreate(&g_taskLoId, &initParam); + if (ret != LOS_OK) { + LOS_TaskUnlock(); + printf("Example_TaskLo create Failed!\n"); + return LOS_NOK; + } + + printf("Example_TaskLo create Success!\n"); + + /* 解锁任务调度,此时会发生任务调度,执行就绪队列中最高优先级任务 */ + LOS_TaskUnlock(); + + return LOS_OK; +} +``` + +### 结果验证 + +编译运行得到的结果为: + +``` +LOS_TaskLock() Success! +Example_TaskHi create Success! +Example_TaskLo create Success! +Enter TaskHi Handler. +Enter TaskLo Handler. +TaskHi LOS_TaskDelay Done. +TaskHi LOS_TaskSuspend Success. +TaskHi LOS_TaskResume Success. +``` + diff --git a/zh-cn/device-dev/kernel/kernel-lite-mini-basic-task.md b/zh-cn/device-dev/kernel/kernel-lite-mini-basic-task.md new file mode 100644 index 0000000000..8ca91b1f10 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-mini-basic-task.md @@ -0,0 +1,7 @@ +# 任务管理 + +- **[基本概念](kernel-lite-mini-basic-task-basic.md)** + +- **[开发指导](kernel-lite-mini-basic-task-guide.md)** + + diff --git "a/zh-cn/device-dev/kernel/\345\237\272\346\234\254\346\246\202\345\277\265-13.md" b/zh-cn/device-dev/kernel/kernel-lite-mini-basic-time-basic.md similarity index 100% rename from "zh-cn/device-dev/kernel/\345\237\272\346\234\254\346\246\202\345\277\265-13.md" rename to zh-cn/device-dev/kernel/kernel-lite-mini-basic-time-basic.md diff --git a/zh-cn/device-dev/kernel/kernel-lite-mini-basic-time-guide.md b/zh-cn/device-dev/kernel/kernel-lite-mini-basic-time-guide.md new file mode 100644 index 0000000000..a0328b1c7d --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-mini-basic-time-guide.md @@ -0,0 +1,159 @@ +# 开发指导 + +- [接口说明](#section158501652121514) +- [开发流程](#section783435801510) +- [编程实例](#section460018317164) + - [实例描述](#section127752801718) + - [示例代码](#section321653551711) + - [结果验证](#section4366193318167) + + +用户需要了解当前系统运行的时间以及Tick与秒、毫秒之间的转换关系时,需要使用到时间管理模块的接口。 + +## 接口说明 + +OpenHarmony LiteOS-M内核的时间管理提供下面几种功能,接口详细信息可以查看API参考。 + +**表 1** 时间管理接口 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    功能分类

    +

    接口名

    +

    描述

    +

    时间转换

    +

    LOS_MS2Tick

    +

    毫秒转换成Tick

    +

    LOS_Tick2MS

    +

    Tick转化为毫秒

    +

    OsCpuTick2MS

    +

    Cycle数目转化为毫秒,使用2个

    +

    UINT32类型的数值分别表示结果数值的高、低32位。

    +

    OsCpuTick2US

    +

    Cycle数目转化为微秒,使用2个

    +

    UINT32类型的数值分别表示结果数值的高、低32位。

    +

    时间统计

    +

    LOS_SysClockGet

    +

    获取系统时钟

    +

    LOS_TickCountGet

    +

    获取自系统启动以来的Tick数

    +

    LOS_CyclePerTickGet

    +

    每个Tick多少Cycle数

    +
    + +## 开发流程 + +时间管理的典型开发流程: + +1. 根据实际需求,完成板级配置适配,并配置系统主时钟频率OS\_SYS\_CLOCK(单位Hz)和LOSCFG\_BASE\_CORE\_TICK\_PER\_SECOND。OS\_SYS\_CLOCK的默认值基于硬件平台配置。 +2. 调用时钟转换/统计接口。 + +>![](../public_sys-resources/icon-note.gif) **说明:** +>- 时间管理不是单独的功能模块,依赖于OS\_SYS\_CLOCK和LOSCFG\_BASE\_CORE\_TICK\_PER\_SECOND两个配置选项。 +>- 系统的Tick数在关中断的情况下不进行计数,故系统Tick数不能作为准确时间使用。 +>- 配置选项维护在开发板工程的文件target\_config.h。 + +## 编程实例 + +### 实例描述 + +在下面的例子中,介绍了时间管理的基本方法,包括: + +1. 时间转换:将毫秒数转换为Tick数,或将Tick数转换为毫秒数。 +2. 时间统计:每Tick的Cycle数、自系统启动以来的Tick数和延迟后的Tick数。 + +### 示例代码 + +前提条件: + +- 使用每秒的Tick数LOSCFG\_BASE\_CORE\_TICK\_PER\_SECOND的默认值100。 +- 配好OS\_SYS\_CLOCK系统主时钟频率。 + +时间转换: + +``` +VOID Example_TransformTime(VOID) +{ + UINT32 ms; + UINT32 tick; + + tick = LOS_MS2Tick(10000); // 10000ms转换为tick + dprintf("tick = %d \n", tick); + ms = LOS_Tick2MS(100); // 100tick转换为ms + dprintf("ms = %d \n", ms); +} +``` + +时间统计和时间延迟: + +``` +VOID Example_GetTime(VOID) +{ + UINT32 cyclePerTick; + UINT64 tickCount; + + cyclePerTick = LOS_CyclePerTickGet(); + if(0 != cyclePerTick) { + dprintf("LOS_CyclePerTickGet = %d \n", cyclePerTick); + } + + tickCount = LOS_TickCountGet(); + if(0 != tickCount) { + dprintf("LOS_TickCountGet = %d \n", (UINT32)tickCount); + } + + LOS_TaskDelay(200); + tickCount = LOS_TickCountGet(); + if(0 != tickCount) { + dprintf("LOS_TickCountGet after delay = %d \n", (UINT32)tickCount); + } +} +``` + +### 结果验证 + +编译运行得到的结果为: + +时间转换: + +``` +tick = 1000 +ms = 1000 +``` + +时间统计和时间延迟: + +``` +LOS_CyclePerTickGet = 495000 +LOS_TickCountGet = 1 +LOS_TickCountGet after delay = 201 +``` + diff --git a/zh-cn/device-dev/kernel/kernel-lite-mini-basic.md b/zh-cn/device-dev/kernel/kernel-lite-mini-basic.md new file mode 100644 index 0000000000..fd6774bee4 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-mini-basic.md @@ -0,0 +1,15 @@ +# 基础内核 + +- **[中断管理](kernel-lite-mini-basic-interrupt.md)** + +- **[任务管理](kernel-lite-mini-basic-task.md)** + +- **[内存管理](kernel-lite-mini-basic-memory.md)** + +- **[内核通信机制](kernel-lite-mini-basic-ipc.md)** + +- **[时间管理](kernel-lite-basic-mini-time.md)** + +- **[软件定时器](kernel-lite-mini-basic-soft.md)** + + diff --git "a/zh-cn/device-dev/kernel/\345\237\272\346\234\254\346\246\202\345\277\265-17.md" b/zh-cn/device-dev/kernel/kernel-lite-mini-extend-cpup-basic.md similarity index 100% rename from "zh-cn/device-dev/kernel/\345\237\272\346\234\254\346\246\202\345\277\265-17.md" rename to zh-cn/device-dev/kernel/kernel-lite-mini-extend-cpup-basic.md diff --git "a/zh-cn/device-dev/kernel/\345\274\200\345\217\221\346\214\207\345\257\274-18.md" b/zh-cn/device-dev/kernel/kernel-lite-mini-extend-cpup-guide.md similarity index 100% rename from "zh-cn/device-dev/kernel/\345\274\200\345\217\221\346\214\207\345\257\274-18.md" rename to zh-cn/device-dev/kernel/kernel-lite-mini-extend-cpup-guide.md diff --git a/zh-cn/device-dev/kernel/kernel-lite-mini-extend-cpup.md b/zh-cn/device-dev/kernel/kernel-lite-mini-extend-cpup.md new file mode 100644 index 0000000000..e49d8a7175 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-mini-extend-cpup.md @@ -0,0 +1,7 @@ +# CPU占用率 + +- **[基本概念](kernel-lite-mini-extend-cpup-basic.md)** + +- **[开发指导](kernel-lite-mini-extend-cpup-guide.md)** + + diff --git a/zh-cn/device-dev/kernel/kernel-lite-mini-extend-file-fat.md b/zh-cn/device-dev/kernel/kernel-lite-mini-extend-file-fat.md new file mode 100644 index 0000000000..d96f14f343 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-mini-extend-file-fat.md @@ -0,0 +1,176 @@ +# FAT + +- [基本概念](#section1772629121418) +- [开发指导](#section1149072811148) + - [驱动适配](#section19174939191414) + - [开发流程](#section131211626151513) + - [编程实例](#section206071303163) + - [实例描述](#section45337345313) + - [示例代码](#section119813171539) + - [结果验证](#section7987101232311) + + +## 基本概念 + +FAT文件系统是File Allocation Table(文件配置表)的简称,主要包括DBR区、FAT区、DATA区三个区域。其中,FAT区各个表项记录存储设备中对应簇的信息,包括簇是否被使用、文件下一个簇的编号、是否文件结尾等。FAT文件系统有FAT12、FAT16、FAT32等多种格式,其中,12、16、32表示对应格式中FAT表项的字节数。FAT文件系统支持多种介质,特别在可移动存储介质(U盘、SD卡、移动硬盘等)上广泛使用,使嵌入式设备和Windows、Linux等桌面系统保持很好的兼容性,方便用户管理操作文件。 + +OpenHarmony内核支持FAT12、FAT16与FAT32三种格式的FAT文件系统,具有代码量小、资源占用小、可裁切、支持多种物理介质等特性,并且与Windows、Linux等系统保持兼容,支持多设备、多分区识别等功能。OpenHarmony内核支持硬盘多分区,可以在主分区以及逻辑分区上创建FAT文件系统。 + +## 开发指导 + +### 驱动适配 + +FAT文件系统的使用需要底层MMC相关驱动的支持。在一个带MMC存储设备的板子上运行FATFS,需要: + +1、适配板端EMMC驱动,实现disk\_status、disk\_initialize、disk\_read、disk\_write、disk\_ioctl接口; + +2、新增fs\_config.h文件,配置FS\_MAX\_SS(存储设备最大sector大小)、FF\_VOLUME\_STRS(分区名)等信息,例如: + +``` +#define FF_VOLUME_STRS "system", "inner", "update", "user" +#define FS_MAX_SS 512 +#define FAT_MAX_OPEN_FILES 50 +``` + +### 开发流程 + +>![](../public_sys-resources/icon-note.gif) **说明:** +>- FATFS文件与目录操作: +> - 单个文件大小不超过4G。 +> - 支持同时打开的文件数最大为FAT\_MAX\_OPEN\_FILES,文件夹数最大为FAT\_MAX\_OPEN\_DIRS。 +> - 暂不支持根目录管理,文件/目录名均以分区名开头,例如“user/testfile”就是在“user”分区下名为“testfile”的文件或目录。 +> - 若需要同时多次打开同一文件,必须全部使用只读方式(O\_RDONLY)。以可写方式(O\_RDWR、O\_WRONLY等)只能打开一次。 +> - 读写指针未分离,例如以O\_APPEND(追加写)方式打开文件后,读指针也在文件尾,从头读文件前需要用户手动置位。 +> - 暂不支持文件与目录的权限管理。 +> - stat及fstat接口暂不支持查询修改时间、创建时间和最后访问时间。微软FAT协议不支持1980年以前的时间。 +>- FATFS分区挂载与卸载: +> - 支持以只读属性挂载分区。当mount函数的入参为MS\_RDONLY时,所有的带有写入的接口,如write、mkdir、unlink,以及非O\_RDONLY属性的open,将均被拒绝。 +> - mount支持通过MS\_REMOUNT标记修改已挂载分区的权限。 +> - 在umount操作前,需确保所有目录及文件全部关闭。 +> - umount2支持通过MNT\_FORCE参数强制关闭所有文件与文件夹并umount,但可能造成数据丢失,请谨慎使用。 +>- FATFS支持重新划分存储设备分区、格式化分区,对应接口为fatfs\_fdisk与fatfs\_format: +> - 在fatfs\_format操作之前,若需要格式化的分区已挂载,需确保分区中的所有目录及文件全部关闭,并且分区umount。 +> - 在fatfs\_fdisk操作前,需要该设备中的所有分区均已umount。 +> - fatfs\_fdisk与fatfs\_format会造成设备数据丢失,请谨慎使用。 + +### 编程实例 + +### 实例描述 + +本实例实现以下功能: + +1. 创建目录“user/test” +2. 在“user/test”目录下创建文件“file.txt” +3. 在文件起始位置写入“Hello OpenHarmony!” +4. 将文件内容刷入设备中 +5. 设置偏移到文件起始位置 +6. 读取文件内容 +7. 关闭文件 +8. 删除文件 +9. 删除目录 + +### 示例代码 + +前提条件: + +- 系统已将MMC设备分区挂载到user目录 + +代码实现如下: + +``` +#include +#include +#include "sys/stat.h" +#include "fcntl.h" +#include "unistd.h" + +#define LOS_OK 0 +#define LOS_NOK -1 + +int FatfsTest(void) +{ + int ret; + int fd = -1; + ssize_t len; + off_t off; + char dirName[20] = "user/test"; + char fileName[20] = "user/test/file.txt"; + char writeBuf[20] = "Hello OpenHarmony!"; + char readBuf[20] = {0}; + + /* 创建目录“user/test” */ + ret = mkdir(dirName, 0777); + if (ret != LOS_OK) { + printf("mkdir failed.\n"); + return LOS_NOK; + } + + /* 创建可读写文件"user/test/file.txt" */ + fd = open(fileName, O_RDWR | O_CREAT, 0777); + if (fd < 0) { + printf("open file failed.\n"); + return LOS_NOK; + } + + /* 将writeBuf中的内容写入文件 */ + len = write(fd, writeBuf, strlen(writeBuf)); + if (len != strlen(writeBuf)) { + printf("write file failed.\n"); + return LOS_NOK; + } + + /* 将文件内容刷入存储设备中 */ + ret = fsync(fd); + if (ret != LOS_OK) { + printf("fsync failed.\n"); + return LOS_NOK; + } + + /* 将读写指针偏移至文件头 */ + off = lseek(fd, 0, SEEK_SET); + if (off != 0) { + printf("lseek failed.\n"); + return LOS_NOK; + } + + /* 将文件内容读出至readBuf中,读取长度为readBuf大小 */ + len = read(fd, readBuf, sizeof(readBuf)); + if (len != strlen(writeBuf)) { + printf("read file failed.\n"); + return LOS_NOK; + } + printf("%s\n", readBuf); + + /* 关闭文件 */ + ret = close(fd); + if (ret != LOS_OK) { + printf("close failed.\n"); + return LOS_NOK; + } + + /* 删除文件"user/test/file.txt" */ + ret = unlink(fileName); + if (ret != LOS_OK) { + printf("unlink failed.\n"); + return LOS_NOK; + } + + /* 删除目录“user/test” */ + ret = rmdir(dirName); + if (ret != LOS_OK) { + printf("rmdir failed.\n"); + return LOS_NOK; + } + + return LOS_OK; +} +``` + +### 结果验证 + +编译运行得到的结果为: + +``` +Hello OpenHarmony! +``` + diff --git a/zh-cn/device-dev/kernel/kernel-lite-mini-extend-file-lit-basic.md b/zh-cn/device-dev/kernel/kernel-lite-mini-extend-file-lit-basic.md new file mode 100644 index 0000000000..17423ee5c4 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-mini-extend-file-lit-basic.md @@ -0,0 +1,72 @@ +# 基本概念 + +- [运行机制](#section10284121317365) + - [日志方式](#section13804114513361) + - [Cow机制](#section172771130193610) + - [LittleFS掉电保护](#section42941021173614) + + +LittleFS主要用在微控制器和Flash上,是一种嵌入式文件系统,具有掉电恢复、擦写均衡、节省ROM/RAM空间等特点。 + +## 运行机制 + +最经典的掉电保护方法有两种,一种是使用日志,一种是通过COW方式。LittleFS结合了两种方法,并优化了两种方案的缺点,提供了一套掉电保护策略 + +### 日志方式 + +**图 1** 日志方式示意图 +![](figure/日志方式示意图.png "日志方式示意图") + +具体步骤为: + +1. 写入数据之前,先在日志区存储开始标志,记录要写入的数据位置和大小; +2. 待写入的数据写入日志区; +3. 待写入的数据写入数据区; +4. 写入完成之后,在日志区记录结束标志。 + +模拟掉电场景: + +1. 步骤1完成,步骤2没有完成;重启之后,保持原来的数据,日志无效; +2. 步骤1,2完成了,步骤3没有完成,尝试把步骤2的数据写入到数据区; +3. 步骤1,2,3完成了,步骤4没有完成,同样尝试把步骤2的数据写入到数据区; + +### Cow机制 + +**图 2** Cow机制示意图 +![](figure/Cow机制示意图.png "Cow机制示意图") + +具体步骤为: + +1. 想更新节点F的数据,先申请一个新的节点,把F的旧数据拷贝过去,然后更新新的数据; +2. 把父节点的指针指向新的节点,去掉旧节点的指针。 + +模拟掉电场景: + +步骤1完成了,步骤2没有完成,则使用旧的数据,新的节点变成孤儿节点。 + +### LittleFS掉电保护 + +LittleFS结合了日志方式和COW机制两种方式进行掉电保护,并且优化了两种方案。 + +文件系统有三要素,超级块,inode,以及数据,对应LittleFS来说,它把超级块以及inode通过日志的方式存储,两种采用统一的存储结构,后文称两者为元数据;普通数据则采用cow的方式存储,采用czt逆序链表的方式。 + +![](figure/zh-cn_image_0000001124307264.png) + +**元数据的存储** + +元数据(对应root,dir)采用双block的方式存储,互为备份,每个block都有一个revision序号,值越大,表示block的数据越新,每个block默认可以存储最多0xff个文件的数据,如果超过这个值,则需要compact(压缩)。 + +Compact是干什么呢? 即当数据的大小大于某个值的时候,把数据整合,剔除同一个id的旧的数据,然后写入到备份block里面。如图所示: + +**图 3** 元数据存储示意图 +![](figure/元数据存储示意图.png "元数据存储示意图") + +**普通数据的存储** + +LittleFS的数据采用链表的方式逆向管理。 + +![](figure/zh-cn_image_0000001132085260.png) + +1. 采用逆向的指针,这样常规的追加数据,不需要额外的开销来重新建立所有的索引; +2. 每个偶数block有多个指针,指向更远的数据,这样可以在检索的时候加快速度。 + diff --git "a/zh-cn/device-dev/kernel/\345\274\200\345\217\221\346\214\207\345\257\274-22.md" b/zh-cn/device-dev/kernel/kernel-lite-mini-extend-file-lit-guide.md similarity index 100% rename from "zh-cn/device-dev/kernel/\345\274\200\345\217\221\346\214\207\345\257\274-22.md" rename to zh-cn/device-dev/kernel/kernel-lite-mini-extend-file-lit-guide.md diff --git a/zh-cn/device-dev/kernel/kernel-lite-mini-extend-file-lit.md b/zh-cn/device-dev/kernel/kernel-lite-mini-extend-file-lit.md new file mode 100644 index 0000000000..b0ffac3d67 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-mini-extend-file-lit.md @@ -0,0 +1,7 @@ +# LittleFS + +- **[基本概念](kernel-lite-mini-extend-file-lit-basic.md)** + +- **[开发指导](kernel-lite-mini-extend-file-lit-guide.md)** + + diff --git a/zh-cn/device-dev/kernel/kernel-lite-mini-extend-file.md b/zh-cn/device-dev/kernel/kernel-lite-mini-extend-file.md new file mode 100644 index 0000000000..c7ee5fabfd --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-mini-extend-file.md @@ -0,0 +1,204 @@ +# 文件系统 + +当前支持的文件系统有FATFS与LittleFS,支持的功能如下表所示: + +**表 1** ****功能列表 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    功能分类

    +

    接口名

    +

    描述

    +

    FATFS

    +

    LITTELFS

    +

    文件操作

    +

    open

    +

    打开文件

    +

    支持

    +

    支持

    +

    close

    +

    关闭文件

    +

    支持

    +

    支持

    +

    read

    +

    读取文件内容

    +

    支持

    +

    支持

    +

    write

    +

    往文件写入内容

    +

    支持

    +

    支持

    +

    lseek

    +

    设置文件偏移位置

    +

    支持

    +

    支持

    +

    unlink

    +

    删除文件

    +

    支持

    +

    支持

    +

    rename

    +

    重命名文件

    +

    支持

    +

    支持

    +

    fstat

    +

    通过文件句柄获取文件信息

    +

    支持

    +

    支持

    +

    stat

    +

    通过文件路径名获取文件信息

    +

    支持

    +

    支持

    +

    fsync

    +

    文件内容刷入存储设备

    +

    支持

    +

    支持

    +

    目录操作

    +

    mkdir

    +

    创建目录

    +

    支持

    +

    支持

    +

    opendir

    +

    打开目录

    +

    支持

    +

    支持

    +

    readdir

    +

    读取目录项内容

    +

    支持

    +

    支持

    +

    closedir

    +

    关闭目录

    +

    支持

    +

    支持

    +

    rmdir

    +

    删除目录

    +

    支持

    +

    支持

    +

    分区操作

    +

    mount

    +

    分区挂载

    +

    支持

    +

    支持

    +

    umount

    +

    分区卸载

    +

    支持

    +

    支持

    +

    umount2

    +

    分区卸载,可通过MNT_FORCE参数进行强制卸载

    +

    支持

    +

    不支持

    +

    statfs

    +

    获取分区信息

    +

    支持

    +

    不支持

    +
    + +- **[FAT](kernel-lite-mini-extend-file-fat.md)** + +- **[LittleFS](kernel-lite-mini-extend-file-lit.md)** + + diff --git a/zh-cn/device-dev/kernel/kernel-lite-mini-extend-support.md b/zh-cn/device-dev/kernel/kernel-lite-mini-extend-support.md new file mode 100644 index 0000000000..c0b1ed5291 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-mini-extend-support.md @@ -0,0 +1,86 @@ +# C++支持 + +- [基本概念](#section11374125415814) + - [运行机制](#section125251720195) + +- [开发指导](#section166302407911) + - [接口说明](#section1881825119919) + - [开发流程](#section76371145108) + - [编程实例](#section994427141111) + + +## 基本概念 + +C++作为目前使用最广泛的编程语言之一,支持类、封装、重载等特性,是在C语言基础上开发的一种面向对象的编程语言。 + +### 运行机制 + +C++代码的识别主要由编译器支持,系统主要对全局对象进行构造函数调用,进行初始化操作。 + +## 开发指导 + +### 接口说明 + +**表 1** C++支持接口 + + + + + + + + + + + + +

    功能分类

    +

    接口名

    +

    描述

    +

    使用C++特性的前置条件

    +

    LOS_CppSystemInit

    +

    C++构造函数初始化

    +
    + +### 开发流程 + +使用C++特性之前,需要调用函数LOS\_CppSystemInit,实现C++构造函数初始化,其中被初始化的构造函数存在init\_array这个段中,段区间通过变量\_\_init\_array\_start\_\_、\_\_init\_array\_end\_\_传递。 + +**表 2** 参数说明 + + + + + + + + + + + + + +

    参数

    +

    参数说明

    +

    __init_array_start__

    +

    init_array段起始位置

    +

    __init_array_end__

    +

    init_array段结束位置

    +
    + +>![](../public_sys-resources/icon-note.gif) **说明:** +>调用该函数时,一定要在c++业务前。另外部分与系统资源强相关的类或接口,如std::thread,std::mutex等,在三方编译器使用的c库非musl c时,存在兼容性问题,不建议使用。 + +### 编程实例 + +``` +void app_init(void) +{ +...... +/* 启动阶段C++初始化 */ +LOS_CppSystemInit((UINTPTR)&__init_array_start__, (UINTPTR)&__init_array_end__); +/* C++业务 */ +...... +} +``` + diff --git a/zh-cn/device-dev/kernel/kernel-lite-mini-extend.md b/zh-cn/device-dev/kernel/kernel-lite-mini-extend.md new file mode 100644 index 0000000000..1d413abe90 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-mini-extend.md @@ -0,0 +1,9 @@ +# 扩展组件 + +- **[C++支持](kernel-lite-mini-extend-support.md)** + +- **[CPU占用率](kernel-lite-mini-extend-cpup.md)** + +- **[文件系统](kernel-lite-mini-extend-file.md)** + + diff --git a/zh-cn/device-dev/kernel/kernel-lite-mini-inner-debug-cet.md b/zh-cn/device-dev/kernel/kernel-lite-mini-inner-debug-cet.md new file mode 100644 index 0000000000..20a2b532d3 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-mini-inner-debug-cet.md @@ -0,0 +1,85 @@ +# 踩内存检测 + +- [基础概念](#section17368154517335) +- [功能配置](#section4696190123420) +- [开发指导](#section672362973417) + - [开发流程](#section026014863416) + - [编程实例](#section186311302356) + - [示例代码](#section12709533354) + - [结果验证](#section81214126369) + + +## 基础概念 + +踩内存检测机制作为内核的可选功能,用于检测动态内存池的完整性。通过该机制,可以及时发现内存池是否发生了踩内存问题,并给出错误信息,便于及时发现系统问题,提高问题解决效率,降低问题定位成本。 + +## 功能配置 + +LOSCFG\_BASE\_MEM\_NODE\_INTEGRITY\_CHECK:开关宏,默认关闭;若打开这个功能,在target\_config.h中将这个宏定义为1。 + +1. 开启这个功能,每次申请内存,会实时检测内存池的完整性。 +2. 如果不开启该功能,也可以调用LOS\_MemIntegrityCheck接口检测,但是每次申请内存时,不会实时检测内存完整性,而且由于节点头没有魔鬼数字(开启时才有,省内存),检测的准确性也会相应降低,但对于系统的性能没有影响,故根据实际情况开关该功能。 + +由于该功能只会检测出哪个内存节点被破坏了,并给出前节点信息(因为内存分布是连续的,当前节点最有可能被前节点破坏)。如果要进一步确认前节点在哪里申请的,需开启内存泄漏检测功能,通过LR记录,辅助定位。 + +>![](../public_sys-resources/icon-caution.gif) **注意:** +>开启该功能,节点头多了魔鬼数字字段,会增大节点头大小。由于实时检测完整性,故性能影响较大;若性能敏感的场景,可以不开启该功能,使用LOS\_MemIntegrityCheck接口检测。 + +## 开发指导 + +### 开发流程 + +通过调用LOS\_MemIntegrityCheck接口检测内存池是否发生了踩内存,如果没有踩内存问题,那么接口返回0且没有log输出;如果存在踩内存问题,那么会输出相关log,详见下文编程实例的结果输出。 + +### 编程实例 + +本实例实现如下功能: + +1. 申请两个物理上连续的内存块; +2. 通过memset构造越界访问,踩到下个节点的头4个字节; +3. 调用LOS\_MemIntegrityCheck检测是否发生踩内存。 + +### 示例代码 + +代码实现如下: + +``` +#include +#include +#include "los_memory.h" +#include "los_config.h" + +void MemIntegrityTest(void) +{ + /* 申请两个物理连续的内存块 */ + void *ptr1 = LOS_MemAlloc(LOSCFG_SYS_HEAP_ADDR, 8); + void *ptr2 = LOS_MemAlloc(LOSCFG_SYS_HEAP_ADDR, 8); + /* 第一个节点内存块大小是8字节,那么12字节的清零,会踩到第二个内存节点的节点头,构造踩内存场景 */ + memset(ptr1, 0, 8 + 4); + LOS_MemIntegrityCheck(LOSCFG_SYS_HEAP_ADDR); +} +``` + +### 结果验证 + +编译运行输出log如下: + +``` +[ERR][OsMemMagicCheckPrint], 2028, memory check error! +memory used but magic num wrong, magic num = 0x00000000 /* 提示信息,检测到哪个字段被破坏了,用例构造了将下个节点的头4个字节清零,即魔鬼数字字段 */ + + broken node head: 0x20003af0 0x00000000 0x80000020, prev node head: 0x20002ad4 0xabcddcba 0x80000020 +/* 被破坏节点和其前节点关键字段信息,分别为其前节点地址、节点的魔鬼数字、节点的sizeAndFlag;可以看出被破坏节点的魔鬼数字字段被清零,符合用例场景 */ + + broken node head LR info: /* 节点的LR信息需要开启内存检测功能才有有效输出 */ + LR[0]:0x0800414e + LR[1]:0x08000cc2 + LR[2]:0x00000000 + + pre node head LR info: /* 通过LR信息,可以在汇编文件中查找前节点是哪里申请,然后排查其使用的准确性 */ + LR[0]:0x08004144 + LR[1]:0x08000cc2 + LR[2]:0x00000000 +[ERR]Memory interity check error, cur node: 0x20003b10, pre node: 0x20003af0 /* 被破坏节点和其前节点的地址 */ +``` + diff --git a/zh-cn/device-dev/kernel/kernel-lite-mini-inner-debug-det.md b/zh-cn/device-dev/kernel/kernel-lite-mini-inner-debug-det.md new file mode 100644 index 0000000000..7f49df4fc8 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-mini-inner-debug-det.md @@ -0,0 +1,128 @@ +# 内存泄漏检测 + +- [基础概念](#section1026719436293) +- [功能配置](#section13991354162914) +- [开发指导](#section95828159308) + - [开发流程](#section369844416304) + - [编程实例](#section460801313313) + - [示例代码](#section96539275311) + - [结果验证](#section20527343183119) + + +## 基础概念 + +内存泄漏检测机制作为内核的可选功能,用于辅助定位动态内存泄漏问题。开启该功能,动态内存机制会自动记录申请内存时的函数调用关系(下文简称LR)。如果出现泄漏,就可以利用这些记录的信息,找到内存申请的地方,方便进一步确认。 + +## 功能配置 + +1. LOSCFG\_MEM\_LEAKCHECK:开关宏,默认关闭;若打开这个功能,在target\_config.h中将这个宏定义为1。 +2. LOSCFG\_MEM\_RECORD\_LR\_CNT:记录的LR层数,默认3层;每层LR消耗sizeof\(void \*\)字节数的内存。 +3. LOSCFG\_MEM\_OMIT\_LR\_CNT:忽略的LR层数,默认4层,即从调用LOS\_MemAlloc的函数开始记录,可根据实际情况调整。为啥需要这个配置?有3点原因如下: + - LOS\_MemAlloc接口内部也有函数调用; + - 外部可能对LOS\_MemAlloc接口有封装; + - LOSCFG\_MEM\_RECORD\_LR\_CNT 配置的LR层数有限; + + +正确配置这个宏,将无效的LR层数忽略,就可以记录有效的LR层数,节省内存消耗。 + +## 开发指导 + +### 开发流程 + +该调测功能可以分析关键的代码逻辑中是否存在内存泄漏。开启这个功能,每次申请内存时,会记录LR信息。在需要检测的代码段前后,调用LOS\_MemUsedNodeShow接口,每次都会打印指定内存池已使用的全部节点信息,对比前后两次的节点信息,新增的节点信息就是疑似泄漏的内存节点。通过LR,可以找到具体申请的代码位置,进一步确认是否泄漏。 + +调用LOS\_MemUsedNodeShow接口输出的节点信息格式如下:每1行为一个节点信息;第1列为节点地址,可以根据这个地址,使用GDB等手段查看节点完整信息;第2列为节点的大小,等于节点头大小+数据域大小;第3\~5列为函数调用关系LR地址,可以根据这个值,结合汇编文件,查看该节点具体申请的位置。 + +``` +node size LR[0] LR[1] LR[2] +0x10017320: 0x528 0x9b004eba 0x9b004f60 0x9b005002 +0x10017848: 0xe0 0x9b02c24e 0x9b02c246 0x9b008ef0 +0x10017928: 0x50 0x9b008ed0 0x9b068902 0x9b0687c4 +0x10017978: 0x24 0x9b008ed0 0x9b068924 0x9b0687c4 +0x1001799c: 0x30 0x9b02c24e 0x9b02c246 0x9b008ef0 +0x100179cc: 0x5c 0x9b02c24e 0x9b02c246 0x9b008ef0 +``` + +>![](../public_sys-resources/icon-caution.gif) **注意:** +>开启内存检测会影响内存申请的性能,且每个内存节点都会记录LR地址,内存开销也加大。 + +### 编程实例 + +本实例实现如下功能:构建内存泄漏代码段。 + +1. 调用LOS\_MemUsedNodeShow接口,输出全部节点信息打印; +2. 申请内存,但没有释放,模拟内存泄漏; +3. 再次调用LOS\_MemUsedNodeShow接口,输出全部节点信息打印; +4. 将两次log进行对比,得出泄漏的节点信息; +5. 通过LR地址,找出泄漏的代码位置; + +### 示例代码 + +代码实现如下: + +``` +#include +#include +#include "los_memory.h" +#include "los_config.h" + +void MemLeakTest(void) +{ + LOS_MemUsedNodeShow(LOSCFG_SYS_HEAP_ADDR); + void *ptr1 = LOS_MemAlloc(LOSCFG_SYS_HEAP_ADDR, 8); + void *ptr2 = LOS_MemAlloc(LOSCFG_SYS_HEAP_ADDR, 8); + LOS_MemUsedNodeShow(LOSCFG_SYS_HEAP_ADDR); +} +``` + +### 结果验证 + +编译运行输出log如下: + +``` +node size LR[0] LR[1] LR[2] +0x20001b04: 0x24 0x08001a10 0x080035ce 0x080028fc +0x20002058: 0x40 0x08002fe8 0x08003626 0x080028fc +0x200022ac: 0x40 0x08000e0c 0x08000e56 0x0800359e +0x20002594: 0x120 0x08000e0c 0x08000e56 0x08000c8a +0x20002aac: 0x56 0x08000e0c 0x08000e56 0x08004220 + +node size LR[0] LR[1] LR[2] +0x20001b04: 0x24 0x08001a10 0x080035ce 0x080028fc +0x20002058: 0x40 0x08002fe8 0x08003626 0x080028fc +0x200022ac: 0x40 0x08000e0c 0x08000e56 0x0800359e +0x20002594: 0x120 0x08000e0c 0x08000e56 0x08000c8a +0x20002aac: 0x56 0x08000e0c 0x08000e56 0x08004220 +0x20003ac4: 0x1d 0x08001458 0x080014e0 0x080041e6 +0x20003ae0: 0x1d 0x080041ee 0x08000cc2 0x00000000 +``` + +对比两次log,差异如下,这些内存节点就是疑似泄漏的内存块: + +``` +0x20003ac4: 0x1d 0x08001458 0x080014e0 0x080041e6 +0x20003ae0: 0x1d 0x080041ee 0x08000cc2 0x00000000 +``` + +部分汇编文件如下: + +``` + MemLeakTest: + 0x80041d4: 0xb510 PUSH {R4, LR} + 0x80041d6: 0x4ca8 LDR.N R4, [PC, #0x2a0] ; g_memStart + 0x80041d8: 0x0020 MOVS R0, R4 + 0x80041da: 0xf7fd 0xf93e BL LOS_MemUsedNodeShow ; 0x800145a + 0x80041de: 0x2108 MOVS R1, #8 + 0x80041e0: 0x0020 MOVS R0, R4 + 0x80041e2: 0xf7fd 0xfbd9 BL LOS_MemAlloc ; 0x8001998 + 0x80041e6: 0x2108 MOVS R1, #8 + 0x80041e8: 0x0020 MOVS R0, R4 + 0x80041ea: 0xf7fd 0xfbd5 BL LOS_MemAlloc ; 0x8001998 + 0x80041ee: 0x0020 MOVS R0, R4 + 0x80041f0: 0xf7fd 0xf933 BL LOS_MemUsedNodeShow ; 0x800145a + 0x80041f4: 0xbd10 POP {R4, PC} + 0x80041f6: 0x0000 MOVS R0, R0 +``` + +其中,通过查找0x080041ee,就可以发现该内存节点是在MemLeakTest接口里申请的且是没有释放的。 + diff --git a/zh-cn/device-dev/kernel/kernel-lite-mini-inner-debug-mes.md b/zh-cn/device-dev/kernel/kernel-lite-mini-inner-debug-mes.md new file mode 100644 index 0000000000..0dd4f93042 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-mini-inner-debug-mes.md @@ -0,0 +1,107 @@ +# 内存信息统计 + +- [基础概念](#section52691565235) +- [功能配置](#section470611682411) +- [开发指导](#section9368374243) + - [开发流程](#section679912407257) + - [编程实例](#section1025453412611) + - [示例代码](#section165277971315) + - [结果验证](#section3460102414271) + + +## 基础概念 + +内存信息包括内存池大小、内存使用量、剩余内存大小、最大空闲内存、内存水线、内存节点数统计、碎片率等。 + +- 内存水线:即内存池的最大使用量,每次申请和释放时,都会更新水线值,实际业务可根据该值,优化内存池大小; + +- 碎片率:衡量内存池的碎片化程度,碎片率高表现为内存池剩余内存很多,但是最大空闲内存块很小,可以用公式(fragment=100-最大空闲内存块大小/剩余内存大小)来度量; + +- 其他参数:通过调用接口(详见[内存管理](kernel-lite-mini-basic-memory.md)章节接口说明),扫描内存池的节点信息,统计出相关信息。 + +## 功能配置 + +LOSCFG\_MEM\_WATERLINE:开关宏,默认打开;若关闭这个功能,在target\_config.h中将这个宏定义为0。如需获取内存水线,需要打开该配置。 + +## 开发指导 + +### 开发流程 + +关键结构体介绍: + +``` +typedef struct { + UINT32 totalUsedSize; // 内存池的内存使用量 + UINT32 totalFreeSize; // 内存池的剩余内存大小 + UINT32 maxFreeNodeSize; // 内存池的最大空闲内存块大小 + UINT32 usedNodeNum; // 内存池的非空闲内存块个数 + UINT32 freeNodeNum; // 内存池的空闲内存块个数 +#if (LOSCFG_MEM_WATERLINE == 1) // 默认打开,如需关闭,在target_config.h中将该宏设置为0 + UINT32 usageWaterLine; // 内存池的水线值 +#endif +} LOS_MEM_POOL_STATUS; +``` + +- 内存水线获取:调用LOS\_MemInfoGet接口,第1个参数是内存池首地址,第2个参数是LOS\_MEM\_POOL\_STATUS类型的句柄,其中字段usageWaterLine即水线值。 + +- 内存碎片率计算:同样调用LOS\_MemInfoGet接口,可以获取内存池的剩余内存大小和最大空闲内存块大小,然后根据公式(fragment=100-最大空闲内存块大小/剩余内存大小)得出此时的动态内存池碎片率。 + +### 编程实例 + +本实例实现如下功能: + +1.创建一个监控线程,用于获取内存池的信息; + +2.调用LOS\_MemInfoGet接口,获取内存池的基础信息; + +3.利用公式算出使用率及碎片率。 + +### 示例代码 + +代码实现如下: + +``` +#include +#include +#include "los_task.h" +#include "los_memory.h" +#include "los_config.h" + +void MemInfoTaskFunc(void) +{ + LOS_MEM_POOL_STATUS poolStatus = {0}; + LOS_MemInfoGet(pool, &poolStatus); + /* 算出内存池当前的碎片率百分比 */ + unsigned char fragment = 100 - poolStatus.maxFreeNodeSize * 100 / poolStatus.totalFreeSize; + /* 算出内存池当前的使用率百分比 */ + unsigned char usage = LOS_MemTotalUsedGet(pool) * 100 / LOS_MemPoolSizeGet(pool); + printf("usage = %d, fragment = %d, maxFreeSize = %d, totalFreeSize = %d, waterLine = %d\n", usage, fragment, poolStatus.maxFreeNodeSize, + poolStatus.totalFreeSize, poolStatus.usageWaterLine); +} + +int MemTest(void) +{ + unsigned int ret; + unsigned int taskID; + TSK_INIT_PARAM_S taskStatus = {0}; + taskStatus.pfnTaskEntry = (TSK_ENTRY_FUNC)MemInfoTaskFunc; + taskStatus.uwStackSize = 0x1000; + taskStatus.pcName = "memInfo"; + taskStatus.usTaskPrio = 10; + ret = LOS_TaskCreate(&taskID, &taskStatus); + if (ret != LOS_OK) { + printf("task create failed\n"); + return -1; + } + return 0; +} +``` + +### 结果验证 + +编译运行输出的结果如下: + +``` +usage = 22, fragment = 3, maxFreeSize = 49056, totalFreeSize = 50132, waterLine = 1414 +``` + diff --git a/zh-cn/device-dev/kernel/kernel-lite-mini-inner-debug.md b/zh-cn/device-dev/kernel/kernel-lite-mini-inner-debug.md new file mode 100644 index 0000000000..0c4474cd15 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-mini-inner-debug.md @@ -0,0 +1,11 @@ +# 内存调测 + +内存调测方法旨在辅助定位动态内存相关问题,提供了基础的动态内存池信息统计手段,向用户呈现内存池水线、碎片率等信息;提供了内存泄漏检测手段,方便用户准确定位存在内存泄漏的代码行,也可以辅助分析系统各个模块内存的使用情况;提供了踩内存检测手段,可以辅助定位越界踩内存的场景。 + +- **[内存信息统计](kernel-lite-mini-inner-debug-mes.md)** + +- **[内存泄漏检测](kernel-lite-mini-inner-debug-det.md)** + +- **[踩内存检测](kernel-lite-mini-inner-debug-cet.md)** + + diff --git a/zh-cn/device-dev/kernel/kernel-lite-mini-inner-exception.md b/zh-cn/device-dev/kernel/kernel-lite-mini-inner-exception.md new file mode 100644 index 0000000000..5828d645f1 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-mini-inner-exception.md @@ -0,0 +1,329 @@ +# 异常调测 + +- [基本概念](#section2741911123412) +- [运行机制](#section16618124317346) +- [接口说明](#section16111931351) +- [使用指导](#section16317163520350) + - [开发流程](#section13457839133618) + - [定位流程](#section197332323815) + + +## 基本概念 + +OpenHarmony LiteOS-M提供异常接管调测手段,帮助开发者定位分析问题。异常接管是操作系统对运行期间发生的异常情况进行处理的一系列动作,例如打印异常发生时异常类型、发生异常时的系统状态、当前函数的调用栈信息、CPU现场信息、任务调用堆栈等信息。 + +## 运行机制 + +栈帧用于保存函数调用过程中的函数参数、变量、返回值等信息。调用函数时,会创建子函数的栈帧,同时将函数入参、局部变量、寄存器入栈。栈帧从高地址向低地址生长。以ARM32 CPU架构为例,每个栈帧中都会保存PC、LR、SP和FP寄存器的历史值。LR链接寄存器(Link Register)指向函数的返回地址,FP帧指针寄存器(Frame Point)指向当前函数的父函数的栈帧起始地址。利用FP寄存器可以得到父函数的栈帧,从栈帧中获取父函数的FP,就可以得到祖父函数的栈帧,以此类推,可以追溯程序调用栈,得到函数间的调用关系。 + +当系统发生异常时,系统打印异常函数的栈帧中保存的寄存器内容,以及父函数、祖父函数的栈帧中的LR链接寄存器、FP帧指针寄存器内容,用户就可以据此追溯函数间的调用关系,定位异常原因。 + +堆栈分析原理如下图所示,实际堆栈信息根据不同CPU架构有所差异,此处仅做示意。 + +**图 1** 堆栈分析原理示意图 +![](figure/堆栈分析原理示意图.png "堆栈分析原理示意图") + +图中不同颜色的寄存器表示不同的函数。可以看到函数调用过程中,寄存器的保存。通过FP寄存器,栈回溯到异常函数的父函数,继续按照规律对栈进行解析,推出函数调用关系,方便用户定位问题。 + +## 接口说明 + +OpenHarmony LiteOS-M内核的回溯栈模块提供下面几种功能,接口详细信息可以查看API参考。 + +**表 1** 回溯栈模块接口 + + + + + + + + + + + + + + + +

    功能分类

    +

    接口名

    +

    描述

    +

    回溯栈接口

    +

    LOS_BackTrace

    +

    打印调用处的函数调用栈关系。

    +

    LOS_RecordLR

    +

    在无法打印的场景,用该接口获取调用处的函数调用栈关系。

    +
    + +## 使用指导 + +### 开发流程 + +开启异常调测的典型流程如下: + +1. 配置异常接管相关宏。 + + 需要在target\_config.h头文件中修改配置: + + + + + + + + + + + + + + + + +

    配置项

    +

    含义

    +

    设置值

    +

    LOSCFG_BACKTRACE_DEPTH

    +

    函数调用栈深度,默认15层

    +

    15

    +

    LOSCFG_BACKTRACE_TYPE

    +

    回溯栈类型:

    +

    0:表示关闭该功能;

    +

    1:表示支持Cortex-m系列硬件的函数调用栈解析;

    +

    2:表示用于Risc-v系列硬件的函数调用栈解析;

    +

    根据工具链类型设置1或2

    +
    + + +1. 使用示例中有问题的代码,编译、运行工程,在串口终端中查看异常信息输出。示例代码模拟异常代码,实际产品开发时使用异常调测机制定位异常问题。 + + 本示例演示异常输出,包含1个任务,该任务入口函数模拟若干函数调用,最终调用一个模拟异常的函数。代码实现如下: + + ``` + #include + #include "los_config.h" + #include "los_interrupt.h" + #include "los_task.h" + + UINT32 g_taskExcId; + #define TSK_PRIOR 4 + + /* 模拟异常函数 */ + + UINT32 Get_Result_Exception_0(UINT16 dividend){ + UINT32 divisor = 0; + UINT32 result = dividend / divisor; + return result; + } + + UINT32 Get_Result_Exception_1(UINT16 dividend){ + return Get_Result_Exception_0(dividend); + } + + UINT32 Get_Result_Exception_2(UINT16 dividend){ + return Get_Result_Exception_1(dividend); + } + + UINT32 Example_Exc(VOID) + { + UINT32 ret; + + printf("Enter Example_Exc Handler.\r\n"); + + /* 模拟函数调用 */ + ret = Get_Result_Exception_2(TSK_PRIOR); + printf("Divided result =%u.\r\n", ret); + + printf("Exit Example_Exc Handler.\r\n"); + return ret; + } + + + /* 任务测试入口函数,创建一个会发生异常的任务 */ + UINT32 Example_Exc_Entry(VOID) + { + UINT32 ret; + TSK_INIT_PARAM_S initParam; + + /* 锁任务调度,防止新创建的任务比本任务高而发生调度 */ + LOS_TaskLock(); + + printf("LOS_TaskLock() Success!\r\n"); + + initParam.pfnTaskEntry = (TSK_ENTRY_FUNC)Example_Exc; + initParam.usTaskPrio = TSK_PRIOR; + initParam.pcName = "Example_Exc"; + initParam.uwStackSize = LOSCFG_SECURE_STACK_DEFAULT_SIZE; + /* 创建高优先级任务,由于锁任务调度,任务创建成功后不会马上执行 */ + ret = LOS_TaskCreate(&g_taskExcId, &initParam); + if (ret != LOS_OK) { + LOS_TaskUnlock(); + + printf("Example_Exc create Failed!\r\n"); + return LOS_NOK; + } + + printf("Example_Exc create Success!\r\n"); + + /* 解锁任务调度,此时会发生任务调度,执行就绪队列中最高优先级任务 */ + LOS_TaskUnlock(); + + return LOS_OK; + } + ``` + + +1. 上述代码串口终端输出异常信息如下: + + ``` + entering kernel init... + LOS_TaskLock() Success! + Example_Exc create Success! + Entering scheduler + Enter Example_Exc Handler. + *************Exception Information************** + Type = 10 + ThrdPid = 4 + Phase = exc in task + FaultAddr = 0xabababab + Current task info: + Task name = Example_Exc + Task ID = 4 + Task SP = 0x200051ac + Task ST = 0x20004ff0 + Task SS = 0x200 + Exception reg dump: + PC = 0x80037da + LR = 0x80037fe + SP = 0x20005190 + R0 = 0x4 + R1 = 0x40 + R2 = 0x4 + R3 = 0x0 + R4 = 0x4040404 + R5 = 0x5050505 + R6 = 0x6060606 + R7 = 0x20005190 + R8 = 0x8080808 + R9 = 0x9090909 + R10 = 0x10101010 + R11 = 0x11111111 + R12 = 0x12121212 + PriMask = 0x0 + xPSR = 0x41000000 + ----- backtrace start ----- + backtrace 0 -- lr = 0x800381a + backtrace 1 -- lr = 0x8003836 + backtrace 2 -- lr = 0x8005a4e + backtrace 3 -- lr = 0x8000494 + backtrace 4 -- lr = 0x8008620 + backtrace 5 -- lr = 0x800282c + backtrace 6 -- lr = 0x80008a0 + backtrace 7 -- lr = 0x80099f8 + backtrace 8 -- lr = 0x800a01a + backtrace 9 -- lr = 0x800282c + backtrace 10 -- lr = 0x80008a0 + backtrace 11 -- lr = 0x80099f8 + backtrace 12 -- lr = 0x8009bf0 + backtrace 13 -- lr = 0x8009c52 + backtrace 14 -- lr = 0x80099aa + ----- backtrace end ----- + + TID Priority Status StackSize WaterLine StackPoint TopOfStack EventMask SemID name + --- -------- -------- --------- ---------- ---------- ---------- --------- ----- ---- + 0 0 Pend 0x2d0 0x104 0x200029bc 0x200027f0 0x0 0xffff Swt_Task + 1 31 Ready 0x500 0x44 0x20002f84 0x20002ac8 0x0 0xffff IdleCore000 + 2 6 Ready 0x1000 0x44 0x20003f94 0x20002fd8 0x0 0xffff TaskSampleEntry1 + 3 7 Ready 0x1000 0x44 0x20004f9c 0x20003fe0 0x0 0xffff TaskSampleEntry2 + 4 4 Running 0x200 0xec 0x200051ac 0x20004ff0 0x0 0xffff Example_Exc + + OS exception NVIC dump: + interrupt enable register, base address: 0xe000e100, size: 0x20 + 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 + interrupt pending register, base address: 0xe000e200, size: 0x20 + 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 + interrupt active register, base address: 0xe000e300, size: 0x20 + 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 + interrupt priority register, base address: 0xe000e400, size: 0xf0 + 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 + 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 + 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 + 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 + interrupt exception register, base address: 0xe000ed18, size: 0xc + 0x0 0x0 0xf0f00000 + interrupt shcsr register, base address: 0xe000ed24, size: 0x4 + 0x70008 + interrupt control register, base address: 0xe000ed04, size: 0x4 + 0x400f806 + + memory pools check: + system heap memcheck over, all passed! + memory pool check end! + ``` + + +### 定位流程 + +异常接管一般的定位步骤如下: + +1. 打开编译后生成的镜像反汇编(asm)文件。如果默认没有生成,可以使用objdump工具生成,命令为: + + ``` + arm-none-eabi-objdump -S -l XXX.elf + ``` + + +1. 搜索PC指针(指向当前正在执行的指令)在asm中的位置,找到发生异常的函数。 + + PC地址指向发生异常时程序正在执行的指令。在当前执行的二进制文件对应的asm文件中,查找PC值0x80037da,找到当前CPU正在执行的指令行,反汇编如下所示: + + ``` + UINT32 Get_Result_Exception_0(UINT16 dividend){ + 80037c8: b480 push {r7} + 80037ca: b085 sub sp, #20 + 80037cc: af00 add r7, sp, #0 + 80037ce: 4603 mov r3, r0 + 80037d0: 80fb strh r3, [r7, #6] + kernel_liteos_m\targets\cortex-m7_nucleo_f767zi_gcc/Core/Src/exc_example.c:10 + UINT32 divisor = 0; + 80037d2: 2300 movs r3, #0 + 80037d4: 60fb str r3, [r7, #12] + kernel_liteos_m\targets\cortex-m7_nucleo_f767zi_gcc/Core/Src/exc_example.c:11 + UINT32 result = dividend / divisor; + 80037d6: 88fa ldrh r2, [r7, #6] + 80037d8: 68fb ldr r3, [r7, #12] + 80037da: fbb2 f3f3 udiv r3, r2, r3 + 80037de: 60bb str r3, [r7, #8] + ``` + + +1. 可以看到: + 1. 异常时CPU正在执行的指令是udiv r3, r2, r3,其中r3取值为0,导致发生除零异常。 + 2. 异常发生在函数Get\_Result\_Exception\_0中。 + +2. 根据LR值查找异常函数的父函数。 + + 包含LR值0x80037fe的反汇编如下所示: + + ``` + 080037ec : + Get_Result_Exception_1(): + kernel_liteos_m\targets\cortex-m7_nucleo_f767zi_gcc/Core/Src/exc_example.c:15 + UINT32 Get_Result_Exception_1(UINT16 dividend){ + 80037ec: b580 push {r7, lr} + 80037ee: b082 sub sp, #8 + 80037f0: af00 add r7, sp, #0 + 80037f2: 4603 mov r3, r0 + 80037f4: 80fb strh r3, [r7, #6] + kernel_liteos_m\targets\cortex-m7_nucleo_f767zi_gcc/Core/Src/exc_example.c:16 + return Get_Result_Exception_0(dividend); + 80037f6: 88fb ldrh r3, [r7, #6] + 80037f8: 4618 mov r0, r3 + 80037fa: f7ff ffe5 bl 80037c8 + 80037fe: 4603 mov r3, r0 + ``` + + +1. LR值80037fe上一行是bl 80037c8 ,此处调用了异常函数,调用异常函数的父函数为Get\_Result\_Exception\_1\(\)。 +2. 重复步骤3,解析异常信息中backtrace start至backtrace end之间的LR值,得到调用产生异常的函数调用栈关系,找到异常原因。 + diff --git "a/zh-cn/device-dev/kernel/Trace\350\260\203\346\265\213.md" b/zh-cn/device-dev/kernel/kernel-lite-mini-inner-trace.md similarity index 100% rename from "zh-cn/device-dev/kernel/Trace\350\260\203\346\265\213.md" rename to zh-cn/device-dev/kernel/kernel-lite-mini-inner-trace.md diff --git a/zh-cn/device-dev/kernel/kernel-lite-mini-inner.md b/zh-cn/device-dev/kernel/kernel-lite-mini-inner.md new file mode 100644 index 0000000000..63cd8f58de --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-mini-inner.md @@ -0,0 +1,9 @@ +# 内核调测 + +- **[内存调测](kernel-lite-mini-inner-debug.md)** + +- **[异常调测](kernel-lite-mini-inner-exception.md)** + +- **[Trace调测](kernel-lite-mini-inner-trace.md)** + + diff --git a/zh-cn/device-dev/kernel/kernel-lite-mini-m.md b/zh-cn/device-dev/kernel/kernel-lite-mini-m.md new file mode 100644 index 0000000000..3548ae04b6 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-mini-m.md @@ -0,0 +1,62 @@ +# 内核概述 + +- [内核简介](#section1429342661510) + - [cpu体系架构支持](#section48891456112819) + - [运行机制](#section4599142312817) + + +## 内核简介 + +OpenHarmony LiteOS-M内核是面向IoT领域构建的轻量级物联网操作系统内核,具有小体积、低功耗、高性能的特点。其代码结构简单,主要包括内核最小功能集、内核抽象层、可选组件以及工程目录等。OpenHarmony LiteOS-M内核架构包含硬件相关层以及硬件无关层,如下图所示,其中Kernel Arch模块属于硬件相关层,该模块按不同编译工具链、芯片架构分类,提供统一的HAL(Hardware Abstraction Layer)接口,提升了硬件易适配性,满足AIoT类型丰富的硬件和编译工具链的拓展;Components等其他模块属于硬件无关层,其中Kernel Task等内核模块提供基础能力,Components模块提供网络、文件系统等组件能力,Utils模块提供错误处理、调测等能力,KAL(Kernel Abstraction Layer)模块提供统一的标准接口。 + +**图 1** 内核架构图 +![](figure/内核架构图.png "内核架构图") + +### cpu体系架构支持 + +CPU体系架构分为通用架构定义和特定架构定义两层,通用架构定义层为所有体系架构都需要支持和实现的接口,特定架构定义层为特定体系架构所特有的部分。在新增一个体系架构的时候,必须需要实现通用架构定义层,如果该体系架构还有特有的功能,可以在特定架构定义层来实现。 + +**表 1** CPU体系架构规则 + + + + + + + + + + + + + + + + + + + + +

    规则

    +

    通用体系架构层

    +

    特定体系架构层

    +

    头文件位置

    +

    kernel/arch/include

    +

    kernel/arch/<arch>/<arch>/<toolchain>/

    +

    头文件命名

    +

    los_<function>.h

    +

    los_arch_<function>.h

    +

    函数命名

    +

    Halxxxx

    +

    Halxxxx

    +
    + +LiteOS-M已经支持ARM Cortex-M3、ARM Cortex-M4、ARM Cortex-M7、ARM Cortex-M33、RISC-V等主流架构,如果需要扩展CPU体系架构,请参考[芯片架构适配点](https://gitee.com/openharmony/docs/blob/master/zh-cn/device-dev/porting/%E7%A7%BB%E6%A4%8D%E6%A6%82%E8%BF%B0.md#%E8%8A%AF%E7%89%87%E6%9E%B6%E6%9E%84%E9%80%82%E9%85%8D%E7%82%B9)。 + +### 运行机制 + +在开发板配置文件target\_config.h配置系统时钟、每秒Tick数,可以对任务、内存、IPC、异常处理模块进行裁剪配置。系统启动时,根据配置进行指定模块的初始化。内核启动流程包含外设初始化、系统时钟配置、内核初始化、操作系统启动等,详见内核启动流程图。 + +**图 2** 内核启动流程 +![](figure/内核启动流程.png "内核启动流程") + diff --git a/zh-cn/device-dev/kernel/kernel-lite-mini-start.md b/zh-cn/device-dev/kernel/kernel-lite-mini-start.md new file mode 100644 index 0000000000..13cd49841e --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-mini-start.md @@ -0,0 +1,47 @@ +# 快速入门 + +- [搭建开发环境](#section157851447151716) +- [获取OpenHarmony源码](#section381985201816) +- [获取示例工程源码](#section204717216181) +- [编译运行](#section9772514181917) + +OpenHarmony LiteOS-M内核的编译构建系统是一个基于gn和ninja的组件化构建系统,支持按组件配置、裁剪和拼装,按需构建出定制化的产品。编译构建系统的详细信息可以参考[考编译构建概](../subsystems/subsys-build-mini-lite.md#section10958256161119)。本文主要介绍如何基于gn和ninja编译LiteOS-M工程。 + +## 搭建开发环境 + +在搭建各个开发板环境前,需要完成OpenHarmony系统基础环境搭建。系统基础环境主要是指OpenHarmony的编译环境和开发环境,详细介绍请参考官方站点[搭建系统基础环境](../quick-start/quickstart-lite-env-setup-des.md)。开发者需要根据环境搭建文档,完成下述软件的安装:Python3.7+、gn、ninja、hb。对于LiteOS-M内核,还需要安装ARM GCC编译工具链。 + +## 获取OpenHarmony源码 + +开发者需要在Linux服务器上通过Git克隆获取OpenHarmony最新源码,详细的源码获取方式,请见[源码获取](../get-code/sourcecode-acquire.md)。获取OpenHarmony完整仓代码后,假设克隆目录为\~/openHarmony。 + +## 获取示例工程源码 + +以开发板Nucleo-F767Zi为例,演示如何编译运行OpenHarmony LiteOS-M内核工程。在本地目录,执行下述命令克隆示例代码。 + +``` +git clone https://gitee.com/harylee/nucleo_f767zi.git +``` + +假设克隆到的代码目录为\~/nucleo\_f767zi。 执行如下命令把代码目录的device、vendor目录复制到openHarmony工程的相应目录。 + +``` +cp -r ~/nucleo_f767zi/device/st ~/openHarmony/device/st +cp -r ~/nucleo_f767zi/vendor/st ~/openHarmony/vendor/st +``` + +关于示例代码目录的说明,可以参考资料站点[板级目录规范](https://gitee.com/openharmony/docs/blob/master/zh-cn/device-dev/porting/%E7%A7%BB%E6%A4%8D%E6%A6%82%E8%BF%B0-0.md#section6204129143013)。如果需要自行移植开发板,请参考[板级系统移植](https://gitee.com/openharmony/docs/blob/master/zh-cn/device-dev/porting/%E6%9D%BF%E7%BA%A7%E7%B3%BB%E7%BB%9F%E7%A7%BB%E6%A4%8D.md)。 + +## 编译运行 + +编译运行前,把交叉编译工具链bin目录配置到PATH环境变量中或者在device/st/nucleo\_f767zi/liteos\_m/config.gni文件中把board\_toolchain\_path配置项设置为交叉编译工具链bin目录。 在OpenHarmony根目录,执行hb set设置产品路径,选择nucleo\_f767zi产品,然后执行hb build开启编译。如下: + +``` +user@dev:~/OpenHarmony$ hb set +[OHOS INFO] Input code path: # 直接按回车,然后选择nucleo_f767zi产品即可 +OHOS Which product do you need? nucleo_f767zi@st +user@dev:~/OpenHarmony$ hb build +``` + +最终的镜像生成在\~/openHarmony/out/nucleo\_f767zi/目录中,通过STM32 ST-LINK Utility软件将镜像文件下载至单板查看运行效果。 + diff --git a/zh-cn/device-dev/kernel/kernel-lite-mini.md b/zh-cn/device-dev/kernel/kernel-lite-mini.md new file mode 100644 index 0000000000..f531579ddb --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-mini.md @@ -0,0 +1,13 @@ +# 轻量系统内核 + +- **[内核概述](kernel-lite-mini-m.md)** + +- **[基础内核](kernel-lite-mini-basic.md)** + +- **[扩展组件](kernel-lite-mini-extend.md)** + +- **[内核调测](kernel-lite-mini-inner.md)** + +- **[附录](kernel-lite-mini-app.md)** + + diff --git a/zh-cn/device-dev/kernel/kernel-lite-small-basic.md b/zh-cn/device-dev/kernel/kernel-lite-small-basic.md new file mode 100644 index 0000000000..d9cac957f9 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-small-basic.md @@ -0,0 +1,11 @@ +# 基础内核 + +- **[进程](kernel-lite-small-process.md)** + +- **[线程](kernel-lite-small-thread.md)** + +- **[内存](kernel-lite-small-memory.md)** + +- **[网络](kernel-lite-small-net.md)** + + diff --git a/zh-cn/device-dev/kernel/FAT.md b/zh-cn/device-dev/kernel/kernel-lite-small-file-fat.md old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/kernel/FAT.md rename to zh-cn/device-dev/kernel/kernel-lite-small-file-fat.md diff --git a/zh-cn/device-dev/kernel/JFFS2.md b/zh-cn/device-dev/kernel/kernel-lite-small-file-jffs.md old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/kernel/JFFS2.md rename to zh-cn/device-dev/kernel/kernel-lite-small-file-jffs.md diff --git a/zh-cn/device-dev/kernel/kernel-lite-small-file-nfs.md b/zh-cn/device-dev/kernel/kernel-lite-small-file-nfs.md new file mode 100644 index 0000000000..dec5a7023b --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-small-file-nfs.md @@ -0,0 +1,163 @@ +# NFS + +- [概述](#section18322139164413) +- [注意事项](#section532912331467) +- [开发指导](#section166873374711) + +## 概述 + +NFS是Network File System(网络文件系统)的缩写。它最大的功能是可以通过网络,让不同的机器、不同的操作系统彼此分享其他用户的文件。因此,用户可以简单地将它看做是一个文件系统服务,在一定程度上相当于Windows环境下的共享文件夹。 + +NFS客户端用户,能够将网络远程的NFS服务端分享的目录挂载到本地端的机器中,运行程序和共享文件,但不占用当前的系统资源,所以,在本地端的机器看起来,远程服务端的目录就好像是自己的一个磁盘一样。 + +## 注意事项 + +- 当前NFS文件不支持权限控制,请在创建NFS目录和文件时使用777权限。 + +- 当前NFS文件不支读阻塞和写阻塞。 + +- 当前NFS文件不支持信号功能。 + +- 当前NFS文件系统mount路径长度(不包含IP的长度)不超过255个字符,超过时返回ENAMETOOLONG错误。 + +- 当前NFS文件支持的操作有:open, close, read, write, seek, dup, dup2, sync, opendir, closedir, readdir, readdir\_r, rewinddir, scandir, statfs, remove, unlink, mkdir, rmdir, rename, stat, stat64, seek64, mmap, mount, umount。 + +- 当前NFS支持TCP和UDP两种传输层协议,默认使用TCP。 + +- open打开一个文件,参数有O\_TRUNC时,必须同时拥有写的权限,才会将文件中的内容清空。 + +- 在文件未关闭的情况下,rename\(\)函数重命名A为B之后,不会改变文件fd。 + +- NFS功能目前处于beta测试阶段,可能存在功能不稳定的情况,建议您不要用于正式商用产品当中。 + + +## 开发指导 + +1. **搭建NFS服务器**。 + + 这里以Ubuntu操作系统为例,说明服务器端设置步骤。 + + 1. 安装NFS服务器软件。 + + 设置好Ubuntu系统的下载源,保证网络连接好的情况下执行: + + ``` + sudo apt-get install nfs-kernel-server + ``` + + 2. 创建用于挂载的目录并设置完全权限 + + ``` + mkdir /home/sqbin/nfs + sudo chmod 777 /home/sqbin/nfs + ``` + + 3. 设置和启动NFS server。 + + 修改NFS配置文件/etc/exports,添加如下一行: + + ``` + /home/sqbin/nfs *(rw,no_root_squash,async) + ``` + + 其中/home/sqbin/nfs是NFS共享的根目录。 + + 执行以下命令启动NFS server: + + ``` + sudo /etc/init.d/nfs-kernel-server start + ``` + + 执行以下命令重启NFS server: + + ``` + sudo /etc/init.d/nfs-kernel-server restart + ``` + + +2. **设置单板为NFS客户端**。 + + 本指导中的NFS客户端指运行OpenHarmony内核的设备。 + + 1. 硬件连接设置。 + + OpenHarmony内核设备连接到NFS服务器的网络。设置两者IP,使其处于同一网段。比如,设置NFS服务器的IP为10.67.212.178/24,设置OpenHarmony内核设备IP为10.67.212.3/24,注意:此IP为内网私有IP地址,用户使用时有差异,以用户实际IP为准。 + + OpenHarmony内核设备上的IP信息可通过ifconfig命令查看。 + + 2. 启动网络,确保单板到NFS服务器之间的网络通畅。 + + 启动以太网或者其他类型网络,使用ping命令检查到服务器的网络是否通畅。 + + ``` + OHOS # ping 10.67.212.178 + [0]Reply from 10.67.212.178: time=1ms TTL=63 + [1]Reply from 10.67.212.178: time=0ms TTL=63 + [2]Reply from 10.67.212.178: time=1ms TTL=63 + [3]Reply from 10.67.212.178: time=1ms TTL=63 + --- 10.67.212.178 ping statistics --- + 4 packets transmitted, 4 received, 0 loss + ``` + + 客户端NFS初始化,运行命令: + + ``` + OHOS # mkdir /nfs + OHOS # mount 10.67.212.178:/home/sqbin/nfs /nfs nfs 1011 1000 + ``` + + 将从串口得到如下回应信息,表明初始化NFS客户端成功。 + + ``` + OHOS # mount 10.67.212.178:/home/sqbin/nfs /nfs nfs 1011 1000 + Mount nfs on 10.67.212.178:/home/sqbin/nfs, uid:1011, gid:1000 + Mount nfs finished. + ``` + + 该命令将服务器10.67.212.178上的/home/sqbin/nfs目录mount在OpenHarmony内核设备上的/nfs上。 + + >![](../public_sys-resources/icon-note.gif) **说明:** + >本例默认nfs server已经配置可用,即示例中服务器10.67.212.178上的/home/sqbin/nfs已配置可访问。 + + mount命令的格式为: + + ``` + mount nfs + ``` + + 其中“SERVER\_IP“表示服务器的IP地址;“SERVER\_PATH“表示服务器端NFS共享目录路径;“CLIENT\_PATH“表示设备上的NFS路径。 + + 如果不想有NFS访问权限限制,请在Linux命令行将NFS根目录权限设置成777: + + ``` + chmod -R 777 /home/sqbin/nfs + ``` + + 至此,NFS客户端设置完毕。NFS文件系统已成功挂载。 + + +3. **利用NFS共享文件**。 + + 在NFS服务器下新建目录dir,并保存。在OpenHarmony内核下运行ls命令: + + ``` + OHOS # ls /nfs + ``` + + 则可从串口得到如下回应: + + ``` + OHOS # ls /nfs + Directory /nfs: + drwxr-xr-x 0 u:0 g:0 dir + ``` + + 可见,刚刚在NFS服务器上新建的dir目录已同步到客户端\(OpenHarmony内核系统\)的/nfs目录,两者保持同步。 + + 同样地,在客户端\(OpenHarmony内核系统\)上创建文件和目录,在NFS服务器上也可以访问,读者可自行体验。 + + **平台差异性:** + + 目前,NFS客户端仅支持NFS v3部分规范要求,因此对于规范支持不全的服务器,无法完全兼容。在开发测试过程中,建议使用Linux的NFS server,因为其对NFS支持很完善。 + + diff --git a/zh-cn/device-dev/kernel/RAMFS.md b/zh-cn/device-dev/kernel/kernel-lite-small-file-ramfs.md old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/kernel/RAMFS.md rename to zh-cn/device-dev/kernel/kernel-lite-small-file-ramfs.md diff --git a/zh-cn/device-dev/kernel/kernel-lite-small-file-vfs.md b/zh-cn/device-dev/kernel/kernel-lite-small-file-vfs.md new file mode 100644 index 0000000000..c7d197be36 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-small-file-vfs.md @@ -0,0 +1,171 @@ +# VFS + +- [概述](#section132540468341) +- [基本概念](#section229417111227) +- [运作机制](#section18114182834215) +- [注意事项](#section18311145173712) +- [开发指导](#section422619258380) +- [编程实例](#section180311121420) +- [结果验证](#section16772334714) + +## 概述 + +## 基本概念 + +VFS是Virtual File System(虚拟文件系统)的缩写,它不是一个实际的文件系统,而是一个异构文件系统之上的软件粘合层,为用户提供统一的类Unix文件操作接口。 + +由于不同类型的文件系统接口不统一,若系统中有多个文件系统类型,访问不同的文件系统就需要使用不同的非标准接口。而通过在系统中添加VFS层,提供统一的抽象接口,屏蔽了底层异构类型的文件系统的差异,使得访问文件系统的系统调用不用关心底层的存储介质和文件系统类型,提高开发效率。VFS和各个具体文件系统的关系如下: + +**图 1** VFS和各个文件系统的关系 +![](figure/VFS和各个文件系统的关系.png "VFS和各个文件系统的关系") + +OpenHarmony内核中,VFS框架是通过在内存中的树结构来实现的,树的每个结点都是一个inode结构体。设备注册和文件系统挂载后会根据路径在树中生成相应的结点。VFS最主要是两个功能: + +- 查找节点。 +- 统一调用(标准)。 + +## 运作机制 + +通过VFS层,可以使用标准的Unix文件操作函数(如open、read、write等)来实现对不同介质上不同文件系统的访问。 + +VFS框架内存中的inode树结点有三种类型: + +- 虚拟结点:作为VFS框架的虚拟文件,保持树的连续性,如/usr、/usr/bin。 +- 设备结点:/dev目录下,对应一个设备,如/dev/mmcblk0。 +- 挂载点:挂载具体文件系统,如/vs/sd、/mnt。 + +**图 2** 文件系统树形结构 +![](figure/文件系统树形结构.png "文件系统树形结构") + +## 注意事项 + +- VFS下的所有文件系统,创建的目录名和文件名最多只可以有255个字节,能支持的全路径长度最长为259字节,超过这个路径长度的文件和目录无法创建。 + +- 目前仅有jffs2文件系统支持完整的权限控制。 + +- inode\_find\(\)函数调用后会使查找到的inode节点连接数+1,调用完成后需要调用inode\_release\(\)使连接数-1,所以一般inode\_find\(\)要和inode\_release\(\)配套使用。 + +- 设备分为字符设备和块设备,为了块设备上的文件系统系统数据安全,需挂载相应文件系统后通过文件系统接口操作数据。 + +- los\_vfs\_init\(\)只能调用一次,多次调用将会造成文件系统异常。 + +- 目前OpenHarmony内核所有的文件系统中的文件名和目录名中只可以出现“-” 与“\_”两种特殊字符,使用其他特殊字符可能造成的后果不可预知,请谨慎为之。 + +- OpenHarmony内核支持open\(\)+O\_DIRECTORY的方法获取目录数据信息。 + +- 挂载点必须为空目录,不能重复挂载至同一挂载点或挂载至其他挂载点下的目录或文件,错误挂载可能损坏设备及系统。 + +- open打开一个文件时,参数O\_RDWR、O\_WRONLY、O\_RDONLY互斥,只能出现一个,若出现2个或以上作为open的参数,文件读写操作会被拒绝,并返回EACCESS错误码,禁止使用。 + +- OpenHarmony内核文件系统在umount操作之前,需确保所有目录及文件全部关闭,否则umount会失败。如果强制umount,可能导致包括但不限于文件系统损坏、设备损坏等问题。 + +- SD卡移除前,需确保所有目录及文件全部关闭,并进行umount操作。如果强制拔卡,可能导致包括但不限于SD数据丢失、SD卡损坏等问题。 + + +## 开发指导 + +**开发流程** + +推荐驱动开发人员使用VFS框架来注册/卸载设备,即调用register\_driver\(\)、register\_blockdriver\(\)接口生成设备结点,应用层使用open\(\)、read\(\)操作设备(字符设备)文件来调用驱动。 + +**文件描述符** + +本系统中,进程的文件描述符最多有256个(File和Socket描述符合并统计),系统文件描述符共640个,系统文件描述符规格: + +- File描述符,普通文件描述符,系统总规格为512。 + +- Socket描述符,系统总规格为128。 + + +**VFS支持的操作** + +open, close, read, write, seek, ioctl, fcntl, mmap, sync, dup, dup2, truncate, opendir, closedir, readdir, rewinddir, mount, umount, statfs, unlink, remove, mkdir, rmdir, rename, stat, utime, seek64, fallocate, fallocate64, truncate64, chmod, chown。 + +>![](../public_sys-resources/icon-note.gif) **说明:** +>- 当前只提供修改jffs2文件以及vfs设备节点属性的接口,各个系统对只读等属性有各自的处理方式。 +>- 在OpenHarmony内核中属性并不冲突(可以任意修改)。 +>- 在OpenHarmony内核中只读属性文件/目录不允许被删除。 +>- 在OpenHarmony内核中只读属性文件/目录允许rename。 +>- 只读文件不允许以O\_CREAT、O\_TRUNC,以及有含有写的权限的方式打开。 +>- 在OpenHarmony内核中设置的系统文件加上隐藏属性,在Windows中只能通过命令行找到(在显示,不显示隐藏文件的属性情况下都不能看到)。 + +## 编程实例 + +``` +/* 说明:展示创建目录,和遍历目录的操作 */ +#include +#include +#include +#include +#include +#include + +int main() +{ + int ret; + char *dirname = "/test"; + char *pathname0 = "/test/test0"; + char *pathname1 = "/test/test1"; + char *pathname2 = "/test/test2"; + struct dirent **namelist; + int num; + + ret = mkdir(dirname, 0777); + if ((ret < 0) && (errno != EEXIST)) { + printf("mkdir failed. path=%s, errno=%d\n", dirname, errno); + goto EXIT; + } + + ret = mkdir(pathname0, 0777); + if ((ret < 0) && (errno != EEXIST)) { + printf("mkdir failed. path=%s, errno=%d\n", pathname0, errno); + goto EXIT0; + } + + ret = mkdir(pathname1, 0777); + if ((ret < 0) && (errno != EEXIST)) { + printf("mkdir failed. path=%s, errno=%d\n", pathname1, errno); + goto EXIT1; + } + + ret = mkdir(pathname2, 0777); + if ((ret < 0) && (errno != EEXIST)) { + printf("mkdir failed. path=%s, errno=%d\n", pathname2, errno); + goto EXIT2; + } + + num = scandir(dirname, &namelist, NULL, alphasort); + if (num < 0) { + perror("scandir"); + } else { + while (num--) { + printf("%s\n", namelist[num]->d_name); + free(namelist[num]); + } + free(namelist); + } + + printf("fs_demo exit.\n"); + return 0; + +EXIT2: + remove(pathname2); +EXIT1: + remove(pathname1); +EXIT0: + remove(pathname0); +EXIT: + remove(dirname); + return 0; +} +``` + +## 结果验证 + +``` +OHOS # test2 +test1 +test0 +fs_demo exit. +``` + diff --git a/zh-cn/device-dev/kernel/kernel-lite-small-file.md b/zh-cn/device-dev/kernel/kernel-lite-small-file.md new file mode 100644 index 0000000000..e88e5dd77b --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-small-file.md @@ -0,0 +1,54 @@ +# 文件系统 + +OpenHarmony轻内核支持的文件系统有:VFS(虚拟文件系统)、NFS、RAMFS、FAT、JFFS2。 + +**各个文件系统功能概述:** + +**表 1** 文件系统功能概述 + + + + + + + + + + + + + + + + + + + + + + +

    文件系统

    +

    功能特点概述

    +

    VFS

    +

    VFS是Virtual File System(虚拟文件系统)的缩写,它不是一个实际的文件系统,而是一个异构文件系统之上的软件粘合层,为用户提供统一的类Unix文件操作接口。

    +

    NFS

    +

    NFS是Network File System(网络文件系统)的缩写。它最大的功能是可以通过网络,让不同的机器、不同的操作系统彼此分享其他用户的文件。

    +

    RAMFS

    +

    RAMFS是一种基于RAM的文件系统。RAMFS文件系统把所有的文件都放在RAM中,所以读/写操作发生在RAM中,避免了对存储器的读写损耗,也提高了数据读写速度。RAMFS是基于RAM的动态文件系统的一种存储缓冲机制。

    +

    FAT

    +

    FAT文件系统是File Allocation Table(文件配置表)的简称,有FAT12、FAT16、FAT32。在可移动存储介质(U盘、SD卡、移动硬盘等)上多使用FAT文件系统,使设备与Windows、Linux等桌面系统之间保持很好的兼容性。

    +

    JFFS2

    +

    JFFS2是Journalling Flash File System Version 2(日志文件系统)的缩写,是MTD设备上的日志型文件系统。主要应用于对NOR_FLASH闪存的文件管理。OpenHarmony内核的JFFS2支持多分区。

    +
    + +- **[VFS](kernel-lite-small-file-vfs.md)** + +- **[NFS](kernel-lite-small-file-nfs.md)** + +- **[RAMFS](kernel-lite-small-file-ramfs.md)** + +- **[FAT](kernel-lite-small-file-fat.md)** + +- **[JFFS2](kernel-lite-small-file-jffs.md)** + + diff --git "a/zh-cn/device-dev/kernel/\344\270\216Linux\346\240\207\345\207\206\345\272\223\347\232\204\345\267\256\345\274\202.md" b/zh-cn/device-dev/kernel/kernel-lite-small-lib-differ.md old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/kernel/\344\270\216Linux\346\240\207\345\207\206\345\272\223\347\232\204\345\267\256\345\274\202.md" rename to zh-cn/device-dev/kernel/kernel-lite-small-lib-differ.md diff --git a/zh-cn/device-dev/kernel/kernel-lite-small-lib-standard.md b/zh-cn/device-dev/kernel/kernel-lite-small-lib-standard.md new file mode 100644 index 0000000000..9af746232e --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-small-lib-standard.md @@ -0,0 +1,197 @@ +# 标准库 + +- [框架流程](#section1247343413257) +- [操作实例](#section4807125622614) +- [常见问题](#section1219455217277) + +OpenHarmony内核使用**musl libc**库,支持标准POSIX接口,开发者可基于POSIX标准接口开发内核之上的组件及应用。 + +## 框架流程 + +**图 1** POSIX接口框架 +![](figure/POSIX接口框架.png "POSIX接口框架") + +**musl libc**库支持POSIX标准,涉及的系统调用相关接口由OpenHarmony内核适配支持 ,以满足接口对外描述的功能要求。 + +标准库支持接口的详细情况请参考C库的API文档,其中也涵盖了与POSIX标准之间的差异说明。 + +## 操作实例 + +在本示例中,主线程创建了THREAD\_NUM个子线程,每个子线程启动后等待被主线程唤醒,主线程成功唤醒所有子线程后,子线程继续执行直至生命周期结束,同时主线程通过pthread\_join方法等待所有线程执行结束。 + +``` +#include +#include +#include + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +#define THREAD_NUM 3 +int g_startNum = 0; /* 启动的线程数 */ +int g_wakenNum = 0; /* 唤醒的线程数 */ + +struct testdata { + pthread_mutex_t mutex; + pthread_cond_t cond; +} g_td; + +/* + * 子线程入口函数 + */ +static void *ChildThreadFunc(void *arg) +{ + int rc; + pthread_t self = pthread_self(); + + /* 获取mutex锁 */ + rc = pthread_mutex_lock(&g_td.mutex); + if (rc != 0) { + printf("ERROR:take mutex lock failed, error code is %d!\n", rc); + goto EXIT; + } + + /* g_startNum计数加一,用于统计已经获得mutex锁的子线程个数 */ + g_startNum++; + + /* 等待cond条件变量 */ + rc = pthread_cond_wait(&g_td.cond, &g_td.mutex); + if (rc != 0) { + printf("ERROR: pthread condition wait failed, error code is %d!\n", rc); + (void)pthread_mutex_unlock(&g_td.mutex); + goto EXIT; + } + + /* 尝试获取mutex锁,正常场景,此处无法获取锁 */ + rc = pthread_mutex_trylock(&g_td.mutex); + if (rc == 0) { + printf("ERROR: mutex gets an abnormal lock!\n"); + goto EXIT; + } + + /* g_wakenNum计数加一,用于统计已经被cond条件变量唤醒的子线程个数 */ + g_wakenNum++; + + /* 释放mutex锁 */ + rc = pthread_mutex_unlock(&g_td.mutex); + if (rc != 0) { + printf("ERROR: mutex release failed, error code is %d!\n", rc); + goto EXIT; + } +EXIT: + return NULL; +} + +static int testcase(void) +{ + int i, rc; + pthread_t thread[THREAD_NUM]; + + /* 初始化mutex锁 */ + rc = pthread_mutex_init(&g_td.mutex, NULL); + if (rc != 0) { + printf("ERROR: mutex init failed, error code is %d!\n", rc); + goto ERROROUT; + } + + /* 初始化cond条件变量 */ + rc = pthread_cond_init(&g_td.cond, NULL); + if (rc != 0) { + printf("ERROR: pthread condition init failed, error code is %d!\n", rc); + goto ERROROUT; + } + + /* 批量创建THREAD_NUM个子线程 */ + for (i = 0; i < THREAD_NUM; i++) { + rc = pthread_create(&thread[i], NULL, ChildThreadFunc, NULL); + if (rc != 0) { + printf("ERROR: pthread create failed, error code is %d!\n", rc); + goto ERROROUT; + } + } + + /* 等待所有子线程都完成mutex锁的获取 */ + while (g_startNum < THREAD_NUM) { + usleep(100); + } + + /* 获取mutex锁,确保所有子线程都阻塞在pthread_cond_wait上 */ + rc = pthread_mutex_lock(&g_td.mutex); + if (rc != 0) { + printf("ERROR: mutex lock failed, error code is %d\n", rc); + goto ERROROUT; + } + + /* 释放mutex锁 */ + rc = pthread_mutex_unlock(&g_td.mutex); + if (rc != 0) { + printf("ERROR: mutex unlock failed, error code is %d!\n", rc); + goto ERROROUT; + } + + for (int j = 0; j < THREAD_NUM; j++) { + /* 在cond条件变量上广播信号 */ + rc = pthread_cond_signal(&g_td.cond); + if (rc != 0) { + printf("ERROR: pthread condition failed, error code is %d!\n", rc); + goto ERROROUT; + } + } + + sleep(1); + + /* 检查是否所有子线程都已被唤醒 */ + if (g_wakenNum != THREAD_NUM) { + printf("ERROR: not all threads awaken, only %d thread(s) awaken!\n", g_wakenNum); + goto ERROROUT; + } + + /* join所有子线程,即等待其结束 */ + for (i = 0; i < THREAD_NUM; i++) { + rc = pthread_join(thread[i], NULL); + if (rc != 0) { + printf("ERROR: pthread join failed, error code is %d!\n", rc); + goto ERROROUT; + } + } + + /* 销毁cond条件变量 */ + rc = pthread_cond_destroy(&g_td.cond); + if (rc != 0) { + printf("ERROR: pthread condition destroy failed, error code is %d!\n", rc); + goto ERROROUT; + } + return 0; +ERROROUT: + return -1; +} + +/* + * 示例代码主函数 + */ +int main(int argc, char *argv[]) +{ + int rc; + + /* 启动测试函数 */ + rc = testcase(); + if (rc != 0) { + printf("ERROR: testcase failed!\n"); + } + + return 0; +} +#ifdef __cplusplus +#if __cplusplus +} +#endif /* __cplusplus */ +#endif /* __cplusplus */ +``` + +## 常见问题 + +无。 + diff --git a/zh-cn/device-dev/kernel/kernel-lite-small-lib.md b/zh-cn/device-dev/kernel/kernel-lite-small-lib.md new file mode 100644 index 0000000000..849c9823bb --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-small-lib.md @@ -0,0 +1,7 @@ +# 标准库 + +- **[标准库](kernel-lite-small-lib-standard.md)** + +- **[与Linux标准库的差异](kernel-lite-small-lib-differ.md)** + + diff --git a/zh-cn/device-dev/kernel/kernel-lite-small-memory.md b/zh-cn/device-dev/kernel/kernel-lite-small-memory.md new file mode 100644 index 0000000000..5f97c5705a --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-small-memory.md @@ -0,0 +1,353 @@ +# 内存 + +- [基本概念](#section1392116583424) +- [使用场景](#section159581619194319) +- [接口说明](#section114001032104317) + +## 基本概念 + +内存管理是开发过程中必须要关注的重要过程,它包括内存的分配、使用和回收。 + +良好的内存管理对于提高软件性能和可靠性有着十分重要的意义。 + +## 使用场景 + +针对用户态开发,OpenHarmony内核提供了一套内存系统调用接口,支持内存的申请释放、重映射、内存属性的设置等,还有C库的标准内存操作函数。 + +## 接口说明 + +**表 1** 标准C库相关接口 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    头文件

    +

    接口

    +

    功能

    +

    strings.h

    +

    int bcmp(const void *s1, const void *s2, size_t n)

    +

    比较字节序列。

    +

    strings.h

    +

    void bcopy(const void *src, void *dest, size_t n)

    +

    拷贝字节序列。

    +

    strings.h

    +

    void bzero(void *s, size_t n)

    +

    写入零值字节。

    +

    string.h

    +

    void *memccpy(void *dest, const void *src, int c, size_t n)

    +

    拷贝src 所指的内存内容前n 个字节到dest 所指的地址上。复制时检查参数c 是否出现,若是则返回dest 中值为c 的下一个字节地址。

    +

    string.h

    +

    void *memchr(const void *s, int c, size_t n)

    +

    在s所指内存的前n个字节中查找c。

    +

    string.h

    +

    int memcmp(const void *s1, const void *s2, size_t n)

    +

    内存比较。

    +

    string.h

    +

    void *memcpy(void *dest, const void *src, size_t n)

    +

    内存拷贝。

    +

    string.h

    +

    void *memmem(const void *haystack, size_t haystacklen, const void *needle, size_t needlelen)

    +

    找到一个子串。

    +

    string.h

    +

    void *memmove(void *dest, const void *src, size_t n)

    +

    内存移动。

    +

    string.h

    +

    void *mempcpy(void *dest, const void *src, size_t n)

    +

    拷贝内存区域。

    +

    string.h

    +

    void *memset(void *s, int c, size_t n)

    +

    内存初始化。

    +

    stdlib.h

    +

    void *malloc(size_t size)

    +

    申请内存。

    +

    stdlib.h

    +

    void *calloc(size_t nmemb, size_t size)

    +

    申请内存并清零。

    +

    stdlib.h

    +

    void *realloc(void *ptr, size_t size)

    +

    重分配内存。

    +

    stdlib.h/malloc.h

    +

    void *valloc(size_t size)

    +

    分配以页对齐的内存。

    +

    stdlib.h

    +

    void free(void *ptr)

    +

    释放内存。

    +

    malloc.h

    +

    size_t malloc_usable_size(void *ptr)

    +

    获取从堆分配的内存块的大小。

    +

    unistd.h

    +

    int getpagesize(void)

    +

    获取页面大小。

    +

    unistd.h

    +

    void *sbrk(intptr_t increment)

    +

    更改数据段大小。

    +
    + +差异接口详细说明: + +- **mmap** + + **函数原型:** + + void \*mmap\(void \*addr, size\_t length, int prot, int flags, int fd, off\_t offset\); + + **函数功能:**申请虚拟内存。 + + **参数说明:** + + + + + + + + + + + + + + + + + + + + + + + + + +

    参数

    +

    描述

    +

    addr

    +

    用来请求使用某个特定的虚拟内存地址。如果取NULL,结果地址就将自动分配(这是推荐的做法),否则会降低程序的可移植性,因为不同系统的可用地址范围不一样。

    +

    length

    +

    内存段的大小。

    +

    prot

    +

    用于设置内存段的访问权限,有如下权限:

    +
    • PROT_READ:允许读该内存段。
    • PROT_WRITE:允许写该内存段。
    • PROT_EXEC:允许执行该内存段。
    • PROT_NONE:不能访问。
    +

    flags

    +

    控制程序对内存段的改变所造成的影响,有如下属性:

    +
    • MAP_PRIVATE:内存段私有,对它的修改值仅对本进程有效。
    • MAP_SHARED:把对该内存段的修改保存到磁盘文件中。
    +

    fd

    +

    打开的文件描述符。

    +

    offset

    +

    用以改变经共享内存段访问的文件中数据的起始偏移值。

    +
    + + >![](../public_sys-resources/icon-note.gif) **说明:** + >mmap与Linux实现差异详见[与Linux标准库的差异](kernel-lite-small-lib-differ.md)章节。 + + **返回值:** + + - 成功返回:虚拟内存地址,这地址是页对齐。 + - 失败返回:\(void \*\)-1。 + + +- **munmap接口** + + **函数原型:** + + int munmap\(void \*addr, size\_t length\); + + **函数功能:**释放虚拟内存。 + + **参数说明:** + + + + + + + + + + + + + +

    参数

    +

    描述

    +

    addr

    +

    虚拟内存起始位置。

    +

    length

    +

    内存段的大小。

    +
    + + **返回值:** + + - 成功返回0。 + - 失败返回-1。 + + +- **mprotect接口** + + **函数原型:** + + int mprotect\(void \*addr, size\_t length, int prot\); + + **函数功能:**修改内存段的访问权限。 + + **参数说明:** + + + + + + + + + + + + + + + + +

    参数

    +

    描述

    +

    addr

    +

    内存段起始地址,必须页对齐;访问权限异常,内核将直接抛异常并且kill该进程,而不会产生SIGSEGV信号给当前进程。

    +

    length

    +

    内存段的大小。

    +

    prot

    +

    内存段的访问权限,有如下定义:

    +
    • PROT_READ:允许读该内存段。
    • PROT_WRITE:允许写该内存段。
    • PROT_EXEC:允许执行该内存段。
    • PROT_NONE:不能访问。
    +
    + + **返回值:** + + - 成功返回0。 + - 失败返回-1。 + + +- **mremap接口** + + **函数原型:** + + void \*mremap\(void \*old\_address, size\_t old\_size, size\_t new\_size, int flags, void new\_address\); + + **函数功能:**重新映射虚拟内存地址。 + + **参数说明:** + + + + + + + + + + + + + + + + + + + +

    参数

    +

    描述

    +

    old_address

    +

    需要扩大(或缩小)的内存段的原始地址。注意old_address必须是页对齐。

    +

    old_size

    +

    内存段的原始大小。

    +

    new_size

    +

    新内存段的大小。

    +

    flags

    +

    如果没有足够的空间在当前位置展开映射,则返回失败

    +
    • MREMAP_MAYMOVE:允许内核将映射重定位到新的虚拟地址。
    • MREMAP_FIXED:mremap()接受第五个参数,void *new_address,该参数指定映射地址必须页对齐;在new_address和new_size指定的地址范围内的所有先前映射都被解除映射。如果指定了MREMAP_FIXED,还必须指定MREMAP_MAYMOVE。
    +
    + + **返回值:** + + - 成功返回:重新映射后的虚拟内存地址。 + - 失败返回:\(\(void \*\)-1\)。 + + diff --git a/zh-cn/device-dev/kernel/kernel-lite-small-net.md b/zh-cn/device-dev/kernel/kernel-lite-small-net.md new file mode 100644 index 0000000000..8aa33611c3 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-small-net.md @@ -0,0 +1,303 @@ +# 网络 + +- [基本概念](#section9840143083510) +- [使用场景](#section1575885183516) +- [接口说明](#section16351198193614) + +## 基本概念 + +网络模块实现了TCP/IP协议栈基本功能,提供标准的POSIX socket接口。 + +>![](../public_sys-resources/icon-note.gif) **说明:** +>当前系统使用**lwIP**提供网络能力。 + +## 使用场景 + +针对用户态开发,OpenHarmony内核提供了一套网络功能系统调用接口,支持socket的创建关闭、数据收发、网络属性的设置等,通过C库提供标准的POSIX socket函数供开发者使用。 + +## 接口说明 + +**表 1** 标准C库相关接口 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    头文件

    +

    接口

    +

    功能

    +

    sys/socket.h

    +

    int accept(int socket, struct sockaddr *address, socklen_t *address_len)

    +

    接受连接。

    +

    sys/socket.h

    +

    int bind(int s, const struct sockaddr *name, socklen_t namelen)

    +

    socket与IP地址绑定。

    +

    sys/socket.h

    +

    int shutdown(int socket, int how)

    +

    关闭连接。

    +

    sys/socket.h

    +

    int getpeername(int s, struct sockaddr *name, socklen_t *namelen)

    +

    获取对端地址。

    +

    sys/socket.h

    +

    int getsockname(int s, struct sockaddr *name, socklen_t *namelen)

    +

    获取本地地址。

    +

    sys/socket.h

    +

    int getsockopt(int s, struct sockaddr *name, socklen_t *namelen)

    +

    获取socket属性信息。

    +

    sys/socket.h

    +

    int setsockopt(int sockfd, int level, int optname, void *optval, socklen_t *optlen)

    +

    配置socket属性。

    +

    unistd.h

    +

    int close(int s)

    +

    关闭socket。

    +

    sys/socket.h

    +

    int connect(int s, const struct sockaddr *name, socklen_t namelen)

    +

    连接到指定的目的IP。

    +

    sys/socket.h

    +

    int listen(int sockfd, int backlog)

    +

    聆听连接本socket的请求。

    +

    sys/socket.h

    +

    ssize_t recv(int socket, void *buffer, size_t length, int flags)

    +

    接收socket上收到的数据。

    +

    sys/socket.h

    +

    ssize_t recvmsg(int s, struct msghdr *message, int flags)

    +

    接收socket上收到的数据,可使用更丰富的参数。

    +

    sys/socket.h

    +

    ssize_t recvfrom(int socket, void *buffer, size_t length, int flags, struct sockaddr *address, socklen_t *address_len)

    +

    接收socket上收到的数据,可同时获得数据来源IP地址。

    +

    sys/socket.h

    +

    ssize_t send(int s, const void *dataptr, size_t size, int flags)

    +

    通过socket发送数据。

    +

    sys/socket.h

    +

    ssize_t sendmsg(int s, const struct msghdr *message, int flags)

    +

    通过socket发送数据,可使用更丰富的参数。

    +

    sys/socket.h

    +

    ssize_t sendto(int s, const void *dataptr, size_t size, int flags, const struct sockaddr *to, socklen_t tolen)

    +

    通过socket发送数据,可指定发送的目的IP地址。

    +

    sys/socket.h

    +

    int socket(int domain, int type, int protocol)

    +

    创建socket。

    +

    sys/select.h

    +

    int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout)

    +

    多路复用。

    +

    sys/ioctl.h

    +

    int ioctl(int s, int request, ...)

    +

    socket属性获取、设置。

    +

    arpa/inet.h

    +

    const char *inet_ntop(int af, const void *src, char *dst, socklen_t size)

    +

    网络地址格式转换:将二进制格式IP地址转换为字符串格式。

    +

    arpa/inet.h

    +

    int inet_pton(int af, const char *src, void *dst)

    +

    网络地址格式转换:将字符串格式IP地址转换为二进制格式。

    +
    + +与标准接口差异详细说明: + +- **sendmsg** + + **函数原型:** + + ssize\_t sendmsg\(int s, const struct msghdr \*message, int flags\) + + **函数功能:**发送消息。 + + **参数说明:** + + + + + + + + + + + + + + + + +

    参数

    +

    描述

    +

    s

    +

    套接字描述符。

    +

    message

    +

    待发送的消息,不支持发送ancillary消息。

    +

    flags

    +

    用于指定发送消息时行为特性,有如下行为特性:

    +
    • MSG_MORE:允许将多次发送的消息进行拼包发送。
    • MSG_DONTWAIT:非阻塞操作。
    +
    + + **返回值:** + + - 成功返回:已发送的消息长度(字节数)。 + - 失败返回:-1,并设置errno。 + + +- **recvmsg** + + **函数原型:** + + ssize\_t recvmsg\(int s, struct msghdr \*message, int flags\) + + **函数功能:**接收消息。 + + **参数说明:** + + + + + + + + + + + + + + + + +

    参数

    +

    描述

    +

    s

    +

    套接字描述符。

    +

    message

    +

    存放接收的消息,不支持接收ancillary消息。

    +

    flags

    +

    用于指定接收消息时行为特性,有如下行为特性:

    +
    • MSG_PEEK:允许预读消息而不取走。
    • MSG_DONTWAIT:非阻塞操作。
    +
    + + **返回值:** + + - 成功返回:已接收的消息长度(字节数)。 + - 失败返回:-1,并设置errno。 + + +- **ioctl** + + **函数原型:** + + int ioctl\(int s, int request, ...\) + + **函数功能:**获取或设置socket属性。 + + **参数说明:** + + + + + + + + + + + + + +

    参数

    +

    描述

    +

    s

    +

    套接字描述符。

    +

    request

    +

    对socket属性要进行的操作,当前支持如下操作:

    +
    • FIONREAD:获取socket当前可读取的数据大小(字节数)。
    • FIONBIO:设置socket是否非阻塞。
    +
    + + **返回值:** + + - 成功返回:0。 + - 失败返回:-1,并设置errno。 + + diff --git a/zh-cn/device-dev/kernel/kernel-lite-small-process.md b/zh-cn/device-dev/kernel/kernel-lite-small-process.md new file mode 100644 index 0000000000..d6b9ca0377 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-small-process.md @@ -0,0 +1,301 @@ +# 进程 + +- [基本概念](#section29197338383) +- [使用场景](#section85513272398) +- [接口说明](#section4517119124015) + +## 基本概念 + +从系统的角度看,进程是资源管理单元。进程可以使用或等待CPU、使用内存空间等系统资源,并独立于其它进程运行。 + +OpenHarmony内核的进程模块可以给用户提供多个进程,实现了进程之间的切换和通信,帮助用户管理业务程序流程。这样用户可以将更多的精力投入到业务功能的实现中。 + +OpenHarmony内核中的进程采用抢占式调度机制,支持时间片轮转调度方式。 + +OpenHarmony内核的进程一共有32个优先级\(0-31\),用户进程可配置的优先级有22个\(10-31\),最高优先级为10,最低优先级为31。 + +高优先级的进程可抢占低优先级进程,低优先级进程必须在高优先级进程阻塞或结束后才能得到调度。 + +每一个用户态进程均拥有自己独立的进程空间,相互之间不可见,实现进程间隔离。 + +用户态根进程init由内核态创建,其它用户态进程均由init进程fork而来。 + +**进程状态说明:** + +- 初始化(Init):该进程正在被创建。 + +- 就绪(Ready):该进程在就绪列表中,等待CPU调度。 + +- 运行(Running):该进程正在运行。 + +- 阻塞(Pending):该进程被阻塞挂起。本进程内所有的线程均被阻塞时,进程被阻塞挂起。 + +- 僵尸态(Zombies):该进程运行结束,等待父进程回收其控制块资源。 + + +**图 1** 进程状态迁移示意图 +![](figure/进程状态迁移示意图.png "进程状态迁移示意图") + +**进程状态迁移说明:** + +- Init→Ready: + + 进程创建或fork时,拿到该进程控制块后进入Init状态,处于进程初始化阶段,当进程初始化完成将进程插入调度队列,此时进程进入就绪状态。 + +- Ready→Running: + + 进程创建后进入就绪态,发生进程切换时,就绪列表中最高优先级的进程被执行,从而进入运行态。若此时该进程中已无其它线程处于就绪态,则该进程从就绪列表删除,只处于运行态;若此时该进程中还有其它线程处于就绪态,则该进程依旧在就绪队列,此时进程的就绪态和运行态共存。 + +- Running→Pending: + + 进程内所有的线程均处于阻塞态时,进程在最后一个线程转为阻塞态时,同步进入阻塞态,然后发生进程切换。 + +- Pending→Ready: + + 阻塞进程内的任意线程恢复就绪态时,进程被加入到就绪队列,同步转为就绪态。 + +- Ready→Pending: + + 进程内的最后一个就绪态线程处于阻塞态时,进程从就绪列表中删除,进程由就绪态转为阻塞态。 + +- Running→Ready: + + 进程由运行态转为就绪态的情况有以下两种: + + 1. 有更高优先级的进程创建或者恢复后,会发生进程调度,此刻就绪列表中最高优先级进程变为运行态,那么原先运行的进程由运行态变为就绪态。 + 2. 若进程的调度策略为SCHED\_RR,且存在同一优先级的另一个进程处于就绪态,则该进程的时间片消耗光之后,该进程由运行态转为就绪态,另一个同优先级的进程由就绪态转为运行态。 + +- Running→Zombies: + + 当进程的主线程或所有线程运行结束后,进程由运行态转为僵尸态,等待父进程回收资源。 + + +## 使用场景 + +进程创建后,用户只能操作自己进程空间的资源,无法操作其它进程的资源(共享资源除外)。 用户态允许进程挂起,恢复,延时等操作,同时也可以设置用户态进程调度优先级和调度策略,获取进程调度优先级和调度策略。进程结束的时候,进程会主动释放持有的进程资源,但持有的进程pid资源需要父进程通过wait/waitpid或父进程退出时回收。 + +## 接口说明 + +OpenHarmony内核系统中的进程管理模块为用户提供下面几种功能: + +**表 1** 进程管理模块功能 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    功能分类

    +

    接口名

    +

    描述

    +

    备注

    +

    进程

    +

    fork

    +

    创建一个新进程。

    +

    -

    +

    exit

    +

    终止进程。

    +

    -

    +

    atexit

    +

    注册正常进程终止的回调函数。

    +

    -

    +

    abort

    +

    中止进程执行。

    +

    -

    +

    getpid

    +

    获取进程ID。

    +

    -

    +

    getppid

    +

    获取父进程ID。

    +

    -

    +

    getpgrp

    +

    获取调用进程的进程组ID。

    +

    -

    +

    getpgid

    +

    获取进程的进程组ID。

    +

    -

    +

    setpgrp

    +

    设置调用进程的进程组ID。

    +

    -

    +

    setpgid

    +

    设置进程的进程组ID。

    +

    -

    +

    kill

    +

    给进程发送信号。

    +
    • 仅支持1-30号信号的发送。
    • 信号的默认行为不支持STOP及CONTINUE,无COREDUMP功能。
    • 不能屏蔽SIGSTOP、SIGKILL、SIGCONT。
    • 异步信号,发送信号给某进程后,直到该进程被调度后才会执行信号回调(为安全起见,杀死进程的动作是进程自己执行的,内核不能通过信号强制杀死对方)。
    • 进程消亡会发送SIGCHLD给父进程,发送动作无法取消。
    • 无法通过信号唤醒正在睡眠的进程。
    +

    wait

    +

    等待任意子进程结束并回收子进程资源。

    +

    status的值可以由以下宏定义解析:

    +
    • WIFEXITED(status):如果子进程正常结束,它就返回真;否则返回假。
    • WEXITSTATUS(status):如果WIFEXITED(status)为真,则可以用该宏取得子进程exit()返回的退出码。
    • WTERMSIG(status) 仅支持以下情况:子进程触发异常结束后通过WTERMSIG获取的进程退出编号始终为SIGUSR2。
    • 不支持的操作: WIFSTOPPED、WSTOPSIG、WCOREDUMP 、WIFCONTINUED。
    +

    waitpid

    +

    等待子进程结束并回收子进程资源。

    +

    options:不支持WUNTRACED,WCONTINUED;

    +

    status的值可以由以下宏定义解析:

    +
    • WIFEXITED(status):如果子进程正常结束,它就返回真;否则返回假。
    • WEXITSTATUS(status):如果WIFEXITED(status)为真,则可以用该宏取得子进程exit()返回的退出码。
    • WTERMSIG(status)仅支持以下情况:子进程触发异常结束后通过WTERMSIG获取的进程退出编号始终为SIGUSR2。
    • 不支持:WIFSTOPPED 、WSTOPSIG、WCOREDUMP 、WIFCONTINUED。
    +

    调度

    +

    getpriority

    +

    获取指定ID的静态优先级。

    +
    • 不支持:PRIO_PGRP、PRIO_USER。
    +
    • 无动态优先级概念,用于设置静态优先级。
    +

    setpriority

    +

    设置指定ID的静态优先级。

    +

    sched_rr_get_interval

    +

    获取执行时间限制。

    +

    -

    +

    sched_yield

    +

    系统调用运行进程主动让出执行权。

    +

    -

    +

    sched_get_priority_max

    +

    获取进程静态优先级取值范围的最大值。

    +

    调度策略只支持:SCHED_RR。

    +

    sched_get_priority_min

    +

    获取进程静态优先级取值范围的最小值。

    +

    sched_getscheduler

    +

    获取调度策略。

    +

    sched_setscheduler

    +

    设置调度策略。

    +

    sched_getparam

    +

    获取调度参数。

    +

    -

    +

    sched_setparam

    +

    设置调度参数。

    +

    -

    +

    exec

    +

    execl

    +

    执行指定的elf格式的用户程序文件。

    +

    -

    +

    execle

    +

    执行指定的elf格式的用户程序文件。

    +

    -

    +

    execlp

    +

    执行指定的elf格式的用户程序文件。

    +

    -

    +

    execv

    +

    执行指定的elf格式的用户程序文件。

    +

    -

    +

    execve

    +

    执行指定的elf格式的用户程序文件。

    +

    -

    +

    execvp

    +

    执行指定的elf格式的用户程序文件。

    +

    -

    +
    + diff --git "a/zh-cn/device-dev/kernel/\347\224\250\346\210\267\346\200\201\345\274\202\345\270\270\344\277\241\346\201\257\350\257\264\346\230\216.md" b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-abn.md old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/kernel/\347\224\250\346\210\267\346\200\201\345\274\202\345\270\270\344\277\241\346\201\257\350\257\264\346\230\216.md" rename to zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-abn.md diff --git a/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file-cat.md b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file-cat.md new file mode 100644 index 0000000000..89f4a35b9f --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file-cat.md @@ -0,0 +1,53 @@ +# cat + +- [命令功能](#section16710153391315) +- [命令格式](#section1699392313158) +- [参数说明](#section1677217374136) +- [使用指南](#section186772414131) +- [使用实例](#section12158131814561) +- [输出说明](#section183926225561) + +## 命令功能 + +cat用于显示文本文件的内容。 + +## 命令格式 + +cat \[_pathname_\] + +## 参数说明 + +**表 1** 参数说明 + + + + + + + + + + + + +

    参数

    +

    参数说明

    +

    取值范围

    +

    pathname

    +

    文件路径。

    +

    已存在的文件。

    +
    + +## 使用指南 + +cat用于显示文本文件的内容。 + +## 使用实例 + +举例:cat hello-harmony.txt + +## 输出说明 + +**图 1** 查看 hello-harmony.txt 文件的信息 +![](figure/查看-hello-harmony-txt-文件的信息.png "查看-hello-harmony-txt-文件的信息") + diff --git a/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file-cd.md b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file-cd.md new file mode 100644 index 0000000000..61247bfba2 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file-cd.md @@ -0,0 +1,57 @@ +# cd + +- [命令功能](#section11690184921316) +- [命令格式](#section75695409569) +- [参数说明](#section71961353181311) +- [使用指南](#section3629759111317) +- [使用实例](#section211620301412) +- [输出说明](#section1968117214577) + +## 命令功能 + +cd命令用来改变当前目录。 + +## 命令格式 + +cd \[_path_\] + +## 参数说明 + +**表 1** 参数说明 + + + + + + + + + + + + +

    参数

    +

    参数说明

    +

    取值范围

    +

    path

    +

    文件路径。

    +

    用户必须具有指定目录中的执行(搜索)许可权。

    +
    + +## 使用指南 + +- 未指定目录参数时,会跳转至根目录。 +- cd后加路径名时,跳转至该路径。 +- 路径名以 /(斜杠)开头时,表示根目录。 +- .(点)表示当前目录。 +- ..(点点)表示父目录。 + +## 使用实例 + +举例:cd .. + +## 输出说明 + +**图 1** 显示结果如下 +![](figure/显示结果如下.png "显示结果如下") + diff --git a/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file-chgrp.md b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file-chgrp.md new file mode 100644 index 0000000000..efeccc336f --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file-chgrp.md @@ -0,0 +1,60 @@ +# chgrp + +- [命令功能](#section6103119161418) +- [命令格式](#section186958132141) +- [参数说明](#section81796174141) +- [使用指南](#section14330152417140) +- [使用实例](#section951823119149) +- [输出说明](#section14271133125715) + +## 命令功能 + +chgrp用于修改文件的群组。 + +## 命令格式 + +chgrp \[_group_\] \[_pathname_\] + +## 参数说明 + +**表 1** 参数说明 + + + + + + + + + + + + + + + + +

    参数

    +

    参数说明

    +

    取值范围

    +

    group

    +

    文件群组。

    +

    [0,0xFFFFFFFF]

    +

    pathname

    +

    文件路径。

    +

    已存在的文件。

    +
    + +## 使用指南 + +在需要修改的文件名前加上文件群组值就可以修改该文件的所属组。 + +## 使用实例 + +举例:chgrp 100 hello-harmony.txt + +## 输出说明 + +**图 1** 修改 hello-harmony.txt 文件的群组为100 +![](figure/修改-hello-harmony-txt-文件的群组为100.png "修改-hello-harmony-txt-文件的群组为100") + diff --git a/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file-chmod.md b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file-chmod.md new file mode 100644 index 0000000000..296ab1e3d3 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file-chmod.md @@ -0,0 +1,60 @@ +# chmod + +- [命令功能](#section13992936121418) +- [命令格式](#section63342439147) +- [参数说明](#section894414671411) +- [使用指南](#section182415221419) +- [使用实例](#section8518195718147) +- [输出说明](#section127391818158) + +## 命令功能 + +chmod用于修改文件操作权限。 + +## 命令格式 + +chmod \[_mode_\] \[_pathname_\] + +## 参数说明 + +**表 1** 参数说明 + + + + + + + + + + + + + + + + +

    参数

    +

    参数说明

    +

    取值范围

    +

    mode

    +

    文件或文件夹权限,用8进制表示对应User、Group、及Other(拥有者、群组、其他组)的权限。

    +

    [0,777]

    +

    pathname

    +

    文件路径。

    +

    已存在的文件。

    +
    + +## 使用指南 + +在需要修改的文件名前加上文件权限值就可以修改该文件的权限值。 + +## 使用实例 + +举例:chmod 666 hello-harmony.txt + +## 输出说明 + +**图 1** 修改 hello-harmony.txt 文件的权限为666 +![](figure/修改-hello-harmony-txt-文件的权限为666.png "修改-hello-harmony-txt-文件的权限为666") + diff --git a/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file-chown.md b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file-chown.md new file mode 100644 index 0000000000..4e63051ec9 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file-chown.md @@ -0,0 +1,70 @@ +# chown + +- [命令功能](#section247414691513) +- [命令格式](#section14773151018159) +- [参数说明](#section598731391517) +- [使用指南](#section16524152071510) +- [使用实例](#section17901152561510) +- [输出说明](#section15513163115816) + +## 命令功能 + +chmod用于将指定文件的拥有者改为指定的用户或组。 + +## 命令格式 + +chown \[_owner_\] \[_group_\] \[_pathname_\] + +## 参数说明 + +**表 1** 参数说明 + + + + + + + + + + + + + + + + + + + + +

    参数

    +

    参数说明

    +

    取值范围

    +

    owner

    +

    文件拥有者。

    +

    [0,0xFFFFFFFF]

    +

    group

    +

    文件群组。

    +

    1、为空。

    +

    2、[0,0xFFFFFFFF]

    +

    pathname

    +

    文件路径。

    +

    已存在的文件。

    +
    + +## 使用指南 + +- 在需要修改的文件名前加上文件拥有者和文件群组就可以分别修改该文件的拥有者和群组。 +- 当owner或group值为-1时则表示对应的owner或group不修改。 +- group参数可以为空。 + +## 使用实例 + +举例:chown 100 200 hello-harmony.txt + +## 输出说明 + +**图 1** 修改 hello-harmony.txt 文件的uid为100,gid为200 +![](figure/修改-hello-harmony-txt-文件的uid为100-gid为200.png "修改-hello-harmony-txt-文件的uid为100-gid为200") + diff --git a/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file-cp.md b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file-cp.md new file mode 100644 index 0000000000..299beb065c --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file-cp.md @@ -0,0 +1,68 @@ +# cp + +- [命令功能](#section6841203041513) +- [命令格式](#section24286359150) +- [参数说明](#section558617385152) +- [使用指南](#section16128156162) +- [使用实例](#section19354171211618) +- [输出说明](#section16754183195914) + +## 命令功能 + +拷贝文件,创建一份副本。 + +## 命令格式 + +cp \[_SOURCEFILE_\] \[_DESTFILE_\] + +## 参数说明 + +**表 1** 参数说明 + + + + + + + + + + + + + + + + +

    参数

    +

    参数说明

    +

    取值范围

    +

    SOURCEFILE

    +

    源文件路径。

    +

    目前只支持文件,不支持目录。

    +

    DESTFILE

    +

    目的文件路径。

    +

    支持目录以及文件。

    +
    + +## 使用指南 + +- 同一路径下,源文件与目的文件不能重名。 +- 源文件必须存在,且不为目录。 +- 源文件路径支持“\*”和“?”通配符,“\*”代表任意多个字符,“?”代表任意单个字符。目的路径不支持通配符。当源路径可匹配多个文件时,目的路径必须为目录。 +- 目的路径为目录时,该目录必须存在。此时目的文件以源文件命名。 +- 目的路径为文件时,所在目录必须存在。此时拷贝文件的同时为副本重命名。 +- 目前不支持多文件拷贝。参数大于2个时,只对前2个参数进行操作。 +- 目的文件不存在时创建新文件,已存在则覆盖。 + +拷贝系统重要资源时,会对系统造成死机等重大未知影响,如用于拷贝/dev/uartdev-0 文件时,会产生系统卡死现象。 + +## 使用实例 + +举例:cp hello-harmony.txt ./tmp/ + +## 输出说明 + +**图 1** 显示结果如下 +![](figure/显示结果如下-17.png "显示结果如下-17") + diff --git a/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file-format.md b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file-format.md new file mode 100644 index 0000000000..200ddb4fe6 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file-format.md @@ -0,0 +1,69 @@ +# format + +- [命令功能](#section1922331919169) +- [命令格式](#section249226169) +- [参数说明](#section985173416177) +- [使用指南](#section1510162714162) +- [使用实例](#section25691431161611) +- [输出说明](#section17368112365920) + +## 命令功能 + +format指令用于格式化磁盘。 + +## 命令格式 + +format <_dev\_inodename_\> <_sectors_\> <_option_\> \[_label_\] + +## 参数说明 + +**表 1** 参数说明 + + + + + + + + + + + + + + + + + + + +

    参数

    +

    参数说明

    +

    dev_inodename

    +

    设备名。

    +

    sectors

    +

    分配的单元内存或扇区大小,如果输入0表示参数为空。(取值必须为0或2的幂,fat32下最大值为128,取值0表示自动选择合适的簇大小,不同size的分区,可用的簇大小范围不同,错误的簇大小指定可能导致格式化失败)。

    +

    option

    +
    格式化选项,用来选择文件系统的类型,有如下几种参数选择:
    • 0x01:FMT_FAT
    • 0x02:FMT_FAT32
    • 0x07:FMT_ANY
    • 0x08:FMT_ERASE (USB不支持该选项)
    +
    +

    传入其他值皆为非法值,将由系统自动选择格式化方式。若格式化U盘时低格位为 1,会出现错误打印。

    +

    label

    +

    该参数为可选参数,输入值应为字符串,用来指定卷标名。当输入字符串"null"时,则把之前设置的卷标名清空。

    +
    + +## 使用指南 + +- format指令用于格式化磁盘,设备名可以在dev目录下查找。format时必须安装存储卡。 +- format只能格式化U盘、sd和mmc卡,对Nand flash和Nor flash格式化不起作用。 +- sectors参数必须传入合法值,传入非法参数可能引发异常。 + +## 使用实例 + +举例:输入format /dev/mmcblk0 128 2 + +## 输出说明 + +结果如下 + +![](figure/zh-cn_image_0000001052370307.png) + diff --git a/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file-is.md b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file-is.md new file mode 100644 index 0000000000..0a1823804e --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file-is.md @@ -0,0 +1,59 @@ +# ls + +- [命令功能](#section6538163771614) +- [命令格式](#section45881743111616) +- [参数说明](#section17528148171617) +- [使用指南](#section041212533166) +- [使用实例](#section986105716167) +- [输出说明](#section2036124918592) + +## 命令功能 + +ls命令用来显示当前目录的内容。 + +## 命令格式 + +ls \[_path_\] + +## 参数说明 + +**表 1** 参数说明 + + + + + + + + + + + + +

    参数

    +

    参数说明

    +

    取值范围

    +

    path

    +

    path为空时,显示当前目录的内容。

    +

    path为无效文件名时,显示失败,提示:

    +

    ls error: No such directory。

    +

    path为有效目录路径时,会显示对应目录下的内容。

    +

    1.为空。

    +

    2.有效的目录路径。

    +
    + +## 使用指南 + +- ls命令显示当前目录的内容。 +- ls可以显示文件的大小。 +- proc下ls无法统计文件大小,显示为0。 + +## 使用实例 + +举例:输入ls + +## 输出说明 + +**图 1** 查看当前系统路径下的目录,显示的内容如下 +![](figure/查看当前系统路径下的目录-显示的内容如下.png "查看当前系统路径下的目录-显示的内容如下") + diff --git a/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file-isfd.md b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file-isfd.md new file mode 100644 index 0000000000..e1fb8007c5 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file-isfd.md @@ -0,0 +1,29 @@ +# lsfd + +- [命令功能](#section2053406181716) +- [命令格式](#section523771017172) +- [使用指南](#section27241213201719) +- [使用实例](#section442617197173) +- [输出说明](#section42491639151813) + +## 命令功能 + +lsfd命令用来显示当前已经打开的文件描述符及对应的文件名。 + +## 命令格式 + +lsfd + +## 使用指南 + +lsfd命令显示当前已经打开文件的fd号以及文件的名字。 + +## 使用实例 + +举例:输入lsfd + +## 输出说明 + +**图 1** lsfd输出说明 +![](figure/lsfd输出说明.png "lsfd输出说明") + diff --git a/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file-mkdir.md b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file-mkdir.md new file mode 100644 index 0000000000..c261ebdca3 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file-mkdir.md @@ -0,0 +1,54 @@ +# mkdir + +- [命令功能](#section1083613274175) +- [命令格式](#section820913118178) +- [参数说明](#section1256834121718) +- [使用指南](#section1294234115172) +- [使用实例](#section1113345211713) +- [输出说明](#section10142201012) + +## 命令功能 + +mkdir命令用来创建一个目录。 + +## 命令格式 + +mkdir \[_directory_\] + +## 参数说明 + +**表 1** 参数说明 + + + + + + + + + + + + +

    参数

    +

    参数说明

    +

    取值范围

    +

    directory

    +

    需要创建的目录。

    +

    N/A

    +
    + +## 使用指南 + +- mkdir后加所需要创建的目录名会在当前目录下创建目录。 +- mkdir后加路径,再加上需要创建的目录名,即在指定目录下创建目录。 + +## 使用实例 + +举例:mkdir share + +## 输出说明 + +**图 1** 创建 share 目录 +![](figure/创建-share-目录.png "创建-share-目录") + diff --git a/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file-mount.md b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file-mount.md new file mode 100644 index 0000000000..103a5d29c4 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file-mount.md @@ -0,0 +1,78 @@ +# mount + +- [命令功能](#section11631837182) +- [命令格式](#section1697638111820) +- [参数说明](#section1650151221819) +- [使用指南](#section124541520171912) +- [使用实例](#section7424625171917) +- [输出说明](#section14757018116) + +## 命令功能 + +mount命令用来将设备挂载到指定目录。 + +## 命令格式 + +mount <_device_\> <_path_\> <_name_\> \[_uid gid_\] + +## 参数说明 + +**表 1** 参数说明 + + + + + + + + + + + + + + + + + + + + + + + + +

    参数

    +

    参数说明

    +

    取值范围

    +

    device

    +

    要挂载的设备(格式为设备所在路径)。

    +

    系统拥有的设备。

    +

    path

    +

    指定目录。

    +

    用户必须具有指定目录中的执行(搜索)许可权。

    +

    N/A

    +

    name

    +

    文件系统的种类。

    +

    vfat, yaffs, jffs, ramfs, nfs,procfs, romfs.

    +

    uid gid

    +

    uid是指用户ID。

    +

    gid是指组ID。

    +

    可选参数,缺省值uid:0,gid:0。

    +

    N/A

    +
    + +## 使用指南 + +mount后加需要挂载的设备信息、指定目录以及设备文件格式,就能成功挂载文件系统到指定目录。 + +## 使用实例 + +举例:mount /dev/mmcblk0p0 /bin1/vs/sd vfat + +## 输出说明 + +将/dev/mmcblk0p0 挂载到/bin1/vs/sd目录 + +![](figure/zh-cn_image_0000001051690323.png) + diff --git a/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file-part.md b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file-part.md new file mode 100644 index 0000000000..52ba25e101 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file-part.md @@ -0,0 +1,52 @@ +# partinfo + +- [命令功能](#section1777503617199) +- [命令格式](#section185501447132114) +- [参数说明](#section1304151212252) +- [使用指南](#section4566131982520) +- [使用实例](#section4351134942514) +- [输出说明](#section66689331412) + +## 命令功能 + +partinfo命令用于查看系统识别的硬盘,SD卡多分区信息。 + +## 命令格式 + +partinfo <_dev\_inodename_\> + +## 参数说明 + +**表 1** 参数说明 + + + + + + + + + + + + +

    参数

    +

    参数说明

    +

    取值范围

    +

    dev_inodename

    +

    要查看的分区名字。

    +

    合法的分区名。

    +
    + +## 使用指南 + +无 + +## 使用实例 + +partinfo /dev/mmcblk0p0 + +## 输出说明 + +![](figure/zh-cn_image_0000001052370303.png) + diff --git a/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file-partion.md b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file-partion.md new file mode 100644 index 0000000000..458f7f05ef --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file-partion.md @@ -0,0 +1,62 @@ +# partition + +- [命令功能](#section255095212257) +- [命令格式](#section10258056122515) +- [参数说明](#section177200581256) +- [使用指南](#section17866411262) +- [使用实例](#section1927174202610) +- [输出说明](#section11321011223) + +## 命令功能 + +partition命令用来查看flash分区信息。 + +## 命令格式 + +partition \[_nand / spinor_\] + +## 参数说明 + +**表 1** 参数说明 + + + + + + + + + + + + + + + + +

    参数

    +

    参数说明

    +

    取值范围

    +

    nand

    +

    显示nand flash分区信息。

    +

    N/A

    +

    spinor

    +

    显示spinor flash分区信息。

    +

    N/A

    +
    + +## 使用指南 + +- partition命令用来查看flash分区信息。 +- 仅当使能yaffs文件系统时才可以查看nand flash分区信息,使能jffs或romfs文件系统时可以查看spinor flash分区信息。 + +## 使用实例 + +举例:partition spinor + +## 输出说明 + +查看spinor flash分区信息 + +![](figure/zh-cn_image_0000001052810300.png) + diff --git a/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file-pwd.md b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file-pwd.md new file mode 100644 index 0000000000..c9d526fc07 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file-pwd.md @@ -0,0 +1,34 @@ +# pwd + +- [命令功能](#section197737712267) +- [命令格式](#section1544061016267) +- [参数说明](#section599112120262) +- [使用指南](#section66901116152615) +- [使用实例](#section7427181922612) +- [输出说明](#section116313389418) + +## 命令功能 + +pwd命令用来显示当前路径。 + +## 命令格式 + +pwd + +## 参数说明 + +无。 + +## 使用指南 + +pwd 命令将当前目录的全路径名称(从根目录)写入标准输出。全部目录使用 / (斜线)分隔。第一个 / 表示根目录, 最后一个目录是当前目录。 + +## 使用实例 + +举例:输入pwd + +## 输出说明 + +**图 1** 查看当前路径 +![](figure/查看当前路径.png "查看当前路径") + diff --git a/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file-rm.md b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file-rm.md new file mode 100644 index 0000000000..b9eb4d90a0 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file-rm.md @@ -0,0 +1,67 @@ +# rm + +- [命令功能](#section181141523142613) +- [命令格式](#section8800926132619) +- [参数说明](#section15476229152617) +- [使用指南](#section10578163215262) +- [使用实例](#section18548133511263) +- [输出说明](#section1565323814265) + +## 命令功能 + +rm命令用来删除文件或文件夹。 + +## 命令格式 + +rm \[_-r_\] \[_dirname / filename_\] + +## 参数说明 + +**表 1** 参数说明 + + + + + + + + + + + + + + + + +

    参数

    +

    参数说明

    +

    取值范围

    +

    -r

    +

    可选参数,若是删除目录则需要该参数。

    +

    N/A

    +

    dirname/filename

    +

    要删除文件或文件夹的名称,支持输入路径。

    +

    N/A

    +
    + +## 使用指南 + +- rm命令一次只能删除一个文件或文件夹。 +- rm -r命令可以删除非空目录。 + +## 使用实例 + +举例: + +1. 输入rm log1.txt +2. 输入rm -r sd + +## 输出说明 + +**图 1** 用 rm 命令删除文件 log1.txt +![](figure/用-rm-命令删除文件-log1-txt.png "用-rm-命令删除文件-log1-txt") + +**图 2** 用 rm -r 删除目录 sd +![](figure/用-rm--r-删除目录-sd.png "用-rm--r-删除目录-sd") + diff --git a/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file-rmdir.md b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file-rmdir.md new file mode 100644 index 0000000000..c37bbea17c --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file-rmdir.md @@ -0,0 +1,55 @@ +# rmdir + +- [命令功能](#section1839611420266) +- [命令格式](#section329574512266) +- [参数说明](#section15865747102620) +- [使用指南](#section107857508261) +- [使用实例](#section11196165315262) +- [输出说明](#section1073811415613) + +## 命令功能 + +rmdir命令用来删除一个目录。 + +## 命令格式 + +rmdir \[_dir_\] + +## 参数说明 + +**表 1** 参数说明 + + + + + + + + + + + + +

    参数

    +

    参数说明

    +

    取值范围

    +

    dir

    +

    需要删除目录的名称,删除目录必须为空,支持输入路径。

    +

    N/A

    +
    + +## 使用指南 + +- rmdir命令只能用来删除目录。 +- rmdir一次只能删除一个目录。 +- rmdir只能删除空目录。 + +## 使用实例 + +举例:输入rmdir dir + +## 输出说明 + +**图 1** 删除一个名为 dir 的目录 +![](figure/删除一个名为-dir-的目录.png "删除一个名为-dir-的目录") + diff --git a/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file-sta.md b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file-sta.md new file mode 100644 index 0000000000..2373311252 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file-sta.md @@ -0,0 +1,52 @@ +# statfs + +- [命令功能](#section153921657152613) +- [命令格式](#section135391102717) +- [参数说明](#section074312314279) +- [使用指南](#section133816772712) +- [使用实例](#section526149182717) + +## 命令功能 + +statfs命令用来打印文件系统的信息,如该文件系统类型、总大小、可用大小等信息。 + +## 命令格式 + +statfs \[_directory_\] + +## 参数说明 + +**表 1** 参数说明 + + + + + + + + + + + + +

    参数

    +

    参数说明

    +

    取值范围

    +

    directory

    +

    文件系统的路径。

    +

    必须是存在的文件系统,并且其支持statfs命令,当前支持的文件系统有:JFFS2,FAT,NFS。

    +
    + +## 使用指南 + +打印信息因文件系统而异。 + +## 使用实例 + +以nfs文件系统为例: + +statfs /nfs + +**图 1** statfs输出说明 +![](figure/statfs输出说明.png "statfs输出说明") + diff --git a/zh-cn/device-dev/kernel/sync.md b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file-sync.md old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/kernel/sync.md rename to zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file-sync.md diff --git a/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file-touch.md b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file-touch.md new file mode 100644 index 0000000000..1ec96315b5 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file-touch.md @@ -0,0 +1,59 @@ +# touch + +- [命令功能](#section17541924112716) +- [命令格式](#section866182711274) +- [参数说明](#section268912296270) +- [使用指南](#section412093332714) +- [使用实例](#section414434814354) +- [输出说明](#section1028419515711) + +## 命令功能 + +- touch命令用来在指定的目录下创建一个不存在的空文件。 +- touch命令操作已存在的文件会成功,不会更新时间戳。 + +## 命令格式 + +touch \[_filename_\] + +## 参数说明 + +**表 1** 参数说明 + + + + + + + + + + + + +

    参数

    +

    参数说明

    +

    取值范围

    +

    filename

    +

    需要创建文件的名称。

    +

    N/A

    +
    + +## 使用指南 + +- touch命令用来创建一个空文件,该文件可读写。 +- 使用touch命令一次只能创建一个文件。 + + >![](../public_sys-resources/icon-notice.gif) **须知:** + >在系统重要资源路径下使用touch命令创建文件,会对系统造成死机等未知影响,如在/dev路径下执行touch uartdev-0,会产生系统卡死现象。 + + +## 使用实例 + +举例:输入touch file.c 输出说明 + +## 输出说明 + +**图 1** 创建一个名为 file.c 的文件 +![](figure/创建一个名为-file-c-的文件.png "创建一个名为-file-c-的文件") + diff --git a/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file-umount.md b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file-umount.md new file mode 100644 index 0000000000..def6e2f84b --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file-umount.md @@ -0,0 +1,55 @@ +# umount + +- [命令功能](#section365125133520) +- [命令格式](#section9615254123512) +- [参数说明](#section63446577355) +- [使用指南](#section92931509368) +- [使用实例](#section144311323616) +- [输出说明](#section360525113611) + +## 命令功能 + +umount命令用来卸载指定文件系统。 + +## 命令格式 + +umount \[_dir_\] + +## 参数说明 + +**表 1** 参数说明 + + + + + + + + + + + + +

    参数

    +

    参数说明

    +

    取值范围

    +

    dir

    +

    需要卸载文件系统对应的目录。

    +

    系统已挂载的文件系统的目录。

    +
    + +## 使用指南 + +umount后加上需要卸载的指定文件系统的目录,即将指定文件系统卸载。 + +## 使用实例 + +举例:umount /bin1/vs/sd + +## 输出说明 + +将已在/bin1/vs/sd挂载的文件系统卸载 + +**图 1** umount输出示例 +![](figure/umount输出示例.png "umount输出示例") + diff --git a/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file-write.md b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file-write.md new file mode 100644 index 0000000000..c94ac15b6a --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file-write.md @@ -0,0 +1,69 @@ +# writeproc + +- [命令功能](#section366714216619) +- [命令格式](#section8833164614615) +- [参数说明](#section12809111019453) +- [使用指南](#section15935131220717) +- [使用实例](#section79281818476) +- [输出说明](#section12742311179) + +## 命令功能 + +proc fs支持传入字符串参数,需要每个文件实现自己的写方法。 + +## 命令格式 + +writeproc <_data_\> \>\> /proc/<_filename_\> + +## 参数说明 + +**表 1** 参数说明 + + + + + + + + + + + + + + + + +

    参数

    +

    参数说明

    +

    取值范围

    +

    data

    +

    要输入的字符串,以空格为结束符,如需输入空格,请用""包裹。

    +

    N/A

    +

    filename

    +

    data要传入的proc文件。

    +

    N/A

    +
    + +## 使用指南 + +proc文件实现自身的write函数,调用writeproc命令后会将入参传入write函数。 + +>![](../public_sys-resources/icon-note.gif) **说明:** +>procfs不支持多线程访问。 + +## 使用实例 + +举例:writeproc test \>\> /proc/uptime + +## 输出说明 + +OHOS \# writeproc test \>\> /proc/uptime + +\[INFO\]write buf is: test + +test \>\> /proc/uptime + +>![](../public_sys-resources/icon-note.gif) **说明:** +>uptime proc文件临时实现write函数,INFO日志为实现的测试函数打印的日志。 + diff --git a/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file.md b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file.md new file mode 100644 index 0000000000..f2d8302ca4 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file.md @@ -0,0 +1,45 @@ +# 文件命令 + +- **[cat](kernel-lite-small-shell-cmd-file-cat.md)** + +- **[cd](kernel-lite-small-shell-cmd-file-cd.md)** + +- **[chgrp](kernel-lite-small-shell-cmd-file-chgrp.md)** + +- **[chmod](kernel-lite-small-shell-cmd-file-chmod.md)** + +- **[chown](kernel-lite-small-shell-cmd-file-chown.md)** + +- **[cp](kernel-lite-small-shell-cmd-file-cp.md)** + +- **[format](kernel-lite-small-shell-cmd-file-format.md)** + +- **[ls](kernel-lite-small-shell-cmd-file-is.md)** + +- **[lsfd](kernel-lite-small-shell-cmd-file-isfd.md)** + +- **[mkdir](kernel-lite-small-shell-cmd-file-mkdir.md)** + +- **[mount](kernel-lite-small-shell-cmd-file-mount.md)** + +- **[partinfo](kernel-lite-small-shell-cmd-file-part.md)** + +- **[partition](kernel-lite-small-shell-cmd-file-partion.md)** + +- **[pwd](kernel-lite-small-shell-cmd-file-pwd.md)** + +- **[rm](kernel-lite-small-shell-cmd-file-rm.md)** + +- **[rmdir](kernel-lite-small-shell-cmd-file-rmdir.md)** + +- **[statfs](kernel-lite-small-shell-cmd-file-sta.md)** + +- **[sync](kernel-lite-small-shell-cmd-file-sync.md)** + +- **[touch](kernel-lite-small-shell-cmd-file-touch.md)** + +- **[writeproc](kernel-lite-small-shell-cmd-file-write.md)** + +- **[umount](kernel-lite-small-shell-cmd-file-umount.md)** + + diff --git a/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-mag.md b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-mag.md new file mode 100644 index 0000000000..bc083f86ce --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-mag.md @@ -0,0 +1,38 @@ +# 魔法键使用方法 + +- [使用场景](#section2350114718546) +- [使用方法](#section3305151511559) + +## 使用场景 + +在系统运行出现无响应等情况时,可以通过魔法键功能确定系统是否被锁中断(魔法键也无响应)或者查看系统任务运行状态等信息。 + +在中断有响应的情况下,可以通过魔法键查看task信息中 cpup(CPU占用率)看是哪个任务长时间占用CPU导致系统其他任务无响应(一般为比较高优先级任务一直抢占CPU,导致低优先级任务无响应)。 + +## 使用方法 + +1. 配置宏LOSCFG\_ENABLE\_MAGICKEY。 + +魔法键依赖于宏LOSCFG\_ENABLE\_MAGICKEY,使用时通过menuconfig在配置项中开启“Enable MAGIC KEY”: + +Debug ---\> Enable MAGIC KEY;若关闭该选项,则魔法键失效。 + +>![](../public_sys-resources/icon-note.gif) **说明:** +>1. 可以在menuconfig中,将光标移动到LOSCFG\_ENABLE\_MAGICKEY上,输入“?”,查看帮助信息。 + +2. 输入“ctrl + r”键,打开魔法键检测功能。 + +在连接UART或者USB转虚拟串口的情况下,输入“ctrl + r” 键,打开魔法键检测功能,输出 “Magic key on”;再输入一次后,则关闭魔法键检测功能,输出“Magic key off”。魔法键功能如下: + +- ctrl + z:帮助键,输出相关魔法键简单介绍; + +- ctrl + t:输出任务相关信息; + +- ctrl + p:系统主动进入panic,输出panic相关信息后,系统会挂住; + +- ctrl + e:系统进行简单完整性内存池检查,检查出错会输出相关错误信息,检查正常会输出“system memcheck over, all passed!”。 + + +>![](../public_sys-resources/icon-notice.gif) **须知:** +>魔法键检测功能打开情况下,如果需要通过UART或者USB转虚拟串口输入特殊字符需避免与魔法键值重复,否则魔法键会被误触发,而原有设计功能可能出现错误。 + diff --git a/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-net-arp.md b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-net-arp.md new file mode 100644 index 0000000000..7ff926b410 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-net-arp.md @@ -0,0 +1,114 @@ +# arp + +- [命令功能](#section201149459368) +- [命令格式](#section579813484364) +- [参数说明](#section168065311366) +- [使用指南](#section19190125723612) +- [使用实例](#section10383416372) + +## 命令功能 + +在以太网中,主机之间的通信是直接使用MAC地址(非IP地址)来通信的,所以,对于使用IP通信的协议,必须能够将IP地址转换成MAC地址,才能在局域网(以太网)内通信。解决这个问题的方法就是主机存储一张IP和MAC地址对应的表,即ARP缓存,主机要往一个局域网内的目的IP地址发送IP包时,就可以从ARP缓存表中查询到目的MAC地址。ARP缓存是由TCP/IP协议栈维护的,用户可通过ARP命令查看和修改ARP表。 + +## 命令格式 + +arp + +arp \[_-i IF_\] -s _IPADDR HWADDR_ + +arp \[_-i IF_\] -d _IPADDR_ + +## 参数说明 + +**表 1** 参数说明 + + + + + + + + + + + + + + + + + + + + + + + + +

    参数

    +

    参数说明

    +

    取值范围

    +

    +

    打印整个ARP缓存的内容。

    +

    N/A

    +

    -i IF

    +

    指定的网络接口(可选参数)。

    +

    N/A

    +

    -s IPADDR

    +

    HWADDR

    +

    增加一条ARP表项,后面的参数是局域网中另一台主机的IP地址及其对应的MAC地址。

    +

    N/A

    +

    -d IPADDR

    +

    删除一条ARP表项。

    +

    N/A

    +
    + +## 使用指南 + +- arp命令用来查询和修改TCP/IP协议栈的ARP缓存表,增加非同一子网内的IP地址的ARP表项是没有意义的,协议栈会返回失败。 +- 命令需要启动TCP/IP协议栈后才能使用。 + +## 使用实例 + +举例: + +1. 输入arp + + **图 1** 打印整个 ARP 缓存表 + + + ![](figure/Snipaste_2021-01-26_10-38-58.png) + + **表 2** 参数说明 + + + + + + + + + + + + + + + + + + + +

    参数

    +

    说明

    +

    Address

    +

    表示网络设备的IPv4地址。

    +

    HWaddress

    +

    表示网络设备的MAC地址。

    +

    Iface

    +

    表示该ARP表项使用的接口名。

    +

    Type

    +

    表示该ARP表项是动态的还是静态的,动态是指ARP表项由协议栈自动创建,静态是指ARP表项是由用户增加的。

    +
    + + diff --git a/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-net-dh.md b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-net-dh.md new file mode 100644 index 0000000000..05d883c72b --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-net-dh.md @@ -0,0 +1,138 @@ +# dhclient + +- [命令功能](#section366714216619) +- [命令格式](#section8833164614615) +- [参数说明](#section12809111019453) +- [使用指南](#section15935131220717) +- [使用实例](#section79281818476) +- [输出说明](#section12742311179) + +## 命令功能 + +设置和查看dhclient的参数。 + +## 命令格式 + +dhclient <_netif name_\> + +dhclient -x <_netif name_\> + +dhclient -gb <_netif name_\> + +dhclient -sv <_vendor_\> + +dhclient -gv + +dhclient -gd <_index_\> + +dhclient -sd <_dns\_ip_\> + +## 参数说明 + +**表 1** 参数说明 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    参数

    +

    参数说明

    +

    取值范围

    +

    <netif name>

    +

    启动对应网卡的dhcp请求。

    +

    网卡名字,eth0。

    +

    -x <netif name>

    +

    关闭对应网卡的dhcp功能。

    +

    网卡名字,eth0。

    +

    -gb <netif name>

    +

    查看对应网卡的dhcp请求是否完成。

    +

    网卡名字,eth0。

    +

    -sv <vendor>

    +

    设置dhcp请求的厂商信息。

    +

    厂商信息,长度是32个字符。

    +

    -gv

    +

    查看dhcp请求的厂商信息。

    +

    N/A

    +

    -gd <index>

    +

    获取第index个dns server的信息。

    +

    index,0或者1。

    +

    -sd <dns_ip>

    +

    设置主dns server的ip。

    +

    dns的ip地址。

    +
    + +## 使用指南 + +dhclient eth0 + +dhclient -x eth0 + +dhclient -gb eth0 + +dhclient -sv MFSI + +dhclient -gv + +dhclient -gd 0 + +dhclient -sd 8.8.8.8 + +## 使用实例 + +![](figure/zh-cn_image_0000001053224218.png) + +## 输出说明 + +**表 2** 输出说明 + + + + + + + + + + + + + +

    输出

    +

    说明

    +

    dhclient: set vendor info [MFSI] success

    +

    设置厂商信息MFSI信息成功。

    +

    dns[0]: 192.168.1.100

    +

    dns server ip地址为192.168.1.100。

    +
    + diff --git a/zh-cn/device-dev/kernel/dns.md b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-net-dns.md old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/kernel/dns.md rename to zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-net-dns.md diff --git a/zh-cn/device-dev/kernel/ifconfig.md b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-net-ipc.md old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/kernel/ifconfig.md rename to zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-net-ipc.md diff --git a/zh-cn/device-dev/kernel/ipdebug.md b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-net-ipd.md old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/kernel/ipdebug.md rename to zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-net-ipd.md diff --git a/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-net-net.md b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-net-net.md new file mode 100644 index 0000000000..b35a6494a1 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-net-net.md @@ -0,0 +1,83 @@ +# netstat + +- [命令功能](#section13469162113816) +- [命令格式](#section795712373812) +- [参数说明](#section17629431193817) +- [使用指南](#section5277153519380) +- [使用实例](#section108141437163820) +- [输出说明](#section1357015107117) + +## 命令功能 + +netstat是控制台命令,是一个监测TCP/IP网络的非常有用的工具,它可以显示实际的网络连接以及每一个网络接口设备的状态信息。netstat用于显示与TCP、UDP协议相关的统计数据,一般用于检验本设备(单板)各端口的网络连接情况。 + +## 命令格式 + +netstat + +## 参数说明 + +无 + +## 使用指南 + +直接输入命令。 + +## 使用实例 + +举例:输入netstat + +**图 1** netstat 打印信息 + + +![](figure/Snipaste_2021-01-26_10-38-58-18.png) + +## 输出说明 + +**表 1** 输出说明 + + + + + + + + + + + + + + + + + + + + + + + + + +

    输出

    +

    说明

    +

    Proto

    +

    协议类型。

    +

    Recv-Q

    +

    未被用户读取的数据量。

    +

    对于Listen TCP,此值为已完成三次握手,但是未被用户accept的TCP连接的数量。

    +

    Send-Q

    +

    对TCP连接,已发送但未确认的数据量。

    +

    对UDP连接,由于IP地址解析未完成而缓存的数据量。

    +

    Local Address

    +

    本地地址和端口。

    +

    Foreign Address

    +

    远程地址和端口。

    +

    State

    +

    TCP连接状态,UDP此项无意义。

    +
    + +>![](../public_sys-resources/icon-note.gif) **说明:** +>形如“========== total sockets 32 ====== unused sockets 22 BootTime 27 s ========== ”,表示一共32个套接字,未使用套接字22个,距系统启动已经过27秒。 + diff --git a/zh-cn/device-dev/kernel/ntpdate.md b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-net-ntp.md old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/kernel/ntpdate.md rename to zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-net-ntp.md diff --git a/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-net-ping.md b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-net-ping.md new file mode 100644 index 0000000000..e1792bc92d --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-net-ping.md @@ -0,0 +1,99 @@ +# ping + +- [命令功能](#section119672573385) +- [命令格式](#section869419010390) +- [参数说明](#section9877183173918) +- [使用指南](#section1097046193914) +- [使用实例](#section14564129113911) +- [输出说明](#section1621732891215) + +## 命令功能 + +ping命令用于测试网络连接是否正常。 + +## 命令格式 + +ping_ _\[_-n cnt_\] \[_-w interval_\] \[_-l data\_len_\]_ _ + +ping \[_-t_\] \[_-w interval_\] __ + +ping _-k_ + +## 参数说明 + +**表 1** 参数说明 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    参数

    +

    参数说明

    +

    取值范围

    +

    IP

    +

    要测试是否网络连通的IPv4地址。

    +

    N/A

    +

    -n cnt

    +

    执行的次数,不带本参数则默认为4次。

    +

    1-65535

    +

    -w interval

    +

    发送两次ping包的时间间隔,单位毫秒。

    +

    >0

    +

    -l data_len

    +

    ping包,即ICMP echo request报文的数据长

    +

    度,不包含ICMP包头。

    +

    0-65500

    +

    -t

    +

    表示永久ping,直到使用ping -k杀死ping线

    +

    程。

    +

    N/A

    +

    -k

    +

    杀死ping线程,停止ping。

    +

    N/A

    +
    + +## 使用指南 + +- ping命令用来测试到目的IP的网络连接是否正常,参数为目的IP地址。 +- 如果目的IP不可达,会显示请求超时。 +- 如果显示发送错误,说明没有到目的IP的路由。 +- 命令需要启动TCP/IP协议栈后才能使用。 + +## 使用实例 + +举例:输入ping 192.168.1.10 + +## 输出说明 + +**图 1** ping tftp 服务器地址 + + +![](figure/Snipaste_2021-01-26_10-38-58-19.png) + diff --git a/zh-cn/device-dev/kernel/ping6.md b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-net-ping6.md old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/kernel/ping6.md rename to zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-net-ping6.md diff --git a/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-net-tel.md b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-net-tel.md new file mode 100644 index 0000000000..95e8083c80 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-net-tel.md @@ -0,0 +1,65 @@ +# telnet + +- [命令功能](#section3551830123913) +- [命令格式](#section14897133233918) +- [参数说明](#section977718353392) +- [使用指南](#section134991538183916) +- [使用实例](#section1097414426398) +- [输出说明](#section11846624191310) + +## 命令功能 + +本命令用于启动或关闭telnet server服务。 + +## 命令格式 + +telnet \[_on | off_\] + +## 参数说明 + +**表 1** 参数说明 + + + + + + + + + + + + + + + + +

    参数

    +

    参数说明

    +

    取值范围

    +

    on

    +

    启动telnet server服务。

    +

    N/A

    +

    off

    +

    关闭telnet server服务。

    +

    N/A

    +
    + +## 使用指南 + +- telnet启动要确保网络驱动及网络协议栈已经初始化完成,且板子的网卡是link up状态。 +- 暂时无法支持多个客户端(telnet + IP)同时连接开发板。 + + >![](../public_sys-resources/icon-notice.gif) **须知:** + >telnet属于调测功能,默认配置为关闭,正式产品中禁止使用该功能。 + + +## 使用实例 + +举例:输入telnet on + +## 输出说明 + +**图 1** 输入 telnet on +![](figure/输入-telnet-on.png "输入-telnet-on") + diff --git a/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-net-tftp.md b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-net-tftp.md new file mode 100644 index 0000000000..d0a864992f --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-net-tftp.md @@ -0,0 +1,87 @@ +# tftp + +- [命令功能](#section15142134573911) +- [命令格式](#section20958174917394) +- [参数说明](#section576613532395) +- [使用指南](#section149795134408) +- [使用实例](#section148921918114015) +- [输出说明](#section7872155631313) + +## 命令功能 + +TFTP(Trivial File Transfer Protocol,简单文件传输协议)是TCP/IP协议族中的一个用来在客户机与服务器之间进行简单文件传输的协议,提供简单、低开销的文件传输服务。端口号为69。 + +tftp命令可以从TFTP服务器上下载文件。 + +## 命令格式 + +./bin/tftp _<-g/-p\>_ _-l_ _\[FullPathLocalFile\] -r \[RemoteFile\] \[Host\]_ + +## 参数说明 + +**表 1** 参数说明 + + + + + + + + + + + + + + + + + + + + + + + + +

    参数

    +

    参数说明

    +

    取值范围

    +

    -g/-p

    +

    文件传输方向:

    +
    • -g 从TFTP服务器获取文件。
    • -p 上传文件到TFTP服务器。
    +

    N/A

    +

    -l FullPathLocalFile

    +

    本地文件完整路径。

    +

    N/A

    +

    -r RemoteFile

    +

    服务端文件名。

    +

    N/A

    +

    Host

    +

    服务端IP。

    +

    N/A

    +
    + +## 使用指南 + +1. 在服务器端搭建TFTP服务器,并进行正确配置。 +2. OpenHarmony单板使用tftp命令上传、下载文件。 +3. 传输的文件大小是有限制的不能大于32M。 + + >![](../public_sys-resources/icon-notice.gif) **须知:** + >tftp属于调测功能,默认配置为关闭,正式产品中禁止使用该功能。 + + +## 使用实例 + +举例:从服务器下载out文件。 + +## 输出说明 + +``` +OHOS # ./bin/tftp -g -l /nfs/out -r out 192.168.1.2 +TFTP transfer finish +``` + +tftp命令执行后,传输正常完成会显示TFTP transfer finish, 失败的话会显示其他的打印信息帮助定位问题。 + diff --git a/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-net.md b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-net.md new file mode 100644 index 0000000000..6695d35058 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-net.md @@ -0,0 +1,25 @@ +# 网络命令 + +- **[arp](kernel-lite-small-shell-cmd-net-arp.md)** + +- **[dhclient](kernel-lite-small-shell-cmd-net-dh.md)** + +- **[dns](kernel-lite-small-shell-cmd-net-dns.md)** + +- **[ifconfig](kernel-lite-small-shell-cmd-net-ipc.md)** + +- **[ipdebug](kernel-lite-small-shell-cmd-net-ipd.md)** + +- **[netstat](kernel-lite-small-shell-cmd-net-net.md)** + +- **[ntpdate](kernel-lite-small-shell-cmd-net-ntp.md)** + +- **[ping](kernel-lite-small-shell-cmd-net-ping.md)** + +- **[ping6](kernel-lite-small-shell-cmd-net-ping6.md)** + +- **[telnet](kernel-lite-small-shell-cmd-net-tel.md)** + +- **[tftp](kernel-lite-small-shell-cmd-net-tftp.md)** + + diff --git a/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys-cpup.md b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys-cpup.md new file mode 100644 index 0000000000..5d9bf1de8a --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys-cpup.md @@ -0,0 +1,65 @@ +# cpup + +- [命令功能](#section1842161614217) +- [命令格式](#section5629527427) +- [参数说明](#section133651361023) +- [使用指南](#section156611948521) +- [使用实例](#section68501605319) +- [输出说明](#section19871522144219) + +## 命令功能 + +cpup命令用于查询系统CPU的占用率。 + +## 命令格式 + +cpup \[_mode_\] \[_taskID_\] + +## 参数说明 + +**表 1** 参数说明 + + + + + + + + + + + + + + + + +

    参数

    +

    参数说明

    +

    取值范围

    +

    mode

    +

    ● 缺省:显示系统最近10s内的CPU占用率。

    +

    ● 0:显示系统最近10s内的CPU占用率。

    +

    ● 1:显示系统最近1s内的CPU占用率。

    +

    ● 其他数字:显示系统启动至今总的CPU 占用率。

    +

    [0,0xFFFFFFFF]

    +

    taskID

    +

    任务ID号

    +

    [0,0xFFFFFFFF]

    +
    + +## 使用指南 + +- 参数缺省时,显示系统10s前的CPU占用率。 +- 只有一个参数时,该参数为mode,显示系统相应时间前的CPU占用率。 +- 输入两个参数时,第一个参数为mode,第二个参数为taskID,显示对应ID号任务的相应时间前的CPU占用率。 + +## 使用实例 + +举例:输入cpup 1 5 + +## 输出说明 + +**图 1** 指令输出结果 +![](figure/指令输出结果.png "指令输出结果") + diff --git a/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys-date.md b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys-date.md new file mode 100644 index 0000000000..0ee6698e2f --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys-date.md @@ -0,0 +1,94 @@ +# date + +- [命令功能](#section56472016338) +- [命令格式](#section16635112512316) +- [参数说明](#section15896030039) +- [使用指南](#section116361036636) +- [使用实例](#section021711411237) +- [输出说明](#section17950184414312) + +## 命令功能 + +date命令用于查询及设置系统日期和时间。 + +## 命令格式 + +date + +date --help + +date +\[_Format_\] + +date -s_ _\[_YY/MM/DD_\] + +date_ _-s_ _\[_hh:mm:ss_\]__ + +date -r \[_Filename_\] + +## 参数说明 + +**表 1** 参数说明 + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    参数

    +

    参数说明

    +

    取值范围

    +

    --help

    +

    使用帮助。

    +

    N/A

    +

    +Format

    +

    根据Format格式打印日期和时间。

    +

    --help中列出的占位符。

    +

    -s YY/MM/DD

    +

    设置系统时间,用“/”分割的年月日。

    +

    >= 1970/01/01

    +

    -s hh:mm:ss

    +

    设置系统时间,用“:”分割的时分秒。

    +

    N/A

    +

    -r Filename

    +

    查询Filename文件的修改时间。

    +

    N/A

    +
    + +## 使用指南 + +- date参数缺省时,默认显示当前系统日期和时间。 +- --help、+Format、-s、-r不能混合使用。 + +## 使用实例 + +举例: + +输入date +%Y--%m--%d。 + +## 输出说明 + +**图 1** 按指定格式打印系统日期 +![](figure/按指定格式打印系统日期.png "按指定格式打印系统日期") + diff --git a/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys-demsg.md b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys-demsg.md new file mode 100644 index 0000000000..b4e1bbd9ee --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys-demsg.md @@ -0,0 +1,113 @@ +# dmesg + +- [命令功能](#section4643204919313) +- [命令格式](#section6553153635) +- [参数说明](#section208971157532) +- [使用指南](#section213115219413) +- [使用实例](#section13736564418) +- [输出说明](#section194005101413) + +## 命令功能 + +dmesg命令用于控制内核dmesg缓存区。 + +## 命令格式 + +dmesg + +dmesg \[_-c/-C/-D/-E/-L/-U_\] + +dmesg -s \[_size_\] + +dmesg -l \[_level_\] + +dmesg \> \[_fileA_\] + +## 参数说明 + +**表 1** 参数说明 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    参数

    +

    参数说明

    +

    取值范围

    +

    -c

    +

    打印缓存区内容并清空缓存区。

    +

    N/A

    +

    -C

    +

    清空缓存区。

    +

    N/A

    +

    -D/-E

    +

    关闭/开启控制台打印。

    +

    N/A

    +

    -L/-U

    +

    关闭/开启串口打印。

    +

    N/A

    +

    -s size

    +

    设置缓存区大小 size是要设置的大小。

    +

    N/A

    +

    -l level

    +

    设置缓存等级。

    +

    0 - 5

    +

    > fileA

    +

    将缓存区内容写入文件。

    +

    N/A

    +
    + +## 使用指南 + +- 该命令依赖于LOSCFG\_SHELL\_DMESG,使用时通过menuconfig在配置项中开启"Enable Shell dmesg": + + Debug ---\> Enable a Debug Version ---\> Enable Shell ---\> Enable Shell dmesg + +- dmesg参数缺省时,默认打印缓存区内容。 +- 各“ - ”选项不能混合使用。 + 1. 写入文件需确保已挂载文件系统。 + 2. 关闭串口打印会影响shell使用,建议先连接telnet再尝试关闭串口。 + + +## 使用实例 + +举例: + +输入dmesg \> /usr/dmesg.log。 + +## 输出说明 + +**图 1** dmesg重定向到文件。 +![](figure/dmesg重定向到文件.png "dmesg重定向到文件") + diff --git a/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys-exec.md b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys-exec.md new file mode 100644 index 0000000000..c5e437ad7c --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys-exec.md @@ -0,0 +1,60 @@ +# exec + +- [命令功能](#section4643204919313) +- [命令格式](#section6553153635) +- [参数说明](#section208971157532) +- [使用指南](#section213115219413) +- [使用实例](#section13736564418) +- [输出说明](#section194005101413) + +## 命令功能 + +exec命令属于shell内置命令,目前实现最基础的执行用户态程序的功能。 + +## 命令格式 + +exec <_executable-file_\> + +## 参数说明 + +**表 1** 参数说明 + + + + + + + + + + + + +

    参数

    +

    参数说明

    +

    取值范围

    +

    executable-file

    +

    有效的可执行文件。

    +

    N/A

    +
    + +## 使用指南 + +该命令当前仅支持执行有效的二进制程序,程序成功执行,默认后台运行,但与Shell共用终端,可能会导致程序打印输出与Shell输出交错显示。 + +## 使用实例 + +举例: + +输入exec helloworld。 + +## 输出说明 + +``` +OHOS # exec helloworld +OHOS # hello world! +``` + +>![](../public_sys-resources/icon-note.gif) **说明:** +>可执行文件执行后,先打印“OHOS \#”提示符原因:目前Shell “exec”命令执行均为后台执行,结果可能导致提示符提前打印。 + diff --git a/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys-free.md b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys-free.md new file mode 100644 index 0000000000..dcfdc36382 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys-free.md @@ -0,0 +1,119 @@ +# free + +- [命令功能](#section175151514841) +- [命令格式](#section8488721749) +- [参数说明](#section27272181949) +- [使用指南](#section148661259410) +- [使用实例](#section68081530242) +- [输出说明](#section171235517543) + +## 命令功能 + +free命令可显示系统内存的使用情况,同时显示系统的text段、data段、rodata段、bss段大小。 + +## 命令格式 + +free \[_-k | -m_\] + +## 参数说明 + +**表 1** 参数说明 + + + + + + + + + + + + + + + + + + + + +

    参数

    +

    参数说明

    +

    取值范围

    +

    无参数

    +

    以Byte为单位显示。

    +

    N/A

    +

    -k

    +

    以KB为单位显示。

    +

    N/A

    +

    -m

    +

    以MB为单位显示。

    +

    N/A

    +
    + +## 使用指南 + +无。 + +## 使用实例 + +举例:分别输入free、free -k、free -m. + +## 输出说明 + +**图 1** 以三种方式显示内存使用情况 +![](figure/以三种方式显示内存使用情况.png "以三种方式显示内存使用情况") + +**表 2** 输出说明 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    输出

    +

    说明

    +

    total

    +

    表示系统动态内存池总量。

    +

    used

    +

    表示已使用内存总量。

    +

    free

    +

    表示未被分配的内存大小。

    +

    heap

    +

    表示已分配堆大小。

    +

    text

    +

    表示代码段大小。

    +

    data

    +

    表示数据段大小。

    +

    rodata

    +

    表示只读数据段大小。

    +

    bss

    +

    表示未初始化全局变量占用内存大小。

    +
    + diff --git a/zh-cn/device-dev/kernel/help.md b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys-help.md old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/kernel/help.md rename to zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys-help.md diff --git a/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys-hwi.md b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys-hwi.md new file mode 100644 index 0000000000..9414e1f744 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys-hwi.md @@ -0,0 +1,94 @@ +# hwi + +- [命令功能](#section445335110416) +- [命令格式](#section1795712553416) +- [参数说明](#section92544592410) +- [使用指南](#section104151141252) +- [使用实例](#section11545171957) +- [输出说明](#section075617368542) + +## 命令功能 + +hwi命令查询当前中断信息 + +## 命令格式 + +hwi + +## 参数说明 + +无。 + +## 使用指南 + +- 输入hwi即显示当前中断号、中断次数及注册中断名称。 +- 若开关LOSCFG\_CPUP\_INCLUDE\_IRQ打开,则还会显示各个中断的处理时间(cycles)、CPU占用率以及中断类型。 + +## 使用实例 + +举例:输入hwi + +## 输出说明 + +1. 显示中断信息(LOSCFG\_CPUP\_INCLUDE\_IRQ关闭) + + ![](figure/zh-cn_image_0000001053826366.png) + +2. 显示中断信息(LOSCFG\_CPUP\_INCLUDE\_IRQ打开) + + ![](figure/zh-cn_image_0000001052810304.png) + + **表 1** 输出说明 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    输出

    +

    说明

    +

    InterruptNo

    +

    中断号。

    +

    Count

    +

    中断次数。

    +

    Name

    +

    注册中断名称。

    +

    CYCLECOST

    +

    中断的处理时间(cycles)。

    +

    CPUUSE

    +

    CPU占用率。

    +

    CPUUSE10s

    +

    最近10s CPU占用率。

    +

    CPUUSE1s

    +

    最近1s CPU占用率。

    +

    mode

    +

    中断类型:

    +
    • normal: 非共享中断。
    • shared: 共享中断。
    +
    + + diff --git a/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys-kill.md b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys-kill.md new file mode 100644 index 0000000000..6f1447fbda --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys-kill.md @@ -0,0 +1,82 @@ +# kill + +- [命令功能](#section366714216619) +- [命令格式](#section8833164614615) +- [参数说明](#section12809111019453) +- [使用指南](#section15935131220717) +- [使用实例](#section79281818476) +- [输出说明](#section12742311179) + +## 命令功能 + +命令用于发送特定信号给指定进程。 + +## 命令格式 + +kill \[_signo_ | _-signo_\] \[_pid_\] + +## 参数说明 + +**表 1** 参数说明 + + + + + + + + + + + + + + + + +

    参数

    +

    参数说明

    +

    取值范围

    +

    signo

    +

    信号ID。

    +

    [1,30]

    +

    pid

    +

    进程ID。

    +

    [1,MAX_INT]

    +
    + +>![](../public_sys-resources/icon-notice.gif) **须知:** +>signo有效范围为\[0,64\],建议取值范围为\[1,30\],其余为保留内容。 + +## 使用指南 + +必须指定发送的信号编号及进程号。 + +进程编号取值范围根据系统配置变化,例如系统最大支持pid为256,则取值范围缩小为\[1-256\]。 + +## 使用实例 + +1. 查看当前进程列表,查看需要杀死的进程PID(7)。 + +**图 1** 查看进程PID +![](figure/查看进程PID.png "查看进程PID") + +2. 发送信号14(SIGALRM默认行为为进程终止)给7号进程**helloworld\_d**(用户态进程):**kill 14 7**(kill -14 7效果相同),并查看当前进程列表,7号进程已终止。 + +**图 2** 信号发送结果图 +![](figure/信号发送结果图.png "信号发送结果图") + +## 输出说明 + +发送成功或失败输出结果如下。 + +**图 3** 发送信号给指定进程 +![](figure/发送信号给指定进程.png "发送信号给指定进程") + +信号发送会显示发送记录,未报错表示信号发送成功。 + +**图 4** 信号发送失败 +![](figure/信号发送失败.png "信号发送失败") + +信号发送失败,上图所示原因为信号发送命令参数无效,请排查信号编号及进程编号是否无效。 + diff --git a/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys-log.md b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys-log.md new file mode 100644 index 0000000000..cdadf98593 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys-log.md @@ -0,0 +1,74 @@ +# log + +- [命令功能](#section128219131856) +- [命令格式](#section3894181710519) +- [参数说明](#section7693122310515) +- [使用指南](#section1982111281512) +- [使用实例](#section176301333259) +- [输出说明](#section14354765415) + +## 命令功能 + +log命令用于修改&查询日志配置。 + +## 命令格式 + +log level \[_levelNum_\] + +## 参数说明 + +**表 1** 参数说明 + + + + + + + + + + + + +

    参数

    +

    参数说明

    +

    取值范围

    +

    levelNum

    +

    配置日志打印等级。

    +

    [0x0,0x5]

    +
    + +## 使用指南 + +- 该命令依赖于LOSCFG\_SHELL\_LK,使用时通过menuconfig在配置项中开启"Enable Shell lk": + + Debug ---\> Enable a Debug Version ---\> Enable Shell ---\> Enable Shell lK。 + +- log level命令用于配置日志的打印等级,包括6个等级 + + TRACE\_EMG = 0, + + TRACE\_COMMON = 1, + + TRACE\_ERROR = 2, + + TRACE\_WARN = 3, + + TRACE\_INFO = 4, + + TRACE\_DEBUG = 5 + + 若level不在有效范围内,会打印提示信息。 + +- 若log level命令不加\[levelNum\]参数,则默认查看当前打印等级,并且提示使用方法。 + +## 使用实例 + +举例: + +输入log level 4 + +## 输出说明 + +![](figure/zh-cn_image_0000001052530298.png) + diff --git a/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys-mem.md b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys-mem.md new file mode 100644 index 0000000000..8ff0289bcd --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys-mem.md @@ -0,0 +1,38 @@ +# memcheck + +- [命令功能](#section191633812516) +- [命令格式](#section428816435510) +- [参数说明](#section1939943304411) +- [使用指南](#section228914491951) +- [使用实例](#section17373205314515) +- [输出说明](#section13406205385413) + +## 命令功能 + +检查动态申请的内存块是否完整,是否存在内存越界造成节点损坏。 + +## 命令格式 + +memcheck + +## 参数说明 + +无。 + +## 使用指南 + +- 当内存池所有节点完整时,输出"system memcheck over, all passed!"。 +- 当内存池存在节点不完整时,输出被损坏节点的内存块信息。 + +## 使用实例 + +举例:输入memcheck + +## 输出说明 + +**图 1** 当前没有内存越界 +![](figure/当前没有内存越界.png "当前没有内存越界") + +**图 2** 出现内存越界 +![](figure/出现内存越界.png "出现内存越界") + diff --git a/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys-oom.md b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys-oom.md new file mode 100644 index 0000000000..e21772b94e --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys-oom.md @@ -0,0 +1,120 @@ +# oom + +- [命令功能](#section366714216619) +- [命令格式](#section8833164614615) +- [参数说明](#section12809111019453) +- [使用指南](#section15935131220717) +- [使用实例](#section79281818476) +- [输出说明](#section12742311179) + +## 命令功能 + +查看和设置低内存阈值以及pagecache内存回收阈值。 + +## 命令格式 + +oom + +oom -i \[_interval_\] + +oom -m \[_mem byte_\] + +oom -r \[_mem byte_\] + +oom -h | --help + +## 参数说明 + +**表 1** 参数说明 + + + + + + + + + + + + + + + + + + + + + + + + +

    参数

    +

    参数说明

    +

    取值范围

    +

    -i [interval]

    +

    设置oom线程任务检查的时间间隔。

    +

    100ms ~ 10000ms

    +

    -m [mem byte]

    +

    设置低内存阈值。

    +

    0MB ~ 1MB,0MB表示不做低内存阈值检查。

    +

    -r [mem byte]

    +

    设置pagecache内存回收阈值。

    +

    低内存阈值 ~ 系统可用最大内存。

    +

    -h | --help

    +

    使用帮助。

    +

    N/A

    +
    + +## 使用指南 + +- 参数缺省时,显示oom功能当前配置信息。 + +## 使用实例 + +当系统内存不足时,会打印出内存不足的提示信息。 + +## 输出说明 + +![](figure/zh-cn_image_0000001053710680.png) + +**表 2** 输出说明 + + + + + + + + + + + + + + + + + + + + + + +

    输出

    +

    说明

    +

    [oom] OS is in low memory state

    +

    total physical memory: 0x1bcf000(byte), used: 0x1b50000(byte), free: 0x7f000(byte), low memory threshold: 0x80000(byte)

    +

    操作系统处于低内存状态。

    +

    整个系统可用物理内存为0x1bcf000 byte,已经使用了 0x1b50000 byte, 还剩0x7f000 byte,当前设置的低内存阈值为0x80000 byte。

    +

    [oom] candidate victim process init pid: 1, actual phy mem byte: 82602

    +

    打印当前各个进程的内存使用情况,init进程实际使用82602byte,其中共享内存按照比例算的。

    +

    [oom] candidate victim process UserProcess12 pid: 12, actual phy mem byte: 25951558

    +

    UserProcess12进程实际使用25951558byte内存。

    +

    [oom] max phy mem used process UserProcess12 pid: 12, actual phy mem: 25951558

    +

    当前使用内存最多的进程是UserProcess12。

    +

    excFrom: User!

    +

    当系统处于低内存的情况下,UserProcess12进程再去申请内存时失败退出。

    +
    + diff --git a/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys-pmm.md b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys-pmm.md new file mode 100644 index 0000000000..067433a0b8 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys-pmm.md @@ -0,0 +1,91 @@ +# pmm + +- [命令功能](#section445335110416) +- [命令格式](#section1795712553416) +- [参数说明](#section92544592410) +- [使用指南](#section104151141252) +- [使用实例](#section11545171957) +- [输出说明](#section075617368542) + +## 命令功能 + +查看系统内存物理页及pagecache物理页使用情况。 + +## 命令格式 + +pmm + +## 参数说明 + +无 + +## 使用指南 + +Debug版本才具备的命令。 + +## 使用实例 + +输入pmm + +## 输出说明 + +**图 1** 查看物理页使用情况 +![](figure/查看物理页使用情况.png "查看物理页使用情况") + +**表 1** 输出说明 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    输出

    +

    说明

    +

    phys_seg

    +

    物理页控制块地址信息

    +

    base

    +

    第一个物理页地址,即物理页内存起始地址

    +

    size

    +

    物理页内存大小

    +

    free_pages

    +

    空闲物理页数量

    +

    active anon

    +

    pagecache中,活跃的匿名页数量

    +

    inactive anon

    +

    pagecache中,不活跃的匿名页数量

    +

    active file

    +

    pagecache中,活跃的文件页数量

    +

    inactive file

    +

    pagecache中,不活跃的文件页数量

    +

    pmm pages

    +

    total:总的物理页数,used:已使用的物理页数,free:空闲的物理页数

    +
    + diff --git a/zh-cn/device-dev/kernel/reset.md b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys-reset.md old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/kernel/reset.md rename to zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys-reset.md diff --git a/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys-sem.md b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys-sem.md new file mode 100644 index 0000000000..4a27c8d10b --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys-sem.md @@ -0,0 +1,91 @@ +# sem + +- [命令功能](#section366714216619) +- [命令格式](#section8833164614615) +- [参数说明](#section12809111019453) +- [使用指南](#section15935131220717) +- [使用实例](#section79281818476) +- [输出说明](#section1975118519456) + +## 命令功能 + +sem命令用于查询系统内核信号量相关信息。 + +## 命令格式 + +sem \[_ID__ / fulldata_\] + +## 参数说明 + +**表 1** 参数说明 + + + + + + + + + + + + + + + + +

    参数

    +

    参数说明

    +

    取值范围

    +

    ID

    +

    信号ID号。

    +

    [0, 0xFFFFFFFF]

    +

    fulldata

    +

    查询所有在用的信号量信息,打印信息包括如下:SemID, Count, Original Count, Creater TaskEntry, Last Access Time。

    +

    N/A

    +
    + +## 使用指南 + +- 参数缺省时,显示所有的信号量的使用数及信号量总数。 +- sem后加ID,显示对应ID信号量的使用数。 +- 参数fulldata依赖于LOSCFG\_DEBUG\_SEMAPHORE,使用时通过menuconfig在配置项中开启"Enable Semaphore Debugging": + + Debug ---\> Enable a Debug Version ---\> Enable Debug LiteOS Kernel Resource ---\> Enable Semaphore Debugging + + +## 使用实例 + +举例1:输入 sem fulldata + +## 输出说明 + +**图 1** 查询所有在用的信号量信息 +![](figure/查询所有在用的信号量信息.png "查询所有在用的信号量信息") + +**表 2** 输出说明 + + + + + + + + + + + + + +

    输出

    +

    说明

    +

    SemID

    +

    信号量ID。

    +

    Count

    +

    信号量使用数。

    +
    + +>![](../public_sys-resources/icon-note.gif) **说明:** +>● sem命令的ID参数输入形式以十进制形式表示或十六进制形式表示皆可。 +>● sem命令的ID参数在\[0, 1023\]范围内时,返回对应ID的信号量的状态(如果对应ID的信号量未被使用则进行提示);其他取值时返回参数错误的提示。 + diff --git a/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys-stack.md b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys-stack.md new file mode 100644 index 0000000000..8f2904a4b8 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys-stack.md @@ -0,0 +1,73 @@ +# stack + +- [命令功能](#section445335110416) +- [命令格式](#section1795712553416) +- [参数说明](#section92544592410) +- [使用指南](#section104151141252) +- [使用实例](#section11545171957) +- [输出说明](#section075617368542) + +## 命令功能 + +查看系统各堆栈使用情况。 + +## 命令格式 + +stack + +## 参数说明 + +无。 + +## 使用指南 + +无。 + +## 使用实例 + +输入:stack + +## 输出说明 + +**图 1** 系统堆栈使用情况 + + +![](figure/zh-cn_image_0000001054624363.png) + +**表 1** 输出说明 + + + + + + + + + + + + + + + + + + + + + + +

    输出

    +

    说明

    +

    stack name

    +

    系统堆栈名

    +

    cpu id

    +

    cpu 号

    +

    stack addr

    +

    栈地址

    +

    total size

    +

    堆栈大小

    +

    used size

    +

    堆栈实际使用大小

    +
    + diff --git a/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys-su.md b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys-su.md new file mode 100644 index 0000000000..a8536a0e4d --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys-su.md @@ -0,0 +1,62 @@ +# su + +- [命令功能](#section297810431676) +- [命令格式](#section157131147876) +- [参数说明](#section04145521671) +- [使用指南](#section14615155610719) +- [使用实例](#section13338150985) +- [输出说明](#section125021924194613) + +## 命令功能 + +su用于变更为其他使用者的身份。 + +## 命令格式 + +su \[_uid_\] \[_gid_\] + +## 参数说明 + +**表 1** 参数说明 + + + + + + + + + + + + + + + + +

    参数

    +

    参数说明

    +

    取值范围

    +

    uid

    +

    目标用户的用户id值。

    +
    • 为空。
    • [0,60000]
    +

    gid

    +

    目标用户的群组id值。

    +
    • 为空。
    • [0,60000]
    +
    + +## 使用指南 + +- su命令缺省切换到root用户,uid默认为0,gid为0。 +- 在su命令后的输入参数uid和gid就可以切换到该uid和gid的用户。 +- 输入参数超出范围时,会打印提醒输入正确范围参数。 + +## 使用实例 + +举例:su 1000 1000 + +## 输出说明 + +**图 1** **切换到**为uid为1000,gid为1000的用户 +![](figure/切换到为uid为1000-gid为1000的用户.png "切换到为uid为1000-gid为1000的用户") + diff --git a/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys-swymr.md b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys-swymr.md new file mode 100644 index 0000000000..07b2b1b042 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys-swymr.md @@ -0,0 +1,110 @@ +# swtmr + +- [命令功能](#section166171064814) +- [命令格式](#section424011111682) +- [参数说明](#section1268410459465) +- [使用指南](#section169806213815) +- [使用实例](#section16676026389) +- [输出说明](#section1541991614710) + +## 命令功能 + +swtmr命令用于查询系统软件定时器相关信息。 + +## 命令格式 + +swtmr \[_ID_\] + +## 参数说明 + +**表 1** 参数说明 + + + + + + + + + + + + +

    参数

    +

    参数说明

    +

    取值范围

    +

    ID

    +

    软件定时器ID号。

    +

    [0,0xFFFFFFFF]

    +
    + +## 使用指南 + +- 参数缺省时,默认显示所有软件定时器的相关信息。 +- swtmr后加ID号时,显示ID对应的软件定时器相关信息。 + +## 使用实例 + +举例:输入swtmr和swtmr 1 + +## 输出说明 + +**图 1** 查询所有软件定时器相关信息 +![](figure/查询所有软件定时器相关信息.png "查询所有软件定时器相关信息") + +**图 2** 查询对应 ID 的软件定时器信息 +![](figure/查询对应-ID-的软件定时器信息.png "查询对应-ID-的软件定时器信息") + +**表 2** 输出说明 + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    输出

    +

    说明

    +

    SwTmrID

    +

    软件定时器ID。

    +

    State

    +

    软件定时器状态。

    +

    状态可能为:"UnUsed", "Created", "Ticking"。

    +

    Mode

    +

    软件定时器模式。

    +

    模式可能为:"Once", "Period", "NSD(单次定时器,定时结束后不会自动删除)"。

    +

    Interval

    +

    软件定时器使用的Tick数。

    +

    Count

    +

    软件定时器已经工作的次数。

    +

    Arg

    +

    传入的参数。

    +

    handlerAddr

    +

    回调函数的地址。

    +
    + +>![](../public_sys-resources/icon-note.gif) **说明:** +>- swtmr命令的ID参数输入形式以十进制形式表示或十六进制形式表示皆可。 +>- swtmr命令的ID参数在\[0, 当前软件定时器个数 - 1\]范围内时,返回对应ID的软件定时器的状态;其他取值时返回错误提示。 + diff --git a/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys-sys.md b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys-sys.md new file mode 100644 index 0000000000..8b59757af0 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys-sys.md @@ -0,0 +1,91 @@ +# systeminfo + +- [命令功能](#section863016434820) +- [命令格式](#section139791817795) +- [参数说明](#section19472339164813) +- [使用指南](#section285522592) +- [使用实例](#section9471171015105) +- [输出说明](#section1657011114915) + +## 命令功能 + +systeminfo命令用于显示当前操作系统内资源使用情况,包括任务、信号量、互斥量、队列、定时器等。 + +## 命令格式 + +systeminfo + +## 参数说明 + +无。 + +## 使用指南 + +无。 + +## 使用实例 + +举例:输入systeminfo + +## 输出说明 + +**图 1** 查看系统资源使用情况 +![](figure/查看系统资源使用情况.png "查看系统资源使用情况") + +**表 1** 输出说明 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    输出

    +

    说明

    +

    Module

    +

    模块名称。

    +

    Used

    +

    当前使用量。

    +

    Total

    +

    最大可用量。

    +

    Enabled

    +

    模块是否开启。

    +

    Task

    +

    任务。

    +

    Sem

    +

    信号量。

    +

    Mutex

    +

    互斥量。

    +

    Queue

    +

    队列。

    +

    SwTmr

    +

    定时器。

    +
    + diff --git a/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys-task.md b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys-task.md new file mode 100644 index 0000000000..4fb2b3e3f8 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys-task.md @@ -0,0 +1,125 @@ +# task + +- [命令功能](#section0533181714106) +- [命令格式](#section1014412308101) +- [参数说明](#section116057158506) +- [使用指南](#section2053502951112) +- [使用实例](#section12629113381116) +- [输出说明](#section19299103465015) + +## 命令功能 + +task命令用于查询进程及线程信息。 + +## 命令格式 + +task/task -a + +## 参数说明 + +**表 1** 参数说明 + + + + + + + + + + + + +

    参数

    +

    参数说明

    +

    取值范围

    +

    -a

    +

    查看更多信息。

    +

    N/A

    +
    + +## 使用指南 + +- 参数缺省时默认打印部分任务信息。 + +## 使用实例 + +举例:输入task + +## 输出说明 + +**图 1** 查询任务部分信息 +![](figure/查询任务部分信息.png "查询任务部分信息") + +**表 2** 输出说明 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    输出

    +

    说明

    +

    PID

    +

    进程ID。

    +

    PPID

    +

    父进程ID。

    +

    PGID

    +

    进程组ID。

    +

    UID

    +

    用户ID。

    +

    Status

    +

    任务当前的状态。

    +

    CPUUSE10s

    +

    10秒内CPU使用率。

    +

    PName

    +

    进程名。

    +

    TID

    +

    任务ID。

    +

    StackSize

    +

    任务堆栈的大小。

    +

    WaterLine

    +

    栈使用的峰值。

    +

    MEMUSE

    +

    内存使用量。

    +

    TaskName

    +

    任务名。

    +
    + diff --git a/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys-uname.md b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys-uname.md new file mode 100644 index 0000000000..ff2c1b7a3d --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys-uname.md @@ -0,0 +1,72 @@ +# uname + +- [命令功能](#section107697383115) +- [命令格式](#section162824341116) +- [使用指南](#section2652124861114) +- [使用实例](#section0107995132) +- [输出说明](#section1215113245511) + +## 命令功能 + +uname命令用于显示当前操作系统的名称,版本创建时间,系统名称,版本信息等。 + +## 命令格式 + +uname \[_-a | -s | -t | -v | --help_\] + +**表 1** 参数说明 + + + + + + + + + + + + + + + + + + + + + + + + + +

    参数

    +

    参数说明

    +

    无参数

    +

    默认显示操作系统名称。

    +

    -a

    +

    显示全部信息。

    +

    -t

    +

    显示版本创建的时间。

    +

    -s

    +

    显示操作系统名称。

    +

    -v

    +

    显示版本信息。

    +

    --help

    +

    显示uname指令格式提示。

    +
    + +## 使用指南 + +uname用于显示当前操作系统名称。语法uname -a | -t| -s| -v 描述uname 命令将正在使用的操作系统名写到标准输出中,这几个参数不能混合使用。 + +## 使用实例 + +举例:输入uname -a + +## 输出说明 + +查看系统信息 + +![](figure/zh-cn_image_0000001052370305.png) + diff --git a/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys-vmm.md b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys-vmm.md new file mode 100644 index 0000000000..35f4ada41e --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys-vmm.md @@ -0,0 +1,158 @@ +# vmm + +- [命令功能](#section445335110416) +- [命令格式](#section1795712553416) +- [参数说明](#section92544592410) +- [使用指南](#section104151141252) +- [使用实例](#section11545171957) +- [输出说明](#section075617368542) + +## 命令功能 + +查看进程的虚拟内存使用情况。 + +## 命令格式 + +vmm \[_-a / -h / --help_\] + +vmm \[_pid_\] + +## 参数说明 + +**表 1** 参数说明 + + + + + + + + + + + + + + + + + + + + +

    参数

    +

    参数说明

    +

    取值范围

    +

    -a

    +

    输出所有进程的虚拟内存使用情况

    +

    N/A

    +

    -h | --help

    +

    命令格式说明

    +

    N/A

    +

    pid

    +

    进程ID,说明指定进程的虚拟内存使用情况

    +

    [0,63]

    +
    + +## 使用指南 + +命令缺省输出所有进程的虚拟内存使用情况。 + +## 使用实例 + +输入vmm 3 + +## 输出说明 + +**图 1** PID为3的进程虚拟内存使用信息 +![](figure/PID为3的进程虚拟内存使用信息.png "PID为3的进程虚拟内存使用信息") + +**表 2** 进程基本信息 + + + + + + + + + + + + + + + + + + + + + + + + + +

    输出

    +

    说明

    +

    PID

    +

    进程ID

    +

    aspace

    +

    进程虚拟内存控制块地址信息

    +

    name

    +

    进程名

    +

    base

    +

    虚拟内存起始地址

    +

    size

    +

    虚拟内存大小

    +

    pages

    +

    已使用的物理页数量

    +
    + +**表 3** 虚拟内存区间信息 + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    输出

    +

    说明

    +

    region

    +

    虚拟区间控制块地址信息

    +

    name

    +

    虚拟区间类型

    +

    base

    +

    虚拟区间起始地址

    +

    size

    +

    虚拟区间大小

    +

    mmu_flags

    +

    虚拟区间mmu映射属性

    +

    pages

    +

    已使用的物理页数量(包括共享内存部分)

    +

    pg/ref

    +

    已使用的物理页数量

    +
    + diff --git a/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys-watch.md b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys-watch.md new file mode 100644 index 0000000000..c3adf787bb --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys-watch.md @@ -0,0 +1,100 @@ +# watch + +- [命令功能](#section20643141481314) +- [命令格式](#section1075441721316) +- [参数说明](#section1472810220135) +- [使用指南](#section186772414131) +- [使用实例](#section4764192791314) +- [输出说明](#section5791253155517) + +## 命令功能 + +watch命令用于周期性的监视一个命令的运行结果。 + +## 命令格式 + +watch + +watch \[_-c/-n/-t/--count/--interval/-no-title/--over_\] \[_command_\] + +## 参数说明 + +**表 1** 参数说明 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    参数

    +

    参数说明

    +

    缺省值

    +

    取值范围

    +

    -c / --count

    +

    命令执行的总次数。

    +

    0xFFFFFF

    +

    (0,0xFFFFFF]

    +

    -n / --interval

    +

    命令周期性执行的时间间隔(s)。

    +

    1s

    +

    (0,0xFFFFFF]

    +

    -t / -no-title

    +

    关闭顶端的时间显示。

    +

    N/A

    +

    N/A

    +

    command

    +

    需要监测的命令。

    +

    N/A

    +

    N/A

    +

    --over

    +

    关闭当前监测指令。

    +

    N/A

    +

    N/A

    +
    + +## 使用指南 + +watch运行过程中可以执行**watch --over**结束本次watch命令。 + +## 使用实例 + +输入举例: + +watch -n 2 -c 6 task + +## 输出说明 + +**图 1** watch task 结果 +![](figure/watch-task-结果.png "watch-task-结果") + +>![](../public_sys-resources/icon-note.gif) **说明:** +>示例中,总共有6次task命令打印,每次间隔2秒,截图为最后一次打印详情。 + diff --git a/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys.md b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys.md new file mode 100644 index 0000000000..8bccc06e16 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys.md @@ -0,0 +1,47 @@ +# 系统命令 + +- **[cpup](kernel-lite-small-shell-cmd-sys-cpup.md)** + +- **[date](kernel-lite-small-shell-cmd-sys-date.md)** + +- **[dmesg](kernel-lite-small-shell-cmd-sys-demsg.md)** + +- **[exec](kernel-lite-small-shell-cmd-sys-exec.md)** + +- **[free](kernel-lite-small-shell-cmd-sys-free.md)** + +- **[help](kernel-lite-small-shell-cmd-sys-help.md)** + +- **[hwi](kernel-lite-small-shell-cmd-sys-hwi.md)** + +- **[kill](kernel-lite-small-shell-cmd-sys-kill.md)** + +- **[log](kernel-lite-small-shell-cmd-sys-log.md)** + +- **[memcheck](kernel-lite-small-shell-cmd-sys-mem.md)** + +- **[oom](kernel-lite-small-shell-cmd-sys-oom.md)** + +- **[pmm](kernel-lite-small-shell-cmd-sys-pmm.md)** + +- **[reset](kernel-lite-small-shell-cmd-sys-reset.md)** + +- **[sem](kernel-lite-small-shell-cmd-sys-sem.md)** + +- **[stack](kernel-lite-small-shell-cmd-sys-stack.md)** + +- **[su](kernel-lite-small-shell-cmd-sys-su.md)** + +- **[swtmr](kernel-lite-small-shell-cmd-sys-swymr.md)** + +- **[systeminfo](kernel-lite-small-shell-cmd-sys-sys.md)** + +- **[task](kernel-lite-small-shell-cmd-sys-task.md)** + +- **[uname](kernel-lite-small-shell-cmd-sys-uname.md)** + +- **[vmm](kernel-lite-small-shell-cmd-sys-vmm.md)** + +- **[watch](kernel-lite-small-shell-cmd-sys-watch.md)** + + diff --git a/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd.md b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd.md new file mode 100644 index 0000000000..95d4b92cff --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd.md @@ -0,0 +1,13 @@ +# Shell命令使用详解 + +本章节介绍了系统关键命令的功能、格式、参数范围、使用指南和使用实例。 + +不在本文档范围内的命令,详见[help](kernel-lite-small-shell-cmd-sys-help.md)命令的输出内容,也可以通过命令的“-h | --help”选项,查看该命令的使用帮助。 + +- **[系统命令](kernel-lite-small-shell-cmd-sys.md)** + +- **[文件命令](kernel-lite-small-shell-cmd-file.md)** + +- **[网络命令](kernel-lite-small-shell-cmd-net.md)** + + diff --git a/zh-cn/device-dev/kernel/kernel-lite-small-shell-des.md b/zh-cn/device-dev/kernel/kernel-lite-small-shell-des.md new file mode 100644 index 0000000000..8b7909db20 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-small-shell-des.md @@ -0,0 +1,36 @@ +# Shell介绍 + +- [注意事项](#section12298165312328) + +OpenHarmony内核提供的Shell支持调试常用的基本功能,包含系统、文件、网络和动态加载相关命令。同时OpenHarmony内核的Shell支持添加新的命令,可以根据需求来进行定制。 + +- 系统相关命令:提供查询系统任务、内核信号量、系统软件定时器、CPU占用率、当前中断等相关信息的能力。 + +- 文件相关命令:支持基本的ls、cd等功能。 + +- 网络相关命令:支持查询接到开发板的其他设备的IP、查询本机IP、测试网络连接、设置开发板的AP和station模式等相关功能。 + + 新增命令的详细流程可参见[开发指导](kernel-lite-small-shell-guide.md)和[编程实例](kernel-lite-small-shell-sample.md)。 + + +## 注意事项 + +在使用Shell功能的过程中,需要注意以下几点: + +- Shell功能支持使用exec命令来运行可执行文件。 +- Shell功能支持默认模式下英文输入。如果出现用户在UTF-8格式下输入了中文字符的情况,只能通过回退三次来删除。 + +- Shell功能支持shell命令、文件名及目录名的Tab键联想补全。若有多个匹配项,则根据共同字符, 打印多个匹配项。对于过多的匹配项(打印多于24行),将会进行打印询问(Display all num possibilities?(y/n)),用户可输入y选择全部打印,或输入n退出打印,选择全部打印并打印超过24行后,会进行--More--提示,此时按回车键继续打印,按q键退出(支持Ctrl+c退出\)。 + +- Shell端工作目录与系统工作目录是分开的,即通过Shell端cd pwd等命令是对Shell端工作目录进行操作,通过chdir getcwd等命令是对系统工作目录进行操作,两个工作目录相互之间没有联系。当文件系统操作命令入参是相对路径时要格外注意。 + +- 在使用网络Shell指令前,需要先调用tcpip\_init函数完成网络初始化并完成telnet连接后才能起作用,内核默认不初始化tcpip\_init。 + +- 不建议使用Shell命令对/dev目录下的设备文件进行操作,这可能会引起不可预知的结果。 + +- Shell功能不符合POSIX标准,仅供调试使用。 + + >![](../public_sys-resources/icon-notice.gif) **须知:** + >Shell功能仅供调试使用,在Debug版本中开启(使用时通过menuconfig在配置项中开启"LOSCFG\_DEBUG\_VERSION"编译开关进行相关控制),商用产品中禁止包含该功能。 + + diff --git a/zh-cn/device-dev/kernel/kernel-lite-small-shell-guide.md b/zh-cn/device-dev/kernel/kernel-lite-small-shell-guide.md new file mode 100644 index 0000000000..7f7327f6b2 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-small-shell-guide.md @@ -0,0 +1,167 @@ +# Shell命令开发指导 + +- [开发指导](#section22071515161018) + +## 开发指导 + +新增Shell命令的典型开发流程如下: + +1. 包含如下头文件: + + ``` + #include "shell.h" + #include "shcmd.h" + ``` + +2. 注册命令。用户可以选择静态注册命令方式和系统运行时动态注册命令方式,静态注册命令方式一般用在系统常用命令注册,动态注册命令方式一般用在用户命令注册。 + + 1. 静态注册命令方式: + + 1. 通过宏的方式注册。 + + 这个宏的原型为: + + ``` + SHELLCMD_ENTRY(l, cmdType, cmdKey, paraNum, cmdHook) + ``` + + **表 1** SHELLCMD\_ENTRY参数详解 + + + + + + + + + + + + + + + + + + + + + + +

    参数

    +

    描述

    +

    l

    +

    静态注册全局变量名(注意:不与系统中其他symbol重名)。

    +

    cmdType

    +

    命令类型:

    +
    • CMD_TYPE_EX:不支持标准命令参数输入,会把用户填写的命令关键字屏蔽掉,例如:输入ls /ramfs,传入给注册函数的参数只有/ramfs,而ls命令关键字并不会被传入。

      +
    • CMD_TYPE_STD:支持的标准命令参数输入,所有输入的字符都会通过命令解析后被传入。

      +
    +

    cmdKey

    +

    命令关键字,函数在Shell中访问的名称。

    +

    paraNum

    +

    调用的执行函数的入参最大个数,暂不支持。

    +

    cmdHook

    +

    命令执行函数地址,即命令实际执行函数。

    +
    + + 如: + + ``` + SHELLCMD_ENTRY(ls_shellcmd, CMD_TYPE_EX, "ls", XARGS, (CMD_CBK_FUNC)osShellCmdLs) + ``` + + 2. 在build/mk/liteos\_tables\_ldflags.mk中添加相应选项: + + 如:上述“ls”命令注册时,需在build/mk/liteos\_tables\_ldflags.mk中添加“-uls\_shellcmd”。其中-u后面跟SHELLCMD\_ENTRY的第一个参数。 + + + 2. 动态注册命令方式: + + 注册函数原型: + + ``` + UINT32 osCmdReg(CmdT ype cmdType, CHAR *cmdKey, UINT32 paraNum, CmdCallBackFunc cmdProc) + ``` + + **表 2** UINT32 osCmdReg参数详解 + + + + + + + + + + + + + + + + + + + +

    参数

    +

    描述

    +

    cmdType

    +

    命令类型:

    +
    • CMD_TYPE_EX:不支持标准命令参数输入,会把用户填写的命令关键字屏蔽掉,例如:输入ls /ramfs,传入给注册函数的参数只有/ramfs,而ls命令关键字并不会被传入。

      +
    • CMD_TYPE_STD:支持的标准命令参数输入,所有输入的字符都会通过命令解析后被传入。

      +
    +

    cmdKey

    +

    命令关键字,函数在Shell中访问的名称。

    +

    paraNum

    +

    调用的执行函数的入参最大个数,暂不支持该参数;当前为默认值XARGS(0xFFFFFFFF)。

    +

    cmdHook

    +

    命令执行函数地址,即命令实际执行函数。

    +
    + + 如: + + ``` + osCmdReg(CMD_TYPE_EX, "ls", XARGS, (CMD_CBK_FUNC)osShellCmdLs) + ``` + + + >![](../public_sys-resources/icon-note.gif) **说明:** + >命令关键字必须是唯一的,也即两个不同的命令项不能拥有相同的命令关键字,否则只会执行其中一个。 + >Shell在执行用户命令时,如果存在多个命令关键字相同的命令,只会执行其中在"help"命令中排序在最前面的一个。 + +3. 添加内置命令函数原型。 + + ``` + UINT32 osShellCmdLs(UINT32 argc, CHAR **argv) + ``` + + **表 3** osShellCmdLs参数说明 + + + + + + + + + + + + + +

    参数

    +

    参数描述

    +

    argc

    +

    Shell命令中,参数个数。

    +

    argv

    +

    为指针数组,每个元素指向一个字符串,可以根据选择命令类型,决定是否要把命令关键字传入给注册函数。

    +
    + +4. 输入Shell命令,有两种输入方式: + - 在串口工具中直接输入Shell命令。 + + - 在telnet工具中输入Shell命令(telnet使用方式详见[telnet](kernel-lite-small-shell-cmd-net-tel.md))。 + + + diff --git "a/zh-cn/device-dev/kernel/Shell\345\221\275\344\273\244\347\274\226\347\250\213\345\256\236\344\276\213.md" b/zh-cn/device-dev/kernel/kernel-lite-small-shell-sample.md old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/kernel/Shell\345\221\275\344\273\244\347\274\226\347\250\213\345\256\236\344\276\213.md" rename to zh-cn/device-dev/kernel/kernel-lite-small-shell-sample.md diff --git a/zh-cn/device-dev/kernel/kernel-lite-small-shell.md b/zh-cn/device-dev/kernel/kernel-lite-small-shell.md new file mode 100644 index 0000000000..edc56c8c73 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-small-shell.md @@ -0,0 +1,15 @@ +# 调测 + +- **[Shell介绍](kernel-lite-small-shell-des.md)** + +- **[Shell命令开发指导](kernel-lite-small-shell-guide.md)** + +- **[Shell命令编程实例](kernel-lite-small-shell-sample.md)** + +- **[Shell命令使用详解](kernel-lite-small-shell-cmd.md)** + +- **[魔法键使用方法](kernel-lite-small-shell-cmd-mag.md)** + +- **[用户态异常信息说明](kernel-lite-small-shell-cmd-abn.md)** + + diff --git a/zh-cn/device-dev/kernel/kernel-lite-small-thread.md b/zh-cn/device-dev/kernel/kernel-lite-small-thread.md new file mode 100644 index 0000000000..b758c77877 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-small-thread.md @@ -0,0 +1,702 @@ +# 线程 + +- [基本概念](#section1179311337405) +- [使用场景](#section44877547404) +- [接口说明](#section2069477134115) + +## 基本概念 + +从系统的角度看,线程是竞争系统资源的最小运行单元。线程可以使用或等待CPU、使用内存空间等系统资源,并独立于其它线程运行。 + +OpenHarmony内核每个进程内的线程独立运行、独立调度,当前进程内线程的调度不受其它进程内线程的影响。 + +OpenHarmony内核中的线程采用抢占式调度机制,同时支持时间片轮转调度和FIFO调度方式。 + +OpenHarmony内核的线程一共有32个优先级\(0-31\),最高优先级为0,最低优先级为31。 + +当前进程内高优先级的线程可抢占当前进程内低优先级线程,当前进程内低优先级线程必须在当前进程内高优先级线程阻塞或结束后才能得到调度。 + +**线程状态说明:** + +- 初始化(Init):该线程正在被创建。 + +- 就绪(Ready):该线程在就绪列表中,等待CPU调度。 + +- 运行(Running):该线程正在运行。 + +- 阻塞(Blocked):该线程被阻塞挂起。Blocked状态包括:pending\(因为锁、事件、信号量等阻塞\)、suspended(主动pend)、delay\(延时阻塞\)、pendtime\(因为锁、事件、信号量时间等超时等待\)。 + +- 退出(Exit):该线程运行结束,等待父线程回收其控制块资源。 + + +**图 1** 线程状态迁移示意图 +![](figure/线程状态迁移示意图.png "线程状态迁移示意图") + +**线程状态迁移说明:** + +- Init→Ready: + + 线程创建拿到控制块后为Init状态,处于线程初始化阶段,当线程初始化完成将线程插入调度队列,此时线程进入就绪状态。 + +- Ready→Running: + + 线程创建后进入就绪态,发生线程切换时,就绪列表中最高优先级的线程被执行,从而进入运行态,但此刻该线程会从就绪列表中删除。 + +- Running→Blocked: + + 正在运行的线程发生阻塞(挂起、延时、读信号量等)时,线程状态由运行态变成阻塞态,然后发生线程切换,运行就绪列表中剩余最高优先级线程。 + +- Blocked→Ready : + + 阻塞的线程被恢复后(线程恢复、延时时间超时、读信号量超时或读到信号量等),此时被恢复的线程会被加入就绪列表,从而由阻塞态变成就绪态。 + +- Ready→Blocked: + + 线程也有可能在就绪态时被阻塞(挂起),此时线程状态会由就绪态转变为阻塞态,该线程从就绪列表中删除,不会参与线程调度,直到该线程被恢复。 + +- Running→Ready: + + 有更高优先级线程创建或者恢复后,会发生线程调度,此刻就绪列表中最高优先级线程变为运行态,那么原先运行的线程由运行态变为就绪态,并加入就绪列表中。 + +- Running→Exit: + + 运行中的线程运行结束,线程状态由运行态变为退出态。若未设置分离属性(PTHREAD\_CREATE\_DETACHED)的线程,运行结束后对外呈现的是Exit状态,即退出态。 + + +## 使用场景 + +线程创建后,用户态可以执行线程调度、挂起、恢复、延时等操作,同时也可以设置线程优先级和调度策略,获取线程优先级和调度策略。 + +## 接口说明 + +OpenHarmony内核系统中的线程管理模块,线程间通信为用户提供下面几种功能: + +**表 1** 线程管理模块功能 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    头文件

    +

    名称

    +

    说明

    +

    备注

    +

    pthread.h

    +

    pthread_attr_destroy

    +

    销毁线程属性对象。

    +

    -

    +

    pthread.h

    +

    pthread_attr_getinheritsched

    +

    获取线程属性对象的调度属性。

    +

    -

    +

    pthread.h

    +

    pthread_attr_getschedparam

    +

    获取线程属性对象的调度参数属性。

    +

    -

    +

    pthread.h

    +

    pthread_attr_getschedpolicy

    +

    获取线程属性对象的调度策略属性。

    +

    OpenHarmony:支持SCHED_FIFO 、SCHED_RR调度策略。

    +

    pthread.h

    +

    pthread_attr_getstacksize

    +

    获取线程属性对象的堆栈大小。

    +

    -

    +

    pthread.h

    +

    pthread_attr_init

    +

    初始化线程属性对象。

    +

    -

    +

    pthread.h

    +

    pthread_attr_setdetachstate

    +

    设置线程属性对象的分离状态。

    +

    -

    +

    pthread.h

    +

    pthread_attr_setinheritsched

    +

    设置线程属性对象的继承调度属性。

    +

    -

    +

    pthread.h

    +

    pthread_attr_setschedparam

    +

    设置线程属性对象的调度参数属性。

    +

    OpenHarmony:设置线程优先级的参数值越小,线程在系统中的优先级越高;设置参数值越大,优先级越低。

    +

    注意:需要将pthread_attr_t线程属性的inheritsched字段设置为PTHREAD_EXPLICIT_SCHED,否则设置的线程调度优先级将不会生效,系统默认设置为PTHREAD_INHERIT_SCHED。

    +

    pthread.h

    +

    pthread_attr_setschedpolicy

    +

    设置线程属性对象的调度策略属性。

    +

    OpenHarmony:支持SCHED_FIFO 、SCHED_RR调度策略。

    +

    pthread.h

    +

    pthread_attr_setstacksize

    +

    设置线程属性对象的堆栈大小。

    +

    -

    +

    pthread.h

    +

    pthread_getattr_np

    +

    获取已创建线程的属性。

    +

    -

    +

    pthread.h

    +

    pthread_cancel

    +

    向线程发送取消请求。

    +

    -

    +

    pthread.h

    +

    pthread_testcancel

    +

    请求交付任何未决的取请求。

    +

    -

    +

    pthread.h

    +

    pthread_setcanceltype

    +

    设置线程可取消类型。

    +

    -

    +

    pthread.h

    +

    pthread_setcancelstate

    +

    设置线程可取消状态。

    +

    -

    +

    pthread.h

    +

    pthread_create

    +

    创建一个新的线程。

    +

    -

    +

    pthread.h

    +

    pthread_detach

    +

    分离一个线程。

    +

    -

    +

    pthread.h

    +

    pthread_equal

    +

    比较两个线程ID是否相等。

    +

    -

    +

    pthread.h

    +

    pthread_exit

    +

    终止正在调用的线程。

    +

    -

    +

    pthread.h

    +

    pthread_getschedparam

    +

    获取线程的调度策略和参数。

    +

    OpenHarmony:支持SCHED_FIFO 、SCHED_RR调度策略。

    +

    pthread.h

    +

    pthread_join

    +

    等待指定的线程结束。

    +

    -

    +

    pthread.h

    +

    pthread_self

    +

    获取当前线程的ID。

    +

    -

    +

    pthread.h

    +

    pthread_setschedprio

    +

    设置线程的调度静态优先级。

    +

    -

    +

    pthread.h

    +

    pthread_kill

    +

    向线程发送信号。

    +

    -

    +

    pthread.h

    +

    pthread_once

    +

    使函数调用只能执行一次。

    +

    -

    +

    pthread.h

    +

    pthread_atfork

    +

    注册fork的处理程序。

    +

    -

    +

    pthread.h

    +

    pthread_cleanup_pop

    +

    删除位于清理处理程序堆栈顶部的例程。

    +

    -

    +

    pthread.h

    +

    pthread_cleanup_push

    +

    将例程推送到清理处理程序堆栈的顶部。

    +

    -

    +

    pthread.h

    +

    pthread_barrier_destroy

    +

    销毁屏障对象(高级实时线程)

    +

    -

    +

    pthread.h

    +

    pthread_barrier_init

    +

    初始化屏障对象(高级实时线程)

    +

    -

    +

    pthread.h

    +

    pthread_barrier_wait

    +

    屏障同步(高级实时线程)

    +

    -

    +

    pthread.h

    +

    pthread_barrierattr_destroy

    +

    销毁屏障属性对象。

    +

    -

    +

    pthread.h

    +

    pthread_barrierattr_init

    +

    初始化屏障属性对象。

    +

    -

    +

    pthread.h

    +

    pthread_mutex_destroy

    +

    销毁互斥锁。

    +

    -

    +

    pthread.h

    +

    pthread_mutex_init

    +

    初始化互斥锁。

    +

    -

    +

    pthread.h

    +

    pthread_mutex_lock

    +

    互斥锁加锁操作。

    +

    -

    +

    pthread.h

    +

    pthread_mutex_trylock

    +

    互斥锁尝试加锁操作。

    +

    -

    +

    pthread.h

    +

    pthread_mutex_unlock

    +

    互斥锁解锁操作。

    +

    -

    +

    pthread.h

    +

    pthread_mutexattr_destroy

    +

    销毁互斥锁属性对象。

    +

    -

    +

    pthread.h

    +

    pthread_mutexattr_gettype

    +

    获取互斥锁类型属性。

    +

    -

    +

    pthread.h

    +

    pthread_mutexattr_init

    +

    初始化互斥锁属性对象。

    +

    -

    +

    pthread.h

    +

    pthread_mutexattr_settype

    +

    设置互斥锁类型属性。

    +

    -

    +

    pthread.h

    +

    pthread_mutex_timedlock

    +

    使用超时锁定互斥锁。

    +

    -

    +

    pthread.h

    +

    pthread_rwlock_destroy

    +

    销毁读写锁。

    +

    -

    +

    pthread.h

    +

    pthread_rwlock_init

    +

    初始化读写锁。

    +

    -

    +

    pthread.h

    +

    pthread_rwlock_rdlock

    +

    获取读写锁读锁操作。

    +

    -

    +

    pthread.h

    +

    pthread_rwlock_timedrdlock

    +

    使用超时锁定读写锁读锁。

    +

    -

    +

    pthread.h

    +

    pthread_rwlock_timedwrlock

    +

    使用超时锁定读写锁写锁。

    +

    -

    +

    pthread.h

    +

    pthread_rwlock_tryrdlock

    +

    尝试获取读写锁读锁操作。

    +

    -

    +

    pthread.h

    +

    pthread_rwlock_trywrlock

    +

    尝试获取读写锁写锁操作。

    +

    -

    +

    pthread.h

    +

    pthread_rwlock_unlock

    +

    读写锁解锁操作。

    +

    -

    +

    pthread.h

    +

    pthread_rwlock_wrlock

    +

    获取读写锁写锁操作。

    +

    -

    +

    pthread.h

    +

    pthread_rwlockattr_destroy

    +

    销毁读写锁属性对象。

    +

    -

    +

    pthread.h

    +

    pthread_rwlockattr_init

    +

    初始化读写锁属性对象。

    +

    -

    +

    pthread.h

    +

    pthread_cond_broadcast

    +

    解除若干已被等待条件阻塞的线程。

    +

    -

    +

    pthread.h

    +

    pthread_cond_destroy

    +

    销毁条件变量。

    +

    -

    +

    pthread.h

    +

    pthread_cond_init

    +

    初始化条件变量。

    +

    -

    +

    pthread.h

    +

    pthread_cond_signal

    +

    解除被阻塞的线程。

    +

    -

    +

    pthread.h

    +

    pthread_cond_timedwait

    +

    定时等待条件。

    +

    -

    +

    pthread.h

    +

    pthread_cond_wait

    +

    等待条件。

    +

    -

    +

    semaphore.h

    +

    sem_destroy

    +

    销毁指定的无名信号量。

    +

    -

    +

    semaphore.h

    +

    sem_getvalue

    +

    获得指定信号量计数值。

    +

    -

    +

    semaphore.h

    +

    sem_init

    +

    创建并初始化一个无名信号量。

    +

    -

    +

    semaphore.h

    +

    sem_post

    +

    增加信号量计数。

    +

    -

    +

    semaphore.h

    +

    sem_timedwait

    +

    获取信号量,且有超时返回功能。

    +

    -

    +

    semaphore.h

    +

    sem_trywait

    +

    尝试获取信号量。

    +

    -

    +

    semaphore.h

    +

    sem_wait

    +

    获取信号量。

    +

    -

    +
    + diff --git a/zh-cn/device-dev/kernel/kernel-lite-small.md b/zh-cn/device-dev/kernel/kernel-lite-small.md new file mode 100644 index 0000000000..a435da97d4 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-small.md @@ -0,0 +1,11 @@ +# 小型系统内核 + +- **[基础内核](kernel-lite-small-basic.md)** + +- **[文件系统](kernel-lite-small-file.md)** + +- **[标准库](kernel-lite-small-lib.md)** + +- **[调测](kernel-lite-small-shell.md)** + + diff --git a/zh-cn/device-dev/kernel/kernel-lite.md b/zh-cn/device-dev/kernel/kernel-lite.md new file mode 100644 index 0000000000..f6fcf22c8e --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite.md @@ -0,0 +1,7 @@ +# 轻量和小型系统内核 + +- **[轻量系统内核](kernel-lite-mini.md)** + +- **[小型系统内核](kernel-lite-small.md)** + + diff --git a/zh-cn/device-dev/kernel/kernel-standard-build.md b/zh-cn/device-dev/kernel/kernel-standard-build.md new file mode 100644 index 0000000000..1b52ac7b1f --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-standard-build.md @@ -0,0 +1,47 @@ +# Linux内核编译与构建指导 + +- [开发示例1](#section19369206113115) + - [场景1:版本级编译原生方式](#section1025111193220) + - [场景2:单独编译修改后的内核](#section17446652173211) + + +## 开发示例1 + +以hi3516dv300开源开发板+ubuntu x86主机开发环境为例。 + +### 场景1:版本级编译原生方式 + +使用工程的全量编译命令,编译生成uImage内核镜像 + +``` +./build.sh --product-name Hi3516DV300 # 编译hi3516dv300的uImage内核镜像 +``` + +### 场景2:单独编译修改后的内核 + +1. 准备工作 + + 1. 按[开发板Patch使用指导](kernel-standard-patch.md)打入所需补丁。 + 2. 准备编译环境,可以使用开源arm clang/gcc编译器。 + + 进入工程主目录配置环境变量: + + ``` + export PATH=`pwd`/prebuilts/clang/host/linux-x86/clang-r353983c/bin:`pwd`/prebuilts/gcc/linux-x86/arm/gcc-linaro-7.5.0-arm-linux-gnueabi/bin/:$PATH # 配置编译环境 + MAKE_OPTIONES="ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- CC=clang HOSTCC=clang" # 使用工程项目自带的clang环境 + ``` + +2. 修改内核代码或内核config (OpenHarmony提供对应平台的defconfig供参考)。 +3. 创建编译目录及生成内核.config。 + + ``` + make ${MAKE_OPTIONES} hi3516dv300_emmc_smp_hos_l2_defconfig # 使用自带的默认config 构建内核 + ``` + +4. 编译生成对应的内核Image。 + + ``` + make ${MAKE_OPTIONES} -j32 uImage # 编译uImage内核镜像 + ``` + + diff --git "a/zh-cn/device-dev/kernel/Linux\345\206\205\346\240\270\346\246\202\350\277\260.md" b/zh-cn/device-dev/kernel/kernel-standard-des.md old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/kernel/Linux\345\206\205\346\240\270\346\246\202\350\277\260.md" rename to zh-cn/device-dev/kernel/kernel-standard-des.md diff --git a/zh-cn/device-dev/kernel/kernel-standard-patch.md b/zh-cn/device-dev/kernel/kernel-standard-patch.md new file mode 100644 index 0000000000..87b3fea376 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-standard-patch.md @@ -0,0 +1,17 @@ +# OpenHarmony开发板Patch使用指导 + +Patch文件位于工程项目源码路径:kernel/linux/patches/linux-4.19,存放特定芯片架构驱动补丁。 + +如需使用特定芯片平台驱动的Patch,需要在内核仓代码完成对芯片平台驱动补丁合入。 + +合入芯片平台驱动补丁,针对不同芯片平台合入对应的patch: + +以Hi3516dv300为例: + +``` +patch -p1 < device/hisilicon/hi3516dv300/sdk_linux/open_source/linux/hisi_linux-4.19_hos_l2.patch +``` + +>![](../public_sys-resources/icon-notice.gif) **须知:** +>由于OpenHarmony的编译构建流程中会拷贝kernel/linux-4.19的代码环境后进行打补丁动作,在使用OpenHarmony的版本级编译命令前,需要kernel/linux-4.19保持原代码环境。 + diff --git a/zh-cn/device-dev/kernel/kernel-standard.md b/zh-cn/device-dev/kernel/kernel-standard.md new file mode 100644 index 0000000000..67af7b81d0 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-standard.md @@ -0,0 +1,9 @@ +# 标准系统内核 + +- **[Linux内核概述](kernel-standard-des.md)** + +- **[OpenHarmony开发板Patch使用指导](kernel-standard-patch.md)** + +- **[Linux内核编译与构建指导](kernel-standard-build.md)** + + diff --git a/zh-cn/device-dev/kernel/kernel.md b/zh-cn/device-dev/kernel/kernel.md new file mode 100644 index 0000000000..05e683e74b --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel.md @@ -0,0 +1,7 @@ +# 内核 + +- **[轻量和小型系统内核](kernel-lite.md)** + +- **[标准系统内核](kernel-standard.md)** + + diff --git a/zh-cn/device-dev/kernel/kill.md b/zh-cn/device-dev/kernel/kill.md deleted file mode 100755 index c88e6abc63..0000000000 --- a/zh-cn/device-dev/kernel/kill.md +++ /dev/null @@ -1,82 +0,0 @@ -# kill - -- [命令功能](#section366714216619) -- [命令格式](#section8833164614615) -- [参数说明](#section12809111019453) -- [使用指南](#section15935131220717) -- [使用实例](#section79281818476) -- [输出说明](#section12742311179) - -## 命令功能 - -命令用于发送特定信号给指定进程。 - -## 命令格式 - -kill \[_signo_ | _-signo_\] \[_pid_\] - -## 参数说明 - -**表 1** 参数说明 - - - - - - - - - - - - - - - - -

    参数

    -

    参数说明

    -

    取值范围

    -

    signo

    -

    信号ID。

    -

    [1,30]

    -

    pid

    -

    进程ID。

    -

    [1,MAX_INT]

    -
    - ->![](public_sys-resources/icon-notice.gif) **须知:** ->signo有效范围为\[0,64\],建议取值范围为\[1,30\],其余为保留内容。 - -## 使用指南 - -必须指定发送的信号编号及进程号。 - -进程编号取值范围根据系统配置变化,例如系统最大支持pid为256,则取值范围缩小为\[1-256\]。 - -## 使用实例 - -1. 查看当前进程列表,查看需要杀死的进程PID(7)。 - -**图 1** 查看进程PID -![](figures/查看进程PID.png "查看进程PID") - -2. 发送信号14(SIGALRM默认行为为进程终止)给7号进程**helloworld\_d**(用户态进程):**kill 14 7**(kill -14 7效果相同),并查看当前进程列表,7号进程已终止。 - -**图 2** 信号发送结果图 -![](figures/信号发送结果图.png "信号发送结果图") - -## 输出说明 - -发送成功或失败输出结果如下。 - -**图 3** 发送信号给指定进程 -![](figures/发送信号给指定进程.png "发送信号给指定进程") - -信号发送会显示发送记录,未报错表示信号发送成功。 - -**图 4** 信号发送失败 -![](figures/信号发送失败.png "信号发送失败") - -信号发送失败,上图所示原因为信号发送命令参数无效,请排查信号编号及进程编号是否无效。 - diff --git a/zh-cn/device-dev/kernel/log.md b/zh-cn/device-dev/kernel/log.md deleted file mode 100755 index d6972d5551..0000000000 --- a/zh-cn/device-dev/kernel/log.md +++ /dev/null @@ -1,74 +0,0 @@ -# log - -- [命令功能](#section128219131856) -- [命令格式](#section3894181710519) -- [参数说明](#section7693122310515) -- [使用指南](#section1982111281512) -- [使用实例](#section176301333259) -- [输出说明](#section14354765415) - -## 命令功能 - -log命令用于修改&查询日志配置。 - -## 命令格式 - -log level \[_levelNum_\] - -## 参数说明 - -**表 1** 参数说明 - - - - - - - - - - - - -

    参数

    -

    参数说明

    -

    取值范围

    -

    levelNum

    -

    配置日志打印等级。

    -

    [0x0,0x5]

    -
    - -## 使用指南 - -- 该命令依赖于LOSCFG\_SHELL\_LK,使用时通过menuconfig在配置项中开启"Enable Shell lk": - - Debug ---\> Enable a Debug Version ---\> Enable Shell ---\> Enable Shell lK。 - -- log level命令用于配置日志的打印等级,包括6个等级 - - TRACE\_EMG = 0, - - TRACE\_COMMON = 1, - - TRACE\_ERROR = 2, - - TRACE\_WARN = 3, - - TRACE\_INFO = 4, - - TRACE\_DEBUG = 5 - - 若level不在有效范围内,会打印提示信息。 - -- 若log level命令不加\[levelNum\]参数,则默认查看当前打印等级,并且提示使用方法。 - -## 使用实例 - -举例: - -输入log level 4 - -## 输出说明 - -![](figures/zh-cn_image_0000001052530298.png) - diff --git a/zh-cn/device-dev/kernel/ls.md b/zh-cn/device-dev/kernel/ls.md deleted file mode 100755 index fa17ee7466..0000000000 --- a/zh-cn/device-dev/kernel/ls.md +++ /dev/null @@ -1,59 +0,0 @@ -# ls - -- [命令功能](#section6538163771614) -- [命令格式](#section45881743111616) -- [参数说明](#section17528148171617) -- [使用指南](#section041212533166) -- [使用实例](#section986105716167) -- [输出说明](#section2036124918592) - -## 命令功能 - -ls命令用来显示当前目录的内容。 - -## 命令格式 - -ls \[_path_\] - -## 参数说明 - -**表 1** 参数说明 - - - - - - - - - - - - -

    参数

    -

    参数说明

    -

    取值范围

    -

    path

    -

    path为空时,显示当前目录的内容。

    -

    path为无效文件名时,显示失败,提示:

    -

    ls error: No such directory。

    -

    path为有效目录路径时,会显示对应目录下的内容。

    -

    1.为空。

    -

    2.有效的目录路径。

    -
    - -## 使用指南 - -- ls命令显示当前目录的内容。 -- ls可以显示文件的大小。 -- proc下ls无法统计文件大小,显示为0。 - -## 使用实例 - -举例:输入ls - -## 输出说明 - -**图 1** 查看当前系统路径下的目录,显示的内容如下 -![](figures/查看当前系统路径下的目录-显示的内容如下.png "查看当前系统路径下的目录-显示的内容如下") - diff --git a/zh-cn/device-dev/kernel/lsfd.md b/zh-cn/device-dev/kernel/lsfd.md deleted file mode 100755 index fe0ac75118..0000000000 --- a/zh-cn/device-dev/kernel/lsfd.md +++ /dev/null @@ -1,29 +0,0 @@ -# lsfd - -- [命令功能](#section2053406181716) -- [命令格式](#section523771017172) -- [使用指南](#section27241213201719) -- [使用实例](#section442617197173) -- [输出说明](#section42491639151813) - -## 命令功能 - -lsfd命令用来显示当前已经打开的文件描述符及对应的文件名。 - -## 命令格式 - -lsfd - -## 使用指南 - -lsfd命令显示当前已经打开文件的fd号以及文件的名字。 - -## 使用实例 - -举例:输入lsfd - -## 输出说明 - -**图 1** lsfd输出说明 -![](figures/lsfd输出说明.png "lsfd输出说明") - diff --git a/zh-cn/device-dev/kernel/memcheck.md b/zh-cn/device-dev/kernel/memcheck.md deleted file mode 100755 index 5e6058dcf6..0000000000 --- a/zh-cn/device-dev/kernel/memcheck.md +++ /dev/null @@ -1,38 +0,0 @@ -# memcheck - -- [命令功能](#section191633812516) -- [命令格式](#section428816435510) -- [参数说明](#section1939943304411) -- [使用指南](#section228914491951) -- [使用实例](#section17373205314515) -- [输出说明](#section13406205385413) - -## 命令功能 - -检查动态申请的内存块是否完整,是否存在内存越界造成节点损坏。 - -## 命令格式 - -memcheck - -## 参数说明 - -无。 - -## 使用指南 - -- 当内存池所有节点完整时,输出"system memcheck over, all passed!"。 -- 当内存池存在节点不完整时,输出被损坏节点的内存块信息。 - -## 使用实例 - -举例:输入memcheck - -## 输出说明 - -**图 1** 当前没有内存越界 -![](figures/当前没有内存越界.png "当前没有内存越界") - -**图 2** 出现内存越界 -![](figures/出现内存越界.png "出现内存越界") - diff --git a/zh-cn/device-dev/kernel/mkdir.md b/zh-cn/device-dev/kernel/mkdir.md deleted file mode 100755 index 444d6a246b..0000000000 --- a/zh-cn/device-dev/kernel/mkdir.md +++ /dev/null @@ -1,54 +0,0 @@ -# mkdir - -- [命令功能](#section1083613274175) -- [命令格式](#section820913118178) -- [参数说明](#section1256834121718) -- [使用指南](#section1294234115172) -- [使用实例](#section1113345211713) -- [输出说明](#section10142201012) - -## 命令功能 - -mkdir命令用来创建一个目录。 - -## 命令格式 - -mkdir \[_directory_\] - -## 参数说明 - -**表 1** 参数说明 - - - - - - - - - - - - -

    参数

    -

    参数说明

    -

    取值范围

    -

    directory

    -

    需要创建的目录。

    -

    N/A

    -
    - -## 使用指南 - -- mkdir后加所需要创建的目录名会在当前目录下创建目录。 -- mkdir后加路径,再加上需要创建的目录名,即在指定目录下创建目录。 - -## 使用实例 - -举例:mkdir share - -## 输出说明 - -**图 1** 创建 share 目录 -![](figures/创建-share-目录.png "创建-share-目录") - diff --git a/zh-cn/device-dev/kernel/mount.md b/zh-cn/device-dev/kernel/mount.md deleted file mode 100755 index 5924e0ca5a..0000000000 --- a/zh-cn/device-dev/kernel/mount.md +++ /dev/null @@ -1,78 +0,0 @@ -# mount - -- [命令功能](#section11631837182) -- [命令格式](#section1697638111820) -- [参数说明](#section1650151221819) -- [使用指南](#section124541520171912) -- [使用实例](#section7424625171917) -- [输出说明](#section14757018116) - -## 命令功能 - -mount命令用来将设备挂载到指定目录。 - -## 命令格式 - -mount <_device_\> <_path_\> <_name_\> \[_uid gid_\] - -## 参数说明 - -**表 1** 参数说明 - - - - - - - - - - - - - - - - - - - - - - - - -

    参数

    -

    参数说明

    -

    取值范围

    -

    device

    -

    要挂载的设备(格式为设备所在路径)。

    -

    系统拥有的设备。

    -

    path

    -

    指定目录。

    -

    用户必须具有指定目录中的执行(搜索)许可权。

    -

    N/A

    -

    name

    -

    文件系统的种类。

    -

    vfat, yaffs, jffs, ramfs, nfs,procfs, romfs.

    -

    uid gid

    -

    uid是指用户ID。

    -

    gid是指组ID。

    -

    可选参数,缺省值uid:0,gid:0。

    -

    N/A

    -
    - -## 使用指南 - -mount后加需要挂载的设备信息、指定目录以及设备文件格式,就能成功挂载文件系统到指定目录。 - -## 使用实例 - -举例:mount /dev/mmcblk0p0 /bin1/vs/sd vfat - -## 输出说明 - -将/dev/mmcblk0p0 挂载到/bin1/vs/sd目录 - -![](figures/zh-cn_image_0000001051690323.png) - diff --git a/zh-cn/device-dev/kernel/netstat.md b/zh-cn/device-dev/kernel/netstat.md deleted file mode 100755 index cca0b0dc9a..0000000000 --- a/zh-cn/device-dev/kernel/netstat.md +++ /dev/null @@ -1,83 +0,0 @@ -# netstat - -- [命令功能](#section13469162113816) -- [命令格式](#section795712373812) -- [参数说明](#section17629431193817) -- [使用指南](#section5277153519380) -- [使用实例](#section108141437163820) -- [输出说明](#section1357015107117) - -## 命令功能 - -netstat是控制台命令,是一个监测TCP/IP网络的非常有用的工具,它可以显示实际的网络连接以及每一个网络接口设备的状态信息。netstat用于显示与TCP、UDP协议相关的统计数据,一般用于检验本设备(单板)各端口的网络连接情况。 - -## 命令格式 - -netstat - -## 参数说明 - -无 - -## 使用指南 - -直接输入命令。 - -## 使用实例 - -举例:输入netstat - -**图 1** netstat 打印信息 - - -![](figures/Snipaste_2021-01-26_10-38-58-1.png) - -## 输出说明 - -**表 1** 输出说明 - - - - - - - - - - - - - - - - - - - - - - - - - -

    输出

    -

    说明

    -

    Proto

    -

    协议类型。

    -

    Recv-Q

    -

    未被用户读取的数据量。

    -

    对于Listen TCP,此值为已完成三次握手,但是未被用户accept的TCP连接的数量。

    -

    Send-Q

    -

    对TCP连接,已发送但未确认的数据量。

    -

    对UDP连接,由于IP地址解析未完成而缓存的数据量。

    -

    Local Address

    -

    本地地址和端口。

    -

    Foreign Address

    -

    远程地址和端口。

    -

    State

    -

    TCP连接状态,UDP此项无意义。

    -
    - ->![](public_sys-resources/icon-note.gif) **说明:** ->形如“========== total sockets 32 ====== unused sockets 22 BootTime 27 s ========== ”,表示一共32个套接字,未使用套接字22个,距系统启动已经过27秒。 - diff --git a/zh-cn/device-dev/kernel/oom.md b/zh-cn/device-dev/kernel/oom.md deleted file mode 100755 index 4590f61fed..0000000000 --- a/zh-cn/device-dev/kernel/oom.md +++ /dev/null @@ -1,120 +0,0 @@ -# oom - -- [命令功能](#section366714216619) -- [命令格式](#section8833164614615) -- [参数说明](#section12809111019453) -- [使用指南](#section15935131220717) -- [使用实例](#section79281818476) -- [输出说明](#section12742311179) - -## 命令功能 - -查看和设置低内存阈值以及pagecache内存回收阈值。 - -## 命令格式 - -oom - -oom -i \[_interval_\] - -oom -m \[_mem byte_\] - -oom -r \[_mem byte_\] - -oom -h | --help - -## 参数说明 - -**表 1** 参数说明 - - - - - - - - - - - - - - - - - - - - - - - - -

    参数

    -

    参数说明

    -

    取值范围

    -

    -i [interval]

    -

    设置oom线程任务检查的时间间隔。

    -

    100ms ~ 10000ms

    -

    -m [mem byte]

    -

    设置低内存阈值。

    -

    0MB ~ 1MB,0MB表示不做低内存阈值检查。

    -

    -r [mem byte]

    -

    设置pagecache内存回收阈值。

    -

    低内存阈值 ~ 系统可用最大内存。

    -

    -h | --help

    -

    使用帮助。

    -

    N/A

    -
    - -## 使用指南 - -- 参数缺省时,显示oom功能当前配置信息。 - -## 使用实例 - -当系统内存不足时,会打印出内存不足的提示信息。 - -## 输出说明 - -![](figures/zh-cn_image_0000001053710680.png) - -**表 2** 输出说明 - - - - - - - - - - - - - - - - - - - - - - -

    输出

    -

    说明

    -

    [oom] OS is in low memory state

    -

    total physical memory: 0x1bcf000(byte), used: 0x1b50000(byte), free: 0x7f000(byte), low memory threshold: 0x80000(byte)

    -

    操作系统处于低内存状态。

    -

    整个系统可用物理内存为0x1bcf000 byte,已经使用了 0x1b50000 byte, 还剩0x7f000 byte,当前设置的低内存阈值为0x80000 byte。

    -

    [oom] candidate victim process init pid: 1, actual phy mem byte: 82602

    -

    打印当前各个进程的内存使用情况,init进程实际使用82602byte,其中共享内存按照比例算的。

    -

    [oom] candidate victim process UserProcess12 pid: 12, actual phy mem byte: 25951558

    -

    UserProcess12进程实际使用25951558byte内存。

    -

    [oom] max phy mem used process UserProcess12 pid: 12, actual phy mem: 25951558

    -

    当前使用内存最多的进程是UserProcess12。

    -

    excFrom: User!

    -

    当系统处于低内存的情况下,UserProcess12进程再去申请内存时失败退出。

    -
    - diff --git a/zh-cn/device-dev/kernel/partinfo.md b/zh-cn/device-dev/kernel/partinfo.md deleted file mode 100755 index b8dc652e97..0000000000 --- a/zh-cn/device-dev/kernel/partinfo.md +++ /dev/null @@ -1,52 +0,0 @@ -# partinfo - -- [命令功能](#section1777503617199) -- [命令格式](#section185501447132114) -- [参数说明](#section1304151212252) -- [使用指南](#section4566131982520) -- [使用实例](#section4351134942514) -- [输出说明](#section66689331412) - -## 命令功能 - -partinfo命令用于查看系统识别的硬盘,SD卡多分区信息。 - -## 命令格式 - -partinfo <_dev\_inodename_\> - -## 参数说明 - -**表 1** 参数说明 - - - - - - - - - - - - -

    参数

    -

    参数说明

    -

    取值范围

    -

    dev_inodename

    -

    要查看的分区名字。

    -

    合法的分区名。

    -
    - -## 使用指南 - -无 - -## 使用实例 - -partinfo /dev/mmcblk0p0 - -## 输出说明 - -![](figures/zh-cn_image_0000001052370303.png) - diff --git a/zh-cn/device-dev/kernel/partition.md b/zh-cn/device-dev/kernel/partition.md deleted file mode 100755 index 9a4b156849..0000000000 --- a/zh-cn/device-dev/kernel/partition.md +++ /dev/null @@ -1,62 +0,0 @@ -# partition - -- [命令功能](#section255095212257) -- [命令格式](#section10258056122515) -- [参数说明](#section177200581256) -- [使用指南](#section17866411262) -- [使用实例](#section1927174202610) -- [输出说明](#section11321011223) - -## 命令功能 - -partition命令用来查看flash分区信息。 - -## 命令格式 - -partition \[_nand / spinor_\] - -## 参数说明 - -**表 1** 参数说明 - - - - - - - - - - - - - - - - -

    参数

    -

    参数说明

    -

    取值范围

    -

    nand

    -

    显示nand flash分区信息。

    -

    N/A

    -

    spinor

    -

    显示spinor flash分区信息。

    -

    N/A

    -
    - -## 使用指南 - -- partition命令用来查看flash分区信息。 -- 仅当使能yaffs文件系统时才可以查看nand flash分区信息,使能jffs或romfs文件系统时可以查看spinor flash分区信息。 - -## 使用实例 - -举例:partition spinor - -## 输出说明 - -查看spinor flash分区信息 - -![](figures/zh-cn_image_0000001052810300.png) - diff --git a/zh-cn/device-dev/kernel/ping.md b/zh-cn/device-dev/kernel/ping.md deleted file mode 100755 index c995f3c5eb..0000000000 --- a/zh-cn/device-dev/kernel/ping.md +++ /dev/null @@ -1,99 +0,0 @@ -# ping - -- [命令功能](#section119672573385) -- [命令格式](#section869419010390) -- [参数说明](#section9877183173918) -- [使用指南](#section1097046193914) -- [使用实例](#section14564129113911) -- [输出说明](#section1621732891215) - -## 命令功能 - -ping命令用于测试网络连接是否正常。 - -## 命令格式 - -ping_ _\[_-n cnt_\] \[_-w interval_\] \[_-l data\_len_\]_ _ - -ping \[_-t_\] \[_-w interval_\] __ - -ping _-k_ - -## 参数说明 - -**表 1** 参数说明 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    参数

    -

    参数说明

    -

    取值范围

    -

    IP

    -

    要测试是否网络连通的IPv4地址。

    -

    N/A

    -

    -n cnt

    -

    执行的次数,不带本参数则默认为4次。

    -

    1-65535

    -

    -w interval

    -

    发送两次ping包的时间间隔,单位毫秒。

    -

    >0

    -

    -l data_len

    -

    ping包,即ICMP echo request报文的数据长

    -

    度,不包含ICMP包头。

    -

    0-65500

    -

    -t

    -

    表示永久ping,直到使用ping -k杀死ping线

    -

    程。

    -

    N/A

    -

    -k

    -

    杀死ping线程,停止ping。

    -

    N/A

    -
    - -## 使用指南 - -- ping命令用来测试到目的IP的网络连接是否正常,参数为目的IP地址。 -- 如果目的IP不可达,会显示请求超时。 -- 如果显示发送错误,说明没有到目的IP的路由。 -- 命令需要启动TCP/IP协议栈后才能使用。 - -## 使用实例 - -举例:输入ping 192.168.1.10 - -## 输出说明 - -**图 1** ping tftp 服务器地址 - - -![](figures/Snipaste_2021-01-26_10-38-58-2.png) - diff --git a/zh-cn/device-dev/kernel/pmm.md b/zh-cn/device-dev/kernel/pmm.md deleted file mode 100755 index 9ed393dfdd..0000000000 --- a/zh-cn/device-dev/kernel/pmm.md +++ /dev/null @@ -1,91 +0,0 @@ -# pmm - -- [命令功能](#section445335110416) -- [命令格式](#section1795712553416) -- [参数说明](#section92544592410) -- [使用指南](#section104151141252) -- [使用实例](#section11545171957) -- [输出说明](#section075617368542) - -## 命令功能 - -查看系统内存物理页及pagecache物理页使用情况。 - -## 命令格式 - -pmm - -## 参数说明 - -无 - -## 使用指南 - -Debug版本才具备的命令。 - -## 使用实例 - -输入pmm - -## 输出说明 - -**图 1** 查看物理页使用情况 -![](figures/查看物理页使用情况.png "查看物理页使用情况") - -**表 1** 输出说明 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    输出

    -

    说明

    -

    phys_seg

    -

    物理页控制块地址信息

    -

    base

    -

    第一个物理页地址,即物理页内存起始地址

    -

    size

    -

    物理页内存大小

    -

    free_pages

    -

    空闲物理页数量

    -

    active anon

    -

    pagecache中,活跃的匿名页数量

    -

    inactive anon

    -

    pagecache中,不活跃的匿名页数量

    -

    active file

    -

    pagecache中,活跃的文件页数量

    -

    inactive file

    -

    pagecache中,不活跃的文件页数量

    -

    pmm pages

    -

    total:总的物理页数,used:已使用的物理页数,free:空闲的物理页数

    -
    - diff --git a/zh-cn/device-dev/kernel/public_sys-resources/icon-caution.gif b/zh-cn/device-dev/kernel/public_sys-resources/icon-caution.gif deleted file mode 100755 index 6e90d7cfc2193e39e10bb58c38d01a23f045d571..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 580 zcmV-K0=xZ3Nk%w1VIu$?0Hp~4{QBgqmQ+MG9K51r{QB&)np^||1PlfQ%(86!{`~yv zv{XhUWKt}AZaiE{EOcHp{O-j3`t;<+eEiycJT4p@77X;(jQsMfB$R?oG%6hQ z+MMLZbQBH@)Vg&1^3?qHb(5!%>3r0+`eq=&V&E}0Dypi0000000000 z00000A^8LW000R9EC2ui03!e$000L5z=Uu}ED8YtqjJd<+B}(9bIOb$3-31_h|V>=0A{ z1Hh0#H30>fNT})^fRU_83uewx9oRr{f{Sx1Ml`t)EQ zGkHZ67&~y{W5Jpq4H_WfuLxp*3<7O}GEl;1ESe36fLNs=B0&LQM1Buf(R)qg(BRd`t1OPjI1m_q4 diff --git a/zh-cn/device-dev/kernel/public_sys-resources/icon-danger.gif b/zh-cn/device-dev/kernel/public_sys-resources/icon-danger.gif deleted file mode 100755 index 6e90d7cfc2193e39e10bb58c38d01a23f045d571..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 580 zcmV-K0=xZ3Nk%w1VIu$?0Hp~4{QBgqmQ+MG9K51r{QB&)np^||1PlfQ%(86!{`~yv zv{XhUWKt}AZaiE{EOcHp{O-j3`t;<+eEiycJT4p@77X;(jQsMfB$R?oG%6hQ z+MMLZbQBH@)Vg&1^3?qHb(5!%>3r0+`eq=&V&E}0Dypi0000000000 z00000A^8LW000R9EC2ui03!e$000L5z=Uu}ED8YtqjJd<+B}(9bIOb$3-31_h|V>=0A{ z1Hh0#H30>fNT})^fRU_83uewx9oRr{f{Sx1Ml`t)EQ zGkHZ67&~y{W5Jpq4H_WfuLxp*3<7O}GEl;1ESe36fLNs=B0&LQM1Buf(R)qg(BRd`t1OPjI1m_q4 diff --git a/zh-cn/device-dev/kernel/public_sys-resources/icon-note.gif b/zh-cn/device-dev/kernel/public_sys-resources/icon-note.gif deleted file mode 100755 index 6314297e45c1de184204098efd4814d6dc8b1cda..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 394 zcmZ?wbhEHblx7fPSjxcg=ii?@_wH=jwxy=7CMGH-B`L+l$wfv=#>UF#$gv|VY%C^b zCQFtrnKN(Bo_%|sJbO}7RAORe!otL&qo<>yq_Sq+8Xqqo5h0P3w3Lvb5E(g{p01vl zxR@)KuDH0l^z`+-dH3eaw=XqSH7aTIx{kzVBN;X&hha0dQSgWuiw0NWUvMRmkD|> diff --git a/zh-cn/device-dev/kernel/public_sys-resources/icon-notice.gif b/zh-cn/device-dev/kernel/public_sys-resources/icon-notice.gif deleted file mode 100755 index 86024f61b691400bea99e5b1f506d9d9aef36e27..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 406 zcmV;H0crk6Nk%w1VIu$@0J8u9|NsB@_xJDb@8;&_*4Ea}&d#;9wWXz{jEszHYim+c zQaU<1At50E0000000000A^8Le000gEEC2ui03!e%000R7038S%NU)&51O^i-Tu6`s z0)`MFE@;3YqD6xSC^kTNu_J>91{PH8XfZ(p1pp2-SU@u3#{mEUC}_}tg3+I#{z}{Ok@D_ZUDg- zt0stin4;pC8M{WLSlRH*1pzqEw1}3oOskyNN?j;7HD{BBZ*OEcv4HK!6Bk6beR+04 z&8}k>SkTusVTDmkyOz#5fCA$JTPGJVQvr3uZ?QzzPQFvD0rGf_PdrcF`pMs}p^BcF zKtKTd`0wipR%nKN&Wj+V}pX;WC3SdJV!a_8Qi zE7z`U*|Y^H0^}fB$R?oG%6hQ z+MMLZbQBH@)Vg&1^3?qHb(5!%>3r0+`eq=&V&E}0Dypi0000000000 z00000A^8LW000R9EC2ui03!e$000L5z=Uu}ED8YtqjJd<+B}(9bIOb$3-31_h|V>=0A{ z1Hh0#H30>fNT})^fRU_83uewx9oRr{f{Sx1Ml`t)EQ zGkHZ67&~y{W5Jpq4H_WfuLxp*3<7O}GEl;1ESe36fLNs=B0&LQM1Buf(R)qg(BRd`t1OPjI1m_q4 diff --git a/zh-cn/device-dev/kernel/pwd.md b/zh-cn/device-dev/kernel/pwd.md deleted file mode 100755 index bff68160ce..0000000000 --- a/zh-cn/device-dev/kernel/pwd.md +++ /dev/null @@ -1,34 +0,0 @@ -# pwd - -- [命令功能](#section197737712267) -- [命令格式](#section1544061016267) -- [参数说明](#section599112120262) -- [使用指南](#section66901116152615) -- [使用实例](#section7427181922612) -- [输出说明](#section116313389418) - -## 命令功能 - -pwd命令用来显示当前路径。 - -## 命令格式 - -pwd - -## 参数说明 - -无。 - -## 使用指南 - -pwd 命令将当前目录的全路径名称(从根目录)写入标准输出。全部目录使用 / (斜线)分隔。第一个 / 表示根目录, 最后一个目录是当前目录。 - -## 使用实例 - -举例:输入pwd - -## 输出说明 - -**图 1** 查看当前路径 -![](figures/查看当前路径.png "查看当前路径") - diff --git a/zh-cn/device-dev/kernel/rm.md b/zh-cn/device-dev/kernel/rm.md deleted file mode 100755 index 2815b287a1..0000000000 --- a/zh-cn/device-dev/kernel/rm.md +++ /dev/null @@ -1,67 +0,0 @@ -# rm - -- [命令功能](#section181141523142613) -- [命令格式](#section8800926132619) -- [参数说明](#section15476229152617) -- [使用指南](#section10578163215262) -- [使用实例](#section18548133511263) -- [输出说明](#section1565323814265) - -## 命令功能 - -rm命令用来删除文件或文件夹。 - -## 命令格式 - -rm \[_-r_\] \[_dirname / filename_\] - -## 参数说明 - -**表 1** 参数说明 - - - - - - - - - - - - - - - - -

    参数

    -

    参数说明

    -

    取值范围

    -

    -r

    -

    可选参数,若是删除目录则需要该参数。

    -

    N/A

    -

    dirname/filename

    -

    要删除文件或文件夹的名称,支持输入路径。

    -

    N/A

    -
    - -## 使用指南 - -- rm命令一次只能删除一个文件或文件夹。 -- rm -r命令可以删除非空目录。 - -## 使用实例 - -举例: - -1. 输入rm log1.txt -2. 输入rm -r sd - -## 输出说明 - -**图 1** 用 rm 命令删除文件 log1.txt -![](figures/用-rm-命令删除文件-log1-txt.png "用-rm-命令删除文件-log1-txt") - -**图 2** 用 rm -r 删除目录 sd -![](figures/用-rm--r-删除目录-sd.png "用-rm--r-删除目录-sd") - diff --git a/zh-cn/device-dev/kernel/rmdir.md b/zh-cn/device-dev/kernel/rmdir.md deleted file mode 100755 index 6a1e52eee3..0000000000 --- a/zh-cn/device-dev/kernel/rmdir.md +++ /dev/null @@ -1,55 +0,0 @@ -# rmdir - -- [命令功能](#section1839611420266) -- [命令格式](#section329574512266) -- [参数说明](#section15865747102620) -- [使用指南](#section107857508261) -- [使用实例](#section11196165315262) -- [输出说明](#section1073811415613) - -## 命令功能 - -rmdir命令用来删除一个目录。 - -## 命令格式 - -rmdir \[_dir_\] - -## 参数说明 - -**表 1** 参数说明 - - - - - - - - - - - - -

    参数

    -

    参数说明

    -

    取值范围

    -

    dir

    -

    需要删除目录的名称,删除目录必须为空,支持输入路径。

    -

    N/A

    -
    - -## 使用指南 - -- rmdir命令只能用来删除目录。 -- rmdir一次只能删除一个目录。 -- rmdir只能删除空目录。 - -## 使用实例 - -举例:输入rmdir dir - -## 输出说明 - -**图 1** 删除一个名为 dir 的目录 -![](figures/删除一个名为-dir-的目录.png "删除一个名为-dir-的目录") - diff --git a/zh-cn/device-dev/kernel/sem.md b/zh-cn/device-dev/kernel/sem.md deleted file mode 100755 index 14342e7531..0000000000 --- a/zh-cn/device-dev/kernel/sem.md +++ /dev/null @@ -1,91 +0,0 @@ -# sem - -- [命令功能](#section366714216619) -- [命令格式](#section8833164614615) -- [参数说明](#section12809111019453) -- [使用指南](#section15935131220717) -- [使用实例](#section79281818476) -- [输出说明](#section1975118519456) - -## 命令功能 - -sem命令用于查询系统内核信号量相关信息。 - -## 命令格式 - -sem \[_ID__ / fulldata_\] - -## 参数说明 - -**表 1** 参数说明 - - - - - - - - - - - - - - - - -

    参数

    -

    参数说明

    -

    取值范围

    -

    ID

    -

    信号ID号。

    -

    [0, 0xFFFFFFFF]

    -

    fulldata

    -

    查询所有在用的信号量信息,打印信息包括如下:SemID, Count, Original Count, Creater TaskEntry, Last Access Time。

    -

    N/A

    -
    - -## 使用指南 - -- 参数缺省时,显示所有的信号量的使用数及信号量总数。 -- sem后加ID,显示对应ID信号量的使用数。 -- 参数fulldata依赖于LOSCFG\_DEBUG\_SEMAPHORE,使用时通过menuconfig在配置项中开启"Enable Semaphore Debugging": - - Debug ---\> Enable a Debug Version ---\> Enable Debug LiteOS Kernel Resource ---\> Enable Semaphore Debugging - - -## 使用实例 - -举例1:输入 sem fulldata - -## 输出说明 - -**图 1** 查询所有在用的信号量信息 -![](figures/查询所有在用的信号量信息.png "查询所有在用的信号量信息") - -**表 2** 输出说明 - - - - - - - - - - - - - -

    输出

    -

    说明

    -

    SemID

    -

    信号量ID。

    -

    Count

    -

    信号量使用数。

    -
    - ->![](public_sys-resources/icon-note.gif) **说明:** ->● sem命令的ID参数输入形式以十进制形式表示或十六进制形式表示皆可。 ->● sem命令的ID参数在\[0, 1023\]范围内时,返回对应ID的信号量的状态(如果对应ID的信号量未被使用则进行提示);其他取值时返回参数错误的提示。 - diff --git a/zh-cn/device-dev/kernel/stack.md b/zh-cn/device-dev/kernel/stack.md deleted file mode 100755 index 526ed83f4d..0000000000 --- a/zh-cn/device-dev/kernel/stack.md +++ /dev/null @@ -1,73 +0,0 @@ -# stack - -- [命令功能](#section445335110416) -- [命令格式](#section1795712553416) -- [参数说明](#section92544592410) -- [使用指南](#section104151141252) -- [使用实例](#section11545171957) -- [输出说明](#section075617368542) - -## 命令功能 - -查看系统各堆栈使用情况。 - -## 命令格式 - -stack - -## 参数说明 - -无。 - -## 使用指南 - -无。 - -## 使用实例 - -输入:stack - -## 输出说明 - -**图 1** 系统堆栈使用情况 - - -![](figures/zh-cn_image_0000001054624363.png) - -**表 1** 输出说明 - - - - - - - - - - - - - - - - - - - - - - -

    输出

    -

    说明

    -

    stack name

    -

    系统堆栈名

    -

    cpu id

    -

    cpu 号

    -

    stack addr

    -

    栈地址

    -

    total size

    -

    堆栈大小

    -

    used size

    -

    堆栈实际使用大小

    -
    - diff --git a/zh-cn/device-dev/kernel/statfs.md b/zh-cn/device-dev/kernel/statfs.md deleted file mode 100755 index bc428c78b2..0000000000 --- a/zh-cn/device-dev/kernel/statfs.md +++ /dev/null @@ -1,52 +0,0 @@ -# statfs - -- [命令功能](#section153921657152613) -- [命令格式](#section135391102717) -- [参数说明](#section074312314279) -- [使用指南](#section133816772712) -- [使用实例](#section526149182717) - -## 命令功能 - -statfs命令用来打印文件系统的信息,如该文件系统类型、总大小、可用大小等信息。 - -## 命令格式 - -statfs \[_directory_\] - -## 参数说明 - -**表 1** 参数说明 - - - - - - - - - - - - -

    参数

    -

    参数说明

    -

    取值范围

    -

    directory

    -

    文件系统的路径。

    -

    必须是存在的文件系统,并且其支持statfs命令,当前支持的文件系统有:JFFS2,FAT,NFS。

    -
    - -## 使用指南 - -打印信息因文件系统而异。 - -## 使用实例 - -以nfs文件系统为例: - -statfs /nfs - -**图 1** statfs输出说明 -![](figures/statfs输出说明.png "statfs输出说明") - diff --git a/zh-cn/device-dev/kernel/su.md b/zh-cn/device-dev/kernel/su.md deleted file mode 100755 index a23b14445d..0000000000 --- a/zh-cn/device-dev/kernel/su.md +++ /dev/null @@ -1,62 +0,0 @@ -# su - -- [命令功能](#section297810431676) -- [命令格式](#section157131147876) -- [参数说明](#section04145521671) -- [使用指南](#section14615155610719) -- [使用实例](#section13338150985) -- [输出说明](#section125021924194613) - -## 命令功能 - -su用于变更为其他使用者的身份。 - -## 命令格式 - -su \[_uid_\] \[_gid_\] - -## 参数说明 - -**表 1** 参数说明 - - - - - - - - - - - - - - - - -

    参数

    -

    参数说明

    -

    取值范围

    -

    uid

    -

    目标用户的用户id值。

    -
    • 为空。
    • [0,60000]
    -

    gid

    -

    目标用户的群组id值。

    -
    • 为空。
    • [0,60000]
    -
    - -## 使用指南 - -- su命令缺省切换到root用户,uid默认为0,gid为0。 -- 在su命令后的输入参数uid和gid就可以切换到该uid和gid的用户。 -- 输入参数超出范围时,会打印提醒输入正确范围参数。 - -## 使用实例 - -举例:su 1000 1000 - -## 输出说明 - -**图 1** **切换到**为uid为1000,gid为1000的用户 -![](figures/切换到为uid为1000-gid为1000的用户.png "切换到为uid为1000-gid为1000的用户") - diff --git a/zh-cn/device-dev/kernel/swtmr.md b/zh-cn/device-dev/kernel/swtmr.md deleted file mode 100755 index 7ab6560488..0000000000 --- a/zh-cn/device-dev/kernel/swtmr.md +++ /dev/null @@ -1,110 +0,0 @@ -# swtmr - -- [命令功能](#section166171064814) -- [命令格式](#section424011111682) -- [参数说明](#section1268410459465) -- [使用指南](#section169806213815) -- [使用实例](#section16676026389) -- [输出说明](#section1541991614710) - -## 命令功能 - -swtmr命令用于查询系统软件定时器相关信息。 - -## 命令格式 - -swtmr \[_ID_\] - -## 参数说明 - -**表 1** 参数说明 - - - - - - - - - - - - -

    参数

    -

    参数说明

    -

    取值范围

    -

    ID

    -

    软件定时器ID号。

    -

    [0,0xFFFFFFFF]

    -
    - -## 使用指南 - -- 参数缺省时,默认显示所有软件定时器的相关信息。 -- swtmr后加ID号时,显示ID对应的软件定时器相关信息。 - -## 使用实例 - -举例:输入swtmr和swtmr 1 - -## 输出说明 - -**图 1** 查询所有软件定时器相关信息 -![](figures/查询所有软件定时器相关信息.png "查询所有软件定时器相关信息") - -**图 2** 查询对应 ID 的软件定时器信息 -![](figures/查询对应-ID-的软件定时器信息.png "查询对应-ID-的软件定时器信息") - -**表 2** 输出说明 - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    输出

    -

    说明

    -

    SwTmrID

    -

    软件定时器ID。

    -

    State

    -

    软件定时器状态。

    -

    状态可能为:"UnUsed", "Created", "Ticking"。

    -

    Mode

    -

    软件定时器模式。

    -

    模式可能为:"Once", "Period", "NSD(单次定时器,定时结束后不会自动删除)"。

    -

    Interval

    -

    软件定时器使用的Tick数。

    -

    Count

    -

    软件定时器已经工作的次数。

    -

    Arg

    -

    传入的参数。

    -

    handlerAddr

    -

    回调函数的地址。

    -
    - ->![](public_sys-resources/icon-note.gif) **说明:** ->- swtmr命令的ID参数输入形式以十进制形式表示或十六进制形式表示皆可。 ->- swtmr命令的ID参数在\[0, 当前软件定时器个数 - 1\]范围内时,返回对应ID的软件定时器的状态;其他取值时返回错误提示。 - diff --git a/zh-cn/device-dev/kernel/systeminfo.md b/zh-cn/device-dev/kernel/systeminfo.md deleted file mode 100755 index 16fbd841d3..0000000000 --- a/zh-cn/device-dev/kernel/systeminfo.md +++ /dev/null @@ -1,91 +0,0 @@ -# systeminfo - -- [命令功能](#section863016434820) -- [命令格式](#section139791817795) -- [参数说明](#section19472339164813) -- [使用指南](#section285522592) -- [使用实例](#section9471171015105) -- [输出说明](#section1657011114915) - -## 命令功能 - -systeminfo命令用于显示当前操作系统内资源使用情况,包括任务、信号量、互斥量、队列、定时器等。 - -## 命令格式 - -systeminfo - -## 参数说明 - -无。 - -## 使用指南 - -无。 - -## 使用实例 - -举例:输入systeminfo - -## 输出说明 - -**图 1** 查看系统资源使用情况 -![](figures/查看系统资源使用情况.png "查看系统资源使用情况") - -**表 1** 输出说明 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    输出

    -

    说明

    -

    Module

    -

    模块名称。

    -

    Used

    -

    当前使用量。

    -

    Total

    -

    最大可用量。

    -

    Enabled

    -

    模块是否开启。

    -

    Task

    -

    任务。

    -

    Sem

    -

    信号量。

    -

    Mutex

    -

    互斥量。

    -

    Queue

    -

    队列。

    -

    SwTmr

    -

    定时器。

    -
    - diff --git a/zh-cn/device-dev/kernel/task.md b/zh-cn/device-dev/kernel/task.md deleted file mode 100755 index 673ed06ae2..0000000000 --- a/zh-cn/device-dev/kernel/task.md +++ /dev/null @@ -1,125 +0,0 @@ -# task - -- [命令功能](#section0533181714106) -- [命令格式](#section1014412308101) -- [参数说明](#section116057158506) -- [使用指南](#section2053502951112) -- [使用实例](#section12629113381116) -- [输出说明](#section19299103465015) - -## 命令功能 - -task命令用于查询进程及线程信息。 - -## 命令格式 - -task/task -a - -## 参数说明 - -**表 1** 参数说明 - - - - - - - - - - - - -

    参数

    -

    参数说明

    -

    取值范围

    -

    -a

    -

    查看更多信息。

    -

    N/A

    -
    - -## 使用指南 - -- 参数缺省时默认打印部分任务信息。 - -## 使用实例 - -举例:输入task - -## 输出说明 - -**图 1** 查询任务部分信息 -![](figures/查询任务部分信息.png "查询任务部分信息") - -**表 2** 输出说明 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    输出

    -

    说明

    -

    PID

    -

    进程ID。

    -

    PPID

    -

    父进程ID。

    -

    PGID

    -

    进程组ID。

    -

    UID

    -

    用户ID。

    -

    Status

    -

    任务当前的状态。

    -

    CPUUSE10s

    -

    10秒内CPU使用率。

    -

    PName

    -

    进程名。

    -

    TID

    -

    任务ID。

    -

    StackSize

    -

    任务堆栈的大小。

    -

    WaterLine

    -

    栈使用的峰值。

    -

    MEMUSE

    -

    内存使用量。

    -

    TaskName

    -

    任务名。

    -
    - diff --git a/zh-cn/device-dev/kernel/telnet.md b/zh-cn/device-dev/kernel/telnet.md deleted file mode 100755 index e68f22de46..0000000000 --- a/zh-cn/device-dev/kernel/telnet.md +++ /dev/null @@ -1,65 +0,0 @@ -# telnet - -- [命令功能](#section3551830123913) -- [命令格式](#section14897133233918) -- [参数说明](#section977718353392) -- [使用指南](#section134991538183916) -- [使用实例](#section1097414426398) -- [输出说明](#section11846624191310) - -## 命令功能 - -本命令用于启动或关闭telnet server服务。 - -## 命令格式 - -telnet \[_on | off_\] - -## 参数说明 - -**表 1** 参数说明 - - - - - - - - - - - - - - - - -

    参数

    -

    参数说明

    -

    取值范围

    -

    on

    -

    启动telnet server服务。

    -

    N/A

    -

    off

    -

    关闭telnet server服务。

    -

    N/A

    -
    - -## 使用指南 - -- telnet启动要确保网络驱动及网络协议栈已经初始化完成,且板子的网卡是link up状态。 -- 暂时无法支持多个客户端(telnet + IP)同时连接开发板。 - - >![](public_sys-resources/icon-notice.gif) **须知:** - >telnet属于调测功能,默认配置为关闭,正式产品中禁止使用该功能。 - - -## 使用实例 - -举例:输入telnet on - -## 输出说明 - -**图 1** 输入 telnet on -![](figures/输入-telnet-on.png "输入-telnet-on") - diff --git a/zh-cn/device-dev/kernel/tftp.md b/zh-cn/device-dev/kernel/tftp.md deleted file mode 100755 index a82fdf9389..0000000000 --- a/zh-cn/device-dev/kernel/tftp.md +++ /dev/null @@ -1,87 +0,0 @@ -# tftp - -- [命令功能](#section15142134573911) -- [命令格式](#section20958174917394) -- [参数说明](#section576613532395) -- [使用指南](#section149795134408) -- [使用实例](#section148921918114015) -- [输出说明](#section7872155631313) - -## 命令功能 - -TFTP(Trivial File Transfer Protocol,简单文件传输协议)是TCP/IP协议族中的一个用来在客户机与服务器之间进行简单文件传输的协议,提供简单、低开销的文件传输服务。端口号为69。 - -tftp命令可以从TFTP服务器上下载文件。 - -## 命令格式 - -./bin/tftp _<-g/-p\>_ _-l_ _\[FullPathLocalFile\] -r \[RemoteFile\] \[Host\]_ - -## 参数说明 - -**表 1** 参数说明 - - - - - - - - - - - - - - - - - - - - - - - - -

    参数

    -

    参数说明

    -

    取值范围

    -

    -g/-p

    -

    文件传输方向:

    -
    • -g 从TFTP服务器获取文件。
    • -p 上传文件到TFTP服务器。
    -

    N/A

    -

    -l FullPathLocalFile

    -

    本地文件完整路径。

    -

    N/A

    -

    -r RemoteFile

    -

    服务端文件名。

    -

    N/A

    -

    Host

    -

    服务端IP。

    -

    N/A

    -
    - -## 使用指南 - -1. 在服务器端搭建TFTP服务器,并进行正确配置。 -2. OpenHarmony单板使用tftp命令上传、下载文件。 -3. 传输的文件大小是有限制的不能大于32M。 - - >![](public_sys-resources/icon-notice.gif) **须知:** - >tftp属于调测功能,默认配置为关闭,正式产品中禁止使用该功能。 - - -## 使用实例 - -举例:从服务器下载out文件。 - -## 输出说明 - -``` -OHOS # ./bin/tftp -g -l /nfs/out -r out 192.168.1.2 -TFTP transfer finish -``` - -tftp命令执行后,传输正常完成会显示TFTP transfer finish, 失败的话会显示其他的打印信息帮助定位问题。 - diff --git a/zh-cn/device-dev/kernel/touch.md b/zh-cn/device-dev/kernel/touch.md deleted file mode 100755 index dc40b522af..0000000000 --- a/zh-cn/device-dev/kernel/touch.md +++ /dev/null @@ -1,59 +0,0 @@ -# touch - -- [命令功能](#section17541924112716) -- [命令格式](#section866182711274) -- [参数说明](#section268912296270) -- [使用指南](#section412093332714) -- [使用实例](#section414434814354) -- [输出说明](#section1028419515711) - -## 命令功能 - -- touch命令用来在指定的目录下创建一个不存在的空文件。 -- touch命令操作已存在的文件会成功,不会更新时间戳。 - -## 命令格式 - -touch \[_filename_\] - -## 参数说明 - -**表 1** 参数说明 - - - - - - - - - - - - -

    参数

    -

    参数说明

    -

    取值范围

    -

    filename

    -

    需要创建文件的名称。

    -

    N/A

    -
    - -## 使用指南 - -- touch命令用来创建一个空文件,该文件可读写。 -- 使用touch命令一次只能创建一个文件。 - - >![](public_sys-resources/icon-notice.gif) **须知:** - >在系统重要资源路径下使用touch命令创建文件,会对系统造成死机等未知影响,如在/dev路径下执行touch uartdev-0,会产生系统卡死现象。 - - -## 使用实例 - -举例:输入touch file.c 输出说明 - -## 输出说明 - -**图 1** 创建一个名为 file.c 的文件 -![](figures/创建一个名为-file-c-的文件.png "创建一个名为-file-c-的文件") - diff --git a/zh-cn/device-dev/kernel/umount.md b/zh-cn/device-dev/kernel/umount.md deleted file mode 100755 index 7cb41d53ef..0000000000 --- a/zh-cn/device-dev/kernel/umount.md +++ /dev/null @@ -1,55 +0,0 @@ -# umount - -- [命令功能](#section365125133520) -- [命令格式](#section9615254123512) -- [参数说明](#section63446577355) -- [使用指南](#section92931509368) -- [使用实例](#section144311323616) -- [输出说明](#section360525113611) - -## 命令功能 - -umount命令用来卸载指定文件系统。 - -## 命令格式 - -umount \[_dir_\] - -## 参数说明 - -**表 1** 参数说明 - - - - - - - - - - - - -

    参数

    -

    参数说明

    -

    取值范围

    -

    dir

    -

    需要卸载文件系统对应的目录。

    -

    系统已挂载的文件系统的目录。

    -
    - -## 使用指南 - -umount后加上需要卸载的指定文件系统的目录,即将指定文件系统卸载。 - -## 使用实例 - -举例:umount /bin1/vs/sd - -## 输出说明 - -将已在/bin1/vs/sd挂载的文件系统卸载 - -**图 1** umount输出示例 -![](figures/umount输出示例.png "umount输出示例") - diff --git a/zh-cn/device-dev/kernel/uname.md b/zh-cn/device-dev/kernel/uname.md deleted file mode 100755 index 71a06837cc..0000000000 --- a/zh-cn/device-dev/kernel/uname.md +++ /dev/null @@ -1,72 +0,0 @@ -# uname - -- [命令功能](#section107697383115) -- [命令格式](#section162824341116) -- [使用指南](#section2652124861114) -- [使用实例](#section0107995132) -- [输出说明](#section1215113245511) - -## 命令功能 - -uname命令用于显示当前操作系统的名称,版本创建时间,系统名称,版本信息等。 - -## 命令格式 - -uname \[_-a | -s | -t | -v | --help_\] - -**表 1** 参数说明 - - - - - - - - - - - - - - - - - - - - - - - - - -

    参数

    -

    参数说明

    -

    无参数

    -

    默认显示操作系统名称。

    -

    -a

    -

    显示全部信息。

    -

    -t

    -

    显示版本创建的时间。

    -

    -s

    -

    显示操作系统名称。

    -

    -v

    -

    显示版本信息。

    -

    --help

    -

    显示uname指令格式提示。

    -
    - -## 使用指南 - -uname用于显示当前操作系统名称。语法uname -a | -t| -s| -v 描述uname 命令将正在使用的操作系统名写到标准输出中,这几个参数不能混合使用。 - -## 使用实例 - -举例:输入uname -a - -## 输出说明 - -查看系统信息 - -![](figures/zh-cn_image_0000001052370305.png) - diff --git a/zh-cn/device-dev/kernel/vmm.md b/zh-cn/device-dev/kernel/vmm.md deleted file mode 100755 index 0d38eadc7e..0000000000 --- a/zh-cn/device-dev/kernel/vmm.md +++ /dev/null @@ -1,158 +0,0 @@ -# vmm - -- [命令功能](#section445335110416) -- [命令格式](#section1795712553416) -- [参数说明](#section92544592410) -- [使用指南](#section104151141252) -- [使用实例](#section11545171957) -- [输出说明](#section075617368542) - -## 命令功能 - -查看进程的虚拟内存使用情况。 - -## 命令格式 - -vmm \[_-a / -h / --help_\] - -vmm \[_pid_\] - -## 参数说明 - -**表 1** 参数说明 - - - - - - - - - - - - - - - - - - - - -

    参数

    -

    参数说明

    -

    取值范围

    -

    -a

    -

    输出所有进程的虚拟内存使用情况

    -

    N/A

    -

    -h | --help

    -

    命令格式说明

    -

    N/A

    -

    pid

    -

    进程ID,说明指定进程的虚拟内存使用情况

    -

    [0,63]

    -
    - -## 使用指南 - -命令缺省输出所有进程的虚拟内存使用情况。 - -## 使用实例 - -输入vmm 3 - -## 输出说明 - -**图 1** PID为3的进程虚拟内存使用信息 -![](figures/PID为3的进程虚拟内存使用信息.png "PID为3的进程虚拟内存使用信息") - -**表 2** 进程基本信息 - - - - - - - - - - - - - - - - - - - - - - - - - -

    输出

    -

    说明

    -

    PID

    -

    进程ID

    -

    aspace

    -

    进程虚拟内存控制块地址信息

    -

    name

    -

    进程名

    -

    base

    -

    虚拟内存起始地址

    -

    size

    -

    虚拟内存大小

    -

    pages

    -

    已使用的物理页数量

    -
    - -**表 3** 虚拟内存区间信息 - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    输出

    -

    说明

    -

    region

    -

    虚拟区间控制块地址信息

    -

    name

    -

    虚拟区间类型

    -

    base

    -

    虚拟区间起始地址

    -

    size

    -

    虚拟区间大小

    -

    mmu_flags

    -

    虚拟区间mmu映射属性

    -

    pages

    -

    已使用的物理页数量(包括共享内存部分)

    -

    pg/ref

    -

    已使用的物理页数量

    -
    - diff --git a/zh-cn/device-dev/kernel/watch.md b/zh-cn/device-dev/kernel/watch.md deleted file mode 100755 index 0586d287df..0000000000 --- a/zh-cn/device-dev/kernel/watch.md +++ /dev/null @@ -1,100 +0,0 @@ -# watch - -- [命令功能](#section20643141481314) -- [命令格式](#section1075441721316) -- [参数说明](#section1472810220135) -- [使用指南](#section186772414131) -- [使用实例](#section4764192791314) -- [输出说明](#section5791253155517) - -## 命令功能 - -watch命令用于周期性的监视一个命令的运行结果。 - -## 命令格式 - -watch - -watch \[_-c/-n/-t/--count/--interval/-no-title/--over_\] \[_command_\] - -## 参数说明 - -**表 1** 参数说明 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    参数

    -

    参数说明

    -

    缺省值

    -

    取值范围

    -

    -c / --count

    -

    命令执行的总次数。

    -

    0xFFFFFF

    -

    (0,0xFFFFFF]

    -

    -n / --interval

    -

    命令周期性执行的时间间隔(s)。

    -

    1s

    -

    (0,0xFFFFFF]

    -

    -t / -no-title

    -

    关闭顶端的时间显示。

    -

    N/A

    -

    N/A

    -

    command

    -

    需要监测的命令。

    -

    N/A

    -

    N/A

    -

    --over

    -

    关闭当前监测指令。

    -

    N/A

    -

    N/A

    -
    - -## 使用指南 - -watch运行过程中可以执行**watch --over**结束本次watch命令。 - -## 使用实例 - -输入举例: - -watch -n 2 -c 6 task - -## 输出说明 - -**图 1** watch task 结果 -![](figures/watch-task-结果.png "watch-task-结果") - ->![](public_sys-resources/icon-note.gif) **说明:** ->示例中,总共有6次task命令打印,每次间隔2秒,截图为最后一次打印详情。 - diff --git a/zh-cn/device-dev/kernel/writeproc.md b/zh-cn/device-dev/kernel/writeproc.md deleted file mode 100755 index 7e0306ff60..0000000000 --- a/zh-cn/device-dev/kernel/writeproc.md +++ /dev/null @@ -1,69 +0,0 @@ -# writeproc - -- [命令功能](#section366714216619) -- [命令格式](#section8833164614615) -- [参数说明](#section12809111019453) -- [使用指南](#section15935131220717) -- [使用实例](#section79281818476) -- [输出说明](#section12742311179) - -## 命令功能 - -proc fs支持传入字符串参数,需要每个文件实现自己的写方法。 - -## 命令格式 - -writeproc <_data_\> \>\> /proc/<_filename_\> - -## 参数说明 - -**表 1** 参数说明 - - - - - - - - - - - - - - - - -

    参数

    -

    参数说明

    -

    取值范围

    -

    data

    -

    要输入的字符串,以空格为结束符,如需输入空格,请用""包裹。

    -

    N/A

    -

    filename

    -

    data要传入的proc文件。

    -

    N/A

    -
    - -## 使用指南 - -proc文件实现自身的write函数,调用writeproc命令后会将入参传入write函数。 - ->![](public_sys-resources/icon-note.gif) **说明:** ->procfs不支持多线程访问。 - -## 使用实例 - -举例:writeproc test \>\> /proc/uptime - -## 输出说明 - -OHOS \# writeproc test \>\> /proc/uptime - -\[INFO\]write buf is: test - -test \>\> /proc/uptime - ->![](public_sys-resources/icon-note.gif) **说明:** ->uptime proc文件临时实现write函数,INFO日志为实现的测试函数打印的日志。 - diff --git "a/zh-cn/device-dev/kernel/\344\270\255\346\226\255\347\256\241\347\220\206.md" "b/zh-cn/device-dev/kernel/\344\270\255\346\226\255\347\256\241\347\220\206.md" deleted file mode 100644 index 29edaf0e1e..0000000000 --- "a/zh-cn/device-dev/kernel/\344\270\255\346\226\255\347\256\241\347\220\206.md" +++ /dev/null @@ -1,7 +0,0 @@ -# 中断管理 - -- **[基本概念](基本概念.md)** - -- **[开发指导](开发指导.md)** - - diff --git "a/zh-cn/device-dev/kernel/\344\272\213\344\273\266.md" "b/zh-cn/device-dev/kernel/\344\272\213\344\273\266.md" deleted file mode 100644 index e998fce8eb..0000000000 --- "a/zh-cn/device-dev/kernel/\344\272\213\344\273\266.md" +++ /dev/null @@ -1,7 +0,0 @@ -# 事件 - -- **[基本概念](基本概念-5.md)** - -- **[开发指导](开发指导-6.md)** - - diff --git "a/zh-cn/device-dev/kernel/\344\272\222\346\226\245\351\224\201.md" "b/zh-cn/device-dev/kernel/\344\272\222\346\226\245\351\224\201.md" deleted file mode 100644 index ce0ea2949c..0000000000 --- "a/zh-cn/device-dev/kernel/\344\272\222\346\226\245\351\224\201.md" +++ /dev/null @@ -1,7 +0,0 @@ -# 互斥锁 - -- **[基本概念](基本概念-7.md)** - -- **[开发指导](开发指导-8.md)** - - diff --git "a/zh-cn/device-dev/kernel/\344\273\273\345\212\241\347\256\241\347\220\206.md" "b/zh-cn/device-dev/kernel/\344\273\273\345\212\241\347\256\241\347\220\206.md" deleted file mode 100644 index 22165d0c36..0000000000 --- "a/zh-cn/device-dev/kernel/\344\273\273\345\212\241\347\256\241\347\220\206.md" +++ /dev/null @@ -1,7 +0,0 @@ -# 任务管理 - -- **[基本概念](基本概念-2.md)** - -- **[开发指导](开发指导-3.md)** - - diff --git "a/zh-cn/device-dev/kernel/\344\277\241\345\217\267\351\207\217.md" "b/zh-cn/device-dev/kernel/\344\277\241\345\217\267\351\207\217.md" deleted file mode 100644 index 6eb88eb04b..0000000000 --- "a/zh-cn/device-dev/kernel/\344\277\241\345\217\267\351\207\217.md" +++ /dev/null @@ -1,7 +0,0 @@ -# 信号量 - -- **[基本概念](基本概念-11.md)** - -- **[开发指导](开发指导-12.md)** - - diff --git "a/zh-cn/device-dev/kernel/\345\206\205\345\255\230.md" "b/zh-cn/device-dev/kernel/\345\206\205\345\255\230.md" deleted file mode 100755 index 871a1c5ac8..0000000000 --- "a/zh-cn/device-dev/kernel/\345\206\205\345\255\230.md" +++ /dev/null @@ -1,353 +0,0 @@ -# 内存 - -- [基本概念](#section1392116583424) -- [使用场景](#section159581619194319) -- [接口说明](#section114001032104317) - -## 基本概念 - -内存管理是开发过程中必须要关注的重要过程,它包括内存的分配、使用和回收。 - -良好的内存管理对于提高软件性能和可靠性有着十分重要的意义。 - -## 使用场景 - -针对用户态开发,OpenHarmony内核提供了一套内存系统调用接口,支持内存的申请释放、重映射、内存属性的设置等,还有C库的标准内存操作函数。 - -## 接口说明 - -**表 1** 标准C库相关接口 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    头文件

    -

    接口

    -

    功能

    -

    strings.h

    -

    int bcmp(const void *s1, const void *s2, size_t n)

    -

    比较字节序列。

    -

    strings.h

    -

    void bcopy(const void *src, void *dest, size_t n)

    -

    拷贝字节序列。

    -

    strings.h

    -

    void bzero(void *s, size_t n)

    -

    写入零值字节。

    -

    string.h

    -

    void *memccpy(void *dest, const void *src, int c, size_t n)

    -

    拷贝src 所指的内存内容前n 个字节到dest 所指的地址上。复制时检查参数c 是否出现,若是则返回dest 中值为c 的下一个字节地址。

    -

    string.h

    -

    void *memchr(const void *s, int c, size_t n)

    -

    在s所指内存的前n个字节中查找c。

    -

    string.h

    -

    int memcmp(const void *s1, const void *s2, size_t n)

    -

    内存比较。

    -

    string.h

    -

    void *memcpy(void *dest, const void *src, size_t n)

    -

    内存拷贝。

    -

    string.h

    -

    void *memmem(const void *haystack, size_t haystacklen, const void *needle, size_t needlelen)

    -

    找到一个子串。

    -

    string.h

    -

    void *memmove(void *dest, const void *src, size_t n)

    -

    内存移动。

    -

    string.h

    -

    void *mempcpy(void *dest, const void *src, size_t n)

    -

    拷贝内存区域。

    -

    string.h

    -

    void *memset(void *s, int c, size_t n)

    -

    内存初始化。

    -

    stdlib.h

    -

    void *malloc(size_t size)

    -

    申请内存。

    -

    stdlib.h

    -

    void *calloc(size_t nmemb, size_t size)

    -

    申请内存并清零。

    -

    stdlib.h

    -

    void *realloc(void *ptr, size_t size)

    -

    重分配内存。

    -

    stdlib.h/malloc.h

    -

    void *valloc(size_t size)

    -

    分配以页对齐的内存。

    -

    stdlib.h

    -

    void free(void *ptr)

    -

    释放内存。

    -

    malloc.h

    -

    size_t malloc_usable_size(void *ptr)

    -

    获取从堆分配的内存块的大小。

    -

    unistd.h

    -

    int getpagesize(void)

    -

    获取页面大小。

    -

    unistd.h

    -

    void *sbrk(intptr_t increment)

    -

    更改数据段大小。

    -
    - -差异接口详细说明: - -- **mmap** - - **函数原型:** - - void \*mmap\(void \*addr, size\_t length, int prot, int flags, int fd, off\_t offset\); - - **函数功能:**申请虚拟内存。 - - **参数说明:** - - - - - - - - - - - - - - - - - - - - - - - - - -

    参数

    -

    描述

    -

    addr

    -

    用来请求使用某个特定的虚拟内存地址。如果取NULL,结果地址就将自动分配(这是推荐的做法),否则会降低程序的可移植性,因为不同系统的可用地址范围不一样。

    -

    length

    -

    内存段的大小。

    -

    prot

    -

    用于设置内存段的访问权限,有如下权限:

    -
    • PROT_READ:允许读该内存段。
    • PROT_WRITE:允许写该内存段。
    • PROT_EXEC:允许执行该内存段。
    • PROT_NONE:不能访问。
    -

    flags

    -

    控制程序对内存段的改变所造成的影响,有如下属性:

    -
    • MAP_PRIVATE:内存段私有,对它的修改值仅对本进程有效。
    • MAP_SHARED:把对该内存段的修改保存到磁盘文件中。
    -

    fd

    -

    打开的文件描述符。

    -

    offset

    -

    用以改变经共享内存段访问的文件中数据的起始偏移值。

    -
    - - >![](public_sys-resources/icon-note.gif) **说明:** - >mmap与Linux实现差异详见[与Linux标准库的差异](与Linux标准库的差异.md)章节。 - - **返回值:** - - - 成功返回:虚拟内存地址,这地址是页对齐。 - - 失败返回:\(void \*\)-1。 - - -- **munmap接口** - - **函数原型:** - - int munmap\(void \*addr, size\_t length\); - - **函数功能:**释放虚拟内存。 - - **参数说明:** - - - - - - - - - - - - - -

    参数

    -

    描述

    -

    addr

    -

    虚拟内存起始位置。

    -

    length

    -

    内存段的大小。

    -
    - - **返回值:** - - - 成功返回0。 - - 失败返回-1。 - - -- **mprotect接口** - - **函数原型:** - - int mprotect\(void \*addr, size\_t length, int prot\); - - **函数功能:**修改内存段的访问权限。 - - **参数说明:** - - - - - - - - - - - - - - - - -

    参数

    -

    描述

    -

    addr

    -

    内存段起始地址,必须页对齐;访问权限异常,内核将直接抛异常并且kill该进程,而不会产生SIGSEGV信号给当前进程。

    -

    length

    -

    内存段的大小。

    -

    prot

    -

    内存段的访问权限,有如下定义:

    -
    • PROT_READ:允许读该内存段。
    • PROT_WRITE:允许写该内存段。
    • PROT_EXEC:允许执行该内存段。
    • PROT_NONE:不能访问。
    -
    - - **返回值:** - - - 成功返回0。 - - 失败返回-1。 - - -- **mremap接口** - - **函数原型:** - - void \*mremap\(void \*old\_address, size\_t old\_size, size\_t new\_size, int flags, void new\_address\); - - **函数功能:**重新映射虚拟内存地址。 - - **参数说明:** - - - - - - - - - - - - - - - - - - - -

    参数

    -

    描述

    -

    old_address

    -

    需要扩大(或缩小)的内存段的原始地址。注意old_address必须是页对齐。

    -

    old_size

    -

    内存段的原始大小。

    -

    new_size

    -

    新内存段的大小。

    -

    flags

    -

    如果没有足够的空间在当前位置展开映射,则返回失败

    -
    • MREMAP_MAYMOVE:允许内核将映射重定位到新的虚拟地址。
    • MREMAP_FIXED:mremap()接受第五个参数,void *new_address,该参数指定映射地址必须页对齐;在new_address和new_size指定的地址范围内的所有先前映射都被解除映射。如果指定了MREMAP_FIXED,还必须指定MREMAP_MAYMOVE。
    -
    - - **返回值:** - - - 成功返回:重新映射后的虚拟内存地址。 - - 失败返回:\(\(void \*\)-1\)。 - - diff --git "a/zh-cn/device-dev/kernel/\345\206\205\345\255\230\344\277\241\346\201\257\347\273\237\350\256\241.md" "b/zh-cn/device-dev/kernel/\345\206\205\345\255\230\344\277\241\346\201\257\347\273\237\350\256\241.md" deleted file mode 100644 index f0dce32252..0000000000 --- "a/zh-cn/device-dev/kernel/\345\206\205\345\255\230\344\277\241\346\201\257\347\273\237\350\256\241.md" +++ /dev/null @@ -1,107 +0,0 @@ -# 内存信息统计 - -- [基础概念](#section52691565235) -- [功能配置](#section470611682411) -- [开发指导](#section9368374243) - - [开发流程](#section679912407257) - - [编程实例](#section1025453412611) - - [示例代码](#section165277971315) - - [结果验证](#section3460102414271) - - -## 基础概念 - -内存信息包括内存池大小、内存使用量、剩余内存大小、最大空闲内存、内存水线、内存节点数统计、碎片率等。 - -- 内存水线:即内存池的最大使用量,每次申请和释放时,都会更新水线值,实际业务可根据该值,优化内存池大小; - -- 碎片率:衡量内存池的碎片化程度,碎片率高表现为内存池剩余内存很多,但是最大空闲内存块很小,可以用公式(fragment=100-最大空闲内存块大小/剩余内存大小)来度量; - -- 其他参数:通过调用接口(详见[内存管理](内存管理.md)章节接口说明),扫描内存池的节点信息,统计出相关信息。 - -## 功能配置 - -LOSCFG\_MEM\_WATERLINE:开关宏,默认打开;若关闭这个功能,在target\_config.h中将这个宏定义为0。如需获取内存水线,需要打开该配置。 - -## 开发指导 - -### 开发流程 - -关键结构体介绍: - -``` -typedef struct { - UINT32 totalUsedSize; // 内存池的内存使用量 - UINT32 totalFreeSize; // 内存池的剩余内存大小 - UINT32 maxFreeNodeSize; // 内存池的最大空闲内存块大小 - UINT32 usedNodeNum; // 内存池的非空闲内存块个数 - UINT32 freeNodeNum; // 内存池的空闲内存块个数 -#if (LOSCFG_MEM_WATERLINE == 1) // 默认打开,如需关闭,在target_config.h中将该宏设置为0 - UINT32 usageWaterLine; // 内存池的水线值 -#endif -} LOS_MEM_POOL_STATUS; -``` - -- 内存水线获取:调用LOS\_MemInfoGet接口,第1个参数是内存池首地址,第2个参数是LOS\_MEM\_POOL\_STATUS类型的句柄,其中字段usageWaterLine即水线值。 - -- 内存碎片率计算:同样调用LOS\_MemInfoGet接口,可以获取内存池的剩余内存大小和最大空闲内存块大小,然后根据公式(fragment=100-最大空闲内存块大小/剩余内存大小)得出此时的动态内存池碎片率。 - -### 编程实例 - -本实例实现如下功能: - -1.创建一个监控线程,用于获取内存池的信息; - -2.调用LOS\_MemInfoGet接口,获取内存池的基础信息; - -3.利用公式算出使用率及碎片率。 - -### 示例代码 - -代码实现如下: - -``` -#include -#include -#include "los_task.h" -#include "los_memory.h" -#include "los_config.h" - -void MemInfoTaskFunc(void) -{ - LOS_MEM_POOL_STATUS poolStatus = {0}; - LOS_MemInfoGet(pool, &poolStatus); - /* 算出内存池当前的碎片率百分比 */ - unsigned char fragment = 100 - poolStatus.maxFreeNodeSize * 100 / poolStatus.totalFreeSize; - /* 算出内存池当前的使用率百分比 */ - unsigned char usage = LOS_MemTotalUsedGet(pool) * 100 / LOS_MemPoolSizeGet(pool); - printf("usage = %d, fragment = %d, maxFreeSize = %d, totalFreeSize = %d, waterLine = %d\n", usage, fragment, poolStatus.maxFreeNodeSize, - poolStatus.totalFreeSize, poolStatus.usageWaterLine); -} - -int MemTest(void) -{ - unsigned int ret; - unsigned int taskID; - TSK_INIT_PARAM_S taskStatus = {0}; - taskStatus.pfnTaskEntry = (TSK_ENTRY_FUNC)MemInfoTaskFunc; - taskStatus.uwStackSize = 0x1000; - taskStatus.pcName = "memInfo"; - taskStatus.usTaskPrio = 10; - ret = LOS_TaskCreate(&taskID, &taskStatus); - if (ret != LOS_OK) { - printf("task create failed\n"); - return -1; - } - return 0; -} -``` - -### 结果验证 - -编译运行输出的结果如下: - -``` -usage = 22, fragment = 3, maxFreeSize = 49056, totalFreeSize = 50132, waterLine = 1414 -``` - diff --git "a/zh-cn/device-dev/kernel/\345\206\205\345\255\230\346\263\204\346\274\217\346\243\200\346\265\213.md" "b/zh-cn/device-dev/kernel/\345\206\205\345\255\230\346\263\204\346\274\217\346\243\200\346\265\213.md" deleted file mode 100644 index 5c57178e50..0000000000 --- "a/zh-cn/device-dev/kernel/\345\206\205\345\255\230\346\263\204\346\274\217\346\243\200\346\265\213.md" +++ /dev/null @@ -1,128 +0,0 @@ -# 内存泄漏检测 - -- [基础概念](#section1026719436293) -- [功能配置](#section13991354162914) -- [开发指导](#section95828159308) - - [开发流程](#section369844416304) - - [编程实例](#section460801313313) - - [示例代码](#section96539275311) - - [结果验证](#section20527343183119) - - -## 基础概念 - -内存泄漏检测机制作为内核的可选功能,用于辅助定位动态内存泄漏问题。开启该功能,动态内存机制会自动记录申请内存时的函数调用关系(下文简称LR)。如果出现泄漏,就可以利用这些记录的信息,找到内存申请的地方,方便进一步确认。 - -## 功能配置 - -1. LOSCFG\_MEM\_LEAKCHECK:开关宏,默认关闭;若打开这个功能,在target\_config.h中将这个宏定义为1。 -2. LOSCFG\_MEM\_RECORD\_LR\_CNT:记录的LR层数,默认3层;每层LR消耗sizeof\(void \*\)字节数的内存。 -3. LOSCFG\_MEM\_OMIT\_LR\_CNT:忽略的LR层数,默认4层,即从调用LOS\_MemAlloc的函数开始记录,可根据实际情况调整。为啥需要这个配置?有3点原因如下: - - LOS\_MemAlloc接口内部也有函数调用; - - 外部可能对LOS\_MemAlloc接口有封装; - - LOSCFG\_MEM\_RECORD\_LR\_CNT 配置的LR层数有限; - - -正确配置这个宏,将无效的LR层数忽略,就可以记录有效的LR层数,节省内存消耗。 - -## 开发指导 - -### 开发流程 - -该调测功能可以分析关键的代码逻辑中是否存在内存泄漏。开启这个功能,每次申请内存时,会记录LR信息。在需要检测的代码段前后,调用LOS\_MemUsedNodeShow接口,每次都会打印指定内存池已使用的全部节点信息,对比前后两次的节点信息,新增的节点信息就是疑似泄漏的内存节点。通过LR,可以找到具体申请的代码位置,进一步确认是否泄漏。 - -调用LOS\_MemUsedNodeShow接口输出的节点信息格式如下:每1行为一个节点信息;第1列为节点地址,可以根据这个地址,使用GDB等手段查看节点完整信息;第2列为节点的大小,等于节点头大小+数据域大小;第3\~5列为函数调用关系LR地址,可以根据这个值,结合汇编文件,查看该节点具体申请的位置。 - -``` -node size LR[0] LR[1] LR[2] -0x10017320: 0x528 0x9b004eba 0x9b004f60 0x9b005002 -0x10017848: 0xe0 0x9b02c24e 0x9b02c246 0x9b008ef0 -0x10017928: 0x50 0x9b008ed0 0x9b068902 0x9b0687c4 -0x10017978: 0x24 0x9b008ed0 0x9b068924 0x9b0687c4 -0x1001799c: 0x30 0x9b02c24e 0x9b02c246 0x9b008ef0 -0x100179cc: 0x5c 0x9b02c24e 0x9b02c246 0x9b008ef0 -``` - ->![](public_sys-resources/icon-caution.gif) **注意:** ->开启内存检测会影响内存申请的性能,且每个内存节点都会记录LR地址,内存开销也加大。 - -### 编程实例 - -本实例实现如下功能:构建内存泄漏代码段。 - -1. 调用LOS\_MemUsedNodeShow接口,输出全部节点信息打印; -2. 申请内存,但没有释放,模拟内存泄漏; -3. 再次调用LOS\_MemUsedNodeShow接口,输出全部节点信息打印; -4. 将两次log进行对比,得出泄漏的节点信息; -5. 通过LR地址,找出泄漏的代码位置; - -### 示例代码 - -代码实现如下: - -``` -#include -#include -#include "los_memory.h" -#include "los_config.h" - -void MemLeakTest(void) -{ - LOS_MemUsedNodeShow(LOSCFG_SYS_HEAP_ADDR); - void *ptr1 = LOS_MemAlloc(LOSCFG_SYS_HEAP_ADDR, 8); - void *ptr2 = LOS_MemAlloc(LOSCFG_SYS_HEAP_ADDR, 8); - LOS_MemUsedNodeShow(LOSCFG_SYS_HEAP_ADDR); -} -``` - -### 结果验证 - -编译运行输出log如下: - -``` -node size LR[0] LR[1] LR[2] -0x20001b04: 0x24 0x08001a10 0x080035ce 0x080028fc -0x20002058: 0x40 0x08002fe8 0x08003626 0x080028fc -0x200022ac: 0x40 0x08000e0c 0x08000e56 0x0800359e -0x20002594: 0x120 0x08000e0c 0x08000e56 0x08000c8a -0x20002aac: 0x56 0x08000e0c 0x08000e56 0x08004220 - -node size LR[0] LR[1] LR[2] -0x20001b04: 0x24 0x08001a10 0x080035ce 0x080028fc -0x20002058: 0x40 0x08002fe8 0x08003626 0x080028fc -0x200022ac: 0x40 0x08000e0c 0x08000e56 0x0800359e -0x20002594: 0x120 0x08000e0c 0x08000e56 0x08000c8a -0x20002aac: 0x56 0x08000e0c 0x08000e56 0x08004220 -0x20003ac4: 0x1d 0x08001458 0x080014e0 0x080041e6 -0x20003ae0: 0x1d 0x080041ee 0x08000cc2 0x00000000 -``` - -对比两次log,差异如下,这些内存节点就是疑似泄漏的内存块: - -``` -0x20003ac4: 0x1d 0x08001458 0x080014e0 0x080041e6 -0x20003ae0: 0x1d 0x080041ee 0x08000cc2 0x00000000 -``` - -部分汇编文件如下: - -``` - MemLeakTest: - 0x80041d4: 0xb510 PUSH {R4, LR} - 0x80041d6: 0x4ca8 LDR.N R4, [PC, #0x2a0] ; g_memStart - 0x80041d8: 0x0020 MOVS R0, R4 - 0x80041da: 0xf7fd 0xf93e BL LOS_MemUsedNodeShow ; 0x800145a - 0x80041de: 0x2108 MOVS R1, #8 - 0x80041e0: 0x0020 MOVS R0, R4 - 0x80041e2: 0xf7fd 0xfbd9 BL LOS_MemAlloc ; 0x8001998 - 0x80041e6: 0x2108 MOVS R1, #8 - 0x80041e8: 0x0020 MOVS R0, R4 - 0x80041ea: 0xf7fd 0xfbd5 BL LOS_MemAlloc ; 0x8001998 - 0x80041ee: 0x0020 MOVS R0, R4 - 0x80041f0: 0xf7fd 0xf933 BL LOS_MemUsedNodeShow ; 0x800145a - 0x80041f4: 0xbd10 POP {R4, PC} - 0x80041f6: 0x0000 MOVS R0, R0 -``` - -其中,通过查找0x080041ee,就可以发现该内存节点是在MemLeakTest接口里申请的且是没有释放的。 - diff --git "a/zh-cn/device-dev/kernel/\345\206\205\345\255\230\347\256\241\347\220\206.md" "b/zh-cn/device-dev/kernel/\345\206\205\345\255\230\347\256\241\347\220\206.md" deleted file mode 100644 index fb44d9bd13..0000000000 --- "a/zh-cn/device-dev/kernel/\345\206\205\345\255\230\347\256\241\347\220\206.md" +++ /dev/null @@ -1,9 +0,0 @@ -# 内存管理 - -- **[基本概念](基本概念-4.md)** - -- **[静态内存](静态内存.md)** - -- **[动态内存](动态内存.md)** - - diff --git "a/zh-cn/device-dev/kernel/\345\206\205\345\255\230\350\260\203\346\265\213.md" "b/zh-cn/device-dev/kernel/\345\206\205\345\255\230\350\260\203\346\265\213.md" deleted file mode 100644 index 82555bc862..0000000000 --- "a/zh-cn/device-dev/kernel/\345\206\205\345\255\230\350\260\203\346\265\213.md" +++ /dev/null @@ -1,11 +0,0 @@ -# 内存调测 - -内存调测方法旨在辅助定位动态内存相关问题,提供了基础的动态内存池信息统计手段,向用户呈现内存池水线、碎片率等信息;提供了内存泄漏检测手段,方便用户准确定位存在内存泄漏的代码行,也可以辅助分析系统各个模块内存的使用情况;提供了踩内存检测手段,可以辅助定位越界踩内存的场景。 - -- **[内存信息统计](内存信息统计.md)** - -- **[内存泄漏检测](内存泄漏检测.md)** - -- **[踩内存检测](踩内存检测.md)** - - diff --git "a/zh-cn/device-dev/kernel/\345\206\205\346\240\270\350\260\203\346\265\213.md" "b/zh-cn/device-dev/kernel/\345\206\205\346\240\270\350\260\203\346\265\213.md" deleted file mode 100644 index 6b7080f2bc..0000000000 --- "a/zh-cn/device-dev/kernel/\345\206\205\346\240\270\350\260\203\346\265\213.md" +++ /dev/null @@ -1,9 +0,0 @@ -# 内核调测 - -- **[内存调测](内存调测.md)** - -- **[异常调测](异常调测.md)** - -- **[Trace调测](Trace调测.md)** - - diff --git "a/zh-cn/device-dev/kernel/\345\212\250\346\200\201\345\206\205\345\255\230.md" "b/zh-cn/device-dev/kernel/\345\212\250\346\200\201\345\206\205\345\255\230.md" deleted file mode 100644 index 05922df9f7..0000000000 --- "a/zh-cn/device-dev/kernel/\345\212\250\346\200\201\345\206\205\345\255\230.md" +++ /dev/null @@ -1,227 +0,0 @@ -# 动态内存 - -- [运行机制](#section328282013571) -- [开发指导](#section7921151015814) - - [使用场景](#section326917198583) - - [接口说明](#section1032331584) - - [开发流程](#section07271773592) - - [编程实例](#section84931234145913) - - [结果验证](#section165233233917) - - -## 运行机制 - -动态内存管理,即在内存资源充足的情况下,根据用户需求,从系统配置的一块比较大的连续内存(内存池,也是堆内存)中分配任意大小的内存块。当用户不需要该内存块时,又可以释放回系统供下一次使用。与静态内存相比,动态内存管理的优点是按需分配,缺点是内存池中容易出现碎片。 - -OpenHarmony LiteOS-M动态内存在TLSF算法的基础上,对区间的划分进行了优化,获得更优的性能,降低了碎片率。动态内存核心算法框图如下: - -**图 1** 动态内存核心算法 -![](figures/动态内存核心算法.png "动态内存核心算法") - -根据空闲内存块的大小,使用多个空闲链表来管理。根据内存空闲块大小分为两个部分:\[4, 127\]和\[27, 231\],如上图size class所示: - -1. 对\[4,127\]区间的内存进行等分,如上图绿色部分所示,分为31个小区间,每个小区间对应内存块大小为4字节的倍数。每个小区间对应一个空闲内存链表和用于标记对应空闲内存链表是否为空的一个比特位,值为1时,空闲链表非空。\[4,127\]区间的31个小区间内存对应31个比特位进行标记链表是否为空。 -2. 大于127字节的空闲内存块,按照2的次幂区间大小进行空闲链表管理。总共分为24个小区间,每个小区间又等分为8个二级小区间,见上图蓝色的Size Class和Size SubClass部分。每个二级小区间对应一个空闲链表和用于标记对应空闲内存链表是否为空的一个比特位。总共24\*8=192个二级小区间,对应192个空闲链表和192个比特位进行标记链表是否为空。 - -例如,当有40字节的空闲内存需要插入空闲链表时,对应小区间\[40,43\],第10个空闲链表,位图标记的第10比特位。把40字节的空闲内存挂载第10个空闲链表上,并判断是否需要更新位图标记。当需要申请40字节的内存时,根据位图标记获取存在满足申请大小的内存块的空闲链表,从空闲链表上获取空闲内存节点。如果分配的节点大于需要申请的内存大小,进行分割节点操作,剩余的节点重新挂载到相应的空闲链表上。当有580字节的空闲内存需要插入空闲链表时,对应二级小区间\[2^9,2^9+2^6\],第31+2\*8=47个空闲链表,并使用位图的第47个比特位来标记链表是否为空。把580字节的空闲内存挂载第47个空闲链表上,并判断是否需要更新位图标记。当需要申请580字节的内存时,根据位图标记获取存在满足申请大小的内存块的空闲链表,从空闲链表上获取空闲内存节点。如果分配的节点大于需要申请的内存大小,进行分割节点操作,剩余的节点重新挂载到相应的空闲链表上。如果对应的空闲链表为空,则向更大的内存区间去查询是否有满足条件的空闲链表,实际计算时,会一次性查找到满足申请大小的空闲链表。 - -内存管理结构如下图所示: - -**图 2** 动态内存管理结构图 -![](figures/动态内存管理结构图.png "动态内存管理结构图") - -- 内存池池头部分 - - 内存池池头部分包含内存池信息、位图标记数组和空闲链表数组。内存池信息包含内存池起始地址及堆区域总大小,内存池属性。位图标记数组有7个32位无符号整数组成,每个比特位标记对应的空闲链表是否挂载空闲内存块节点。空闲内存链表包含223个空闲内存头节点信息,每个空闲内存头节点信息维护内存节点头和空闲链表中的前驱、后继空闲内存节点。 - -- 内存池节点部分 - - 包含3种类型节点:未使用空闲内存节点,已使用内存节点和尾节点。每个内存节点维护一个前序指针,指向内存池中上一个内存节点,还维护内存节点的大小和使用标记。空闲内存节点和已使用内存节点后面的内存区域是数据域,尾节点没有数据域。 - - -## 开发指导 - -### 使用场景 - -动态内存管理的主要工作是动态分配并管理用户申请到的内存区间。动态内存管理主要用于用户需要使用大小不等的内存块的场景,当用户需要使用内存时,可以通过操作系统的动态内存申请函数索取指定大小的内存块,一旦使用完毕,通过动态内存释放函数归还所占用内存,使之可以重复使用。 - -### 接口说明 - -OpenHarmony LiteOS-M的动态内存管理主要为用户提供以下功能,接口详细信息可以查看API参考。 - -**表 1** 动态内存模块接口 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    功能分类

    -

    接口名

    -

    描述

    -

    初始化和删除内存池

    -

    LOS_MemInit

    -

    初始化一块指定的动态内存池,大小为size。

    -

    LOS_MemDeInit

    -

    删除指定内存池,仅打开LOSCFG_MEM_MUL_POOL时有效。

    -

    申请、释放动态内存

    -

    LOS_MemAlloc

    -

    从指定动态内存池中申请size长度的内存。

    -

    LOS_MemFree

    -

    释放从指定动态内存中申请的内存。

    -

    LOS_MemRealloc

    -

    按size大小重新分配内存块,并将原内存块内容拷贝到新内存块。如果新内存块申请成功,则释放原内存块。

    -

    LOS_MemAllocAlign

    -

    从指定动态内存池中申请长度为size且地址按boundary字节对齐的内存。

    -

    获取内存池信息

    -

    LOS_MemPoolSizeGet

    -

    获取指定动态内存池的总大小。

    -

    LOS_MemTotalUsedGet

    -

    获取指定动态内存池的总使用量大小。

    -

    LOS_MemInfoGet

    -

    获取指定内存池的内存结构信息,包括空闲内存大小、已使用内存大小、空闲内存块数量、已使用的内存块数量、最大的空闲内存块大小。

    -

    LOS_MemPoolList

    -

    打印系统中已初始化的所有内存池,包括内存池的起始地址、内存池大小、空闲内存总大小、已使用内存总大小、最大的空闲内存块大小、空闲内存块数量、已使用的内存块数量。仅打开LOSCFG_MEM_MUL_POOL时有效。

    -

    获取内存块信息

    -

    LOS_MemFreeNodeShow

    -

    打印指定内存池的空闲内存块的大小及数量。

    -

    LOS_MemUsedNodeShow

    -

    打印指定内存池的已使用内存块的大小及数量。

    -

    检查指定内存池的完整性

    -

    LOS_MemIntegrityCheck

    -

    对指定内存池做完整性检查,仅打开LOSCFG_BASE_MEM_NODE_INTEGRITY_CHECK时有效。

    -
    - ->![](public_sys-resources/icon-note.gif) **说明:** ->- 由于动态内存管理需要管理控制块数据结构来管理内存,这些数据结构会额外消耗内存,故实际用户可使用内存总量小于配置项OS\_SYS\_MEM\_SIZE的大小。 ->- 对齐分配内存接口LOS\_MemAllocAlign/LOS\_MemMallocAlign因为要进行地址对齐,可能会额外消耗部分内存,故存在一些遗失内存,当系统释放该对齐内存时,同时回收由于对齐导致的遗失内存。 - -### 开发流程 - -本节介绍使用动态内存的典型场景开发流程。 - -1. 初始化LOS\_MemInit。 - - 初始一个内存池后生成一个内存池控制头、尾节点EndNode,剩余的内存被标记为FreeNode内存节点。注:EndNode作为内存池末尾的节点,size为0。 - - -1. 申请任意大小的动态内存LOS\_MemAlloc。 - - 判断动态内存池中是否存在大于申请量大小的空闲内存块空间,若存在,则划出一块内存块,以指针形式返回,若不存在,返回NULL。如果空闲内存块大于申请量,需要对内存块进行分割,剩余的部分作为空闲内存块挂载到空闲内存链表上。 - - -1. 释放动态内存LOS\_MemFree。 - - 回收内存块,供下一次使用。调用LOS\_MemFree释放内存块,则会回收内存块,并且将其标记为FreeNode。在回收内存块时,相邻的FreeNode会自动合并。 - - -### 编程实例 - -本实例执行以下步骤: - -1. 初始化一个动态内存池。 -2. 从动态内存池中申请一个内存块。 -3. 在内存块中存放一个数据。 -4. 打印出内存块中的数据。 -5. 释放该内存块。 - -示例代码如下: - -``` -#include "los_memory.h" - -VOID Example_DynMem(VOID) -{ - UINT32 *mem = NULL; - UINT32 ret; - - /*初始化内存池*/ - ret = LOS_MemInit(g_testPool, TEST_POOL_SIZE); - if (LOS_OK == ret) { - printf("Mem init success!\n"); - } else { - printf("Mem init failed!\n"); - return; - } - - /*分配内存*/ - mem = (UINT32 *)LOS_MemAlloc(g_testPool, 4); - if (NULL == mem) { - printf("Mem alloc failed!\n"); - return; - } - printf("Mem alloc success!\n"); - - /*赋值*/ - *mem = 828; - printf("*mem = %d\n", *mem); - - /*释放内存*/ - ret = LOS_MemFree(g_testPool, mem); - if (LOS_OK == ret) { - printf("Mem free success!\n"); - } else { - printf("Mem free failed!\n"); - } - - return; -} -``` - -### 结果验证 - -输出结果如下: - -``` -Mem init success! -Mem alloc success! -*mem = 828 -Mem free success! -``` - diff --git "a/zh-cn/device-dev/kernel/\345\217\214\345\220\221\351\223\276\350\241\250.md" "b/zh-cn/device-dev/kernel/\345\217\214\345\220\221\351\223\276\350\241\250.md" deleted file mode 100644 index 8b9323d618..0000000000 --- "a/zh-cn/device-dev/kernel/\345\217\214\345\220\221\351\223\276\350\241\250.md" +++ /dev/null @@ -1,191 +0,0 @@ -# 双向链表 - -- [基本概念](#section1990715203418) -- [功能说明](#section848334511411) -- [开发流程](#section01781261552) -- [编程实例](#section67569495514) - - [实例描述](#section48761994551) - - [示例代码](#section1280202685519) - - [结果验证](#section5811249105512) - - -## 基本概念 - -双向链表是指含有往前和往后两个方向的链表,即每个结点中除存放下一个节点指针外,还增加一个指向前一个节点的指针。其头指针head是唯一确定的。 - -从双向链表中的任意一个结点开始,都可以很方便地访问它的前驱结点和后继结点,这种数据结构形式使得双向链表在查找时更加方便,特别是大量数据的遍历。由于双向链表具有对称性,能方便地完成各种插入、删除等操作,但需要注意前后方向的操作。 - -## 功能说明 - -双向链表模块为用户提供下面几种功能,接口详细信息可以查看API参考。 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    功能分类

    -

    接口名

    -

    描述

    -

    初始化链表

    -

    LOS_ListInit

    -

    将指定双向链表节点初始化为双向链表

    -

    LOS_DL_LIST_HEAD

    -

    定义一个双向链表节点并以该节点初始化为双向链表

    -

    增加节点

    -

    LOS_ListAdd

    -

    将指定节点插入到双向链表头端

    -

    LOS_ListTailInsert

    -

    将指定节点插入到双向链表尾端

    -

    删除节点

    -

    LOS_ListDelete

    -

    将指定节点从链表中删除

    -

    LOS_ListDelInit

    -

    将指定节点从链表中删除,并使用该节点初始化链表

    -

    判断双向链表是否为空

    -

    LOS_ListEmpty

    -

    判断链表是否为空

    -

    获取结构体信息

    -

    LOS_DL_LIST_ENTRY

    -

    获取包含链表的结构体地址,接口的第一个入参表示的是链表中的某个节点,第二个入参是要获取的结构体名称,第三个入参是链表在该结构体中的名称

    -

    LOS_OFF_SET_OF

    -

    获取指定结构体内的成员相对于结构体起始地址的偏移量

    -

    遍历双向链表

    -

    LOS_DL_LIST_FOR_EACH

    -

    遍历双向链表

    -

    LOS_DL_LIST_FOR_EACH_SAFE

    -

    遍历双向链表,并存储当前节点的后继节点用于安全校验

    -

    遍历包含双向链表的结构体

    -

    LOS_DL_LIST_FOR_EACH_ENTRY

    -

    遍历指定双向链表,获取包含该链表节点的结构体地址

    -

    LOS_DL_LIST_FOR_EACH_ENTRY_SAFE

    -

    遍历指定双向链表,获取包含该链表节点的结构体地址,并存储包含当前节点的后继节点的结构体地址

    -
    - -## 开发流程 - -双向链表的典型开发流程: - -1. 调用LOS\_ListInit/LOS\_DL\_LIST\_HEAD初始双向链表。 -2. 调用LOS\_ListAdd向链表插入节点。 -3. 调用LOS\_ListTailInsert向链表尾部插入节点。 -4. 调用LOS\_ListDelete删除指定节点。 -5. 调用LOS\_ListEmpty判断链表是否为空。 -6. 调用LOS\_ListDelInit删除指定节点并以此节点初始化链表。 - ->![](public_sys-resources/icon-note.gif) **说明:** ->- 需要注意节点指针前后方向的操作。 ->- 链表操作接口,为底层接口,不对入参进行判空,需要使用者确保传参合法。 ->- 如果链表节点的内存是动态申请的,删除节点时,要注意释放内存。 - -## 编程实例 - -### 实例描述 - -本实例实现如下功能: - -1. 初始化双向链表。 -2. 增加节点。 -3. 删除节点。 -4. 测试操作是否成功。 - -### 示例代码 - -示例代码如下: - -``` -#include "stdio.h" -#include "los_list.h" - -static UINT32 ListSample(VOID) -{ - LOS_DL_LIST listHead = {NULL,NULL}; - LOS_DL_LIST listNode1 = {NULL,NULL}; - LOS_DL_LIST listNode2 = {NULL,NULL}; - - //首先初始化链表 - printf("Initial head\n"); - LOS_ListInit(&listHead); - - //添加节点1和节点2,并校验他们的相互关系 - LOS_ListAdd(&listHead, &listNode1); - if (listNode1.pstNext == &listHead && listNode1.pstPrev == &listHead) { - printf("Add listNode1 success\n"); - } - - LOS_ListTailInsert(&listHead, &listNode2); - if (listNode2.pstNext == &listHead && listNode2.pstPrev == &listNode1) { - printf("Tail insert listNode2 success\n"); - } - - //删除两个节点 - LOS_ListDelete(&listNode1); - LOS_ListDelete(&listNode2); - - //确认链表为空 - if (LOS_ListEmpty(&listHead)) { - printf("Delete success\n"); - } - - return LOS_OK; -} -``` - -### 结果验证 - -编译运行得到的结果为: - -``` -Initial head -Add listNode1 success -Tail insert listNode2 success -Delete success -``` - diff --git "a/zh-cn/device-dev/kernel/\345\237\272\346\234\254\346\225\260\346\215\256\347\273\223\346\236\204.md" "b/zh-cn/device-dev/kernel/\345\237\272\346\234\254\346\225\260\346\215\256\347\273\223\346\236\204.md" deleted file mode 100644 index 5464ca3cee..0000000000 --- "a/zh-cn/device-dev/kernel/\345\237\272\346\234\254\346\225\260\346\215\256\347\273\223\346\236\204.md" +++ /dev/null @@ -1,5 +0,0 @@ -# 基本数据结构 - -- **[双向链表](双向链表.md)** - - diff --git "a/zh-cn/device-dev/kernel/\345\237\272\346\234\254\346\246\202\345\277\265-11.md" "b/zh-cn/device-dev/kernel/\345\237\272\346\234\254\346\246\202\345\277\265-11.md" deleted file mode 100644 index dd72ce5e10..0000000000 --- "a/zh-cn/device-dev/kernel/\345\237\272\346\234\254\346\246\202\345\277\265-11.md" +++ /dev/null @@ -1,53 +0,0 @@ -# 基本概念 - -- [运行机制](#section1794010261861) - - [信号量控制块](#section11372149164815) - - [信号量运作原理](#section139726510491) - - -信号量(Semaphore)是一种实现任务间通信的机制,可以实现任务间同步或共享资源的互斥访问。 - -一个信号量的数据结构中,通常有一个计数值,用于对有效资源数的计数,表示剩下的可被使用的共享资源数,其值的含义分两种情况: - -- 0,表示该信号量当前不可获取,因此可能存在正在等待该信号量的任务。 -- 正值,表示该信号量当前可被获取。 - -以同步为目的的信号量和以互斥为目的的信号量在使用上有如下不同: - -- 用作互斥时,初始信号量计数值不为0,表示可用的共享资源个数。在需要使用共享资源前,先获取信号量,然后使用一个共享资源,使用完毕后释放信号量。这样在共享资源被取完,即信号量计数减至0时,其他需要获取信号量的任务将被阻塞,从而保证了共享资源的互斥访问。另外,当共享资源数为1时,建议使用二值信号量,一种类似于互斥锁的机制。 -- 用作同步时,初始信号量计数值为0。任务1获取信号量而阻塞,直到任务2或者某中断释放信号量,任务1才得以进入Ready或Running态,从而达到了任务间的同步。 - -## 运行机制 - -### 信号量控制块 - -``` -/** - * 信号量控制块数据结构 - */ -typedef struct { - UINT16 semStat; /* 信号量状态 */ - UINT16 semType; /* 信号量类型 */ - UINT16 semCount; /* 信号量计数 */ - UINT16 semId; /* 信号量索引号 */ - LOS_DL_LIST semList; /* 挂接阻塞于该信号量的任务 */ -} LosSemCB; -``` - -### 信号量运作原理 - -信号量初始化,为配置的N个信号量申请内存(N值可以由用户自行配置,通过LOSCFG\_BASE\_IPC\_SEM\_LIMIT宏实现),并把所有信号量初始化成未使用,加入到未使用链表中供系统使用。 - -信号量创建,从未使用的信号量链表中获取一个信号量,并设定初值。 - -信号量申请,若其计数器值大于0,则直接减1返回成功。否则任务阻塞,等待其它任务释放该信号量,等待的超时时间可设定。当任务被一个信号量阻塞时,将该任务挂到信号量等待任务队列的队尾。 - -信号量释放,若没有任务等待该信号量,则直接将计数器加1返回。否则唤醒该信号量等待任务队列上的第一个任务。 - -信号量删除,将正在使用的信号量置为未使用信号量,并挂回到未使用链表。 - -信号量允许多个任务在同一时刻访问共享资源,但会限制同一时刻访问此资源的最大任务数目。当访问资源的任务数达到该资源允许的最大数量时,会阻塞其他试图获取该资源的任务,直到有任务释放该信号量。 - -**图 1** 信号量运作示意图 -![](figures/信号量运作示意图.png "信号量运作示意图") - diff --git "a/zh-cn/device-dev/kernel/\345\237\272\346\234\254\346\246\202\345\277\265-2.md" "b/zh-cn/device-dev/kernel/\345\237\272\346\234\254\346\246\202\345\277\265-2.md" deleted file mode 100644 index db5ae0ccd5..0000000000 --- "a/zh-cn/device-dev/kernel/\345\237\272\346\234\254\346\246\202\345\277\265-2.md" +++ /dev/null @@ -1,96 +0,0 @@ -# 基本概念 - -- [任务相关概念](#section673132352511) -- [任务运行机制](#section176294469251) - -从系统角度看,任务是竞争系统资源的最小运行单元。任务可以使用或等待CPU、使用内存空间等系统资源,并独立于其它任务运行。 - -OpenHarmony LiteOS-M的任务模块可以给用户提供多个任务,实现任务间的切换,帮助用户管理业务程序流程。任务模块具有如下特性: - -- 支持多任务。 -- 一个任务表示一个线程。 -- 抢占式调度机制,高优先级的任务可打断低优先级任务,低优先级任务必须在高优先级任务阻塞或结束后才能得到调度。 -- 相同优先级任务支持时间片轮转调度方式。 -- 共有32个优先级\[0-31\],最高优先级为0,最低优先级为31。 - -## 任务相关概念 - -**任务状态** - -任务有多种运行状态。系统初始化完成后,创建的任务就可以在系统中竞争一定的资源,由内核进行调度。 - -任务状态通常分为以下四种: - -- 就绪(Ready):该任务在就绪队列中,只等待CPU。 -- 运行(Running):该任务正在执行。 -- 阻塞(Blocked):该任务不在就绪队列中。包含任务被挂起(suspend状态)、任务被延时(delay状态)、任务正在等待信号量、读写队列或者等待事件等。 -- 退出态(Dead):该任务运行结束,等待系统回收资源。 - -**任务状态迁移** - -**图 1** 任务状态示意图 -![](figures/任务状态示意图.png "任务状态示意图") - -**任务状态迁移说明:** - -- 就绪态→运行态 - - 任务创建后进入就绪态,发生任务切换时,就绪队列中最高优先级的任务被执行,从而进入运行态,同时该任务从就绪队列中移出。 - -- 运行态→阻塞态 - - 正在运行的任务发生阻塞(挂起、延时、读信号量等)时,该任务会从就绪队列中删除,任务状态由运行态变成阻塞态,然后发生任务切换,运行就绪队列中最高优先级任务。 - -- 阻塞态→就绪态(阻塞态→运行态) - - 阻塞的任务被恢复后(任务恢复、延时时间超时、读信号量超时或读到信号量等),此时被恢复的任务会被加入就绪队列,从而由阻塞态变成就绪态;此时如果被恢复任务的优先级高于正在运行任务的优先级,则会发生任务切换,该任务由就绪态变成运行态。 - -- 就绪态→阻塞态 - - 任务也有可能在就绪态时被阻塞(挂起),此时任务状态由就绪态变为阻塞态,该任务从就绪队列中删除,不会参与任务调度,直到该任务被恢复。 - -- 运行态→就绪态 - - 有更高优先级任务创建或者恢复后,会发生任务调度,此刻就绪队列中最高优先级任务变为运行态,那么原先运行的任务由运行态变为就绪态,依然在就绪队列中。 - -- 运行态→退出态 - - 运行中的任务运行结束,任务状态由运行态变为退出态。退出态包含任务运行结束的正常退出状态以及Invalid状态。例如,任务运行结束但是没有自删除,对外呈现的就是Invalid状态,即退出态。 - -- 阻塞态→退出态 - - 阻塞的任务调用删除接口,任务状态由阻塞态变为退出态。 - - -**任务ID** - -任务ID,在任务创建时通过参数返回给用户,是任务的重要标识。系统中的ID号是唯一的。用户可以通过任务ID对指定任务进行任务挂起、任务恢复、查询任务名等操作。 - -**任务优先级** - -优先级表示任务执行的优先顺序。任务的优先级决定了在发生任务切换时即将要执行的任务,就绪队列中最高优先级的任务将得到执行。 - -**任务入口函数** - -新任务得到调度后将执行的函数。该函数由用户实现,在任务创建时,通过任务创建结构体设置。 - -**任务栈** - -每个任务都拥有一个独立的栈空间,我们称为任务栈。栈空间里保存的信息包含局部变量、寄存器、函数参数、函数返回地址等。 - -**任务上下文** - -任务在运行过程中使用的一些资源,如寄存器等,称为任务上下文。当这个任务挂起时,其他任务继续执行,可能会修改寄存器等资源中的值。如果任务切换时没有保存任务上下文,可能会导致任务恢复后出现未知错误。因此在任务切换时会将切出任务的任务上下文信息,保存在自身的任务栈中,以便任务恢复后,从栈空间中恢复挂起时的上下文信息,从而继续执行挂起时被打断的代码。 - -**任务控制块TCB** - -每个任务都含有一个任务控制块\(TCB\)。TCB包含了任务上下文栈指针(stack pointer)、任务状态、任务优先级、任务ID、任务名、任务栈大小等信息。TCB可以反映出每个任务运行情况。 - -**任务切换** - -任务切换包含获取就绪队列中最高优先级任务、切出任务上下文保存、切入任务上下文恢复等动作。 - -## 任务运行机制 - -用户创建任务时,系统会初始化任务栈,预置上下文。此外,系统还会将“任务入口函数”地址放在相应位置。这样在任务第一次启动进入运行态时,将会执行“任务入口函数”。 - diff --git "a/zh-cn/device-dev/kernel/\345\237\272\346\234\254\346\246\202\345\277\265-21.md" "b/zh-cn/device-dev/kernel/\345\237\272\346\234\254\346\246\202\345\277\265-21.md" deleted file mode 100644 index 310f6014ea..0000000000 --- "a/zh-cn/device-dev/kernel/\345\237\272\346\234\254\346\246\202\345\277\265-21.md" +++ /dev/null @@ -1,82 +0,0 @@ -# 基本概念 - -- [运行机制](#section10284121317365) - - [日志方式](#section13804114513361) - - [Cow机制](#section172771130193610) - - [lfs掉电保护](#section42941021173614) - - -LittleFS主要用在微控制器和flash上,是一种嵌入式文件系统,具有如下3个特点: - -1. 掉电恢复 - - 在写入时即使复位或者掉电也可以恢复到上一个正确的状态。 - -2. 擦写均衡 - - 有效延长flash的使用寿命。 - -3. 有限的RAM/ROM - - 节省ROM和RAM空间。 - - -## 运行机制 - -最经典的掉电保护方法有两种,一种是使用日志,一种是通过COW方式。lfs结合了两种方法,并优化了两种方案的缺点,提供了一套掉电保护策略 - -### 日志方式 - -![](figures/zh-cn_image_0000001124310992.png) - -具体步骤为: - -1. 写入数据之前,先在日志区存储开始标志,记录要写入的数据位置和大小; -2. 待写入的数据写入日志区; -3. 待写入的数据写入数据区; -4. 写入完成之后,在日志区记录结束标志。 - -模拟掉电场景: - -1. 步骤1完成,步骤2没有完成;重启之后,保持原来的数据,日志无效; -2. 步骤1,2完成了,步骤3没有完成,尝试把步骤2的数据写入到数据区; -3. 步骤1,2,3完成了,步骤4没有完成,同样尝试把步骤2的数据写入到数据区; - -### Cow机制 - -![](figures/zh-cn_image_0000001170790681.png) - -具体步骤为: - -1. 想更新节点F的数据,先申请一个新的节点,把F的旧数据拷贝过去,然后更新新的数据; -2. 把父节点的指针指向新的节点,去掉旧节点的指针。 - -模拟掉电场景: - -步骤1完成了,步骤2没有完成,则使用旧的数据,新的节点变成孤儿节点。 - -### lfs掉电保护 - -fs结合了日志方式和COW机制两种方式进行掉电保护,并且优化了两种方案。 - -前面谈过文件系统三要素,超级块,inode,以及数据。对应lfs来说,他把超级块以及inode通过日志的方式存储,两种采用统一的存储结构,后文称两者为元数据;普通数据则采用cow的方式存储,采用czt逆序链表的方式。 - -![](figures/zh-cn_image_0000001124307264.png) - -**元数据的存储** - -![](figures/zh-cn_image_0000001124147160.png) - -元数据(对应root,dir)采用双block的方式存储,互为备份,每个block都有一个revision序号,值越大,表示block的数据越新,每个block默认可以存储最多0xff个文件的数据,如果超过这个值,则需要compact(压缩)。 - -Compact是干什么呢? 即当数据的大小大于某个值的时候,把数据整合,剔除同一个id的旧的数据,然后写入到备份block里面。 - -**普通数据的存储** - -Lfs的数据采用链表的方式逆向管理。 - -![](figures/zh-cn_image_0000001124306828.png) - -1. 采用逆向的指针,这样常规的追加数据,不需要额外的开销来重新建立所有的索引; -2. 每个偶数block有多个指针,指向更远的数据,这样可以在检索的时候加快速度。 - diff --git "a/zh-cn/device-dev/kernel/\345\237\272\346\234\254\346\246\202\345\277\265-5.md" "b/zh-cn/device-dev/kernel/\345\237\272\346\234\254\346\246\202\345\277\265-5.md" deleted file mode 100644 index a96f943c8d..0000000000 --- "a/zh-cn/device-dev/kernel/\345\237\272\346\234\254\346\246\202\345\277\265-5.md" +++ /dev/null @@ -1,52 +0,0 @@ -# 基本概念 - -- [运行机制](#section1735611583011) - - [事件控制块](#section1161415384467) - - [事件运作原理](#section187761153144617) - - -事件(Event)是一种任务间的通信机制,可用于任务间的同步操作。事件的特点是: - -- 任务间的事件同步,可以一对多,也可以多对多。一对多表示一个任务可以等待多个事件,多对多表示多个任务可以等待多个事件。但是一次写事件最多触发一个任务从阻塞中醒来。 -- 事件读超时机制。 -- 只做任务间同步,不传输具体数据。 - -提供了事件初始化、事件读写、事件清零、事件销毁等接口。 - -## 运行机制 - -### 事件控制块 - -``` -/** - * 事件控制块数据结构 - */ -typedef struct tagEvent { - UINT32 uwEventID; /* 事件集合,表示已经处理(写入和清零)的事件集合 */ - LOS_DL_LIST stEventList; /* 等待特定事件的任务链表 */ -} EVENT_CB_S, *PEVENT_CB_S; -``` - -### 事件运作原理 - -**事件初始化:**会创建一个事件控制块,该控制块维护一个已处理的事件集合,以及等待特定事件的任务链表。 - -**写事件:**会向事件控制块写入指定的事件,事件控制块更新事件集合,并遍历任务链表,根据任务等待具体条件满足情况决定是否唤醒相关任务。 - -**读事件:**如果读取的事件已存在时,会直接同步返回。其他情况会根据超时时间以及事件触发情况,来决定返回时机:等待的事件条件在超时时间耗尽之前到达,阻塞任务会被直接唤醒,否则超时时间耗尽该任务才会被唤醒。 - -读事件条件满足与否取决于入参eventMask和mode,eventMask即需要关注的事件。mode是具体处理方式,分以下三种情况: - -LOS\_WAITMODE\_AND:表示eventMask中所有事件都发生时,才返回。 - -LOS\_WAITMODE\_OR:表示eventMask中任何事件发生时,就返回。 - -LOS\_WAITMODE\_CLR:事件读取成功后,对应读取到的事件会被清零。需要配合LOS\_WAITMODE\_AND或者LOS\_WAITMODE\_OR来使用。 - -**事件清零:**根据指定掩码,去对事件控制块的事件集合进行清零操作。当掩码为0时,表示将事件集合全部清零。当掩码为0xffff时,表示不清除任何事件,保持事件集合原状。 - -**事件销毁:**销毁指定的事件控制块。 - -**图 1** 事件运作原理图 -![](figures/事件运作原理图.png "事件运作原理图") - diff --git "a/zh-cn/device-dev/kernel/\345\237\272\346\234\254\346\246\202\345\277\265-7.md" "b/zh-cn/device-dev/kernel/\345\237\272\346\234\254\346\246\202\345\277\265-7.md" deleted file mode 100644 index 4989a0b93e..0000000000 --- "a/zh-cn/device-dev/kernel/\345\237\272\346\234\254\346\246\202\345\277\265-7.md" +++ /dev/null @@ -1,19 +0,0 @@ -# 基本概念 - -- [运行机制](#section115161649726) - -互斥锁又称互斥型信号量,是一种特殊的二值性信号量,用于实现对共享资源的独占式处理。 - -任意时刻互斥锁的状态只有两种,开锁或闭锁。当有任务持有时,互斥锁处于闭锁状态,这个任务获得该互斥锁的所有权。当该任务释放它时,该互斥锁被开锁,任务失去该互斥锁的所有权。当一个任务持有互斥锁时,其他任务将不能再对该互斥锁进行开锁或持有。 - -多任务环境下往往存在多个任务竞争同一共享资源的应用场景,互斥锁可被用于对共享资源的保护从而实现独占式访问。另外互斥锁可以解决信号量存在的优先级翻转问题。 - -## 运行机制 - -多任务环境下会存在多个任务访问同一公共资源的场景,而有些公共资源是非共享的,需要任务进行独占式处理。互斥锁怎样来避免这种冲突呢? - -用互斥锁处理非共享资源的同步访问时,如果有任务访问该资源,则互斥锁为加锁状态。此时其他任务如果想访问这个公共资源则会被阻塞,直到互斥锁被持有该锁的任务释放后,其他任务才能重新访问该公共资源,此时互斥锁再次上锁,如此确保同一时刻只有一个任务正在访问这个公共资源,保证了公共资源操作的完整性。 - -**图 1** 互斥锁运作示意图 -![](figures/互斥锁运作示意图.png "互斥锁运作示意图") - diff --git "a/zh-cn/device-dev/kernel/\345\237\272\346\234\254\346\246\202\345\277\265-9.md" "b/zh-cn/device-dev/kernel/\345\237\272\346\234\254\346\246\202\345\277\265-9.md" deleted file mode 100644 index 90541dda60..0000000000 --- "a/zh-cn/device-dev/kernel/\345\237\272\346\234\254\346\246\202\345\277\265-9.md" +++ /dev/null @@ -1,67 +0,0 @@ -# 基本概念 - -- [运行机制](#section1582619446311) - - [队列控制块](#section1648304614720) - - [队列运作原理](#section15384012164811) - - -队列又称消息队列,是一种常用于任务间通信的数据结构。队列接收来自任务或中断的不固定长度消息,并根据不同的接口确定传递的消息是否存放在队列空间中。 - -任务能够从队列里面读取消息,当队列中的消息为空时,挂起读取任务;当队列中有新消息时,挂起的读取任务被唤醒并处理新消息。任务也能够往队列里写入消息,当队列已经写满消息时,挂起写入任务;当队列中有空闲消息节点时,挂起的写入任务被唤醒并写入消息。 - -可以通过调整读队列和写队列的超时时间来调整读写接口的阻塞模式,如果将读队列和写队列的超时时间设置为0,就不会挂起任务,接口会直接返回,这就是非阻塞模式。反之,如果将都队列和写队列的超时时间设置为大于0的时间,就会以阻塞模式运行。 - -消息队列提供了异步处理机制,允许将一个消息放入队列,但不立即处理。同时队列还有缓冲消息的作用,可以使用队列实现任务异步通信,队列具有如下特性: - -- 消息以先进先出的方式排队,支持异步读写。 -- 读队列和写队列都支持超时机制。 -- 每读取一条消息,就会将该消息节点设置为空闲。 -- 发送消息类型由通信双方约定,可以允许不同长度(不超过队列的消息节点大小)的消息。 -- 一个任务能够从任意一个消息队列接收和发送消息。 -- 多个任务能够从同一个消息队列接收和发送消息。 -- 创建队列时所需的队列空间,接口内系统自行动态申请内存。 - -## 运行机制 - -### 队列控制块 - -``` -/** - * 队列控制块数据结构 - */ -typedef struct -{ - UINT8 *queue; /* 队列消息内存空间的指针 */ - UINT16 queueState; /* 队列状态 */ - UINT16 queueLen; /* 队列中消息节点个数,即队列长度 */ - UINT16 queueSize; /* 消息节点大小 */ - UINT16 queueID; /* 队列ID */ - UINT16 queueHead; /* 消息头节点位置(数组下标)*/ - UINT16 queueTail; /* 消息尾节点位置(数组下标)*/ - UINT16 readWriteableCnt[OS_READWRITE_LEN]; /* 数组下标0的元素表示队列中可读消息数, - 数组下标1的元素表示队列中可写消息数 */ - LOS_DL_LIST readWriteList[OS_READWRITE_LEN]; /* 读取或写入消息的任务等待链表, - 下标0:读取链表,下标1:写入链表 */ - LOS_DL_LIST memList; /* 内存块链表 */ -} LosQueueCB; -``` - -每个队列控制块中都含有队列状态,表示该队列的使用情况: - -- OS\_QUEUE\_UNUSED:队列未被使用。 -- OS\_QUEUE\_INUSED:队列被使用中。 - -### 队列运作原理 - -- 创建队列时,创建队列成功会返回队列ID。 -- 在队列控制块中维护着一个消息头节点位置Head和一个消息尾节点位置Tail,用于表示当前队列中消息的存储情况。Head表示队列中被占用的消息节点的起始位置。Tail表示被占用的消息节点的结束位置,也是空闲消息节点的起始位置。队列刚创建时,Head和Tail均指向队列起始位置。 -- 写队列时,根据readWriteableCnt\[1\]判断队列是否可以写入,不能对已满(readWriteableCnt\[1\]为0)队列进行写操作。写队列支持两种写入方式:向队列尾节点写入,也可以向队列头节点写入。尾节点写入时,根据Tail找到起始空闲消息节点作为数据写入对象,如果Tail已经指向队列尾部则采用回卷方式。头节点写入时,将Head的前一个节点作为数据写入对象,如果Head指向队列起始位置则采用回卷方式。 -- 读队列时,根据readWriteableCnt\[0\]判断队列是否有消息需要读取,对全部空闲(readWriteableCnt\[0\]为0)队列进行读操作会引起任务挂起。如果队列可以读取消息,则根据Head找到最先写入队列的消息节点进行读取。如果Head已经指向队列尾部则采用回卷方式。 -- 删除队列时,根据队列ID找到对应队列,把队列状态置为未使用,把队列控制块置为初始状态,并释放队列所占内存。 - -图 1 队列读写数据操作示意图 - -![](figures/zh-cn_image_0000001124146302.png) - -上图对读写队列做了示意,图中只画了尾节点写入方式,没有画头节点写入,但是两者是类似的。 - diff --git "a/zh-cn/device-dev/kernel/\345\237\272\347\241\200\345\206\205\346\240\270-1.md" "b/zh-cn/device-dev/kernel/\345\237\272\347\241\200\345\206\205\346\240\270-1.md" deleted file mode 100644 index df2416afdc..0000000000 --- "a/zh-cn/device-dev/kernel/\345\237\272\347\241\200\345\206\205\346\240\270-1.md" +++ /dev/null @@ -1,15 +0,0 @@ -# 基础内核 - -- **[中断管理](中断管理.md)** - -- **[任务管理](任务管理.md)** - -- **[内存管理](内存管理.md)** - -- **[IPC](IPC.md)** - -- **[时间管理](时间管理.md)** - -- **[软件定时器](软件定时器.md)** - - diff --git "a/zh-cn/device-dev/kernel/\345\237\272\347\241\200\345\206\205\346\240\270.md" "b/zh-cn/device-dev/kernel/\345\237\272\347\241\200\345\206\205\346\240\270.md" deleted file mode 100644 index 94b43451a9..0000000000 --- "a/zh-cn/device-dev/kernel/\345\237\272\347\241\200\345\206\205\346\240\270.md" +++ /dev/null @@ -1,11 +0,0 @@ -# 基础内核 - -- **[进程](进程.md)** - -- **[线程](线程.md)** - -- **[内存](内存.md)** - -- **[网络](网络.md)** - - diff --git "a/zh-cn/device-dev/kernel/\345\260\217\345\236\213\347\263\273\347\273\237\345\206\205\346\240\270.md" "b/zh-cn/device-dev/kernel/\345\260\217\345\236\213\347\263\273\347\273\237\345\206\205\346\240\270.md" deleted file mode 100644 index d248439963..0000000000 --- "a/zh-cn/device-dev/kernel/\345\260\217\345\236\213\347\263\273\347\273\237\345\206\205\346\240\270.md" +++ /dev/null @@ -1,15 +0,0 @@ -# 小型系统内核 - -- **[认识LiteOS-M内核](认识LiteOS-M内核.md)** - -- **[快速入门](快速入门.md)** - -- **[基础内核](基础内核-1.md)** - -- **[扩展组件](扩展组件.md)** - -- **[内核调测](内核调测.md)** - -- **[附录](附录.md)** - - diff --git "a/zh-cn/device-dev/kernel/\345\274\200\345\217\221\346\214\207\345\257\274-10.md" "b/zh-cn/device-dev/kernel/\345\274\200\345\217\221\346\214\207\345\257\274-10.md" deleted file mode 100644 index c521fd755d..0000000000 --- "a/zh-cn/device-dev/kernel/\345\274\200\345\217\221\346\214\207\345\257\274-10.md" +++ /dev/null @@ -1,199 +0,0 @@ -# 开发指导 - -- [接口说明](#section158501652121514) -- [开发流程](#section783435801510) -- [编程实例](#section460018317164) - - [实例描述](#section2148236125814) - - [示例代码](#section121451047155716) - - [结果验证](#section2742182082117) - - -## 接口说明 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    功能分类

    -

    接口名

    -

    描述

    -

    创建/删除消息队列

    -

    LOS_QueueCreate

    -

    创建一个消息队列,由系统动态申请队列空间。

    -

    LOS_QueueDelete

    -

    根据队列ID删除一个指定队列。

    -

    读/写队列(不带拷贝)

    -

    LOS_QueueRead

    -

    读取指定队列头节点中的数据(队列节点中的数据实际上是一个地址)。

    -

    LOS_QueueWrite

    -

    向指定队列尾节点中写入入参bufferAddr的值(即buffer的地址)。

    -

    LOS_QueueWriteHead

    -

    向指定队列头节点中写入入参bufferAddr的值(即buffer的地址)。

    -

    读/写队列(带拷贝)

    -

    LOS_QueueReadCopy

    -

    读取指定队列头节点中的数据。

    -

    LOS_QueueWriteCopy

    -

    向指定队列尾节点中写入入参bufferAddr中保存的数据。

    -

    LOS_QueueWriteHeadCopy

    -

    向指定队列头节点中写入入参bufferAddr中保存的数据。

    -

    获取队列信息

    -

    LOS_QueueInfoGet

    -

    获取指定队列的信息,包括队列ID、队列长度、消息节点大小、头节点、尾节点、可读节点数量、可写节点数量、等待读操作的任务、等待写操作的任务。

    -
    - -## 开发流程 - -1. 用LOS\_QueueCreate创建队列。创建成功后,可以得到队列ID。 -2. 通过LOS\_QueueWrite或者LOS\_QueueWriteCopy写队列。 -3. 通过LOS\_QueueRead或者LOS\_QueueReadCopy读队列。 -4. 通过LOS\_QueueInfoGet获取队列信息。 -5. 通过LOS\_QueueDelete删除队列。 - ->![](public_sys-resources/icon-note.gif) **说明:** ->- 系统支持的最大队列数是指:整个系统的队列资源总个数,而非用户能使用的个数。例如:系统软件定时器多占用一个队列资源,那么用户能使用的队列资源就会减少一个。 ->- 创建队列时传入的队列名和flags暂时未使用,作为以后的预留参数。 ->- 队列接口函数中的入参timeOut是相对时间。 ->- LOS\_QueueReadCopy和LOS\_QueueWriteCopy及LOS\_QueueWriteHeadCopy是一组接口,LOS\_QueueRead和LOS\_QueueWrite及LOS\_QueueWriteHead是一组接口,每组接口需要配套使用。 ->- 鉴于LOS\_QueueWrite和LOS\_QueueWriteHead和LOS\_QueueRead这组接口实际操作的是数据地址,用户必须保证调用LOS\_QueueRead获取到的指针所指向的内存区域在读队列期间没有被异常修改或释放,否则可能导致不可预知的后果。 ->- 鉴于LOS\_QueueWrite和LOS\_QueueWriteHead和LOS\_QueueRead这组接口实际操作的是数据地址,也就意味着实际写和读的消息长度仅仅是一个指针数据,因此用户使用这组接口之前,需确保创建队列时的消息节点大小,为一个指针的长度,避免不必要的浪费和读取失败。 - -## 编程实例 - -### 实例描述 - -创建一个队列,两个任务。任务1调用写队列接口发送消息,任务2通过读队列接口接收消息。 - -1. 通过LOS\_TaskCreate创建任务1和任务2。 -2. 通过LOS\_QueueCreate创建一个消息队列。 -3. 在任务1 SendEntry中发送消息。 -4. 在任务2 RecvEntry中接收消息。 -5. 通过LOS\_QueueDelete删除队列。 - -### 示例代码 - -示例代码如下: - -``` -#include "los_task.h" -#include "los_queue.h" -static UINT32 g_queue; -#define BUFFER_LEN 50 - -VOID SendEntry(VOID) -{ - UINT32 ret = 0; - CHAR abuf[] = "test message"; - UINT32 len = sizeof(abuf); - - ret = LOS_QueueWriteCopy(g_queue, abuf, len, 0); - if(ret != LOS_OK) { - printf("send message failure, error: %x\n", ret); - } -} - -VOID RecvEntry(VOID) -{ - UINT32 ret = 0; - CHAR readBuf[BUFFER_LEN] = {0}; - UINT32 readLen = BUFFER_LEN; - - //休眠1s - usleep(1000000); - ret = LOS_QueueReadCopy(g_queue, readBuf, &readLen, 0); - if(ret != LOS_OK) { - printf("recv message failure, error: %x\n", ret); - } - - printf("recv message: %s\n", readBuf); - - ret = LOS_QueueDelete(g_queue); - if(ret != LOS_OK) { - printf("delete the queue failure, error: %x\n", ret); - } - - printf("delete the queue success!\n"); -} - -UINT32 ExampleQueue(VOID) -{ - printf("start queue example\n"); - UINT32 ret = 0; - UINT32 task1, task2; - TSK_INIT_PARAM_S initParam = {0}; - - initParam.pfnTaskEntry = (TSK_ENTRY_FUNC)SendEntry; - initParam.usTaskPrio = 9; - initParam.uwStackSize = LOSCFG_BASE_CORE_TSK_DEFAULT_STACK_SIZE; - initParam.pcName = "SendQueue"; - - LOS_TaskLock(); - ret = LOS_TaskCreate(&task1, &initParam); - if(ret != LOS_OK) { - printf("create task1 failed, error: %x\n", ret); - return ret; - } - - initParam.pcName = "RecvQueue"; - initParam.pfnTaskEntry = (TSK_ENTRY_FUNC)RecvEntry; - ret = LOS_TaskCreate(&task2, &initParam); - if(ret != LOS_OK) { - printf("create task2 failed, error: %x\n", ret); - return ret; - } - - ret = LOS_QueueCreate("queue", 5, &g_queue, 0, 50); - if(ret != LOS_OK) { - printf("create queue failure, error: %x\n", ret); - } - - printf("create the queue success!\n"); - LOS_TaskUnlock(); - return ret; -} -``` - -### 结果验证 - -编译运行得到的结果为: - -``` -start test example -create the queue success! -recv message: test message -delete the queue success! -``` - diff --git "a/zh-cn/device-dev/kernel/\345\274\200\345\217\221\346\214\207\345\257\274-12.md" "b/zh-cn/device-dev/kernel/\345\274\200\345\217\221\346\214\207\345\257\274-12.md" deleted file mode 100644 index 4a483b3391..0000000000 --- "a/zh-cn/device-dev/kernel/\345\274\200\345\217\221\346\214\207\345\257\274-12.md" +++ /dev/null @@ -1,206 +0,0 @@ -# 开发指导 - -- [接口说明](#section158501652121514) -- [开发流程](#section783435801510) -- [编程实例](#section460018317164) - - [实例描述](#section22061718111412) - - [示例代码](#section1775922321416) - - [结果验证](#section160404016213) - - -## 接口说明 - - - - - - - - - - - - - - - - - - - - - - - - - -

    功能分类

    -

    接口名

    -

    描述

    -

    创建/删除信号量

    -

    LOS_SemCreate

    -

    创建信号量,返回信号量ID

    -

    LOS_BinarySemCreate

    -

    创建二值信号量,其计数值最大为1

    -

    LOS_SemDelete

    -

    删除指定的信号量

    -

    申请/释放信号量

    -

    LOS_SemPend

    -

    申请指定的信号量,并设置超时时间

    -

    LOS_SemPost

    -

    释放指定的信号量

    -
    - -## 开发流程 - -1. 创建信号量LOS\_SemCreate,若要创建二值信号量则调用LOS\_BinarySemCreate。 -2. 申请信号量LOS\_SemPend。 -3. 释放信号量LOS\_SemPost。 -4. 删除信号量LOS\_SemDelete。 - ->![](public_sys-resources/icon-note.gif) **说明:** ->由于中断不能被阻塞,因此不能在中断中使用阻塞模式申请信号量。 - -## 编程实例 - -### 实例描述 - -本实例实现如下功能: - -1. 测试任务ExampleSem创建一个信号量,锁任务调度,创建两个任务ExampleSemTask1、ExampleSemTask2, ExampleSemTask2优先级高于ExampleSemTask1,两个任务中申请同一信号量,解锁任务调度后两任务阻塞,测试任务ExampleSem释放信号量。 -2. ExampleSemTask2得到信号量,被调度,然后任务休眠20Tick,ExampleSemTask2延迟,ExampleSemTask1被唤醒。 -3. ExampleSemTask1定时阻塞模式申请信号量,等待时间为10Tick,因信号量仍被ExampleSemTask2持有,ExampleSemTask1挂起,10Tick后仍未得到信号量,ExampleSemTask1被唤醒,试图以永久阻塞模式申请信号量,ExampleSemTask1挂起。 -4. 20Tick后ExampleSemTask2唤醒, 释放信号量后,ExampleSemTask1得到信号量被调度运行,最后释放信号量。 -5. ExampleSemTask1执行完,40Tick后任务ExampleSem被唤醒,执行删除信号量。 - -### 示例代码 - -示例代码如下: - -``` -#include "los_sem.h" -#include "securec.h" - -/* 任务ID */ -static UINT32 g_testTaskId01; -static UINT32 g_testTaskId02; - -/* 测试任务优先级 */ -#define TASK_PRIO_TEST 5 - -/* 信号量结构体id */ -static UINT32 g_semId; - -VOID ExampleSemTask1(VOID) -{ - UINT32 ret; - - printf("ExampleSemTask1 try get sem g_semId, timeout 10 ticks.\n"); - - /* 定时阻塞模式申请信号量,定时时间为10ticks */ - ret = LOS_SemPend(g_semId, 10); - - /* 申请到信号量 */ - if (ret == LOS_OK) { - LOS_SemPost(g_semId); - return; - } - /* 定时时间到,未申请到信号量 */ - if (ret == LOS_ERRNO_SEM_TIMEOUT) { - printf("ExampleSemTask1 timeout and try get sem g_semId wait forever.\n"); - - /*永久阻塞模式申请信号量*/ - ret = LOS_SemPend(g_semId, LOS_WAIT_FOREVER); - printf("ExampleSemTask1 wait_forever and get sem g_semId.\n"); - if (ret == LOS_OK) { - LOS_SemPost(g_semId); - return; - } - } -} - -VOID ExampleSemTask2(VOID) -{ - UINT32 ret; - printf("ExampleSemTask2 try get sem g_semId wait forever.\n"); - - /* 永久阻塞模式申请信号量 */ - ret = LOS_SemPend(g_semId, LOS_WAIT_FOREVER); - - if (ret == LOS_OK) { - printf("ExampleSemTask2 get sem g_semId and then delay 20 ticks.\n"); - } - - /* 任务休眠20 ticks */ - LOS_TaskDelay(20); - - printf("ExampleSemTask2 post sem g_semId.\n"); - /* 释放信号量 */ - LOS_SemPost(g_semId); - return; -} - -UINT32 ExampleSem(VOID) -{ - UINT32 ret; - TSK_INIT_PARAM_S task1; - TSK_INIT_PARAM_S task2; - - /* 创建信号量 */ - LOS_SemCreate(0, &g_semId); - - /* 锁任务调度 */ - LOS_TaskLock(); - - /* 创建任务1 */ - (VOID)memset_s(&task1, sizeof(TSK_INIT_PARAM_S), 0, sizeof(TSK_INIT_PARAM_S)); - task1.pfnTaskEntry = (TSK_ENTRY_FUNC)ExampleSemTask1; - task1.pcName = "TestTask1"; - task1.uwStackSize = LOSCFG_BASE_CORE_TSK_DEFAULT_STACK_SIZE; - task1.usTaskPrio = TASK_PRIO_TEST; - ret = LOS_TaskCreate(&g_testTaskId01, &task1); - if (ret != LOS_OK) { - printf("task1 create failed .\n"); - return LOS_NOK; - } - - /* 创建任务2 */ - (VOID)memset_s(&task2, sizeof(TSK_INIT_PARAM_S), 0, sizeof(TSK_INIT_PARAM_S)); - task2.pfnTaskEntry = (TSK_ENTRY_FUNC)ExampleSemTask2; - task2.pcName = "TestTask2"; - task2.uwStackSize = LOSCFG_BASE_CORE_TSK_DEFAULT_STACK_SIZE; - task2.usTaskPrio = (TASK_PRIO_TEST - 1); - ret = LOS_TaskCreate(&g_testTaskId02, &task2); - if (ret != LOS_OK) { - printf("task2 create failed.\n"); - return LOS_NOK; - } - - /* 解锁任务调度 */ - LOS_TaskUnlock(); - - ret = LOS_SemPost(g_semId); - - /* 任务休眠400 ticks */ - LOS_TaskDelay(400); - - /* 删除信号量 */ - LOS_SemDelete(g_semId); - return LOS_OK; -} -``` - -### 结果验证 - -编译运行得到的结果为: - -``` -ExampleSemTask2 try get sem g_semId wait forever. -ExampleSemTask2 get sem g_semId and then delay 20 ticks. -ExampleSemTask1 try get sem g_semId, timeout 10 ticks. - -ExampleSemTask1 timeout and try get sem g_semId wait forever. -ExampleSemTask2 post sem g_semId. -ExampleSemTask1 wait_forever and get sem g_semId. -``` - diff --git "a/zh-cn/device-dev/kernel/\345\274\200\345\217\221\346\214\207\345\257\274-14.md" "b/zh-cn/device-dev/kernel/\345\274\200\345\217\221\346\214\207\345\257\274-14.md" deleted file mode 100644 index 46c7d87b7c..0000000000 --- "a/zh-cn/device-dev/kernel/\345\274\200\345\217\221\346\214\207\345\257\274-14.md" +++ /dev/null @@ -1,159 +0,0 @@ -# 开发指导 - -- [接口说明](#section158501652121514) -- [开发流程](#section783435801510) -- [编程实例](#section460018317164) - - [实例描述](#section127752801718) - - [示例代码](#section321653551711) - - [结果验证](#section4366193318167) - - -用户需要了解当前系统运行的时间以及Tick与秒、毫秒之间的转换关系时,需要使用到时间管理模块的接口。 - -## 接口说明 - -OpenHarmony LiteOS-M内核的时间管理提供下面几种功能,接口详细信息可以查看API参考。 - -**表 1** 时间管理接口 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    功能分类

    -

    接口名

    -

    描述

    -

    时间转换

    -

    LOS_MS2Tick

    -

    毫秒转换成Tick

    -

    LOS_Tick2MS

    -

    Tick转化为毫秒

    -

    OsCpuTick2MS

    -

    Cycle数目转化为毫秒,使用2个

    -

    UINT32类型的数值分别表示结果数值的高、低32位。

    -

    OsCpuTick2US

    -

    Cycle数目转化为微秒,使用2个

    -

    UINT32类型的数值分别表示结果数值的高、低32位。

    -

    时间统计

    -

    LOS_SysClockGet

    -

    获取系统时钟

    -

    LOS_TickCountGet

    -

    获取自系统启动以来的Tick数

    -

    LOS_CyclePerTickGet

    -

    每个Tick多少Cycle数

    -
    - -## 开发流程 - -时间管理的典型开发流程: - -1. 根据实际需求,完成板级配置适配,并配置系统主时钟频率OS\_SYS\_CLOCK(单位Hz)和LOSCFG\_BASE\_CORE\_TICK\_PER\_SECOND。OS\_SYS\_CLOCK的默认值基于硬件平台配置。 -2. 调用时钟转换/统计接口。 - ->![](public_sys-resources/icon-note.gif) **说明:** ->- 时间管理不是单独的功能模块,依赖于OS\_SYS\_CLOCK和LOSCFG\_BASE\_CORE\_TICK\_PER\_SECOND两个配置选项。 ->- 系统的Tick数在关中断的情况下不进行计数,故系统Tick数不能作为准确时间使用。 ->- 配置选项维护在开发板工程的文件target\_config.h。 - -## 编程实例 - -### 实例描述 - -在下面的例子中,介绍了时间管理的基本方法,包括: - -1. 时间转换:将毫秒数转换为Tick数,或将Tick数转换为毫秒数。 -2. 时间统计:每Tick的Cycle数、自系统启动以来的Tick数和延迟后的Tick数。 - -### 示例代码 - -前提条件: - -- 使用每秒的Tick数LOSCFG\_BASE\_CORE\_TICK\_PER\_SECOND的默认值100。 -- 配好OS\_SYS\_CLOCK系统主时钟频率。 - -时间转换: - -``` -VOID Example_TransformTime(VOID) -{ - UINT32 ms; - UINT32 tick; - - tick = LOS_MS2Tick(10000); // 10000ms转换为tick - dprintf("tick = %d \n", tick); - ms = LOS_Tick2MS(100); // 100tick转换为ms - dprintf("ms = %d \n", ms); -} -``` - -时间统计和时间延迟: - -``` -VOID Example_GetTime(VOID) -{ - UINT32 cyclePerTick; - UINT64 tickCount; - - cyclePerTick = LOS_CyclePerTickGet(); - if(0 != cyclePerTick) { - dprintf("LOS_CyclePerTickGet = %d \n", cyclePerTick); - } - - tickCount = LOS_TickCountGet(); - if(0 != tickCount) { - dprintf("LOS_TickCountGet = %d \n", (UINT32)tickCount); - } - - LOS_TaskDelay(200); - tickCount = LOS_TickCountGet(); - if(0 != tickCount) { - dprintf("LOS_TickCountGet after delay = %d \n", (UINT32)tickCount); - } -} -``` - -### 结果验证 - -编译运行得到的结果为: - -时间转换: - -``` -tick = 1000 -ms = 1000 -``` - -时间统计和时间延迟: - -``` -LOS_CyclePerTickGet = 495000 -LOS_TickCountGet = 1 -LOS_TickCountGet after delay = 201 -``` - diff --git "a/zh-cn/device-dev/kernel/\345\274\200\345\217\221\346\214\207\345\257\274-16.md" "b/zh-cn/device-dev/kernel/\345\274\200\345\217\221\346\214\207\345\257\274-16.md" deleted file mode 100644 index 37753d3a43..0000000000 --- "a/zh-cn/device-dev/kernel/\345\274\200\345\217\221\346\214\207\345\257\274-16.md" +++ /dev/null @@ -1,218 +0,0 @@ -# 开发指导 - -- [接口说明](#section158501652121514) -- [开发流程](#section783435801510) -- [编程实例](#section460018317164) - - [实例描述](#section3741753191918) - - [示例代码](#section20760101182016) - - [结果验证](#section11244112818172) - - -## 接口说明 - -OpenHarmony LiteOS-M内核的软件定时器模块提供下面几种功能,接口详细信息可以查看API参考。 - -**表 1** 软件定时器接口 - - - - - - - - - - - - - - - - - - - - - - - - - - -

    功能分类

    -

    接口名

    -

    描述

    -

    创建、删除定时器

    -

    LOS_SwtmrCreate

    -

    创建定时器

    -

    LOS_SwtmrDelete

    -

    删除定时器

    -

    启动、停止定时器

    -

    LOS_SwtmrStart

    -

    启动定时器

    -

    LOS_SwtmrStop

    -

    停止定时器

    -

    获得软件定时器剩余Tick数

    -

    LOS_SwtmrTimeGet

    -

    获得软件定时器剩余Tick数

    -
    - -## 开发流程 - -软件定时器的典型开发流程: - -1. 配置软件定时器。 - - 确认配置项LOSCFG\_BASE\_CORE\_SWTMR和LOSCFG\_BASE\_IPC\_QUEUE为1打开状态; - - 配置LOSCFG\_BASE\_CORE\_SWTMR\_LIMIT最大支持的软件定时器数; - - 配置OS\_SWTMR\_HANDLE\_QUEUE\_SIZE软件定时器队列最大长度; - -2. 创建定时器LOS\_SwtmrCreate。 - - 创建一个指定计时时长、指定超时处理函数、指定触发模式的软件定时器; - - 返回函数运行结果,成功或失败; - -3. 启动定时器LOS\_SwtmrStart。 -4. 获得软件定时器剩余Tick数LOS\_SwtmrTimeGet。 -5. 停止定时器LOS\_SwtmrStop。 -6. 删除定时器LOS\_SwtmrDelete。 - ->![](public_sys-resources/icon-note.gif) **说明:** ->- 软件定时器的回调函数中不要做过多操作,不要使用可能引起任务挂起或者阻塞的接口或操作。 ->- 软件定时器使用了系统的一个队列和一个任务资源,软件定时器任务的优先级设定为0,且不允许修改 。 ->- 系统可配置的软件定时器资源个数是指:整个系统可使用的软件定时器资源总个数,而并非是用户可使用的软件定时器资源个数。例如:系统软件定时器多占用一个软件定时器资源数,那么用户能使用的软件定时器资源就会减少一个。 ->- 创建单次软件定时器,该定时器超时执行完回调函数后,系统会自动删除该软件定时器,并回收资源。 ->- 创建单次不自删除属性的定时器,用户需要调用定时器删除接口删除定时器,回收定时器资源,避免资源泄露。 - -## 编程实例 - -### 实例描述 - -在下面的例子中,演示如下功能: - -1. 软件定时器创建、启动、删除、暂停、重启操作。 -2. 单次软件定时器,周期软件定时器使用方法。 - -### 示例代码 - -前提条件: - -- 在los\_config.h中,将LOSCFG\_BASE\_CORE\_SWTMR配置项打开。 -- 在los\_config.h中,将LOSCFG\_BASE\_CORE\_SWTMR\_ALIGN配置项关闭,示例代码中演示代码不涉及定时器对齐。 -- 配置好LOSCFG\_BASE\_CORE\_SWTMR\_LIMIT最大支持的软件定时器数。 -- 配置好OS\_SWTMR\_HANDLE\_QUEUE\_SIZE软件定时器队列最大长度。 - -代码实现如下: - -``` -#include "los_swtmr.h" - -/* Timer count */ -UINT32 g_timerCount1 = 0; -UINT32 g_timerCount2 = 0; - -/* 任务ID */ -UINT32 g_testTaskId01; - -void Timer1_Callback(UINT32 arg) // 回调函数1 -{ - UINT32 tick_last1; - g_timerCount1++; - tick_last1=(UINT32)LOS_TickCountGet(); // 获取当前Tick数 - printf("g_timerCount1=%d, tick_last1=%d\n", g_timerCount1, tick_last1); -} - -void Timer2_Callback(UINT32 arg) // 回调函数2 -{ - UINT32 tick_last2; - tick_last2=(UINT32)LOS_TickCountGet(); - g_timerCount2++; - printf("g_timerCount2=%d tick_last2=%d\n", g_timerCount2, tick_last2); -} - -void Timer_example(void) -{ - UINT32 id1; // timer id - UINT32 id2; // timer id - UINT32 uwTick; - - /*创建单次软件定时器,Tick数为1000,启动到1000Tick数时执行回调函数1 */ - LOS_SwtmrCreate (1000, LOS_SWTMR_MODE_ONCE, Timer1_Callback, &id1, 1); - - /*创建周期性软件定时器,每100Tick数执行回调函数2 */ - LOS_SwtmrCreate(100, LOS_SWTMR_MODE_PERIOD, Timer2_Callback, &id2, 1); - printf("create Timer1 success\n"); - - LOS_SwtmrStart (id1); //启动单次软件定时器 - printf("start Timer1 sucess\n"); - - LOS_TaskDelay(200); //延时200Tick数 - LOS_SwtmrTimeGet(id1, &uwTick); // 获得单次软件定时器剩余Tick数 - printf("uwTick =%d\n", uwTick); - - LOS_SwtmrStop(id1); // 停止软件定时器 - printf("stop Timer1 sucess\n"); - - LOS_SwtmrStart(id1); - LOS_TaskDelay(1000); - - LOS_SwtmrDelete(id1); // 删除软件定时器 - printf("delete Timer1 sucess\n"); - - LOS_SwtmrStart(id2); // 启动周期性软件定时器 - printf("start Timer2\n"); - - LOS_TaskDelay(1000); - LOS_SwtmrStop(id2); - LOS_SwtmrDelete(id2); -} - -UINT32 Example_TaskEntry(VOID) -{ - UINT32 ret; - TSK_INIT_PARAM_S task1; - - /* 锁任务调度 */ - LOS_TaskLock(); - - /* 创建任务1 */ - memset(&task1, 0, sizeof(TSK_INIT_PARAM_S)); - task1.pfnTaskEntry = (TSK_ENTRY_FUNC)Timer_example; - task1.pcName = "TimerTsk"; - task1.uwStackSize = LOSCFG_BASE_CORE_TSK_DEFAULT_STACK_SIZE; - task1.usTaskPrio = 5; - ret = LOS_TaskCreate(&g_testTaskId01, &task1); - if (ret != LOS_OK) { - printf("TimerTsk create failed.\n"); - return LOS_NOK; - } - - /* 解锁任务调度 */ - LOS_TaskUnlock(); - - return LOS_OK; -} -``` - -### 结果验证 - -编译烧录运行,输出结果如下: - -``` -create Timer1 success -start Timer1 sucess -uwTick =798 -stop Timer1 sucess -g_timerCount1=1, tick_last1=1208 -delete Timer1 sucess -start Timer2 -g_timerCount2=1 tick_last2=1313 -g_timerCount2=2 tick_last2=1413 -g_timerCount2=3 tick_last2=1513 -g_timerCount2=4 tick_last2=1613 -g_timerCount2=5 tick_last2=1713 -g_timerCount2=6 tick_last2=1813 -g_timerCount2=7 tick_last2=1913 -g_timerCount2=8 tick_last2=2013 -g_timerCount2=9 tick_last2=2113 -g_timerCount2=10 tick_last2=2213 -``` - diff --git "a/zh-cn/device-dev/kernel/\345\274\200\345\217\221\346\214\207\345\257\274-3.md" "b/zh-cn/device-dev/kernel/\345\274\200\345\217\221\346\214\207\345\257\274-3.md" deleted file mode 100644 index ee4e2944bc..0000000000 --- "a/zh-cn/device-dev/kernel/\345\274\200\345\217\221\346\214\207\345\257\274-3.md" +++ /dev/null @@ -1,306 +0,0 @@ -# 开发指导 - -- [接口说明](#section158501652121514) -- [开发流程](#section783435801510) -- [编程实例](#section460018317164) - - [结果验证](#section189023104457) - - -任务创建后,内核可以执行锁任务调度,解锁任务调度,挂起,恢复,延时等操作,同时也可以设置任务优先级,获取任务优先级。 - -## 接口说明 - -OpenHarmony LiteOS-M内核的任务管理模块提供下面几种功能,接口详细信息可以查看API参考。 - -**表 1** 任务管理模块接口 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    功能分类

    -

    接口名

    -

    描述

    -

    创建和删除任务

    -

    LOS_TaskCreateOnly

    -

    创建任务,并使该任务进入suspend状态,不对该任务进行调度。如果需要调度,可以调用LOS_TaskResume使该任务进入ready状态。

    -

    LOS_TaskCreate

    -

    创建任务,并使该任务进入ready状态,如果就绪队列中没有更高优先级的任务,则运行该任务。

    -

    LOS_TaskDelete

    -

    删除指定的任务。

    -

    控制任务状态

    -

    LOS_TaskResume

    -

    恢复挂起的任务,使该任务进入ready状态。

    -

    LOS_TaskSuspend

    -

    挂起指定的任务,然后切换任务

    -

    LOS_TaskDelay

    -

    任务延时等待,释放CPU,等待时间到期后该任务会重新进入ready状态。传入参数为Tick数目。

    -

    LOS_Msleep

    -

    传入参数为毫秒数,转换为Tick数目,调用LOS_TaskDelay。

    -

    LOS_TaskYield

    -

    当前任务时间片设置为0,释放CPU,触发调度运行就绪任务队列中优先级最高的任务。

    -

    控制任务调度

    -

    LOS_TaskLock

    -

    锁任务调度,但任务仍可被中断打断。

    -

    LOS_TaskUnlock

    -

    解锁任务调度。

    -

    LOS_Schedule

    -

    触发任务调度。

    -

    控制任务优先级

    -

    LOS_CurTaskPriSet

    -

    设置当前任务的优先级。

    -

    LOS_TaskPriSet

    -

    设置指定任务的优先级。

    -

    LOS_TaskPriGet

    -

    获取指定任务的优先级。

    -

    获取任务信息

    -

    LOS_CurTaskIDGet

    -

    获取当前任务的ID。

    -

    LOS_NextTaskIDGet

    -

    获取任务就绪队列中优先级最高的任务的ID。

    -

    LOS_NewTaskIDGet

    -

    等同LOS_NextTaskIDGet。

    -

    LOS_CurTaskNameGet

    -

    获取当前任务的名称。

    -

    LOS_TaskNameGet

    -

    获取指定任务的名称。

    -

    LOS_TaskStatusGet

    -

    获取指定任务的状态。

    -

    LOS_TaskInfoGet

    -

    获取指定任务的信息,包括任务状态、优先级、任务栈大小、栈顶指针SP、任务入口函数、已使用的任务栈大小等。

    -

    LOS_TaskIsRunning

    -

    获取任务模块是否已经开始调度运行。

    -

    任务信息维测

    -

    LOS_TaskSwitchInfoGet

    -

    获取任务切换信息,需要开启宏LOSCFG_BASE_CORE_EXC_TSK_SWITCH。

    -
    - -## 开发流程 - -以创建任务为例,讲解开发流程。 - -1. 锁任务调度LOS\_TaskLock,防止高优先级任务调度。 -2. 创建任务LOS\_TaskCreate。 -3. 解锁任务LOS\_TaskUnlock,让任务按照优先级进行调度。 -4. 延时任务LOS\_TaskDelay,任务延时等待。 -5. 挂起指定的任务LOS\_TaskSuspend,任务挂起等待恢复操作。 -6. 恢复挂起的任务LOS\_TaskResume。 - ->![](public_sys-resources/icon-note.gif) **说明:** ->- 执行Idle任务时,会对待回收链表中的任务控制块和任务栈进行回收。 ->- 任务名是指针,并没有分配空间,在设置任务名时,禁止将局部变量的地址赋值给任务名指针。 ->- 任务栈的大小按8字节大小对齐。确定任务栈大小的原则是,够用就行,多了浪费,少了任务栈溢出。 ->- 挂起当前任务时,如果已经锁任务调度,则无法挂起。 ->- Idle任务及软件定时器任务不能被挂起或者删除。 ->- 在中断处理函数中或者在锁任务的情况下,执行LOS\_TaskDelay会失败。 ->- 锁任务调度,并不关中断,因此任务仍可被中断打断。 ->- 锁任务调度必须和解锁任务调度配合使用。 ->- 设置任务优先级时可能会发生任务调度。 ->- 可配置的系统最大任务数是指:整个系统的任务总个数,而非用户能使用的任务个数。例如:系统软件定时器多占用一个任务资源,那么用户能使用的任务资源就会减少一个。 ->- LOS\_CurTaskPriSet和LOS\_TaskPriSet接口不能在中断中使用,也不能用于修改软件定时器任务的优先级。 ->- LOS\_TaskPriGet接口传入的task ID对应的任务未创建或者超过最大任务数,统一返回-1。 ->- 在删除任务时要保证任务申请的资源(如互斥锁、信号量等)已被释放。 - -## 编程实例 - -本实例介绍基本的任务操作方法,包含2个不同优先级任务的创建、任务延时、任务锁与解锁调度、挂起和恢复等操作,阐述任务优先级调度的机制以及各接口的应用。示例代码如下: - -``` -UINT32 g_taskHiId; -UINT32 g_taskLoId; -#define TSK_PRIOR_HI 4 -#define TSK_PRIOR_LO 5 - -UINT32 Example_TaskHi(VOID) -{ - UINT32 ret; - - printf("Enter TaskHi Handler.\n"); - - /* 延时100个Ticks,延时后该任务会挂起,执行剩余任务中最高优先级的任务(TaskLo任务) */ - ret = LOS_TaskDelay(100); - if (ret != LOS_OK) { - printf("Delay TaskHi Failed.\n"); - return LOS_NOK; - } - - /* 100个Ticks时间到了后,该任务恢复,继续执行 */ - printf("TaskHi LOS_TaskDelay Done.\n"); - - /* 挂起自身任务 */ - ret = LOS_TaskSuspend(g_taskHiId); - if (ret != LOS_OK) { - printf("Suspend TaskHi Failed.\n"); - return LOS_NOK; - } - printf("TaskHi LOS_TaskResume Success.\n"); - return ret; -} - -/* 低优先级任务入口函数 */ -UINT32 Example_TaskLo(VOID) -{ - UINT32 ret; - - printf("Enter TaskLo Handler.\n"); - - /* 延时100个Ticks,延时后该任务会挂起,执行剩余任务中最高优先级的任务 */ - ret = LOS_TaskDelay(100); - if (ret != LOS_OK) { - printf("Delay TaskLo Failed.\n"); - return LOS_NOK; - } - - printf("TaskHi LOS_TaskSuspend Success.\n"); - - /* 恢复被挂起的任务g_taskHiId */ - ret = LOS_TaskResume(g_taskHiId); - if (ret != LOS_OK) { - printf("Resume TaskHi Failed.\n"); - return LOS_NOK; - } - return ret; -} - -/* 任务测试入口函数,创建两个不同优先级的任务 */ -UINT32 Example_TskCaseEntry(VOID) -{ - UINT32 ret; - TSK_INIT_PARAM_S initParam; - - /* 锁任务调度,防止新创建的任务比本任务高而发生调度 */ - LOS_TaskLock(); - - printf("LOS_TaskLock() Success!\n"); - - initParam.pfnTaskEntry = (TSK_ENTRY_FUNC)Example_TaskHi; - initParam.usTaskPrio = TSK_PRIOR_HI; - initParam.pcName = "TaskHi"; - initParam.uwStackSize = LOSCFG_BASE_CORE_TSK_DEFAULT_STACK_SIZE; - - /* 创建高优先级任务,由于锁任务调度,任务创建成功后不会马上执行 */ - ret = LOS_TaskCreate(&g_taskHiId, &initParam); - if (ret != LOS_OK) { - LOS_TaskUnlock(); - - printf("Example_TaskHi create Failed!\n"); - return LOS_NOK; - } - - printf("Example_TaskHi create Success!\n"); - - initParam.pfnTaskEntry = (TSK_ENTRY_FUNC)Example_TaskLo; - initParam.usTaskPrio = TSK_PRIOR_LO; - initParam.pcName = "TaskLo"; - initParam.uwStackSize = LOSCFG_BASE_CORE_TSK_DEFAULT_STACK_SIZE; - - /* 创建低优先级任务,由于锁任务调度,任务创建成功后不会马上执行 */ - ret = LOS_TaskCreate(&g_taskLoId, &initParam); - if (ret != LOS_OK) { - LOS_TaskUnlock(); - printf("Example_TaskLo create Failed!\n"); - return LOS_NOK; - } - - printf("Example_TaskLo create Success!\n"); - - /* 解锁任务调度,此时会发生任务调度,执行就绪队列中最高优先级任务 */ - LOS_TaskUnlock(); - - return LOS_OK; -} -``` - -### 结果验证 - -编译运行得到的结果为: - -``` -LOS_TaskLock() Success! -Example_TaskHi create Success! -Example_TaskLo create Success! -Enter TaskHi Handler. -Enter TaskLo Handler. -TaskHi LOS_TaskDelay Done. -TaskHi LOS_TaskSuspend Success. -TaskHi LOS_TaskResume Success. -``` - diff --git "a/zh-cn/device-dev/kernel/\345\274\200\345\217\221\346\214\207\345\257\274-6.md" "b/zh-cn/device-dev/kernel/\345\274\200\345\217\221\346\214\207\345\257\274-6.md" deleted file mode 100644 index 6869a792fd..0000000000 --- "a/zh-cn/device-dev/kernel/\345\274\200\345\217\221\346\214\207\345\257\274-6.md" +++ /dev/null @@ -1,194 +0,0 @@ -# 开发指导 - -- [接口说明](#section158501652121514) -- [开发流程](#section783435801510) -- [编程实例](#section460018317164) - - [实例描述](#section896412438910) - - [示例代码](#section149077554912) - - [结果验证](#section4461439172017) - - -## 接口说明 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    功能分类

    -

    接口名

    -

    描述

    -

    事件检测

    -

    LOS_EventPoll

    -

    根据eventID,eventMask(事件掩码),mode(事件读取模式),检查用户期待的事件是否发生。

    -
    须知:

    当mode含LOS_WAITMODE_CLR,且用户期待的事件发生时,此时eventID中满足要求的事件会被清零,这种情况下eventID既是入参也是出参。其他情况eventID只作为入参。

    -
    -

    初始化

    -

    LOS_EventInit

    -

    事件控制块初始化。

    -

    事件读

    -

    LOS_EventRead

    -

    读事件(等待事件),任务会根据timeOut(单位:tick)进行阻塞等待;

    -

    未读取到事件时,返回值为0;

    -

    正常读取到事件时,返回正值(事件发生的集合);

    -

    其他情况返回特定错误码。

    -

    事件写

    -

    LOS_EventWrite

    -

    写一个特定的事件到事件控制块。

    -

    事件清除

    -

    LOS_EventClear

    -

    根据events掩码,清除事件控制块中的事件。

    -

    事件销毁

    -

    LOS_EventDestroy

    -

    事件控制块销毁。

    -
    - -## 开发流程 - -事件的典型开发流程: - -1. 初始化事件控制块 -2. 阻塞读事件控制块 -3. 写入相关事件 -4. 阻塞任务被唤醒,读取事件并检查是否满足要求 -5. 处理事件控制块 -6. 事件控制块销毁 - ->![](public_sys-resources/icon-note.gif) **说明:** ->- 进行事件读写操作时,事件的第25位为保留位,不可以进行位设置。 ->- 对同一事件反复写入,算作一次写入。 - -## 编程实例 - -### 实例描述 - -示例中,任务Example\_TaskEntry创建一个任务Example\_Event,Example\_Event读事件阻塞,Example\_TaskEntry向该任务写事件。可以通过示例日志中打印的先后顺序理解事件操作时伴随的任务切换。 - -1. 在任务Example\_TaskEntry创建任务Example\_Event,其中任务Example\_Event优先级高于Example\_TaskEntry。 -2. 在任务Example\_Event中读事件0x00000001,阻塞,发生任务切换,执行任务Example\_TaskEntry。 -3. 在任务Example\_TaskEntry向任务Example\_Event写事件0x00000001,发生任务切换,执行任务Example\_Event。 -4. Example\_Event得以执行,直到任务结束。 -5. Example\_TaskEntry得以执行,直到任务结束。 - -### 示例代码 - -示例代码如下: - -``` -#include "los_event.h" -#include "los_task.h" -#include "securec.h" - -/* 任务ID */ -UINT32 g_testTaskId; - -/* 事件控制结构体 */ -EVENT_CB_S g_exampleEvent; - -/* 等待的事件类型 */ -#define EVENT_WAIT 0x00000001 - -/* 用例任务入口函数 */ -VOID Example_Event(VOID) -{ - UINT32 ret; - UINT32 event; - - /* 超时等待方式读事件,超时时间为100 ticks, 若100 ticks后未读取到指定事件,读事件超时,任务直接唤醒 */ - printf("Example_Event wait event 0x%x \n", EVENT_WAIT); - - event = LOS_EventRead(&g_exampleEvent, EVENT_WAIT, LOS_WAITMODE_AND, 100); - if (event == EVENT_WAIT) { - printf("Example_Event,read event :0x%x\n", event); - } else { - printf("Example_Event,read event timeout\n"); - } -} - -UINT32 Example_TaskEntry(VOID) -{ - UINT32 ret; - TSK_INIT_PARAM_S task1; - - /* 事件初始化 */ - ret = LOS_EventInit(&g_exampleEvent); - if (ret != LOS_OK) { - printf("init event failed .\n"); - return -1; - } - - /* 创建任务 */ - (VOID)memset_s(&task1, sizeof(TSK_INIT_PARAM_S), 0, sizeof(TSK_INIT_PARAM_S)); - task1.pfnTaskEntry = (TSK_ENTRY_FUNC)Example_Event; - task1.pcName = "EventTsk1"; - task1.uwStackSize = OS_TSK_DEFAULT_STACK_SIZE; - task1.usTaskPrio = 5; - ret = LOS_TaskCreate(&g_testTaskId, &task1); - if (ret != LOS_OK) { - printf("task create failed.\n"); - return LOS_NOK; - } - - /* 写g_testTaskId 等待事件 */ - printf("Example_TaskEntry write event.\n"); - - ret = LOS_EventWrite(&g_exampleEvent, EVENT_WAIT); - if (ret != LOS_OK) { - printf("event write failed.\n"); - return LOS_NOK; - } - - /* 清标志位 */ - printf("EventMask:%d\n", g_exampleEvent.uwEventID); - LOS_EventClear(&g_exampleEvent, ~g_exampleEvent.uwEventID); - printf("EventMask:%d\n", g_exampleEvent.uwEventID); - - /* 删除任务 */ - ret = LOS_TaskDelete(g_testTaskId); - if (ret != LOS_OK) { - printf("task delete failed.\n"); - return LOS_NOK; - } - - return LOS_OK; -} -``` - -### 结果验证 - -编译运行得到的结果为: - -``` -Example_Event wait event 0x1 -Example_TaskEntry write event. -Example_Event,read event :0x1 -EventMask:1 -EventMask:0 -``` - diff --git "a/zh-cn/device-dev/kernel/\345\274\200\345\217\221\346\214\207\345\257\274-8.md" "b/zh-cn/device-dev/kernel/\345\274\200\345\217\221\346\214\207\345\257\274-8.md" deleted file mode 100644 index a194bc9e58..0000000000 --- "a/zh-cn/device-dev/kernel/\345\274\200\345\217\221\346\214\207\345\257\274-8.md" +++ /dev/null @@ -1,205 +0,0 @@ -# 开发指导 - -- [接口说明](#section158501652121514) -- [开发流程](#section783435801510) -- [编程实例](#section1426719434114) - - [实例描述](#section896412438910) - - [示例代码](#section149077554912) - - [结果验证](#section2059413981311) - - -## 接口说明 - -**表 1** 互斥锁模块接口 - - - - - - - - - - - - - - - - - - - - - - -

    功能分类

    -

    接口名

    -

    描述

    -

    互斥锁的创建和删除

    -

    LOS_MuxCreate

    -

    创建互斥锁

    -

    LOS_MuxDelete

    -

    删除指定的互斥锁

    -

    互斥锁的申请和释放

    -

    LOS_MuxPend

    -

    申请指定的互斥锁

    -

    LOS_MuxPost

    -

    释放指定的互斥锁

    -
    - -## 开发流程 - -互斥锁典型场景的开发流程: - -1. 创建互斥锁LOS\_MuxCreate。 -2. 申请互斥锁LOS\_MuxPend。 - - 申请模式有三种:无阻塞模式、永久阻塞模式、定时阻塞模式。 - - - 无阻塞模式:任务需要申请互斥锁,若该互斥锁当前没有任务持有,或者持有该互斥锁的任务和申请该互斥锁的任务为同一个任务,则申请成功。 - - 永久阻塞模式:任务需要申请互斥锁,若该互斥锁当前没有被占用,则申请成功。否则,该任务进入阻塞态,系统切换到就绪任务中优先级高者继续执行。任务进入阻塞态后,直到有其他任务释放该互斥锁,阻塞任务才会重新得以执行。 - - 定时阻塞模式:任务需要申请互斥锁,若该互斥锁当前没有被占用,则申请成功。否则该任务进入阻塞态,系统切换到就绪任务中优先级高者继续执行。任务进入阻塞态后,指定时间超时前有其他任务释放该互斥锁,或者用户指定时间超时后,阻塞任务才会重新得以执行。 - -3. 释放互斥锁LOS\_MuxPost。 - - 如果有任务阻塞于指定互斥锁,则唤醒被阻塞任务中优先级高的,该任务进入就绪态,并进行任务调度; - - 如果没有任务阻塞于指定互斥锁,则互斥锁释放成功。 - -4. 删除互斥锁LOS\_MuxDelete。 - ->![](public_sys-resources/icon-note.gif) **说明:** ->- 两个任务不能对同一把互斥锁加锁。如果某任务对已被持有的互斥锁加锁,则该任务会被挂起,直到持有该锁的任务对互斥锁解锁,才能执行对这把互斥锁的加锁操作。 ->- 互斥锁不能在中断服务程序中使用。 ->- LiteOS-M内核作为实时操作系统需要保证任务调度的实时性,尽量避免任务的长时间阻塞,因此在获得互斥锁之后,应该尽快释放互斥锁。 ->- 持有互斥锁的过程中,不得再调用LOS\_TaskPriSet等接口更改持有互斥锁任务的优先级。 - -## 编程实例 - -### 实例描述 - -本实例实现如下流程。 - -1. 任务Example\_TaskEntry创建一个互斥锁,锁任务调度,创建两个任务Example\_MutexTask1、Example\_MutexTask2。Example\_MutexTask2优先级高于Example\_MutexTask1,解锁任务调度。 -2. Example\_MutexTask2被调度,以永久阻塞模式申请互斥锁,并成功获取到该互斥锁,然后任务休眠100Tick,Example\_MutexTask2挂起,Example\_MutexTask1被唤醒。 -3. Example\_MutexTask1以定时阻塞模式申请互斥锁,等待时间为10Tick,因互斥锁仍被Example\_MutexTask2持有,Example\_MutexTask1挂起。10Tick超时时间到达后,Example\_MutexTask1被唤醒,以永久阻塞模式申请互斥锁,因互斥锁仍被Example\_MutexTask2持有,Example\_MutexTask1挂起。 -4. 100Tick休眠时间到达后,Example\_MutexTask2被唤醒, 释放互斥锁,唤醒Example\_MutexTask1。Example\_MutexTask1成功获取到互斥锁后,释放,删除互斥锁。 - -### 示例代码 - -示例代码如下: - -``` -#include -#include "los_mux.h" - -/* 互斥锁句柄id */ -UINT32 g_testMux; -/* 任务ID */ -UINT32 g_testTaskId01; -UINT32 g_testTaskId02; - -VOID Example_MutexTask1(VOID) -{ - UINT32 ret; - - printf("task1 try to get mutex, wait 10 ticks.\n"); - /* 申请互斥锁 */ - ret = LOS_MuxPend(g_testMux, 10); - - if (ret == LOS_OK) { - printf("task1 get mutex g_testMux.\n"); - /* 释放互斥锁 */ - LOS_MuxPost(g_testMux); - return; - } - if (ret == LOS_ERRNO_MUX_TIMEOUT ) { - printf("task1 timeout and try to get mutex, wait forever.\n"); - /* 申请互斥锁 */ - ret = LOS_MuxPend(g_testMux, LOS_WAIT_FOREVER); - if (ret == LOS_OK) { - printf("task1 wait forever, get mutex g_testMux.\n"); - /* 释放互斥锁 */ - LOS_MuxPost(g_testMux); - /* 删除互斥锁 */ - LOS_MuxDelete(g_testMux); - printf("task1 post and delete mutex g_testMux.\n"); - return; - } - } - return; -} - -VOID Example_MutexTask2(VOID) -{ - printf("task2 try to get mutex, wait forever.\n"); - /* 申请互斥锁 */ - (VOID)LOS_MuxPend(g_testMux, LOS_WAIT_FOREVER); - - printf("task2 get mutex g_testMux and suspend 100 ticks.\n"); - - /* 任务休眠100Ticks */ - LOS_TaskDelay(100); - - printf("task2 resumed and post the g_testMux\n"); - /* 释放互斥锁 */ - LOS_MuxPost(g_testMux); - return; -} - -UINT32 Example_TaskEntry(VOID) -{ - UINT32 ret; - TSK_INIT_PARAM_S task1; - TSK_INIT_PARAM_S task2; - - /* 创建互斥锁 */ - LOS_MuxCreate(&g_testMux); - - /* 锁任务调度 */ - LOS_TaskLock(); - - /* 创建任务1 */ - memset(&task1, 0, sizeof(TSK_INIT_PARAM_S)); - task1.pfnTaskEntry = (TSK_ENTRY_FUNC)Example_MutexTask1; - task1.pcName = "MutexTsk1"; - task1.uwStackSize = LOSCFG_BASE_CORE_TSK_DEFAULT_STACK_SIZE; - task1.usTaskPrio = 5; - ret = LOS_TaskCreate(&g_testTaskId01, &task1); - if (ret != LOS_OK) { - printf("task1 create failed.\n"); - return LOS_NOK; - } - - /* 创建任务2 */ - memset(&task2, 0, sizeof(TSK_INIT_PARAM_S)); - task2.pfnTaskEntry = (TSK_ENTRY_FUNC)Example_MutexTask2; - task2.pcName = "MutexTsk2"; - task2.uwStackSize = LOSCFG_BASE_CORE_TSK_DEFAULT_STACK_SIZE; - task2.usTaskPrio = 4; - ret = LOS_TaskCreate(&g_testTaskId02, &task2); - if (ret != LOS_OK) { - printf("task2 create failed.\n"); - return LOS_NOK; - } - - /* 解锁任务调度 */ - LOS_TaskUnlock(); - - return LOS_OK; -} -``` - -### 结果验证 - -编译运行得到的结果为: - -``` -task2 try to get mutex, wait forever. -task2 get mutex g_testMux and suspend 100 ticks. -task1 try to get mutex, wait 10 ticks. -task1 timeout and try to get mutex, wait forever. -task2 resumed and post the g_testMux -task1 wait forever, get mutex g_testMux. -task1 post and delete mutex g_testMux. -``` - diff --git "a/zh-cn/device-dev/kernel/\345\274\200\345\217\221\346\214\207\345\257\274.md" "b/zh-cn/device-dev/kernel/\345\274\200\345\217\221\346\214\207\345\257\274.md" deleted file mode 100644 index c97dfdd3f2..0000000000 --- "a/zh-cn/device-dev/kernel/\345\274\200\345\217\221\346\214\207\345\257\274.md" +++ /dev/null @@ -1,130 +0,0 @@ -# 开发指导 - -- [接口说明](#section158501652121514) -- [开发流程](#section11841123033618) -- [编程实例](#section460018317164) - - [结果验证](#section1048572415182) - - -当产生中断请求时,CPU暂停当前的任务,转而去响应外设请求。用户可以根据需要注册对应的中断处理程序,指定CPU响应中断请求时所执行的具体操作。 - -## 接口说明 - -OpenHarmony LiteOS-M内核的中断模块提供下面几种功能,接口详细信息可以查看API参考。 - -**表 1** 中断模块接口 - - - - - - - - - - - - - - - - - - - - - - - - - -

    功能分类

    -

    接口名

    -

    描述

    -

    创建、删除中断

    -

    HalHwiCreate

    -

    中断创建,注册中断号、中断触发模式、中断优先级、中断处理程序。中断被触发时,会调用该中断处理程序。

    -

    HalHwiDelete

    -

    根据指定的中断号,删除中断。

    -

    打开、关闭中断

    -

    LOS_IntUnLock

    -

    开中断,使能当前处理器所有中断响应。

    -

    LOS_IntLock

    -

    关中断,关闭当前处理器所有中断响应。

    -

    LOS_IntRestore

    -

    恢复到使用LOS_IntLock、LOS_IntUnLock操作之前的中断状态。

    -
    - -## 开发流程 - -1. 调用中断创建接口HalHwiCreate创建中断。 -2. 调用TestHwiTrigger接口触发指定中断(该接口在测试套中定义,通过写中断控制器的相关寄存器模拟外部中断,一般的外设设备,不需要执行这一步)。 -3. 调用HalHwiDelete接口删除指定中断,此接口根据实际情况使用,判断是否需要删除中断。 - ->![](public_sys-resources/icon-note.gif) **说明:** ->- 根据具体硬件,配置支持的最大中断数及可设置的中断优先级个数。 ->- 中断处理程序耗时不能过长,否则会影响CPU对中断的及时响应。 ->- 中断响应过程中不能直接、间接执行引起调度的LOS\_Schedule等函数。 ->- 中断恢复LOS\_IntRestore\(\)的入参必须是与之对应的LOS\_IntLock\(\)的返回值(即关中断之前的CPSR值)。Cortex-M系列处理器中0-15中断为内部使用,因此不建议用户去申请和创建。 - -## 编程实例 - -本实例实现如下功能: - -1. 创建中断。 -2. 触发中断。 -3. 删除中断。 - -代码实现如下,演示如何创建中断和删除中断,当指定的中断号HWI\_NUM\_TEST产生中断时,会调用中断处理函数: - -``` -#include "los_interrupt.h" - -/*创建中断*/ -#define HWI_NUM_TEST 7 - -STATIC VOID HwiUsrIrq(VOID) -{ - printf("in the func HwiUsrIrq \n"); -} - -static UINT32 Example_Interrupt(VOID) -{ - UINT32 ret; - HWI_PRIOR_T hwiPrio = 3; - HWI_MODE_T mode = 0; - HWI_ARG_T arg = 0; - - /*创建中断*/ - ret = HalHwiCreate(HWI_NUM_TEST, hwiPrio, mode, (HWI_PROC_FUNC)HwiUsrIrq, arg); - if(ret == LOS_OK){ - printf("Hwi create success!\n"); - } else { - printf("Hwi create failed!\n"); - return LOS_NOK; - } - - /* 延时50个Ticks, 当有硬件中断发生时,会调用函数HwiUsrIrq*/ - LOS_TaskDelay(50); - - /*删除中断*/ - ret = HalHwiDelete(HWI_NUM_TEST); - if(ret == LOS_OK){ - printf("Hwi delete success!\n"); - } else { - printf("Hwi delete failed!\n"); - return LOS_NOK; - } - return LOS_OK; -} -``` - -### 结果验证 - -编译运行得到的结果为: - -``` -Hwi create success! -Hwi delete success!. -``` - diff --git "a/zh-cn/device-dev/kernel/\345\274\202\345\270\270\350\260\203\346\265\213.md" "b/zh-cn/device-dev/kernel/\345\274\202\345\270\270\350\260\203\346\265\213.md" deleted file mode 100644 index 8e9a050102..0000000000 --- "a/zh-cn/device-dev/kernel/\345\274\202\345\270\270\350\260\203\346\265\213.md" +++ /dev/null @@ -1,329 +0,0 @@ -# 异常调测 - -- [基本概念](#section2741911123412) -- [运行机制](#section16618124317346) -- [接口说明](#section16111931351) -- [使用指导](#section16317163520350) - - [开发流程](#section13457839133618) - - [定位流程](#section197332323815) - - -## 基本概念 - -OpenHarmony LiteOS-M提供异常接管调测手段,帮助开发者定位分析问题。异常接管是操作系统对运行期间发生的异常情况进行处理的一系列动作,例如打印异常发生时异常类型、发生异常时的系统状态、当前函数的调用栈信息、CPU现场信息、任务调用堆栈等信息。 - -## 运行机制 - -栈帧用于保存函数调用过程中的函数参数、变量、返回值等信息。调用函数时,会创建子函数的栈帧,同时将函数入参、局部变量、寄存器入栈。栈帧从高地址向低地址生长。以ARM32 CPU架构为例,每个栈帧中都会保存PC、LR、SP和FP寄存器的历史值。LR链接寄存器(Link Register)指向函数的返回地址,FP帧指针寄存器(Frame Point)指向当前函数的父函数的栈帧起始地址。利用FP寄存器可以得到父函数的栈帧,从栈帧中获取父函数的FP,就可以得到祖父函数的栈帧,以此类推,可以追溯程序调用栈,得到函数间的调用关系。 - -当系统发生异常时,系统打印异常函数的栈帧中保存的寄存器内容,以及父函数、祖父函数的栈帧中的LR链接寄存器、FP帧指针寄存器内容,用户就可以据此追溯函数间的调用关系,定位异常原因。 - -堆栈分析原理如下图所示,实际堆栈信息根据不同CPU架构有所差异,此处仅做示意。 - -**图 1** 堆栈分析原理示意图 -![](figures/堆栈分析原理示意图.png "堆栈分析原理示意图") - -图中不同颜色的寄存器表示不同的函数。可以看到函数调用过程中,寄存器的保存。通过FP寄存器,栈回溯到异常函数的父函数,继续按照规律对栈进行解析,推出函数调用关系,方便用户定位问题。 - -## 接口说明 - -OpenHarmony LiteOS-M内核的回溯栈模块提供下面几种功能,接口详细信息可以查看API参考。 - -**表 1** 回溯栈模块接口 - - - - - - - - - - - - - - - -

    功能分类

    -

    接口名

    -

    描述

    -

    回溯栈接口

    -

    LOS_BackTrace

    -

    打印调用处的函数调用栈关系。

    -

    LOS_RecordLR

    -

    在无法打印的场景,用该接口获取调用处的函数调用栈关系。

    -
    - -## 使用指导 - -### 开发流程 - -开启异常调测的典型流程如下: - -1. 配置异常接管相关宏。 - - 需要在target\_config.h头文件中修改配置: - - - - - - - - - - - - - - - - -

    配置项

    -

    含义

    -

    设置值

    -

    LOSCFG_BACKTRACE_DEPTH

    -

    函数调用栈深度,默认15层

    -

    15

    -

    LOSCFG_BACKTRACE_TYPE

    -

    回溯栈类型:

    -

    0:表示关闭该功能;

    -

    1:表示支持Cortex-m系列硬件的函数调用栈解析;

    -

    2:表示用于Risc-v系列硬件的函数调用栈解析;

    -

    根据工具链类型设置1或2

    -
    - - -1. 使用示例中有问题的代码,编译、运行工程,在串口终端中查看异常信息输出。示例代码模拟异常代码,实际产品开发时使用异常调测机制定位异常问题。 - - 本示例演示异常输出,包含1个任务,该任务入口函数模拟若干函数调用,最终调用一个模拟异常的函数。代码实现如下: - - ``` - #include - #include "los_config.h" - #include "los_interrupt.h" - #include "los_task.h" - - UINT32 g_taskExcId; - #define TSK_PRIOR 4 - - /* 模拟异常函数 */ - - UINT32 Get_Result_Exception_0(UINT16 dividend){ - UINT32 divisor = 0; - UINT32 result = dividend / divisor; - return result; - } - - UINT32 Get_Result_Exception_1(UINT16 dividend){ - return Get_Result_Exception_0(dividend); - } - - UINT32 Get_Result_Exception_2(UINT16 dividend){ - return Get_Result_Exception_1(dividend); - } - - UINT32 Example_Exc(VOID) - { - UINT32 ret; - - printf("Enter Example_Exc Handler.\r\n"); - - /* 模拟函数调用 */ - ret = Get_Result_Exception_2(TSK_PRIOR); - printf("Divided result =%u.\r\n", ret); - - printf("Exit Example_Exc Handler.\r\n"); - return ret; - } - - - /* 任务测试入口函数,创建一个会发生异常的任务 */ - UINT32 Example_Exc_Entry(VOID) - { - UINT32 ret; - TSK_INIT_PARAM_S initParam; - - /* 锁任务调度,防止新创建的任务比本任务高而发生调度 */ - LOS_TaskLock(); - - printf("LOS_TaskLock() Success!\r\n"); - - initParam.pfnTaskEntry = (TSK_ENTRY_FUNC)Example_Exc; - initParam.usTaskPrio = TSK_PRIOR; - initParam.pcName = "Example_Exc"; - initParam.uwStackSize = LOSCFG_SECURE_STACK_DEFAULT_SIZE; - /* 创建高优先级任务,由于锁任务调度,任务创建成功后不会马上执行 */ - ret = LOS_TaskCreate(&g_taskExcId, &initParam); - if (ret != LOS_OK) { - LOS_TaskUnlock(); - - printf("Example_Exc create Failed!\r\n"); - return LOS_NOK; - } - - printf("Example_Exc create Success!\r\n"); - - /* 解锁任务调度,此时会发生任务调度,执行就绪队列中最高优先级任务 */ - LOS_TaskUnlock(); - - return LOS_OK; - } - ``` - - -1. 上述代码串口终端输出异常信息如下: - - ``` - entering kernel init... - LOS_TaskLock() Success! - Example_Exc create Success! - Entering scheduler - Enter Example_Exc Handler. - *************Exception Information************** - Type = 10 - ThrdPid = 4 - Phase = exc in task - FaultAddr = 0xabababab - Current task info: - Task name = Example_Exc - Task ID = 4 - Task SP = 0x200051ac - Task ST = 0x20004ff0 - Task SS = 0x200 - Exception reg dump: - PC = 0x80037da - LR = 0x80037fe - SP = 0x20005190 - R0 = 0x4 - R1 = 0x40 - R2 = 0x4 - R3 = 0x0 - R4 = 0x4040404 - R5 = 0x5050505 - R6 = 0x6060606 - R7 = 0x20005190 - R8 = 0x8080808 - R9 = 0x9090909 - R10 = 0x10101010 - R11 = 0x11111111 - R12 = 0x12121212 - PriMask = 0x0 - xPSR = 0x41000000 - ----- backtrace start ----- - backtrace 0 -- lr = 0x800381a - backtrace 1 -- lr = 0x8003836 - backtrace 2 -- lr = 0x8005a4e - backtrace 3 -- lr = 0x8000494 - backtrace 4 -- lr = 0x8008620 - backtrace 5 -- lr = 0x800282c - backtrace 6 -- lr = 0x80008a0 - backtrace 7 -- lr = 0x80099f8 - backtrace 8 -- lr = 0x800a01a - backtrace 9 -- lr = 0x800282c - backtrace 10 -- lr = 0x80008a0 - backtrace 11 -- lr = 0x80099f8 - backtrace 12 -- lr = 0x8009bf0 - backtrace 13 -- lr = 0x8009c52 - backtrace 14 -- lr = 0x80099aa - ----- backtrace end ----- - - TID Priority Status StackSize WaterLine StackPoint TopOfStack EventMask SemID name - --- -------- -------- --------- ---------- ---------- ---------- --------- ----- ---- - 0 0 Pend 0x2d0 0x104 0x200029bc 0x200027f0 0x0 0xffff Swt_Task - 1 31 Ready 0x500 0x44 0x20002f84 0x20002ac8 0x0 0xffff IdleCore000 - 2 6 Ready 0x1000 0x44 0x20003f94 0x20002fd8 0x0 0xffff TaskSampleEntry1 - 3 7 Ready 0x1000 0x44 0x20004f9c 0x20003fe0 0x0 0xffff TaskSampleEntry2 - 4 4 Running 0x200 0xec 0x200051ac 0x20004ff0 0x0 0xffff Example_Exc - - OS exception NVIC dump: - interrupt enable register, base address: 0xe000e100, size: 0x20 - 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 - interrupt pending register, base address: 0xe000e200, size: 0x20 - 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 - interrupt active register, base address: 0xe000e300, size: 0x20 - 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 - interrupt priority register, base address: 0xe000e400, size: 0xf0 - 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 - 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 - 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 - 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 - interrupt exception register, base address: 0xe000ed18, size: 0xc - 0x0 0x0 0xf0f00000 - interrupt shcsr register, base address: 0xe000ed24, size: 0x4 - 0x70008 - interrupt control register, base address: 0xe000ed04, size: 0x4 - 0x400f806 - - memory pools check: - system heap memcheck over, all passed! - memory pool check end! - ``` - - -### 定位流程 - -异常接管一般的定位步骤如下: - -1. 打开编译后生成的镜像反汇编(asm)文件。如果默认没有生成,可以使用objdump工具生成,命令为: - - ``` - arm-none-eabi-objdump -S -l XXX.elf - ``` - - -1. 搜索PC指针(指向当前正在执行的指令)在asm中的位置,找到发生异常的函数。 - - PC地址指向发生异常时程序正在执行的指令。在当前执行的二进制文件对应的asm文件中,查找PC值0x80037da,找到当前CPU正在执行的指令行,反汇编如下所示: - - ``` - UINT32 Get_Result_Exception_0(UINT16 dividend){ - 80037c8: b480 push {r7} - 80037ca: b085 sub sp, #20 - 80037cc: af00 add r7, sp, #0 - 80037ce: 4603 mov r3, r0 - 80037d0: 80fb strh r3, [r7, #6] - kernel_liteos_m\targets\cortex-m7_nucleo_f767zi_gcc/Core/Src/exc_example.c:10 - UINT32 divisor = 0; - 80037d2: 2300 movs r3, #0 - 80037d4: 60fb str r3, [r7, #12] - kernel_liteos_m\targets\cortex-m7_nucleo_f767zi_gcc/Core/Src/exc_example.c:11 - UINT32 result = dividend / divisor; - 80037d6: 88fa ldrh r2, [r7, #6] - 80037d8: 68fb ldr r3, [r7, #12] - 80037da: fbb2 f3f3 udiv r3, r2, r3 - 80037de: 60bb str r3, [r7, #8] - ``` - - -1. 可以看到: - 1. 异常时CPU正在执行的指令是udiv r3, r2, r3,其中r3取值为0,导致发生除零异常。 - 2. 异常发生在函数Get\_Result\_Exception\_0中。 - -2. 根据LR值查找异常函数的父函数。 - - 包含LR值0x80037fe的反汇编如下所示: - - ``` - 080037ec : - Get_Result_Exception_1(): - kernel_liteos_m\targets\cortex-m7_nucleo_f767zi_gcc/Core/Src/exc_example.c:15 - UINT32 Get_Result_Exception_1(UINT16 dividend){ - 80037ec: b580 push {r7, lr} - 80037ee: b082 sub sp, #8 - 80037f0: af00 add r7, sp, #0 - 80037f2: 4603 mov r3, r0 - 80037f4: 80fb strh r3, [r7, #6] - kernel_liteos_m\targets\cortex-m7_nucleo_f767zi_gcc/Core/Src/exc_example.c:16 - return Get_Result_Exception_0(dividend); - 80037f6: 88fb ldrh r3, [r7, #6] - 80037f8: 4618 mov r0, r3 - 80037fa: f7ff ffe5 bl 80037c8 - 80037fe: 4603 mov r3, r0 - ``` - - -1. LR值80037fe上一行是bl 80037c8 ,此处调用了异常函数,调用异常函数的父函数为Get\_Result\_Exception\_1\(\)。 -2. 重复步骤3,解析异常信息中backtrace start至backtrace end之间的LR值,得到调用产生异常的函数调用栈关系,找到异常原因。 - diff --git "a/zh-cn/device-dev/kernel/\345\277\253\351\200\237\345\205\245\351\227\250.md" "b/zh-cn/device-dev/kernel/\345\277\253\351\200\237\345\205\245\351\227\250.md" deleted file mode 100644 index 53ddc75318..0000000000 --- "a/zh-cn/device-dev/kernel/\345\277\253\351\200\237\345\205\245\351\227\250.md" +++ /dev/null @@ -1,47 +0,0 @@ -# 快速入门 - -- [搭建开发环境](#section157851447151716) -- [获取OpenHarmony源码](#section381985201816) -- [获取示例工程源码](#section204717216181) -- [编译运行](#section9772514181917) - -OpenHarmony LiteOS-M内核的编译构建系统是一个基于gn和ninja的组件化构建系统,支持按组件配置、裁剪和拼装,按需构建出定制化的产品。编译构建系统的详细信息可以参考[编译构建概述](https://gitee.com/openharmony/docs/blob/master/zh-cn/device-dev/subsystems/%E7%BC%96%E8%AF%91%E6%9E%84%E5%BB%BA%E6%A6%82%E8%BF%B0.md)。本文主要介绍如何基于gn和ninja编译LiteOS-M工程。 - -## 搭建开发环境 - -在搭建各个开发板环境前,需要完成OpenHarmony系统基础环境搭建。系统基础环境主要是指OpenHarmony的编译环境和开发环境,详细介绍请参考官方站点[搭建系统基础环境](https://gitee.com/openharmony/docs/blob/master/zh-cn/device-dev/quick-start/%E6%90%AD%E5%BB%BA%E7%B3%BB%E7%BB%9F%E7%8E%AF%E5%A2%83.md)。开发者需要根据环境搭建文档,完成下述软件的安装:Python3.7+、gn、ninja、hb。对于LiteOS-M内核,还需要安装ARM GCC编译工具链。 - -## 获取OpenHarmony源码 - -开发者需要在Linux服务器上通过Git克隆获取OpenHarmony最新源码,详细的源码获取方式,请见[源码获取](https://gitee.com/openharmony/docs/blob/master/zh-cn/device-dev/get-code/%E6%BA%90%E7%A0%81%E8%8E%B7%E5%8F%96.md)。获取OpenHarmony完整仓代码后,假设克隆目录为\~/openHarmony。 - -## 获取示例工程源码 - -以开发板Nucleo-F767Zi为例,演示如何编译运行OpenHarmony LiteOS-M内核工程。在本地目录,执行下述命令克隆示例代码。 - -``` -git clone https://gitee.com/harylee/nucleo_f767zi.git -``` - -假设克隆到的代码目录为\~/nucleo\_f767zi。 执行如下命令把代码目录的device、vendor目录复制到openHarmony工程的相应目录。 - -``` -cp -r ~/nucleo_f767zi/device/st ~/openHarmony/device/st -cp -r ~/nucleo_f767zi/vendor/st ~/openHarmony/vendor/st -``` - -关于示例代码目录的说明,可以参考资料站点[板级目录规范](https://gitee.com/openharmony/docs/blob/master/zh-cn/device-dev/porting/%E7%A7%BB%E6%A4%8D%E6%A6%82%E8%BF%B0-0.md#section6204129143013)。如果需要自行移植开发板,请参考[板级系统移植](https://gitee.com/openharmony/docs/blob/master/zh-cn/device-dev/porting/%E6%9D%BF%E7%BA%A7%E7%B3%BB%E7%BB%9F%E7%A7%BB%E6%A4%8D.md)。 - -## 编译运行 - -编译运行前,把交叉编译工具链bin目录配置到PATH环境变量中或者在device/st/nucleo\_f767zi/liteos\_m/config.gni文件中把board\_toolchain\_path配置项设置为交叉编译工具链bin目录。 在OpenHarmony根目录,执行hb set设置产品路径,选择nucleo\_f767zi产品,然后执行hb build开启编译。如下: - -``` -user@dev:~/OpenHarmony$ hb set -[OHOS INFO] Input code path: # 直接按回车,然后选择nucleo_f767zi产品即可 -OHOS Which product do you need? nucleo_f767zi@st -user@dev:~/OpenHarmony$ hb build -``` - -最终的镜像生成在\~/openHarmony/out/nucleo\_f767zi/目录中,通过STM32 ST-LINK Utility软件将镜像文件下载至单板查看运行效果。 - diff --git "a/zh-cn/device-dev/kernel/\346\211\251\345\261\225\347\273\204\344\273\266.md" "b/zh-cn/device-dev/kernel/\346\211\251\345\261\225\347\273\204\344\273\266.md" deleted file mode 100644 index dcfc826616..0000000000 --- "a/zh-cn/device-dev/kernel/\346\211\251\345\261\225\347\273\204\344\273\266.md" +++ /dev/null @@ -1,9 +0,0 @@ -# 扩展组件 - -- **[C++支持](C++支持.md)** - -- **[CPUP](CPUP.md)** - -- **[文件系统](文件系统-19.md)** - - diff --git "a/zh-cn/device-dev/kernel/\346\226\207\344\273\266\345\221\275\344\273\244.md" "b/zh-cn/device-dev/kernel/\346\226\207\344\273\266\345\221\275\344\273\244.md" deleted file mode 100755 index c1735a0278..0000000000 --- "a/zh-cn/device-dev/kernel/\346\226\207\344\273\266\345\221\275\344\273\244.md" +++ /dev/null @@ -1,45 +0,0 @@ -# 文件命令 - -- **[cat](cat.md)** - -- **[cd](cd.md)** - -- **[chgrp](chgrp.md)** - -- **[chmod](chmod.md)** - -- **[chown](chown.md)** - -- **[cp](cp.md)** - -- **[format](format.md)** - -- **[ls](ls.md)** - -- **[lsfd](lsfd.md)** - -- **[mkdir](mkdir.md)** - -- **[mount](mount.md)** - -- **[partinfo](partinfo.md)** - -- **[partition](partition.md)** - -- **[pwd](pwd.md)** - -- **[rm](rm.md)** - -- **[rmdir](rmdir.md)** - -- **[statfs](statfs.md)** - -- **[sync](sync.md)** - -- **[touch](touch.md)** - -- **[writeproc](writeproc.md)** - -- **[umount](umount.md)** - - diff --git "a/zh-cn/device-dev/kernel/\346\226\207\344\273\266\347\263\273\347\273\237-19.md" "b/zh-cn/device-dev/kernel/\346\226\207\344\273\266\347\263\273\347\273\237-19.md" deleted file mode 100644 index ba10ab39c5..0000000000 --- "a/zh-cn/device-dev/kernel/\346\226\207\344\273\266\347\263\273\347\273\237-19.md" +++ /dev/null @@ -1,204 +0,0 @@ -# 文件系统 - -当前支持的文件系统有FATFS与LittleFS,支持的功能如下表所示: - -**表 1** ****功能列表 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    功能分类

    -

    接口名

    -

    描述

    -

    FATFS

    -

    LITTELFS

    -

    文件操作

    -

    open

    -

    打开文件

    -

    支持

    -

    支持

    -

    close

    -

    关闭文件

    -

    支持

    -

    支持

    -

    read

    -

    读取文件内容

    -

    支持

    -

    支持

    -

    write

    -

    往文件写入内容

    -

    支持

    -

    支持

    -

    lseek

    -

    设置文件偏移位置

    -

    支持

    -

    支持

    -

    unlink

    -

    删除文件

    -

    支持

    -

    支持

    -

    rename

    -

    重命名文件

    -

    支持

    -

    支持

    -

    fstat

    -

    通过文件句柄获取文件信息

    -

    支持

    -

    支持

    -

    stat

    -

    通过文件路径名获取文件信息

    -

    支持

    -

    支持

    -

    fsync

    -

    文件内容刷入存储设备

    -

    支持

    -

    支持

    -

    目录操作

    -

    mkdir

    -

    创建目录

    -

    支持

    -

    支持

    -

    opendir

    -

    打开目录

    -

    支持

    -

    支持

    -

    readdir

    -

    读取目录项内容

    -

    支持

    -

    支持

    -

    closedir

    -

    关闭目录

    -

    支持

    -

    支持

    -

    rmdir

    -

    删除目录

    -

    支持

    -

    支持

    -

    分区操作

    -

    mount

    -

    分区挂载

    -

    支持

    -

    支持

    -

    umount

    -

    分区卸载

    -

    支持

    -

    支持

    -

    umount2

    -

    分区卸载,可通过MNT_FORCE参数进行强制卸载

    -

    支持

    -

    不支持

    -

    statfs

    -

    获取分区信息

    -

    支持

    -

    不支持

    -
    - -- **[FAT](FAT-20.md)** - -- **[LittleFS](LittleFS.md)** - - diff --git "a/zh-cn/device-dev/kernel/\346\226\207\344\273\266\347\263\273\347\273\237.md" "b/zh-cn/device-dev/kernel/\346\226\207\344\273\266\347\263\273\347\273\237.md" deleted file mode 100644 index b17821e62d..0000000000 --- "a/zh-cn/device-dev/kernel/\346\226\207\344\273\266\347\263\273\347\273\237.md" +++ /dev/null @@ -1,54 +0,0 @@ -# 文件系统 - -OpenHarmony轻内核支持的文件系统有:VFS(虚拟文件系统)、NFS、RAMFS、FAT、JFFS2。 - -**各个文件系统功能概述:** - -**表 1** 文件系统功能概述 - - - - - - - - - - - - - - - - - - - - - - -

    文件系统

    -

    功能特点概述

    -

    VFS

    -

    VFS是Virtual File System(虚拟文件系统)的缩写,它不是一个实际的文件系统,而是一个异构文件系统之上的软件粘合层,为用户提供统一的类Unix文件操作接口。

    -

    NFS

    -

    NFS是Network File System(网络文件系统)的缩写。它最大的功能是可以通过网络,让不同的机器、不同的操作系统彼此分享其他用户的文件。

    -

    RAMFS

    -

    RAMFS是一种基于RAM的文件系统。RAMFS文件系统把所有的文件都放在RAM中,所以读/写操作发生在RAM中,避免了对存储器的读写损耗,也提高了数据读写速度。RAMFS是基于RAM的动态文件系统的一种存储缓冲机制。

    -

    FAT

    -

    FAT文件系统是File Allocation Table(文件配置表)的简称,有FAT12、FAT16、FAT32。在可移动存储介质(U盘、SD卡、移动硬盘等)上多使用FAT文件系统,使设备与Windows、Linux等桌面系统之间保持很好的兼容性。

    -

    JFFS2

    -

    JFFS2是Journalling Flash File System Version 2(日志文件系统)的缩写,是MTD设备上的日志型文件系统。主要应用于对NOR_FLASH闪存的文件管理。OpenHarmony内核的JFFS2支持多分区。

    -
    - -- **[VFS](VFS.md)** - -- **[NFS](NFS.md)** - -- **[RAMFS](RAMFS.md)** - -- **[FAT](FAT.md)** - -- **[JFFS2](JFFS2.md)** - - diff --git "a/zh-cn/device-dev/kernel/\346\227\266\351\227\264\347\256\241\347\220\206.md" "b/zh-cn/device-dev/kernel/\346\227\266\351\227\264\347\256\241\347\220\206.md" deleted file mode 100644 index 967a229499..0000000000 --- "a/zh-cn/device-dev/kernel/\346\227\266\351\227\264\347\256\241\347\220\206.md" +++ /dev/null @@ -1,7 +0,0 @@ -# 时间管理 - -- **[基本概念](基本概念-13.md)** - -- **[开发指导](开发指导-14.md)** - - diff --git "a/zh-cn/device-dev/kernel/\346\240\207\345\207\206\345\272\223-0.md" "b/zh-cn/device-dev/kernel/\346\240\207\345\207\206\345\272\223-0.md" deleted file mode 100755 index a365148450..0000000000 --- "a/zh-cn/device-dev/kernel/\346\240\207\345\207\206\345\272\223-0.md" +++ /dev/null @@ -1,197 +0,0 @@ -# 标准库 - -- [框架流程](#section1247343413257) -- [操作实例](#section4807125622614) -- [常见问题](#section1219455217277) - -OpenHarmony内核OpenHarmony使用**musl libc**库,支持标准POSIX接口,开发者可基于POSIX标准接口开发内核之上的组件及应用。 - -## 框架流程 - -**图 1** POSIX接口框架 -![](figures/POSIX接口框架.png "POSIX接口框架") - -**musl libc**库支持POSIX标准,涉及的系统调用相关接口由OpenHarmony内核适配支持 ,以满足接口对外描述的功能要求。 - -标准库支持接口的详细情况请参考C库的API文档,其中也涵盖了与POSIX标准之间的差异说明。 - -## 操作实例 - -在本示例中,主线程创建了THREAD\_NUM个子线程,每个子线程启动后等待被主线程唤醒,主线程成功唤醒所有子线程后,子线程继续执行直至生命周期结束,同时主线程通过pthread\_join方法等待所有线程执行结束。 - -``` -#include -#include -#include - -#ifdef __cplusplus -#if __cplusplus -extern "C" { -#endif /* __cplusplus */ -#endif /* __cplusplus */ - -#define THREAD_NUM 3 -int g_startNum = 0; /* 启动的线程数 */ -int g_wakenNum = 0; /* 唤醒的线程数 */ - -struct testdata { - pthread_mutex_t mutex; - pthread_cond_t cond; -} g_td; - -/* - * 子线程入口函数 - */ -static void *ChildThreadFunc(void *arg) -{ - int rc; - pthread_t self = pthread_self(); - - /* 获取mutex锁 */ - rc = pthread_mutex_lock(&g_td.mutex); - if (rc != 0) { - printf("ERROR:take mutex lock failed, error code is %d!\n", rc); - goto EXIT; - } - - /* g_startNum计数加一,用于统计已经获得mutex锁的子线程个数 */ - g_startNum++; - - /* 等待cond条件变量 */ - rc = pthread_cond_wait(&g_td.cond, &g_td.mutex); - if (rc != 0) { - printf("ERROR: pthread condition wait failed, error code is %d!\n", rc); - (void)pthread_mutex_unlock(&g_td.mutex); - goto EXIT; - } - - /* 尝试获取mutex锁,正常场景,此处无法获取锁 */ - rc = pthread_mutex_trylock(&g_td.mutex); - if (rc == 0) { - printf("ERROR: mutex gets an abnormal lock!\n"); - goto EXIT; - } - - /* g_wakenNum计数加一,用于统计已经被cond条件变量唤醒的子线程个数 */ - g_wakenNum++; - - /* 释放mutex锁 */ - rc = pthread_mutex_unlock(&g_td.mutex); - if (rc != 0) { - printf("ERROR: mutex release failed, error code is %d!\n", rc); - goto EXIT; - } -EXIT: - return NULL; -} - -static int testcase(void) -{ - int i, rc; - pthread_t thread[THREAD_NUM]; - - /* 初始化mutex锁 */ - rc = pthread_mutex_init(&g_td.mutex, NULL); - if (rc != 0) { - printf("ERROR: mutex init failed, error code is %d!\n", rc); - goto ERROROUT; - } - - /* 初始化cond条件变量 */ - rc = pthread_cond_init(&g_td.cond, NULL); - if (rc != 0) { - printf("ERROR: pthread condition init failed, error code is %d!\n", rc); - goto ERROROUT; - } - - /* 批量创建THREAD_NUM个子线程 */ - for (i = 0; i < THREAD_NUM; i++) { - rc = pthread_create(&thread[i], NULL, ChildThreadFunc, NULL); - if (rc != 0) { - printf("ERROR: pthread create failed, error code is %d!\n", rc); - goto ERROROUT; - } - } - - /* 等待所有子线程都完成mutex锁的获取 */ - while (g_startNum < THREAD_NUM) { - usleep(100); - } - - /* 获取mutex锁,确保所有子线程都阻塞在pthread_cond_wait上 */ - rc = pthread_mutex_lock(&g_td.mutex); - if (rc != 0) { - printf("ERROR: mutex lock failed, error code is %d\n", rc); - goto ERROROUT; - } - - /* 释放mutex锁 */ - rc = pthread_mutex_unlock(&g_td.mutex); - if (rc != 0) { - printf("ERROR: mutex unlock failed, error code is %d!\n", rc); - goto ERROROUT; - } - - for (int j = 0; j < THREAD_NUM; j++) { - /* 在cond条件变量上广播信号 */ - rc = pthread_cond_signal(&g_td.cond); - if (rc != 0) { - printf("ERROR: pthread condition failed, error code is %d!\n", rc); - goto ERROROUT; - } - } - - sleep(1); - - /* 检查是否所有子线程都已被唤醒 */ - if (g_wakenNum != THREAD_NUM) { - printf("ERROR: not all threads awaken, only %d thread(s) awaken!\n", g_wakenNum); - goto ERROROUT; - } - - /* join所有子线程,即等待其结束 */ - for (i = 0; i < THREAD_NUM; i++) { - rc = pthread_join(thread[i], NULL); - if (rc != 0) { - printf("ERROR: pthread join failed, error code is %d!\n", rc); - goto ERROROUT; - } - } - - /* 销毁cond条件变量 */ - rc = pthread_cond_destroy(&g_td.cond); - if (rc != 0) { - printf("ERROR: pthread condition destroy failed, error code is %d!\n", rc); - goto ERROROUT; - } - return 0; -ERROROUT: - return -1; -} - -/* - * 示例代码主函数 - */ -int main(int argc, char *argv[]) -{ - int rc; - - /* 启动测试函数 */ - rc = testcase(); - if (rc != 0) { - printf("ERROR: testcase failed!\n"); - } - - return 0; -} -#ifdef __cplusplus -#if __cplusplus -} -#endif /* __cplusplus */ -#endif /* __cplusplus */ -``` - -## 常见问题 - -无。 - diff --git "a/zh-cn/device-dev/kernel/\346\240\207\345\207\206\345\272\223.md" "b/zh-cn/device-dev/kernel/\346\240\207\345\207\206\345\272\223.md" deleted file mode 100755 index 56f2c7aa1b..0000000000 --- "a/zh-cn/device-dev/kernel/\346\240\207\345\207\206\345\272\223.md" +++ /dev/null @@ -1,7 +0,0 @@ -# 标准库 - -- **[标准库](标准库-0.md)** - -- **[与Linux标准库的差异](与Linux标准库的差异.md)** - - diff --git "a/zh-cn/device-dev/kernel/\346\240\207\345\207\206\345\272\223\346\224\257\346\214\201.md" "b/zh-cn/device-dev/kernel/\346\240\207\345\207\206\345\272\223\346\224\257\346\214\201.md" deleted file mode 100644 index 7522c305c5..0000000000 --- "a/zh-cn/device-dev/kernel/\346\240\207\345\207\206\345\272\223\346\224\257\346\214\201.md" +++ /dev/null @@ -1,7 +0,0 @@ -# 标准库支持 - -- **[CMSIS支持](CMSIS支持.md)** - -- **[POSIX支持](POSIX支持.md)** - - diff --git "a/zh-cn/device-dev/kernel/\346\240\207\345\207\206\347\263\273\347\273\237\345\206\205\346\240\270.md" "b/zh-cn/device-dev/kernel/\346\240\207\345\207\206\347\263\273\347\273\237\345\206\205\346\240\270.md" deleted file mode 100644 index 5911c5e037..0000000000 --- "a/zh-cn/device-dev/kernel/\346\240\207\345\207\206\347\263\273\347\273\237\345\206\205\346\240\270.md" +++ /dev/null @@ -1,9 +0,0 @@ -# 标准系统内核 - -- **[Linux内核概述](Linux内核概述.md)** - -- **[OpenHarmony开发板Patch使用指导](OpenHarmony开发板Patch使用指导.md)** - -- **[Linux内核编译与构建指导](Linux内核编译与构建指导.md)** - - diff --git "a/zh-cn/device-dev/kernel/\346\266\210\346\201\257\351\230\237\345\210\227.md" "b/zh-cn/device-dev/kernel/\346\266\210\346\201\257\351\230\237\345\210\227.md" deleted file mode 100644 index 3a56400156..0000000000 --- "a/zh-cn/device-dev/kernel/\346\266\210\346\201\257\351\230\237\345\210\227.md" +++ /dev/null @@ -1,7 +0,0 @@ -# 消息队列 - -- **[基本概念](基本概念-9.md)** - -- **[开发指导](开发指导-10.md)** - - diff --git "a/zh-cn/device-dev/kernel/\347\263\273\347\273\237\345\221\275\344\273\244.md" "b/zh-cn/device-dev/kernel/\347\263\273\347\273\237\345\221\275\344\273\244.md" deleted file mode 100755 index 6d10fdb022..0000000000 --- "a/zh-cn/device-dev/kernel/\347\263\273\347\273\237\345\221\275\344\273\244.md" +++ /dev/null @@ -1,47 +0,0 @@ -# 系统命令 - -- **[cpup](cpup.md)** - -- **[date](date.md)** - -- **[dmesg](dmesg.md)** - -- **[exec](exec.md)** - -- **[free](free.md)** - -- **[help](help.md)** - -- **[hwi](hwi.md)** - -- **[kill](kill.md)** - -- **[log](log.md)** - -- **[memcheck](memcheck.md)** - -- **[oom](oom.md)** - -- **[pmm](pmm.md)** - -- **[reset](reset.md)** - -- **[sem](sem.md)** - -- **[stack](stack.md)** - -- **[su](su.md)** - -- **[swtmr](swtmr.md)** - -- **[systeminfo](systeminfo.md)** - -- **[task](task.md)** - -- **[uname](uname.md)** - -- **[vmm](vmm.md)** - -- **[watch](watch.md)** - - diff --git "a/zh-cn/device-dev/kernel/\347\272\277\347\250\213.md" "b/zh-cn/device-dev/kernel/\347\272\277\347\250\213.md" deleted file mode 100755 index 7add0e4dc7..0000000000 --- "a/zh-cn/device-dev/kernel/\347\272\277\347\250\213.md" +++ /dev/null @@ -1,702 +0,0 @@ -# 线程 - -- [基本概念](#section1179311337405) -- [使用场景](#section44877547404) -- [接口说明](#section2069477134115) - -## 基本概念 - -从系统的角度看,线程是竞争系统资源的最小运行单元。线程可以使用或等待CPU、使用内存空间等系统资源,并独立于其它线程运行。 - -OpenHarmony内核每个进程内的线程独立运行、独立调度,当前进程内线程的调度不受其它进程内线程的影响。 - -OpenHarmony内核中的线程采用抢占式调度机制,同时支持时间片轮转调度和FIFO调度方式。 - -OpenHarmony内核的线程一共有32个优先级\(0-31\),最高优先级为0,最低优先级为31。 - -当前进程内高优先级的线程可抢占当前进程内低优先级线程,当前进程内低优先级线程必须在当前进程内高优先级线程阻塞或结束后才能得到调度。 - -**线程状态说明:** - -- 初始化(Init):该线程正在被创建。 - -- 就绪(Ready):该线程在就绪列表中,等待CPU调度。 - -- 运行(Running):该线程正在运行。 - -- 阻塞(Blocked):该线程被阻塞挂起。Blocked状态包括:pending\(因为锁、事件、信号量等阻塞\)、suspended(主动pend)、delay\(延时阻塞\)、pendtime\(因为锁、事件、信号量时间等超时等待\)。 - -- 退出(Exit):该线程运行结束,等待父线程回收其控制块资源。 - - -**图 1** 线程状态迁移示意图 -![](figures/线程状态迁移示意图.png "线程状态迁移示意图") - -**线程状态迁移说明:** - -- Init→Ready: - - 线程创建拿到控制块后为Init状态,处于线程初始化阶段,当线程初始化完成将线程插入调度队列,此时线程进入就绪状态。 - -- Ready→Running: - - 线程创建后进入就绪态,发生线程切换时,就绪列表中最高优先级的线程被执行,从而进入运行态,但此刻该线程会从就绪列表中删除。 - -- Running→Blocked: - - 正在运行的线程发生阻塞(挂起、延时、读信号量等)时,线程状态由运行态变成阻塞态,然后发生线程切换,运行就绪列表中剩余最高优先级线程。 - -- Blocked→Ready : - - 阻塞的线程被恢复后(线程恢复、延时时间超时、读信号量超时或读到信号量等),此时被恢复的线程会被加入就绪列表,从而由阻塞态变成就绪态。 - -- Ready→Blocked: - - 线程也有可能在就绪态时被阻塞(挂起),此时线程状态会由就绪态转变为阻塞态,该线程从就绪列表中删除,不会参与线程调度,直到该线程被恢复。 - -- Running→Ready: - - 有更高优先级线程创建或者恢复后,会发生线程调度,此刻就绪列表中最高优先级线程变为运行态,那么原先运行的线程由运行态变为就绪态,并加入就绪列表中。 - -- Running→Exit: - - 运行中的线程运行结束,线程状态由运行态变为退出态。若未设置分离属性(PTHREAD\_CREATE\_DETACHED)的线程,运行结束后对外呈现的是Exit状态,即退出态。 - - -## 使用场景 - -线程创建后,用户态可以执行线程调度、挂起、恢复、延时等操作,同时也可以设置线程优先级和调度策略,获取线程优先级和调度策略。 - -## 接口说明 - -OpenHarmony内核系统中的线程管理模块,线程间通信为用户提供下面几种功能: - -**表 1** 线程管理模块功能 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    头文件

    -

    名称

    -

    说明

    -

    备注

    -

    pthread.h

    -

    pthread_attr_destroy

    -

    销毁线程属性对象。

    -

    -

    -

    pthread.h

    -

    pthread_attr_getinheritsched

    -

    获取线程属性对象的调度属性。

    -

    -

    -

    pthread.h

    -

    pthread_attr_getschedparam

    -

    获取线程属性对象的调度参数属性。

    -

    -

    -

    pthread.h

    -

    pthread_attr_getschedpolicy

    -

    获取线程属性对象的调度策略属性。

    -

    OpenHarmony:支持SCHED_FIFO 、SCHED_RR调度策略。

    -

    pthread.h

    -

    pthread_attr_getstacksize

    -

    获取线程属性对象的堆栈大小。

    -

    -

    -

    pthread.h

    -

    pthread_attr_init

    -

    初始化线程属性对象。

    -

    -

    -

    pthread.h

    -

    pthread_attr_setdetachstate

    -

    设置线程属性对象的分离状态。

    -

    -

    -

    pthread.h

    -

    pthread_attr_setinheritsched

    -

    设置线程属性对象的继承调度属性。

    -

    -

    -

    pthread.h

    -

    pthread_attr_setschedparam

    -

    设置线程属性对象的调度参数属性。

    -

    OpenHarmony:设置线程优先级的参数值越小,线程在系统中的优先级越高;设置参数值越大,优先级越低。

    -

    注意:需要将pthread_attr_t线程属性的inheritsched字段设置为PTHREAD_EXPLICIT_SCHED,否则设置的线程调度优先级将不会生效,系统默认设置为PTHREAD_INHERIT_SCHED。

    -

    pthread.h

    -

    pthread_attr_setschedpolicy

    -

    设置线程属性对象的调度策略属性。

    -

    OpenHarmony:支持SCHED_FIFO 、SCHED_RR调度策略。

    -

    pthread.h

    -

    pthread_attr_setstacksize

    -

    设置线程属性对象的堆栈大小。

    -

    -

    -

    pthread.h

    -

    pthread_getattr_np

    -

    获取已创建线程的属性。

    -

    -

    -

    pthread.h

    -

    pthread_cancel

    -

    向线程发送取消请求。

    -

    -

    -

    pthread.h

    -

    pthread_testcancel

    -

    请求交付任何未决的取请求。

    -

    -

    -

    pthread.h

    -

    pthread_setcanceltype

    -

    设置线程可取消类型。

    -

    -

    -

    pthread.h

    -

    pthread_setcancelstate

    -

    设置线程可取消状态。

    -

    -

    -

    pthread.h

    -

    pthread_create

    -

    创建一个新的线程。

    -

    -

    -

    pthread.h

    -

    pthread_detach

    -

    分离一个线程。

    -

    -

    -

    pthread.h

    -

    pthread_equal

    -

    比较两个线程ID是否相等。

    -

    -

    -

    pthread.h

    -

    pthread_exit

    -

    终止正在调用的线程。

    -

    -

    -

    pthread.h

    -

    pthread_getschedparam

    -

    获取线程的调度策略和参数。

    -

    OpenHarmony:支持SCHED_FIFO 、SCHED_RR调度策略。

    -

    pthread.h

    -

    pthread_join

    -

    等待指定的线程结束。

    -

    -

    -

    pthread.h

    -

    pthread_self

    -

    获取当前线程的ID。

    -

    -

    -

    pthread.h

    -

    pthread_setschedprio

    -

    设置线程的调度静态优先级。

    -

    -

    -

    pthread.h

    -

    pthread_kill

    -

    向线程发送信号。

    -

    -

    -

    pthread.h

    -

    pthread_once

    -

    使函数调用只能执行一次。

    -

    -

    -

    pthread.h

    -

    pthread_atfork

    -

    注册fork的处理程序。

    -

    -

    -

    pthread.h

    -

    pthread_cleanup_pop

    -

    删除位于清理处理程序堆栈顶部的例程。

    -

    -

    -

    pthread.h

    -

    pthread_cleanup_push

    -

    将例程推送到清理处理程序堆栈的顶部。

    -

    -

    -

    pthread.h

    -

    pthread_barrier_destroy

    -

    销毁屏障对象(高级实时线程)

    -

    -

    -

    pthread.h

    -

    pthread_barrier_init

    -

    初始化屏障对象(高级实时线程)

    -

    -

    -

    pthread.h

    -

    pthread_barrier_wait

    -

    屏障同步(高级实时线程)

    -

    -

    -

    pthread.h

    -

    pthread_barrierattr_destroy

    -

    销毁屏障属性对象。

    -

    -

    -

    pthread.h

    -

    pthread_barrierattr_init

    -

    初始化屏障属性对象。

    -

    -

    -

    pthread.h

    -

    pthread_mutex_destroy

    -

    销毁互斥锁。

    -

    -

    -

    pthread.h

    -

    pthread_mutex_init

    -

    初始化互斥锁。

    -

    -

    -

    pthread.h

    -

    pthread_mutex_lock

    -

    互斥锁加锁操作。

    -

    -

    -

    pthread.h

    -

    pthread_mutex_trylock

    -

    互斥锁尝试加锁操作。

    -

    -

    -

    pthread.h

    -

    pthread_mutex_unlock

    -

    互斥锁解锁操作。

    -

    -

    -

    pthread.h

    -

    pthread_mutexattr_destroy

    -

    销毁互斥锁属性对象。

    -

    -

    -

    pthread.h

    -

    pthread_mutexattr_gettype

    -

    获取互斥锁类型属性。

    -

    -

    -

    pthread.h

    -

    pthread_mutexattr_init

    -

    初始化互斥锁属性对象。

    -

    -

    -

    pthread.h

    -

    pthread_mutexattr_settype

    -

    设置互斥锁类型属性。

    -

    -

    -

    pthread.h

    -

    pthread_mutex_timedlock

    -

    使用超时锁定互斥锁。

    -

    -

    -

    pthread.h

    -

    pthread_rwlock_destroy

    -

    销毁读写锁。

    -

    -

    -

    pthread.h

    -

    pthread_rwlock_init

    -

    初始化读写锁。

    -

    -

    -

    pthread.h

    -

    pthread_rwlock_rdlock

    -

    获取读写锁读锁操作。

    -

    -

    -

    pthread.h

    -

    pthread_rwlock_timedrdlock

    -

    使用超时锁定读写锁读锁。

    -

    -

    -

    pthread.h

    -

    pthread_rwlock_timedwrlock

    -

    使用超时锁定读写锁写锁。

    -

    -

    -

    pthread.h

    -

    pthread_rwlock_tryrdlock

    -

    尝试获取读写锁读锁操作。

    -

    -

    -

    pthread.h

    -

    pthread_rwlock_trywrlock

    -

    尝试获取读写锁写锁操作。

    -

    -

    -

    pthread.h

    -

    pthread_rwlock_unlock

    -

    读写锁解锁操作。

    -

    -

    -

    pthread.h

    -

    pthread_rwlock_wrlock

    -

    获取读写锁写锁操作。

    -

    -

    -

    pthread.h

    -

    pthread_rwlockattr_destroy

    -

    销毁读写锁属性对象。

    -

    -

    -

    pthread.h

    -

    pthread_rwlockattr_init

    -

    初始化读写锁属性对象。

    -

    -

    -

    pthread.h

    -

    pthread_cond_broadcast

    -

    解除若干已被等待条件阻塞的线程。

    -

    -

    -

    pthread.h

    -

    pthread_cond_destroy

    -

    销毁条件变量。

    -

    -

    -

    pthread.h

    -

    pthread_cond_init

    -

    初始化条件变量。

    -

    -

    -

    pthread.h

    -

    pthread_cond_signal

    -

    解除被阻塞的线程。

    -

    -

    -

    pthread.h

    -

    pthread_cond_timedwait

    -

    定时等待条件。

    -

    -

    -

    pthread.h

    -

    pthread_cond_wait

    -

    等待条件。

    -

    -

    -

    semaphore.h

    -

    sem_destroy

    -

    销毁指定的无名信号量。

    -

    -

    -

    semaphore.h

    -

    sem_getvalue

    -

    获得指定信号量计数值。

    -

    -

    -

    semaphore.h

    -

    sem_init

    -

    创建并初始化一个无名信号量。

    -

    -

    -

    semaphore.h

    -

    sem_post

    -

    增加信号量计数。

    -

    -

    -

    semaphore.h

    -

    sem_timedwait

    -

    获取信号量,且有超时返回功能。

    -

    -

    -

    semaphore.h

    -

    sem_trywait

    -

    尝试获取信号量。

    -

    -

    -

    semaphore.h

    -

    sem_wait

    -

    获取信号量。

    -

    -

    -
    - diff --git "a/zh-cn/device-dev/kernel/\347\275\221\347\273\234.md" "b/zh-cn/device-dev/kernel/\347\275\221\347\273\234.md" deleted file mode 100755 index 17eafd2f16..0000000000 --- "a/zh-cn/device-dev/kernel/\347\275\221\347\273\234.md" +++ /dev/null @@ -1,303 +0,0 @@ -# 网络 - -- [基本概念](#section9840143083510) -- [使用场景](#section1575885183516) -- [接口说明](#section16351198193614) - -## 基本概念 - -网络模块实现了TCP/IP协议栈基本功能,提供标准的POSIX socket接口。 - ->![](public_sys-resources/icon-note.gif) **说明:** ->当前系统使用**lwIP**提供网络能力。 - -## 使用场景 - -针对用户态开发,OpenHarmony内核提供了一套网络功能系统调用接口,支持socket的创建关闭、数据收发、网络属性的设置等,通过C库提供标准的POSIX socket函数供开发者使用。 - -## 接口说明 - -**表 1** 标准C库相关接口 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    头文件

    -

    接口

    -

    功能

    -

    sys/socket.h

    -

    int accept(int socket, struct sockaddr *address, socklen_t *address_len)

    -

    接受连接。

    -

    sys/socket.h

    -

    int bind(int s, const struct sockaddr *name, socklen_t namelen)

    -

    socket与IP地址绑定。

    -

    sys/socket.h

    -

    int shutdown(int socket, int how)

    -

    关闭连接。

    -

    sys/socket.h

    -

    int getpeername(int s, struct sockaddr *name, socklen_t *namelen)

    -

    获取对端地址。

    -

    sys/socket.h

    -

    int getsockname(int s, struct sockaddr *name, socklen_t *namelen)

    -

    获取本地地址。

    -

    sys/socket.h

    -

    int getsockopt(int s, struct sockaddr *name, socklen_t *namelen)

    -

    获取socket属性信息。

    -

    sys/socket.h

    -

    int setsockopt(int sockfd, int level, int optname, void *optval, socklen_t *optlen)

    -

    配置socket属性。

    -

    unistd.h

    -

    int close(int s)

    -

    关闭socket。

    -

    sys/socket.h

    -

    int connect(int s, const struct sockaddr *name, socklen_t namelen)

    -

    连接到指定的目的IP。

    -

    sys/socket.h

    -

    int listen(int sockfd, int backlog)

    -

    聆听连接本socket的请求。

    -

    sys/socket.h

    -

    ssize_t recv(int socket, void *buffer, size_t length, int flags)

    -

    接收socket上收到的数据。

    -

    sys/socket.h

    -

    ssize_t recvmsg(int s, struct msghdr *message, int flags)

    -

    接收socket上收到的数据,可使用更丰富的参数。

    -

    sys/socket.h

    -

    ssize_t recvfrom(int socket, void *buffer, size_t length, int flags, struct sockaddr *address, socklen_t *address_len)

    -

    接收socket上收到的数据,可同时获得数据来源IP地址。

    -

    sys/socket.h

    -

    ssize_t send(int s, const void *dataptr, size_t size, int flags)

    -

    通过socket发送数据。

    -

    sys/socket.h

    -

    ssize_t sendmsg(int s, const struct msghdr *message, int flags)

    -

    通过socket发送数据,可使用更丰富的参数。

    -

    sys/socket.h

    -

    ssize_t sendto(int s, const void *dataptr, size_t size, int flags, const struct sockaddr *to, socklen_t tolen)

    -

    通过socket发送数据,可指定发送的目的IP地址。

    -

    sys/socket.h

    -

    int socket(int domain, int type, int protocol)

    -

    创建socket。

    -

    sys/select.h

    -

    int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout)

    -

    多路复用。

    -

    sys/ioctl.h

    -

    int ioctl(int s, int request, ...)

    -

    socket属性获取、设置。

    -

    arpa/inet.h

    -

    const char *inet_ntop(int af, const void *src, char *dst, socklen_t size)

    -

    网络地址格式转换:将二进制格式IP地址转换为字符串格式。

    -

    arpa/inet.h

    -

    int inet_pton(int af, const char *src, void *dst)

    -

    网络地址格式转换:将字符串格式IP地址转换为二进制格式。

    -
    - -与标准接口差异详细说明: - -- **sendmsg** - - **函数原型:** - - ssize\_t sendmsg\(int s, const struct msghdr \*message, int flags\) - - **函数功能:**发送消息。 - - **参数说明:** - - - - - - - - - - - - - - - - -

    参数

    -

    描述

    -

    s

    -

    套接字描述符。

    -

    message

    -

    待发送的消息,不支持发送ancillary消息。

    -

    flags

    -

    用于指定发送消息时行为特性,有如下行为特性:

    -
    • MSG_MORE:允许将多次发送的消息进行拼包发送。
    • MSG_DONTWAIT:非阻塞操作。
    -
    - - **返回值:** - - - 成功返回:已发送的消息长度(字节数)。 - - 失败返回:-1,并设置errno。 - - -- **recvmsg** - - **函数原型:** - - ssize\_t recvmsg\(int s, struct msghdr \*message, int flags\) - - **函数功能:**接收消息。 - - **参数说明:** - - - - - - - - - - - - - - - - -

    参数

    -

    描述

    -

    s

    -

    套接字描述符。

    -

    message

    -

    存放接收的消息,不支持接收ancillary消息。

    -

    flags

    -

    用于指定接收消息时行为特性,有如下行为特性:

    -
    • MSG_PEEK:允许预读消息而不取走。
    • MSG_DONTWAIT:非阻塞操作。
    -
    - - **返回值:** - - - 成功返回:已接收的消息长度(字节数)。 - - 失败返回:-1,并设置errno。 - - -- **ioctl** - - **函数原型:** - - int ioctl\(int s, int request, ...\) - - **函数功能:**获取或设置socket属性。 - - **参数说明:** - - - - - - - - - - - - - -

    参数

    -

    描述

    -

    s

    -

    套接字描述符。

    -

    request

    -

    对socket属性要进行的操作,当前支持如下操作:

    -
    • FIONREAD:获取socket当前可读取的数据大小(字节数)。
    • FIONBIO:设置socket是否非阻塞。
    -
    - - **返回值:** - - - 成功返回:0。 - - 失败返回:-1,并设置errno。 - - diff --git "a/zh-cn/device-dev/kernel/\347\275\221\347\273\234\345\221\275\344\273\244.md" "b/zh-cn/device-dev/kernel/\347\275\221\347\273\234\345\221\275\344\273\244.md" deleted file mode 100755 index 2a1245c157..0000000000 --- "a/zh-cn/device-dev/kernel/\347\275\221\347\273\234\345\221\275\344\273\244.md" +++ /dev/null @@ -1,25 +0,0 @@ -# 网络命令 - -- **[arp](arp.md)** - -- **[dhclient](dhclient.md)** - -- **[dns](dns.md)** - -- **[ifconfig](ifconfig.md)** - -- **[ipdebug](ipdebug.md)** - -- **[netstat](netstat.md)** - -- **[ntpdate](ntpdate.md)** - -- **[ping](ping.md)** - -- **[ping6](ping6.md)** - -- **[telnet](telnet.md)** - -- **[tftp](tftp.md)** - - diff --git "a/zh-cn/device-dev/kernel/\350\256\244\350\257\206LiteOS-M\345\206\205\346\240\270.md" "b/zh-cn/device-dev/kernel/\350\256\244\350\257\206LiteOS-M\345\206\205\346\240\270.md" deleted file mode 100644 index 7984b0843b..0000000000 --- "a/zh-cn/device-dev/kernel/\350\256\244\350\257\206LiteOS-M\345\206\205\346\240\270.md" +++ /dev/null @@ -1,62 +0,0 @@ -# 认识LiteOS-M内核 - -- [内核简介](#section1429342661510) - - [cpu体系架构支持](#section48891456112819) - - [运行机制](#section4599142312817) - - -## 内核简介 - -OpenHarmony LiteOS-M内核是面向IoT领域构建的轻量级物联网操作系统内核,具有小体积、低功耗、高性能的特点。其代码结构简单,主要包括内核最小功能集、内核抽象层、可选组件以及工程目录等。OpenHarmony LiteOS-M内核架构包含硬件相关层以及硬件无关层,如下图所示,其中Kernel Arch模块属于硬件相关层,该模块按不同编译工具链、芯片架构分类,提供统一的HAL(Hardware Abstraction Layer)接口,提升了硬件易适配性,满足AIoT类型丰富的硬件和编译工具链的拓展;Components等其他模块属于硬件无关层,其中Kernel Task等内核模块提供基础能力,Components模块提供网络、文件系统等组件能力,Utils模块提供错误处理、调测等能力,KAL(Kernel Abstraction Layer)模块提供统一的标准接口。 - -**图 1** 内核架构图 -![](figures/内核架构图.png "内核架构图") - -### cpu体系架构支持 - -CPU体系架构分为通用架构定义和特定架构定义两层,通用架构定义层为所有体系架构都需要支持和实现的接口,特定架构定义层为特定体系架构所特有的部分。在新增一个体系架构的时候,必须需要实现通用架构定义层,如果该体系架构还有特有的功能,可以在特定架构定义层来实现。 - -**表 1** CPU体系架构规则 - - - - - - - - - - - - - - - - - - - - -

    规则

    -

    通用体系架构层

    -

    特定体系架构层

    -

    头文件位置

    -

    kernel/arch/include

    -

    kernel/arch/<arch>/<arch>/<toolchain>/

    -

    头文件命名

    -

    los_<function>.h

    -

    los_arch_<function>.h

    -

    函数命名

    -

    Halxxxx

    -

    Halxxxx

    -
    - -LiteOS-M已经支持ARM Cortex-M3、ARM Cortex-M4、ARM Cortex-M7、ARM Cortex-M33、RISC-V等主流架构,如果需要扩展CPU体系架构,请参考[芯片架构适配点](https://gitee.com/openharmony/docs/blob/master/zh-cn/device-dev/porting/%E7%A7%BB%E6%A4%8D%E6%A6%82%E8%BF%B0.md#%E8%8A%AF%E7%89%87%E6%9E%B6%E6%9E%84%E9%80%82%E9%85%8D%E7%82%B9)。 - -### 运行机制 - -在开发板配置文件target\_config.h配置系统时钟、每秒Tick数,可以对任务、内存、IPC、异常处理模块进行裁剪配置。系统启动时,根据配置进行指定模块的初始化。内核启动流程包含外设初始化、系统时钟配置、内核初始化、操作系统启动等,详见内核启动流程图。 - -**图 2** 内核启动流程 -![](figures/内核启动流程.png "内核启动流程") - diff --git "a/zh-cn/device-dev/kernel/\350\260\203\346\265\213.md" "b/zh-cn/device-dev/kernel/\350\260\203\346\265\213.md" deleted file mode 100755 index 2327e14123..0000000000 --- "a/zh-cn/device-dev/kernel/\350\260\203\346\265\213.md" +++ /dev/null @@ -1,15 +0,0 @@ -# 调测 - -- **[Shell介绍](Shell介绍.md)** - -- **[Shell命令开发指导](Shell命令开发指导.md)** - -- **[Shell命令编程实例](Shell命令编程实例.md)** - -- **[Shell命令使用详解](Shell命令使用详解.md)** - -- **[魔法键使用方法](魔法键使用方法.md)** - -- **[用户态异常信息说明](用户态异常信息说明.md)** - - diff --git "a/zh-cn/device-dev/kernel/\350\270\251\345\206\205\345\255\230\346\243\200\346\265\213.md" "b/zh-cn/device-dev/kernel/\350\270\251\345\206\205\345\255\230\346\243\200\346\265\213.md" deleted file mode 100644 index ab5d4101a0..0000000000 --- "a/zh-cn/device-dev/kernel/\350\270\251\345\206\205\345\255\230\346\243\200\346\265\213.md" +++ /dev/null @@ -1,85 +0,0 @@ -# 踩内存检测 - -- [基础概念](#section17368154517335) -- [功能配置](#section4696190123420) -- [开发指导](#section672362973417) - - [开发流程](#section026014863416) - - [编程实例](#section186311302356) - - [示例代码](#section12709533354) - - [结果验证](#section81214126369) - - -## 基础概念 - -踩内存检测机制作为内核的可选功能,用于检测动态内存池的完整性。通过该机制,可以及时发现内存池是否发生了踩内存问题,并给出错误信息,便于及时发现系统问题,提高问题解决效率,降低问题定位成本。 - -## 功能配置 - -LOSCFG\_BASE\_MEM\_NODE\_INTEGRITY\_CHECK:开关宏,默认关闭;若打开这个功能,在target\_config.h中将这个宏定义为1。 - -1. 开启这个功能,每次申请内存,会实时检测内存池的完整性。 -2. 如果不开启该功能,也可以调用LOS\_MemIntegrityCheck接口检测,但是每次申请内存时,不会实时检测内存完整性,而且由于节点头没有魔鬼数字(开启时才有,省内存),检测的准确性也会相应降低,但对于系统的性能没有影响,故根据实际情况开关该功能。 - -由于该功能只会检测出哪个内存节点被破坏了,并给出前节点信息(因为内存分布是连续的,当前节点最有可能被前节点破坏)。如果要进一步确认前节点在哪里申请的,需开启内存泄漏检测功能,通过LR记录,辅助定位。 - ->![](public_sys-resources/icon-caution.gif) **注意:** ->开启该功能,节点头多了魔鬼数字字段,会增大节点头大小。由于实时检测完整性,故性能影响较大;若性能敏感的场景,可以不开启该功能,使用LOS\_MemIntegrityCheck接口检测。 - -## 开发指导 - -### 开发流程 - -通过调用LOS\_MemIntegrityCheck接口检测内存池是否发生了踩内存,如果没有踩内存问题,那么接口返回0且没有log输出;如果存在踩内存问题,那么会输出相关log,详见下文编程实例的结果输出。 - -### 编程实例 - -本实例实现如下功能: - -1. 申请两个物理上连续的内存块; -2. 通过memset构造越界访问,踩到下个节点的头4个字节; -3. 调用LOS\_MemIntegrityCheck检测是否发生踩内存。 - -### 示例代码 - -代码实现如下: - -``` -#include -#include -#include "los_memory.h" -#include "los_config.h" - -void MemIntegrityTest(void) -{ - /* 申请两个物理连续的内存块 */ - void *ptr1 = LOS_MemAlloc(LOSCFG_SYS_HEAP_ADDR, 8); - void *ptr2 = LOS_MemAlloc(LOSCFG_SYS_HEAP_ADDR, 8); - /* 第一个节点内存块大小是8字节,那么12字节的清零,会踩到第二个内存节点的节点头,构造踩内存场景 */ - memset(ptr1, 0, 8 + 4); - LOS_MemIntegrityCheck(LOSCFG_SYS_HEAP_ADDR); -} -``` - -### 结果验证 - -编译运行输出log如下: - -``` -[ERR][OsMemMagicCheckPrint], 2028, memory check error! -memory used but magic num wrong, magic num = 0x00000000 /* 提示信息,检测到哪个字段被破坏了,用例构造了将下个节点的头4个字节清零,即魔鬼数字字段 */ - - broken node head: 0x20003af0 0x00000000 0x80000020, prev node head: 0x20002ad4 0xabcddcba 0x80000020 -/* 被破坏节点和其前节点关键字段信息,分别为其前节点地址、节点的魔鬼数字、节点的sizeAndFlag;可以看出被破坏节点的魔鬼数字字段被清零,符合用例场景 */ - - broken node head LR info: /* 节点的LR信息需要开启内存检测功能才有有效输出 */ - LR[0]:0x0800414e - LR[1]:0x08000cc2 - LR[2]:0x00000000 - - pre node head LR info: /* 通过LR信息,可以在汇编文件中查找前节点是哪里申请,然后排查其使用的准确性 */ - LR[0]:0x08004144 - LR[1]:0x08000cc2 - LR[2]:0x00000000 -[ERR]Memory interity check error, cur node: 0x20003b10, pre node: 0x20003af0 /* 被破坏节点和其前节点的地址 */ -``` - diff --git "a/zh-cn/device-dev/kernel/\350\275\257\344\273\266\345\256\232\346\227\266\345\231\250.md" "b/zh-cn/device-dev/kernel/\350\275\257\344\273\266\345\256\232\346\227\266\345\231\250.md" deleted file mode 100644 index 903970bdd6..0000000000 --- "a/zh-cn/device-dev/kernel/\350\275\257\344\273\266\345\256\232\346\227\266\345\231\250.md" +++ /dev/null @@ -1,7 +0,0 @@ -# 软件定时器 - -- **[基本概念](基本概念-15.md)** - -- **[开发指导](开发指导-16.md)** - - diff --git "a/zh-cn/device-dev/kernel/\350\275\273\351\207\217\345\222\214\345\260\217\345\236\213\347\263\273\347\273\237\345\206\205\346\240\270.md" "b/zh-cn/device-dev/kernel/\350\275\273\351\207\217\345\222\214\345\260\217\345\236\213\347\263\273\347\273\237\345\206\205\346\240\270.md" deleted file mode 100644 index 0ae605881a..0000000000 --- "a/zh-cn/device-dev/kernel/\350\275\273\351\207\217\345\222\214\345\260\217\345\236\213\347\263\273\347\273\237\345\206\205\346\240\270.md" +++ /dev/null @@ -1,7 +0,0 @@ -# 轻量和小型系统内核 - -- **[轻量系统内核](轻量系统内核.md)** - -- **[小型系统内核](小型系统内核.md)** - - diff --git "a/zh-cn/device-dev/kernel/\350\275\273\351\207\217\347\263\273\347\273\237\345\206\205\346\240\270.md" "b/zh-cn/device-dev/kernel/\350\275\273\351\207\217\347\263\273\347\273\237\345\206\205\346\240\270.md" deleted file mode 100644 index 290c4915bf..0000000000 --- "a/zh-cn/device-dev/kernel/\350\275\273\351\207\217\347\263\273\347\273\237\345\206\205\346\240\270.md" +++ /dev/null @@ -1,11 +0,0 @@ -# 轻量系统内核 - -- **[基础内核](基础内核.md)** - -- **[文件系统](文件系统.md)** - -- **[标准库](标准库.md)** - -- **[调测](调测.md)** - - diff --git "a/zh-cn/device-dev/kernel/\350\277\233\347\250\213.md" "b/zh-cn/device-dev/kernel/\350\277\233\347\250\213.md" deleted file mode 100755 index c425b175ae..0000000000 --- "a/zh-cn/device-dev/kernel/\350\277\233\347\250\213.md" +++ /dev/null @@ -1,301 +0,0 @@ -# 进程 - -- [基本概念](#section29197338383) -- [使用场景](#section85513272398) -- [接口说明](#section4517119124015) - -## 基本概念 - -从系统的角度看,进程是资源管理单元。进程可以使用或等待CPU、使用内存空间等系统资源,并独立于其它进程运行。 - -OpenHarmony内核的进程模块可以给用户提供多个进程,实现了进程之间的切换和通信,帮助用户管理业务程序流程。这样用户可以将更多的精力投入到业务功能的实现中。 - -OpenHarmony内核中的进程采用抢占式调度机制,支持时间片轮转调度方式。 - -OpenHarmony内核的进程一共有32个优先级\(0-31\),用户进程可配置的优先级有22个\(10-31\),最高优先级为10,最低优先级为31。 - -高优先级的进程可抢占低优先级进程,低优先级进程必须在高优先级进程阻塞或结束后才能得到调度。 - -每一个用户态进程均拥有自己独立的进程空间,相互之间不可见,实现进程间隔离。 - -用户态根进程init由内核态创建,其它用户态进程均由init进程fork而来。 - -**进程状态说明:** - -- 初始化(Init):该进程正在被创建。 - -- 就绪(Ready):该进程在就绪列表中,等待CPU调度。 - -- 运行(Running):该进程正在运行。 - -- 阻塞(Pending):该进程被阻塞挂起。本进程内所有的线程均被阻塞时,进程被阻塞挂起。 - -- 僵尸态(Zombies):该进程运行结束,等待父进程回收其控制块资源。 - - -**图 1** 进程状态迁移示意图 -![](figures/进程状态迁移示意图.png "进程状态迁移示意图") - -**进程状态迁移说明:** - -- Init→Ready: - - 进程创建或fork时,拿到该进程控制块后进入Init状态,处于进程初始化阶段,当进程初始化完成将进程插入调度队列,此时进程进入就绪状态。 - -- Ready→Running: - - 进程创建后进入就绪态,发生进程切换时,就绪列表中最高优先级的进程被执行,从而进入运行态。若此时该进程中已无其它线程处于就绪态,则该进程从就绪列表删除,只处于运行态;若此时该进程中还有其它线程处于就绪态,则该进程依旧在就绪队列,此时进程的就绪态和运行态共存。 - -- Running→Pending: - - 进程内所有的线程均处于阻塞态时,进程在最后一个线程转为阻塞态时,同步进入阻塞态,然后发生进程切换。 - -- Pending→Ready: - - 阻塞进程内的任意线程恢复就绪态时,进程被加入到就绪队列,同步转为就绪态。 - -- Ready→Pending: - - 进程内的最后一个就绪态线程处于阻塞态时,进程从就绪列表中删除,进程由就绪态转为阻塞态。 - -- Running→Ready: - - 进程由运行态转为就绪态的情况有以下两种: - - 1. 有更高优先级的进程创建或者恢复后,会发生进程调度,此刻就绪列表中最高优先级进程变为运行态,那么原先运行的进程由运行态变为就绪态。 - 2. 若进程的调度策略为SCHED\_RR,且存在同一优先级的另一个进程处于就绪态,则该进程的时间片消耗光之后,该进程由运行态转为就绪态,另一个同优先级的进程由就绪态转为运行态。 - -- Running→Zombies: - - 当进程的主线程或所有线程运行结束后,进程由运行态转为僵尸态,等待父进程回收资源。 - - -## 使用场景 - -进程创建后,用户只能操作自己进程空间的资源,无法操作其它进程的资源(共享资源除外)。 用户态允许进程挂起,恢复,延时等操作,同时也可以设置用户态进程调度优先级和调度策略,获取进程调度优先级和调度策略。进程结束的时候,进程会主动释放持有的进程资源,但持有的进程pid资源需要父进程通过wait/waitpid或父进程退出时回收。 - -## 接口说明 - -OpenHarmony内核系统中的进程管理模块为用户提供下面几种功能: - -**表 1** 进程管理模块功能 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    功能分类

    -

    接口名

    -

    描述

    -

    备注

    -

    进程

    -

    fork

    -

    创建一个新进程。

    -

    -

    -

    exit

    -

    终止进程。

    -

    -

    -

    atexit

    -

    注册正常进程终止的回调函数。

    -

    -

    -

    abort

    -

    中止进程执行。

    -

    -

    -

    getpid

    -

    获取进程ID。

    -

    -

    -

    getppid

    -

    获取父进程ID。

    -

    -

    -

    getpgrp

    -

    获取调用进程的进程组ID。

    -

    -

    -

    getpgid

    -

    获取进程的进程组ID。

    -

    -

    -

    setpgrp

    -

    设置调用进程的进程组ID。

    -

    -

    -

    setpgid

    -

    设置进程的进程组ID。

    -

    -

    -

    kill

    -

    给进程发送信号。

    -
    • 仅支持1-30号信号的发送。
    • 信号的默认行为不支持STOP及CONTINUE,无COREDUMP功能。
    • 不能屏蔽SIGSTOP、SIGKILL、SIGCONT。
    • 异步信号,发送信号给某进程后,直到该进程被调度后才会执行信号回调(为安全起见,杀死进程的动作是进程自己执行的,内核不能通过信号强制杀死对方)。
    • 进程消亡会发送SIGCHLD给父进程,发送动作无法取消。
    • 无法通过信号唤醒正在睡眠的进程。
    -

    wait

    -

    等待任意子进程结束并回收子进程资源。

    -

    status的值可以由以下宏定义解析:

    -
    • WIFEXITED(status):如果子进程正常结束,它就返回真;否则返回假。
    • WEXITSTATUS(status):如果WIFEXITED(status)为真,则可以用该宏取得子进程exit()返回的退出码。
    • WTERMSIG(status) 仅支持以下情况:子进程触发异常结束后通过WTERMSIG获取的进程退出编号始终为SIGUSR2。
    • 不支持的操作: WIFSTOPPED、WSTOPSIG、WCOREDUMP 、WIFCONTINUED。
    -

    waitpid

    -

    等待子进程结束并回收子进程资源。

    -

    options:不支持WUNTRACED,WCONTINUED;

    -

    status的值可以由以下宏定义解析:

    -
    • WIFEXITED(status):如果子进程正常结束,它就返回真;否则返回假。
    • WEXITSTATUS(status):如果WIFEXITED(status)为真,则可以用该宏取得子进程exit()返回的退出码。
    • WTERMSIG(status)仅支持以下情况:子进程触发异常结束后通过WTERMSIG获取的进程退出编号始终为SIGUSR2。
    • 不支持:WIFSTOPPED 、WSTOPSIG、WCOREDUMP 、WIFCONTINUED。
    -

    调度

    -

    getpriority

    -

    获取指定ID的静态优先级。

    -
    • 不支持:PRIO_PGRP、PRIO_USER。
    -
    • 无动态优先级概念,用于设置静态优先级。
    -

    setpriority

    -

    设置指定ID的静态优先级。

    -

    sched_rr_get_interval

    -

    获取执行时间限制。

    -

    -

    -

    sched_yield

    -

    系统调用运行进程主动让出执行权。

    -

    -

    -

    sched_get_priority_max

    -

    获取进程静态优先级取值范围的最大值。

    -

    调度策略只支持:SCHED_RR。

    -

    sched_get_priority_min

    -

    获取进程静态优先级取值范围的最小值。

    -

    sched_getscheduler

    -

    获取调度策略。

    -

    sched_setscheduler

    -

    设置调度策略。

    -

    sched_getparam

    -

    获取调度参数。

    -

    -

    -

    sched_setparam

    -

    设置调度参数。

    -

    -

    -

    exec

    -

    execl

    -

    执行指定的elf格式的用户程序文件。

    -

    -

    -

    execle

    -

    执行指定的elf格式的用户程序文件。

    -

    -

    -

    execlp

    -

    执行指定的elf格式的用户程序文件。

    -

    -

    -

    execv

    -

    执行指定的elf格式的用户程序文件。

    -

    -

    -

    execve

    -

    执行指定的elf格式的用户程序文件。

    -

    -

    -

    execvp

    -

    执行指定的elf格式的用户程序文件。

    -

    -

    -
    - diff --git "a/zh-cn/device-dev/kernel/\351\231\204\345\275\225.md" "b/zh-cn/device-dev/kernel/\351\231\204\345\275\225.md" deleted file mode 100644 index 73adc5ca61..0000000000 --- "a/zh-cn/device-dev/kernel/\351\231\204\345\275\225.md" +++ /dev/null @@ -1,9 +0,0 @@ -# 附录 - -- **[内核编码规范](内核编码规范.md)** - -- **[基本数据结构](基本数据结构.md)** - -- **[标准库支持](标准库支持.md)** - - diff --git "a/zh-cn/device-dev/kernel/\351\235\231\346\200\201\345\206\205\345\255\230.md" "b/zh-cn/device-dev/kernel/\351\235\231\346\200\201\345\206\205\345\255\230.md" deleted file mode 100644 index 090cea4a0d..0000000000 --- "a/zh-cn/device-dev/kernel/\351\235\231\346\200\201\345\206\205\345\255\230.md" +++ /dev/null @@ -1,182 +0,0 @@ -# 静态内存 - -- [运行机制](#section165473517522) -- [开发指导](#section57511620165218) - - [使用场景](#section215474911529) - - [接口说明](#section79231214539) - - [开发流程](#section1388511316548) - - [编程实例](#section17801515105519) - - [结果验证](#section11818154112319) - - -## 运行机制 - -静态内存实质上是一个静态数组,静态内存池内的块大小在初始化时设定,初始化后块大小不可变更。 - -静态内存池由一个控制块LOS\_MEMBOX\_INFO和若干相同大小的内存块LOS\_MEMBOX\_NODE构成。控制块位于内存池头部,用于内存块管理,包含内存块大小uwBlkSize,内存块数量uwBlkNum,已分配使用的内存块数量uwBlkCnt和空闲内存块链表stFreeList。内存块的申请和释放以块大小为粒度,每个内存块包含指向下一个内存块的指针pstNext。 - -**图 1** 静态内存示意图 -![](figures/静态内存示意图.png "静态内存示意图") - -## 开发指导 - -### 使用场景 - -当用户需要使用固定长度的内存时,可以通过静态内存分配的方式获取内存,一旦使用完毕,通过静态内存释放函数归还所占用内存,使之可以重复使用。 - -### 接口说明 - -OpenHarmony LiteOS-M的静态内存管理主要为用户提供以下功能,接口详细信息可以查看API参考。 - -**表 1** 静态内存模块接口 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    功能分类

    -

    接口名

    -

    描述

    -

    初始化静态内存池

    -

    LOS_MemboxInit

    -

    初始化一个静态内存池,根据入参设定其起始地址、总大小及每个内存块大小。

    -

    清除静态内存块内容

    -

    LOS_MemboxClr

    -

    清零从静态内存池中申请的静态内存块的内容。

    -

    申请、释放静态内存

    -

    LOS_MemboxAlloc

    -

    从指定的静态内存池中申请一块静态内存块。

    -

    LOS_MemboxFree

    -

    释放从静态内存池中申请的一块静态内存块。

    -

    获取、打印静态内存池信息

    -

    LOS_MemboxStatisticsGet

    -

    获取指定静态内存池的信息,包括内存池中总内存块数量、已经分配出去的内存块数量、每个内存块的大小。

    -

    LOS_ShowBox

    -

    打印指定静态内存池所有节点信息(打印等级是LOS_INFO_LEVEL),包括内存池起始地址、内存块大小、总内存块数量、每个空闲内存块的起始地址、所有内存块的起始地址。

    -
    - ->![](public_sys-resources/icon-note.gif) **说明:** ->初始化后的内存池的内存块数量,不等于总大小除于内存块大小,因为内存池的控制块和每个内存块的控制头,都存在内存开销,设置总大小时,需要将这些因素考虑进去。 - -### 开发流程 - -本节介绍使用静态内存的典型场景开发流程。 - -1. 规划一片内存区域作为静态内存池。 -2. 调用LOS\_MemboxInit初始化静态内存池。 - - 初始化会将入参指定的内存区域分割为N块(N值取决于静态内存总大小和块大小),将所有内存块挂到空闲链表,在内存起始处放置控制头。 - -3. 调用LOS\_MemboxAlloc接口分配静态内存。 - - 系统将会从空闲链表中获取第一个空闲块,并返回该内存块的起始地址。 - -4. 调用LOS\_MemboxClr接口。 - - 将入参地址对应的内存块清零。 - -5. 调用LOS\_MemboxFree接口。 - - 将该内存块加入空闲链表。 - - -### 编程实例 - -本实例执行以下步骤: - -1. 初始化一个静态内存池。 -2. 从静态内存池中申请一块静态内存。 -3. 在内存块存放一个数据。 -4. 打印出内存块中的数据。 -5. 清除内存块中的数据。 -6. 释放该内存块。 - - 示例代码如下: - - -``` -#include "los_membox.h" - -VOID Example_StaticMem(VOID) -{ - UINT32 *mem = NULL; - UINT32 blkSize = 10; - UINT32 boxSize = 100; - UINT32 boxMem[1000]; - UINT32 ret; - - /*内存池初始化*/ - ret = LOS_MemboxInit(&boxMem[0], boxSize, blkSize); - if(ret != LOS_OK) { - printf("Membox init failed!\n"); - return; - } else { - printf("Membox init success!\n"); - } - - /*申请内存块*/ - mem = (UINT32 *)LOS_MemboxAlloc(boxMem); - if (NULL == mem) { - printf("Mem alloc failed!\n"); - return; - } - printf("Mem alloc success!\n"); - - /*赋值*/ - *mem = 828; - printf("*mem = %d\n", *mem); - - /*清除内存内容*/ - LOS_MemboxClr(boxMem, mem); - printf("Mem clear success \n *mem = %d\n", *mem); - - /*释放内存*/ - ret = LOS_MemboxFree(boxMem, mem); - if (LOS_OK == ret) { - printf("Mem free success!\n"); - } else { - printf("Mem free failed!\n"); - } - - return; -} -``` - -### 结果验证 - -输出结果如下: - -``` -Membox init success! -Mem alloc success! -*mem = 828 -Mem clear success -*mem = 0 -Mem free success! -``` - diff --git "a/zh-cn/device-dev/kernel/\351\255\224\346\263\225\351\224\256\344\275\277\347\224\250\346\226\271\346\263\225.md" "b/zh-cn/device-dev/kernel/\351\255\224\346\263\225\351\224\256\344\275\277\347\224\250\346\226\271\346\263\225.md" deleted file mode 100755 index 9bd18a8340..0000000000 --- "a/zh-cn/device-dev/kernel/\351\255\224\346\263\225\351\224\256\344\275\277\347\224\250\346\226\271\346\263\225.md" +++ /dev/null @@ -1,38 +0,0 @@ -# 魔法键使用方法 - -- [使用场景](#section2350114718546) -- [使用方法](#section3305151511559) - -## 使用场景 - -在系统运行出现无响应等情况时,可以通过魔法键功能确定系统是否被锁中断(魔法键也无响应)或者查看系统任务运行状态等信息。 - -在中断有响应的情况下,可以通过魔法键查看task信息中 cpup(CPU占用率)看是哪个任务长时间占用CPU导致系统其他任务无响应(一般为比较高优先级任务一直抢占CPU,导致低优先级任务无响应)。 - -## 使用方法 - -1. 配置宏LOSCFG\_ENABLE\_MAGICKEY。 - -魔法键依赖于宏LOSCFG\_ENABLE\_MAGICKEY,使用时通过menuconfig在配置项中开启“Enable MAGIC KEY”: - -Debug ---\> Enable MAGIC KEY;若关闭该选项,则魔法键失效。 - ->![](public_sys-resources/icon-note.gif) **说明:** ->1. 可以在menuconfig中,将光标移动到LOSCFG\_ENABLE\_MAGICKEY上,输入“?”,查看帮助信息。 - -2. 输入“ctrl + r”键,打开魔法键检测功能。 - -在连接UART或者USB转虚拟串口的情况下,输入“ctrl + r” 键,打开魔法键检测功能,输出 “Magic key on”;再输入一次后,则关闭魔法键检测功能,输出“Magic key off”。魔法键功能如下: - -- ctrl + z:帮助键,输出相关魔法键简单介绍; - -- ctrl + t:输出任务相关信息; - -- ctrl + p:系统主动进入panic,输出panic相关信息后,系统会挂住; - -- ctrl + e:系统进行简单完整性内存池检查,检查出错会输出相关错误信息,检查正常会输出“system memcheck over, all passed!”。 - - ->![](public_sys-resources/icon-notice.gif) **须知:** ->魔法键检测功能打开情况下,如果需要通过UART或者USB转虚拟串口输入特殊字符需避免与魔法键值重复,否则魔法键会被误触发,而原有设计功能可能出现错误。 - diff --git "a/zh-cn/device-dev/porting/CMake\346\226\271\345\274\217\347\273\204\347\273\207\347\274\226\350\257\221\347\232\204\345\272\223\347\247\273\346\244\215.md" "b/zh-cn/device-dev/porting/CMake\346\226\271\345\274\217\347\273\204\347\273\207\347\274\226\350\257\221\347\232\204\345\272\223\347\247\273\346\244\215.md" deleted file mode 100755 index bb7404eca3..0000000000 --- "a/zh-cn/device-dev/porting/CMake\346\226\271\345\274\217\347\273\204\347\273\207\347\274\226\350\257\221\347\232\204\345\272\223\347\247\273\346\244\215.md" +++ /dev/null @@ -1,435 +0,0 @@ -# CMake方式组织编译的库移植 - -- [源码获取](#section1771132116245) -- [移植思路](#section9737174410328) -- [交叉编译](#section38205577332) - - [编译参考](#section1088111263418) - - [设置执行交叉编译](#section8168182883515) - -- [测试](#section6686144293611) -- [将该库编译添加到OpenHarmony工程中](#section1651053153715) - -以double-conversion库为例,其移植过程如下文所示 - -## 源码获取 - -从仓库[获取double-conversion源码](https://github.com/google/double-conversion),其目录结构如下表: - -**表 1** 源码目录结构 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    名称

    -

    描述

    -

    double-conversion/cmake/

    -

    CMake组织编译使用到的模板

    -

    double-conversion/double-conversion/

    -

    源文件目录

    -

    double-conversion/msvc/

    -

    -

    -

    double-conversion/test/

    -

    测试用例源文件

    -

    double-conversion/.gitignore

    -

    -

    -

    double-conversion/AUTHORS

    -

    -

    -

    double-conversion/BUILD

    -

    -

    -

    double-conversion/CMakeLists.txt

    -

    CMake方式顶层编译组织文件

    -

    double-conversion/COPYING

    -

    -

    -

    double-conversion/Changelog

    -

    -

    -

    double-conversion/LICENSE

    -

    -

    -

    double-conversion/Makefile

    -

    -

    -

    double-conversion/README.md

    -

    -

    -

    double-conversion/SConstruct

    -

    -

    -

    double-conversion/WORKSPACE

    -

    -

    -
    - -## 移植思路 - -移植思路:通过修改工具链,交叉编译该三方库,生成OpenHarmony平台的可执行文件,最后再通过GN调用CMake的方式添加到OpenHarmony工程中。 - -## 交叉编译 - -### 编译参考 - -代码仓库的[README.md](https://github.com/google/double-conversion/blob/master/README.md)中详细介绍了使用CMake编译double-conversion库的步骤,以及测试方法。本文参考该指导设置该库的编译配置,并完成测试。若开发人员在移植过程中对该库的编译选项配置有疑惑的地方,可参考该指导。对于其他使用CMake可独立编译的三方库,在移植时可以参考其自带的编译指导。 - -### 设置执行交叉编译 - -CMake方式可通过指定工具链进行交叉编译,修改并编译该库,生成OpenHarmony平台的可执行文件,步骤如下: - -1. 设置工具链 - - 将下列clang工具链配置添加到该工程的顶层CMakeLists.txt(即[表1中的该文件](#table824211132418))中即可。 - - ``` - set(CMAKE_CROSSCOMPILING TRUE) - set(CMAKE_SYSTEM_NAME Generic) - set(CMAKE_CXX_COMPILER_ID Clang) - set(CMAKE_TOOLCHAIN_PREFIX llvm-) - #指定c编译工具(确保工具链所在路径已经添加到了PATH环境变量中)和编译标志,使用clang编译时标志中必须指定--target,否则无法交叉编译。 - set(CMAKE_C_COMPILER clang) - set(CMAKE_C_FLAGS "--target=arm-liteos -D__clang__ -march=armv7-a -w") - #指定c++编译工具(确保工具链所在路径已经添加到了PATH环境变量中)和编译标志,必须指定--target,否则无法交叉编译。 - set(CMAKE_CXX_COMPILER clang++) - set(CMAKE_CXX_FLAGS "--target=arm-liteos -D__clang__ -march=armv7-a -w") - #指定链接工具和链接标志,必须指定--target和--sysroot,其中OHOS_ROOT_PATH可通过cmake命令后缀参数来指定。 - set(MY_LINK_FLAGS "--target=arm-liteos --sysroot=${OHOS_SYSROOT_PATH}") - set(CMAKE_LINKER clang) - set(CMAKE_CXX_LINKER clang++) - set(CMAKE_C_LINKER clang) - set(CMAKE_C_LINK_EXECUTABLE "${CMAKE_C_LINKER} - ${MY_LINK_FLAGS} -o ") - set(CMAKE_CXX_LINK_EXECUTABLE "${CMAKE_CXX_LINKER} - ${MY_LINK_FLAGS} -o ") - #指定链接库的查找路径。 - set(CMAKE_SYSROOT ${OHOS_SYSROOT_PATH}) - ``` - -2. 执行编译 - - linux命令行中进入double-conversion的源文件目录(即[表1所示目录](#table824211132418)),执行下列命令: - - ``` - mkdir build && cd build - cmake .. -DBUILD_TESTING=ON -DOHOS_SYSROOT_PATH="..." - make -j - ``` - - 其中OHOS\_SYSROOT\_PATH需用绝对路径指定出sysroot目录的位置,以OpenHarmony为例即目录openHarmony/prebuilts/lite/sysroot的绝对路径。 - -3. 查看结果 - - 步骤2操作完成后,build目录下会生成静态库文件和测试用例: - - **表 2** 编译生成文件目录结构 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    名称

    -

    描述

    -

    double-conversion/build/libdouble-conversion.a

    -

    生成的静态库文件

    -

    double-conversion/build/test/

    -

    目录下存放生成的测试用例和相关CMake缓存文件

    -

    double-conversion/build/CMakeCache.txt

    -

    CMake构建过程中的缓存文件

    -

    double-conversion/build/CMakeFiles/

    -

    -

    -

    double-conversion/build/cmake_install.cmake

    -

    -

    -

    double-conversion/build/CTestTestfile.cmake

    -

    -

    -

    double-conversion/build/DartConfiguration.tcl

    -

    -

    -

    double-conversion/build/generated/

    -

    -

    -

    double-conversion/build/Makefile

    -

    -

    -

    double-conversion/build/Testing/

    -

    -

    -
    - - -## 测试 - -1. 搭建OpenHarmony环境 - - 以hi3518ev300为例,编译出OpenHarmony镜像,烧写到开发板,参考[开发Hi3518第一个示例程序](https://device.harmonyos.com/cn/docs/start/introduce/oem_camera_start_example-0000001051610926)。 - - 进入系统如下所示: - - **图 1** OpenHarmony启动成功界面 - ![](figures/OpenHarmony启动成功界面.png "OpenHarmony启动成功界面") - -2. 挂载nfs目录,将[表2](#table1452412391911)中test目录下cctest可执行文件放入nfs目录 -3. 执行用例 - - 该库采用非交叉编译时用例是通过make test执行,CMake会有相关的执行结果统计;交叉编译时无法使用该方法,因此可直接执行生成的测试文件完成测试。 - - - 挂载成功后执行下列命令可列出用例所有条目: - - ``` - cd nfs - ./cctest --list - ``` - - 上述命令执行结果部分展示: - - ``` - test-bignum/Assign< - test-bignum/ShiftLeft< - test-bignum/AddUInt64< - test-bignum/AddBignum< - test-bignum/SubtractBignum< - test-bignum/MultiplyUInt32< - test-bignum/MultiplyUInt64< - test-bignum/MultiplyPowerOfTen< - test-bignum/DivideModuloIntBignum< - test-bignum/Compare< - test-bignum/PlusCompare< - test-bignum/Square< - test-bignum/AssignPowerUInt16< - test-bignum-dtoa/BignumDtoaVariousDoubles< - test-bignum-dtoa/BignumDtoaShortestVariousFloats< - test-bignum-dtoa/BignumDtoaGayShortest< - test-bignum-dtoa/BignumDtoaGayShortestSingle< - test-bignum-dtoa/BignumDtoaGayFixed< - test-bignum-dtoa/BignumDtoaGayPrecision< - test-conversions/DoubleToShortest< - test-conversions/DoubleToShortestSingle< - ... - ``` - - - 以test-bignum条目为例,执行下列命令开始测试: - - ``` - ./cctest test-bignum - ``` - - 测试结果如下则表示通过: - - ``` - Ran 13 tests. - ``` - - -## 将该库编译添加到OpenHarmony工程中 - -1. 复制库到OpenHarmony工程中 - - 拷贝已经能够成功交叉编译的库到OpenHarmony的third\_party目录,为了不修改要移植的三方库目录下的BUILD.gn文件,再添加一层目录放置新增的gn转CMake编译适配文件,新增的文件有BUILD.gn、build\_thirdparty.py、 config.gni,新增后的目录结构如下所示。 - - **表 3** 添加到工程后的目录结构 - - - - - - - - - - - - - - - - - - - -

    名称

    -

    描述

    -

    openHarmony/third_party/double-conversion/BUILD.gn

    -

    将三方库加入工程的gn适配文件

    -

    openHarmony/third_party/double-conversion/build_thirdpaty.py

    -

    GN调用shell命令脚本文件,由上面GN文件将相关命令传入,实现GN转CMake

    -

    openHarmony/third_party/double-conversion/config.gni

    -

    三方库编译配置文件,可修改该文件来配置用例是否参与构建等

    -

    openHarmony/third_party/double-conversion/double-conversion/

    -

    要移植的三方库目录

    -
    - -2. 添加gn到CMake适配文件 - - - **新增的BUILD.gn文件实现如下,其他采用CMake方式可独立编译的三方库移植到OpenHarmony平台时只需修改路径即可**。 - - ``` - import("config.gni") - group("double-conversion") { - if (ohos_build_thirdparty_migrated_from_fuchisa == true) { - deps = [":make"] - } - } - if (ohos_build_thirdparty_migrated_from_fuchisa == true) { - action("make") { - script = "//third_party/double-conversion/build_thirdparty.py" - outputs = ["$root_out_dir/log_dc.txt"] - exec_path = rebase_path(rebase_path("./build", ohos_third_party_dir)) - command = "rm * .* -rf && $CMAKE_TOOLS_PATH/cmake .. $CMAKE_FLAG $CMAKE_TOOLCHAIN_FLAG && make -j" - args = [ - "--path=$exec_path", - "--command=${command}" - ] - } - } - ``` - - - **新增的config.gni用于配置该库,实现如下,其他采用CMake方式可独立编译的三方库移植到OpenHarmony时只需修改CMAKE\_FLAG的配置即可。** - - ``` - #CMAKE_FLAG: config compile feature - CMAKE_FLAG = "-DBUILD_TESTING=ON -DCMAKE_CXX_STANDARD=11" - - #toolchain:follow up-layer,depend on $ohos_build_compiler - if (ohos_build_compiler == "clang") { - CMAKE_TOOLCHAIN_FLAG = "-DOHOS_SYSROOT_PATH=${ohos_root_path}prebuilts/lite/sysroot/" - } else { - CMAKE_TOOLCHAIN_FLAG = "" - } - - #CMake tools path,no need setting if this path already joined to $PATH. - CMAKE_TOOLS_PATH = "setting CMake tools path..." - ``` - - - **新增的build\_thirdparty.py实现如下,其他采用CMake方式可独立编译的三方库移植到OpenHarmony时无需修改即可使用。** - - ``` - import os - import sys - from subprocess import Popen - import argparse - import shlex - - def cmd_exec(command): - cmd = shlex.split(command) - proc = Popen(cmd) - proc.wait() - ret_code = proc.returncode - if ret_code != 0: - raise Exception("{} failed, return code is {}".format(cmd, ret_code)) - - def main(): - parser = argparse.ArgumentParser() - parser.add_argument('--path', help='Build path.') - parser.add_argument('--command', help='Build command.') - parser.add_argument('--enable', help='enable python.', nargs='*') - args = parser.parse_args() - - if args.enable: - if args.enable[0] == 'false': - return - - if args.path: - curr_dir = os.getcwd() - os.chdir(args.path) - if args.command: - if '&&' in args.command: - command = args.command.split('&&') - for data in command: - cmd_exec(data) - else: - cmd_exec(args.command) - os.chdir(curr_dir) - - if __name__ == '__main__': - sys.exit(main()) - ``` - - - 在配置文件中添加开关控制该库编译,默认设为关闭 - - 在//build/lite/ohos\_var.gni文件中添加下列配置: - - ``` - declare_args() { - ohos_build_thirdparty_migrated_from_fuchisa = true - } - ``` - -3. 编译构建 - - - 手动单独构建: - - 执行下列命令 - - ``` - hb build -T //third_party/double-conversion:double-conversion - ``` - - 编译成功则[build](#li15717101715249)目录下会生成静态库文件和测试用例 - - diff --git "a/zh-cn/device-dev/porting/Makefile\346\226\271\345\274\217\347\273\204\347\273\207\347\274\226\350\257\221\347\232\204\345\272\223\347\247\273\346\244\215.md" "b/zh-cn/device-dev/porting/Makefile\346\226\271\345\274\217\347\273\204\347\273\207\347\274\226\350\257\221\347\232\204\345\272\223\347\247\273\346\244\215.md" deleted file mode 100755 index a2a6a92ee5..0000000000 --- "a/zh-cn/device-dev/porting/Makefile\346\226\271\345\274\217\347\273\204\347\273\207\347\274\226\350\257\221\347\232\204\345\272\223\347\247\273\346\244\215.md" +++ /dev/null @@ -1,309 +0,0 @@ -# Makefile方式组织编译的库移植 - -- [源码获取](#section114115321416) -- [设置交叉编译](#section81263255384) -- [测试](#section1830015913391) -- [将该库编译添加到OpenHarmony工程中](#section1898016213406) - -以yxml库为例,其移植过程如下文所示 - -## 源码获取 - -从仓库[获取yxml源码](https://github.com/getdnsapi/yxml),其目录结构如下表: - -**表 1** 源码目录结构 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    名称

    -

    描述

    -

    yxml/bench/

    -

    benchmark相关代码

    -

    yxml/test/

    -

    测试输入输出文件,及测试脚本

    -

    yxml/Makefile

    -

    编译组织文件

    -

    yxml/.gitattributes

    -

    -

    -

    yxml/.gitignore

    -

    -

    -

    yxml/COPYING

    -

    -

    -

    yxml/yxml.c

    -

    -

    -

    yxml/yxml.c.in

    -

    -

    -

    yxml/yxml-gen.pl

    -

    -

    -

    yxml/yxml.h

    -

    -

    -

    yxml/yxml.md

    -

    -

    -

    yxml/yxml-states

    -

    -

    -
    - -## 设置交叉编译 - -设置Makefile的交叉编译工具链,修改并编译该库,生成OpenHarmony平台的可执行文件,步骤如下: - -1. 设置工具链 - - 将下列clang工具链配置替换掉yxml库根目录的MakeFile(即[表1中的文件](#table16520154171813))中的原有配置。 - - clang工具链配置 - - ``` - #设置交叉编译工具链,确保工具链所在路径已经添加到了PATH环境变量中 - CC:=clang - AR:=llvm-ar - #cflags中必须要添加--target及--sysroot选项 - CFLAGS:=-Wall -Wextra -Wno-unused-parameter -O2 -g --target=arm-liteos -march=armv7-a --sysroot=$(OHOS_ROOT_PATH)prebuilts/lite/sysroot - ``` - - 原有配置 - - ``` - CC:=gcc - AR:=ar - CFLAGS:=-Wall -Wextra -Wno-unused-parameter -O2 -g - ``` - -2. 执行编译 - - linux命令行中进入yxml的源文件目录(即图1所示目录),执行下列命令: - - ``` - make test OHOS_SYSROOT_PATH=... - ``` - - 其中OHOS\_SYSROOT\_PATH需用绝对路径指定出sysroot所在目录,以OpenHarmony为例即源码根目录prebuilts/lite/sysroot/所在的绝对路径。 - -3. 查看结果 - - 步骤2操作完成后,yxml下会生成out目录,里面有静态库文件和测试用例: - - **表 2** yxml编译生成目录 - - - - - - - - - - - - - -

    名称

    -

    描述

    -

    openHarmony/third_party/yxml/yxml/out/lib/

    -

    编译生成的静态库的存放目录

    -

    openHarmony/third_party/yxml/yxml/out/test/

    -

    编译生成的测试用例及其输入输出等文件的存放目录

    -
    - - -## 测试 - -yxml库测试步骤与double-conversion库基本一致,可参考[CMake方式组织编译的库移植](CMake方式组织编译的库移植.md#section6686144293611)的测试过程,以下内容介绍yxml库测试用例的使用方法: - -**表 3** 生成的test目录结构示意 - - - - - - - - - - - - - - - - - - - -

    名称

    -

    描述

    -

    openHarmony/third_party/yxml/yxml/out/test/test.sh

    -

    自动化测试脚本,由于OpenHarmony不支持脚本运行,因此无法使用,可参考其内容手动测试

    -

    openHarmony/third_party/yxml/yxml/out/test/test

    -

    用于测试的可执行文件

    -

    openHarmony/third_party/yxml/yxml/out/test/*.xml

    -

    测试输入文件

    -

    openHarmony/third_party/yxml/yxml/out/test/*.out

    -

    期望的输出文件

    -
    - -test.sh内容如下所示: - -``` -#!/bin/sh -for i in *.xml; do - b=`basename $i .xml` - o=${b}.out - t=${b}.test - ./test <$i >$t - if [ -n "`diff -q $o $t`" ]; then - echo "Test failed for $i:" - diff -u $o $t - exit 1 - fi -done -echo "All tests completed successfully." -``` - -由于OpenHarmony的shell中暂不支持输入输出重定向(<和\>),所以测试时需要将输入\*.xml文件内容直接复制进shell后回车,输出内容会直接展示在shell窗口。过程如下: - -下列操作假定已按照2.4节的步骤搭建OpenHarmony,挂载并进入nfs目录: - -1. 执行下列命令 - - ``` - ./test - ``` - -2. 复制\*.xml内容到shell - - 以[test目录](#table115941423164318)下pi01.xml为例,内容如下,输入到shell并回车: - - ``` - - ``` - -3. 比较shell中输出的内容与[test目录](#table115941423164318)中对应的\*.out文件是否一致 - - 输出结果如下: - - ``` - pistart SomePI - picontent abc - piend - elemstart a - elemend - ok - ``` - - 经比较与[test目录](#table115941423164318)下pi01.out内容一致,测试通过。 - - -## 将该库编译添加到OpenHarmony工程中 - -yxml库添加的过程除了适配文件build.gn和config.gni有些许变化外,其他和double-conversion库完全一致,参考[CMake方式组织编译的库移植](CMake方式组织编译的库移植.md#section1651053153715)的配置过程。要修改的适配文件及添加后的目录结构如下: - -- yxml库新增的BUILD.gn实现如下: - -``` -import("config.gni") -group("yxml") { - if (ohos_build_thirdparty_migrated_from_fuchisa == true) { - deps = [":make"] - } -} -if (ohos_build_thirdparty_migrated_from_fuchisa == true) { - action("make") { - script = "//third_party/yxml/build_thirdparty.py" - outputs = ["$target_out_dir/log_yxml.txt"] - exec_path = rebase_path(rebase_path("./yxml", root_build_dir)) - command = "make clean && $MAKE_COMMAND" - args = [ - "--path=$exec_path", - "--command=${command}" - ] - } -} -``` - -- yxml库新增的config.gni配置如下: - -``` -TEST_ENABLE = "YES" - -if (TEST_ENABLE == "YES") { - MAKE_COMMAND = "make test OHOS_SYSROOT_PATH=${ohos_root_path}prebuilts/lite/sysroot/" -} else { - MAKE_COMMAND = "make OHOS_SYSROOT_PATH=${ohos_root_path}prebuilts/lite/sysroot/" -} -``` - -- 添加完成后目录结构示意: - -**表 4** 添加到工程后的目录结构 - - - - - - - - - - - - - - - - - - - -

    名称

    -

    描述

    -

    openHarmony/third_party/yxml/BUILD.gn

    -

    将三方库加入工程的gn适配文件

    -

    openHarmony/third_party/yxml/build_thirdpaty.py

    -

    GN调用shell命令脚本文件,由上面GN文件将相关命令传入,实现GN转Makefile

    -

    openHarmony/third_party/yxml/config.gni

    -

    三方库编译配置文件,可修改该文件来配置用例是否参与构建等

    -

    openHarmony/third_party/yxml/yxml/

    -

    要移植的三方库目录

    -
    - diff --git a/zh-cn/device-dev/porting/Readme-CN.md b/zh-cn/device-dev/porting/Readme-CN.md index 0dca00c895..6e960a48da 100755 --- a/zh-cn/device-dev/porting/Readme-CN.md +++ b/zh-cn/device-dev/porting/Readme-CN.md @@ -1,27 +1,33 @@ # 移植指南 -- [三方库移植指导](三方库移植指导.md) - - [概述](概述.md) - - [CMake方式组织编译的库移植](CMake方式组织编译的库移植.md) - - [Makefile方式组织编译的库移植](Makefile方式组织编译的库移植.md) - -- [三方芯片移植指导](三方芯片移植指导.md) - - [移植准备](移植准备.md) - - [移植须知](移植须知.md) - - [编译构建适配流程](编译构建适配流程.md) - - - [内核移植](内核移植.md) - - [移植概述](移植概述.md) - - [内核基础适配](内核基础适配.md) - - [内核移植验证](内核移植验证.md) - - - [板级系统移植](板级系统移植.md) - - [移植概述](移植概述-0.md) - - [板级驱动适配](板级驱动适配.md) - - [HAL层实现](HAL层实现.md) - - [系统组件调用](系统组件调用.md) - - [三方组件适配](三方组件适配.md) - - [XTS认证](XTS认证.md) - - - [常见问题](常见问题.md) - +- [三方库移植指导](transplant-thirdparty.md) + - [概述](transplant-thirdparty-overview.md) + - [CMake方式组织编译的库移植](transplant-thirdparty-cmake.md) + - [Makefile方式组织编译的库移植](transplant-thirdparty-makefile.md) +- [轻量系统芯片移植指导](transplant-minichip.md) + - [移植准备](transplant-chip-prepare.md) + - [移植须知](transplant-chip-prepare-knows.md) + - [编译构建适配流程](transplant-chip-prepare-process.md) + - [内核移植](transplant-chip-kernel.md) + - [移植概述](transplant-chip-kernel-overview.md) + - [内核基础适配](transplant-chip-kernel-adjustment.md) + - [内核移植验证](transplant-chip-kernel-verify.md) + - [板级系统移植](transplant-chip-board.md) + - [移植概述](transplant-chip-board-overview.md) + - [板级驱动适配](transplant-chip-board-drive.md) + - [HAL层实现](transplant-chip-board-hal.md) + - [系统组件调用](transplant-chip-board-component.md) + - [三方组件适配](transplant-chip-board-bundle.md) + - [XTS认证](transplant-chip-board-xts.md) + - [常见问题](transplant-chip-faqs.md) +- [小型系统芯片移植指导](transplant-smallchip.md) + - [移植准备](transplant-smallchip-prepare.md) + - [移植须知](transplant-smallchip-prepare-needs.md) + - [编译构建](transplant-smallchip-prepare-building.md) + - [移植内核](transplant-smallchip-kernel.md) + - [LiteOS-A内核](transplant-smallchip-kernel-a.md) + - [Linux内核](transplant-smallchip-kernel-linux.md) + - [驱动移植](transplant-smallchip-drive.md) + - [移植概述](transplant-smallchip-drive-des.md) + - [平台驱动移植](transplant-smallchip-drive-plat.md) + - [器件驱动移植](transplant-smallchip-drive-oom.md) \ No newline at end of file diff --git "a/zh-cn/device-dev/porting/XTS\350\256\244\350\257\201.md" "b/zh-cn/device-dev/porting/XTS\350\256\244\350\257\201.md" deleted file mode 100755 index 44b37d0144..0000000000 --- "a/zh-cn/device-dev/porting/XTS\350\256\244\350\257\201.md" +++ /dev/null @@ -1,65 +0,0 @@ -# XTS认证 - -- [XTS简介](#section6725155811454) - - [将XTS认证子系统加入编译组件中](#section46981118105417) - - [执行联接类模组acts测试用例](#section9489122319819) - - -## XTS简介 - -XTS是OpenHarmony生态认证测试套件的集合,当前包括acts(application compatibility test suite)应用兼容性测试套。test/xts仓当前包括acts与tools软件包: - -- acts,存放acts相关测试用例源码与配置文件,其目的是帮助终端设备厂商尽早发现软件与OpenHarmony的不兼容性,确保软件在整个开发过程中满足OpenHarmony的兼容性要求。 -- tools,存放acts相关测试用例开发框架。 - ->![](public_sys-resources/icon-note.gif) **说明:** ->XTS的启动依赖SAMGR系统服务。 - -适配分为两步,包括: - -1. 将XTS认证子系统加入编译组件中。 -2. 执行联接类模组acts测试用例。 - -### 将XTS认证子系统加入编译组件中 - -举例:将XTS认证子系统加入hispark\_aries产品编译组件中为例。 - -1. 在vendor/hisilicon/hispark\_aries/config.json中加入XTS认证子系统定义: - - ``` - { - "subsystem": "test", - "components": [ - { "component": "xts_acts", "features":[] }, - { "component": "xts_tools", "features":[] } - ] - }, - ``` - -2. Debug版本才会触发XTS认证子系统编译; - -### 执行联接类模组acts测试用例 - -举例:以hispark\_aries产品执行联接类模组acts测试用例为例。 - -1. 获取编译镜像。 - - 请在如下目录获取版本镜像:out/hispark\_pegasus/wifiiot\_hispark\_pegasus/。 - - >![](public_sys-resources/icon-note.gif) **说明:** - >判断当前版本镜像是否集成acts测试套件方法:在map文件中查看对应.a是否被编译即可。 - -2. 版本镜像烧录进开发板。 -3. 测试步骤。 - - (1)使用串口工具登录开发板,并保存串口打印信息。 - - (2)重启设备,查看串口日志。 - -4. 测试结果分析指导。 - - (1)基于串口打印日志进行分析; - - (2)每个测试套件执行以“Start to run test suite”开始,以“xx Tests xx Failures xx Ignored”结束。 - - diff --git a/zh-cn/device-dev/porting/figure/HDF_WIFI.png b/zh-cn/device-dev/porting/figure/HDF_WIFI.png new file mode 100644 index 0000000000000000000000000000000000000000..56e6ab3aee9a539c76afd3edac98f21bff0766d5 GIT binary patch literal 60062 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