Merge remote-tracking branch 'upstream/2023_open_source_contest' into 2023_open_source_contest_warmup_2nd_issue1

This commit is contained in:
kkk 2023-07-31 11:46:12 +08:00
commit 9c0eced907
297 changed files with 1598 additions and 127 deletions

View File

@ -240,8 +240,49 @@ menu "test app"
bool "Config test soft timer"
default n
menuconfig USER_TEST_HASH
bool "Config test hash"
default n
menuconfig USER_TEST_RADIX
bool "Config test radix tree"
default n
menuconfig USER_TEST_RBTREE
bool "Config test red black tree"
default n
menuconfig USER_TEST_MODBUS_TCP
bool "Config test modbus_tcp"
default n
menuconfig USER_TEST_WEBSERVER
bool "Config test webserver"
default n
menuconfig USER_TEST_MQTTCLIENT
bool "Config test mqtt client"
default n
menuconfig USER_TEST_FTPCLIENT
bool "Config test ftp client"
default n
menuconfig USER_TEST_LORA_P2P
bool "Config test lora p2p"
default n
menuconfig USER_TEST_LORAWAN_SINGLEGW
bool "Config test lorawan single channel gateway"
default n
menuconfig USER_TEST_CANOPEN
bool "Config test CanOpen"
default n
menuconfig USER_TEST_USB_CAMERA
bool "Config test usb camera"
default n
endif
endmenu

View File

@ -99,11 +99,51 @@ ifeq ($(CONFIG_ADD_XIZI_FEATURES),y)
ifeq ($(CONFIG_USER_TEST_TIMER),y)
SRC_FILES += test_timer.c
endif
ifeq ($(CONFIG_USER_TEST_HASH),y)
SRC_FILES += test_hash/test_hash.c
endif
ifeq ($(CONFIG_USER_TEST_RADIX),y)
SRC_FILES += test_radix_tree/test_radix_tree.c
endif
ifeq ($(CONFIG_USER_TEST_RBTREE),y)
SRC_FILES += test_rbtree/test_rbtree.c
endif
ifeq ($(CONFIG_USER_TEST_MODBUS_TCP),y)
SRC_DIR += test_modbus_tcp
endif
ifeq ($(CONFIG_USER_TEST_WEBSERVER),y)
SRC_FILES +=
endif
ifeq ($(CONFIG_USER_TEST_MQTTCLIENT),y)
SRC_FILES +=
endif
ifeq ($(CONFIG_USER_TEST_FTPCLIENT),y)
SRC_FILES +=
endif
ifeq ($(CONFIG_USER_TEST_LORA_P2P),y)
SRC_FILES +=
endif
ifeq ($(CONFIG_USER_TEST_LORAWAN_SINGLEGW),y)
SRC_FILES +=
endif
ifeq ($(CONFIG_USER_TEST_CANOPEN),y)
SRC_FILES +=
endif
ifeq ($(CONFIG_USER_TEST_USB_CAMERA),y)
SRC_FILES +=
endif
include $(KERNEL_ROOT)/compiler.mk
endif

View File

@ -25,7 +25,7 @@
#ifdef BOARD_EDU_RISCV64_EVB
#define BSP_LED_PIN 29
#define BSP_KEY_PIN 31
#elif defined BOARD_HC32F4A0_EVB
#elif defined BOARD_EDU_ARM32_EVB
#define BSP_LED_PIN 134
#define BSP_KEY_PIN 176
#endif

Binary file not shown.

After

Width:  |  Height:  |  Size: 75 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 102 KiB

View File

@ -0,0 +1,58 @@
# 基于cortex-m3-emulator实现哈希表并测试验证##
## 1. 简介
利用c语言实现了哈希表HashMap包括添加键值对(Put),获取键对应的值(Get), 删除健Delete清空哈希表(Clear) 迭代遍历哈希表(hashMapIterator)等功能
操作。
利用数组Entry作为存储空间利用链表(*next)解决冲突。当哈希表的大小超过数组大小后,为避免发生冲突过多的情况,可以对哈希表扩容。
## 2. 数据结构设计说明
键值对结构
typedef struct entry {
void * key; // 键
void * value; // 值
struct entry * next; // 冲突链表
}*Entry;
哈希结构
typedef struct hashMap {
int size; // 当前大小
int listSize; // 有效空间大小
HashCode hashCode; // 哈希函数
Equal equal; // 判等函数
Entry list; // 存储区域
Put put; // 添加键的函数
Get get; // 获取键对应值的函数
Remove remove; // 删除键
Clear clear; // 清空Map
Exists exists; // 判断键是否存在
Boolean autoAssign; // 设定是否根据当前数据量动态调整内存大小,默认开启
}*HashMap;
包括以下函数功能,分别为:
`createHashMap`:创建一个哈希结构
`defaultPut`:添加键值对
`defaultGet`:获取键对应值
`defaultRemove`:删除指定键的键值对
`defaultExists`:判断键值是否存在
`defaultClear`清空Map的函数类型
`resetHashMap`:重新构建哈希表
## 3. 测试程序说明
测试了哈希表的插入键值对(Put),判断键是否存在(Exist),获取键对应的值(Get) 删除健Delete迭代遍历哈希表(hashMapIterator),清空哈希表(Clear)等操作。
并展示了利用链地址法解决哈希冲突的示例, 两个不同的人(Bob和Li Ming)的hashcode相同。
## 4. 运行结果(##需结合运行测试截图按步骤说明##
![image](ConfigOpen.png)
打开menuconfig之后将test_hash_map开启(y),保存后退出
![image](CompileSuccess.png)
编译XiZi-cortex-m3-emulator.elf成功
![image](ShellCommand.png)
启动qemu模拟Xiuos操作系统验证TestHash注册Shell命令
![image](TestHash.png)
执行TestHash命令打印测试结果。

Binary file not shown.

After

Width:  |  Height:  |  Size: 94 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 95 KiB

View File

@ -0,0 +1,323 @@
/**
* @file: test_hash.c
* @brief: a application of test hash function
* @version: 3.0
* @author: Yao wenying
* @date: 2023/05/26
*/
#include <transform.h>
#include"test_hash.h"
int defaultHashCode(HashMap hashMap, let key) {
char * k = (char *)key;
unsigned long h = 0;
while (*k) {
h = (h << 4) + *k++;
unsigned long g = h & 0xF0000000L;
if (g) {
h ^= g >> 24;
}
h &= ~g;
}
return h % hashMap->listSize;
}
Boolean defaultEqual(let key1, let key2) {
return strcmp((string)key1, (string)key2) ? False : True;
}
void resetHashMap(HashMap hashMap, int listSize) {
if (listSize < 8) return;
// 键值对临时存储空间
Entry tempList = newEntryList(hashMap->size);
HashMapIterator iterator = createHashMapIterator(hashMap);
int length = hashMap->size;
for (int index = 0; hasNextHashMapIterator(iterator); index++) {
// 迭代取出所有键值对
iterator = nextHashMapIterator(iterator);
tempList[index].key = iterator->entry->key;
tempList[index].value = iterator->entry->value;
tempList[index].next = NULL;
}
freeHashMapIterator(&iterator);
// 清除原有键值对数据
hashMap->size = 0;
for (int i = 0; i < hashMap->listSize; i++) {
Entry current = &hashMap->list[i];
current->key = NULL;
current->value = NULL;
if (current->next != NULL) {
while (current->next != NULL) {
Entry temp = current->next->next;
free(current->next);
current->next = temp;
}
}
}
// 更改内存大小
hashMap->listSize = listSize;
Entry relist = (Entry)realloc(hashMap->list, hashMap->listSize * sizeof(struct entry));
if (relist != NULL) {
hashMap->list = relist;
relist = NULL;
}
// 初始化数据
for (int i = 0; i < hashMap->listSize; i++) {
hashMap->list[i].key = NULL;
hashMap->list[i].value = NULL;
hashMap->list[i].next = NULL;
}
// 将所有键值对重新写入内存
for (int i = 0; i < length; i++) {
hashMap->put(hashMap, tempList[i].key, tempList[i].value);
}
free(tempList);
}
void defaultPut(HashMap hashMap, let key, let value) {
// 获取哈希值
int index = hashMap->hashCode(hashMap, key);
if (hashMap->list[index].key == NULL) {
hashMap->size++;
// 该地址为空时直接存储
hashMap->list[index].key = key;
hashMap->list[index].value = value;
}
else {
Entry current = &hashMap->list[index];
while (current != NULL) {
if (hashMap->equal(key, current->key)) {
// 对于键值已经存在的直接覆盖
current->value = value;
return;
}
current = current->next;
};
// 发生冲突则创建节点挂到相应位置的next上
Entry entry = newEntry();
entry->key = key;
entry->value = value;
entry->next = hashMap->list[index].next;
hashMap->list[index].next = entry;
hashMap->size++;
}
if (hashMap->autoAssign && hashMap->size >= hashMap->listSize) {
// 内存扩充至原来的两倍
// *注: 扩充时考虑的是当前存储元素数量与存储空间的大小关系,而不是存储空间是否已经存满,
// 例如: 存储空间为10存入了10个键值对但是全部冲突了所以存储空间空着9个其余的全部挂在一个上面
// 这样检索的时候和遍历查询没有什么区别了可以简单这样理解当我存入第11个键值对的时候一定会发生冲突
// 这是由哈希函数本身的特性(取模)决定的,冲突就会导致检索变慢,所以这时候扩充存储空间,对原有键值对进行
// 再次散列,会把冲突的数据再次分散开,加快索引定位速度。
resetHashMap(hashMap, hashMap->listSize * 2);
}
}
let defaultGet(HashMap hashMap, let key) {
if (hashMap->exists(hashMap, key)) {
int index = hashMap->hashCode(hashMap, key);
Entry entry = &hashMap->list[index];
while (entry != NULL) {
if (hashMap->equal(entry->key, key)) {
return entry->value;
}
entry = entry->next;
}
}
return NULL;
}
let defaultRemove(HashMap hashMap, let key) {
int index = hashMap->hashCode(hashMap, key);
Entry entry = &hashMap->list[index];
if (entry->key == NULL) {
return NULL;
}
let entryKey = entry->key;
Boolean result = False;
if (hashMap->equal(entry->key, key)) {
hashMap->size--;
if (entry->next != NULL) {
Entry temp = entry->next;
entry->key = temp->key;
entry->value = temp->value;
entry->next = temp->next;
free(temp);
}
else {
entry->key = NULL;
entry->value = NULL;
}
result = True;
}
else {
Entry p = entry;
entry = entry->next;
while (entry != NULL) {
if (hashMap->equal(entry->key, key)) {
hashMap->size--;
p->next = entry->next;
free(entry);
result = True;
break;
}
p = entry;
entry = entry->next;
};
}
// 如果空间占用不足一半,则释放多余内存
if (result && hashMap->autoAssign && hashMap->size < hashMap->listSize / 2) {
resetHashMap(hashMap, hashMap->listSize / 2);
}
return entryKey;
}
Boolean defaultExists(HashMap hashMap, let key) {
int index = hashMap->hashCode(hashMap, key);
Entry entry = &hashMap->list[index];
if (entry->key == NULL) {
return False;
}
else {
while (entry != NULL) {
if (hashMap->equal(entry->key, key)) {
return True;
}
entry = entry->next;
}
return False;
}
}
void defaultClear(HashMap hashMap) {
for (int i = 0; i < hashMap->listSize; i++) {
// 释放冲突值内存
Entry entry = hashMap->list[i].next;
while (entry != NULL) {
Entry next = entry->next;
free(entry);
entry = next;
}
hashMap->list[i].next = NULL;
}
// 释放存储空间
free(hashMap->list);
hashMap->list = NULL;
hashMap->size = -1;
hashMap->listSize = 0;
}
HashMap createHashMap(HashCode hashCode, Equal equal) {
HashMap hashMap = newHashMap();
if (hashMap == NULL) {
return NULL;
}
hashMap->size = 0;
hashMap->listSize = 8;
hashMap->hashCode = hashCode == NULL ? defaultHashCode : hashCode;
hashMap->equal = equal == NULL ? defaultEqual : equal;
hashMap->exists = defaultExists;
hashMap->get = defaultGet;
hashMap->put = defaultPut;
hashMap->remove = defaultRemove;
hashMap->clear = defaultClear;
hashMap->autoAssign = True;
// 起始分配8个内存空间溢出时会自动扩充
hashMap->list = newEntryList(hashMap->listSize);
if (hashMap->list == NULL) {
return NULL;
}
Entry p = hashMap->list;
for (int i = 0; i < hashMap->listSize; i++) {
p[i].key = p[i].value = p[i].next = NULL;
}
return hashMap;
}
HashMapIterator createHashMapIterator(HashMap hashMap) {
HashMapIterator iterator = newHashMapIterator();
if (iterator == NULL) {
return NULL;
}
iterator->hashMap = hashMap;
iterator->count = 0;
iterator->hashCode = -1;
iterator->entry = NULL;
return iterator;
}
Boolean hasNextHashMapIterator(HashMapIterator iterator) {
return iterator->count < iterator->hashMap->size ? True : False;
}
HashMapIterator nextHashMapIterator(HashMapIterator iterator) {
if (hasNextHashMapIterator(iterator)) {
if (iterator->entry != NULL && iterator->entry->next != NULL) {
iterator->count++;
iterator->entry = iterator->entry->next;
return iterator;
}
while (++iterator->hashCode < iterator->hashMap->listSize) {
Entry entry = &iterator->hashMap->list[iterator->hashCode];
if (entry->key != NULL) {
iterator->count++;
iterator->entry = entry;
break;
}
}
}
return iterator;
}
void freeHashMapIterator(HashMapIterator * iterator) {
free(*iterator);
*iterator = NULL;
}
#define Put(map, key, value) map->put(map, (void *)key, (void *)value);
#define Get(map, key) (char *)map->get(map, (void *)key)
#define Remove(map, key) map->remove(map, (void *)key)
#define Existe(map, key) map->exists(map, (void *)key)
void TestHash() {
HashMap map = createHashMap(NULL, NULL);
Put(map, "000123", "Annie");
Put(map, "000245", "Bob");
Put(map, "000284", "Daniel");
Put(map, "000281", "Luna");
Put(map, "000587", "Yao");
Put(map, "000985", "Li Ming");
Put(map, "000852", "Janne");
printf("print the key-values in hashmap:\n");
HashMapIterator iterator = createHashMapIterator(map);
while (hasNextHashMapIterator(iterator)) {
iterator = nextHashMapIterator(iterator);
printf("{ key: %s, key: %s, hashcode: %d }\n",
(char *)iterator->entry->key, (char *)iterator->entry->value, iterator->hashCode);
}
printf("key: 000852, exists: %s\n", Existe(map, "000852") ? "true" : "false");
printf("000852: %s\n", Get(map, "000852"));
printf("remove 000852 %s\n", Remove(map, "000852") ? "true" : "false");
printf("key: 000852, exists: %s\n", Existe(map, "000852") ? "true" : "false");
map->clear(map);
freeHashMapIterator(&iterator);
}
PRIV_SHELL_CMD_FUNCTION(TestHash, Implement hash_map, PRIV_SHELL_CMD_MAIN_ATTR);

View File

@ -0,0 +1,129 @@
/**
* @file: test_hash.h
* @brief: a application of test hash function
* @version: 3.0
* @author: Yao wenying
* @date: 2023/05/26
*/
#ifndef __HASHMAP_H__
#define __HASHMAP_H__
#include<stdlib.h>
#include<string.h>
#include<stdio.h>
// 实现数据的基本类型
// 字符串类型
#define string char *
#define newString(str) strcpy((char *)malloc(strlen(str) + 1), str)
#define NEW(type) (type *)malloc(sizeof(type))
// 布尔类型
enum _Boolean { True = 1, False = 0 };
typedef enum _Boolean Boolean;
#define let void *
typedef struct entry {
let key; // 键
let value; // 值
struct entry * next; // 冲突链表
}*Entry;
#define newEntry() NEW(struct entry)
#define newEntryList(length) (Entry)malloc(length * sizeof(struct entry))
// 哈希结构
typedef struct hashMap *HashMap;
#define newHashMap() NEW(struct hashMap)
// 哈希函数类型
typedef int(*HashCode)(HashMap, let key);
// 判等函数类型
typedef Boolean(*Equal)(let key1, let key2);
// 添加键函数类型
typedef void(*Put)(HashMap hashMap, let key, let value);
// 获取键对应值的函数类型
typedef let(*Get)(HashMap hashMap, let key);
// 删除键的函数类型
typedef let(*Remove)(HashMap hashMap, let key);
// 清空Map的函数类型
typedef void(*Clear)(HashMap hashMap);
// 判断键值是否存在的函数类型
typedef Boolean(*Exists)(HashMap hashMap, let key);
typedef struct hashMap {
int size; // 当前大小
int listSize; // 有效空间大小
HashCode hashCode; // 哈希函数
Equal equal; // 判等函数
Entry list; // 存储区域
Put put; // 添加键的函数
Get get; // 获取键对应值的函数
Remove remove; // 删除键
Clear clear; // 清空Map
Exists exists; // 判断键是否存在
Boolean autoAssign; // 设定是否根据当前数据量动态调整内存大小,默认开启
}*HashMap;
// 迭代器结构
typedef struct hashMapIterator {
Entry entry; // 迭代器当前指向
int count; // 迭代次数
int hashCode; // 键值对的哈希值
HashMap hashMap;
}*HashMapIterator;
#define newHashMapIterator() NEW(struct hashMapIterator)
// 默认哈希函数
static int defaultHashCode(HashMap hashMap, let key);
// 默认判断键值是否相等
static Boolean defaultEqual(let key1, let key2);
// 默认添加键值对
static void defaultPut(HashMap hashMap, let key, let value);
// 默认获取键对应值
static let defaultGet(HashMap hashMap, let key);
// 默认删除键
static let defaultRemove(HashMap hashMap, let key);
// 默认判断键是否存在
static Boolean defaultExists(HashMap hashMap, let key);
// 默认清空Map
static void defaultClear(HashMap hashMap);
// 重新构建
static void resetHashMap(HashMap hashMap, int listSize);
// 创建一个哈希结构
HashMap createHashMap(HashCode hashCode, Equal equal);
// 创建哈希结构迭代器
HashMapIterator createHashMapIterator(HashMap hashMap);
// 迭代器是否有下一个
Boolean hasNextHashMapIterator(HashMapIterator iterator);
// 迭代到下一次
HashMapIterator nextHashMapIterator(HashMapIterator iterator);
// 释放迭代器内存
void freeHashMapIterator(HashMapIterator * iterator);
#endif // !__HASHMAP_H__

View File

@ -0,0 +1,67 @@
# 基于k210-emulator实现基数树并测试验证
## 1. 简介
基于矽璓模拟器k210-emulator实现基数树并编写测试程序在shell终端打印结果。
## 2. 数据结构设计说明
基数树节点设计为:
```c
typedef struct _node {
void* value;
struct _node* next[NODE_SIZE];
} node;
```
其中,节点在树中的路径即为键,`value` 存储值,`NODE_SIZE` 定义为 128足以容纳所有 ASCII 值。
一共实现了 5 个函数,分别为:
- `CreateNode`:创建一个基数树节点
- `InsertNode`:将一对键值对插入基数树
- `DeleteNode`:删除指定键的键值对
- `FindNode`:查找指定键对应的值
- `DestroyTree`:销毁整个基数树
## 3. 测试程序说明
测试程序 `TestRadix` 已经注册为 shell 命令,可以调用执行。
测试程序定义了以下键值对:
```c
char keys[][MAX_WORD_LEN] = {
"what",
"where",
"why",
"how",
"hello!",
"apple",
"12345"
};
int values[] = {1, 2, 3, 4, 5, 6, 7};
```
1. 程序的第一部分创建了基数树,并且将定义的 7 个键值对的前 6 个插入了基数树,然后分别查找 7 个键,前 6 个均可以找到对应的值,最后一个未插入,因此无法找到
2. 程序的第二部分从基数树中删除了 `where``how` 两个键,再次分别查找 7 个键,删除的键值对和未插入的键值对均无法找到
3. 程序的第三部分重新插入了已删除的 `where` 和未插入过的 `12345` ,再次分别查找 7 个键,新插入的值可以检索到
4. 程序的第四部分将基数树销毁,再次分别查找 7 个键,所有的键值对均无法找到
## 4. 运行结果(##需结合运行测试截图按步骤说明##
1. 在工作区终端中输入命令:`make BOARD=k210-emulator menuconfig`,进入配置页面
![fig1](fig1.png)
2. 依次进入 `APP_Framework` -> `Applications` -> `test app` 目录,将 `Enable application test function` 选项置为 `Y`
![fig2](fig2.png)
3. 进入 `Enable application test function``Config test radix tree` 选项置为 `Y`
![fig3](fig3.png)
4. 一直选择 `Exit` 退出配置,在最后需要确认的页面选择 `Yes` 保存配置
![fig4](fig4.png)
5. 执行编译命令:`make BOARD=k210-emulator`,正常情况下应当编译无误
![fig5](fig5.png)
6. 在 `qemu` 中运行:`qemu-system-riscv64 -nographic -machine sifive_u -bios build/XiZi-k210-emulator.elf`
![fig6](fig6.png)
7. 在 shell 中运行命令 `TestRadix`,执行结果与预期一致,验证完成。
![fig7](fig7.png)

Binary file not shown.

After

Width:  |  Height:  |  Size: 89 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 71 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 131 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 61 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 238 KiB

View File

@ -0,0 +1,187 @@
/**
* @file: test_radix_tree.c
* @brief: Implement a simple radix tree
* @version: 1.0
* @date: 2023/5/24
*/
#include <transform.h>
#include "test_radix_tree.h"
/**
* @description: Create a radix tree node
* @return node pointer
*/
node* CreateNode()
{
node* n = (node*)malloc(sizeof(node));
n->value = NULL;
for (int i = 0; i < NODE_SIZE; i++) {
n->next[i] = NULL;
}
return n;
}
/**
* @description: Insert a new node to radix tree
* @param root - radix tree root
* @param key - new node key
* @param value - new node value
* @return void
*/
void InsertNode(node* root, const char* key, void* value)
{
if (root == NULL) {
return;
}
node* cur = root;
size_t len = strlen(key);
for (size_t i = 0; i < len; i++) {
uint8_t b = (uint8_t)key[i];
if (cur->next[b] == NULL) {
cur->next[b] = CreateNode();
}
cur = cur->next[b];
}
cur->value = value;
}
/**
* @description: Delete a node from radix tree
* @param root - radix tree root
* @param key - key which is needed to delete
* @return void
*/
void DeleteNode(node* root, const char* key)
{
if (root == NULL) {
return;
}
node** cur = &root;
size_t len = strlen(key);
for (size_t i = 0; i < len; i++) {
uint8_t b = (uint8_t)key[i];
if ((*cur)->next[b] == NULL) {
return;
}
cur = &((*cur)->next[b]);
}
if ((*cur)->value == NULL) {
return;
}
(*cur)->value = NULL;
int has_children = 0;
for (int i = 0; i < NODE_SIZE; i++) {
if ((*cur)->next[i] != NULL) {
has_children = 1;
break;
}
}
if (!has_children) {
free(*cur);
(*cur) = NULL;
}
}
/**
* @description: find a node by key
* @param root - radix tree root
* @param key - key which is needed to find
* @return value pointer corresponding to key
*/
void* FindNode(node* root, const char* key)
{
if (root == NULL) {
return NULL;
}
node* cur = root;
size_t len = strlen(key);
for (size_t i = 0; i < len; i++) {
uint8_t b = (uint8_t)key[i];
if (cur->next[b] == NULL) {
return NULL;
}
cur = cur->next[b];
}
return cur->value;
}
/**
* @description: Destroy the radix tree
* @param root - radix tree root
* @return void
*/
void DestroyTree(node* root)
{
if (root == NULL) {
return;
}
for (int i = 0; i < NODE_SIZE; i++) {
DestroyTree(root->next[i]);
}
free(root);
}
void TestRadix()
{
char keys[][MAX_WORD_LEN] = {
"what",
"where",
"why",
"how",
"hello!",
"apple",
"12345"
};
int values[] = {1, 2, 3, 4, 5, 6, 7};
printf("\nCreate tree and add key & value:\n");
node* root = CreateNode();
if (!root) printf("Create node failed.\n");
int num = sizeof(keys) / sizeof(keys[0]);
for (int i = 0; i < num - 1; ++i) {
InsertNode(root, keys[i], &values[i]);
}
for (int i = 0; i < num; ++i) {
int* v = (int*)FindNode(root, keys[i]);
if (v) printf("keys[%d] \"%s\"'v = %d, values[%d] = %d\n", i, keys[i], *v, i, values[i]);
else printf("keys[%d] \"%s\" not found\n", i, keys[i]);
}
printf("\nDelete \"where\" and \"how\":\n");
DeleteNode(root, keys[1]);
DeleteNode(root, keys[3]);
for (int i = 0; i < num; ++i) {
int* v = (int*)FindNode(root, keys[i]);
if (v) printf("keys[%d] \"%s\"'v = %d, values[%d] = %d\n", i, keys[i], *v, i, values[i]);
else printf("keys[%d] \"%s\" not found\n", i, keys[i]);
}
printf("\nInsert \"where\" and \"12345\":\n");
InsertNode(root, keys[1], &values[1]);
InsertNode(root, keys[6], &values[6]);
for (int i = 0; i < num; ++i) {
int* v = (int*)FindNode(root, keys[i]);
if (v) printf("keys[%d] \"%s\"'v = %d, values[%d] = %d\n", i, keys[i], *v, i, values[i]);
else printf("keys[%d] \"%s\" not found\n", i, keys[i]);
}
printf("\nDestroy tree:\n");
DestroyTree(root);
root = NULL;
for (int i = 0; i < num; ++i) {
int* v = (int*)FindNode(root, keys[i]);
if (v) printf("keys[%d] \"%s\"'v = %d, values[%d] = %d\n", i, keys[i], *v, i, values[i]);
else printf("keys[%d] \"%s\" not found\n", i, keys[i]);
}
}
PRIV_SHELL_CMD_FUNCTION(TestRadix, Implement a simple radix tree, PRIV_SHELL_CMD_MAIN_ATTR);

View File

@ -0,0 +1,20 @@
/**
* @file: test_radix_tree.h
* @brief: Implement a simple radix tree
* @version: 1.0
* @date: 2023/5/24
*/
#define NODE_SIZE 128
#define MAX_WORD_LEN 128
typedef struct _node {
void* value;
struct _node* next[NODE_SIZE];
} node;
node* CreateNode();
void InsertNode(node* root, const char* key, void* value);
void DeleteNode(node* root, const char* key);
void* FindNode(node* root, const char* key);
void DestroyTree(node* root);

View File

@ -0,0 +1,69 @@
# 基于cortex-m4-emulator实现红黑树并测试验证
## 1. 简介
红黑树是一种自平衡的二叉查找树具有良好的插入、删除和查找性能本次提交结果为红黑树数据结构的简单实现。test_rbtree.h中定义了红黑树的数据结构和声明插入、删除、查找相关操作函数;test_rbtree.c中为操作函数的定义并提供了测试函数TestRBTree用于验证红黑树的正确性。
## 2. 数据结构设计说明
**RBNodeType 结构体**
用来存储一个红黑树结点的相关信息
- key节点的键值
- left_child指向左子节点的指针
- right_child指向右子节点的指针
- parent指向父节点的指针
- is_red表示节点的颜色true表示红色false表示黑色
**RBTreeType 结构体**
用来存储一个红黑树的相关信息
- root指向红黑树的根节点的指针
- leaf红黑树的叶节点由于叶节点并不需要存储数据故每棵树只分配一个叶节点
**RBTreeTraversal 函数**
该函数用于遍历红黑树并打印节点的键值。采用中序遍历的方式,递归地遍历左子树、当前节点和右子树。
**RBTreeLeftRotate 函数**
该函数实现红黑树的左旋转操作。接受一个当前节点指针作为参数,并按照左旋转的规则调整节点和子树的位置。
**RBTreeRightRotate 函数**
该函数实现红黑树的右旋转操作。接受一个当前节点指针作为参数,并按照右旋转的规则调整节点和子树的位置。
**InsertFixup 函数**
该函数用于插入节点后修复红黑树的平衡性。接受一个当前节点指针作为参数,并根据红黑树的性质进行旋转和着色操作,以恢复平衡。
**RBTreeInsert 函数**
该函数用于向红黑树中插入一个新节点。接受一个新节点指针作为参数,并根据新节点的键值插入到适当的位置,然后调用 InsertFixup 进行修复。
**DeleteFixup 函数**
该函数用于删除节点后修复红黑树的平衡性。接受一个当前节点指针作为参数,并根据红黑树的性质进行旋转和着色操作,以恢复平衡。
**RBTreeDelete 函数**
该函数用于从红黑树中删除指定节点。接受一个目标节点指针作为参数,并根据不同的情况进行节点的替换和删除操作,然后调用 DeleteFixup 进行修复。
**FindSuccessor 函数**
该函数用于查找给定节点的后继节点。接受一个当前节点指针作为参数,并在红黑树中找到当前节点的后继节点。
**RBTreeSearch 函数**
该函数用于在红黑树中查找指定键值的节点。接受一个键值作为参数,并在红黑树中进行查找,返回找到的节点指针。
## 3. 测试程序说明
TestRBTree用于验证红黑树的功能和正确性,下面是该程序的使用步骤和说明:
- 函数中定义一个默认关键字数组其中包含了20个整数关键字运行时自动遍历数组构建红黑树构建完成后中序遍历输出结果可以根据输出结果验证红黑树的节点顺序以及颜色是否符合预期。
- 对关键字数组中的每个关键字,在红黑树中进行搜索,并输出找到节点的父节点、左子节点和右子节点的关键字,随后删除该节点。
- 在每次删除操作后,程序会询问是否显示当前的红黑树。如果输入 "Y" 或 "y",将再次进行中序遍历,并输出当前红黑树中的结点,可以根据输出结果查看结点是否符合预期。当树空时结束程序。
## 4. 运行结果(##需结合运行测试截图按步骤说明##
根据默认关键字数组构建红黑树
![Alt text](image.png)
根据键值查找结点,输出相关信息并删除,可以输入'Y'或'y'展示删除后的红黑树
![Alt text](image-1.png)
到达空树,退出程序
![Alt text](image-2.png)

Binary file not shown.

After

Width:  |  Height:  |  Size: 65 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 125 KiB

View File

@ -0,0 +1,341 @@
/*
* Copyright (c) 2023 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: test_rbtree.c
* @brief: a application of red-black tree function
* @version: 1.0
* @author: AIIT XUOS Lab
* @date: 2023/6/23
*/
#include<string.h>
#include <transform.h>
#include"test_rbtree.h"
#ifdef ADD_XIZI_FEATURES
void RBTreeTraversal(RBTreeType *tree, RBNodeType *node)
{
if (node != tree->leaf) {
RBTreeTraversal(tree, node->left_child);
printf("key:%d, color:%s\n", node->key, (node->is_red ? "Red" : "Black"));
RBTreeTraversal(tree, node->right_child);
}
}
RBNodeType* RBTreeSearch(RBTreeType *tree, int key)
{
RBNodeType* current_node = tree->root;
while (current_node != tree->leaf){
if (key < current_node->key)
current_node = current_node->left_child;
else if (key > current_node->key)
current_node = current_node->right_child;
else
return current_node;
}
return tree->leaf;
}
void RBTreeLeftRotate(RBTreeType *tree, RBNodeType *current_node)
{
RBNodeType* child_node = current_node->right_child;
current_node->right_child = child_node->left_child;
if (child_node->left_child != tree->leaf)
child_node->left_child->parent = current_node;
child_node->parent = current_node->parent;
if (current_node->parent == tree->leaf)
tree->root = child_node;
else if (current_node == current_node->parent->left_child)
current_node->parent->left_child = child_node;
else
current_node->parent->right_child = child_node;
child_node->left_child = current_node;
current_node->parent = child_node;
}
void RBTreeRightRotate(RBTreeType *tree, RBNodeType* current_node)
{
RBNodeType* child_node = current_node->left_child;
current_node->left_child = child_node->right_child;
if (child_node->right_child != tree->leaf)
child_node->right_child->parent = current_node;
child_node->parent = current_node->parent;
if (current_node->parent == tree->leaf)
tree->root = child_node;
else if (current_node == current_node->parent->right_child)
current_node->parent->right_child = child_node;
else
current_node->parent->left_child = child_node;
child_node->right_child = current_node;
current_node->parent = child_node;
}
void InsertFixup(RBTreeType *tree, RBNodeType* current_node)
{
while (current_node->parent->is_red){
/* The parent of current_node is the left subtree of the grandfather */
if (current_node->parent == current_node->parent->parent->left_child){
RBNodeType * uncle_node = current_node->parent->parent->right_child;
if (uncle_node->is_red){ /* case1:red uncle and red parent, change color */
uncle_node->is_red = false;
current_node->parent->is_red = false;
current_node->parent->parent->is_red = true;
current_node = current_node->parent->parent;
}else{ /* case2:black uncle and red parent, need rotation */
if (current_node->parent->right_child == current_node){
current_node = current_node->parent;
RBTreeLeftRotate(tree, current_node);
}
current_node->parent->is_red = false;
current_node->parent->parent->is_red = true;
RBTreeRightRotate(tree, current_node->parent->parent);
}
/* The parent of current_node is the right subtree of the grandfather, same with left subtree */
}else{
RBNodeType * uncle_node = current_node->parent->parent->left_child;
if (uncle_node->is_red){
uncle_node->is_red = false;
current_node->parent->is_red = false;
current_node->parent->parent->is_red = true;
current_node = current_node->parent->parent;
}else{
if (current_node->parent->left_child == current_node){
current_node = current_node->parent;
RBTreeRightRotate(tree, current_node);
}
current_node->parent->is_red = false;
current_node->parent->parent->is_red = true;
RBTreeLeftRotate(tree, current_node->parent->parent);
}
}
}
tree->root->is_red = false;
}
void RBTreeInsert(RBTreeType *tree, RBNodeType* new_node)
{
RBNodeType* previous_node = tree->root;
RBNodeType* current_node = tree->root;
while (current_node != tree->leaf){
previous_node = current_node;
if (new_node->key > current_node->key)
current_node = current_node->right_child;
else if (new_node->key < current_node->key)
current_node = current_node->left_child;
else
return;
}
if (previous_node == tree->leaf){
tree->root = new_node;
tree->root->parent = tree->leaf;
}else{
new_node->parent = previous_node;
if (previous_node->key > new_node->key)
previous_node->left_child = new_node;
else
previous_node->right_child = new_node;
}
InsertFixup(tree, new_node);
}
RBNodeType* FindSuccessor(RBTreeType *tree, RBNodeType* current_node)
{
RBNodeType* parent_node = current_node->parent;
if (current_node->right_child != tree->leaf){
current_node = current_node->right_child;
while (current_node->left_child != tree->leaf)
current_node = current_node->left_child;
return current_node;
}
while ((parent_node != tree->leaf) && (current_node == parent_node->right_child)){
current_node = parent_node;
parent_node = parent_node->parent;
}
return parent_node;
}
void DeleteFixup(RBTreeType *tree, RBNodeType* current_node)
{
while ((current_node != tree->root) && (current_node->is_red == false)){
if (current_node == current_node->parent->left_child){
RBNodeType* brother_node = current_node->parent->right_child;
if (brother_node->is_red){
brother_node->is_red = false;
current_node->parent->is_red = true;
RBTreeLeftRotate(tree, current_node->parent);
brother_node = current_node->parent->right_child;
}
if ((brother_node->left_child->is_red == false) && (brother_node->right_child->is_red == false)){
brother_node->is_red = true;
current_node = current_node->parent;
}else{
if (brother_node->right_child->is_red == false){
brother_node->left_child->is_red = false;
brother_node->is_red = true;
RBTreeRightRotate(tree, brother_node);
brother_node = current_node->parent->right_child;
}
brother_node->is_red = current_node->parent->is_red;
current_node->parent->is_red = false;
brother_node->right_child->is_red = false;
RBTreeLeftRotate(tree, current_node->parent);
current_node = tree->root;
}
}else{
RBNodeType* brother_node = current_node->parent->left_child;
if (brother_node->is_red){
brother_node->is_red = false;
current_node->parent->is_red = true;
RBTreeRightRotate(tree, current_node->parent);
brother_node = current_node->parent->left_child;
}
if ((brother_node->left_child->is_red == false) && (brother_node->right_child->is_red == false)){
brother_node->is_red = true;
current_node = current_node->parent;
}else{
if (brother_node->left_child->is_red == false){
brother_node->right_child->is_red = false;
brother_node->is_red = true;
RBTreeLeftRotate(tree, brother_node);
brother_node = current_node->parent->left_child;
}
brother_node->is_red = current_node->parent->is_red;
current_node->parent->is_red = false;
brother_node->left_child->is_red = false;
RBTreeRightRotate(tree, current_node->parent);
current_node = tree->root;
}
}
}
current_node->is_red = false;
}
void RBTreeDelete(RBTreeType *tree, RBNodeType* target_node)
{
RBNodeType* delete_node = tree->leaf;
RBNodeType* replace_node = tree->leaf;
if ((target_node->left_child == tree->leaf) || (target_node->right_child == tree->leaf))
delete_node = target_node;
else
delete_node = FindSuccessor(tree, target_node);
if (delete_node->left_child != tree->leaf) /* successor still has subtree */
replace_node = delete_node->left_child;
else if (delete_node->right_child != tree->leaf)
replace_node = delete_node->right_child;
replace_node->parent = delete_node->parent;
if (delete_node->parent == tree->leaf) /* delete a root node */
tree->root = replace_node;
else if (delete_node == delete_node->parent->left_child)
delete_node->parent->left_child = replace_node;
else
delete_node->parent->right_child = replace_node;
if (delete_node != target_node)
target_node->key = delete_node->key;
if (delete_node->is_red == false)
DeleteFixup(tree, replace_node);
free(delete_node);
}
void TestRBTree(void)
{
int default_key[] = { 16, 25, 23, 5, 2, 6, 17, 37, 38, 98, 20, 19, 47, 49, 12, 21, 9, 18, 14, 15 };
int array_size = sizeof(default_key) / sizeof(default_key[0]);
printf("Test Red Black Tree\n");
printf("default_key array: ");
for (int i = 0; i < array_size; i++)
printf("%d ", default_key[i]);
printf("\n%d elements\n", array_size);
RBTreeType *tree = (RBTreeType *)malloc(sizeof(RBTreeType));
if (tree == NULL) {
printf("malloc failed\n");
return;
}
tree->leaf = (RBNodeType*)malloc(sizeof(RBNodeType));
tree->leaf->left_child = NULL;
tree->leaf->right_child = NULL;
tree->leaf->parent = NULL;
tree->leaf->is_red = false;
tree->leaf->key = -1;
tree->root = tree->leaf;
RBNodeType *node = tree->leaf;
for (int i = 0; i < array_size; i++) {
node = (RBNodeType*)malloc(sizeof(RBNodeType));
node->left_child = tree->leaf;
node->right_child = tree->leaf;
node->parent = NULL;
node->is_red = true;
node->key = default_key[i];
printf("insert key[%d]=%d\n",i,default_key[i]);
RBTreeInsert(tree, node);
}
printf("------------------Inorder Traversal------------------\n");
RBTreeTraversal(tree, tree->root);
for (int i = 0; i < array_size; i++) {
printf("search key = %d\n", default_key[i]);
node = RBTreeSearch(tree, default_key[i]);
printf("search succeeded, parent node: %d, left-child: %d, right-child: %d\n", node->parent->key, node->left_child->key, node->right_child->key);
printf("delete key = %d\n", node->key);
RBTreeDelete(tree, node);
printf("Show current tree?Y/N \n");
char ch;
scanf("%c", &ch);
if (ch == 'Y' || ch == 'y') {
printf("------------------Inorder Traversal Tree After Deletion------------------\n");
if (tree->root != tree->leaf)
RBTreeTraversal(tree, tree->root);
else
printf("the tree is empty.\n");
}
}
}
PRIV_SHELL_CMD_FUNCTION(TestRBTree, a red-black tree test sample, PRIV_SHELL_CMD_MAIN_ATTR);
#endif

View File

@ -0,0 +1,60 @@
/*
* Copyright (c) 2023 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: test_rbtree.h
* @brief: a head file of red-black tree structure
* @version: 1.0
* @author: AIIT XUOS Lab
* @date: 2023/6/23
*/
#ifndef REDBLACKTREE_H_
#define REDBLACKTREE_H_
#include <stdbool.h>
#include <stdio.h>
typedef struct RedBlackNode
{
int key;
struct RedBlackNode *left_child;
struct RedBlackNode *right_child;
struct RedBlackNode *parent;
bool is_red;
} RBNodeType;
typedef struct RedBlackTree
{
RBNodeType *root;
RBNodeType *leaf;
} RBTreeType;
void TestRBTree(void);
void RBTreeTraversal(RBTreeType *tree, RBNodeType *node);
void RBTreeLeftRotate(RBTreeType *tree, RBNodeType *current_node);
void RBTreeRightRotate(RBTreeType *tree, RBNodeType* current_node);
void InsertFixup(RBTreeType *tree, RBNodeType* current_node);
void RBTreeInsert(RBTreeType *tree, RBNodeType* new_node);
void DeleteFixup(RBTreeType *tree, RBNodeType* current_node);
void RBTreeDelete(RBTreeType *tree, RBNodeType* target_node);
RBNodeType* FindSuccessor(RBTreeType *tree, RBNodeType* current_node);
RBNodeType* RBTreeSearch(RBTreeType *tree, int key);
#endif

View File

@ -1,4 +1,4 @@
# KEYENCE 通信测试
# keyence通信测试
[TOC]
@ -12,11 +12,55 @@
- 存储区ZF区。
## JSON配方设计
* 共测试INT16共1种类型数据,以下为JSON文件解释。
- ```json
{
"device_id": 1, //设备ID默认是1此参数无效
"device_name": "KV8000", //设备名称,自定义
"communication_type": 0, //通讯协议类型 0是以太网1是串口
"socket_config": { //以太网配置
"plc_ip": "192.168.250.40", //PLC的IP地址
"local_ip": "192.168.250.233", //矽达通IP地址设定
"gateway": "192.168.250.1", //矽达通的网关地址设定
"netmask": "255.255.255.0", //矽达通子网掩码设定
"port":502 //端口号设定
},
"protocol_type": 3, //通讯协议3代表modbus-tcp协议
"read_period": 100, //交互周期ms
"read_item_list": [
{
"value_name": "ZF0", //变量名称,自定义
"value_type": 3, //变量类型BOOL = 1,INT8 = 2,INT16,INT32,UINT8,UINT16,UINT32,DOUBLE,FLOAT = 9
"function_code": 3, //功能码。3是读
"start_address": 0, //起始地址
"data_length": 1 //BOOL长度默认是1代表读取1个BOOL长度
},
{
"value_name": "ZF2", //变量名称,自定义
"value_type": 3, //变量类型BOOL = 1,INT8 = 2,INT16,INT32,UINT8,UINT16,UINT32,DOUBLE,FLOAT = 9
"function_code": 3, //功能码。3/6是读
"start_address": 2, //起始地址偏移1位
"data_length": 1 //BOOL长度默认是1代表读取1个BOOL长度
}
]
}
```
## 通信测试
1共测试INT16类型数据。
(1) 新增1个通信demo命名为keyence_KV8000.c
2测试ZF区数据。
(2) 复制样例代码程序到keyence_KV8000.c文件中
3D区数据测试用功能码03和06以字为单位读写。如读写ZF1则配方文件中起始地址则直接写1即可。
(3) void **ControlKV8000Test**(void) 更改函数名;
(4) PRIV_SHELL_CMD_FUNCTION(**ControKV8000Test**, keyence plc KV8000 Demo**, PRIV_SHELL_CMD_MAIN_ATTR);更改测试指令;
(5) 剪裁配置完成后,用过烧写器下载至矽达通中,重启后完成测试。

View File

@ -1,12 +1,14 @@
# OMRON_CP1L通信测试
# OMRON_CP1L/H通信测试
[TOC]
## 通信接线及参数设置
* 本体无接口增加CP1W-CIF41网络板卡
* CP1L本体无接口,增加CP1W-CIF41网络板卡,CP1H自带网口,采用网线直连的方式
* FINS协议PLC IP192.168.250.31Port9600
* ![CP1H](./image/CP1H.jpg)
* ![CP1L](./image/CP1L.jpg)
* ![xidatong](./image/xidatong.jpg)
## 存储区

Binary file not shown.

After

Width:  |  Height:  |  Size: 190 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 182 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 204 KiB

View File

@ -1,21 +1,65 @@
# SCHNEIDER M241通信测试
# SCHNEIDER M241L通信测试
[TOC]
## 通信接线及参数设置
* 串口
* M241支持2路485串口本次采用的是serial2。波特率9600数据位8位停止位1位校验偶校验
* M241支持2路485串口本次采用的是serial2。波特率9600数据位8位停止位1位校验偶校验
## 存储区
- 存储区MW区。
## JSON配方设计
* 共测试BOOLINT16共2种类型数据,以下为JSON文件解释。
- ```json
{
"device_id": 1, //设备ID默认是1此参数无效
"device_name": "m241", //设备名称,自定义
"communication_type": 1, //通讯协议类型 0是以太网1是串口
"serial_config": { //串口配置
"station": 1, //站号
"baud_rate": 9600, //波特率
"data_bits": 8, //数据位
"stop_bits": 1, //停止位
"check_mode": 3 //1无校验2校验3偶校验
},
"protocol_type": 3, //通讯协议3代表modbus-tcp协议
"read_period": 100, //交互周期ms
"read_item_list": [
{
"value_name": "MW0", //变量名称,自定义
"value_type": 3, //变量类型BOOL = 1,INT8 = 2,INT16,INT32,UINT8,UINT16,UINT32,DOUBLE,FLOAT = 9
"function_code": 3, //功能码。3是读
"start_address": 0, //起始地址
"data_length": 1 //BOOL长度默认是1代表读取1个BOOL长度
},
{
"value_name": "MW1", //变量名称,自定义
"value_type": 3, //变量类型BOOL = 1,INT8 = 2,INT16,INT32,UINT8,UINT16,UINT32,DOUBLE,FLOAT = 9
"function_code": 3, //功能码。3是读
"start_address": 1, //起始地址偏移1位
"data_length": 1 //BOOL长度默认是1代表读取1个BOOL长度
}
]
}
```
## 通信测试
1共测试INT16共1种类型数据。
(1) 新增1个通信demo命名为schneider_m241.c
2测试MW区数据。
(2) 复制样例代码程序到schneider_m241.c文件中
3MW区数据测试用功能码03以字为单位读取。如读MW100则配方文件中起始地址则直接写100即可。
(3) void **ControlSCHNEIDERM241Test**(void) 更改函数名;
(4) PRIV_SHELL_CMD_FUNCTION(**ControlM241Test**, **Schneider M241 Demo**, PRIV_SHELL_CMD_MAIN_ATTR);更改测试指令;
(5) 剪裁配置完成后,用过烧写器下载至矽达通中,重启后完成测试。

View File

@ -1,4 +1,4 @@
# XINJIE 通信测试
# XINJE通信测试
[TOC]
@ -12,12 +12,55 @@
- 存储区M、D区。
## JSON配方设计
* 共测试BOOLINT16共2种类型数据,以下为JSON文件解释。
- ```json
{
"device_id": 1, //设备ID默认是1此参数无效
"device_name": "XDH", //设备名称,自定义
"communication_type": 0, //通讯协议类型 0是以太网1是串口
"socket_config": { //以太网配置
"plc_ip": "192.168.250.32", //PLC的IP地址
"local_ip": "192.168.250.233", //矽达通IP地址设定
"gateway": "192.168.250.1", //矽达通的网关地址设定
"netmask": "255.255.255.0", //矽达通子网掩码设定
"port":502 //端口号设定
},
"protocol_type": 3, //通讯协议3代表modbus-tcp协议
"read_period": 100, //交互周期ms
"read_item_list": [
{
"value_name": "MW0", //变量名称,自定义
"value_type": 3, //变量类型BOOL = 1,INT8 = 2,INT16,INT32,UINT8,UINT16,UINT32,DOUBLE,FLOAT = 9
"function_code": 3, //功能码。3是读
"start_address": 0, //起始地址
"data_length": 1 //BOOL长度默认是1代表读取1个BOOL长度
},
{
"value_name": "MW1", //变量名称,自定义
"value_type": 3, //变量类型BOOL = 1,INT8 = 2,INT16,INT32,UINT8,UINT16,UINT32,DOUBLE,FLOAT = 9
"function_code": 3, //功能码。3是读
"start_address": 1, //起始地址偏移1位
"data_length": 1 //BOOL长度默认是1代表读取1个BOOL长度
}
]
}
```
## 通信测试
1共测试BOOLINT16共2种类型数据。
(1) 新增1个通信demo命名为xinje_xdh.c
2测试M区及D区数据。
(2) 复制样例代码程序到xinje_xdh.c文件中
3D区数据测试用功能码03和06以字为单位读写。如读写D500则配方文件中起始地址则直接写500即可。
(3) void **ControlXINJEXDHTest**(void) 更改函数名;
4M区数据测试用功能码01和05以位为单位读写。如读写M19则配方文件中起始地址则直接写19即可。
(4) PRIV_SHELL_CMD_FUNCTION(**ControlXINJEXDHTest**, **Omron Plc Cp1l Demo**, PRIV_SHELL_CMD_MAIN_ATTR);更改测试指令;
(5) 剪裁配置完成后,用过烧写器下载至矽达通中,重启后完成测试。

View File

@ -6,7 +6,7 @@ MAKEFLAGS += --no-print-directory
riscv_support := kd233 maix-go hifive1-rev-B gapuino gd32vf103-rvstar rv32m1-vega aiit-riscv64-board xidatong-riscv64 edu-riscv64
arm_support += stm32f407-st-discovery stm32f407zgt6 stm32f103-nano nuvoton-m2354 ok1052-c imxrt1176-sbc aiit-arm32-board xidatong-arm32 xiwangtong-arm32 hc32f4a0
arm_support += stm32f407-st-discovery stm32f407zgt6 stm32f103-nano nuvoton-m2354 ok1052-c imxrt1176-sbc aiit-arm32-board xidatong-arm32 xiwangtong-arm32 edu-arm32
emulator_support += hifive1-emulator k210-emulator cortex-m0-emulator cortex-m3-emulator cortex-m4-emulator
support := $(riscv_support) $(arm_support) $(emulator_support)
SRC_DIR :=
@ -62,10 +62,6 @@ PART += COMPILE_KERNEL
else ifeq ($(CONFIG_COMPILER_APP)_$(CONFIG_COMPILER_KERNEL),y_y)
PART := COMPILE_APP COMPILE_KERNEL
else ifeq ($(CONFIG_MCUBOOT_BOOTLOADER), y)
PART := COMPILE_BOOTLOADER
else ifeq ($(CONFIG_MCUBOOT_APPLICATION), y)
PART := COMPILE_APPLICATION
else
PART :=
@ -77,9 +73,16 @@ ifeq ($(CONFIG_RESOURCES_LWIP), y)
PART += COMPILE_LWIP
endif
ifeq ($(CONFIG_MCUBOOT_BOOTLOADER), y)
PART += COMPILE_BOOTLOADER
else ifeq ($(CONFIG_MCUBOOT_APPLICATION), y)
PART += COMPILE_APPLICATION
else
PART += COMPILE_ALL
endif
endif
all: $(PART)

View File

@ -23,13 +23,13 @@
ARM架构系列的开发板有
aiit-arm32-board nuvoton-m2354 ok1052-c stm32f103-nano stm32f407-st-discovery stm32f407zgt6 xidatong-arm32
aiit-arm32-board nuvoton-m2354 ok1052-c stm32f103-nano stm32f407-st-discovery stm32f407zgt6 xidatong-arm32 edu-arm32
### RISC-V
RISC-V架构系列的开发板有
aiit-riscv64-board gapuino gd32vf103-rvstar hifive1-rev-B kd233 maix-go rv32m1-vega
aiit-riscv64-board gapuino gd32vf103-rvstar hifive1-rev-B kd233 maix-go rv32m1-vega edu-riscv64
## 开发环境

View File

@ -25,7 +25,7 @@ SRC_DIR := shared
SRC_DIR += cortex-m4
endif
ifeq ($(CONFIG_BOARD_HC32F4A0_EVB),y)
ifeq ($(CONFIG_BOARD_EDU_ARM32_EVB),y)
SRC_DIR := shared
SRC_DIR += cortex-m4
endif

View File

@ -14,7 +14,7 @@ SRC_FILES += svc_handle.c mpu.c
endif
endif
ifeq ($(CONFIG_BOARD_HC32F4A0_EVB),y)
ifeq ($(CONFIG_BOARD_EDU_ARM32_EVB),y)
SRC_DIR += hc32f4a0
endif

View File

@ -2,7 +2,7 @@
# Automatically generated file; DO NOT EDIT.
# XiZi_IIoT Project Configuration
#
CONFIG_BOARD_HC32F4A0_EVB=y
CONFIG_BOARD_EDU_ARM32_EVB=y
CONFIG_ARCH_ARM=y
#
@ -25,7 +25,7 @@ CONFIG_SERIAL_6_DEVICE_NAME_0="usart6_dev6"
#
# config board app name
#
CONFIG_BOARD_APP_NAME="/XiUOS_hc32f4a0_app.bin"
CONFIG_BOARD_APP_NAME="/XiUOS_edu_arm32_app.bin"
#
# Hardware feature

View File

@ -10,21 +10,21 @@ config KERNEL_DIR
option env="KERNEL_ROOT"
default "../.."
config BOARD_HC32F4A0_EVB
config BOARD_EDU_ARM32_EVB
bool
select ARCH_ARM
default y
source "$KERNEL_DIR/arch/Kconfig"
menu "hc32f4a0 feature"
menu "edu-arm32 feature"
source "$BSP_DIR/third_party_driver/Kconfig"
menu "config default board resources"
menu "config board app name"
config BOARD_APP_NAME
string "config board app name"
default "/XiUOS_hc32f4a0_app.bin"
default "/XiUOS_edu_arm32_app.bin"
endmenu
endmenu

View File

@ -1,4 +1,4 @@
# 从零开始构建矽璓工业物联操作系统使用ARM架构的HC32F4A0开发板
# 从零开始构建矽璓工业物联操作系统使用ARM架构的edu-arm32开发板
[XiUOS](http://xuos.io/) (X Industrial Ubiquitous Operating System) 矽璓工业物联操作系统是一款面向工业物联场景的泛在操作系统,来自泛在操作系统研究计划。所谓泛在操作系统(UOS: Ubiquitous Operating Systems)是支持互联网时代人机物融合泛在计算应用模式的新型操作系统是传统操作系统概念的泛化与延伸。在泛在操作系统技术体系中不同的泛在计算设备和泛在应用场景需要符合各自特性的不同UOSXiUOS即是面向工业物联场景的一种UOS主要由一个极简的微型实时操作系统(RTOS)内核和其上的智能工业物联框架构成,支持工业物联网(IIoT: Industrial Internet of Things)应用。
@ -101,7 +101,7 @@ ARM arm-none-eabi(`gcc version 6.3.1`)默认安装到Ubuntu的/usr/bin/arm
$ sudo apt install gcc-arm-none-eabi
```
# 在HC32F4A0上创建第一个应用 --helloworld
# 在edu-arm32上创建第一个应用 --helloworld
## 1. 简介
@ -133,8 +133,8 @@ XiUOS板级驱动当前支持使用UART。
```c
cd ./Ubiquitous/XiZi
make BOARD=hc32f4a0 distclean
make BOARD=hc32f4a0 menuconfig
make BOARD=edu-arm32 distclean
make BOARD=edu-arm32 menuconfig
```
2.在menuconfig界面配置需要关闭和开启的功能按回车键进入下级菜单按Y键选中需要开启的功能按N键选中需要关闭的功能配置结束后保存并退出本例旨在演示简单的输出例程所以没有需要配置的选项双击快捷键ESC退出配置
@ -148,15 +148,15 @@ make BOARD=hc32f4a0 menuconfig
3.继续执行以下命令,进行编译
```c
make BOARD=hc32f4a0
make BOARD=edu-arm32
```
4.如果编译正确无误会产生XiZi_hc32f4a0.elf、XiZi_hc32f4a0.bin文件。其中XiZi_shc32f4a0.bin需要烧写到设备中进行运行。
4.如果编译正确无误会产生XiZi-edu-arm32.elf、XiZi-edu-arm32.bin文件。其中XiZi-edu-arm32.bin需要烧写到设备中进行运行。
## 3. 烧写及执行
### 3.1 烧写
将BOARD=hc32f4a0开发板通过TYPE-C接口转接到PC然后使用华大官方HDSC ISP工具进行烧写bin文件。
将BOARD=edu-arm32开发板通过TYPE-C接口转接到PC然后使用华大官方HDSC ISP工具进行烧写bin文件。
1、烧写工具HDSC ISP可参考[https://www.hdsc.com.cn/Category83-1496](https://www.hdsc.com.cn/Category83-1496)
@ -167,6 +167,6 @@ make BOARD=hc32f4a0
### 3.2 运行结果
如果编译 & 烧写无误,将会在串口终端上看到信息打印输出,(终端串口引脚为UART3)。
如果编译 & 烧写无误,将会在串口终端上看到信息打印输出,(终端TYPE-C串口引脚为UART3)。
![terminal](img/terminal.png)

View File

@ -12,7 +12,7 @@
/**
* @file board.c
* @brief support hc32f4a0-board init configure and start-up
* @brief support edu-arm32-board init configure and start-up
* @version 2.0
* @author AIIT XUOS Lab
* @date 2022-09-08
@ -20,13 +20,13 @@
/*************************************************
File name: board.c
Description: support hc32f4a0-board init configure and driver/task/... init
Description: support edu-arm32-board init configure and driver/task/... init
Others:
History:
1. Date: 2022-09-08
Author: AIIT XUOS Lab
Modification:
1. support hc32f4a0-board InitBoardHardware
1. support edu-arm32-board InitBoardHardware
*************************************************/
#include <xizi.h>

View File

@ -12,7 +12,7 @@
/**
* @file board.h
* @brief define hc32f4a0-board init configure and start-up function
* @brief define edu-arm32-board init configure and start-up function
* @version 2.0
* @author AIIT XUOS Lab
* @date 2022-09-08
@ -20,14 +20,14 @@
/*************************************************
File name: board.h
Description: define hc32f4a0-board board init function and struct
Description: define edu-arm32-board board init function and struct
Others:
History:
1. Date: 2021-04-25
Author: AIIT XUOS Lab
Modification:
1. define hc32f4a0-board InitBoardHardware
2. define hc32f4a0-board data and bss struct
1. define edu-arm32-board InitBoardHardware
2. define edu-arm32-board data and bss struct
*************************************************/
#ifndef BOARD_H

View File

@ -2,10 +2,10 @@ export CROSS_COMPILE ?=/usr/bin/arm-none-eabi-
export CFLAGS := -mcpu=cortex-m4 -mthumb -mfpu=fpv4-sp-d16 -mfloat-abi=softfp -ffunction-sections -fdata-sections -Dgcc -O0 -gdwarf-2 -g -fgnu89-inline -Wa,-mimplicit-it=thumb -Werror
export AFLAGS := -c -mcpu=cortex-m4 -mthumb -mfpu=fpv4-sp-d16 -mfloat-abi=softfp -ffunction-sections -fdata-sections -x assembler-with-cpp -Wa,-mimplicit-it=thumb -gdwarf-2
export LFLAGS := -mcpu=cortex-m4 -mthumb -mfpu=fpv4-sp-d16 -mfloat-abi=softfp -ffunction-sections -fdata-sections -Wl,--gc-sections,-Map=XiZi_hc32f4a0.map,-cref,-u,Reset_Handler -T $(BSP_ROOT)/link.lds
export LFLAGS := -mcpu=cortex-m4 -mthumb -mfpu=fpv4-sp-d16 -mfloat-abi=softfp -ffunction-sections -fdata-sections -Wl,--gc-sections,-Map=XiZi-edu-arm32.map,-cref,-u,Reset_Handler -T $(BSP_ROOT)/link.lds
export CXXFLAGS := -mcpu=cortex-m4 -mthumb -mfpu=fpv4-sp-d16 -mfloat-abi=softfp -ffunction-sections -fdata-sections -Dgcc -O0 -gdwarf-2 -g -Werror
export APPLFLAGS := -mcpu=cortex-m4 -mthumb -mfpu=fpv4-sp-d16 -mfloat-abi=softfp -ffunction-sections -fdata-sections -Wl,--gc-sections,-Map=XiZi_app.map,-cref,-u, -T $(BSP_ROOT)/link_userspace.lds
export APPLFLAGS :=
export DEFINES := -DHAVE_CCONFIG_H -DHC32F4A0 -DUSE_DDL_DRIVER -DHAVE_SIGINFO

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 89 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 71 KiB

View File

Before

Width:  |  Height:  |  Size: 43 KiB

After

Width:  |  Height:  |  Size: 43 KiB

View File

@ -11,7 +11,7 @@
/**
* @file hardware_irq.c
* @brief support hc32f4a0-board irq configure
* @brief support edu-arm32-board irq configure
* @version 2.0
* @author AIIT XUOS Lab
* @date 2022-09-13
@ -19,13 +19,13 @@
/*************************************************
File name: hardware_irq.c
Description: support hc32f4a0-board irq configure
Description: support edu-arm32-board irq configure
Others:
History:
1. Date: 2022-09-13
Author: AIIT XUOS Lab
Modification:
1. support hc32f4a0-board irq
1. support edu-arm32-board irq
*************************************************/
/*******************************************************************************

Some files were not shown because too many files have changed in this diff Show More