Compare commits
342 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3a35bee743 | ||
|
|
b6bec0c2b6 | ||
|
|
a49eeaf548 | ||
|
|
e2e127bb0e | ||
|
|
877ef9e221 | ||
|
|
4179e4910b | ||
|
|
6bfbbc18f2 | ||
|
|
c08d854d4b | ||
|
|
ddb889623d | ||
|
|
acd53026b0 | ||
|
|
a0337a42e3 | ||
|
|
d1d4632292 | ||
|
|
1f252e418f | ||
|
|
d1625c7d84 | ||
|
|
37cbb51afa | ||
|
|
711bd5bd15 | ||
|
|
a3db2480a1 | ||
|
|
7c0b7367d1 | ||
|
|
b342734aad | ||
|
|
372c097688 | ||
|
|
62dcbef383 | ||
|
|
a672abce6f | ||
|
|
bd31aad3ef | ||
|
|
97eccb0b36 | ||
|
|
491264e3fc | ||
|
|
fb7a0478e5 | ||
|
|
d59acc2e03 | ||
|
|
17be211288 | ||
|
|
8fa0d977a0 | ||
|
|
aa43d46953 | ||
|
|
2af68252cb | ||
|
|
ebb1321b7c | ||
|
|
f98689fc30 | ||
|
|
8992dce241 | ||
|
|
7ecf1af00f | ||
|
|
5799b31942 | ||
|
|
c20c9c20d2 | ||
|
|
b6bd1de959 | ||
|
|
60442e489a | ||
|
|
be4da6f37d | ||
|
|
b4730f3f87 | ||
|
|
12c9220487 | ||
|
|
cb8c68659c | ||
|
|
62df72af5b | ||
|
|
c782dd26c4 | ||
|
|
efb28105e8 | ||
|
|
4640055ab6 | ||
|
|
db225df433 | ||
|
|
19edea21d7 | ||
|
|
856edb7ec6 | ||
|
|
203184e18c | ||
|
|
c07c918150 | ||
|
|
d368db9e76 | ||
|
|
235dcb761c | ||
|
|
4a8ac7c02b | ||
|
|
de27c59e51 | ||
|
|
d71c5fcd2f | ||
|
|
e366c8817c | ||
|
|
f2ba792380 | ||
|
|
cc6c459e7b | ||
|
|
e9e9080ae0 | ||
|
|
ead80da91f | ||
|
|
c9db5635b0 | ||
|
|
3397a5245b | ||
|
|
85cbc7717e | ||
|
|
58060874d6 | ||
|
|
a080d98470 | ||
|
|
4aacf28974 | ||
|
|
1dfb44a706 | ||
|
|
3306194902 | ||
|
|
fa1637ffbd | ||
|
|
c1036ec9a2 | ||
|
|
a7baf1e7ed | ||
|
|
4405b85eae | ||
|
|
b76b1506cd | ||
|
|
b1e7057b17 | ||
|
|
6816dc023a | ||
|
|
644f2bbf37 | ||
|
|
19bd5a4705 | ||
|
|
d99d4e8f52 | ||
|
|
b1264ad3c9 | ||
|
|
607b8ca017 | ||
|
|
a21ca4af2a | ||
|
|
a51473d791 | ||
|
|
20b852eb38 | ||
|
|
60ce72b37a | ||
|
|
20bc1e6e8b | ||
|
|
c78ab5242c | ||
|
|
a42f20ab3c | ||
|
|
668796ee18 | ||
|
|
2356e42955 | ||
|
|
3653ac690d | ||
|
|
c30ba15c6f | ||
|
|
0379084f40 | ||
|
|
e70244d75e | ||
|
|
4fc79c211a | ||
|
|
ac69e135ca | ||
|
|
49caa6e533 | ||
|
|
96ca3b18f1 | ||
|
|
86cb28ee4f | ||
|
|
fe06b461ee | ||
|
|
1c60efe8a8 | ||
|
|
32cb324324 | ||
|
|
592ca413e8 | ||
|
|
f24189d7e1 | ||
|
|
9d970e7832 | ||
|
|
5a8b6d79aa | ||
|
|
e0c78f200b | ||
|
|
86b1d9c77d | ||
|
|
e33b0d0264 | ||
|
|
2b69d31744 | ||
|
|
a9ac7efed2 | ||
|
|
5fe8fb59b2 | ||
|
|
7a172fd136 | ||
|
|
ca74d5cb93 | ||
|
|
251846604a | ||
|
|
2930757728 | ||
|
|
25cd73821f | ||
|
|
eb14677832 | ||
|
|
c631063b7a | ||
|
|
f3d527cf70 | ||
|
|
b3c770dd26 | ||
|
|
8609045f2a | ||
|
|
9959ec6470 | ||
|
|
8b2eee0aa0 | ||
|
|
224201ba55 | ||
|
|
dfdc29b1d8 | ||
|
|
410178e426 | ||
|
|
471e2d7920 | ||
|
|
e69139c6b9 | ||
|
|
4c0b05b752 | ||
|
|
281a3b672a | ||
|
|
7b82f2a60b | ||
|
|
2f86d928c6 | ||
|
|
abe138ab27 | ||
|
|
9bf26cdbf9 | ||
|
|
267528408e | ||
|
|
3f13410d96 | ||
|
|
ac588f2fcf | ||
|
|
7d5149af24 | ||
|
|
48a19fe349 | ||
|
|
25221ac786 | ||
|
|
06c9c6ecc4 | ||
|
|
8f6cac9797 | ||
|
|
8aac82b1b4 | ||
|
|
bea5eda2e0 | ||
|
|
43f19c4b55 | ||
|
|
a184611226 | ||
|
|
0eee31179c | ||
|
|
ecfbdb207f | ||
|
|
ab578dfe0e | ||
|
|
a4f24a29fc | ||
|
|
2aa5c0f0ba | ||
|
|
a5e97b1431 | ||
|
|
92347f7e29 | ||
|
|
b07ad19dc3 | ||
|
|
ebbb30c763 | ||
|
|
58b3e0b6a6 | ||
|
|
a85e9fdb6d | ||
|
|
626cbb084d | ||
|
|
b0f717bee4 | ||
|
|
51d3a8ab41 | ||
|
|
d7e29f19cc | ||
|
|
d7cb0876f6 | ||
|
|
dd5a68916e | ||
|
|
d008cbf09f | ||
|
|
2e209ef174 | ||
|
|
3fdc18e837 | ||
|
|
6be676af78 | ||
|
|
d14ec3cb12 | ||
|
|
21e01b2f6b | ||
|
|
4a07f534d8 | ||
|
|
869e69097f | ||
|
|
d77c1828b2 | ||
|
|
bb93aefe1d | ||
|
|
cd9a3ee143 | ||
|
|
c3e8810e1a | ||
|
|
ce480336d8 | ||
|
|
34ca5a215c | ||
|
|
5b47a83022 | ||
|
|
55dc35f2de | ||
|
|
7f5192351a | ||
|
|
281482855d | ||
|
|
6fc420e6a3 | ||
|
|
2e074a4391 | ||
|
|
6b7a233511 | ||
|
|
b22f9a3851 | ||
|
|
2fcb4ad3ad | ||
|
|
2db749991e | ||
|
|
6dbbfd804e | ||
|
|
41b8b3e896 | ||
|
|
d16c698789 | ||
|
|
c251937f9f | ||
|
|
88d7ef83d3 | ||
|
|
09d86f55b0 | ||
|
|
6664b23234 | ||
|
|
e9af33ca78 | ||
|
|
d542b4dc9b | ||
|
|
6f9be6d790 | ||
|
|
af345b75fb | ||
|
|
3f9904eb53 | ||
|
|
198d61918b | ||
|
|
da37bf4777 | ||
|
|
f87c40f6fb | ||
|
|
f6a0c0b0b7 | ||
|
|
78387f9b16 | ||
|
|
8593dedd37 | ||
|
|
4c1580fab2 | ||
|
|
5786b7dffc | ||
|
|
5b785b0105 | ||
|
|
fc825ea557 | ||
|
|
9a555bc8b5 | ||
|
|
6ad0b192e8 | ||
|
|
a3d753153c | ||
|
|
b9d10a7cf1 | ||
|
|
be3b3b8016 | ||
|
|
9a1a407ea6 | ||
|
|
336c970010 | ||
|
|
168e36d09e | ||
|
|
21f57bf229 | ||
|
|
2d8147a92b | ||
|
|
3b74443dac | ||
|
|
1afdd8c056 | ||
|
|
b3667294ed | ||
|
|
545f1f1b3c | ||
|
|
af42ebca62 | ||
|
|
fde280b6a0 | ||
|
|
c4daa1dc44 | ||
|
|
61cd542d92 | ||
|
|
bf9d610675 | ||
|
|
1c16e3a463 | ||
|
|
f50dab2bde | ||
|
|
60e46d0c3b | ||
|
|
38d2cb3c85 | ||
|
|
fcd14e038e | ||
|
|
903fca4991 | ||
|
|
81323fa992 | ||
|
|
49533d9e84 | ||
|
|
2c9f3f8113 | ||
|
|
d41517ab90 | ||
|
|
5b9cbad759 | ||
|
|
fedd6affc9 | ||
|
|
96af003398 | ||
|
|
4510a95e90 | ||
|
|
2886ca5f78 | ||
|
|
86ef526303 | ||
|
|
fba573cc0b | ||
|
|
36f3e40c55 | ||
|
|
f564ef8d28 | ||
|
|
e603afa739 | ||
|
|
0e496a791f | ||
|
|
223933b6f9 | ||
|
|
1df91a6b3c | ||
|
|
fc505837b9 | ||
|
|
b6b06aa538 | ||
|
|
579956c027 | ||
|
|
994658c08c | ||
|
|
13a4c0f813 | ||
|
|
0ddb5bfd1f | ||
|
|
3a7e7dee79 | ||
|
|
2faece8dc6 | ||
|
|
e85b0832e1 | ||
|
|
d73170d1c6 | ||
|
|
8de08a5ae1 | ||
|
|
cd964dff27 | ||
|
|
6d0f2ca39a | ||
|
|
f5ef4304ff | ||
|
|
b97a54dbed | ||
|
|
9158349752 | ||
|
|
4a7f51a5e9 | ||
|
|
b9a6714ed7 | ||
|
|
e37efc70ce | ||
|
|
cb87bea665 | ||
|
|
b907bfab1c | ||
|
|
804bd57aa0 | ||
|
|
dd3694c6b8 | ||
|
|
dc455ac70d | ||
|
|
8b1a886e13 | ||
|
|
82e7002069 | ||
|
|
4caf2266b8 | ||
|
|
8f2bdc034e | ||
|
|
06c351e27c | ||
|
|
7f1805e498 | ||
|
|
836eae32c4 | ||
|
|
33388e60ab | ||
|
|
7e9c6b16f6 | ||
|
|
89a2236b18 | ||
|
|
92301257f3 | ||
|
|
c079c8f80a | ||
|
|
789ea394c8 | ||
|
|
28503618b5 | ||
|
|
3e65883a7f | ||
|
|
9f56e71545 | ||
|
|
bee2741235 | ||
|
|
54e8b8569b | ||
|
|
a3cb3fd650 | ||
|
|
221bd363c9 | ||
|
|
8b2d6082d1 | ||
|
|
0f7d7f446f | ||
|
|
75c879b9e5 | ||
|
|
013e3c14cc | ||
|
|
9fcd9338d3 | ||
|
|
0daed4872f | ||
|
|
03e646e0d0 | ||
|
|
f48da2b6f9 | ||
|
|
59f6f8d89c | ||
|
|
302079ab81 | ||
|
|
4d594e6bc7 | ||
|
|
b318eb315c | ||
|
|
6300cb511b | ||
|
|
1402fe12e9 | ||
|
|
829f05296a | ||
|
|
86d96159fe | ||
|
|
e012005b45 | ||
|
|
a2d278bb04 | ||
|
|
ed1010d84b | ||
|
|
9fb9a3a2ec | ||
|
|
fc257d1f8b | ||
|
|
6978a341c5 | ||
|
|
6f7cf059ec | ||
|
|
dac189d6cc | ||
|
|
8ccf223eb0 | ||
|
|
340c6fe503 | ||
|
|
f90ac499be | ||
|
|
0602e09627 | ||
|
|
f65b5652d7 | ||
|
|
a8eb0f1617 | ||
|
|
83b223e0db | ||
|
|
0828327cd0 | ||
|
|
e5ec525b13 | ||
|
|
7b3eab0f64 | ||
|
|
4249cb391e | ||
|
|
fad57ab4dd | ||
|
|
c4e0918583 | ||
|
|
1599057195 | ||
|
|
d59964e87f | ||
|
|
a0fb0006ca | ||
|
|
a4dd99c678 | ||
|
|
915c82552d | ||
|
|
3e2b6f6fa9 | ||
|
|
872f8bc9ca | ||
|
|
2b3d0be7da |
11
.gitignore
vendored
11
.gitignore
vendored
@@ -1,8 +1,3 @@
|
||||
xsconfig.h
|
||||
xsconfig.mk
|
||||
.config
|
||||
.config.old
|
||||
build
|
||||
XiUOS.*
|
||||
*.swp
|
||||
.vscode
|
||||
*.vscode
|
||||
*.o
|
||||
.DS_Store
|
||||
6
.gitmodules
vendored
Normal file
6
.gitmodules
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
[submodule "Ubiquitous/RT_Thread/rt-thread"]
|
||||
path = Ubiquitous/RT_Thread/rt-thread
|
||||
url = https://code.gitlink.org.cn/chunyexixiaoyu/rt-thread.git
|
||||
[submodule "Ubiquitous/RT_Thread/bsp/k210/kendryte-sdk/kendryte-sdk-source"]
|
||||
path = Ubiquitous/RT_Thread/aiit_board/k210/kendryte-sdk/kendryte-sdk-source
|
||||
url = https://code.gitlink.org.cn/chunyexixiaoyu/kendryte-sdk-source.git
|
||||
22
APP_Framework/Applications/Kconfig
Normal file
22
APP_Framework/Applications/Kconfig
Normal file
@@ -0,0 +1,22 @@
|
||||
menu "Applications"
|
||||
|
||||
menu "config stack size and priority of main task"
|
||||
config MAIN_KTASK_STACK_SIZE
|
||||
int "Set main task stack size"
|
||||
default 1024
|
||||
config MAIN_KTASK_PRIORITY
|
||||
int
|
||||
default 4 if KTASK_PRIORITY_8
|
||||
default 10 if KTASK_PRIORITY_32
|
||||
default 85 if KTASK_PRIORITY_256
|
||||
endmenu
|
||||
|
||||
source "$APP_DIR/Applications/ota/Kconfig"
|
||||
|
||||
source "$APP_DIR/Applications/app_test/Kconfig"
|
||||
source "$APP_DIR/Applications/connection_app/Kconfig"
|
||||
source "$APP_DIR/Applications/control_app/Kconfig"
|
||||
source "$APP_DIR/Applications/knowing_app/Kconfig"
|
||||
source "$APP_DIR/Applications/sensor_app/Kconfig"
|
||||
|
||||
endmenu
|
||||
7
APP_Framework/Applications/Make.defs
Normal file
7
APP_Framework/Applications/Make.defs
Normal file
@@ -0,0 +1,7 @@
|
||||
############################################################################
|
||||
# APP_Framework/Applications/Make.defs
|
||||
############################################################################
|
||||
CONFIGURED_APPS += $(APPDIR)/../../../APP_Framework/Applications
|
||||
CONFIGURED_APPS += $(APPDIR)/../../../APP_Framework/Applications/general_functions/list
|
||||
|
||||
include $(wildcard $(APPDIR)/../../../APP_Framework/Applications/*/Make.defs)
|
||||
36
APP_Framework/Applications/Makefile
Normal file
36
APP_Framework/Applications/Makefile
Normal file
@@ -0,0 +1,36 @@
|
||||
include $(KERNEL_ROOT)/.config
|
||||
|
||||
ifeq ($(CONFIG_ADD_NUTTX_FETURES),y)
|
||||
include $(APPDIR)/Make.defs
|
||||
CSRCS += framework_init.c
|
||||
include $(APPDIR)/Application.mk
|
||||
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_ADD_XIUOS_FETURES),y)
|
||||
SRC_DIR := general_functions app_test
|
||||
|
||||
SRC_FILES := main.c framework_init.c
|
||||
|
||||
ifeq ($(CONFIG_APPLICATION_OTA),y)
|
||||
SRC_DIR += ota
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_APPLICATION_SENSOR),y)
|
||||
SRC_DIR += sensor_app
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_APPLICATION_CONNECTION),y)
|
||||
SRC_DIR += connection_app
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_APPLICATION_KNOWING),y)
|
||||
SRC_DIR += knowing_app
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_APPLICATION_CONTROL),y)
|
||||
SRC_DIR += control_app
|
||||
endif
|
||||
|
||||
include $(KERNEL_ROOT)/compiler.mk
|
||||
endif
|
||||
20
APP_Framework/Applications/SConscript
Normal file
20
APP_Framework/Applications/SConscript
Normal file
@@ -0,0 +1,20 @@
|
||||
import os
|
||||
Import('RTT_ROOT')
|
||||
Import('rtconfig')
|
||||
from building import *
|
||||
|
||||
cwd = GetCurrentDir()
|
||||
|
||||
SOURCES = ['framework_init.c']
|
||||
path = [cwd]
|
||||
objs = []
|
||||
group = DefineGroup('sensor', SOURCES, depend = [], CPPPATH = [cwd])
|
||||
objs = objs + group
|
||||
list = os.listdir(cwd)
|
||||
|
||||
for d in list:
|
||||
path = os.path.join(cwd, d)
|
||||
if os.path.isfile(os.path.join(path, 'SConscript')):
|
||||
objs = objs + SConscript(os.path.join(path, 'SConscript'))
|
||||
|
||||
Return('objs')
|
||||
12
APP_Framework/Applications/app_test/Kconfig
Normal file
12
APP_Framework/Applications/app_test/Kconfig
Normal file
@@ -0,0 +1,12 @@
|
||||
menu "test app"
|
||||
menuconfig USER_TEST
|
||||
bool "Enable application test function "
|
||||
default n
|
||||
|
||||
if USER_TEST
|
||||
config USER_TEST_SPI_FLASH
|
||||
bool "Config test spi flash"
|
||||
default n
|
||||
|
||||
endif
|
||||
endmenu
|
||||
7
APP_Framework/Applications/app_test/Makefile
Normal file
7
APP_Framework/Applications/app_test/Makefile
Normal file
@@ -0,0 +1,7 @@
|
||||
SRC_FILES :=
|
||||
|
||||
ifeq ($(CONFIG_USER_TEST_SPI_FLASH),y)
|
||||
SRC_FILES += test_spi_flash.c
|
||||
endif
|
||||
|
||||
include $(KERNEL_ROOT)/compiler.mk
|
||||
175
APP_Framework/Applications/app_test/test_spi_flash.c
Normal file
175
APP_Framework/Applications/app_test/test_spi_flash.c
Normal file
@@ -0,0 +1,175 @@
|
||||
/*
|
||||
* File : spi_flash_sfud.c
|
||||
* This file is part of RT-Thread RTOS
|
||||
* COPYRIGHT (C) 2006 - 2016, RT-Thread Development Team
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2016-09-28 armink first version.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file test_spi_flash.c
|
||||
* @brief support to test spi flash function
|
||||
* @version 1.0
|
||||
* @author AIIT XUOS Lab
|
||||
* @date 2021-05-17
|
||||
*/
|
||||
|
||||
/*************************************************
|
||||
File name: test_spi_flash.c
|
||||
Description: support spi flash function test
|
||||
Others: add spi flash test cmd from SFUD/blob/master/demo/stm32f2xx_rtt/RT-Thread-2.1.0/components/drivers/spi/spi_flash_sfud.c
|
||||
https://github.com/armink/SFUD/
|
||||
History:
|
||||
1. Date: 2021-05-17
|
||||
Author: AIIT XUOS Lab
|
||||
Modification:
|
||||
1. support spi flash open, read and write function
|
||||
*************************************************/
|
||||
|
||||
#include <xiuos.h>
|
||||
#include <device.h>
|
||||
#include <flash_spi.h>
|
||||
#include <user_api.h>
|
||||
|
||||
#define SPI_FLASH_PATH "/dev/spi1_W25Q64"
|
||||
#define FlashDataPrint(ch) ((unsigned int)((ch) - ' ') < 127u - ' ')
|
||||
|
||||
static int spi_flash_fd;
|
||||
|
||||
void FlashOpen(void)
|
||||
{
|
||||
x_err_t ret = EOK;
|
||||
|
||||
spi_flash_fd = open(SPI_FLASH_PATH, O_RDWR);
|
||||
if (spi_flash_fd < 0) {
|
||||
KPrintf("open spi flash fd error %d\n", spi_flash_fd);
|
||||
}
|
||||
|
||||
KPrintf("Spi Flash init succeed\n");
|
||||
|
||||
return;
|
||||
}
|
||||
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN),
|
||||
FlashOpen, FlashOpen, open spi flash device);
|
||||
|
||||
void FlashRead(int argc, char *argv[])
|
||||
{
|
||||
x_size_t i, j = 0;
|
||||
uint32 addr;
|
||||
uint32 size;
|
||||
uint8 data[16];
|
||||
|
||||
struct BusBlockReadParam read_param;
|
||||
memset(&read_param, 0, sizeof(struct BusBlockReadParam));
|
||||
|
||||
memset(data, 0, 16);
|
||||
|
||||
if (3 != argc) {
|
||||
KPrintf("FlashRead cmd format: FlashRead addr size.\n");
|
||||
return;
|
||||
} else {
|
||||
addr = strtol(argv[1], NULL, 0);
|
||||
size = strtol(argv[2], NULL, 0);
|
||||
|
||||
read_param.buffer = data;
|
||||
read_param.pos = addr;
|
||||
read_param.size = size;
|
||||
|
||||
if (read_param.buffer) {
|
||||
read(spi_flash_fd, &read_param, size);
|
||||
if (size == read_param.read_length) {
|
||||
KPrintf("Read the %s flash data success. Start from 0x%08X, size is %ld. The data is:\n",
|
||||
SPI_FLASH_PATH, addr, size);
|
||||
KPrintf("Offset (h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F\n");
|
||||
for (i = 0; i < size; i += 16) {
|
||||
KPrintf("[%08X] ", addr + i);
|
||||
/* dump hex */
|
||||
for (j = 0; j < 16; j++) {
|
||||
if (i + j < size) {
|
||||
KPrintf("%02X ", data[i + j]);
|
||||
} else {
|
||||
KPrintf(" ");
|
||||
}
|
||||
}
|
||||
/* dump char for hex */
|
||||
for (j = 0; j < 16; j++) {
|
||||
if (i + j < size) {
|
||||
KPrintf("%c", FlashDataPrint(data[i + j]) ? data[i + j] : '.');
|
||||
}
|
||||
}
|
||||
KPrintf("\n");
|
||||
}
|
||||
KPrintf("\n");
|
||||
}
|
||||
} else {
|
||||
KPrintf("SpiFlashRead alloc read buffer failed!\n");
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN),
|
||||
FlashRead, FlashRead, read data from spi flash device);
|
||||
|
||||
void FlashWrite(int argc, char *argv[])
|
||||
{
|
||||
x_err_t ret = EOK;
|
||||
x_size_t i, j = 0;
|
||||
uint32 addr;
|
||||
uint32 size;
|
||||
uint8 data[16];
|
||||
|
||||
struct BusBlockWriteParam write_param;
|
||||
memset(&write_param, 0, sizeof(struct BusBlockWriteParam));
|
||||
|
||||
memset(data, 0, 16);
|
||||
|
||||
if (argc < 3) {
|
||||
KPrintf("FlashWrite cmd format: FlashWrite addr data.\n");
|
||||
return;
|
||||
} else {
|
||||
addr = strtol(argv[1], NULL, 0);
|
||||
size = argc - 2;
|
||||
|
||||
write_param.buffer = data;
|
||||
write_param.pos = addr;
|
||||
write_param.size = size;
|
||||
|
||||
if (data) {
|
||||
for (i = 0; i < size; i++) {
|
||||
data[i] = strtol(argv[2 + i], NULL, 0);
|
||||
}
|
||||
|
||||
ret = write(spi_flash_fd, &write_param, size);
|
||||
if (EOK == ret) {
|
||||
KPrintf("Write the %s flash data success. Start from 0x%08X, size is %ld.\n",
|
||||
SPI_FLASH_PATH, addr, size);
|
||||
KPrintf("Write data: ");
|
||||
for (i = 0; i < size; i++) {
|
||||
KPrintf("%d ", data[i]);
|
||||
}
|
||||
KPrintf(".\n");
|
||||
}
|
||||
} else {
|
||||
KPrintf("SpiFlashWrite alloc write buffer failed!\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN),
|
||||
FlashWrite, FlashWrite, write data to spi flash device);
|
||||
7
APP_Framework/Applications/connection_app/Kconfig
Executable file
7
APP_Framework/Applications/connection_app/Kconfig
Executable file
@@ -0,0 +1,7 @@
|
||||
menu "connection app"
|
||||
|
||||
menuconfig APPLICATION_CONNECTION
|
||||
bool "Using connection apps"
|
||||
default n
|
||||
|
||||
endmenu
|
||||
7
APP_Framework/Applications/connection_app/Makefile
Executable file
7
APP_Framework/Applications/connection_app/Makefile
Executable file
@@ -0,0 +1,7 @@
|
||||
SRC_DIR :=
|
||||
|
||||
ifeq ($(CONFIG_RESOURCES_LWIP),y)
|
||||
SRC_DIR += socket_demo
|
||||
endif
|
||||
|
||||
include $(KERNEL_ROOT)/compiler.mk
|
||||
3
APP_Framework/Applications/connection_app/socket_demo/Makefile
Executable file
3
APP_Framework/Applications/connection_app/socket_demo/Makefile
Executable file
@@ -0,0 +1,3 @@
|
||||
SRC_FILES := lwip_tcp_socket_demo.c lwip_udp_socket_demo.c
|
||||
|
||||
include $(KERNEL_ROOT)/compiler.mk
|
||||
187
APP_Framework/Applications/connection_app/socket_demo/lwip_tcp_socket_demo.c
Executable file
187
APP_Framework/Applications/connection_app/socket_demo/lwip_tcp_socket_demo.c
Executable file
@@ -0,0 +1,187 @@
|
||||
/*
|
||||
* Copyright (c) 2020 AIIT XUOS Lab
|
||||
* XiUOS is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
* See the Mulan PSL v2 for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file tcp_echo_socket_demo.c
|
||||
* @brief One UDP demo based on LwIP
|
||||
* @version 1.0
|
||||
* @author AIIT XUOS Lab
|
||||
* @date 2021-05-29
|
||||
*/
|
||||
#include <transform.h>
|
||||
#include <xiuos.h>
|
||||
#include "board.h"
|
||||
#include "sys_arch.h"
|
||||
#include <lwip/sockets.h>
|
||||
#include "lwip/sys.h"
|
||||
|
||||
/*******************************************************************************
|
||||
* Definitions
|
||||
******************************************************************************/
|
||||
|
||||
/*******************************************************************************
|
||||
* Prototypes
|
||||
******************************************************************************/
|
||||
|
||||
/*******************************************************************************
|
||||
* Variables
|
||||
******************************************************************************/
|
||||
|
||||
char tcp_socket_ip[] = {192, 168, 250, 252};
|
||||
|
||||
#define TCP_BUF_SIZE 1024
|
||||
|
||||
/*******************************************************************************
|
||||
* Code
|
||||
******************************************************************************/
|
||||
|
||||
static void tcp_recv_demo(void *arg)
|
||||
{
|
||||
lw_print("tcp_recv_demo start.\n");
|
||||
|
||||
int fd = -1;
|
||||
char *recv_buf;
|
||||
struct sockaddr_in tcp_addr, server_addr;
|
||||
int recv_len;
|
||||
socklen_t addr_len;
|
||||
|
||||
while(1)
|
||||
{
|
||||
recv_buf = (char *)malloc(TCP_BUF_SIZE);
|
||||
if (recv_buf == NULL)
|
||||
{
|
||||
lw_print("No memory\n");
|
||||
goto __exit;
|
||||
}
|
||||
|
||||
fd = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if (fd < 0)
|
||||
{
|
||||
lw_print("Socket error\n");
|
||||
goto __exit;
|
||||
}
|
||||
|
||||
tcp_addr.sin_family = AF_INET;
|
||||
tcp_addr.sin_addr.s_addr = INADDR_ANY;
|
||||
tcp_addr.sin_port = htons(LOCAL_PORT_SERVER);
|
||||
memset(&(tcp_addr.sin_zero), 0, sizeof(tcp_addr.sin_zero));
|
||||
|
||||
if (bind(fd, (struct sockaddr *)&tcp_addr, sizeof(struct sockaddr)) == -1)
|
||||
{
|
||||
lw_print("Unable to bind\n");
|
||||
goto __exit;
|
||||
}
|
||||
|
||||
lw_print("tcp bind sucess, start to receive.\n");
|
||||
lw_print("\n\nLocal Port:%d\n\n", LOCAL_PORT_SERVER);
|
||||
|
||||
while(1)
|
||||
{
|
||||
memset(recv_buf, 0, TCP_BUF_SIZE);
|
||||
recv_len = recvfrom(fd, recv_buf, TCP_BUF_SIZE, 0, (struct sockaddr *)&server_addr, &addr_len);
|
||||
lw_pr_info("Receive from : %s\n", inet_ntoa(server_addr.sin_addr));
|
||||
lw_pr_info("Receive data : %s\n\n", recv_buf);
|
||||
sendto(fd, recv_buf, recv_len, 0, (struct sockaddr*)&server_addr, addr_len);
|
||||
}
|
||||
|
||||
__exit:
|
||||
if (fd >= 0)
|
||||
closesocket(fd);
|
||||
|
||||
if (recv_buf)
|
||||
free(recv_buf);
|
||||
}
|
||||
}
|
||||
|
||||
void tcp_socket_recv_run(int argc, char *argv[])
|
||||
{
|
||||
int result = 0;
|
||||
pthread_t th_id;
|
||||
pthread_attr_t attr;
|
||||
|
||||
if(argc == 2)
|
||||
{
|
||||
lw_print("lw: [%s] gw %s\n", __func__, argv[1]);
|
||||
sscanf(argv[1], "%d.%d.%d.%d", &tcp_socket_ip[0], &tcp_socket_ip[1], &tcp_socket_ip[2], &tcp_socket_ip[3]);
|
||||
}
|
||||
|
||||
ETH_BSP_Config();
|
||||
lwip_config_tcp(lwip_ipaddr, lwip_netmask, lwip_gwaddr);
|
||||
sys_thread_new("tcp_recv_demo", tcp_recv_demo, NULL, 4096, 15);
|
||||
}
|
||||
|
||||
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN) | SHELL_CMD_PARAM_NUM(3),
|
||||
TCPSocketRecv, tcp_socket_recv_run, TCP recv echo);
|
||||
|
||||
static void tcp_send_demo(void *arg)
|
||||
{
|
||||
int cnt = TEST_LWIP_TIMES;
|
||||
lw_print("tcp_send_demo start.\n");
|
||||
int fd = -1;
|
||||
char send_msg[128];
|
||||
|
||||
memset(send_msg, 0, sizeof(send_msg));
|
||||
fd = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if (fd < 0)
|
||||
{
|
||||
lw_print("Socket error\n");
|
||||
goto __exit;
|
||||
}
|
||||
|
||||
struct sockaddr_in tcp_sock;
|
||||
tcp_sock.sin_family = AF_INET;
|
||||
tcp_sock.sin_port = htons(TARGET_PORT_CLIENT);
|
||||
tcp_sock.sin_addr.s_addr = PP_HTONL(LWIP_MAKEU32(tcp_socket_ip[0],tcp_socket_ip[1],tcp_socket_ip[2],tcp_socket_ip[3]));
|
||||
memset(&(tcp_sock.sin_zero), 0, sizeof(tcp_sock.sin_zero));
|
||||
|
||||
if (connect(fd, (struct sockaddr *)&tcp_sock, sizeof(struct sockaddr)))
|
||||
{
|
||||
lw_print("Unable to connect\n");
|
||||
goto __exit;
|
||||
}
|
||||
|
||||
lw_print("tcp connect success, start to send.\n");
|
||||
lw_print("\n\nTarget Port:%d\n\n", tcp_sock.sin_port);
|
||||
|
||||
while (cnt --)
|
||||
{
|
||||
lw_print("Lwip client is running.\n");
|
||||
snprintf(send_msg, sizeof(send_msg), "TCP test package times %d\r\n", cnt);
|
||||
sendto(fd, send_msg, strlen(send_msg), 0, (struct sockaddr*)&tcp_sock, sizeof(struct sockaddr));
|
||||
lw_print("Send tcp msg: %s ", send_msg);
|
||||
MdelayKTask(1000);
|
||||
}
|
||||
|
||||
__exit:
|
||||
if (fd >= 0)
|
||||
closesocket(fd);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void tcp_socket_send_run(int argc, char *argv[])
|
||||
{
|
||||
if(argc == 2)
|
||||
{
|
||||
lw_print("lw: [%s] gw %s\n", __func__, argv[1]);
|
||||
sscanf(argv[1], "%d.%d.%d.%d", &tcp_socket_ip[0], &tcp_socket_ip[1], &tcp_socket_ip[2], &tcp_socket_ip[3]);
|
||||
}
|
||||
|
||||
ETH_BSP_Config();
|
||||
lwip_config_tcp(lwip_ipaddr, lwip_netmask, lwip_gwaddr);
|
||||
sys_thread_new("tcp socket", tcp_send_demo, NULL, 4096, 25);
|
||||
}
|
||||
|
||||
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN) | SHELL_CMD_PARAM_NUM(0),
|
||||
TCPSocketSend, tcp_socket_send_run, TCP send demo);
|
||||
|
||||
209
APP_Framework/Applications/connection_app/socket_demo/lwip_udp_socket_demo.c
Executable file
209
APP_Framework/Applications/connection_app/socket_demo/lwip_udp_socket_demo.c
Executable file
@@ -0,0 +1,209 @@
|
||||
/*
|
||||
* Copyright (c) 2020 AIIT XUOS Lab
|
||||
* XiUOS is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
* See the Mulan PSL v2 for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file lwip_udp_socket_demo.c
|
||||
* @brief One UDP demo based on LwIP
|
||||
* @version 1.0
|
||||
* @author AIIT XUOS Lab
|
||||
* @date 2021-05-29
|
||||
*/
|
||||
#include <transform.h>
|
||||
#include <xiuos.h>
|
||||
#include "board.h"
|
||||
#include "sys_arch.h"
|
||||
#include "lwip/udp.h"
|
||||
#include "lwip/opt.h"
|
||||
|
||||
/*******************************************************************************
|
||||
* Definitions
|
||||
******************************************************************************/
|
||||
|
||||
/*******************************************************************************
|
||||
* Prototypes
|
||||
******************************************************************************/
|
||||
|
||||
/*******************************************************************************
|
||||
* Variables
|
||||
******************************************************************************/
|
||||
extern char udp_target[];
|
||||
static struct udp_pcb *udpecho_raw_pcb;
|
||||
char udp_socket_ip[] = {192, 168, 250, 252};
|
||||
|
||||
/*******************************************************************************
|
||||
* Code
|
||||
******************************************************************************/
|
||||
|
||||
#include <lwip/sockets.h>
|
||||
#include "lwip/sys.h"
|
||||
|
||||
#define LWIP_UDP_TASK_STACK 4096
|
||||
#define LWIP_UDP_TASK_PRIO 25
|
||||
#define UDP_BUF_SIZE 1024
|
||||
|
||||
static void udp_recv_demo(void *arg)
|
||||
{
|
||||
lw_print("udp_recv_demo start.\n");
|
||||
|
||||
int socket_fd = -1;
|
||||
char *recv_buf;
|
||||
struct sockaddr_in udp_addr, server_addr;
|
||||
int recv_len;
|
||||
socklen_t addr_len;
|
||||
|
||||
while(1)
|
||||
{
|
||||
recv_buf = (char *)malloc(UDP_BUF_SIZE);
|
||||
if (recv_buf == NULL)
|
||||
{
|
||||
lw_print("No memory\n");
|
||||
goto __exit;
|
||||
}
|
||||
|
||||
socket_fd = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if (socket_fd < 0)
|
||||
{
|
||||
lw_print("Socket error\n");
|
||||
goto __exit;
|
||||
}
|
||||
|
||||
udp_addr.sin_family = AF_INET;
|
||||
udp_addr.sin_addr.s_addr = INADDR_ANY;
|
||||
udp_addr.sin_port = htons(LOCAL_PORT_SERVER);
|
||||
memset(&(udp_addr.sin_zero), 0, sizeof(udp_addr.sin_zero));
|
||||
|
||||
if (bind(socket_fd, (struct sockaddr *)&udp_addr, sizeof(struct sockaddr)) == -1)
|
||||
{
|
||||
lw_print("Unable to bind\n");
|
||||
goto __exit;
|
||||
}
|
||||
|
||||
lw_print("UDP bind sucess, start to receive.\n");
|
||||
lw_print("\n\nLocal Port:%d\n\n", LOCAL_PORT_SERVER);
|
||||
|
||||
while(1)
|
||||
{
|
||||
memset(recv_buf, 0, UDP_BUF_SIZE);
|
||||
recv_len = recvfrom(socket_fd, recv_buf, UDP_BUF_SIZE, 0, (struct sockaddr *)&server_addr, &addr_len);
|
||||
lw_print("Receive from : %s\n", inet_ntoa(server_addr.sin_addr));
|
||||
lw_print("Receive data : %s\n\n", recv_buf);
|
||||
sendto(socket_fd, recv_buf, recv_len, 0, (struct sockaddr*)&server_addr, addr_len);
|
||||
}
|
||||
|
||||
__exit:
|
||||
if (socket_fd >= 0)
|
||||
closesocket(socket_fd);
|
||||
|
||||
if (recv_buf)
|
||||
free(recv_buf);
|
||||
}
|
||||
}
|
||||
|
||||
static void udp_recv_demo_thread(void* param)
|
||||
{
|
||||
ETH_BSP_Config();
|
||||
lwip_config_tcp(lwip_ipaddr, lwip_netmask, lwip_gwaddr);
|
||||
sys_thread_new("udp_recv_demo", udp_recv_demo, NULL, LWIP_UDP_TASK_STACK, LWIP_UDP_TASK_PRIO);
|
||||
}
|
||||
|
||||
void udp_socket_recv_run(int argc, char *argv[])
|
||||
{
|
||||
int result = 0;
|
||||
pthread_t th_id;
|
||||
pthread_attr_t attr;
|
||||
|
||||
if(argc == 2)
|
||||
{
|
||||
lw_print("lw: [%s] gw %s\n", __func__, argv[1]);
|
||||
sscanf(argv[1], "%d.%d.%d.%d", &udp_socket_ip[0], &udp_socket_ip[1], &udp_socket_ip[2], &udp_socket_ip[3]);
|
||||
}
|
||||
|
||||
sys_thread_new("udp socket send", udp_recv_demo_thread, NULL, 4096, 15);
|
||||
}
|
||||
|
||||
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN) | SHELL_CMD_PARAM_NUM(3),
|
||||
UDPSocketRecv, udp_socket_recv_run, UDP recv echo);
|
||||
|
||||
static void udp_send_demo(void *arg)
|
||||
{
|
||||
int cnt = TEST_LWIP_TIMES;
|
||||
char send_str[128];
|
||||
|
||||
lw_print("udp_send_demo start.\n");
|
||||
|
||||
int socket_fd = -1;
|
||||
memset(send_str, 0, sizeof(send_str));
|
||||
|
||||
socket_fd = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if (socket_fd < 0)
|
||||
{
|
||||
lw_print("Socket error\n");
|
||||
goto __exit;
|
||||
}
|
||||
|
||||
struct sockaddr_in udp_sock;
|
||||
udp_sock.sin_family = AF_INET;
|
||||
udp_sock.sin_port = htons(TARGET_PORT_CLIENT);
|
||||
udp_sock.sin_addr.s_addr = PP_HTONL(LWIP_MAKEU32(udp_target[0],udp_target[1],udp_target[2],udp_target[3]));
|
||||
memset(&(udp_sock.sin_zero), 0, sizeof(udp_sock.sin_zero));
|
||||
|
||||
if (connect(socket_fd, (struct sockaddr *)&udp_sock, sizeof(struct sockaddr)))
|
||||
{
|
||||
lw_print("Unable to connect\n");
|
||||
goto __exit;
|
||||
}
|
||||
|
||||
lw_print("UDP connect success, start to send.\n");
|
||||
lw_print("\n\nTarget Port:%d\n\n", udp_sock.sin_port);
|
||||
|
||||
while (cnt --)
|
||||
{
|
||||
snprintf(send_str, sizeof(send_str), "UDP test package times %d\r\n", cnt);
|
||||
sendto(socket_fd, send_str, strlen(send_str), 0, (struct sockaddr*)&udp_sock, sizeof(struct sockaddr));
|
||||
lw_pr_info("Send UDP msg: %s ", send_str);
|
||||
MdelayKTask(1000);
|
||||
}
|
||||
|
||||
__exit:
|
||||
if (socket_fd >= 0)
|
||||
{
|
||||
closesocket(socket_fd);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void udp_send_demo_thread(void* param)
|
||||
{
|
||||
ETH_BSP_Config();
|
||||
lwip_config_tcp(lwip_ipaddr, lwip_netmask, lwip_gwaddr);
|
||||
sys_thread_new("udp_send_demo", udp_send_demo, NULL, LWIP_UDP_TASK_STACK, LWIP_UDP_TASK_PRIO);
|
||||
}
|
||||
|
||||
void udp_socket_send_run(int argc, char *argv[])
|
||||
{
|
||||
int result = 0;
|
||||
pthread_t th_id;
|
||||
pthread_attr_t attr;
|
||||
|
||||
if(argc == 2)
|
||||
{
|
||||
lw_print("lw: [%s] gw %s\n", __func__, argv[1]);
|
||||
sscanf(argv[1], "%d.%d.%d.%d", &udp_socket_ip[0], &udp_socket_ip[1], &udp_socket_ip[2], &udp_socket_ip[3]);
|
||||
}
|
||||
|
||||
sys_thread_new("udp socket send", udp_send_demo_thread, NULL, 4096, 15);
|
||||
}
|
||||
|
||||
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN) | SHELL_CMD_PARAM_NUM(3),
|
||||
UDPSocketSend, udp_socket_send_run, UDP send echo);
|
||||
|
||||
9
APP_Framework/Applications/control_app/Kconfig
Executable file
9
APP_Framework/Applications/control_app/Kconfig
Executable file
@@ -0,0 +1,9 @@
|
||||
menu "control app"
|
||||
|
||||
menuconfig APPLICATION_CONTROL
|
||||
bool "Using control apps"
|
||||
default n
|
||||
depends on SUPPORT_CONTROL_FRAMEWORK
|
||||
|
||||
endmenu
|
||||
|
||||
11
APP_Framework/Applications/control_app/Makefile
Executable file
11
APP_Framework/Applications/control_app/Makefile
Executable file
@@ -0,0 +1,11 @@
|
||||
SRC_DIR :=
|
||||
|
||||
ifeq ($(CONFIG_RESOURCES_LWIP),y)
|
||||
|
||||
ifeq ($(CONFIG_USING_CONTROL_PLC_OPCUA), y)
|
||||
SRC_DIR += opcua_demo
|
||||
endif
|
||||
|
||||
endif
|
||||
|
||||
include $(KERNEL_ROOT)/compiler.mk
|
||||
3
APP_Framework/Applications/control_app/opcua_demo/Makefile
Executable file
3
APP_Framework/Applications/control_app/opcua_demo/Makefile
Executable file
@@ -0,0 +1,3 @@
|
||||
SRC_FILES :=opcua_demo.c
|
||||
|
||||
include $(KERNEL_ROOT)/compiler.mk
|
||||
160
APP_Framework/Applications/control_app/opcua_demo/opcua_demo.c
Executable file
160
APP_Framework/Applications/control_app/opcua_demo/opcua_demo.c
Executable file
@@ -0,0 +1,160 @@
|
||||
/*
|
||||
* Copyright (c) 2021 AIIT XUOS Lab
|
||||
* XiUOS is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
* See the Mulan PSL v2 for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file ua_demo.c
|
||||
* @brief Demo for OpcUa function
|
||||
* @version 1.0
|
||||
* @author AIIT XUOS Lab
|
||||
* @date 2021.11.11
|
||||
*/
|
||||
|
||||
#include <list.h>
|
||||
#include <transform.h>
|
||||
#include "board.h"
|
||||
#include <lwip/altcp.h>
|
||||
#include "open62541.h"
|
||||
#include "ua_api.h"
|
||||
|
||||
/*******************************************************************************
|
||||
* Definitions
|
||||
******************************************************************************/
|
||||
//#define ua_print KPrintf
|
||||
#define ua_trace() KPrintf("ua: [%s] %d pass!\n", __func__, __LINE__)
|
||||
|
||||
#define TCP_LOCAL_PORT 4840
|
||||
|
||||
/*******************************************************************************
|
||||
* Prototypes
|
||||
******************************************************************************/
|
||||
|
||||
/*******************************************************************************
|
||||
* Variables
|
||||
******************************************************************************/
|
||||
|
||||
const char *test_uri = "opc.tcp://192.168.250.5:4840";
|
||||
const char *test_cb_str = "tcp client connected\r\n";
|
||||
|
||||
char test_ua_gw[] = {192, 168, 250, 5};
|
||||
|
||||
static pthread_t eth_input_id = 0;
|
||||
static pthread_t ua_demo_id;
|
||||
|
||||
/*******************************************************************************
|
||||
* Code
|
||||
******************************************************************************/
|
||||
|
||||
void *test_ua_get_server_info(void *param);
|
||||
|
||||
static void test_ua_connect(void *arg)
|
||||
{
|
||||
struct netif net;
|
||||
UA_StatusCode retval;
|
||||
|
||||
UA_Client *client = UA_Client_new();
|
||||
|
||||
if (client == NULL)
|
||||
{
|
||||
ua_print("ua: [%s] tcp client null\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
UA_ClientConfig *config = UA_Client_getConfig(client);
|
||||
UA_ClientConfig_setDefault(config);
|
||||
|
||||
retval = UA_Client_connect(client, test_uri);
|
||||
if (retval != UA_STATUSCODE_GOOD)
|
||||
{
|
||||
ua_print("ua: [%s] ret %x\n", __func__, retval);
|
||||
}
|
||||
|
||||
ua_print("ua: [%s] start Ua Test!\n", __func__);
|
||||
UA_Client_disconnect(client);
|
||||
UA_Client_delete(client);
|
||||
}
|
||||
|
||||
void test_ua_connect_thr(void *arg)
|
||||
{
|
||||
ETH_BSP_Config();
|
||||
lwip_config_tcp(lwip_ipaddr, lwip_netmask, test_ua_gw);
|
||||
test_ua_connect(NULL);
|
||||
}
|
||||
|
||||
void test_sh_ua_connect(void)
|
||||
{
|
||||
int result = 0;
|
||||
pthread_t th_id;
|
||||
pthread_attr_t attr;
|
||||
sys_thread_new("ua test", test_ua_connect_thr, NULL, 4096, 15);
|
||||
}
|
||||
|
||||
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN) | SHELL_CMD_PARAM_NUM(0),
|
||||
UaConnect, test_sh_ua_connect, Test Opc UA connection);
|
||||
|
||||
void *test_ua_get_server_info(void *param)
|
||||
{
|
||||
UA_Client *client = UA_Client_new();
|
||||
|
||||
ua_print("ua: [%s] start ...\n", __func__);
|
||||
|
||||
if (client == NULL)
|
||||
{
|
||||
ua_print("ua: [%s] tcp client null\n", __func__);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
UA_ClientConfig *config = UA_Client_getConfig(client);
|
||||
UA_ClientConfig_setDefault(config);
|
||||
|
||||
UA_StatusCode retval = UA_Client_connect(client, OPC_SERVER);
|
||||
if(retval != UA_STATUSCODE_GOOD) {
|
||||
ua_print("ua: [%s] connect failed %#x\n", __func__, retval);
|
||||
UA_Client_delete(client);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ua_print("ua: [%s] connect ok!\n", __func__);
|
||||
|
||||
ua_read_time(client);
|
||||
ua_get_server_info(client);
|
||||
|
||||
/* Clean up */
|
||||
UA_Client_disconnect(client);
|
||||
UA_Client_delete(client); /* Disconnects the client internally */
|
||||
}
|
||||
|
||||
void *test_ua_get_server_info_thr(void *arg)
|
||||
{
|
||||
ETH_BSP_Config();
|
||||
lwip_config_tcp(lwip_ipaddr, lwip_netmask, test_ua_gw);
|
||||
test_ua_get_server_info(NULL);
|
||||
}
|
||||
|
||||
void *test_sh_ua_get_server_info(void *param)
|
||||
{
|
||||
int result = 0;
|
||||
pthread_attr_t attr;
|
||||
|
||||
attr.schedparam.sched_priority = 15;
|
||||
attr.stacksize = 4096;
|
||||
|
||||
result = pthread_create(&ua_demo_id, &attr, test_ua_get_server_info_thr, NULL);
|
||||
if (0 == result) {
|
||||
lw_print("test_ua_get_server_info %d successfully!\n", __func__, ua_demo_id);
|
||||
} else {
|
||||
lw_print("test_ua_get_server_info failed! error code is %d\n", __func__, result);
|
||||
}
|
||||
}
|
||||
|
||||
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN) | SHELL_CMD_PARAM_NUM(0),
|
||||
UaGetInfo, test_sh_ua_get_server_info, Get information from OpcUA server);
|
||||
|
||||
212
APP_Framework/Applications/framework_init.c
Normal file
212
APP_Framework/Applications/framework_init.c
Normal file
@@ -0,0 +1,212 @@
|
||||
/*
|
||||
* Copyright (c) 2020 AIIT XUOS Lab
|
||||
* XiUOS is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
* See the Mulan PSL v2 for more details.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <transform.h>
|
||||
|
||||
extern int SensorFrameworkInit(void);
|
||||
extern int AdapterFrameworkInit(void);
|
||||
|
||||
extern int Adapter4GInit(void);
|
||||
extern int AdapterNbiotInit(void);
|
||||
extern int AdapterBlueToothInit(void);
|
||||
extern int AdapterWifiInit(void);
|
||||
extern int AdapterEthernetInit(void);
|
||||
extern int AdapterZigbeeInit(void);
|
||||
extern int AdapterLoraInit(void);
|
||||
|
||||
extern int D124VoiceInit(void);
|
||||
extern int Hs300xTemperatureInit(void);
|
||||
extern int Hs300xHumidityInit(void);
|
||||
extern int Ps5308Pm1_0Init(void);
|
||||
extern int Ps5308Pm2_5Init(void);
|
||||
extern int Ps5308Pm10Init(void);
|
||||
extern int Zg09Co2Init(void);
|
||||
extern int As830Ch4Init(void);
|
||||
extern int Tb600bIaq10IaqInit(void);
|
||||
extern int Tb600bTvoc10TvocInit(void);
|
||||
extern int Tb600bWqHcho1osInit(void);
|
||||
|
||||
typedef int (*InitFunc)(void);
|
||||
struct InitDesc
|
||||
{
|
||||
const char* fn_name;
|
||||
const InitFunc fn;
|
||||
};
|
||||
|
||||
static int AppInitDesc(struct InitDesc sub_desc[])
|
||||
{
|
||||
int i = 0;
|
||||
int ret = 0;
|
||||
for( i = 0; sub_desc[i].fn != NULL; i++ ) {
|
||||
ret = sub_desc[i].fn();
|
||||
printf("initialize %s %s\n",sub_desc[i].fn_name, ret == 0 ? "success" : "failed");
|
||||
if(0 != ret) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct InitDesc framework[] =
|
||||
{
|
||||
#ifdef SUPPORT_SENSOR_FRAMEWORK
|
||||
{ "sensor_framework", SensorFrameworkInit },
|
||||
#endif
|
||||
|
||||
#ifdef SUPPORT_CONNECTION_FRAMEWORK
|
||||
{ "connection_framework", AdapterFrameworkInit },
|
||||
#endif
|
||||
|
||||
{ "NULL", NULL },
|
||||
};
|
||||
|
||||
static struct InitDesc sensor_desc[] =
|
||||
{
|
||||
#ifdef SENSOR_DEVICE_D124
|
||||
{ "d124_voice", D124VoiceInit },
|
||||
#endif
|
||||
|
||||
#ifdef SENSOR_DEVICE_HS300X
|
||||
#ifdef SENSOR_QUANTITY_HS300X_TEMPERATURE
|
||||
{ "hs300x_temperature", Hs300xTemperatureInit },
|
||||
#endif
|
||||
#ifdef SENSOR_QUANTITY_HS300X_HUMIDITY
|
||||
{ "hs300x_humidity", Hs300xHumidityInit },
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef SENSOR_PS5308
|
||||
#ifdef SENSOR_QUANTITY_PS5308_PM1_0
|
||||
{ "ps5308_pm1_0", Ps5308Pm1_0Init },
|
||||
#endif
|
||||
#ifdef SENSOR_QUANTITY_PS5308_PM2_5
|
||||
{ "ps5308_pm2_5", Ps5308Pm2_5Init },
|
||||
#endif
|
||||
#ifdef SENSOR_QUANTITY_PS5308_PM10
|
||||
{ "ps5308_pm10", Ps5308Pm10Init },
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef SENSOR_ZG09
|
||||
{ "zg09_co2", Zg09Co2Init },
|
||||
#endif
|
||||
|
||||
#ifdef SENSOR_AS830
|
||||
{ "ch4_as830", As830Ch4Init },
|
||||
#endif
|
||||
|
||||
#ifdef SENSOR_TB600B_IAQ10
|
||||
{ "iaq_tb600b_iaq10", Tb600bIaq10IaqInit },
|
||||
#endif
|
||||
|
||||
#ifdef SENSOR_TB600B_TVOC10
|
||||
{ "tvoc_tb600b_tvoc10", Tb600bTvoc10TvocInit },
|
||||
#endif
|
||||
|
||||
#ifdef SENSOR_TB600B_WQ_HCHO1OS
|
||||
{ "tvoc_tb600b_wq_hcho1os", Tb600bWqHcho1osInit },
|
||||
#endif
|
||||
|
||||
{ "NULL", NULL },
|
||||
};
|
||||
|
||||
static struct InitDesc connection_desc[] =
|
||||
{
|
||||
#ifdef CONNECTION_ADAPTER_4G
|
||||
{ "4G adapter", Adapter4GInit},
|
||||
#endif
|
||||
#ifdef CONNECTION_ADAPTER_NB
|
||||
{ "NB adpter", AdapterNbiotInit},
|
||||
#endif
|
||||
#ifdef CONNECTION_ADAPTER_ZIGBEE
|
||||
{ "zigbee adapter", AdapterZigbeeInit},
|
||||
#endif
|
||||
#ifdef CONNECTION_ADAPTER_BLUETOOTH
|
||||
{ "bluetooth adapter", AdapterBlueToothInit},
|
||||
#endif
|
||||
#ifdef CONNECTION_ADAPTER_WIFI
|
||||
{ "wifi adapter", AdapterWifiInit},
|
||||
#endif
|
||||
#ifdef CONNECTION_ADAPTER_ETHERNET
|
||||
{ "ethernet adapter", AdapterEthernetInit},
|
||||
#endif
|
||||
#ifdef CONNECTION_ADAPTER_LORA
|
||||
{ "lora adapter", AdapterLoraInit},
|
||||
#endif
|
||||
{ "NULL", NULL },
|
||||
};
|
||||
|
||||
/**
|
||||
* This function will init sensor framework and all sub sensors
|
||||
* @param sub_desc framework
|
||||
*
|
||||
*/
|
||||
static int SensorDeviceFrameworkInit(struct InitDesc sub_desc[])
|
||||
{
|
||||
int i = 0;
|
||||
int ret = 0;
|
||||
for ( i = 0; sub_desc[i].fn != NULL; i++ ) {
|
||||
if (0 == strncmp(sub_desc[i].fn_name, "sensor_framework", strlen("sensor_framework"))) {
|
||||
ret = sub_desc[i].fn();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (0 == ret) {
|
||||
printf("initialize sensor_framework success.\n");
|
||||
AppInitDesc(sensor_desc);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function will init connection framework and all sub components
|
||||
* @param sub_desc framework
|
||||
*
|
||||
*/
|
||||
static int ConnectionDeviceFrameworkInit(struct InitDesc sub_desc[])
|
||||
{
|
||||
int i = 0;
|
||||
int ret = 0;
|
||||
for ( i = 0; sub_desc[i].fn != NULL; i++ ) {
|
||||
if (0 == strncmp(sub_desc[i].fn_name, "connection_framework", strlen("connection_framework"))) {
|
||||
ret = sub_desc[i].fn();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (0 == ret) {
|
||||
printf("initialize connection_framework success.\n");
|
||||
AppInitDesc(connection_desc);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function will init system framework
|
||||
*
|
||||
*/
|
||||
int FrameworkInit(void)
|
||||
{
|
||||
#ifdef SUPPORT_SENSOR_FRAMEWORK
|
||||
SensorDeviceFrameworkInit(framework);
|
||||
#endif
|
||||
|
||||
#ifdef SUPPORT_CONNECTION_FRAMEWORK
|
||||
ConnectionDeviceFrameworkInit(framework);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
3
APP_Framework/Applications/general_functions/Makefile
Normal file
3
APP_Framework/Applications/general_functions/Makefile
Normal file
@@ -0,0 +1,3 @@
|
||||
SRC_DIR := list
|
||||
|
||||
include $(KERNEL_ROOT)/compiler.mk
|
||||
14
APP_Framework/Applications/general_functions/SConscript
Normal file
14
APP_Framework/Applications/general_functions/SConscript
Normal file
@@ -0,0 +1,14 @@
|
||||
import os
|
||||
Import('RTT_ROOT')
|
||||
from building import *
|
||||
|
||||
cwd = GetCurrentDir()
|
||||
objs = []
|
||||
list = os.listdir(cwd)
|
||||
|
||||
for d in list:
|
||||
path = os.path.join(cwd, d)
|
||||
if os.path.isfile(os.path.join(path, 'SConscript')):
|
||||
objs = objs + SConscript(os.path.join(path, 'SConscript'))
|
||||
|
||||
Return('objs')
|
||||
11
APP_Framework/Applications/general_functions/list/Makefile
Normal file
11
APP_Framework/Applications/general_functions/list/Makefile
Normal file
@@ -0,0 +1,11 @@
|
||||
include $(KERNEL_ROOT)/.config
|
||||
ifeq ($(CONFIG_ADD_NUTTX_FETURES),y)
|
||||
include $(APPDIR)/Make.defs
|
||||
CSRCS += double_list.c single_list.c
|
||||
include $(APPDIR)/Application.mk
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_ADD_XIUOS_FETURES),y)
|
||||
SRC_FILES := double_list.c single_list.c
|
||||
include $(KERNEL_ROOT)/compiler.mk
|
||||
endif
|
||||
11
APP_Framework/Applications/general_functions/list/SConscript
Normal file
11
APP_Framework/Applications/general_functions/list/SConscript
Normal file
@@ -0,0 +1,11 @@
|
||||
import os
|
||||
from building import *
|
||||
Import('RTT_ROOT')
|
||||
Import('rtconfig')
|
||||
cwd = GetCurrentDir()
|
||||
DEPENDS = [""]
|
||||
|
||||
SOURCES = ['double_list.c'] + ['single_list.c']
|
||||
path = [cwd]
|
||||
objs = DefineGroup('list', src = SOURCES, depend = DEPENDS,CPPPATH = path)
|
||||
Return("objs")
|
||||
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* Copyright (c) 2020 AIIT XUOS Lab
|
||||
* XiUOS is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
* See the Mulan PSL v2 for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file: double_link.c
|
||||
* @brief: functions definition of double list for application
|
||||
* @version: 1.0
|
||||
* @author: AIIT XUOS Lab
|
||||
* @date: 2020/3/15
|
||||
*
|
||||
*/
|
||||
|
||||
#include "list.h"
|
||||
|
||||
void AppInitDoubleList(DoublelistType *list_head)
|
||||
{
|
||||
list_head->node_next = list_head;
|
||||
list_head->node_prev = list_head;
|
||||
}
|
||||
|
||||
void AppDoubleListInsertNodeAfter(DoublelistType *list, DoublelistType *list_node)
|
||||
{
|
||||
list->node_next->node_prev = list_node;
|
||||
list_node->node_next = list->node_next;
|
||||
|
||||
list->node_next = list_node;
|
||||
list_node->node_prev = list;
|
||||
}
|
||||
|
||||
void AppDoubleListInsertNodeBefore(DoublelistType *list, DoublelistType *list_node)
|
||||
{
|
||||
list->node_prev->node_next = list_node;
|
||||
list_node->node_prev = list->node_prev;
|
||||
|
||||
list->node_prev = list_node;
|
||||
list_node->node_next = list;
|
||||
}
|
||||
|
||||
void AppDoubleListRmNode(DoublelistType *list_node)
|
||||
{
|
||||
list_node->node_next->node_prev = list_node->node_prev;
|
||||
list_node->node_prev->node_next = list_node->node_next;
|
||||
|
||||
list_node->node_next = list_node;
|
||||
list_node->node_prev = list_node;
|
||||
}
|
||||
|
||||
int AppIsDoubleListEmpty(const DoublelistType *list)
|
||||
{
|
||||
return list->node_next == list;
|
||||
}
|
||||
|
||||
struct DoublelistNode *AppDoubleListGetHead(const DoublelistType *list)
|
||||
{
|
||||
return AppIsDoubleListEmpty(list) ? NULL : list->node_next;
|
||||
}
|
||||
|
||||
struct DoublelistNode *AppDoubleListGetNext(const DoublelistType *list,
|
||||
const struct DoublelistNode *list_node)
|
||||
{
|
||||
return list_node->node_next == list ? NULL : list_node->node_next;
|
||||
}
|
||||
|
||||
unsigned int AppDoubleListLenGet(const DoublelistType *list)
|
||||
{
|
||||
unsigned int linklist_length = 0;
|
||||
const DoublelistType *tmp_node = list;
|
||||
while (tmp_node->node_next != list)
|
||||
{
|
||||
tmp_node = tmp_node->node_next;
|
||||
linklist_length ++;
|
||||
}
|
||||
|
||||
return linklist_length;
|
||||
}
|
||||
120
APP_Framework/Applications/general_functions/list/list.h
Normal file
120
APP_Framework/Applications/general_functions/list/list.h
Normal file
@@ -0,0 +1,120 @@
|
||||
/*
|
||||
* Copyright (c) 2020 AIIT XUOS Lab
|
||||
* XiUOS is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
* See the Mulan PSL v2 for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file: list.h
|
||||
* @brief: function declaration and structure defintion of list
|
||||
* @version: 1.0
|
||||
* @author: AIIT XUOS Lab
|
||||
* @date: 2021/6/23
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __LIST_H__
|
||||
#define __LIST_H__
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdarg.h>
|
||||
#include <fcntl.h>
|
||||
#include<stddef.h>
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
typedef struct DoublelistNode
|
||||
{
|
||||
struct DoublelistNode *node_next;
|
||||
struct DoublelistNode *node_prev;
|
||||
} DoublelistType;
|
||||
|
||||
// Single List
|
||||
typedef struct SinglelistNode
|
||||
{
|
||||
struct SinglelistNode *node_next;
|
||||
} SinglelistType;
|
||||
|
||||
|
||||
#define CONTAINER_OF(item, type, member) \
|
||||
((type *)((char *)(item) - (unsigned long)(&((type *)0)->member)))
|
||||
|
||||
|
||||
#define DOUBLE_LIST_OBJ_INIT(obj) { &(obj), &(obj) }
|
||||
|
||||
void AppInitDoubleList(DoublelistType *linklist_head);
|
||||
void AppDoubleListInsertNodeAfter(DoublelistType *list, DoublelistType *list_node);
|
||||
void AppDoubleListInsertNodeBefore(DoublelistType *list, DoublelistType *list_node);
|
||||
void AppDoubleListRmNode(DoublelistType *list_node);
|
||||
int AppIsDoubleListEmpty(const DoublelistType *list);
|
||||
struct DoublelistNode *AppDoubleLinkListGetHead(const DoublelistType *list);
|
||||
struct DoublelistNode *AppDoubleLinkListGetNext(const DoublelistType *list,
|
||||
const struct DoublelistNode *list_node);
|
||||
unsigned int AppDoubleListLenGet(const DoublelistType *list);
|
||||
|
||||
#define DOUBLE_LIST_ENTRY(item, type, member) \
|
||||
CONTAINER_OF(item, type, member)
|
||||
|
||||
#define DOUBLE_LIST_FOR_EACH(item, head) \
|
||||
for (item = (head)->node_next; item != (head); item = item->node_next)
|
||||
|
||||
#define DOUBLE_LIST_FOR_EACH_SAFE(item, node_next, head) \
|
||||
for (item = (head)->node_next, node_next = item->node_next; item != (head); \
|
||||
item = node_next, node_next = item->node_next)
|
||||
|
||||
#define DOUBLE_LIST_FOR_EACH_ENTRY(item, head, member) \
|
||||
for (item = DOUBLE_LIST_ENTRY((head)->node_next, typeof(*item), member); \
|
||||
&item->member != (head); \
|
||||
item = DOUBLE_LIST_ENTRY(item->member.node_next, typeof(*item), member))
|
||||
|
||||
#define DOUBLE_LIST_FOR_EACH_ENTRY_SAFE(item, node_next, head, member) \
|
||||
for (item = DOUBLE_LIST_ENTRY((head)->node_next, typeof(*item), member), \
|
||||
node_next = DOUBLE_LIST_ENTRY(item->member.node_next, typeof(*item), member); \
|
||||
&item->member != (head); \
|
||||
item = node_next, node_next = DOUBLE_LIST_ENTRY(node_next->member.node_next, typeof(*node_next), member))
|
||||
|
||||
#define DOUBLE_LIST_FIRST_ENTRY(ptr, type, member) \
|
||||
DOUBLE_LIST_ENTRY((ptr)->node_next, type, member)
|
||||
|
||||
#define SINGLE_LIST_OBJ_INIT(obj) { NONE }
|
||||
|
||||
void AppInitSingleList(SinglelistType *list);
|
||||
void AppAppendSingleList(SinglelistType *list, SinglelistType *list_node);
|
||||
void AppSingleListNodeInsert(SinglelistType *list, SinglelistType *list_node);
|
||||
unsigned int AppSingleListGetLen(const SinglelistType *list);
|
||||
SinglelistType *AppSingleListRmNode(SinglelistType *list, SinglelistType *list_node);
|
||||
SinglelistType *AppSingleListGetFirstNode(SinglelistType *list);
|
||||
SinglelistType *AppSingleListGetTailNode(SinglelistType *list);
|
||||
SinglelistType *AppSingleListGetNextNode(SinglelistType *list_node);
|
||||
int AppIsSingleListEmpty(SinglelistType *list);
|
||||
|
||||
#define SINGLE_LIST_ENTRY(node, type, member) \
|
||||
CONTAINER_OF(node, type, member)
|
||||
|
||||
#define SINGLE_LIST_FOR_EACH(item, head) \
|
||||
for (item = (head)->node_next; item != NONE; item = item->node_next)
|
||||
|
||||
#define SINGLE_LIST_FOR_EACH_ENTRY(item, head, member) \
|
||||
for (item = SINGLE_LIST_ENTRY((head)->node_next, typeof(*item), member); \
|
||||
&item->member != (NONE); \
|
||||
item = SINGLE_LIST_ENTRY(item->member.node_next, typeof(*item), member))
|
||||
|
||||
#define SINGLE_LIST_FIRST_ENTRY(ptr, type, member) \
|
||||
SINGLE_LIST_ENTRY((ptr)->node_next, type, member)
|
||||
|
||||
#define SINGLE_LIST_TAIL_ENTRY(ptr, type, member) \
|
||||
SINGLE_LIST_ENTRY(AppSingleListGetTailNode(ptr), type, member)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* Copyright (c) 2020 AIIT XUOS Lab
|
||||
* XiUOS is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
* See the Mulan PSL v2 for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file: double_link.c
|
||||
* @brief: functions definition of single list for application
|
||||
* @version: 1.0
|
||||
* @author: AIIT XUOS Lab
|
||||
* @date: 2020/3/15
|
||||
*
|
||||
*/
|
||||
|
||||
#include "list.h"
|
||||
|
||||
void AppInitSingleList(SinglelistType *list)
|
||||
{
|
||||
list->node_next = NULL;
|
||||
}
|
||||
|
||||
void AppAppendSingleList(SinglelistType *list, SinglelistType *list_node)
|
||||
{
|
||||
struct SinglelistNode *node;
|
||||
|
||||
node = list;
|
||||
while (node->node_next) node = node->node_next;
|
||||
|
||||
node->node_next = list_node;
|
||||
list_node->node_next = NULL;
|
||||
}
|
||||
|
||||
void AppSingleListNodeInsert(SinglelistType *list, SinglelistType *list_node)
|
||||
{
|
||||
list_node->node_next = list->node_next;
|
||||
list->node_next = list_node;
|
||||
}
|
||||
|
||||
unsigned int AppSingleListGetLen(const SinglelistType *list)
|
||||
{
|
||||
unsigned int length = 0;
|
||||
const SinglelistType *tmp_list = list->node_next;
|
||||
while (tmp_list != NULL)
|
||||
{
|
||||
tmp_list = tmp_list->node_next;
|
||||
length ++;
|
||||
}
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
SinglelistType *AppSingleListRmNode(SinglelistType *list, SinglelistType *list_node)
|
||||
{
|
||||
struct SinglelistNode *node = list;
|
||||
while (node->node_next && node->node_next != list_node) node = node->node_next;
|
||||
|
||||
if (node->node_next != (SinglelistType *)0){
|
||||
node->node_next = node->node_next->node_next;
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
SinglelistType *AppSingleListGetFirstNode(SinglelistType *list)
|
||||
{
|
||||
return list->node_next;
|
||||
}
|
||||
|
||||
SinglelistType *AppSingleListGetTailNode(SinglelistType *list)
|
||||
{
|
||||
while (list->node_next) list = list->node_next;
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
SinglelistType *AppSingleListGetNextNode(SinglelistType *list_node)
|
||||
{
|
||||
return list_node->node_next;
|
||||
}
|
||||
|
||||
int AppIsSingleListEmpty(SinglelistType *list)
|
||||
{
|
||||
return list->node_next == NULL;
|
||||
}
|
||||
15
APP_Framework/Applications/knowing_app/Kconfig
Executable file
15
APP_Framework/Applications/knowing_app/Kconfig
Executable file
@@ -0,0 +1,15 @@
|
||||
menu "knowing app"
|
||||
menuconfig APPLICATION_KNOWING
|
||||
bool "Using knowing apps"
|
||||
default n
|
||||
|
||||
if APPLICATION_KNOWING
|
||||
source "$APP_DIR/Applications/knowing_app/mnist/Kconfig"
|
||||
source "$APP_DIR/Applications/knowing_app/k210_detect_entry/Kconfig"
|
||||
source "$APP_DIR/Applications/knowing_app/iris_ml_demo/Kconfig"
|
||||
source "$APP_DIR/Applications/knowing_app/k210_fft_test/Kconfig"
|
||||
source "$APP_DIR/Applications/knowing_app/image_processing/Kconfig"
|
||||
source "$APP_DIR/Applications/knowing_app/cmsis_5_demo/Kconfig"
|
||||
|
||||
endif
|
||||
endmenu
|
||||
3
APP_Framework/Applications/knowing_app/Makefile
Executable file
3
APP_Framework/Applications/knowing_app/Makefile
Executable file
@@ -0,0 +1,3 @@
|
||||
SRC_DIR := mnist
|
||||
|
||||
include $(KERNEL_ROOT)/compiler.mk
|
||||
14
APP_Framework/Applications/knowing_app/SConscript
Normal file
14
APP_Framework/Applications/knowing_app/SConscript
Normal file
@@ -0,0 +1,14 @@
|
||||
import os
|
||||
Import('RTT_ROOT')
|
||||
from building import *
|
||||
|
||||
cwd = GetCurrentDir()
|
||||
objs = []
|
||||
list = os.listdir(cwd)
|
||||
|
||||
for d in list:
|
||||
path = os.path.join(cwd, d)
|
||||
if os.path.isfile(os.path.join(path, 'SConscript')):
|
||||
objs = objs + SConscript(os.path.join(path, 'SConscript'))
|
||||
|
||||
Return('objs')
|
||||
16
APP_Framework/Applications/knowing_app/cmsis_5_demo/Kconfig
Normal file
16
APP_Framework/Applications/knowing_app/cmsis_5_demo/Kconfig
Normal file
@@ -0,0 +1,16 @@
|
||||
menuconfig USING_CMSIS_5_DEMOAPP
|
||||
bool "CMSIS-5 demo app"
|
||||
depends on USING_USING_CMSIS_5_NN
|
||||
default n
|
||||
|
||||
if USING_CMSIS_5_DEMOAPP
|
||||
|
||||
config USING_CMSIS_5_NN_DEMOAPP
|
||||
bool "Using CMSIS-5 NN demo app"
|
||||
select USING_IMAGE_PROCESSING
|
||||
select IMAGE_PROCESSING_USING_TJPGD
|
||||
default n
|
||||
|
||||
endif
|
||||
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
import os
|
||||
Import('RTT_ROOT')
|
||||
from building import *
|
||||
|
||||
cwd = GetCurrentDir()
|
||||
objs = []
|
||||
list = os.listdir(cwd)
|
||||
|
||||
for d in list:
|
||||
path = os.path.join(cwd, d)
|
||||
if os.path.isfile(os.path.join(path, 'SConscript')):
|
||||
objs = objs + SConscript(os.path.join(path, 'SConscript'))
|
||||
|
||||
Return('objs')
|
||||
@@ -0,0 +1,14 @@
|
||||
# CMSIS-NN cifar10 example
|
||||
|
||||
The model of this example is from [[ARM-software](https://github.com/ARM-software)/**[ML-examples](https://github.com/ARM-software/ML-examples)**] and can be deployed on Arm Cortex-M CPUs using [CMSIS-NN](https://github.com/ARM-software/CMSIS_5).
|
||||
|
||||
## Requirements:
|
||||
- CMSIS-NN in Framework/knowing/cmsis_5
|
||||
- TJpgDec in Framework/knowing/image_processing
|
||||
- Enough stack size (recommend 10240) for finsh thread which can be changed in "RT-Thread Components->Command shell->finsh shell" by menuconfig.
|
||||
|
||||
## To run this demo:
|
||||
- Place the photo where you want
|
||||
- Run demo by type the command
|
||||
```
|
||||
cmsisnn_demo /path/to/photo
|
||||
@@ -0,0 +1,18 @@
|
||||
from building import *
|
||||
import os
|
||||
|
||||
cwd = GetCurrentDir()
|
||||
|
||||
src = Split('''
|
||||
model/m4/nn.c
|
||||
demo/cmsisnn_demo.c
|
||||
''')
|
||||
|
||||
path = [
|
||||
cwd + '/model/m4',
|
||||
cwd + '/demo'
|
||||
]
|
||||
|
||||
group = DefineGroup('CMSISNN-cifar10', src, depend = ['USING_CMSIS_5_DEMOAPP'], CPPPATH = path)
|
||||
|
||||
Return('group')
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 1000 B |
@@ -0,0 +1,157 @@
|
||||
#include <transform.h>
|
||||
#include <tjpgd.h>
|
||||
#include "../model/m4/nn.h"
|
||||
|
||||
#define WORK_POOL_SIZE (4 * 1024 + 32)
|
||||
|
||||
const char *cifar10_label[] = {"Plane", "Car", "Bird", "Cat", "Deer", "Dog", "Frog", "Horse", "Ship", "Truck"};
|
||||
|
||||
int get_top_prediction(q7_t *predictions)
|
||||
{
|
||||
int max_ind = 0;
|
||||
int max_val = -128;
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
if (max_val < predictions[i])
|
||||
{
|
||||
max_val = predictions[i];
|
||||
max_ind = i;
|
||||
}
|
||||
}
|
||||
return max_ind;
|
||||
}
|
||||
|
||||
int cmsisnn_inference(uint8_t *input_data)
|
||||
{
|
||||
q7_t output_data[10];
|
||||
run_nn((q7_t *)input_data, output_data);
|
||||
arm_softmax_q7(output_data, IP1_OUT_DIM, output_data);
|
||||
int top_ind = get_top_prediction(output_data);
|
||||
printf("\rPrediction: %s \r\n", cifar10_label[top_ind]);
|
||||
return top_ind;
|
||||
}
|
||||
|
||||
typedef struct
|
||||
{
|
||||
FILE *fp;
|
||||
uint8_t *fbuf;
|
||||
uint16_t wfbuf;
|
||||
} IODEV;
|
||||
|
||||
unsigned int in_func_cmsisnn(JDEC *jd, uint8_t *buff, unsigned int nbyte)
|
||||
{
|
||||
IODEV *dev = (IODEV *)jd->device;
|
||||
|
||||
if (buff)
|
||||
{
|
||||
return (uint16_t)fread(buff, 1, nbyte, dev->fp);
|
||||
}
|
||||
else
|
||||
{
|
||||
return fseek(dev->fp, nbyte, SEEK_CUR) ? 0 : nbyte;
|
||||
}
|
||||
}
|
||||
|
||||
int out_func_cmsisnn(JDEC *jd, void *bitmap, JRECT *rect)
|
||||
{
|
||||
IODEV *dev = (IODEV *)jd->device;
|
||||
uint8_t *src, *dst;
|
||||
uint16_t y, bws, bwd;
|
||||
|
||||
if (rect->left == 0)
|
||||
{
|
||||
printf("\r%lu%%", (rect->top << jd->scale) * 100UL / jd->height);
|
||||
}
|
||||
|
||||
src = (uint8_t *)bitmap;
|
||||
dst = dev->fbuf + 3 * (rect->top * dev->wfbuf + rect->left);
|
||||
bws = 3 * (rect->right - rect->left + 1);
|
||||
bwd = 3 * dev->wfbuf;
|
||||
for (y = rect->top; y <= rect->bottom; y++)
|
||||
{
|
||||
memcpy(dst, src, bws);
|
||||
src += bws;
|
||||
dst += bwd;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int cmsisnn_demo(int argc, char *argv[])
|
||||
{
|
||||
void *work;
|
||||
JDEC jdec;
|
||||
JRESULT res;
|
||||
IODEV devid;
|
||||
|
||||
if (argc < 2)
|
||||
{
|
||||
printf("Jpeg_Dec illegal arguments ...\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
devid.fp = fopen(argv[1], "r+");
|
||||
if (!devid.fp)
|
||||
{
|
||||
printf("Jpeg_Dec open the file failed...\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
work = malloc(WORK_POOL_SIZE);
|
||||
if (work == NULL)
|
||||
{
|
||||
printf("Jpeg_Dec work malloc failed...\n");
|
||||
res = -1;
|
||||
goto __exit;
|
||||
}
|
||||
|
||||
res = jd_prepare(&jdec, in_func_cmsisnn, work, WORK_POOL_SIZE, &devid);
|
||||
if (res == JDR_OK)
|
||||
{
|
||||
printf("Image dimensions: %u by %u. %u bytes used.\n", jdec.width, jdec.height, 3100 - jdec.sz_pool);
|
||||
|
||||
devid.fbuf = malloc(3 * jdec.width * jdec.height);
|
||||
if (devid.fbuf == NULL)
|
||||
{
|
||||
printf("Jpeg_Dec devid.fbuf malloc failed, need to use %d Bytes ...\n", 3 * jdec.width * jdec.height);
|
||||
res = -1;
|
||||
goto __exit;
|
||||
}
|
||||
devid.wfbuf = jdec.width;
|
||||
|
||||
res = jd_decomp(&jdec, out_func_cmsisnn, 0);
|
||||
if (res == JDR_OK)
|
||||
{
|
||||
printf("\rDecompress success \n");
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Failed to decompress: rc=%d\n", res);
|
||||
}
|
||||
|
||||
cmsisnn_inference(devid.fbuf);
|
||||
|
||||
if (devid.fbuf != NULL)
|
||||
{
|
||||
free(devid.fbuf);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Failed to prepare: rc=%d\n", res);
|
||||
}
|
||||
|
||||
__exit:
|
||||
if (work != NULL)
|
||||
{
|
||||
free(work);
|
||||
}
|
||||
|
||||
fclose(devid.fp);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
#ifdef __RT_THREAD_H__
|
||||
MSH_CMD_EXPORT(cmsisnn_demo, cifar10 demo and filename should be followed);
|
||||
#endif
|
||||
@@ -0,0 +1,46 @@
|
||||
#include "nn.h"
|
||||
|
||||
// Timer t;
|
||||
|
||||
static uint8_t mean[DATA_OUT_CH*DATA_OUT_DIM*DATA_OUT_DIM] = MEAN_DATA;
|
||||
|
||||
static q7_t conv1_wt[CONV1_IN_CH*CONV1_KER_DIM*CONV1_KER_DIM*CONV1_OUT_CH] = CONV1_WT;
|
||||
static q7_t conv1_bias[CONV1_OUT_CH] = CONV1_BIAS;
|
||||
|
||||
static q7_t conv2_wt[CONV2_IN_CH*CONV2_KER_DIM*CONV2_KER_DIM*CONV2_OUT_CH] = CONV2_WT;
|
||||
static q7_t conv2_bias[CONV2_OUT_CH] = CONV2_BIAS;
|
||||
|
||||
static q7_t conv3_wt[CONV3_IN_CH*CONV3_KER_DIM*CONV3_KER_DIM*CONV3_OUT_CH] = CONV3_WT;
|
||||
static q7_t conv3_bias[CONV3_OUT_CH] = CONV3_BIAS;
|
||||
|
||||
static q7_t ip1_wt[IP1_IN_DIM*IP1_OUT_DIM] = IP1_WT;
|
||||
static q7_t ip1_bias[IP1_OUT_DIM] = IP1_BIAS;
|
||||
|
||||
//Add input_data and output_data in top main.cpp file
|
||||
//uint8_t input_data[DATA_OUT_CH*DATA_OUT_DIM*DATA_OUT_DIM];
|
||||
//q7_t output_data[IP1_OUT_DIM];
|
||||
|
||||
q7_t col_buffer[3200];
|
||||
q7_t scratch_buffer[40960];
|
||||
|
||||
void mean_subtract(q7_t* image_data) {
|
||||
for(int i=0; i<DATA_OUT_CH*DATA_OUT_DIM*DATA_OUT_DIM; i++) {
|
||||
image_data[i] = (q7_t)__SSAT( ((int)(image_data[i] - mean[i]) >> DATA_RSHIFT), 8);
|
||||
}
|
||||
}
|
||||
|
||||
void run_nn(q7_t* input_data, q7_t* output_data) {
|
||||
q7_t* buffer1 = scratch_buffer;
|
||||
q7_t* buffer2 = buffer1 + 32768;
|
||||
mean_subtract(input_data);
|
||||
arm_convolve_HWC_q7_RGB(input_data, CONV1_IN_DIM, CONV1_IN_CH, conv1_wt, CONV1_OUT_CH, CONV1_KER_DIM, CONV1_PAD, CONV1_STRIDE, conv1_bias, CONV1_BIAS_LSHIFT, CONV1_OUT_RSHIFT, buffer1, CONV1_OUT_DIM, (q15_t*)col_buffer, NULL);
|
||||
arm_maxpool_q7_HWC(buffer1, POOL1_IN_DIM, POOL1_IN_CH, POOL1_KER_DIM, POOL1_PAD, POOL1_STRIDE, POOL1_OUT_DIM, col_buffer, buffer2);
|
||||
arm_relu_q7(buffer2, RELU1_OUT_DIM*RELU1_OUT_DIM*RELU1_OUT_CH);
|
||||
arm_convolve_HWC_q7_fast(buffer2, CONV2_IN_DIM, CONV2_IN_CH, conv2_wt, CONV2_OUT_CH, CONV2_KER_DIM, CONV2_PAD, CONV2_STRIDE, conv2_bias, CONV2_BIAS_LSHIFT, CONV2_OUT_RSHIFT, buffer1, CONV2_OUT_DIM, (q15_t*)col_buffer, NULL);
|
||||
arm_relu_q7(buffer1, RELU2_OUT_DIM*RELU2_OUT_DIM*RELU2_OUT_CH);
|
||||
arm_avepool_q7_HWC(buffer1, POOL2_IN_DIM, POOL2_IN_CH, POOL2_KER_DIM, POOL2_PAD, POOL2_STRIDE, POOL2_OUT_DIM, col_buffer, buffer2);
|
||||
arm_convolve_HWC_q7_fast(buffer2, CONV3_IN_DIM, CONV3_IN_CH, conv3_wt, CONV3_OUT_CH, CONV3_KER_DIM, CONV3_PAD, CONV3_STRIDE, conv3_bias, CONV3_BIAS_LSHIFT, CONV3_OUT_RSHIFT, buffer1, CONV3_OUT_DIM, (q15_t*)col_buffer, NULL);
|
||||
arm_relu_q7(buffer1, RELU3_OUT_DIM*RELU3_OUT_DIM*RELU3_OUT_CH);
|
||||
arm_avepool_q7_HWC(buffer1, POOL3_IN_DIM, POOL3_IN_CH, POOL3_KER_DIM, POOL3_PAD, POOL3_STRIDE, POOL3_OUT_DIM, col_buffer, buffer2);
|
||||
arm_fully_connected_q7_opt(buffer2, ip1_wt, IP1_IN_DIM, IP1_OUT_DIM, IP1_BIAS_LSHIFT, IP1_OUT_RSHIFT, ip1_bias, output_data, (q15_t*)col_buffer);
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
#ifndef __NN_H__
|
||||
#define __NN_H__
|
||||
|
||||
// #include "mbed.h"
|
||||
#include "arm_math.h"
|
||||
#include "parameter.h"
|
||||
#include "weights.h"
|
||||
#include "arm_nnfunctions.h"
|
||||
|
||||
void run_nn(q7_t* input_data, q7_t* output_data);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,69 @@
|
||||
#define DATA_OUT_CH 3
|
||||
#define DATA_OUT_DIM 32
|
||||
|
||||
#define CONV1_IN_DIM 32
|
||||
#define CONV1_IN_CH 3
|
||||
#define CONV1_KER_DIM 5
|
||||
#define CONV1_PAD 2
|
||||
#define CONV1_STRIDE 1
|
||||
#define CONV1_OUT_CH 32
|
||||
#define CONV1_OUT_DIM 32
|
||||
|
||||
#define POOL1_IN_DIM 32
|
||||
#define POOL1_IN_CH 32
|
||||
#define POOL1_KER_DIM 3
|
||||
#define POOL1_STRIDE 2
|
||||
#define POOL1_PAD 0
|
||||
#define POOL1_OUT_DIM 16
|
||||
|
||||
#define RELU1_OUT_CH 32
|
||||
#define RELU1_OUT_DIM 16
|
||||
|
||||
#define CONV2_IN_DIM 16
|
||||
#define CONV2_IN_CH 32
|
||||
#define CONV2_KER_DIM 5
|
||||
#define CONV2_PAD 2
|
||||
#define CONV2_STRIDE 1
|
||||
#define CONV2_OUT_CH 16
|
||||
#define CONV2_OUT_DIM 16
|
||||
|
||||
#define RELU2_OUT_CH 16
|
||||
#define RELU2_OUT_DIM 16
|
||||
|
||||
#define POOL2_IN_DIM 16
|
||||
#define POOL2_IN_CH 16
|
||||
#define POOL2_KER_DIM 3
|
||||
#define POOL2_STRIDE 2
|
||||
#define POOL2_PAD 0
|
||||
#define POOL2_OUT_DIM 8
|
||||
|
||||
#define CONV3_IN_DIM 8
|
||||
#define CONV3_IN_CH 16
|
||||
#define CONV3_KER_DIM 5
|
||||
#define CONV3_PAD 2
|
||||
#define CONV3_STRIDE 1
|
||||
#define CONV3_OUT_CH 32
|
||||
#define CONV3_OUT_DIM 8
|
||||
|
||||
#define RELU3_OUT_CH 32
|
||||
#define RELU3_OUT_DIM 8
|
||||
|
||||
#define POOL3_IN_DIM 8
|
||||
#define POOL3_IN_CH 32
|
||||
#define POOL3_KER_DIM 3
|
||||
#define POOL3_STRIDE 2
|
||||
#define POOL3_PAD 0
|
||||
#define POOL3_OUT_DIM 4
|
||||
|
||||
#define IP1_IN_DIM 512
|
||||
#define IP1_OUT_DIM 10
|
||||
|
||||
#define DATA_RSHIFT 0
|
||||
#define CONV1_BIAS_LSHIFT 0
|
||||
#define CONV1_OUT_RSHIFT 11
|
||||
#define CONV2_BIAS_LSHIFT 0
|
||||
#define CONV2_OUT_RSHIFT 8
|
||||
#define CONV3_BIAS_LSHIFT 0
|
||||
#define CONV3_OUT_RSHIFT 8
|
||||
#define IP1_BIAS_LSHIFT 5
|
||||
#define IP1_OUT_RSHIFT 7
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,46 @@
|
||||
#include "nn.h"
|
||||
|
||||
// Timer t;
|
||||
|
||||
static uint8_t mean[DATA_OUT_CH*DATA_OUT_DIM*DATA_OUT_DIM] = MEAN_DATA;
|
||||
|
||||
static q7_t conv1_wt[CONV1_IN_CH*CONV1_KER_DIM*CONV1_KER_DIM*CONV1_OUT_CH] = CONV1_WT;
|
||||
static q7_t conv1_bias[CONV1_OUT_CH] = CONV1_BIAS;
|
||||
|
||||
static q7_t conv2_wt[CONV2_IN_CH*CONV2_KER_DIM*CONV2_KER_DIM*CONV2_OUT_CH] = CONV2_WT;
|
||||
static q7_t conv2_bias[CONV2_OUT_CH] = CONV2_BIAS;
|
||||
|
||||
static q7_t conv3_wt[CONV3_IN_CH*CONV3_KER_DIM*CONV3_KER_DIM*CONV3_OUT_CH] = CONV3_WT;
|
||||
static q7_t conv3_bias[CONV3_OUT_CH] = CONV3_BIAS;
|
||||
|
||||
static q7_t ip1_wt[IP1_IN_DIM*IP1_OUT_DIM] = IP1_WT;
|
||||
static q7_t ip1_bias[IP1_OUT_DIM] = IP1_BIAS;
|
||||
|
||||
//Add input_data and output_data in top main.cpp file
|
||||
//uint8_t input_data[DATA_OUT_CH*DATA_OUT_DIM*DATA_OUT_DIM];
|
||||
//q7_t output_data[IP1_OUT_DIM];
|
||||
|
||||
q7_t col_buffer[6400];
|
||||
q7_t scratch_buffer[40960];
|
||||
|
||||
void mean_subtract(q7_t* image_data) {
|
||||
for(int i=0; i<DATA_OUT_CH*DATA_OUT_DIM*DATA_OUT_DIM; i++) {
|
||||
image_data[i] = (q7_t)__SSAT( ((int)(image_data[i] - mean[i]) >> DATA_RSHIFT), 8);
|
||||
}
|
||||
}
|
||||
|
||||
void run_nn(q7_t* input_data, q7_t* output_data) {
|
||||
q7_t* buffer1 = scratch_buffer;
|
||||
q7_t* buffer2 = buffer1 + 32768;
|
||||
mean_subtract(input_data);
|
||||
arm_convolve_HWC_q7_RGB(input_data, CONV1_IN_DIM, CONV1_IN_CH, conv1_wt, CONV1_OUT_CH, CONV1_KER_DIM, CONV1_PAD, CONV1_STRIDE, conv1_bias, CONV1_BIAS_LSHIFT, CONV1_OUT_RSHIFT, buffer1, CONV1_OUT_DIM, (q15_t*)col_buffer, NULL);
|
||||
arm_maxpool_q7_HWC(buffer1, POOL1_IN_DIM, POOL1_IN_CH, POOL1_KER_DIM, POOL1_PAD, POOL1_STRIDE, POOL1_OUT_DIM, col_buffer, buffer2);
|
||||
arm_relu_q7(buffer2, RELU1_OUT_DIM*RELU1_OUT_DIM*RELU1_OUT_CH);
|
||||
arm_convolve_HWC_q7_fast(buffer2, CONV2_IN_DIM, CONV2_IN_CH, conv2_wt, CONV2_OUT_CH, CONV2_KER_DIM, CONV2_PAD, CONV2_STRIDE, conv2_bias, CONV2_BIAS_LSHIFT, CONV2_OUT_RSHIFT, buffer1, CONV2_OUT_DIM, (q15_t*)col_buffer, NULL);
|
||||
arm_relu_q7(buffer1, RELU2_OUT_DIM*RELU2_OUT_DIM*RELU2_OUT_CH);
|
||||
arm_avepool_q7_HWC(buffer1, POOL2_IN_DIM, POOL2_IN_CH, POOL2_KER_DIM, POOL2_PAD, POOL2_STRIDE, POOL2_OUT_DIM, col_buffer, buffer2);
|
||||
arm_convolve_HWC_q7_fast(buffer2, CONV3_IN_DIM, CONV3_IN_CH, conv3_wt, CONV3_OUT_CH, CONV3_KER_DIM, CONV3_PAD, CONV3_STRIDE, conv3_bias, CONV3_BIAS_LSHIFT, CONV3_OUT_RSHIFT, buffer1, CONV3_OUT_DIM, (q15_t*)col_buffer, NULL);
|
||||
arm_relu_q7(buffer1, RELU3_OUT_DIM*RELU3_OUT_DIM*RELU3_OUT_CH);
|
||||
arm_avepool_q7_HWC(buffer1, POOL3_IN_DIM, POOL3_IN_CH, POOL3_KER_DIM, POOL3_PAD, POOL3_STRIDE, POOL3_OUT_DIM, col_buffer, buffer2);
|
||||
arm_fully_connected_q7_opt(buffer2, ip1_wt, IP1_IN_DIM, IP1_OUT_DIM, IP1_BIAS_LSHIFT, IP1_OUT_RSHIFT, ip1_bias, output_data, (q15_t*)col_buffer);
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
#ifndef __NN_H__
|
||||
#define __NN_H__
|
||||
|
||||
// #include "mbed.h"
|
||||
#include "arm_math.h"
|
||||
#include "parameter.h"
|
||||
#include "weights.h"
|
||||
#include "arm_nnfunctions.h"
|
||||
|
||||
void run_nn(q7_t* input_data, q7_t* output_data);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,69 @@
|
||||
#define DATA_OUT_CH 3
|
||||
#define DATA_OUT_DIM 32
|
||||
|
||||
#define CONV1_IN_DIM 32
|
||||
#define CONV1_IN_CH 3
|
||||
#define CONV1_KER_DIM 5
|
||||
#define CONV1_PAD 2
|
||||
#define CONV1_STRIDE 1
|
||||
#define CONV1_OUT_CH 32
|
||||
#define CONV1_OUT_DIM 32
|
||||
|
||||
#define POOL1_IN_DIM 32
|
||||
#define POOL1_IN_CH 32
|
||||
#define POOL1_KER_DIM 3
|
||||
#define POOL1_STRIDE 2
|
||||
#define POOL1_PAD 0
|
||||
#define POOL1_OUT_DIM 16
|
||||
|
||||
#define RELU1_OUT_CH 32
|
||||
#define RELU1_OUT_DIM 16
|
||||
|
||||
#define CONV2_IN_DIM 16
|
||||
#define CONV2_IN_CH 32
|
||||
#define CONV2_KER_DIM 5
|
||||
#define CONV2_PAD 2
|
||||
#define CONV2_STRIDE 1
|
||||
#define CONV2_OUT_CH 32
|
||||
#define CONV2_OUT_DIM 16
|
||||
|
||||
#define RELU2_OUT_CH 32
|
||||
#define RELU2_OUT_DIM 16
|
||||
|
||||
#define POOL2_IN_DIM 16
|
||||
#define POOL2_IN_CH 32
|
||||
#define POOL2_KER_DIM 3
|
||||
#define POOL2_STRIDE 2
|
||||
#define POOL2_PAD 0
|
||||
#define POOL2_OUT_DIM 8
|
||||
|
||||
#define CONV3_IN_DIM 8
|
||||
#define CONV3_IN_CH 32
|
||||
#define CONV3_KER_DIM 5
|
||||
#define CONV3_PAD 2
|
||||
#define CONV3_STRIDE 1
|
||||
#define CONV3_OUT_CH 64
|
||||
#define CONV3_OUT_DIM 8
|
||||
|
||||
#define RELU3_OUT_CH 64
|
||||
#define RELU3_OUT_DIM 8
|
||||
|
||||
#define POOL3_IN_DIM 8
|
||||
#define POOL3_IN_CH 64
|
||||
#define POOL3_KER_DIM 3
|
||||
#define POOL3_STRIDE 2
|
||||
#define POOL3_PAD 0
|
||||
#define POOL3_OUT_DIM 4
|
||||
|
||||
#define IP1_IN_DIM 1024
|
||||
#define IP1_OUT_DIM 10
|
||||
|
||||
#define DATA_RSHIFT 0
|
||||
#define CONV1_BIAS_LSHIFT 0
|
||||
#define CONV1_OUT_RSHIFT 9
|
||||
#define CONV2_BIAS_LSHIFT 0
|
||||
#define CONV2_OUT_RSHIFT 9
|
||||
#define CONV3_BIAS_LSHIFT 0
|
||||
#define CONV3_OUT_RSHIFT 9
|
||||
#define IP1_BIAS_LSHIFT 3
|
||||
#define IP1_OUT_RSHIFT 5
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,6 @@
|
||||
menuconfig USING_IMAGE_PROCESSING_APP
|
||||
bool "image processing app "
|
||||
default n
|
||||
if USING_IMAGE_PROCESSING_APP
|
||||
source "$APP_DIR/Applications/knowing_app/image_processing/TJpgDec_APP/Kconfig"
|
||||
endif
|
||||
@@ -0,0 +1,14 @@
|
||||
import os
|
||||
Import('RTT_ROOT')
|
||||
from building import *
|
||||
|
||||
cwd = GetCurrentDir()
|
||||
objs = []
|
||||
list = os.listdir(cwd)
|
||||
|
||||
for d in list:
|
||||
path = os.path.join(cwd, d)
|
||||
if os.path.isfile(os.path.join(path, 'SConscript')):
|
||||
objs = objs + SConscript(os.path.join(path, 'SConscript'))
|
||||
|
||||
Return('objs')
|
||||
@@ -0,0 +1,4 @@
|
||||
config IMAGE_PROCESSING_TJPGDEC_APP
|
||||
bool "image processing apps/TJpgDec(example)"
|
||||
select IMAGE_PROCESSING_USING_TJPGD
|
||||
default n
|
||||
@@ -0,0 +1,9 @@
|
||||
from building import *
|
||||
|
||||
cwd = GetCurrentDir()
|
||||
src = Glob('*.c') + Glob('*.cpp')
|
||||
CPPPATH = [cwd]
|
||||
|
||||
group = DefineGroup('TJpgDec(example)', src, depend = ['IMAGE_PROCESSING_TJPGDEC_APP'], LOCAL_CPPPATH = CPPPATH)
|
||||
|
||||
Return('group')
|
||||
@@ -0,0 +1,151 @@
|
||||
#include <transform.h>
|
||||
#include <tjpgd.h>
|
||||
#define WORK_POOL_SIZE (4*1024+32)//This value depends on the resolution of the image
|
||||
|
||||
/* User defined device identifier */
|
||||
typedef struct {
|
||||
FILE *fp; /* File pointer for input function */
|
||||
uint8_t *fbuf; /* Pointer to the frame buffer for output function */
|
||||
uint16_t wfbuf; /* Width of the frame buffer [pix] */
|
||||
} IODEV;
|
||||
|
||||
|
||||
/*------------------------------*/
|
||||
/* User defined input funciton */
|
||||
/*------------------------------*/
|
||||
|
||||
unsigned int in_func (JDEC* jd, uint8_t* buff, unsigned int nbyte)
|
||||
{
|
||||
IODEV *dev = (IODEV*)jd->device; /* Device identifier for the session (5th argument of jd_prepare function) */
|
||||
|
||||
|
||||
if (buff) {
|
||||
/* Read bytes from input stream */
|
||||
return (uint16_t)fread(buff, 1, nbyte, dev->fp);
|
||||
} else {
|
||||
/* Remove bytes from input stream */
|
||||
return fseek(dev->fp, nbyte, SEEK_CUR) ? 0 : nbyte;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*------------------------------*/
|
||||
/* User defined output funciton */
|
||||
/*------------------------------*/
|
||||
|
||||
int out_func (JDEC* jd, void* bitmap, JRECT* rect)
|
||||
{
|
||||
IODEV *dev = (IODEV*)jd->device;
|
||||
uint8_t *src, *dst;
|
||||
uint16_t y, bws, bwd;
|
||||
|
||||
|
||||
/* Put progress indicator */
|
||||
if (rect->left == 0) {
|
||||
printf("\r%lu%%", (rect->top << jd->scale) * 100UL / jd->height);
|
||||
}
|
||||
|
||||
/* Copy the decompressed RGB rectanglar to the frame buffer (assuming RGB888 cfg) */
|
||||
src = (uint8_t*)bitmap;
|
||||
dst = dev->fbuf + 3 * (rect->top * dev->wfbuf + rect->left); /* Left-top of destination rectangular */
|
||||
bws = 3 * (rect->right - rect->left + 1); /* Width of source rectangular [byte] */
|
||||
bwd = 3 * dev->wfbuf; /* Width of frame buffer [byte] */
|
||||
for (y = rect->top; y <= rect->bottom; y++) {
|
||||
memcpy(dst, src, bws); /* Copy a line */
|
||||
src += bws; dst += bwd; /* Next line */
|
||||
}
|
||||
|
||||
return 1; /* Continue to decompress */
|
||||
}
|
||||
|
||||
|
||||
/*------------------------------*/
|
||||
/* Program Jpeg_Dec */
|
||||
/*------------------------------*/
|
||||
|
||||
int Jpeg_Dec (int argc, char* argv[])
|
||||
{
|
||||
void *work; /* Pointer to the decompressor work area */
|
||||
JDEC jdec; /* Decompression object */
|
||||
JRESULT res; /* Result code of TJpgDec API */
|
||||
IODEV devid; /* User defined device identifier */
|
||||
|
||||
/* Open a JPEG file */
|
||||
if (argc < 2)
|
||||
{
|
||||
printf("Jpeg_Dec illegal arguments ...\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
devid.fp = fopen(argv[1], "r+");
|
||||
if (!devid.fp)
|
||||
{
|
||||
printf("Jpeg_Dec open the file failed...\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Allocate a work area for TJpgDec */
|
||||
work = malloc(WORK_POOL_SIZE);
|
||||
if(work == NULL)
|
||||
{
|
||||
printf("Jpeg_Dec work malloc failed...\n");
|
||||
res = -1;
|
||||
goto __exit;
|
||||
}
|
||||
|
||||
/* Prepare to decompress */
|
||||
res = jd_prepare(&jdec, in_func, work, WORK_POOL_SIZE, &devid);
|
||||
if (res == JDR_OK)
|
||||
{
|
||||
/* Ready to dcompress. Image info is available here. */
|
||||
printf("Image dimensions: %u by %u. %u bytes used.\n", jdec.width, jdec.height, 3100 - jdec.sz_pool);
|
||||
|
||||
devid.fbuf = malloc(3 * jdec.width * jdec.height); /* Frame buffer for output image (assuming RGB888 cfg) */
|
||||
if(devid.fbuf == RT_NULL)
|
||||
{
|
||||
printf("Jpeg_Dec devid.fbuf malloc failed, need to use %d Bytes ...\n", 3 * jdec.width * jdec.height);
|
||||
res = -1;
|
||||
goto __exit;
|
||||
}
|
||||
devid.wfbuf = jdec.width;
|
||||
|
||||
res = jd_decomp(&jdec, out_func, 0); /* Start to decompress with 1/1 scaling */
|
||||
if (res == JDR_OK) {
|
||||
/* Decompression succeeded. You have the decompressed image in the frame buffer here. */
|
||||
printf("\rOK \n");
|
||||
// for(int j = 0; j<3 * jdec.width * jdec.height;j++)
|
||||
// {
|
||||
// printf("%d,",*(devid.fbuf+j));
|
||||
// }
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Failed to decompress: rc=%d\n", res);
|
||||
}
|
||||
|
||||
if(devid.fbuf != NULL)
|
||||
{
|
||||
free(devid.fbuf); /* Discard frame buffer */
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Failed to prepare: rc=%d\n", res);
|
||||
}
|
||||
|
||||
__exit:
|
||||
if(work != NULL)
|
||||
{
|
||||
free(work); /* Discard work area */
|
||||
}
|
||||
|
||||
fclose(devid.fp); /* Close the JPEG file */
|
||||
|
||||
return res;
|
||||
}
|
||||
#ifdef __RT_THREAD_H__
|
||||
MSH_CMD_EXPORT(Jpeg_Dec, Jpeg Decode Test);
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
#include <stdarg.h>
|
||||
|
||||
/**
|
||||
* Predict class for features vector
|
||||
*/
|
||||
int predict(float *x)
|
||||
{
|
||||
if (x[2] <= 2.449999988079071) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
else {
|
||||
if (x[3] <= 1.75) {
|
||||
if (x[2] <= 4.950000047683716) {
|
||||
if (x[3] <= 1.6500000357627869) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
else {
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
||||
else {
|
||||
if (x[3] <= 1.550000011920929) {
|
||||
return 2;
|
||||
}
|
||||
|
||||
else {
|
||||
if (x[2] <= 5.450000047683716) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
else {
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
else {
|
||||
if (x[2] <= 4.8500001430511475) {
|
||||
if (x[1] <= 3.100000023841858) {
|
||||
return 2;
|
||||
}
|
||||
|
||||
else {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
else {
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
config IRIS_ML_DEMO
|
||||
bool "enable apps/iris ml demo"
|
||||
default n
|
||||
@@ -0,0 +1,41 @@
|
||||
#include <stdarg.h>
|
||||
|
||||
/**
|
||||
* Compute dot product
|
||||
*/
|
||||
float dot(float *x, ...)
|
||||
{
|
||||
va_list w;
|
||||
va_start(w, 4);
|
||||
float dot = 0.0;
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
const float wi = va_arg(w, double);
|
||||
dot += x[i] * wi;
|
||||
}
|
||||
|
||||
return dot;
|
||||
}
|
||||
|
||||
/**
|
||||
* Predict class for features vector
|
||||
*/
|
||||
int predict(float *x)
|
||||
{
|
||||
float votes[3] = {0.0f};
|
||||
votes[0] = dot(x, -0.423405592418, 0.967388282125, -2.517050233286, -1.079182996654) + 9.84868307535428;
|
||||
votes[1] = dot(x, 0.534517184386, -0.321908835083, -0.206465997471, -0.944448257908) + 2.238120068472271;
|
||||
votes[2] = dot(x, -0.111111591968, -0.645479447042, 2.723516230758, 2.023631254562) + -12.086803143826813;
|
||||
// return argmax of votes
|
||||
int classIdx = 0;
|
||||
float maxVotes = votes[0];
|
||||
|
||||
for (int i = 1; i < 3; i++) {
|
||||
if (votes[i] > maxVotes) {
|
||||
classIdx = i;
|
||||
maxVotes = votes[i];
|
||||
}
|
||||
}
|
||||
|
||||
return classIdx;
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
# Machine learning demo using iris dataset
|
||||
|
||||
### Classification task demo, tested on stm32f4 and k210-based edge devices. Training on iris dataset by *Decision Tree classifier*, *Support Vector Machine classifier* and *Logistic Regression classifier*.
|
||||
|
||||
---
|
||||
|
||||
## Training
|
||||
|
||||
Model generated by [Sklearn](https://scikit-learn.org/stable/) and converted to C language by [micromlgen](https://forgeplus.trustie.net/projects/yangtuo250/micromlgen).
|
||||
|
||||
### Enviroment preparation
|
||||
|
||||
```shell
|
||||
pip install scikit-learn
|
||||
git clone https://git.trustie.net/yangtuo250/micromlgen.git -b C
|
||||
cd micromlgen && pip install -e .
|
||||
```
|
||||
|
||||
### Train it!
|
||||
|
||||
```python
|
||||
# load iris dataset
|
||||
from sklearn.datasets import load_iris
|
||||
X, y = load_iris(return_X_y=True)
|
||||
|
||||
# train SVC classifier and convert
|
||||
clf = SVC(kernel='linear', gamma=0.001).fit(X, y)
|
||||
print(port(clf, cplusplus=False, platform=platforms.STM32F4))
|
||||
|
||||
# train logistic regression classifier and convert
|
||||
clf = LogisticRegression(max_iter=1000).fit(X, y)
|
||||
print(port(clf, cplusplus=False, platform=platforms.STM32F4))
|
||||
|
||||
# train decision tree classifier and convert
|
||||
clf = DecisionTreeClassifier().fit(X, y)
|
||||
print(port(clf, cplusplus=False, platform=platforms.STM32F4)
|
||||
```
|
||||
Copy each content generated by print to a single C language file.
|
||||
|
||||
---
|
||||
|
||||
## Deployment
|
||||
|
||||
### compile and burn
|
||||
|
||||
Use `(scons --)menuconfig` in *bsp folder(Ubiquitous/RT_Thread/bsp/k210(or stm32f407-atk-coreboard))*, open **APP_Framwork --> Applications --> knowing app --> enable apps/iris ml demo** to enable this app. `scons -j(n)` to compile and burn in by *st-flash(for ARM)* or *kflash(for k210)*.
|
||||
|
||||
### testing set
|
||||
|
||||
Copy *iris.csv* to SD card */csv/iris.csv*.
|
||||
|
||||
---
|
||||
|
||||
## Run
|
||||
|
||||
In serial terminal:
|
||||
- `iris_SVC_predict` for SVC prediction
|
||||
- `iris_DecisonTree_predict` for decision tree prediction
|
||||
- `iris_LogisticRegression_predict` for logistic regression prediction
|
||||
|
||||
Example output:
|
||||
|
||||
```shell
|
||||
data 1: 5.1000 3.5000 1.4000 0.2000 result: 0
|
||||
data 2: 6.4000 3.2000 4.5000 1.5000 result: 1
|
||||
data 3: 5.8000 2.7000 5.1000 1.9000 result: 2
|
||||
data 4: 7.7000 3.8000 6.7000 2.2000 result: 2
|
||||
data 5: 5.5000 2.6000 4.4000 1.2000 result: 1
|
||||
data 6: 5.1000 3.8000 1.9000 0.4000 result: 0
|
||||
data 7: 5.8000 2.7000 3.9000 1.2000 result: 1
|
||||
```
|
||||
@@ -0,0 +1,9 @@
|
||||
from building import *
|
||||
|
||||
cwd = GetCurrentDir()
|
||||
src = Glob('*.c') + Glob('*.cpp')
|
||||
CPPPATH = [cwd]
|
||||
|
||||
group = DefineGroup('Applications', src, depend = ['IRIS_ML_DEMO'], LOCAL_CPPPATH = CPPPATH)
|
||||
|
||||
Return('group')
|
||||
@@ -0,0 +1,78 @@
|
||||
/**
|
||||
* SVC model trained by iris dataset
|
||||
*/
|
||||
#include <stdarg.h>
|
||||
|
||||
/**
|
||||
* Compute kernel between feature vector and support vector.
|
||||
* Kernel type: linear
|
||||
*/
|
||||
float compute_kernel(float *x, ...)
|
||||
{
|
||||
va_list w;
|
||||
va_start(w, 4);
|
||||
float kernel = 0.0;
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
kernel += x[i] * va_arg(w, double);
|
||||
}
|
||||
|
||||
return kernel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Predict class for features vector
|
||||
*/
|
||||
int predict(float *x)
|
||||
{
|
||||
float kernels[27] = {0};
|
||||
float decisions[3] = {0};
|
||||
int votes[3] = {0};
|
||||
kernels[0] = compute_kernel(x, 5.1, 3.3, 1.7, 0.5);
|
||||
kernels[1] = compute_kernel(x, 4.8, 3.4, 1.9, 0.2);
|
||||
kernels[2] = compute_kernel(x, 4.5, 2.3, 1.3, 0.3);
|
||||
kernels[3] = compute_kernel(x, 6.9, 3.1, 4.9, 1.5);
|
||||
kernels[4] = compute_kernel(x, 6.3, 3.3, 4.7, 1.6);
|
||||
kernels[5] = compute_kernel(x, 6.1, 2.9, 4.7, 1.4);
|
||||
kernels[6] = compute_kernel(x, 5.6, 3.0, 4.5, 1.5);
|
||||
kernels[7] = compute_kernel(x, 6.2, 2.2, 4.5, 1.5);
|
||||
kernels[8] = compute_kernel(x, 5.9, 3.2, 4.8, 1.8);
|
||||
kernels[9] = compute_kernel(x, 6.3, 2.5, 4.9, 1.5);
|
||||
kernels[10] = compute_kernel(x, 6.8, 2.8, 4.8, 1.4);
|
||||
kernels[11] = compute_kernel(x, 6.7, 3.0, 5.0, 1.7);
|
||||
kernels[12] = compute_kernel(x, 6.0, 2.7, 5.1, 1.6);
|
||||
kernels[13] = compute_kernel(x, 5.4, 3.0, 4.5, 1.5);
|
||||
kernels[14] = compute_kernel(x, 5.1, 2.5, 3.0, 1.1);
|
||||
kernels[15] = compute_kernel(x, 4.9, 2.5, 4.5, 1.7);
|
||||
kernels[16] = compute_kernel(x, 6.5, 3.2, 5.1, 2.0);
|
||||
kernels[17] = compute_kernel(x, 6.0, 2.2, 5.0, 1.5);
|
||||
kernels[18] = compute_kernel(x, 6.3, 2.7, 4.9, 1.8);
|
||||
kernels[19] = compute_kernel(x, 6.2, 2.8, 4.8, 1.8);
|
||||
kernels[20] = compute_kernel(x, 6.1, 3.0, 4.9, 1.8);
|
||||
kernels[21] = compute_kernel(x, 7.2, 3.0, 5.8, 1.6);
|
||||
kernels[22] = compute_kernel(x, 6.3, 2.8, 5.1, 1.5);
|
||||
kernels[23] = compute_kernel(x, 6.0, 3.0, 4.8, 1.8);
|
||||
kernels[24] = compute_kernel(x, 6.3, 2.5, 5.0, 1.9);
|
||||
kernels[25] = compute_kernel(x, 6.5, 3.0, 5.2, 2.0);
|
||||
kernels[26] = compute_kernel(x, 5.9, 3.0, 5.1, 1.8);
|
||||
decisions[0] = 1.452844496978 + kernels[0] * 0.67075289031 + kernels[2] * 0.077097563476 + kernels[14] * -0.747850453786;
|
||||
decisions[1] = 1.507713125178 + kernels[0] * 0.043820415076 + kernels[1] * 0.159872086718 + kernels[15] * -0.203692501794;
|
||||
decisions[2] = 6.78097118511 + kernels[3] + kernels[4] + kernels[5] + kernels[6] + kernels[7] + kernels[8] + kernels[9] +
|
||||
kernels[10] * 0.243261886421 + kernels[11] + kernels[12] + kernels[13] - kernels[15] - kernels[16] -
|
||||
kernels[17] - kernels[18] - kernels[19] - kernels[20] + kernels[21] * -0.437859817863 - kernels[22] -
|
||||
kernels[23] + kernels[24] * -0.645105347981 + kernels[25] * -0.160296720576 - kernels[26];
|
||||
votes[decisions[0] > 0 ? 0 : 1] += 1;
|
||||
votes[decisions[1] > 0 ? 0 : 2] += 1;
|
||||
votes[decisions[2] > 0 ? 1 : 2] += 1;
|
||||
int val = votes[0];
|
||||
int idx = 0;
|
||||
|
||||
for (int i = 1; i < 3; i++) {
|
||||
if (votes[i] > val) {
|
||||
val = votes[i];
|
||||
idx = i;
|
||||
}
|
||||
}
|
||||
|
||||
return idx;
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
5.1,3.5,1.4,0.2
|
||||
6.4,3.2,4.5,1.5
|
||||
5.8,2.7,5.1,1.9
|
||||
7.7,3.8,6.7,2.2
|
||||
5.5,2.6,4.4,1.2
|
||||
5.1,3.8,1.9,0.4
|
||||
5.8,2.7,3.9,1.2
|
||||
|
@@ -0,0 +1,99 @@
|
||||
#include <string.h>
|
||||
#include <transform.h>
|
||||
|
||||
#define FEATURE_NUM 4
|
||||
#define CSV_PATH "/csv/iris.csv"
|
||||
#define CSV_BUFFER_SIZE (1 * 1024)
|
||||
|
||||
static float data[10][FEATURE_NUM] = {};
|
||||
static int data_len = 0;
|
||||
|
||||
void simple_CSV_read()
|
||||
{
|
||||
int fin;
|
||||
int col = 0;
|
||||
char buffer[CSV_BUFFER_SIZE] = "";
|
||||
char *tmp = "";
|
||||
char *delim = ",\n ";
|
||||
|
||||
fin = open(CSV_PATH, O_RDONLY);
|
||||
if (!fin) {
|
||||
printf("Error open file %s", CSV_PATH);
|
||||
// exit(-1);
|
||||
return;
|
||||
}
|
||||
read(fin, buffer, sizeof(buffer));
|
||||
close(fin);
|
||||
|
||||
data_len = 0;
|
||||
for (tmp = strtok(buffer, delim); tmp && *tmp; col++, tmp = strtok(NULL, delim)) {
|
||||
if (0 == col % FEATURE_NUM) {
|
||||
// printf("\n");
|
||||
data_len++;
|
||||
col = 0;
|
||||
}
|
||||
data[data_len - 1][col] = atof(tmp);
|
||||
// printf("%.4f ", data[data_len - 1][col]);
|
||||
}
|
||||
// printf("\n");
|
||||
}
|
||||
|
||||
void iris_SVC_predict()
|
||||
{
|
||||
#include "SVCModel.h"
|
||||
int result;
|
||||
|
||||
simple_CSV_read();
|
||||
|
||||
for (int i = 0; i < data_len; i++) {
|
||||
result = predict(data[i]);
|
||||
printf("data %d: ", i + 1);
|
||||
for (int j = 0; j < FEATURE_NUM; j++) {
|
||||
printf("%.4f ", data[i][j]);
|
||||
}
|
||||
printf("result: %d\n", result);
|
||||
}
|
||||
}
|
||||
#ifdef __RT_THREAD_H__
|
||||
MSH_CMD_EXPORT(iris_SVC_predict, iris predict by SVC);
|
||||
#endif
|
||||
|
||||
void iris_DecisonTree_predict()
|
||||
{
|
||||
#include "DecisionTreeClassifierModel.h"
|
||||
int result;
|
||||
|
||||
simple_CSV_read();
|
||||
|
||||
for (int i = 0; i < data_len; i++) {
|
||||
result = predict(data[i]);
|
||||
printf("data %d: ", i + 1);
|
||||
for (int j = 0; j < FEATURE_NUM; j++) {
|
||||
printf("%.4f ", data[i][j]);
|
||||
}
|
||||
printf("result: %d\n", result);
|
||||
}
|
||||
}
|
||||
#ifdef __RT_THREAD_H__
|
||||
MSH_CMD_EXPORT(iris_DecisonTree_predict, iris predict by decison tree classifier);
|
||||
#endif
|
||||
|
||||
void iris_LogisticRegression_predict()
|
||||
{
|
||||
#include "LogisticRegressionModel.h"
|
||||
int result;
|
||||
|
||||
simple_CSV_read();
|
||||
|
||||
for (int i = 0; i < data_len; i++) {
|
||||
result = predict(data[i]);
|
||||
printf("data %d: ", i + 1);
|
||||
for (int j = 0; j < FEATURE_NUM; j++) {
|
||||
printf("%.4f ", data[i][j]);
|
||||
}
|
||||
printf("result: %d\n", result);
|
||||
}
|
||||
}
|
||||
#ifdef __RT_THREAD_H__
|
||||
MSH_CMD_EXPORT(iris_LogisticRegression_predict, iris predict by logistic regression);
|
||||
#endif
|
||||
@@ -0,0 +1,10 @@
|
||||
config K210_DETECT_ENTRY
|
||||
bool "enable apps/k210 yolov2 detect entry"
|
||||
depends on BOARD_K210_EVB
|
||||
depends on DRV_USING_OV2640
|
||||
depends on USING_KPU_PROCESSING
|
||||
depends on USING_YOLOV2
|
||||
depends on USING_YOLOV2_JSONPARSER
|
||||
depends on USING_K210_YOLOV2_DETECT
|
||||
select LIB_USING_CJSON
|
||||
default n
|
||||
@@ -0,0 +1,35 @@
|
||||
# Face detection demo
|
||||
|
||||
### A face object detection task demo. Running MobileNet-yolo on K210-based edge devices.
|
||||
|
||||
---
|
||||
|
||||
## Training
|
||||
|
||||
kmodel from [GitHub](https://github.com/kendryte/kendryte-standalone-demo/blob/develop/face_detect/detect.kmodel).
|
||||
|
||||
## Deployment
|
||||
|
||||
### compile and burn
|
||||
|
||||
Use `(scons --)menuconfig` in bsp folder *(Ubiquitous/RT_Thread/bsp/k210)*, open:
|
||||
|
||||
- More Drivers --> ov2640 driver
|
||||
- Board Drivers Config --> Enable LCD on SPI0
|
||||
- Board Drivers Config --> Enable SDCARD (spi1(ss0))
|
||||
- Board Drivers Config --> Enable DVP(camera)
|
||||
- RT-Thread Components --> POSIX layer and C standard library --> Enable pthreads APIs
|
||||
- APP_Framework --> Framework --> support knowing framework --> kpu model postprocessing --> yolov2 region layer
|
||||
- APP_Framework --> Applications --> knowing app --> enable apps/face detect
|
||||
|
||||
`scons -j(n)` to compile and burn in by *kflash*.
|
||||
|
||||
### json config and kmodel
|
||||
|
||||
Copy json config for deployment o SD card */kmodel*. Example config file is *detect.json* in this directory. Copy final kmodel to SD card */kmodel* either.
|
||||
|
||||
---
|
||||
|
||||
## Run
|
||||
|
||||
In serial terminal, `face_detect` to start a detection thread, `face_detect_delete` to stop it. Detection results can be found in output.
|
||||
@@ -0,0 +1,9 @@
|
||||
from building import *
|
||||
|
||||
cwd = GetCurrentDir()
|
||||
src = Glob('*.c') + Glob('*.cpp')
|
||||
CPPPATH = [cwd]
|
||||
|
||||
group = DefineGroup('Applications', src, depend = ['USING_K210_YOLOV2_DETECT'], LOCAL_CPPPATH = CPPPATH)
|
||||
|
||||
Return('group')
|
||||
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"net_input_size": [
|
||||
240,
|
||||
320
|
||||
],
|
||||
"net_output_shape": [
|
||||
20,
|
||||
15,
|
||||
30
|
||||
],
|
||||
"sensor_output_size": [
|
||||
240,
|
||||
320
|
||||
],
|
||||
"anchors": [
|
||||
1.889,
|
||||
2.5245,
|
||||
2.9465,
|
||||
3.94056,
|
||||
3.99987,
|
||||
5.3658,
|
||||
5.155437,
|
||||
6.92275,
|
||||
6.718375,
|
||||
9.01025
|
||||
],
|
||||
"kmodel_size": 388776,
|
||||
"obj_thresh": [
|
||||
0.7
|
||||
],
|
||||
"labels": [
|
||||
"face"
|
||||
],
|
||||
"nms_thresh": 0.3
|
||||
}
|
||||
Binary file not shown.
@@ -0,0 +1,37 @@
|
||||
{
|
||||
"net_input_size": [
|
||||
256,
|
||||
256
|
||||
],
|
||||
"net_output_shape": [
|
||||
8,
|
||||
8,
|
||||
35
|
||||
],
|
||||
"sensor_output_size": [
|
||||
256,
|
||||
256
|
||||
],
|
||||
"anchors": [
|
||||
0.1384,
|
||||
0.276,
|
||||
0.308,
|
||||
0.504,
|
||||
0.5792,
|
||||
0.8952,
|
||||
1.072,
|
||||
1.6184,
|
||||
2.1128,
|
||||
3.184
|
||||
],
|
||||
"kmodel_size": 2714044,
|
||||
"obj_thresh": [
|
||||
0.7,
|
||||
0.99
|
||||
],
|
||||
"labels": [
|
||||
"head",
|
||||
"helmet"
|
||||
],
|
||||
"nms_thresh": 0.45
|
||||
}
|
||||
Binary file not shown.
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"net_input_size": [
|
||||
224,
|
||||
320
|
||||
],
|
||||
"net_output_shape": [
|
||||
10,
|
||||
7,
|
||||
30
|
||||
],
|
||||
"sensor_output_size": [
|
||||
240,
|
||||
320
|
||||
],
|
||||
"anchors": [
|
||||
1.043,
|
||||
1.092,
|
||||
0.839,
|
||||
2.1252,
|
||||
1.109,
|
||||
2.7461,
|
||||
1.378,
|
||||
3.6708,
|
||||
2.049,
|
||||
4.6711
|
||||
],
|
||||
"kmodel_size": 2713236,
|
||||
"obj_thresh": [
|
||||
0.7
|
||||
],
|
||||
"labels": [
|
||||
"human"
|
||||
],
|
||||
"nms_thresh": 0.35
|
||||
}
|
||||
Binary file not shown.
@@ -0,0 +1,16 @@
|
||||
#include "k210_yolov2_detect.h"
|
||||
static void detect_app(int argc, char *argv[])
|
||||
{
|
||||
if (2 != argc) {
|
||||
printf("Usage: detect_app <ABSOLUTE_CONFIG_JSON_PATH>");
|
||||
} else {
|
||||
k210_detect(argv[1]);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
// clang-format off
|
||||
#ifdef __RT_THREAD_H__
|
||||
MSH_CMD_EXPORT(detect_app, k210 detect app usage: detect_app <ABSOLUTE_CONFIG_JSON_PATH>);
|
||||
#endif
|
||||
// clang-format on
|
||||
@@ -0,0 +1,3 @@
|
||||
config K210_FFT_TEST
|
||||
bool "enable apps/k210 fft test"
|
||||
default n
|
||||
@@ -0,0 +1,9 @@
|
||||
from building import *
|
||||
|
||||
cwd = GetCurrentDir()
|
||||
src = Glob('*.c') + Glob('*.cpp')
|
||||
CPPPATH = [cwd]
|
||||
|
||||
group = DefineGroup('Applications', src, depend = ['K210_FFT_TEST'], LOCAL_CPPPATH = CPPPATH)
|
||||
|
||||
Return('group')
|
||||
101
APP_Framework/Applications/knowing_app/k210_fft_test/fft_soft.c
Normal file
101
APP_Framework/Applications/knowing_app/k210_fft_test/fft_soft.c
Normal file
@@ -0,0 +1,101 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include "fft_soft.h"
|
||||
|
||||
#define PI 3.14159265358979323846
|
||||
complex add(complex a, complex b)
|
||||
{
|
||||
complex ret = {a.real + b.real, a.imag + b.imag};
|
||||
return ret;
|
||||
}
|
||||
|
||||
complex sub(complex a, complex b)
|
||||
{
|
||||
complex ret = {a.real - b.real, a.imag - b.imag};
|
||||
return ret;
|
||||
}
|
||||
|
||||
complex mul(complex a, complex b)
|
||||
{
|
||||
complex ret = {a.real * b.real - a.imag * b.imag, a.real * b.imag + a.imag * b.real};
|
||||
return ret;
|
||||
}
|
||||
|
||||
void bitrev(complex *data, int n)
|
||||
{
|
||||
int j = 0;
|
||||
int m = 0;
|
||||
for (int i = 0; i < n; i++)
|
||||
{
|
||||
if (j > i)
|
||||
SWAP(data[i], data[j]);
|
||||
m = n / 2;
|
||||
while (j >= m && m != 0)
|
||||
{
|
||||
j -= m;
|
||||
m >>= 1;
|
||||
}
|
||||
j += m;
|
||||
}
|
||||
}
|
||||
|
||||
void fft_soft(complex *data, int n)
|
||||
{
|
||||
int M = 0;
|
||||
for (int i = n; i > 1; i = i >> 1, M++);
|
||||
|
||||
bitrev(data, n);
|
||||
|
||||
for (int m = 0; m < M; m++)
|
||||
{
|
||||
int K = n >> (m + 1);
|
||||
for (int k = 0; k < K; k++)
|
||||
{
|
||||
int J = 2 << m;
|
||||
int base = k * J;
|
||||
for (int j = 0; j < J / 2; j++)
|
||||
{
|
||||
int t = base + j;
|
||||
complex w = {cos(-2 * PI * j * K / n), sin(-2 * PI * j * K / n)};
|
||||
complex wn = mul(data[t + J / 2], w);
|
||||
complex temp = data[t];
|
||||
data[t] = add(data[t], wn);
|
||||
data[t + J / 2] = sub(temp, wn);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ifft_soft(complex *data, int n)
|
||||
{
|
||||
int M = 0;
|
||||
for (int i = n; i > 1; i = i >> 1, M++);
|
||||
|
||||
bitrev(data, n);
|
||||
|
||||
for (int m = 0; m < M; m++)
|
||||
{
|
||||
int K = n >> (m + 1);
|
||||
for (int k = 0; k < K; k++)
|
||||
{
|
||||
int J = 2 << m;
|
||||
int base = k * J;
|
||||
for (int j = 0; j < J / 2; j++)
|
||||
{
|
||||
int t = base + j;
|
||||
complex w = {cos(2 * PI * j * K / n), sin(2 * PI * j * K / n)};
|
||||
complex wn = mul(data[t + J / 2], w);
|
||||
complex temp = data[t];
|
||||
data[t] = add(data[t], wn);
|
||||
data[t + J / 2] = sub(temp, wn);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < n; i++)
|
||||
{
|
||||
data[i].real /= n;
|
||||
data[i].imag /= n;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
#ifndef _FFT_SOFT_H
|
||||
#define _FFT_SOFT_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define SWAP(a, b) do {complex t = (a); (a) = (b); (b) = t;} while(0)
|
||||
|
||||
typedef struct{double real, imag;} complex;
|
||||
|
||||
void fft_soft(complex *data, int n);
|
||||
void ifft_soft(complex *data, int n);
|
||||
void show(complex *data, int n);
|
||||
|
||||
#endif /* _FFT_SOFT_H */
|
||||
159
APP_Framework/Applications/knowing_app/k210_fft_test/fft_test.c
Normal file
159
APP_Framework/Applications/knowing_app/k210_fft_test/fft_test.c
Normal file
@@ -0,0 +1,159 @@
|
||||
/* Copyright 2018 Canaan Inc.
|
||||
*
|
||||
* 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 <transform.h>
|
||||
#include <math.h>
|
||||
#include "encoding.h"
|
||||
#include "dmac.h"
|
||||
#include "fft.h"
|
||||
#include "encoding.h"
|
||||
#include "sysctl.h"
|
||||
#include "fft_soft.h"
|
||||
|
||||
#define FFT_N 512U
|
||||
#define FFT_FORWARD_SHIFT 0x0U
|
||||
#define FFT_BACKWARD_SHIFT 0x1ffU
|
||||
#define PI 3.14159265358979323846
|
||||
|
||||
typedef enum _complex_mode
|
||||
{
|
||||
FFT_HARD = 0,
|
||||
FFT_SOFT = 1,
|
||||
FFT_COMPLEX_MAX,
|
||||
} complex_mode_t;
|
||||
|
||||
int16_t real[FFT_N];
|
||||
int16_t imag[FFT_N];
|
||||
float hard_power[FFT_N];
|
||||
float soft_power[FFT_N];
|
||||
float hard_angel[FFT_N];
|
||||
float soft_angel[FFT_N];
|
||||
uint64_t fft_out_data[FFT_N / 2];
|
||||
uint64_t buffer_input[FFT_N];
|
||||
uint64_t buffer_output[FFT_N];
|
||||
uint64_t cycle[FFT_COMPLEX_MAX][FFT_DIR_MAX];
|
||||
|
||||
uint16_t get_bit1_num(uint32_t data)
|
||||
{
|
||||
uint16_t num;
|
||||
for (num = 0; data; num++)
|
||||
data &= data - 1;
|
||||
return num;
|
||||
}
|
||||
|
||||
void k210_fft_test(void)
|
||||
{
|
||||
int32_t i;
|
||||
float tempf1[3];
|
||||
fft_data_t *output_data;
|
||||
fft_data_t *input_data;
|
||||
uint16_t bit1_num = get_bit1_num(FFT_FORWARD_SHIFT);
|
||||
complex_hard_t data_hard[FFT_N] = {0};
|
||||
complex data_soft[FFT_N] = {0};
|
||||
for (i = 0; i < FFT_N; i++)
|
||||
{
|
||||
tempf1[0] = 0.3 * cosf(2 * PI * i / FFT_N + PI / 3) * 256;
|
||||
tempf1[1] = 0.1 * cosf(16 * 2 * PI * i / FFT_N - PI / 9) * 256;
|
||||
tempf1[2] = 0.5 * cosf((19 * 2 * PI * i / FFT_N) + PI / 6) * 256;
|
||||
data_hard[i].real = (int16_t)(tempf1[0] + tempf1[1] + tempf1[2] + 10);
|
||||
data_hard[i].imag = (int16_t)0;
|
||||
data_soft[i].real = data_hard[i].real;
|
||||
data_soft[i].imag = data_hard[i].imag;
|
||||
}
|
||||
for (int i = 0; i < FFT_N / 2; ++i)
|
||||
{
|
||||
input_data = (fft_data_t *)&buffer_input[i];
|
||||
input_data->R1 = data_hard[2 * i].real;
|
||||
input_data->I1 = data_hard[2 * i].imag;
|
||||
input_data->R2 = data_hard[2 * i + 1].real;
|
||||
input_data->I2 = data_hard[2 * i + 1].imag;
|
||||
}
|
||||
cycle[FFT_HARD][FFT_DIR_FORWARD] = read_cycle();
|
||||
fft_complex_uint16_dma(DMAC_CHANNEL0, DMAC_CHANNEL1, FFT_FORWARD_SHIFT, FFT_DIR_FORWARD, buffer_input, FFT_N, buffer_output);
|
||||
cycle[FFT_HARD][FFT_DIR_FORWARD] = read_cycle() - cycle[FFT_HARD][FFT_DIR_FORWARD];
|
||||
cycle[FFT_SOFT][FFT_DIR_FORWARD] = read_cycle();
|
||||
fft_soft(data_soft, FFT_N);
|
||||
cycle[FFT_SOFT][FFT_DIR_FORWARD] = read_cycle() - cycle[FFT_SOFT][FFT_DIR_FORWARD];
|
||||
for (i = 0; i < FFT_N / 2; i++)
|
||||
{
|
||||
output_data = (fft_data_t*)&buffer_output[i];
|
||||
data_hard[2 * i].imag = output_data->I1 ;
|
||||
data_hard[2 * i].real = output_data->R1 ;
|
||||
data_hard[2 * i + 1].imag = output_data->I2 ;
|
||||
data_hard[2 * i + 1].real = output_data->R2 ;
|
||||
}
|
||||
|
||||
for (i = 0; i < FFT_N; i++)
|
||||
{
|
||||
hard_power[i] = sqrt(data_hard[i].real * data_hard[i].real + data_hard[i].imag * data_hard[i].imag) * 2;
|
||||
soft_power[i] = sqrt(data_soft[i].real * data_soft[i].real + data_soft[i].imag * data_soft[i].imag) * 2;
|
||||
}
|
||||
|
||||
printf("\n[hard fft real][soft fft real][hard fft imag][soft fft imag]\n");
|
||||
for (i = 0; i < FFT_N / 2; i++)
|
||||
printf("%3d:%7d %7d %7d %7d\n",
|
||||
i, data_hard[i].real, (int32_t)data_soft[i].real, data_hard[i].imag, (int32_t)data_soft[i].imag);
|
||||
|
||||
printf("\nhard power soft power:\n");
|
||||
printf("%3d : %f %f\n", 0, hard_power[0] / 2 / FFT_N * (1 << bit1_num), soft_power[0] / 2 / FFT_N);
|
||||
for (i = 1; i < FFT_N / 2; i++)
|
||||
printf("%3d : %f %f\n", i, hard_power[i] / FFT_N * (1 << bit1_num), soft_power[i] / FFT_N);
|
||||
|
||||
printf("\nhard phase soft phase:\n");
|
||||
for (i = 0; i < FFT_N / 2; i++)
|
||||
{
|
||||
hard_angel[i] = atan2(data_hard[i].imag, data_hard[i].real);
|
||||
soft_angel[i] = atan2(data_soft[i].imag, data_soft[i].real);
|
||||
printf("%3d : %f %f\n", i, hard_angel[i] * 180 / PI, soft_angel[i] * 180 / PI);
|
||||
}
|
||||
|
||||
for (int i = 0; i < FFT_N / 2; ++i)
|
||||
{
|
||||
input_data = (fft_data_t *)&buffer_input[i];
|
||||
input_data->R1 = data_hard[2 * i].real;
|
||||
input_data->I1 = data_hard[2 * i].imag;
|
||||
input_data->R2 = data_hard[2 * i + 1].real;
|
||||
input_data->I2 = data_hard[2 * i + 1].imag;
|
||||
}
|
||||
cycle[FFT_HARD][FFT_DIR_BACKWARD] = read_cycle();
|
||||
fft_complex_uint16_dma(DMAC_CHANNEL0, DMAC_CHANNEL1, FFT_BACKWARD_SHIFT, FFT_DIR_BACKWARD, buffer_input, FFT_N, buffer_output);
|
||||
cycle[FFT_HARD][FFT_DIR_BACKWARD] = read_cycle() - cycle[FFT_HARD][FFT_DIR_BACKWARD];
|
||||
cycle[FFT_SOFT][FFT_DIR_BACKWARD] = read_cycle();
|
||||
ifft_soft(data_soft, FFT_N);
|
||||
cycle[FFT_SOFT][FFT_DIR_BACKWARD] = read_cycle() - cycle[FFT_SOFT][FFT_DIR_BACKWARD];
|
||||
for (i = 0; i < FFT_N / 2; i++)
|
||||
{
|
||||
output_data = (fft_data_t*)&buffer_output[i];
|
||||
data_hard[2 * i].imag = output_data->I1 ;
|
||||
data_hard[2 * i].real = output_data->R1 ;
|
||||
data_hard[2 * i + 1].imag = output_data->I2 ;
|
||||
data_hard[2 * i + 1].real = output_data->R2 ;
|
||||
}
|
||||
printf("\n[hard ifft real][soft ifft real][hard ifft imag][soft ifft imag]\n");
|
||||
for (i = 0; i < FFT_N / 2; i++)
|
||||
printf("%3d:%7d %7d %7d %7d\n",
|
||||
i, data_hard[i].real, (int32_t)data_soft[i].real, data_hard[i].imag, (int32_t)data_soft[i].imag);
|
||||
|
||||
printf("[hard fft test] [%d bytes] forward time = %ld us, backward time = %ld us\n",
|
||||
FFT_N,
|
||||
cycle[FFT_HARD][FFT_DIR_FORWARD]/(sysctl_clock_get_freq(SYSCTL_CLOCK_CPU)/1000000),
|
||||
cycle[FFT_HARD][FFT_DIR_BACKWARD]/(sysctl_clock_get_freq(SYSCTL_CLOCK_CPU)/1000000));
|
||||
printf("[soft fft test] [%d bytes] forward time = %ld us, backward time = %ld us\n",
|
||||
FFT_N,
|
||||
cycle[FFT_SOFT][FFT_DIR_FORWARD]/(sysctl_clock_get_freq(SYSCTL_CLOCK_CPU)/1000000),
|
||||
cycle[FFT_SOFT][FFT_DIR_BACKWARD]/(sysctl_clock_get_freq(SYSCTL_CLOCK_CPU)/1000000));
|
||||
}
|
||||
#ifdef __RT_THREAD_H__
|
||||
MSH_CMD_EXPORT(k210_fft_test,k210 fft test );
|
||||
#endif
|
||||
BIN
APP_Framework/Applications/knowing_app/mnist/K210 mnist .png
Normal file
BIN
APP_Framework/Applications/knowing_app/mnist/K210 mnist .png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 32 KiB |
4
APP_Framework/Applications/knowing_app/mnist/Kconfig
Normal file
4
APP_Framework/Applications/knowing_app/mnist/Kconfig
Normal file
@@ -0,0 +1,4 @@
|
||||
config APP_MNIST
|
||||
bool "enable apps/mnist"
|
||||
depends on USING_TENSORFLOWLITEMICRO
|
||||
default n
|
||||
7
APP_Framework/Applications/knowing_app/mnist/Makefile
Executable file
7
APP_Framework/Applications/knowing_app/mnist/Makefile
Executable file
@@ -0,0 +1,7 @@
|
||||
SRC_FILES := \
|
||||
main.cpp \
|
||||
mnistmain.c
|
||||
CPPPATHS += -I.
|
||||
|
||||
|
||||
include $(KERNEL_ROOT)/compiler.mk
|
||||
23
APP_Framework/Applications/knowing_app/mnist/README.md
Normal file
23
APP_Framework/Applications/knowing_app/mnist/README.md
Normal file
@@ -0,0 +1,23 @@
|
||||
# MNIST 说明
|
||||
|
||||
要使用本例程,MCU RAM必须至少500K左右,所以本例程目前在K210上面验证过,stm32f407 目前在rtt上原则上只能采取dlmodule加载的方式。
|
||||
|
||||

|
||||
|
||||
## 使用
|
||||
|
||||
tools/mnist-train.py 训练生成 mnist 模型。
|
||||
|
||||
tools/mnist-inference.py 使用 mnist 模型进行推理。
|
||||
|
||||
tools/mnist-c-model.py 将 mnist 模型转换成 C 的数组保存在 model.h 中。
|
||||
|
||||
tools/mnist-c-digit.py 将 mnist 数据集中的某个数字转成数组保存在 digit.h 中。
|
||||
|
||||
## 参考资料
|
||||
|
||||
https://tensorflow.google.cn/lite/performance/post_training_quantization
|
||||
|
||||
https://tensorflow.google.cn/lite/performance/post_training_integer_quant
|
||||
|
||||
https://colab.research.google.com/github/tensorflow/tensorflow/blob/master/tensorflow/lite/micro/examples/hello_world/train/train_hello_world_model.ipynb
|
||||
9
APP_Framework/Applications/knowing_app/mnist/SConscript
Normal file
9
APP_Framework/Applications/knowing_app/mnist/SConscript
Normal file
@@ -0,0 +1,9 @@
|
||||
from building import *
|
||||
|
||||
cwd = GetCurrentDir()
|
||||
src = Glob('*.c') + Glob('*.cpp')
|
||||
CPPPATH = [cwd]
|
||||
|
||||
group = DefineGroup('Applications', src, depend = ['APP_MNIST'], LOCAL_CPPPATH = CPPPATH)
|
||||
|
||||
Return('group')
|
||||
@@ -1,23 +1,3 @@
|
||||
/*
|
||||
* Copyright (c) 2020 AIIT XUOS Lab
|
||||
* XiOS is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
* See the Mulan PSL v2 for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file: digit.h
|
||||
* @brief: store digits in this file
|
||||
* @version: 1.0
|
||||
* @author: AIIT XUOS Lab
|
||||
* @date: 2021/4/30
|
||||
*
|
||||
*/
|
||||
const float mnist_digit[] = {
|
||||
0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00,
|
||||
0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00,
|
||||
97
APP_Framework/Applications/knowing_app/mnist/main.cpp
Normal file
97
APP_Framework/Applications/knowing_app/mnist/main.cpp
Normal file
@@ -0,0 +1,97 @@
|
||||
#include <cstdio>
|
||||
#include <transform.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "tensorflow/lite/micro/all_ops_resolver.h"
|
||||
#include "tensorflow/lite/micro/micro_error_reporter.h"
|
||||
#include "tensorflow/lite/micro/micro_interpreter.h"
|
||||
#include "tensorflow/lite/schema/schema_generated.h"
|
||||
#include "tensorflow/lite/version.h"
|
||||
|
||||
#include "digit.h"
|
||||
#include "model.h"
|
||||
|
||||
namespace {
|
||||
tflite::ErrorReporter* error_reporter = nullptr;
|
||||
const tflite::Model* model = nullptr;
|
||||
tflite::MicroInterpreter* interpreter = nullptr;
|
||||
TfLiteTensor* input = nullptr;
|
||||
TfLiteTensor* output = nullptr;
|
||||
constexpr int kTensorArenaSize = 110 * 1024;
|
||||
uint8_t *tensor_arena = nullptr;
|
||||
//uint8_t tensor_arena[kTensorArenaSize];
|
||||
}
|
||||
|
||||
extern "C" void mnist_app() {
|
||||
tflite::MicroErrorReporter micro_error_reporter;
|
||||
error_reporter = µ_error_reporter;
|
||||
|
||||
model = tflite::GetModel(mnist_model);
|
||||
if (model->version() != TFLITE_SCHEMA_VERSION) {
|
||||
TF_LITE_REPORT_ERROR(error_reporter,
|
||||
"Model provided is schema version %d not equal "
|
||||
"to supported version %d.",
|
||||
model->version(), TFLITE_SCHEMA_VERSION);
|
||||
return;
|
||||
}
|
||||
|
||||
tensor_arena = (uint8_t *)malloc(kTensorArenaSize);
|
||||
if (tensor_arena == nullptr) {
|
||||
TF_LITE_REPORT_ERROR(error_reporter, "malloc for tensor_arena failed");
|
||||
return;
|
||||
}
|
||||
|
||||
tflite::AllOpsResolver resolver;
|
||||
tflite::MicroInterpreter static_interpreter(
|
||||
model, resolver, tensor_arena, kTensorArenaSize, error_reporter);
|
||||
interpreter = &static_interpreter;
|
||||
|
||||
// Allocate memory from the tensor_arena for the model's tensors.
|
||||
TfLiteStatus allocate_status = interpreter->AllocateTensors();
|
||||
if (allocate_status != kTfLiteOk) {
|
||||
TF_LITE_REPORT_ERROR(error_reporter, "AllocateTensors() failed");
|
||||
return;
|
||||
}
|
||||
|
||||
input = interpreter->input(0);
|
||||
output = interpreter->output(0);
|
||||
|
||||
printf("------- Input Digit -------\n");
|
||||
for (int i = 0; i < 28; i++) {
|
||||
for (int j = 0; j < 28; j++) {
|
||||
if (mnist_digit[i*28+j] > 0.3)
|
||||
printf("#");
|
||||
else
|
||||
printf(".");
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
for (int i = 0; i < 28*28; i++) {
|
||||
input->data.f[i] = mnist_digit[i];
|
||||
}
|
||||
|
||||
TfLiteStatus invoke_status = interpreter->Invoke();
|
||||
if (invoke_status != kTfLiteOk) {
|
||||
TF_LITE_REPORT_ERROR(error_reporter, "Invoke failed on x_val\n");
|
||||
return;
|
||||
}
|
||||
|
||||
// Read the predicted y value from the model's output tensor
|
||||
float max = 0.0;
|
||||
int index;
|
||||
for (int i = 0; i < 10; i++) {
|
||||
if(output->data.f[i]>max){
|
||||
max = output->data.f[i];
|
||||
index = i;
|
||||
}
|
||||
}
|
||||
printf("------- Output Result -------\n");
|
||||
printf("result is %d\n", index);
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
#ifdef __RT_THREAD_H__
|
||||
MSH_CMD_EXPORT(mnist_app, run mnist app);
|
||||
#endif
|
||||
}
|
||||
@@ -19,12 +19,13 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <xiuos.h>
|
||||
#include <transform.h>
|
||||
|
||||
void mnist_app(void);
|
||||
|
||||
int tfmnist(void) {
|
||||
mnist_app();
|
||||
}
|
||||
|
||||
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_FUNC)|SHELL_CMD_PARAM_NUM(0), tfmnist, tfmnist, run mnist demo of tflite);
|
||||
// #ifndef SEPARATE_COMPILE
|
||||
// SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_FUNC)|SHELL_CMD_PARAM_NUM(0)|SHELL_CMD_DISABLE_RETURN, tfmnist, tfmnist, run mnist demo of tflite);
|
||||
// #endif
|
||||
@@ -1,23 +1,3 @@
|
||||
/*
|
||||
* Copyright (c) 2020 AIIT XUOS Lab
|
||||
* XiOS is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
* See the Mulan PSL v2 for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file: model.h
|
||||
* @brief: store model weights in this file
|
||||
* @version: 1.0
|
||||
* @author: AIIT XUOS Lab
|
||||
* @date: 2021/4/30
|
||||
*
|
||||
*/
|
||||
unsigned char mnist_model[] = {
|
||||
0x1c, 0x00, 0x00, 0x00, 0x54, 0x46, 0x4c, 0x33, 0x14, 0x00, 0x20, 0x00,
|
||||
0x04, 0x00, 0x08, 0x00, 0x0c, 0x00, 0x10, 0x00, 0x14, 0x00, 0x00, 0x00,
|
||||
@@ -0,0 +1,36 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import tensorflow as tf
|
||||
|
||||
print("TensorFlow version %s" % (tf.__version__))
|
||||
|
||||
def show(image):
|
||||
for i in range(28):
|
||||
for j in range(28):
|
||||
if image[i][j] > 0.3:
|
||||
print('#', end = '')
|
||||
else:
|
||||
print('.', end = '')
|
||||
print()
|
||||
|
||||
digit_file_path = 'digit.h'
|
||||
digit_content = '''const float mnist_digit[] = {
|
||||
%s
|
||||
};
|
||||
const int mnist_label = %d;
|
||||
'''
|
||||
|
||||
if __name__ == '__main__':
|
||||
mnist = tf.keras.datasets.mnist
|
||||
(_, _), (test_images, test_labels) = mnist.load_data()
|
||||
index = 0
|
||||
shape = 28
|
||||
image = test_images[index].astype('float32')/255
|
||||
label = test_labels[index]
|
||||
print('label: %d' % label)
|
||||
#show(image)
|
||||
digit_data = (',\n ').join([ (', ').join([ '%.2f' % image[row][col] for col in range(shape)]) for row in range(shape)])
|
||||
digit_file = open(digit_file_path, 'w')
|
||||
digit_file.write(digit_content % (digit_data, label))
|
||||
digit_file.close()
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
#tflite_file_path = 'mnist-default-quan.tflite'
|
||||
tflite_file_path = 'mnist.tflite'
|
||||
model_file_path = 'model.h'
|
||||
|
||||
tflite_file = open(tflite_file_path, 'rb')
|
||||
tflite_data = tflite_file.read()
|
||||
tflite_file.close()
|
||||
tflite_array = [ '0x%02x' % byte for byte in tflite_data ]
|
||||
|
||||
model_content = '''unsigned char mnist_model[] = {
|
||||
%s
|
||||
};
|
||||
unsigned int mnist_model_len = %d;
|
||||
'''
|
||||
# 12 bytes in a line, the same with xxd
|
||||
bytes_of_line = 12
|
||||
model_data = (',\n ').join([ (', ').join(tflite_array[i:i+bytes_of_line]) for i in range(0, len(tflite_array), bytes_of_line) ])
|
||||
model_file = open(model_file_path, 'w')
|
||||
model_file.write(model_content % (model_data, len(tflite_array)))
|
||||
model_file.close()
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import tensorflow as tf
|
||||
|
||||
print("TensorFlow version %s" % (tf.__version__))
|
||||
|
||||
MODEL_NAME_H5 = 'mnist.h5'
|
||||
MODEL_NAME_TFLITE = 'mnist.tflite'
|
||||
DEFAULT_QUAN_MODEL_NAME_TFLITE = 'mnist-default-quan.tflite'
|
||||
FULL_QUAN_MODEL_NAME_TFLITE = 'mnist-full-quan.tflite'
|
||||
|
||||
|
||||
def show(image):
|
||||
for i in range(28):
|
||||
for j in range(28):
|
||||
if image[i][j][0] > 0.3:
|
||||
print('#', end = '')
|
||||
else:
|
||||
print(' ', end = '')
|
||||
print()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
mnist = tf.keras.datasets.mnist
|
||||
(_, _), (test_images, test_labels) = mnist.load_data()
|
||||
test_images = test_images.reshape(10000, 28, 28, 1)
|
||||
index = 0
|
||||
input_image = test_images[index].astype('float32')/255
|
||||
target_label = test_labels[index]
|
||||
|
||||
interpreter = tf.lite.Interpreter(model_path = DEFAULT_QUAN_MODEL_NAME_TFLITE)
|
||||
interpreter.allocate_tensors()
|
||||
input_details = interpreter.get_input_details()[0]
|
||||
output_details = interpreter.get_output_details()[0]
|
||||
interpreter.set_tensor(input_details['index'], [input_image])
|
||||
interpreter.invoke()
|
||||
output = interpreter.get_tensor(output_details['index'])[0]
|
||||
|
||||
show(input_image)
|
||||
print('target label: %d, predict label: %d' % (target_label, output.argmax()))
|
||||
18
applications/tflite_mnist/tools/mnist-train.py → APP_Framework/Applications/knowing_app/mnist/tools/mnist-train.py
Executable file → Normal file
18
applications/tflite_mnist/tools/mnist-train.py → APP_Framework/Applications/knowing_app/mnist/tools/mnist-train.py
Executable file → Normal file
@@ -1,22 +1,4 @@
|
||||
#!/usr/bin/env python3
|
||||
# ==========================================================================================
|
||||
# Copyright (c) 2020 AIIT XUOS Lab
|
||||
# XiOS is licensed under Mulan PSL v2.
|
||||
# You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
# You may obtain a copy of Mulan PSL v2 at:
|
||||
# http://license.coscl.org.cn/MulanPSL2
|
||||
# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
# EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
# MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
# See the Mulan PSL v2 for more details.
|
||||
|
||||
# @file: mnist-train.py
|
||||
# @brief: model training
|
||||
# @version: 1.0
|
||||
# @author: AIIT XUOS Lab
|
||||
# @date: 2021/4/30
|
||||
# ==========================================================================================
|
||||
|
||||
|
||||
import os
|
||||
import tensorflow as tf
|
||||
31
APP_Framework/Applications/main.c
Normal file
31
APP_Framework/Applications/main.c
Normal file
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright (c) 2020 AIIT XUOS Lab
|
||||
* XiUOS is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
* See the Mulan PSL v2 for more details.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
// #include <user_api.h>
|
||||
#include <transform.h>
|
||||
|
||||
extern int FrameworkInit();
|
||||
extern void ApplicationOtaTaskInit(void);
|
||||
int main(void)
|
||||
{
|
||||
printf("Hello, world! \n");
|
||||
FrameworkInit();
|
||||
#ifdef APPLICATION_OTA
|
||||
ApplicationOtaTaskInit();
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
// int cppmain(void);
|
||||
|
||||
|
||||
7
APP_Framework/Applications/ota/Kconfig
Executable file
7
APP_Framework/Applications/ota/Kconfig
Executable file
@@ -0,0 +1,7 @@
|
||||
menu "ota app "
|
||||
menuconfig APPLICATION_OTA
|
||||
bool "Using app bin ota"
|
||||
default n
|
||||
|
||||
|
||||
endmenu
|
||||
3
APP_Framework/Applications/ota/Makefile
Normal file
3
APP_Framework/Applications/ota/Makefile
Normal file
@@ -0,0 +1,3 @@
|
||||
SRC_FILES := ota.c
|
||||
|
||||
include $(KERNEL_ROOT)/compiler.mk
|
||||
19
APP_Framework/Applications/ota/README.md
Normal file
19
APP_Framework/Applications/ota/README.md
Normal file
@@ -0,0 +1,19 @@
|
||||
# OTA README
|
||||
|
||||
xiuos当前的ota功能允许应用bin文件可以通过4G实现远程的bin文件更新(限制:1、bin文件存放在设备SD卡并且应用从SD卡启动;2、暂且支持4G实现;3、暂时只支持aiit终端;4、只支持xiuos内核)。
|
||||
|
||||
## 文件说明
|
||||
|
||||
| 名称 | 说明 |
|
||||
| -- | -- |
|
||||
| ota.c| xiuos设备OTA代码 |
|
||||
| ota_server.c | pc服务端的实例代码供参考 |
|
||||
|
||||
|
||||
## 使用说明
|
||||
xiuos的应用bin文件更新依赖上层的adapter框架,因此需要在menuconfig同时配置以下选项:
|
||||
1、ota开关APPLICATION_OTA打开;
|
||||
2、adapter的4G功能开关;
|
||||
3、拆分的应用启动SEPARATE_COMPILE开关从SD卡启动的配置开关APP_STARTUP_FROM_SDCARD。
|
||||
|
||||
|
||||
411
APP_Framework/Applications/ota/ota.c
Normal file
411
APP_Framework/Applications/ota/ota.c
Normal file
@@ -0,0 +1,411 @@
|
||||
|
||||
/*
|
||||
* Copyright (c) 2020 AIIT XUOS Lab
|
||||
* XiUOS is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
* See the Mulan PSL v2 for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file: ota.c
|
||||
* @brief: a application ota task of system
|
||||
* @version: 1.0
|
||||
* @author: AIIT XUOS Lab
|
||||
* @date: 2021/11/3
|
||||
*
|
||||
*/
|
||||
#include <transform.h>
|
||||
#include <adapter.h>
|
||||
|
||||
extern int main(void);
|
||||
|
||||
struct ota_header_t
|
||||
{
|
||||
int16 frame_flag; ///< frame start flag 2 Bytes
|
||||
uint8 dev_type; ///< device type
|
||||
uint8 burn_mode; ///< data burn way
|
||||
uint32 total_len; ///< send data total length caculated from each frame_len
|
||||
uint32 dev_hid; ///< device hardware version
|
||||
uint32 dev_sid; ///< device software version
|
||||
char resv[8]; ///< reserve
|
||||
};
|
||||
|
||||
struct ota_frame_t
|
||||
{
|
||||
uint32 frame_id; ///< Current frame id
|
||||
uint32 frame_len; ///< Current frame data length
|
||||
char frame_data[64]; ///< Current frame data,max length 64
|
||||
uint32 crc; ///< Current frame data crc
|
||||
};
|
||||
|
||||
struct ota_data
|
||||
{
|
||||
struct ota_header_t header;
|
||||
struct ota_frame_t frame;
|
||||
char end[4];
|
||||
};
|
||||
|
||||
pthread_t ota_task;
|
||||
pthread_t restart_main;
|
||||
|
||||
/**
|
||||
* @description: CRC16 check
|
||||
* @param data data buffer
|
||||
* @param length data length
|
||||
* @return check code
|
||||
*/
|
||||
uint32_t OtaCrc16(uint8_t * data, uint32_t length)
|
||||
{
|
||||
int j;
|
||||
unsigned int reg_crc=0xFFFF;
|
||||
printf("crc data length[%d] Bytes,",length);
|
||||
|
||||
while (length--) {
|
||||
reg_crc ^= *data++;
|
||||
for (j=0;j<8;j++) {
|
||||
if(reg_crc & 0x01)
|
||||
reg_crc=reg_crc >>1 ^ 0xA001;
|
||||
else
|
||||
reg_crc=reg_crc >>1;
|
||||
}
|
||||
}
|
||||
printf(" crc = [0x%x]\n",reg_crc);
|
||||
return reg_crc;
|
||||
}
|
||||
|
||||
uint32_t FileCrc16(uint8_t * data, uint32_t length, unsigned int last_crc)
|
||||
{
|
||||
int j;
|
||||
//printf("crc data length[%d] Bytes,",length);
|
||||
|
||||
while (length--) {
|
||||
last_crc ^= *data++;
|
||||
for (j=0;j<8;j++) {
|
||||
if(last_crc & 0x01)
|
||||
last_crc = last_crc >>1 ^ 0xA001;
|
||||
else
|
||||
last_crc = last_crc >>1;
|
||||
}
|
||||
}
|
||||
|
||||
//printf(" crc = [0x%x]\n",last_crc);
|
||||
|
||||
return last_crc;
|
||||
}
|
||||
|
||||
|
||||
static int SaveAppBin(int fd, char* buf, int len)
|
||||
{
|
||||
int ret = 0;
|
||||
int fd_t = 0;
|
||||
fd_t = open( BOARD_APP_NAME, O_RDWR | O_APPEND);
|
||||
ret = write(fd, buf, len);
|
||||
if(ret < 0){
|
||||
printf("fd = %d write buf len[%d] failed.ret = %d\n",fd_t,len,ret);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("fd[%d] write buf length[%d] done.\n",fd_t,ret);
|
||||
}
|
||||
|
||||
close(fd_t);
|
||||
}
|
||||
|
||||
static int CrcFileCheck(uint32 crc_check, unsigned long total_len)
|
||||
{
|
||||
int ret = 0;
|
||||
int fd = 0;
|
||||
int len = 0;
|
||||
char *buf = NULL;
|
||||
unsigned int last_crc = 0xffff;
|
||||
unsigned long already_crc_length = 0;
|
||||
|
||||
fd = open( BOARD_APP_NAME, O_RDONLY );
|
||||
if(fd < 0){
|
||||
printf("open %s bin failed.\n",BOARD_APP_NAME);
|
||||
return -1;
|
||||
}
|
||||
|
||||
buf = PrivMalloc(128);
|
||||
if(NULL == buf)
|
||||
{
|
||||
printf("malloc failed.\n");
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* crc check every 1024 Bytes until crc all the total file */
|
||||
while(already_crc_length != total_len)
|
||||
{
|
||||
memset(buf , 0 , 128);
|
||||
len = read(fd, buf, 128);
|
||||
if(len < 0)
|
||||
{
|
||||
printf("file read failed.ret = %d\n",len);
|
||||
ret = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
last_crc = FileCrc16(buf, len, last_crc);
|
||||
already_crc_length += len;
|
||||
printf("read len[%d] Bytes,already_crc_length[%d]\n",len,already_crc_length);
|
||||
}
|
||||
|
||||
|
||||
if (last_crc != crc_check)
|
||||
{
|
||||
printf("file crc error!!! last crc[%x] != check[%x]\n",last_crc,crc_check);
|
||||
ret =-1;
|
||||
}
|
||||
|
||||
PrivFree(buf);
|
||||
close(fd);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void RestartApplication(void)
|
||||
{
|
||||
pthread_attr_t attr;
|
||||
attr.schedparam.sched_priority = 10;
|
||||
attr.stacksize = 2048;
|
||||
|
||||
while(1)
|
||||
{
|
||||
unsigned long pid = PrivUserTaskSearch();
|
||||
if ((pid > 0) && (pid != pthread_self()))
|
||||
{
|
||||
printf("kill usertask pid[%d]\n",pid);
|
||||
PrivTaskDelete(pid, 0);
|
||||
PrivTaskDelay(1000); /* NOTE:this delay will make a schedule and recycle all user task */
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
printf("restart main.\n");
|
||||
PrivTaskCreate(&restart_main, &attr, (void *)main, NULL);
|
||||
}
|
||||
static int OtaDataRecv(struct Adapter* adapter)
|
||||
{
|
||||
struct ota_data recv_msg;
|
||||
char reply[16] = {0};
|
||||
int ret = 0;
|
||||
int try_times = 10;
|
||||
int fd = 0;
|
||||
int frame_cnt = 0;
|
||||
|
||||
fd = open( BOARD_APP_NAME, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
|
||||
if(fd < 0)
|
||||
{
|
||||
printf("open %s failed\n",BOARD_APP_NAME);
|
||||
return -1;
|
||||
}
|
||||
close(fd);
|
||||
|
||||
while(1) {
|
||||
memset(&recv_msg, 0, sizeof(struct ota_data));
|
||||
printf("recv msg...\n");
|
||||
ret = AdapterDeviceRecv(adapter, &recv_msg, sizeof(struct ota_data));
|
||||
if(ret >= 0 && recv_msg.header.frame_flag == 0x5A5A)
|
||||
{
|
||||
if(0 == strncmp("aiit_ota_end",recv_msg.frame.frame_data, strlen("aiit_ota_end")))
|
||||
{
|
||||
printf("total [%d]frames [%d]Bytes crc[%x],receive successful,\n",frame_cnt,recv_msg.header.total_len,recv_msg.frame.crc);
|
||||
if(0 != CrcFileCheck(recv_msg.frame.crc, recv_msg.header.total_len))
|
||||
{
|
||||
printf("crc check %s bin failed.please try again.\n", BOARD_APP_NAME);
|
||||
ret = -1;
|
||||
break;
|
||||
}
|
||||
PrivTaskDelay(500);
|
||||
printf("tolal file crc done.send ok\n");
|
||||
memset(reply, 0, 16);
|
||||
memcpy(reply, "ok", strlen("ok"));
|
||||
|
||||
AdapterDeviceSend(adapter, reply, strlen(reply));
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
frame_cnt = recv_msg.frame.frame_id;
|
||||
|
||||
if(0 == strncmp("wait_ok_timeout",recv_msg.frame.frame_data, strlen("wait_ok_timeout")))
|
||||
{
|
||||
printf("go to send ok again.\n");
|
||||
goto send_ok_again;
|
||||
|
||||
}
|
||||
|
||||
if (recv_msg.frame.crc == OtaCrc16(recv_msg.frame.frame_data,recv_msg.frame.frame_len))
|
||||
{
|
||||
printf("save current [%d] frame,length[%d] Bytes.\n",frame_cnt,recv_msg.frame.frame_len);
|
||||
for(int i = 0; i < recv_msg.frame.frame_len;i++ ){
|
||||
printf(" %x ",*((char *)&recv_msg.frame.frame_data + i));
|
||||
}
|
||||
printf("\n");
|
||||
SaveAppBin(fd, recv_msg.frame.frame_data, recv_msg.frame.frame_len);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("current [%d] frame crc check failed,try again!\n",frame_cnt);
|
||||
goto try_again;
|
||||
}
|
||||
|
||||
send_ok_again:
|
||||
memset(reply, 0, 16);
|
||||
memcpy(reply, "ok", strlen("ok"));
|
||||
// PrivTaskDelay(100);
|
||||
|
||||
ret = AdapterDeviceSend(adapter, reply, strlen(reply));
|
||||
if(ret < 0){
|
||||
printf("send ok failed.\n");
|
||||
goto send_ok_again;
|
||||
}
|
||||
printf("send reply[%s] done.\n",reply);
|
||||
try_times = 10;
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
try_again:
|
||||
if(try_times == 0)
|
||||
{
|
||||
printf("oops!!! current [%d] frame try 10 times failed,break out!\n",frame_cnt);
|
||||
ret = -1;
|
||||
break;
|
||||
}
|
||||
memset(reply, 0, 16);
|
||||
memcpy(reply, "retry", strlen("retry"));
|
||||
printf("[%d] frame receive failed. retry\n",frame_cnt);
|
||||
AdapterDeviceSend(adapter, reply, strlen(reply));
|
||||
try_times--;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
close(fd);
|
||||
|
||||
if(0 == ret) {
|
||||
printf("ota file done,start application.\n");
|
||||
RestartApplication();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void *OtaKTaskEntry(void *parameter)
|
||||
{
|
||||
struct ota_data recv_msg;
|
||||
char reply[16] = {0};
|
||||
int baud_rate = BAUD_RATE_115200;
|
||||
int len = 0;
|
||||
int ret = 0;
|
||||
|
||||
struct Adapter* adapter = AdapterDeviceFindByName("4G");
|
||||
uint8 server_addr[64] = "115.238.53.61";
|
||||
uint8 server_port[64] = "9898";
|
||||
|
||||
adapter->socket.socket_id = 0;
|
||||
|
||||
AdapterDeviceOpen(adapter);
|
||||
AdapterDeviceControl(adapter, OPE_INT, &baud_rate);
|
||||
AdapterDeviceConnect(adapter, CLIENT, server_addr, server_port, IPV4);
|
||||
|
||||
/* using nbiot as connection way*/
|
||||
|
||||
// struct Adapter* adapter = AdapterDeviceFindByName("nbiot");
|
||||
|
||||
// while(1)
|
||||
// {
|
||||
// int connect_times = 5;
|
||||
// ret = AdapterDeviceOpen(adapter);
|
||||
// if(ret < 0)
|
||||
// {
|
||||
// printf("open adapter failed\n");
|
||||
// continue;
|
||||
// }
|
||||
|
||||
// connect_again:
|
||||
// connect_times--;
|
||||
// ret = AdapterDeviceConnect(adapter, 1, "115.238.53.61","9898",1);
|
||||
// if(ret < 0)
|
||||
// {
|
||||
// if(connect_times > 0){
|
||||
// goto connect_again;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// AdapterDeviceClose(adapter);
|
||||
// continue;
|
||||
// }
|
||||
// }
|
||||
// break;
|
||||
// }
|
||||
PrivTaskDelay(5000);
|
||||
while(1)
|
||||
{
|
||||
memset(&recv_msg, 0, sizeof(struct ota_data));
|
||||
/* step1: Confirm the start signal of transmission*/
|
||||
printf("waiting for start msg...\n");
|
||||
ret = AdapterDeviceRecv(adapter, &recv_msg, sizeof(struct ota_data));
|
||||
for(int i = 0; i < sizeof(struct ota_data);i++ ){
|
||||
printf(" %x ",*((char *)&recv_msg + i));
|
||||
}
|
||||
printf("\n");
|
||||
if(ret >= 0 && recv_msg.header.frame_flag == 0x5A5A)
|
||||
{
|
||||
if (0 == strncmp("aiit_ota_start",recv_msg.frame.frame_data, strlen("aiit_ota_start")))
|
||||
{
|
||||
memset(reply, 0, 16);
|
||||
memcpy(reply, "ready", strlen("ready"));
|
||||
// PrivTaskDelay(3000);
|
||||
printf("receive start signal,send [ready] signal to server\n");
|
||||
send_ready_again:
|
||||
ret = AdapterDeviceSend(adapter, reply, strlen(reply));
|
||||
if(ret < 0)
|
||||
{
|
||||
goto send_ready_again;
|
||||
}
|
||||
PrivTaskDelay(3000);
|
||||
printf("start receive ota file.\n");
|
||||
/* step2: start receive source bin file of application*/
|
||||
ret = OtaDataRecv(adapter);
|
||||
if (0 != ret)
|
||||
{
|
||||
memset(reply, 0, 16);
|
||||
memcpy(reply, "ota_restart", strlen("ota_restart"));
|
||||
AdapterDeviceSend(adapter, reply, strlen(reply));
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
memset(reply, 0, 16);
|
||||
memcpy(reply, "notready", strlen("notready"));
|
||||
printf("ota status:not ready\n");
|
||||
ret = AdapterDeviceSend(adapter, reply, strlen(reply));
|
||||
}
|
||||
PrivTaskDelay(3000); /* check ota signal every 5s */
|
||||
}
|
||||
AdapterDeviceClose(adapter);
|
||||
|
||||
}
|
||||
|
||||
void ApplicationOtaTaskInit(void)
|
||||
{
|
||||
pthread_attr_t attr;
|
||||
attr.schedparam.sched_priority = 20;
|
||||
attr.stacksize = 4096;
|
||||
|
||||
PrivTaskCreate(&ota_task, &attr, OtaKTaskEntry, NULL);
|
||||
|
||||
}
|
||||
364
APP_Framework/Applications/ota/ota_server.c
Normal file
364
APP_Framework/Applications/ota/ota_server.c
Normal file
@@ -0,0 +1,364 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <sys/socket.h>
|
||||
#include <pthread.h>
|
||||
#include <time.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <errno.h>
|
||||
#include <sys/time.h>
|
||||
#include <assert.h>
|
||||
#include <netdb.h>
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
typedef int BOOL;
|
||||
#define true 1
|
||||
#define false 0
|
||||
|
||||
int serverfd;//服务器socket
|
||||
int clientfd[100000];//客户端的socketfd,100个元素,clientfd[0]~clientfd[99]
|
||||
int size = 99999;//用来控制进入聊天室的人数为50以内
|
||||
int PORT = 9898;//端口号
|
||||
typedef struct sockaddr meng;
|
||||
|
||||
struct ota_header_t
|
||||
{
|
||||
int16_t frame_flag; ///< frame start flag 2 Bytes
|
||||
uint8_t dev_type; ///< device type
|
||||
uint8_t burn_mode; ///< data burn way
|
||||
uint32_t total_len; ///< send data total length caculated from each frame_len
|
||||
uint32_t dev_hid; ///< device hardware version
|
||||
uint32_t dev_sid; ///< device software version
|
||||
char resv[8]; ///< reserve
|
||||
};
|
||||
|
||||
struct ota_frame_t
|
||||
{
|
||||
uint32_t frame_id; ///< Current frame id
|
||||
uint32_t frame_len; ///< Current frame data length
|
||||
char frame_data[64]; ///< Current frame data,max length 224
|
||||
uint32_t crc; ///< Current frame data crc
|
||||
};
|
||||
|
||||
struct ota_data
|
||||
{
|
||||
struct ota_header_t header;
|
||||
struct ota_frame_t frame;
|
||||
char end[4];
|
||||
};
|
||||
|
||||
pthread_t ota_ktask;
|
||||
|
||||
/**
|
||||
* @description: CRC16 check
|
||||
* @param data data buffer
|
||||
* @param length data length
|
||||
* @return check code
|
||||
*/
|
||||
uint32_t OtaCrc16(uint8_t * data, uint32_t length)
|
||||
{
|
||||
int j;
|
||||
unsigned int reg_crc=0xFFFF;
|
||||
|
||||
printf("crc data length[%d] Bytes,",length);
|
||||
|
||||
while (length--) {
|
||||
reg_crc ^= *data++;
|
||||
for (j=0;j<8;j++) {
|
||||
if(reg_crc & 0x01)
|
||||
reg_crc=reg_crc >>1 ^ 0xA001;
|
||||
else
|
||||
reg_crc=reg_crc >>1;
|
||||
}
|
||||
}
|
||||
printf(" crc = [0x%x]\n",reg_crc);
|
||||
return reg_crc;
|
||||
}
|
||||
|
||||
void init(void)
|
||||
{
|
||||
serverfd = socket(PF_INET,SOCK_STREAM,0);
|
||||
|
||||
if (serverfd == -1)
|
||||
{
|
||||
perror("创建socket失败");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
//为套接字设置ip协议 设置端口号 并自动获取本机ip转化为网络ip
|
||||
|
||||
struct sockaddr_in addr;//存储套接字的信息
|
||||
addr.sin_family = AF_INET;//地址族
|
||||
addr.sin_port = htons(PORT);//设置server端端口号,你可以随便设置,当sin_port = 0时,系统随机选择一个未被使用的端口号
|
||||
addr.sin_addr.s_addr = htons(INADDR_ANY);//当sin_addr = INADDR_ANY时,表示从本机的任一网卡接收数据
|
||||
|
||||
//绑定套接字
|
||||
// int on = 1;
|
||||
struct timeval timeout;
|
||||
timeout.tv_sec = 5;
|
||||
timeout.tv_usec = 0;
|
||||
if(setsockopt(serverfd, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(struct timeval)) < 0)
|
||||
{
|
||||
perror("端口设置失败");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
if (bind(serverfd,(meng*)&addr,sizeof(addr)) == -1)
|
||||
{
|
||||
perror("绑定失败");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
if (listen(serverfd,100) == -1)
|
||||
{//监听最大连接数
|
||||
perror("设置监听失败");
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
int OtaFileSend(int fd)
|
||||
{
|
||||
unsigned char buf[32] = { 0 };
|
||||
struct ota_data data;
|
||||
FILE *file_fd;
|
||||
char ch;
|
||||
int length = 0;
|
||||
int try_times = 10;
|
||||
int recv_end_times = 3;
|
||||
int ret = 0;
|
||||
int frame_cnt = 0;
|
||||
int file_length = 0;
|
||||
char * file_buf = NULL;
|
||||
|
||||
file_fd = fopen("/home/aep04/wwg/XiUOS_aiit-arm32-board_app.bin", "r");
|
||||
if (NULL == file_fd){
|
||||
printf("open file failed.\n");
|
||||
return -1;
|
||||
}
|
||||
fseek(file_fd, 0, SEEK_SET);
|
||||
printf("start send file.\n");
|
||||
while(!feof(file_fd))
|
||||
{
|
||||
memset(&data, 0, sizeof(data));
|
||||
|
||||
data.header.frame_flag = 0x5A5A;
|
||||
length = fread( data.frame.frame_data, 1, 64, file_fd );
|
||||
if(length > 0)
|
||||
{
|
||||
printf("read %d Bytes\n",length);
|
||||
data.frame.frame_id = frame_cnt;
|
||||
data.frame.frame_len = length;
|
||||
data.frame.crc = OtaCrc16(data.frame.frame_data, length);
|
||||
file_length += length;
|
||||
}
|
||||
|
||||
send_again:
|
||||
usleep(50000);
|
||||
printf("ota send current[%d] frame.\n",frame_cnt);
|
||||
length = send(fd, &data, sizeof(data), MSG_NOSIGNAL);
|
||||
if(length < 0){
|
||||
printf("send [%d] frame faile.go to send again\n",frame_cnt);
|
||||
goto send_again;
|
||||
}
|
||||
|
||||
recv_again:
|
||||
memset(buf, 0, 32);
|
||||
length = recv(fd, buf, sizeof(buf), 0);
|
||||
if(length < 0 ){
|
||||
printf("[%d] frame waiting for ok timeout,receive again.\n",frame_cnt);
|
||||
goto recv_again;
|
||||
}
|
||||
|
||||
printf("receive buf[%s] length = %d\n",buf, length);
|
||||
if(0 == strncmp(buf, "ok", length))
|
||||
{
|
||||
try_times = 10;
|
||||
printf("[%d]frame data send done.\n",frame_cnt);
|
||||
frame_cnt++;
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(try_times > 0)
|
||||
{
|
||||
try_times--;
|
||||
goto send_again;
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("send frame[%d] 10 times failed.\n",frame_cnt);
|
||||
ret = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* finally,crc check total bin file.*/
|
||||
if (ret == 0)
|
||||
{
|
||||
sleep(1);
|
||||
printf("total send file length[%d] Bytes [%d] frames.\n",file_length,frame_cnt);
|
||||
printf("now crc check total bin file.\n");
|
||||
file_buf = malloc(file_length);
|
||||
memset(file_buf, 0, file_length);
|
||||
memset(&data, 0, sizeof(data));
|
||||
|
||||
data.header.frame_flag = 0x5A5A;
|
||||
|
||||
file_fd = fopen("/home/aep04/wwg/XiUOS_aiit-arm32-board_app.bin", "r");
|
||||
if (NULL == file_fd){
|
||||
printf("open file failed.\n");
|
||||
return -1;
|
||||
}
|
||||
fseek(file_fd, 0, SEEK_SET);
|
||||
length = fread(file_buf,1, file_length, file_fd);
|
||||
printf("read file length = %d\n",length);
|
||||
if(length > 0) {
|
||||
data.frame.frame_id = frame_cnt;
|
||||
data.header.total_len = file_length;
|
||||
data.frame.frame_len = strlen("aiit_ota_end");
|
||||
data.frame.crc = OtaCrc16(file_buf, length);
|
||||
memcpy(data.frame.frame_data,"aiit_ota_end",strlen("aiit_ota_end"));
|
||||
}
|
||||
|
||||
send_end_signal:
|
||||
printf("send aiit_ota_end signal.\n");
|
||||
length = send(fd, &data, sizeof(data), MSG_NOSIGNAL);
|
||||
if(length < 0){
|
||||
printf("send end signal faile,send end signal again\n");
|
||||
goto send_end_signal;
|
||||
}
|
||||
|
||||
recv_end_signal:
|
||||
memset(buf, 0, 32);
|
||||
length = recv(fd, buf, sizeof(buf), 0);
|
||||
if(length < 0 )
|
||||
{
|
||||
recv_end_times--;
|
||||
printf("end signal waiting for ok timeout,receive again.\n");
|
||||
if(recv_end_times > 0)
|
||||
{
|
||||
goto recv_end_signal;
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = -1;
|
||||
}
|
||||
}
|
||||
|
||||
if(0 != strncmp(buf, "ok", length))
|
||||
{
|
||||
printf("error end !!!\n");
|
||||
ret = -1;
|
||||
}
|
||||
|
||||
free(file_buf);
|
||||
}
|
||||
|
||||
fclose(file_fd);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void* server_thread(void* p)
|
||||
{
|
||||
int fd = *(int*)p;
|
||||
unsigned char buf[32] = { 0 };
|
||||
struct ota_data data;
|
||||
int ret = 0;
|
||||
int length = 0;
|
||||
|
||||
printf("pthread = %d\n",fd);
|
||||
sleep(8);
|
||||
while(1)
|
||||
{
|
||||
memset(&data, 0x0 , sizeof(struct ota_data));
|
||||
data.header.frame_flag = 0x5A5A;
|
||||
memcpy(data.frame.frame_data,"aiit_ota_start",strlen("aiit_ota_start"));
|
||||
data.frame.frame_len = strlen("aiit_ota_start");
|
||||
|
||||
printf("send start signal.\n");
|
||||
ret = send(fd, &data, sizeof(data), MSG_NOSIGNAL);
|
||||
if (ret > 0){
|
||||
printf("send %s[%d] Bytes\n",data.frame.frame_data,ret);
|
||||
}
|
||||
// sleep(1);
|
||||
memset(buf, 0, 32);
|
||||
length = recv(fd, buf, sizeof(buf), 0);
|
||||
if (length <= 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("recv buf %s length %d\n",buf,length);
|
||||
if(0 == strncmp(buf, "ready", length))
|
||||
{
|
||||
ret = OtaFileSend(fd);
|
||||
if (ret == 0) {
|
||||
printf("ota file send successful.\n");
|
||||
break;
|
||||
} else { /* ota failed then restart the ota process */
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
printf("exit fd = %d\n",fd);
|
||||
close(fd);
|
||||
pthread_exit(0);
|
||||
}
|
||||
|
||||
void server(void)
|
||||
{
|
||||
printf("ota Server startup\n");
|
||||
while(1)
|
||||
{
|
||||
struct sockaddr_in fromaddr;
|
||||
socklen_t len = sizeof(fromaddr);
|
||||
int fd = accept(serverfd,(meng*)&fromaddr,&len);
|
||||
|
||||
//调用accept进入堵塞状态,等待客户端的连接
|
||||
|
||||
if (fd == -1)
|
||||
{
|
||||
// printf("The client connection is wrong...\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
int i = 0;
|
||||
for (i = 0;i < size;i++)
|
||||
{
|
||||
if (clientfd[i] == 0)
|
||||
{
|
||||
//记录客户端的socket
|
||||
clientfd[i] = fd;
|
||||
|
||||
//有客户端连接之后,启动线程给此客户服务
|
||||
pthread_t tid;
|
||||
pthread_create(&tid,0,server_thread,&fd);
|
||||
break;
|
||||
}
|
||||
|
||||
if (size == i)
|
||||
{
|
||||
//发送给客户端说聊天室满了
|
||||
char* str = "Devices full";
|
||||
printf("%s", str);
|
||||
send(fd,str,strlen(str),0);
|
||||
close(fd);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
init();
|
||||
server();
|
||||
}
|
||||
|
||||
128
APP_Framework/Applications/sensor_app/Kconfig
Executable file
128
APP_Framework/Applications/sensor_app/Kconfig
Executable file
@@ -0,0 +1,128 @@
|
||||
menu "sensor app"
|
||||
|
||||
menuconfig APPLICATION_SENSOR
|
||||
bool "Using sensor apps"
|
||||
default n
|
||||
|
||||
if APPLICATION_SENSOR
|
||||
menuconfig APPLICATION_SENSOR_HCHO
|
||||
bool "Using sensor HCHO apps"
|
||||
default n
|
||||
|
||||
if APPLICATION_SENSOR_HCHO
|
||||
config APPLICATION_SENSOR_HCHO_TB600B_WQ_HCHO1OS
|
||||
bool "Using sensor TB600B_WQ_HCHO1OS apps"
|
||||
default n
|
||||
endif
|
||||
|
||||
menuconfig APPLICATION_SENSOR_TVOC
|
||||
bool "Using sensor TVOC apps"
|
||||
default n
|
||||
|
||||
if APPLICATION_SENSOR_TVOC
|
||||
config APPLICATION_SENSOR_TVOC_TB600B_TVOC10
|
||||
bool "Using sensor TB600B_TVOC10 apps"
|
||||
default n
|
||||
endif
|
||||
|
||||
menuconfig APPLICATION_SENSOR_IAQ
|
||||
bool "Using sensor IAQ apps"
|
||||
default n
|
||||
|
||||
if APPLICATION_SENSOR_IAQ
|
||||
config APPLICATION_SENSOR_IAQ_TB600B_IAQ10
|
||||
bool "Using sensor TB600B_IAQ10 apps"
|
||||
default n
|
||||
endif
|
||||
|
||||
menuconfig APPLICATION_SENSOR_CH4
|
||||
bool "Using sensor CH4 apps"
|
||||
default n
|
||||
|
||||
if APPLICATION_SENSOR_CH4
|
||||
config APPLICATION_SENSOR_CH4_AS830
|
||||
bool "Using sensor AS830 apps"
|
||||
default n
|
||||
endif
|
||||
|
||||
menuconfig APPLICATION_SENSOR_CO2
|
||||
bool "Using sensor CO2 apps"
|
||||
default n
|
||||
|
||||
if APPLICATION_SENSOR_CO2
|
||||
config APPLICATION_SENSOR_CO2_ZG09
|
||||
bool "Using sensor ZG09 apps"
|
||||
default n
|
||||
endif
|
||||
|
||||
menuconfig APPLICATION_SENSOR_PM1_0
|
||||
bool "Using sensor PM1.0 apps"
|
||||
default n
|
||||
|
||||
if APPLICATION_SENSOR_PM1_0
|
||||
config APPLICATION_SENSOR_PM1_0_PS5308
|
||||
bool "Using sensor PS5308 apps"
|
||||
default n
|
||||
endif
|
||||
|
||||
menuconfig APPLICATION_SENSOR_PM2_5
|
||||
bool "Using sensor PM2.5 apps"
|
||||
default n
|
||||
|
||||
if APPLICATION_SENSOR_PM2_5
|
||||
config APPLICATION_SENSOR_PM2_5_PS5308
|
||||
bool "Using sensor PS5308 apps"
|
||||
default n
|
||||
endif
|
||||
|
||||
menuconfig APPLICATION_SENSOR_PM10
|
||||
bool "Using sensor PM10 apps"
|
||||
default n
|
||||
|
||||
if APPLICATION_SENSOR_PM10
|
||||
config APPLICATION_SENSOR_PM10_PS5308
|
||||
bool "Using sensor PS5308 apps"
|
||||
default n
|
||||
endif
|
||||
|
||||
menuconfig APPLICATION_SENSOR_VOICE
|
||||
bool "Using sensor voice apps"
|
||||
default n
|
||||
|
||||
if APPLICATION_SENSOR_VOICE
|
||||
config APPLICATION_SENSOR_VOICE_D124
|
||||
bool "Using sensor D124 apps"
|
||||
default n
|
||||
endif
|
||||
|
||||
menuconfig APPLICATION_SENSOR_TEMPERATURE
|
||||
bool "Using sensor temperature apps"
|
||||
default n
|
||||
|
||||
if APPLICATION_SENSOR_TEMPERATURE
|
||||
config APPLICATION_SENSOR_TEMPERATURE_HS300X
|
||||
bool "Using sensor HS300x apps"
|
||||
default n
|
||||
|
||||
if ADD_NUTTX_FETURES
|
||||
endif
|
||||
|
||||
endif
|
||||
|
||||
menuconfig APPLICATION_SENSOR_HUMIDITY
|
||||
bool "Using sensor humidity apps"
|
||||
default n
|
||||
|
||||
if APPLICATION_SENSOR_HUMIDITY
|
||||
config APPLICATION_SENSOR_HUMIDITY_HS300X
|
||||
bool "Using sensor HS300x apps"
|
||||
default n
|
||||
|
||||
if ADD_NUTTX_FETURES
|
||||
endif
|
||||
|
||||
endif
|
||||
|
||||
endif
|
||||
|
||||
endmenu
|
||||
6
APP_Framework/Applications/sensor_app/Make.defs
Normal file
6
APP_Framework/Applications/sensor_app/Make.defs
Normal file
@@ -0,0 +1,6 @@
|
||||
############################################################################
|
||||
# APP_Framework/Applications/sensor_app/Make.defs
|
||||
############################################################################
|
||||
ifneq ($(CONFIG_APPLICATION_SENSOR),)
|
||||
CONFIGURED_APPS += $(APPDIR)/../../../APP_Framework/Applications/sensor_app
|
||||
endif
|
||||
103
APP_Framework/Applications/sensor_app/Makefile
Normal file
103
APP_Framework/Applications/sensor_app/Makefile
Normal file
@@ -0,0 +1,103 @@
|
||||
include $(KERNEL_ROOT)/.config
|
||||
|
||||
ifeq ($(CONFIG_ADD_NUTTX_FETURES),y)
|
||||
include $(APPDIR)/Make.defs
|
||||
|
||||
ifeq ($(CONFIG_APPLICATION_SENSOR_HCHO_TB600B_WQ_HCHO1OS), y)
|
||||
CSRCS += hcho_tb600b_wq_hcho1os.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_APPLICATION_SENSOR_TVOC_TB600B_TVOC10), y)
|
||||
CSRCS += tvoc_tb600b_tvoc10.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_APPLICATION_SENSOR_IAQ_TB600B_IAQ10), y)
|
||||
CSRCS += iaq_tb600b_iaq10.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_APPLICATION_SENSOR_CH4_AS830), y)
|
||||
CSRCS += ch4_as830.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_APPLICATION_SENSOR_CO2_ZG09), y)
|
||||
CSRCS += co2_zg09.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_APPLICATION_SENSOR_PM1_0_PS5308), y)
|
||||
CSRCS += pm1_0_ps5308.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_APPLICATION_SENSOR_PM2_5_PS5308), y)
|
||||
CSRCS += pm2_5_ps5308.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_APPLICATION_SENSOR_PM10_PS5308), y)
|
||||
CSRCS += pm10_0_ps5308.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_APPLICATION_SENSOR_VOICE_D124), y)
|
||||
CSRCS += voice_d124.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_APPLICATION_SENSOR_HUMIDITY_HS300X), y)
|
||||
CSRCS += humidity_hs300x.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_APPLICATION_SENSOR_TEMPERATURE_HS300X), y)
|
||||
CSRCS += temperature_hs300x.c
|
||||
endif
|
||||
|
||||
include $(APPDIR)/Application.mk
|
||||
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_ADD_XIUOS_FETURES),y)
|
||||
SRC_FILES :=
|
||||
|
||||
ifeq ($(CONFIG_APPLICATION_SENSOR_HCHO_TB600B_WQ_HCHO1OS), y)
|
||||
SRC_FILES += hcho_tb600b_wq_hcho1os.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_APPLICATION_SENSOR_TVOC_TB600B_TVOC10), y)
|
||||
SRC_FILES += tvoc_tb600b_tvoc10.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_APPLICATION_SENSOR_IAQ_TB600B_IAQ10), y)
|
||||
SRC_FILES += iaq_tb600b_iaq10.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_APPLICATION_SENSOR_CH4_AS830), y)
|
||||
SRC_FILES += ch4_as830.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_APPLICATION_SENSOR_CO2_ZG09), y)
|
||||
SRC_FILES += co2_zg09.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_APPLICATION_SENSOR_PM1_0_PS5308), y)
|
||||
SRC_FILES += pm1_0_ps5308.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_APPLICATION_SENSOR_PM2_5_PS5308), y)
|
||||
SRC_FILES += pm2_5_ps5308.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_APPLICATION_SENSOR_PM10_PS5308), y)
|
||||
SRC_FILES += pm10_0_ps5308.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_APPLICATION_SENSOR_VOICE_D124), y)
|
||||
SRC_FILES += voice_d124.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_APPLICATION_SENSOR_HUMIDITY_HS300X), y)
|
||||
SRC_FILES += humidity_hs300x.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_APPLICATION_SENSOR_TEMPERATURE_HS300X), y)
|
||||
SRC_FILES += temperature_hs300x.c
|
||||
endif
|
||||
|
||||
include $(KERNEL_ROOT)/compiler.mk
|
||||
|
||||
endif
|
||||
20
APP_Framework/Applications/sensor_app/SConscript
Normal file
20
APP_Framework/Applications/sensor_app/SConscript
Normal file
@@ -0,0 +1,20 @@
|
||||
import os
|
||||
from building import *
|
||||
Import('RTT_ROOT')
|
||||
Import('rtconfig')
|
||||
cwd = GetCurrentDir()
|
||||
DEPENDS = ["SUPPORT_SENSOR_FRAMEWORK"]
|
||||
SOURCES = []
|
||||
if GetDepend(['APPLICATION_SENSOR_CO2_ZG09']):
|
||||
SOURCES = ['co2_zg09.c'] + SOURCES
|
||||
if GetDepend(['APPLICATION_SENSOR_PM1_0_PS5308']):
|
||||
SOURCES = ['pm1_0_ps5308.c.c'] + SOURCES
|
||||
if GetDepend(['APPLICATION_SENSOR_VOICE_D124']):
|
||||
SOURCES = ['voice_d124.c'] + SOURCES
|
||||
if GetDepend(['APPLICATION_SENSOR_HUMIDITY_HS300X']):
|
||||
SOURCES = ['humidity_hs300x.c'] + SOURCES
|
||||
if GetDepend(['APPLICATION_SENSOR_TEMPERATURE_HS300X']):
|
||||
SOURCES = ['temperature_hs300x.c'] + SOURCES
|
||||
path = [cwd]
|
||||
objs = DefineGroup('sensor_app', src = SOURCES, depend = DEPENDS,CPPPATH = path)
|
||||
Return("objs")
|
||||
36
APP_Framework/Applications/sensor_app/ch4_as830.c
Normal file
36
APP_Framework/Applications/sensor_app/ch4_as830.c
Normal file
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright (c) 2020 AIIT XUOS Lab
|
||||
* XiUOS is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
* See the Mulan PSL v2 for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file ch4_as830.c
|
||||
* @brief CH4 AS830 example
|
||||
* @version 1.0
|
||||
* @author AIIT XUOS Lab
|
||||
* @date 2021.12.10
|
||||
*/
|
||||
|
||||
#ifdef ADD_XIUOS_FETURES
|
||||
# include <user_api.h>
|
||||
#endif
|
||||
#include <sensor.h>
|
||||
|
||||
/**
|
||||
* @description: Read a ch4
|
||||
* @return 0
|
||||
*/
|
||||
void Ch4As830(void)
|
||||
{
|
||||
struct SensorQuantity *ch4 = SensorQuantityFind(SENSOR_QUANTITY_AS830_CH4, SENSOR_QUANTITY_CH4);
|
||||
SensorQuantityOpen(ch4);
|
||||
printf("CH4 : %d %%LTL\n", SensorQuantityRead(ch4));
|
||||
SensorQuantityClose(ch4);
|
||||
}
|
||||
@@ -18,7 +18,9 @@
|
||||
* @date 2021.04.23
|
||||
*/
|
||||
|
||||
#include "../user_api/switch_api/user_api.h"
|
||||
#ifdef ADD_XIUOS_FETURES
|
||||
# include <user_api.h>
|
||||
#endif
|
||||
#include <sensor.h>
|
||||
|
||||
/**
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright (c) 2020 AIIT XUOS Lab
|
||||
* XiUOS is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
* See the Mulan PSL v2 for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file hcho_tb600b_wq_hcho1os.c
|
||||
* @brief hcho example
|
||||
* @version 1.0
|
||||
* @author AIIT XUOS Lab
|
||||
* @date 2021.12.15
|
||||
*/
|
||||
|
||||
#ifdef ADD_XIUOS_FETURES
|
||||
# include <user_api.h>
|
||||
#endif
|
||||
#include <sensor.h>
|
||||
|
||||
|
||||
/**
|
||||
* @description: Read a hcho
|
||||
* @return 0
|
||||
*/
|
||||
void HchoTb600bHcho1os(void)
|
||||
{
|
||||
struct SensorQuantity *hcho = SensorQuantityFind(SENSOR_QUANTITY_TB600B_HCHO, SENSOR_QUANTITY_HCHO);
|
||||
SensorQuantityOpen(hcho);
|
||||
int32_t result = 0;
|
||||
|
||||
result = SensorQuantityRead(hcho);
|
||||
|
||||
printf("tvoc concentration is : %dppb\n", result);
|
||||
SensorQuantityClose(hcho);
|
||||
}
|
||||
@@ -18,7 +18,10 @@
|
||||
* @date 2021.04.23
|
||||
*/
|
||||
|
||||
#include "../user_api/switch_api/user_api.h"
|
||||
#ifdef ADD_XIUOS_FETURES
|
||||
# include <user_api.h>
|
||||
#endif
|
||||
|
||||
#include <sensor.h>
|
||||
|
||||
/**
|
||||
@@ -27,9 +30,14 @@
|
||||
*/
|
||||
void HumiHs300x(void)
|
||||
{
|
||||
int i = 0;
|
||||
int32 humidity;
|
||||
struct SensorQuantity *humi = SensorQuantityFind(SENSOR_QUANTITY_HS300X_HUMIDITY, SENSOR_QUANTITY_HUMI);
|
||||
SensorQuantityOpen(humi);
|
||||
int32 humidity = SensorQuantityRead(humi);
|
||||
printf("Humidity : %d.%d %%RH\n", humidity/10, humidity%10);
|
||||
for (i = 0; i < 100; i ++) {
|
||||
humidity = SensorQuantityRead(humi);
|
||||
printf("Humidity : %d.%d %%RH\n", humidity/10, humidity%10);
|
||||
PrivTaskDelay(5000);
|
||||
}
|
||||
SensorQuantityClose(humi);
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user