Merge branch 'prepare_for_master' of https://gitlink.org.cn/xuos/xiuos into lorawan_develop

This commit is contained in:
Liu_Weichao 2023-07-19 09:33:34 +08:00
commit 02b676e910
44 changed files with 4603 additions and 1198 deletions

View File

@ -163,6 +163,8 @@ static int Ec200tIoctl(struct Adapter *adapter, int cmd, void *args)
serial_cfg.serial_parity_mode = PARITY_NONE;
serial_cfg.serial_bit_order = STOP_BITS_1;
serial_cfg.serial_invert_mode = NRZ_NORMAL;
//serial receive timeout 10s
serial_cfg.serial_timeout = 10000;
serial_cfg.is_ext_uart = 0;
#ifdef ADAPTER_EC200T_DRIVER_EXT_PORT
serial_cfg.is_ext_uart = 1;

View File

@ -1,22 +1,22 @@
/****************************************************************************
* boards/arm/imx6/sabre-lite/include/board.h
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you 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.
*
****************************************************************************/
/*
* 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 board.h
* @brief sabre-lite board.h file
* @version 1.0
* @author AIIT XUOS Lab
* @date 2023.05.15
*/
#ifndef __BOARDS_ARM_IMX6_SABRE_LITE_INCLUDE_BOARD_H
#define __BOARDS_ARM_IMX6_SABRE_LITE_INCLUDE_BOARD_H

View File

@ -1,22 +1,22 @@
/****************************************************************************
* boards/arm/imx6/sabre-lite/include/board_memorymap.h
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you 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.
*
****************************************************************************/
/*
* 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 board_memorymap.h
* @brief sabre-lite board memorymap
* @version 1.0
* @author AIIT XUOS Lab
* @date 2023.05.15
*/
#ifndef __BOARDS_ARM_IMX6_SABRE_LITE_INCLUDE_BOARD_MEMORYMAP_H
#define __BOARDS_ARM_IMX6_SABRE_LITE_INCLUDE_BOARD_MEMORYMAP_H

View File

@ -1,22 +1,22 @@
/****************************************************************************
* boards/arm/imx6/sabre-lite/src/imx_appinit.c
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you 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.
*
****************************************************************************/
/*
* 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 imx_appinit.c
* @brief sabre-lite imx_appinit.c file
* @version 1.0
* @author AIIT XUOS Lab
* @date 2023.05.15
*/
/****************************************************************************
* Included Files

View File

@ -1,22 +1,22 @@
/****************************************************************************
* boards/arm/imx6/sabre-lite/src/imx_autoleds.c
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you 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.
*
****************************************************************************/
/*
* 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 imx_autoleds.c
* @brief sabre-lite imx_autoleds.c file
* @version 1.0
* @author AIIT XUOS Lab
* @date 2023.05.15
*/
/* LEDs
*

View File

@ -1,22 +1,22 @@
/****************************************************************************
* boards/arm/imx6/sabre-lite/src/imx_boardinit.c
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you 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.
*
****************************************************************************/
/*
* 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 imx_boardinit.c
* @brief sabre-lite imx_boardinit.c file
* @version 1.0
* @author AIIT XUOS Lab
* @date 2023.05.15
*/
/****************************************************************************
* Included Files

View File

@ -1,22 +1,22 @@
/****************************************************************************
* boards/arm/imx6/sabre-lite/src/imx_bringup.c
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you 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.
*
****************************************************************************/
/*
* 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 imx_bringup.c
* @brief sabre-lite imx_bringup.c file
* @version 1.0
* @author AIIT XUOS Lab
* @date 2023.05.15
*/
/****************************************************************************
* Included Files

View File

@ -1,22 +1,22 @@
/****************************************************************************
* boards/arm/imx6/sabre-lite/src/imx_userleds.c
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you 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.
*
****************************************************************************/
/*
* 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 imx_userleds.c
* @brief sabre-lite imx_userleds.c file
* @version 1.0
* @author AIIT XUOS Lab
* @date 2023.05.15
*/
/****************************************************************************
* Included Files

View File

@ -1,22 +1,22 @@
/****************************************************************************
* boards/arm/imx6/sabre-lite/src/sabre-lite.h
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you 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.
*
****************************************************************************/
/*
* 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 sabre-lite.h
* @brief sabre-lite sabre-lite.h file
* @version 1.0
* @author AIIT XUOS Lab
* @date 2023.05.15
*/
#ifndef __BOARDS_ARM_IMX6_SABRE_LITE_SRC_SABRE_LITE_H
#define __BOARDS_ARM_IMX6_SABRE_LITE_SRC_SABRE_LITE_H

View File

@ -1,3 +1,3 @@
SRC_FILES := task.c schedule.c ipc.c
SRC_FILES := schedule.c ipc.c
include $(KERNEL_ROOT)/compiler.mk

View File

@ -0,0 +1,537 @@
/*
* 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: task.c
* @brief: file task.c
* @version: 1.0
* @author: AIIT XUOS Lab
* @date: 2023/05/18
*
*/
#include <task.h>
// 全局运行队列和本地运行队列
tcb_t *global_run_queue_head = NULL;
tcb_t *global_run_queue_tail = NULL;
tcb_t *local_run_queue_head[8] = {NULL};
tcb_t *local_run_queue_tail[8] = {NULL};
// 当前任务的指针
volatile tcb_t *current_task = NULL;
/*******************************************************************************
* : tcb_init
* :
* : tcb:,priority:,stack_size:
* :
*******************************************************************************/
void tcb_init(tcb_t *tcb, int priority, int stack_size) {
tcb->priority = priority;
tcb->state = TASK_CREATED;
tcb->message_queue = NULL;
tcb->stack = (uint8_t*)malloc(stack_size);
tcb->stack_size = stack_size;
tcb->stack_ptr = tcb->stack + stack_size - sizeof(context_t);
// 将任务的上下文保存在栈中
context_t *context = (context_t*)tcb->stack_ptr;
context_init(context, (void*)task_entry, tcb->stack_ptr);
}
/*******************************************************************************
* : tcb_destroy
* :
* : tcb:
* :
*******************************************************************************/
void tcb_destroy(tcb_t *tcb) {
free(tcb->stack_bottom);
tcb->stack_ptr = NULL;
tcb->stack_bottom = NULL;
tcb->stack_size = 0;
tcb->state = TASK_BLOCKED;
tcb->priority = 0;
tcb->next = NULL;
if (tcb->message_queue != NULL) {
message_queue_destroy(tcb->message_queue);
tcb->message_queue = NULL;
}
}
/*******************************************************************************
* : get_current_task
* :
* :
* :
*******************************************************************************/
tcb_t *get_current_task() {
return (tcb_t*)current_task;
}
/*******************************************************************************
* : get_local_run_queue_head
* :
* : cpu_id:cpu的id
* :
*******************************************************************************/
tcb_t *get_local_run_queue_head(int cpu_id) {
return local_run_queue_head[cpu_id];
}
/*******************************************************************************
* : add_to_global_run_queue
* :
* : tcb:
* :
*******************************************************************************/
void add_to_global_run_queue(tcb_t *tcb) {
// 将任务添加到全局运行队列的尾部
if (global_run_queue_head == NULL) {
global_run_queue_head = tcb;
global_run_queue_tail = tcb;
} else {
global_run_queue_tail->next = tcb;
global_run_queue_tail = tcb;
}
}
/*******************************************************************************
* : take_from_global_run_queue
* :
* :
* : tcb:
*******************************************************************************/
tcb_t *take_from_global_run_queue() {
// 从全局运行队列的头部取出一个任务
if (global_run_queue_head == NULL) {
return NULL;
} else {
tcb_t *tcb = global_run_queue_head;
global_run_queue_head = tcb->next;
if (global_run_queue_head == NULL) {
global_run_queue_tail = NULL;
}
return tcb;
}
}
/*******************************************************************************
* : add_to_local_run_queue
* :
* : tcb:,cpu_id:CPU id
* :
*******************************************************************************/
void add_to_local_run_queue(tcb_t *tcb, int cpu_id) {
// 将任务添加到本地运行队列的尾部
if (local_run_queue_head[cpu_id] == NULL) {
local_run_queue_head[cpu_id] = tcb;
local_run_queue_tail[cpu_id] = tcb;
} else {
local_run_queue_tail[cpu_id]->next = tcb;
local_run_queue_tail[cpu_id] = tcb;
}
}
/*******************************************************************************
* : take_from_local_run_queue
* :
* : cpu_id:CPU id
* :
*******************************************************************************/
tcb_t *take_from_local_run_queue(int cpu_id) {
// 从本地运行队列的头部取出一个任务
if (local_run_queue_head[cpu_id] == NULL) {
return NULL;
} else {
tcb_t *tcb = local_run_queue_head[cpu_id];
local_run_queue_head[cpu_id] = tcb->next;
if (local_run_queue_head[cpu_id] == NULL) {
local_run_queue_tail[cpu_id] = NULL;
}
return tcb;
}
}
/*******************************************************************************
* : move_current_task_to_global_run_queue
* : ,
* :
* :
*******************************************************************************/
void move_current_task_to_global_run_queue() {
int cpu_id = get_cpu_id();
tcb_t *tcb = (tcb_t*)current_task;
tcb->state = TASK_READY;
add_to_global_run_queue(tcb);
local_run_queue_head[cpu_id] = NULL;
local_run_queue_tail[cpu_id] = NULL;
current_task = NULL;
}
/*******************************************************************************
* : switch_to_next_task
* :
* :
* :
*******************************************************************************/
void switch_to_next_task() {
int cpu_id = get_cpu_id();
tcb_t *current_tcb = (tcb_t*)current_task;
tcb_t *next_tcb = take_from_local_run_queue(cpu_id);
if (next_tcb == NULL) {
next_tcb = take_from_global_run_queue();
}
if (next_tcb == NULL) {
// 如果没有可运行的任务,则将当前任务继续运行
return;
}
// 保存当前任务的上下文
if (current_tcb != NULL) {
current_tcb->stack_ptr = get_stack_pointer();
}
// 切换到下一个任务的上下文
current_task = next_tcb;
set_stack_pointer(next_tcb->stack_ptr);
// 如果切换到的任务是新的任务,需要执行任务初始化函数
if (current_tcb != next_tcb) {
next_tcb->state = TASK_RUNNING;
task_init(next_tcb);
}
}
/*******************************************************************************
* : task_init
* :
* : tcb:
* :
*******************************************************************************/
void task_init(tcb_t *tcb) {
// 创建消息队列
message_queue_t mq = (message_queue_t)malloc(sizeof(message_queue_t));
mq->buffer = (message_t)malloc(sizeof(message_t) * 16);
mq->capacity = 16;
mq->head = 0;
mq->tail = 0;
mq->count = 0;
tcb->message_queue = mq;
}
/*******************************************************************************
* : create_task
* :
* : priority:,stack_size:
* :
*******************************************************************************/
tcb_t *create_task(int priority, int stack_size) {
tcb_t *tcb = (tcb_t*)malloc(sizeof(tcb_t));
tcb_init(tcb, priority, stack_size);
add_to_global_run_queue(tcb);
return tcb;
}
/*******************************************************************************
* : destroy_task
* :
* : tcb:
* :
*******************************************************************************/
void destroy_task(tcb_t *tcb) {
tcb_destroy(tcb);
free(tcb);
}
/*******************************************************************************
* : send_message
* :
* : dest_tcb:,type:,data:
* :
*******************************************************************************/
void send_message(tcb_t *dest_tcb, int type, void *data) {
message_t message;
message.type = type;
message.data = data;
if (dest_tcb->message_queue == NULL) {
// 如果目标任务没有消息队列,则创建一个消息队列
dest_tcb->message_queue = message_queue_create(16);
}
// 将消息添加到目标任务的消息队列中
message_queue_push(dest_tcb->message_queue, &message);
}
/*******************************************************************************
* : receive_message
* :
* : type:,data:
* :
*******************************************************************************/
void receive_message(int type, void *data) {
tcb_t *current_tcb = (tcb_t*)current_task;
message_t message;
// 从当前任务的消息队列中取出消息
while (message_queue_pop(current_tcb->message_queue, &message) != 0) {
if (message.type == type) {
// 如果消息的类型匹配,则返回消息数据
memcpy(data, message.data, sizeof(void*));
return;
}
}
// 如果没有匹配的消息,则当前任务被阻塞,直到有匹配的消息为止
current_tcb->state = TASK_BLOCKED;
while (message_queue_pop(current_tcb->message_queue, &message) != 0) {
if (message.type == type) {
// 如果有匹配的消息,则返回消息数据,并将当前任务状态设置为就绪
memcpy(data, message.data, sizeof(void*));
current_tcb->state = TASK_READY;
return;
}
}
// 如果还是没有匹配的消息,则当前任务一直被阻塞
while (1) {
wait_for_interrupt();
}
}
/*******************************************************************************
* : message_queue_create
* :
* : capacity:
* :
*******************************************************************************/
message_queue_t *message_queue_create(int capacity) {
message_queue_t *mq = (message_queue_t*)malloc(sizeof(message_queue_t));
mq->buffer = (message_t*)malloc(sizeof(message_t) * capacity);
mq->capacity = capacity;
mq->head = 0;
mq->tail = 0;
mq->count = 0;
return mq;
}
/*******************************************************************************
* : message_queue_destroy
* :
* : mq:
* :
*******************************************************************************/
void message_queue_destroy(message_queue_t *mq) {
free(mq->buffer);
free(mq);
}
/*******************************************************************************
* : message_queue_push
* :
* : message_queue_t:,message_t:
* : 0:,-1:
*******************************************************************************/
int message_queue_push(message_queue_t *mq, message_t *message) {
if (mq->count >= mq->capacity) {
return -1; // 队列已满
}
mq->buffer[mq->tail] = *message;
mq->tail = (mq->tail + 1) % mq->capacity;
mq->count++;
return 0;
}
/*******************************************************************************
* : message_queue_pop
* :
* : message_queue_t:,message_t:
* : 0:,-1:
*******************************************************************************/
int message_queue_pop(message_queue_t *mq, message_t *message) {
if (mq->count <= 0) {
return -1; // 队列已空
}
*message = mq->buffer[mq->head];
mq->head = (mq->head + 1) % mq->capacity;
mq->count--;
return 0;
}
/*******************************************************************************
* : context_init
* :
* : message_queue_t:,message_t:
* : 0:,-1:
*******************************************************************************/
void context_init(context_t *context, void (*entry)(void), void *stack_ptr) {
context->cpsr = 0x10; // 设置 CPSR 的初始值
context->pc = (uint32_t)entry; // 设置 PC 的初始值为任务入口地址
context->r0 = (uint32_t)stack_ptr; // 设置 R0 的初始值为栈指针
context->r1 = 0; // 设置 R1 的初始值为 0
context->r2 = 0; // 设置 R2 的初始值为 0
context->r3 = 0; // 设置 R3 的初始值为 0
context->r4 = 0; // 设置 R4 的初始值为 0
context->r5 = 0; // 设置 R5 的初始值为 0
context->r6 = 0; // 设置 R6 的初始值为 0
context->r7 = 0; // 设置 R7 的初始值为 0
context->r8 = 0; // 设置 R8 的初始值为 0
context->r9 = 0; // 设置 R9 的初始值为 0
context->r10 = 0; // 设置 R10 的初始值为 0
context->r11 = 0; // 设置 R11 的初始值为 0
context->r12 = 0; // 设置 R12 的初始值为 0
context->sp = (uint32_t)stack_ptr; // 设置 SP 的初始值为栈指针
context->lr = (uint32_t)task_exit; // 设置 LR 的初始值为线程退出函数的地址
}
/*******************************************************************************
* : wait_for_interrupt
* :
* :
* :
*******************************************************************************/
void wait_for_interrupt() {
// 在实现中,可以使用 WFI 指令等待中断
__asm__ volatile("wfi");
}
/*******************************************************************************
* : get_cpu_id
* : CPU id
* :
* : cpu id
*******************************************************************************/
int get_cpu_id() {
uint32_t mpidr;
__asm__ volatile("mrc p15, 0, %0, c0, c0, 5" : "=r"(mpidr));
return mpidr & 0xff;
}
/*******************************************************************************
* : get_stack_pointer
* :
* :
* :
*******************************************************************************/
void *get_stack_pointer() {
// 在实现中,可以使用 ARM 的 SP 寄存器获取栈指针
void *sp;
__asm__ volatile("mov %0, sp" : "=r"(sp));
return sp;
}
/*******************************************************************************
* : set_stack_pointer
* :
* :
* :
*******************************************************************************/
void set_stack_pointer(void *sp) {
// 在实现中,可以使用 ARM 的 SP 寄存器设置栈指针
__asm__ volatile("mov sp, %0" : : "r"(sp));
}
/*******************************************************************************
* : add_interrupt_handler
* :
* : irq:,handler:,priority:
* :
*******************************************************************************/
void add_interrupt_handler(int irq, void (*handler)(void), int priority) {
uint32_t *vector_table = (uint32_t*)0x0;
// 将中断处理函数写入中断向量表中
vector_table[irq + 16] = (uint32_t)handler;
// 设置中断优先级
uint8_t priority_shift = 8 - __NVIC_PRIO_BITS;
uint32_t priority_mask = 0xff << priority_shift;
uint32_t priority_value = (priority << priority_shift) & priority_mask;
uint32_t *priority_reg = (uint32_t*)0xE000E400;
int index = irq / 4;
int offset = irq % 4;
priority_reg[index] &= ~(0xff << (offset * 8));
priority_reg[index] |= (priority_value << (offset * 8));
// 使能中断
uint32_t *enable_reg = (uint32_t*)0xE000E100;
enable_reg[irq / 32] |= 1 << (irq % 32);
}
/*******************************************************************************
* : enter_critical
* :
* :
* :
*******************************************************************************/
void enter_critical() {
// 在实现中,可以使用 ARM 的 CPSR 寄存器进入临界区
__asm__ volatile("cpsid i");
}
/*******************************************************************************
* : leave_critical
* :
* :
* :
*******************************************************************************/
void leave_critical() {
// 在实现中,可以使用 ARM 的 CPSR 寄存器离开临界区
__asm__ volatile("cpsie i");
}
/*******************************************************************************
* : task_exit
* : 退
* :
* :
*******************************************************************************/
void task_exit() {
// 切换到下一个任务
switch_to_next_task();
// 在实现中,可以使用 ARM 的 WFE 指令等待下一个中断
__asm__ volatile("wfe");
}
/*******************************************************************************
* : task_entry
* :
* :
* :
*******************************************************************************/
void task_entry() {
tcb_t *current_tcb = (tcb_t*)current_task;
current_tcb->state = TASK_RUNNING;
task_init(current_tcb);
while (1) {
switch_to_next_task();
}
}

View File

@ -0,0 +1,135 @@
/*
* 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: task.h
* @brief: file task.h
* @version: 1.0
* @author: AIIT XUOS Lab
* @date: 2023/05/18
*
*/
#ifndef __TASK_H__
#define __TASK_H__
#include <stdio.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
// 任务状态枚举类型
typedef enum {
TASK_CREATED, // 初始状态
TASK_READY, // 就绪状态
TASK_RUNNING, // 运行状态
TASK_BLOCKED, // 阻塞状态
} task_state_t;
// 任务控制块结构体
typedef struct tcb {
uint32_t *stack_ptr; // 任务堆栈指针
uint32_t *stack_bottom; // 任务堆栈底部指针
uint32_t stack_size; // 任务堆栈大小
task_state_t state; // 任务状态
int priority; // 任务优先级
struct tcb *next; // 指向下一个任务控制块的指针
struct message_queue *message_queue; // 消息队列
} tcb_t;
// 消息结构体
typedef struct message {
int type; // 消息类型
void *data; // 消息数据指针
} message_t;
// 消息队列结构体
typedef struct message_queue {
message_t *buffer; // 消息缓冲区
int capacity; // 缓冲区容量
int count; // 当前缓冲区中的消息数量
int head; // 队头指针
int tail; // 队尾指针
semaphore_t *semaphore; // 信号量,用于实现消息队列的同步机制
} message_queue_t;
// 信号量结构体
typedef struct semaphore {
int count; // 计数器
tcb_t *wait_list_head; // 指向等待信号量的任务控制块的指针
mutex_t mutex; // 互斥锁,用于保护信号量和等待队列的访问
} semaphore_t;
// 互斥锁结构体
typedef struct mutex {
int lock; // 锁标志
} mutex_t;
// 上下文结构体
typedef struct {
uint32_t cpsr; // 控制寄存器
uint32_t pc; // 程序计数器
uint32_t r0; // 寄存器 R0
uint32_t r1; // 寄存器 R1
uint32_t r2; // 寄存器 R2
uint32_t r3; // 寄存器 R3
uint32_t r4; // 寄存器 R4
uint32_t r5; // 寄存器 R5
uint32_t r6; // 寄存器 R6
uint32_t r7; // 寄存器 R7
uint32_t r8; // 寄存器 R8
uint32_t r9; // 寄存器 R9
uint32_t r10; // 寄存器 R10
uint32_t r11; // 寄存器 R11
uint32_t r12; // 寄存器 R12
uint32_t sp; // 栈指针
uint32_t lr; // 链接寄存器
} context_t;
void tcb_init(tcb_t *tcb, int priority, int stack_size);
void tcb_destroy(tcb_t *tcb);
tcb_t *get_current_task(void);
tcb_t *get_local_run_queue_head(int cpu_id);
void add_to_global_run_queue(tcb_t *tcb);
tcb_t *take_from_global_run_queue(void);
void add_to_local_run_queue(tcb_t *tcb, int cpu_id);
tcb_t *take_from_local_run_queue(int cpu_id);
void move_current_task_to_global_run_queue(void);
void switch_to_next_task(void);
void task_init(tcb_t *tcb);
tcb_t *create_task(int priority, int stack_size);
void destroy_task(tcb_t *tcb);
void send_message(tcb_t *dest_tcb, int type, void *data);
void receive_message(int type, void *data);
message_queue_t *message_queue_create(int capacity);
void message_queue_destroy(message_queue_t *mq);
int message_queue_push(message_queue_t *mq, message_t *message);
int message_queue_pop(message_queue_t *mq, message_t *message);
int message_queue_push(message_queue_t *mq, message_t *message);
void context_init(context_t *context, void (*entry)(void), void *stack_ptr);
void wait_for_interrupt(void);
int get_cpu_id(void);
void *get_stack_pointer(void);
void set_stack_pointer(void *sp);
void add_interrupt_handler(int irq, void (*handler)(void), int priority);
void enter_critical(void);
void leave_critical(void);
void task_exit(void);
void task_entry(void);
#endif

View File

@ -11,7 +11,7 @@ menuconfig BSP_USING_SPI
bool "Using SPI device"
default n
select RESOURCES_SPI
select BSP_USING_DMA
select BSP_USING_DMA
if BSP_USING_SPI
source "$BSP_DIR/third_party_driver/spi/Kconfig"
endif
@ -117,6 +117,7 @@ menuconfig BSP_USING_WIZCHIP
bool "Using w5500 as network device"
default n
select RESOURCES_WIZCHIP
select BSP_USING_SPI
if BSP_USING_WIZCHIP
source "$BSP_DIR/third_party_driver/ethernet/Kconfig"
endif

View File

@ -1,15 +1,17 @@
# Kconfig file
config BSP_USING_W5500
bool "Using w5500 "
default y
bool "Using w5500"
default y
# if BSP_USING_W5500
config BSP_WIZ_RST_PIN
int
default 13
config BSP_WIZ_RST_PIN
int
default 13
config BSP_WIZ_INT_PIN
int
default 14
# endif
config BSP_WIZ_INT_PIN
int
default 14
config BSP_WIZ_USE_IPERF
bool "Using iperf"
default y

View File

@ -1,3 +1,3 @@
SRC_FILES := socket.c connect_w5500.c w5500.c wizchip_conf.c spi_interface.c wiz_ping.c
SRC_FILES := socket.c connect_w5500.c w5500.c wizchip_conf.c spi_interface.c wiz_ping.c connect_w5500_test.c wiz_iperf.c
include $(KERNEL_ROOT)/compiler.mk

View File

@ -23,47 +23,53 @@ extern void spi_select_cs(void);
extern void spi_deselete_cs(void);
// global configurations for w5500 tcp connection
const uint32_t g_wiznet_buf_size = 2048;
uint32_t get_gbuf_size() {
static const uint32_t g_wiznet_buf_size = 2048;
return g_wiznet_buf_size;
}
static wiz_NetInfo g_wiz_netinfo = {.mac = {0x00, 0x08, 0xdc, 0x11, 0x11, 0x11},
.ip = {192, 168, 131, 42},
.sn = {255, 255, 254, 0},
.gw = {192, 168, 130, 1},
.dns = {0, 0, 0, 0},
.dhcp = NETINFO_STATIC};
wiz_NetInfo *get_gnetinfo() {
static wiz_NetInfo g_wiz_netinfo = {.mac = {0x00, 0x08, 0xdc, 0x11, 0x11, 0x11},
.ip = {192, 168, 130, 77},
.sn = {255, 255, 254, 0},
.gw = {192, 168, 130, 1},
.dns = {0, 0, 0, 0},
.dhcp = NETINFO_STATIC};
return &g_wiz_netinfo;
}
int network_init() {
wiz_NetInfo check_wiz_netinfo;
check_wiz_netinfo.dhcp = NETINFO_STATIC;
ctlnetwork(CN_SET_NETINFO, (void *)&g_wiz_netinfo);
ctlnetwork(CN_SET_NETINFO, (void *)get_gnetinfo());
ctlnetwork(CN_GET_NETINFO, (void *)&check_wiz_netinfo);
if (memcmp(&g_wiz_netinfo, &check_wiz_netinfo, sizeof(wiz_NetInfo)) != 0) {
if (memcmp(get_gnetinfo(), &check_wiz_netinfo, sizeof(wiz_NetInfo)) != 0) {
KPrintf(
"mac: %d; ip: %d; gw: %d; sn: %d; dns: %d; dhcp: %d;\n",
memcmp(&g_wiz_netinfo.mac, &check_wiz_netinfo.mac, sizeof(uint8_t) * 6),
memcmp(&g_wiz_netinfo.ip, &check_wiz_netinfo.ip, sizeof(uint8_t) * 4),
memcmp(&g_wiz_netinfo.sn, &check_wiz_netinfo.sn, sizeof(uint8_t) * 4),
memcmp(&g_wiz_netinfo.gw, &check_wiz_netinfo.gw, sizeof(uint8_t) * 4),
memcmp(&g_wiz_netinfo.dns, &check_wiz_netinfo.dns, sizeof(uint8_t) * 4),
memcmp(&g_wiz_netinfo.dhcp, &check_wiz_netinfo.dhcp, sizeof(uint8_t)));
memcmp(&get_gnetinfo()->mac, &check_wiz_netinfo.mac, sizeof(uint8_t) * 6),
memcmp(&get_gnetinfo()->ip, &check_wiz_netinfo.ip, sizeof(uint8_t) * 4),
memcmp(&get_gnetinfo()->sn, &check_wiz_netinfo.sn, sizeof(uint8_t) * 4),
memcmp(&get_gnetinfo()->gw, &check_wiz_netinfo.gw, sizeof(uint8_t) * 4),
memcmp(&get_gnetinfo()->dns, &check_wiz_netinfo.dns, sizeof(uint8_t) * 4),
memcmp(&get_gnetinfo()->dhcp, &check_wiz_netinfo.dhcp, sizeof(uint8_t)));
KPrintf("WIZCHIP set network information fail.\n");
return ERROR;
}
uint8_t tmpstr[6];
ctlwizchip(CW_GET_ID, (void *)tmpstr);
KPrintf("=== %s NET CONF ===\r\n", (char *)tmpstr);
KPrintf("MAC: %02X:%02X:%02X:%02X:%02X:%02X\r\n", g_wiz_netinfo.mac[0],
g_wiz_netinfo.mac[1], g_wiz_netinfo.mac[2], g_wiz_netinfo.mac[3],
g_wiz_netinfo.mac[4], g_wiz_netinfo.mac[5]);
KPrintf("SIP: %d.%d.%d.%d\r\n", g_wiz_netinfo.ip[0], g_wiz_netinfo.ip[1],
g_wiz_netinfo.ip[2], g_wiz_netinfo.ip[3]);
KPrintf("GAR: %d.%d.%d.%d\r\n", g_wiz_netinfo.gw[0], g_wiz_netinfo.gw[1],
g_wiz_netinfo.gw[2], g_wiz_netinfo.gw[3]);
KPrintf("SUB: %d.%d.%d.%d\r\n", g_wiz_netinfo.sn[0], g_wiz_netinfo.sn[1],
g_wiz_netinfo.sn[2], g_wiz_netinfo.sn[3]);
KPrintf("DNS: %d.%d.%d.%d\r\n", g_wiz_netinfo.dns[0], g_wiz_netinfo.dns[1],
g_wiz_netinfo.dns[2], g_wiz_netinfo.dns[3]);
KPrintf("MAC: %02X:%02X:%02X:%02X:%02X:%02X\r\n", get_gnetinfo()->mac[0],
get_gnetinfo()->mac[1], get_gnetinfo()->mac[2], get_gnetinfo()->mac[3],
get_gnetinfo()->mac[4], get_gnetinfo()->mac[5]);
KPrintf("SIP: %d.%d.%d.%d\r\n", get_gnetinfo()->ip[0], get_gnetinfo()->ip[1],
get_gnetinfo()->ip[2], get_gnetinfo()->ip[3]);
KPrintf("GAR: %d.%d.%d.%d\r\n", get_gnetinfo()->gw[0], get_gnetinfo()->gw[1],
get_gnetinfo()->gw[2], get_gnetinfo()->gw[3]);
KPrintf("SUB: %d.%d.%d.%d\r\n", get_gnetinfo()->sn[0], get_gnetinfo()->sn[1],
get_gnetinfo()->sn[2], get_gnetinfo()->sn[3]);
KPrintf("DNS: %d.%d.%d.%d\r\n", get_gnetinfo()->dns[0], get_gnetinfo()->dns[1],
get_gnetinfo()->dns[2], get_gnetinfo()->dns[3]);
KPrintf("======================\r\n");
return EOK;
@ -255,312 +261,4 @@ int HwWiznetInit(void) {
network_init();
return EOK;
}
/****************** basic functions ********************/
enum TCP_OPTION {
SEND_DATA = 0,
RECV_DATA,
};
uint32_t wiz_client_op(uint8_t sn, uint8_t *buf, uint32_t buf_size,
uint8_t dst_ip[4], uint16_t dst_port,
enum TCP_OPTION opt) {
// assert(buf_size <= g_wiznet_buf_size);
int32_t ret;
switch (getSn_SR(sn)) {
case SOCK_CLOSE_WAIT:
wiz_sock_disconnect(sn);
break;
case SOCK_CLOSED:
wiz_socket(sn, Sn_MR_TCP, 5000, 0x00);
break;
case SOCK_INIT:
KPrintf("[SOCKET CLIENT] sock init.\n");
wiz_sock_connect(sn, dst_ip, dst_port);
break;
case SOCK_ESTABLISHED:
if (getSn_IR(sn) & Sn_IR_CON) {
printf("[SOCKET CLIENT] %d:Connected\r\n", sn);
setSn_IR(sn, Sn_IR_CON);
}
if (opt == SEND_DATA) {
uint32_t sent_size = 0;
ret = wiz_sock_send(sn, buf, buf_size);
if (ret < 0) {
wiz_sock_close(sn);
return ret;
}
} else if (opt == RECV_DATA) {
uint32_t size = 0;
if ((size = getSn_RX_RSR(sn)) > 0) {
if (size > buf_size) size = buf_size;
ret = wiz_sock_recv(sn, buf, size);
if (ret <= 0) return ret;
}
}
break;
default:
break;
}
}
void wiz_client_op_test(int argc, char *argv[]) {
/* argv[1]: ip ip addr
* argv[2]: port port number
* argv[3]: msg send msg
* argv[4]: count test times,if no this parameter,default 10 times
*/
if (argc < 4)
{
KPrintf("wiz_client_op_test error\n");
return;
}
uint8_t client_sock = 2;
uint32_t tmp_ip[4];
uint8_t ip[4];
uint64_t pCount = 10;
uint8_t buf[g_wiznet_buf_size];
uint16_t port;
sscanf(argv[1], "%d.%d.%d.%d", &tmp_ip[0], &tmp_ip[1], &tmp_ip[2], &tmp_ip[3]);
ip[0] = (uint8_t)tmp_ip[0];
ip[1] = (uint8_t)tmp_ip[1];
ip[2] = (uint8_t)tmp_ip[2];
ip[3] = (uint8_t)tmp_ip[3];
port = atoi(argv[2]);
KPrintf("wiz client to wiz_server, send to %d.%d.%d.%d %d\n", // tip info
ip[0], ip[1], ip[2], ip[3], port);
if (argc >= 5){
pCount = atoi(argv[4]);
}
for(uint64_t i = 0; i < pCount; i++)
{
wiz_client_op(client_sock, argv[3], strlen(argv[3]), ip, port, SEND_DATA);
MdelayKTask(10);
// waiting for a responding.
wiz_client_op(client_sock, buf, g_wiznet_buf_size, ip, port, RECV_DATA);
KPrintf("received msg: %s\n", buf);
memset(buf, 0, g_wiznet_buf_size);
}
}
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN),
wiz_client_op, wiz_client_op_test,
wiz_sock_recv or wiz_sock_send data as tcp client);
int32_t wiz_server_op(uint8_t sn, uint8_t *buf, uint32_t buf_size,
uint16_t port, enum TCP_OPTION opt) {
int32_t ret = 0;
uint16_t size = 0, sentsize = 0;
switch (getSn_SR(sn)) {
case SOCK_ESTABLISHED:
if (getSn_IR(sn) & Sn_IR_CON) {
printf("%d:Connected\r\n", sn);
setSn_IR(sn, Sn_IR_CON);
}
if (opt == SEND_DATA) {
uint32_t sent_size = 0;
ret = wiz_sock_send(sn, buf, buf_size);
if (ret < 0) {
wiz_sock_close(sn);
return ret;
}
} else if (opt == RECV_DATA) {
uint32_t size = 0;
if ((size = getSn_RX_RSR(sn)) > 0) {
if (size > buf_size) size = buf_size;
ret = wiz_sock_recv(sn, buf, size);
return ret;
}
}
break;
case SOCK_CLOSE_WAIT:
printf("%d:CloseWait\r\n", sn);
if ((ret = wiz_sock_disconnect(sn)) != SOCK_OK) return ret;
printf("%d:Closed\r\n", sn);
break;
case SOCK_INIT:
printf("%d:Listen, port [%d]\r\n", sn, port);
if ((ret = wiz_sock_listen(sn)) != SOCK_OK) return ret;
break;
case SOCK_CLOSED:
printf("%d:LBTStart\r\n", sn);
if ((ret = wiz_socket(sn, Sn_MR_TCP, port, 0x00)) != sn) return ret;
printf("%d:Opened\r\n", sn);
break;
default:
break;
}
return 0;
}
void wiz_server(void *param) {
uint16_t port = *(uint16_t *)param;
KPrintf("wiz server, listen port: %d\n", port);
uint8_t buf[g_wiznet_buf_size];
memset(buf, 0, g_wiznet_buf_size);
int ret = 0;
uint32_t size = 0;
while (1) {
ret = wiz_server_op(0, buf, g_wiznet_buf_size, port, RECV_DATA);
while(buf[size] != 0){
size ++;
}
if (ret > 0) {
KPrintf("received %d bytes: %s\n", size, buf);
wiz_server_op(0, buf, g_wiznet_buf_size, port, SEND_DATA);
memset(buf, 0, g_wiznet_buf_size);
}
size = 0;
}
}
void wiz_server_test(uint16_t port) {
/* argv[1]: port
*/
int32 wiz_server_id =
KTaskCreate("wiz_server", wiz_server, (void *)&port, 4096, 25);
x_err_t flag = StartupKTask(wiz_server_id);
if (flag != EOK) {
KPrintf("StartupKTask wiz_server_id failed .\n");
}
}
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_FUNC) |
SHELL_CMD_PARAM_NUM(1),
wiz_server_op, wiz_server_test,
wiz_sock_recv or wiz_sock_send data as tcp server);
void loopback_udps(int argc, char *argv[])
{
/* argv[1]: remote_ip ip address of remote udp
* argv[2]: remote_port the port number of the remote udp
* argv[2]: local_port the port number of the local udp
*/
uint32_t tmp_ip[4];
uint8_t remote_ip[4];
uint16_t remote_port, local_port;
uint8_t buffer[g_wiznet_buf_size];
uint16_t len = 0;
if (argc < 4)
{
KPrintf("loopback_udps test error\n");
return;
}
sscanf(argv[1], "%d.%d.%d.%d", &tmp_ip[0], &tmp_ip[1], &tmp_ip[2], &tmp_ip[3]);
for(int i = 0;i < 4; i++)
{
remote_ip[i] = (uint8_t)tmp_ip[i];
}
remote_port = atoi(argv[2]);
local_port = atoi(argv[3]);
while(1)
{
switch (getSn_SR(0))
{
case SOCK_UDP:
if(getSn_IR(0) & Sn_IR_RECV)
{
setSn_IR(0, Sn_IR_RECV);
}
if((len = getSn_RX_RSR(0))>0)
{
memset(buffer,0,len+1);
wiz_sock_recvfrom(0, buffer, len, remote_ip, (uint16_t *)&remote_port);
printf("received msg: %s\n", buffer);
wiz_sock_sendto(0, buffer, len, remote_ip, remote_port);
}
break;
case SOCK_CLOSED:
printf("LBUStart\r\n");
wiz_socket(0, Sn_MR_UDP, local_port, 0);
break;
}
}
}
/* wiz_udp remote_ip remote_port local_port */
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN),
wiz_udp, loopback_udps, w5500 upd test);
void ifconfig() {
wiz_NetInfo wiz_netinfo;
ctlnetwork(CN_GET_NETINFO, (void *)&wiz_netinfo);
uint8_t tmpstr[6];
ctlwizchip(CW_GET_ID, (void *)tmpstr);
KPrintf("=== %s NET CONF ===\r\n", (char *)tmpstr);
KPrintf("MAC: %02X:%02X:%02X:%02X:%02X:%02X\r\n", wiz_netinfo.mac[0],
wiz_netinfo.mac[1], wiz_netinfo.mac[2], wiz_netinfo.mac[3],
wiz_netinfo.mac[4], wiz_netinfo.mac[5]);
KPrintf("SIP: %d.%d.%d.%d\r\n", wiz_netinfo.ip[0], wiz_netinfo.ip[1],
wiz_netinfo.ip[2], wiz_netinfo.ip[3]);
KPrintf("GAR: %d.%d.%d.%d\r\n", wiz_netinfo.gw[0], wiz_netinfo.gw[1],
wiz_netinfo.gw[2], wiz_netinfo.gw[3]);
KPrintf("SUB: %d.%d.%d.%d\r\n", wiz_netinfo.sn[0], wiz_netinfo.sn[1],
wiz_netinfo.sn[2], wiz_netinfo.sn[3]);
KPrintf("DNS: %d.%d.%d.%d\r\n", wiz_netinfo.dns[0], wiz_netinfo.dns[1],
wiz_netinfo.dns[2], wiz_netinfo.dns[3]);
KPrintf("======================\r\n");
}
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_FUNC),
ifconfig, ifconfig, printf w5500 configurations);
void char_arr_assign(uint8_t *dst, uint32_t *src, int len) {
for (int i = 0; i < len; ++i) {
dst[i] = (uint8_t)(src[i]);
}
}
char *network_param_name[] = {"ip", "sn", "gw"};
void config_w5500_network(int argc, char *argv[]) {
if (argc < 2) {
KPrintf("[W5500] Network config require params.\n");
return;
}
wiz_NetInfo wiz_netinfo;
memcpy(&wiz_netinfo, &g_wiz_netinfo, sizeof(wiz_NetInfo));
int cur_arg_idx = 1;
while (argv[cur_arg_idx] != NULL) {
if (argv[cur_arg_idx + 1] == NULL) {
KPrintf("[W5500] Network config %s requires value.\n", argv[cur_arg_idx]);
return;
}
uint32_t tmp_arr[4];
sscanf(argv[cur_arg_idx + 1], "%d.%d.%d.%d", &tmp_arr[0], &tmp_arr[1],
&tmp_arr[2], &tmp_arr[3]);
if (memcmp(argv[cur_arg_idx], network_param_name[0], 2 * sizeof(char)) ==
0) {
char_arr_assign(wiz_netinfo.ip, tmp_arr, 4);
} else if (memcmp(argv[cur_arg_idx], network_param_name[1],
2 * sizeof(char)) == 0) {
char_arr_assign(wiz_netinfo.sn, tmp_arr, 4);
} else if (memcmp(argv[cur_arg_idx], network_param_name[2],
2 * sizeof(char)) == 0) {
char_arr_assign(wiz_netinfo.gw, tmp_arr, 4);
} else {
KPrintf("[W5500] Invalid network param.\n");
}
cur_arg_idx += 2;
}
ctlnetwork(CN_SET_NETINFO, (void *)&wiz_netinfo);
KPrintf("[W5500] Network config success.\n", argv[cur_arg_idx]);
ifconfig();
}
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN),
config_w5500_network, config_w5500_network,
set w5500 configurations);
}

View File

@ -0,0 +1,314 @@
#include <dev_pin.h>
#include <string.h>
#include <stdlib.h>
#include "socket.h"
extern uint32_t get_gbuf_size();
extern wiz_NetInfo *get_gnetinfo();
enum TCP_OPTION {
SEND_DATA = 0,
RECV_DATA,
};
uint32_t wiz_client_op(uint8_t sn, uint8_t *buf, uint32_t buf_size,
uint8_t dst_ip[4], uint16_t dst_port,
enum TCP_OPTION opt) {
// assert(buf_size <= get_gbuf_size());
int32_t ret;
switch (getSn_SR(sn)) {
case SOCK_CLOSE_WAIT:
wiz_sock_disconnect(sn);
break;
case SOCK_CLOSED:
wiz_socket(sn, Sn_MR_TCP, 5000, 0x00);
break;
case SOCK_INIT:
KPrintf("[SOCKET CLIENT] sock init.\n");
wiz_sock_connect(sn, dst_ip, dst_port);
break;
case SOCK_ESTABLISHED:
if (getSn_IR(sn) & Sn_IR_CON) {
printf("[SOCKET CLIENT] %d:Connected\r\n", sn);
setSn_IR(sn, Sn_IR_CON);
}
if (opt == SEND_DATA) {
uint32_t sent_size = 0;
ret = wiz_sock_send(sn, buf, buf_size);
if (ret < 0) {
wiz_sock_close(sn);
return ret;
}
} else if (opt == RECV_DATA) {
uint32_t size = 0;
if ((size = getSn_RX_RSR(sn)) > 0) {
if (size > buf_size) size = buf_size;
ret = wiz_sock_recv(sn, buf, size);
if (ret <= 0) return ret;
}
}
break;
default:
break;
}
}
void wiz_client_op_test(int argc, char *argv[]) {
/* argv[1]: ip ip addr
* argv[2]: port port number
* argv[3]: msg send msg
* argv[4]: count test times,if no this parameter,default 10 times
*/
if (argc < 4)
{
KPrintf("wiz_client_op_test error\n");
return;
}
uint8_t client_sock = 2;
uint32_t tmp_ip[4];
uint8_t ip[4];
uint64_t pCount = 10;
uint8_t buf[get_gbuf_size()];
uint16_t port;
sscanf(argv[1], "%d.%d.%d.%d", &tmp_ip[0], &tmp_ip[1], &tmp_ip[2], &tmp_ip[3]);
ip[0] = (uint8_t)tmp_ip[0];
ip[1] = (uint8_t)tmp_ip[1];
ip[2] = (uint8_t)tmp_ip[2];
ip[3] = (uint8_t)tmp_ip[3];
port = atoi(argv[2]);
KPrintf("wiz client to wiz_server, send to %d.%d.%d.%d %d\n", // tip info
ip[0], ip[1], ip[2], ip[3], port);
if (argc >= 5){
pCount = atoi(argv[4]);
}
for(uint64_t i = 0; i < pCount; i++)
{
wiz_client_op(client_sock, argv[3], strlen(argv[3]), ip, port, SEND_DATA);
MdelayKTask(10);
// waiting for a responding.
wiz_client_op(client_sock, buf, get_gbuf_size(), ip, port, RECV_DATA);
KPrintf("received msg: %s\n", buf);
memset(buf, 0, get_gbuf_size());
}
}
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN),
wiz_client_op, wiz_client_op_test,
wiz_sock_recv or wiz_sock_send data as tcp client);
int32_t wiz_server_op(uint8_t sn, uint8_t *buf, uint32_t buf_size,
uint16_t port, enum TCP_OPTION opt) {
int32_t ret = 0;
uint16_t size = 0, sentsize = 0;
switch (getSn_SR(sn)) {
case SOCK_ESTABLISHED:
if (getSn_IR(sn) & Sn_IR_CON) {
printf("%d:Connected\r\n", sn);
setSn_IR(sn, Sn_IR_CON);
}
if (opt == SEND_DATA) {
uint32_t sent_size = 0;
ret = wiz_sock_send(sn, buf, buf_size);
if (ret < 0) {
wiz_sock_close(sn);
return ret;
}
} else if (opt == RECV_DATA) {
uint32_t size = 0;
if ((size = getSn_RX_RSR(sn)) > 0) {
if (size > buf_size) size = buf_size;
ret = wiz_sock_recv(sn, buf, size);
return ret;
}
}
break;
case SOCK_CLOSE_WAIT:
printf("%d:CloseWait\r\n", sn);
if ((ret = wiz_sock_disconnect(sn)) != SOCK_OK) return ret;
printf("%d:Closed\r\n", sn);
break;
case SOCK_INIT:
printf("%d:Listen, port [%d]\r\n", sn, port);
if ((ret = wiz_sock_listen(sn)) != SOCK_OK) return ret;
break;
case SOCK_CLOSED:
printf("%d:LBTStart\r\n", sn);
if ((ret = wiz_socket(sn, Sn_MR_TCP, port, 0x00)) != sn) return ret;
printf("%d:Opened\r\n", sn);
break;
default:
break;
}
return 0;
}
void wiz_server(void *param) {
uint16_t port = *(uint16_t *)param;
KPrintf("wiz server, listen port: %d\n", port);
uint8_t buf[get_gbuf_size()];
memset(buf, 0, get_gbuf_size());
int ret = 0;
uint32_t size = 0;
while (1) {
ret = wiz_server_op(0, buf, get_gbuf_size(), port, RECV_DATA);
while(buf[size] != 0){
size ++;
}
if (ret > 0) {
KPrintf("received %d bytes: %s\n", size, buf);
wiz_server_op(0, buf, get_gbuf_size(), port, SEND_DATA);
memset(buf, 0, get_gbuf_size());
}
size = 0;
}
}
void wiz_server_test(uint16_t port) {
/* argv[1]: port
*/
int32 wiz_server_id =
KTaskCreate("wiz_server", wiz_server, (void *)&port, 4096, 25);
x_err_t flag = StartupKTask(wiz_server_id);
if (flag != EOK) {
KPrintf("StartupKTask wiz_server_id failed .\n");
}
}
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_FUNC) |
SHELL_CMD_PARAM_NUM(1),
wiz_server_op, wiz_server_test,
wiz_sock_recv or wiz_sock_send data as tcp server);
void loopback_udps(int argc, char *argv[])
{
/* argv[1]: remote_ip ip address of remote udp
* argv[2]: remote_port the port number of the remote udp
* argv[2]: local_port the port number of the local udp
*/
uint32_t tmp_ip[4];
uint8_t remote_ip[4];
uint16_t remote_port, local_port;
uint8_t buffer[get_gbuf_size()];
uint16_t len = 0;
if (argc < 4)
{
KPrintf("loopback_udps test error\n");
return;
}
sscanf(argv[1], "%d.%d.%d.%d", &tmp_ip[0], &tmp_ip[1], &tmp_ip[2], &tmp_ip[3]);
for(int i = 0;i < 4; i++)
{
remote_ip[i] = (uint8_t)tmp_ip[i];
}
remote_port = atoi(argv[2]);
local_port = atoi(argv[3]);
while(1)
{
switch (getSn_SR(0))
{
case SOCK_UDP:
if(getSn_IR(0) & Sn_IR_RECV)
{
setSn_IR(0, Sn_IR_RECV);
}
if((len = getSn_RX_RSR(0))>0)
{
memset(buffer, 0, len + 1);
wiz_sock_recvfrom(0, buffer, len, remote_ip, (uint16_t *)&remote_port);
printf("received msg: %s\n", buffer);
wiz_sock_sendto(0, buffer, len, remote_ip, remote_port);
}
break;
case SOCK_CLOSED:
printf("LBUStart\r\n");
wiz_socket(0, Sn_MR_UDP, local_port, 0);
break;
}
}
}
/* wiz_udp remote_ip remote_port local_port */
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN),
wiz_udp, loopback_udps, w5500 upd test);
void ifconfig() {
wiz_NetInfo wiz_netinfo;
ctlnetwork(CN_GET_NETINFO, (void *)&wiz_netinfo);
uint8_t tmpstr[6];
ctlwizchip(CW_GET_ID, (void *)tmpstr);
KPrintf("=== %s NET CONF ===\r\n", (char *)tmpstr);
KPrintf("MAC: %02X:%02X:%02X:%02X:%02X:%02X\r\n", wiz_netinfo.mac[0],
wiz_netinfo.mac[1], wiz_netinfo.mac[2], wiz_netinfo.mac[3],
wiz_netinfo.mac[4], wiz_netinfo.mac[5]);
KPrintf("SIP: %d.%d.%d.%d\r\n", wiz_netinfo.ip[0], wiz_netinfo.ip[1],
wiz_netinfo.ip[2], wiz_netinfo.ip[3]);
KPrintf("GAR: %d.%d.%d.%d\r\n", wiz_netinfo.gw[0], wiz_netinfo.gw[1],
wiz_netinfo.gw[2], wiz_netinfo.gw[3]);
KPrintf("SUB: %d.%d.%d.%d\r\n", wiz_netinfo.sn[0], wiz_netinfo.sn[1],
wiz_netinfo.sn[2], wiz_netinfo.sn[3]);
KPrintf("DNS: %d.%d.%d.%d\r\n", wiz_netinfo.dns[0], wiz_netinfo.dns[1],
wiz_netinfo.dns[2], wiz_netinfo.dns[3]);
KPrintf("======================\r\n");
}
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_FUNC),
ifconfig, ifconfig, printf w5500 configurations);
void char_arr_assign(uint8_t *dst, uint32_t *src, int len) {
for (int i = 0; i < len; ++i) {
dst[i] = (uint8_t)(src[i]);
}
}
char *network_param_name[] = {"ip", "sn", "gw"};
void config_w5500_network(int argc, char *argv[]) {
if (argc < 2) {
KPrintf("[W5500] Network config require params.\n");
return;
}
wiz_NetInfo wiz_netinfo;
memcpy(&wiz_netinfo, get_gnetinfo(), sizeof(wiz_NetInfo));
int cur_arg_idx = 1;
while (argv[cur_arg_idx] != NULL) {
if (argv[cur_arg_idx + 1] == NULL) {
KPrintf("[W5500] Network config %s requires value.\n", argv[cur_arg_idx]);
return;
}
uint32_t tmp_arr[4];
sscanf(argv[cur_arg_idx + 1], "%d.%d.%d.%d", &tmp_arr[0], &tmp_arr[1],
&tmp_arr[2], &tmp_arr[3]);
if (memcmp(argv[cur_arg_idx], network_param_name[0], 2 * sizeof(char)) ==
0) {
char_arr_assign(wiz_netinfo.ip, tmp_arr, 4);
} else if (memcmp(argv[cur_arg_idx], network_param_name[1],
2 * sizeof(char)) == 0) {
char_arr_assign(wiz_netinfo.sn, tmp_arr, 4);
} else if (memcmp(argv[cur_arg_idx], network_param_name[2],
2 * sizeof(char)) == 0) {
char_arr_assign(wiz_netinfo.gw, tmp_arr, 4);
} else {
KPrintf("[W5500] Invalid network param.\n");
}
cur_arg_idx += 2;
}
ctlnetwork(CN_SET_NETINFO, (void *)&wiz_netinfo);
KPrintf("[W5500] Network config success.\n", argv[cur_arg_idx]);
ifconfig();
}
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN),
config_w5500_network, config_w5500_network,
set w5500 configurations);

View File

@ -0,0 +1,465 @@
#include "socket.h"
#include "w5500.h"
#include "connect_w5500.h"
#ifdef BSP_WIZ_USE_IPERF
#define IPERF_PORT 5001
#define IPERF_BUFSZ (4 * 1024)
#define IPERF_MODE_STOP 0
#define IPERF_MODE_SERVER 1
#define IPERF_MODE_CLIENT 2
typedef struct{
int mode;
uint8 host[4];
uint16 port;
} IPERF_PARAM;
static IPERF_PARAM param = {IPERF_MODE_STOP, {0, 0, 0, 0}, IPERF_PORT};
static void iperf_udp_client(void *thread_param)
{
int sock;
uint8 *buffer;
uint16 local_port = 4840;
uint32 packet_count = 0;
uint32 tick;
int send_size;
send_size = IPERF_BUFSZ > 1470 ? 1470 : IPERF_BUFSZ;
sock = 0; // w5500支持8个socket独立工作todo socket端口管理
// setSn_TXBUF_SIZE(sock, 16);
// setSn_RXBUF_SIZE(sock, 16);
buffer = malloc(IPERF_BUFSZ);
if (buffer == NULL){
printf("[%s:%d] malloc failed\n", __FILE__, __LINE__);
return;
}
for(int i = 0; i < IPERF_BUFSZ; i++)
buffer[i] = i % 10;
KPrintf("iperf udp mode run...\n");
while (param.mode != IPERF_MODE_STOP){
switch(getSn_SR(sock)){
case SOCK_CLOSED:
wiz_socket(sock, Sn_MR_UDP, local_port, 0x00);
break;
case SOCK_UDP:
packet_count++;
tick = CurrentTicksGain();
buffer[0] = (uint8)(packet_count >> 24);
buffer[1] = (uint8)(packet_count >> 16);
buffer[2] = (uint8)(packet_count >> 8);
buffer[3] = (uint8)(packet_count);
buffer[4] = (uint8)((tick / TICK_PER_SECOND) >> 24);
buffer[5] = (uint8)((tick / TICK_PER_SECOND) >> 16);
buffer[6] = (uint8)((tick / TICK_PER_SECOND) >> 8);
buffer[7] = (uint8)((tick / TICK_PER_SECOND));
buffer[8] = (uint8)(((tick % TICK_PER_SECOND) * 1000) >> 24);
buffer[9] = (uint8)(((tick % TICK_PER_SECOND) * 1000) >> 16);
buffer[10] = (uint8)(((tick % TICK_PER_SECOND) * 1000) >> 8);
buffer[11] = (uint8)(((tick % TICK_PER_SECOND) * 1000));
wiz_sock_sendto(sock, buffer, send_size, param.host, param.port);
break;
}
}
if(getSn_SR(sock) != SOCK_CLOSED) wiz_sock_close(sock);
free(buffer);
KPrintf("iperf udp mode exit...\n");
}
static void iperf_udp_server(void *thread_param)
{
int sock, sender_len, r_size;
uint8 *buffer, client_addr[4];
uint16 client_port;
uint32 pcount = 0, last_pcount = 0;
uint32 lost, total;
uint64 recvlen;
x_ticks_t tick1, tick2;
struct timeval timeout;
buffer = malloc(IPERF_BUFSZ);
if (buffer == NULL){
return;
}
sock = 0; //todo
// setSn_RXBUF_SIZE(sock, 16);
// setSn_TXBUF_SIZE(sock, 16);
KPrintf("iperf udp server run...\n");
while (param.mode != IPERF_MODE_STOP){
tick1 = CurrentTicksGain();
tick2 = tick1;
lost = 0;
total = 0;
recvlen = 0;
while ((tick2 - tick1) < (TICK_PER_SECOND * 5)){
switch(getSn_SR(sock)){
case SOCK_UDP:
if ((r_size = getSn_RX_RSR(sock)) > 0){
if (r_size > IPERF_BUFSZ) r_size = IPERF_BUFSZ;
memset(buffer, 0, IPERF_BUFSZ);
wiz_sock_recvfrom(sock, buffer, r_size, client_addr, &client_port);
recvlen += r_size;
last_pcount = buffer[0] << 24 | buffer[1] << 16 | buffer[2] << 8 | buffer[3];
if(last_pcount > pcount){
total += last_pcount - pcount;
lost += last_pcount - pcount - 1;
pcount = last_pcount;
}
else if(last_pcount < 10){
pcount = last_pcount;
total = 1;
lost = 0;
}
}
tick2 = CurrentTicksGain();
break;
case SOCK_CLOSED:
wiz_socket(sock, Sn_MR_UDP, param.port, 0x00);
break;
}
}
if (recvlen > 0){
long data;
int integer, decimal;
KTaskDescriptorType tid;
tid = GetKTaskDescriptor();
data = recvlen * TICK_PER_SECOND / 125 / (tick2 - tick1);
integer = data/1000;
decimal = data%1000;
KPrintf("%s: %d.%03d0 Mbps! recv:%d lost:%d total:%d\n", tid->task_base_info.name, integer, decimal, total - lost, lost, total);
}
}
free(buffer);
if(getSn_SR(sock) != SOCK_CLOSED) wiz_sock_close(sock);
}
static void iperf_client(void *thread_param)
{
int i;
int sock = 0;
int ret;
uint8_t *send_buf, connected = 0;
uint64 sentlen;
x_ticks_t tick1, tick2;
// setSn_RXBUF_SIZE(sock, 16);
// setSn_TXBUF_SIZE(sock, 16);
send_buf = (uint8_t *) malloc(IPERF_BUFSZ);
if (!send_buf) return ;
for (i = 0; i < IPERF_BUFSZ; i ++)
send_buf[i] = i & 0xff;
while (param.mode != IPERF_MODE_STOP)
{
while((getSn_SR(sock) != SOCK_ESTABLISHED || !connected) && param.mode != IPERF_MODE_STOP){
switch (getSn_SR(sock)) {
case SOCK_ESTABLISHED:
if (getSn_IR(sock) & Sn_IR_CON) {
KPrintf("Connected\n", sock);
setSn_IR(sock, Sn_IR_CON);
}
connected = 1;
break;
case SOCK_CLOSE_WAIT:
wiz_sock_disconnect(sock);
break;
case SOCK_INIT:
KPrintf("Socket %d:try to connect to [%d.%d.%d.%d:%d]...",
sock, param.host[0], param.host[1], param.host[2], param.host[3], param.port);
ret = wiz_sock_connect(sock, param.host, param.port);
if (ret != SOCK_OK){
printf("failed, wait 1s to try again\n");
MdelayKTask(1000);
}
break;
case SOCK_CLOSED:
if(connected) KPrintf("Socket %d:closed\n", sock);
wiz_socket(sock, Sn_MR_TCP, param.port, 0x00);
connected = 0;
break;
default:
break;
}
}
sentlen = 0;
tick1 = CurrentTicksGain();
while (param.mode != IPERF_MODE_STOP){
tick2 = CurrentTicksGain();
if (tick2 - tick1 >= TICK_PER_SECOND * 5){
long data;
int integer, decimal;
KTaskDescriptorType tid;
tid = GetKTaskDescriptor();
data = sentlen * TICK_PER_SECOND / 125 / (tick2 - tick1);
integer = data/1000;
decimal = data%1000;
KPrintf("%s: %d.%03d0 Mbps!\n", tid->task_base_info.name, integer, decimal);
tick1 = tick2;
sentlen = 0;
}
ret = wiz_sock_send(sock, send_buf, IPERF_BUFSZ);
if (ret > 0){
sentlen += ret;
}
if (ret < 0) break;
}
if(getSn_SR(sock) != SOCK_CLOSED)wiz_sock_close(sock);
KPrintf("Disconnected, iperf client exit!");
}
free(send_buf);
}
static void iperf_server(void *thread_param)
{
uint8_t *recv_data;
x_ticks_t tick1, tick2;
int sock = -1, connected = 0, bytes_received;
uint64 recvlen;
sock = 0; //todo
// setSn_RXBUF_SIZE(sock, 16);
// setSn_TXBUF_SIZE(sock, 16);
recv_data = (uint8_t *)malloc(IPERF_BUFSZ);
if (recv_data == NULL){
KPrintf("No memory!\n");
goto __exit;
}
while (param.mode != IPERF_MODE_STOP){
while((getSn_SR(sock) != SOCK_ESTABLISHED || !connected)){
switch (getSn_SR(sock)) {
case SOCK_ESTABLISHED:
if (getSn_IR(sock) & Sn_IR_CON) {
KPrintf("Socket %d:Connected\n", sock);
setSn_IR(sock, Sn_IR_CON);
}
recvlen = 0;
tick1 = CurrentTicksGain();
connected = 1;
break;
case SOCK_CLOSE_WAIT:
wiz_sock_disconnect(sock);
break;
case SOCK_INIT:
KPrintf("Socket %d:Listen, port [%d]\n", sock, param.port);
wiz_sock_listen(sock);
break;
case SOCK_CLOSED:
if(connected) KPrintf("Socket %d:closed\n", sock);
wiz_socket(sock, Sn_MR_TCP, param.port, 0x00);
connected = 0;
break;
default:
break;
}
if(param.mode == IPERF_MODE_STOP) goto __exit;
}
if ((bytes_received = getSn_RX_RSR(sock)) > 0) {
if (bytes_received > IPERF_BUFSZ) bytes_received = IPERF_BUFSZ;
memset(recv_data, 0, IPERF_BUFSZ);
wiz_sock_recv(sock, recv_data, bytes_received);
recvlen += bytes_received;
}
tick2 = CurrentTicksGain();
if (tick2 - tick1 >= TICK_PER_SECOND * 5){
long data;
int integer, decimal;
KTaskDescriptorType tid;
tid = GetKTaskDescriptor();
data = recvlen * TICK_PER_SECOND / 125 / (tick2 - tick1);
integer = data/1000;
decimal = data%1000;
KPrintf("%s: %d.%03d0 Mbps!\n", tid->task_base_info.name, integer, decimal);
tick1 = tick2;
recvlen = 0;
}
}
__exit:
if(getSn_SR(sock) != SOCK_CLOSED)wiz_sock_close(sock);
if (recv_data) free(recv_data);
}
void iperf_usage(void)
{
KPrintf("Usage: iperf [-s|-c host] [options] [multi-threaded]\n");
KPrintf(" iperf [-h|--stop]\n");
KPrintf("\n");
KPrintf("Client/Server:\n");
KPrintf(" -p # server port to listen on/connect to\n");
KPrintf("\n");
KPrintf("Server specific:\n");
KPrintf(" -s run in server mode\n");
KPrintf("\n");
KPrintf("Client specific:\n");
KPrintf(" -c <host> run in client mode, connecting to <host>\n");
KPrintf("\n");
KPrintf("Miscellaneous:\n");
KPrintf(" -h print this message and quit\n");
KPrintf(" --stop stop iperf program\n");
KPrintf(" -u testing UDP protocol\n");
KPrintf(" -m <time> the number of multi-threaded \ns");
return;
}
int iperf(int argc, char **argv)
{
int mode = 0; /* server mode */
char *host = NULL;
int port = IPERF_PORT;
int numtid = 1;
int use_udp = 0;
int index = 1;
if (argc == 1)
{
goto __usage;
}
if (strcmp(argv[1], "-u") == 0)
{
index = 2;
use_udp = 1;
}
if (strcmp(argv[index], "-h") == 0) goto __usage;
else if (strcmp(argv[index], "--stop") == 0)
{
/* stop iperf */
param.mode = IPERF_MODE_STOP;
MdelayKTask(10);
return 0;
}
else if (strcmp(argv[index], "-s") == 0)
{
mode = IPERF_MODE_SERVER; /* server mode */
/* iperf -s -p 5000 */
if (argc >= 4)
{
if (strcmp(argv[index + 1], "-p") == 0)
{
port = atoi(argv[index + 2]);
}
else goto __usage;
}
}
else if (strcmp(argv[index], "-c") == 0)
{
mode = IPERF_MODE_CLIENT; /* client mode */
if (argc < 3) goto __usage;
host = argv[index + 1];
if (argc >= 5)
{
/* iperf -c host -p port */
if (strcmp(argv[index + 2], "-p") == 0)
{
port = atoi(argv[index + 3]);
}
else goto __usage;
}
}
else goto __usage;
if (argc >= 7)
{
if(strcmp(argv[argc - 2], "-m") == 0)
{
numtid = atoi(argv[argc - 1]);
}
else goto __usage;
}
/* start iperf */
if (param.mode == IPERF_MODE_STOP)
{
int i = 0;
char tid_name[NAME_NUM_MAX + 1] = {0};
param.mode = mode;
param.port = port;
if (host) {
uint32 t1,t2,t3,t4;
sscanf(host, "%d.%d.%d.%d", &t1, &t2, &t3, &t4);
param.host[0] = (uint8)t1;
param.host[1] = (uint8)t2;
param.host[2] = (uint8)t3;
param.host[3] = (uint8)t4;
}
for (i = 0; i < numtid; i++)
{
int32 tid = 0;
void (*function)(void *parameter);
if (use_udp)
{
if (mode == IPERF_MODE_CLIENT)
{
snprintf(tid_name, sizeof(tid_name), "iperfc%02d", i + 1);
function = iperf_udp_client;
}
else if (mode == IPERF_MODE_SERVER)
{
snprintf(tid_name, sizeof(tid_name), "iperfd%02d", i + 1);
function = iperf_udp_server;
}
}
else
{
if (mode == IPERF_MODE_CLIENT)
{
snprintf(tid_name, sizeof(tid_name), "iperfc%02d", i + 1);
function = iperf_client;
}
else if (mode == IPERF_MODE_SERVER)
{
snprintf(tid_name, sizeof(tid_name), "iperfd%02d", i + 1);
function = iperf_server;
}
}
tid = KTaskCreate(tid_name, function, NULL, 4096, 25);
if (tid) StartupKTask(tid);
MdelayKTask(10);
}
}
else
{
KPrintf("Please stop iperf firstly, by:\n");
KPrintf("iperf --stop\n");
}
return 0;
__usage:
iperf_usage();
return 0;
}
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN),
iperf, iperf,
iperf throughput test);
#endif

View File

@ -78,6 +78,10 @@ Modification:
#include <connect_can.h>
#endif
#ifdef BSP_USING_LWIP
#include <connect_ethernet.h>
#endif
extern void entry(void);
extern int HwUsartInit();
@ -209,6 +213,8 @@ struct InitSequenceDesc _board_init[] =
#endif
#ifdef BSP_USING_CAN
{ "can", HwCanInit },
#endif
#ifdef BSP_USING_LWIP
#endif
{ " NONE ", NONE },
};

View File

@ -1 +1,3 @@
config BSP_USING_ETH
bool
default y

View File

@ -1,3 +1,3 @@
SRC_FILES := ethernetif.c
SRC_FILES := ethernetif.c eth_driver.c
include $(KERNEL_ROOT)/compiler.mk

View File

@ -0,0 +1,287 @@
/**
* @file ethernetif.c
* @brief support hc32f4a0-board ethernetif function and register to Lwip
* @version 3.0
* @author AIIT XUOS Lab
* @date 2022-12-05
*/
#include <connect_ethernet.h>
#include <hc32_ll_gpio.h>
#include <hc32_ll_utility.h>
#include <hc32_ll_fcg.h>
#include <lwip/timeouts.h>
#include <netif/etharp.h>
#include <sys_arch.h>
void eth_irq_handler(void) {
static x_base eth_irq_lock;
eth_irq_lock = DISABLE_INTERRUPT();
// handle irq
if (RESET != ETH_DMA_GetStatus(ETH_DMA_FLAG_RIS)) {
sys_sem_signal(get_eth_recv_sem());
ETH_DMA_ClearStatus(ETH_DMA_FLAG_RIS | ETH_DMA_FLAG_NIS);
}
ENABLE_INTERRUPT(eth_irq_lock);
}
/**
* @brief In this function, the hardware should be initialized.
* @param netif The already initialized network interface structure for this ethernetif.
* @retval int32_t:
* - LL_OK: Initialize success
* - LL_ERR: Initialize failed
*/
int32_t low_level_init(struct netif *netif)
{
int32_t i32Ret = LL_ERR;
stc_eth_init_t stcEthInit;
uint16_t u16RegVal;
/* Enable ETH clock */
FCG_Fcg1PeriphClockCmd(FCG1_PERIPH_ETHMAC, ENABLE);
/* Init Ethernet GPIO */
Ethernet_GpioInit();
/* Reset ETHERNET */
(void)ETH_DeInit();
/* Configure structure initialization */
(void)ETH_CommStructInit(&EthHandle.stcCommInit);
(void)ETH_StructInit(&stcEthInit);
#ifdef ETH_INTERFACE_RMII
EthHandle.stcCommInit.u32Interface = ETH_MAC_IF_RMII;
#else
EthHandle.stcCommInit.u32Interface = ETH_MAC_IF_MII;
#endif
// stcEthInit.stcMacInit.u32ReceiveAll = ETH_MAC_RX_ALL_ENABLE;
EthHandle.stcCommInit.u32ReceiveMode = ETH_RX_MD_INT;
// EthHandle.stcCommInit.u32ChecksumMode = ETH_MAC_CHECKSUM_MD_SW;
// install irq
sys_sem_new(get_eth_recv_sem(), 0);
hc32_install_irq_handler(&eth_irq_config, eth_irq_handler, ENABLE);
/* Configure ethernet peripheral */
if (LL_OK == ETH_Init(&EthHandle, &stcEthInit)) {
u8EthInitStatus = 1U;
i32Ret = LL_OK;
}
#ifdef ETHERNET_LOOPBACK_TEST
/* Enable PHY loopback */
(void)ETH_PHY_LoopBackCmd(&EthHandle, ENABLE);
#endif
/* Initialize Tx Descriptors list: Chain Mode */
(void)ETH_DMA_TxDescListInit(&EthHandle, EthDmaTxDscrTab, &EthTxBuff[0][0], ETH_TX_BUF_NUM);
/* Initialize Rx Descriptors list: Chain Mode */
(void)ETH_DMA_RxDescListInit(&EthHandle, EthDmaRxDscrTab, &EthRxBuff[0][0], ETH_RX_BUF_NUM);
/* set MAC hardware address length */
netif->hwaddr_len = 6U;
/* set MAC hardware address */
EthHandle.stcCommInit.u16AutoNego = ETH_AUTO_NEGO_DISABLE;
netif->hwaddr[0] = (EthHandle.stcCommInit).au8MacAddr[0];
netif->hwaddr[1] = (EthHandle.stcCommInit).au8MacAddr[1];
netif->hwaddr[2] = (EthHandle.stcCommInit).au8MacAddr[2];
netif->hwaddr[3] = (EthHandle.stcCommInit).au8MacAddr[3];
netif->hwaddr[4] = (EthHandle.stcCommInit).au8MacAddr[4];
netif->hwaddr[5] = (EthHandle.stcCommInit).au8MacAddr[5];
/* maximum transfer unit */
netif->mtu = 1500U;
/* device capabilities */
netif->flags |= NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP;
/* Enable MAC and DMA transmission and reception */
(void)ETH_Start();
/* Configure PHY LED mode */
u16RegVal = PHY_PAGE_ADDR_7;
(void)ETH_PHY_WriteReg(&EthHandle, PHY_PSR, u16RegVal);
(void)ETH_PHY_ReadReg(&EthHandle, PHY_P7_IWLFR, &u16RegVal);
MODIFY_REG16(u16RegVal, PHY_LED_SELECT, PHY_LED_SELECT_10);
(void)ETH_PHY_WriteReg(&EthHandle, PHY_P7_IWLFR, u16RegVal);
u16RegVal = PHY_PAGE_ADDR_0;
(void)ETH_PHY_WriteReg(&EthHandle, PHY_PSR, u16RegVal);
#ifdef ETH_INTERFACE_RMII
/* Disable Power Saving Mode */
(void)ETH_PHY_ReadReg(&EthHandle, PHY_PSMR, &u16RegVal);
CLR_REG16_BIT(u16RegVal, PHY_EN_PWR_SAVE);
(void)ETH_PHY_WriteReg(&EthHandle, PHY_PSMR, u16RegVal);
/* Configure PHY to generate an interrupt when Eth Link state changes */
u16RegVal = PHY_PAGE_ADDR_7;
(void)ETH_PHY_WriteReg(&EthHandle, PHY_PSR, u16RegVal);
/* Enable Interrupt on change of link status */
(void)ETH_PHY_ReadReg(&EthHandle, PHY_P7_IWLFR, &u16RegVal);
SET_REG16_BIT(u16RegVal, PHY_INT_LINK_CHANGE);
(void)ETH_PHY_WriteReg(&EthHandle, PHY_P7_IWLFR, u16RegVal);
u16RegVal = PHY_PAGE_ADDR_0;
(void)ETH_PHY_WriteReg(&EthHandle, PHY_PSR, u16RegVal);
#endif
return i32Ret;
}
/**
* @brief This function should do the actual transmission of the packet.
* @param netif The network interface structure for this ethernetif.
* @param p The MAC packet to send.
* @retval int32_t:
* - LL_OK: The packet could be sent
* - LL_ERR: The packet couldn't be sent
*/
err_t low_level_output(struct netif *netif, struct pbuf *p)
{
err_t i32Ret;
struct pbuf *q;
uint8_t *txBuffer;
__IO stc_eth_dma_desc_t *DmaTxDesc;
uint32_t byteCnt;
uint32_t frameLength = 0UL;
uint32_t bufferOffset;
uint32_t payloadOffset;
DmaTxDesc = EthHandle.stcTxDesc;
txBuffer = (uint8_t *)((EthHandle.stcTxDesc)->u32Buf1Addr);
bufferOffset = 0UL;
/* Copy frame from pbufs to driver buffers */
for (q = p; q != NULL; q = q->next) {
/* If this buffer isn't available, goto error */
if (0UL != (DmaTxDesc->u32ControlStatus & ETH_DMA_TXDESC_OWN)) {
i32Ret = (err_t)ERR_USE;
goto error;
}
/* Get bytes in current buffer */
byteCnt = q->len;
payloadOffset = 0UL;
/* Check if the length of data to copy is bigger than Tx buffer size */
while ((byteCnt + bufferOffset) > ETH_TX_BUF_SIZE) {
/* Copy data to Tx buffer*/
(void)memcpy((uint8_t *) & (txBuffer[bufferOffset]), (uint8_t *) & (((uint8_t *)q->payload)[payloadOffset]), (ETH_TX_BUF_SIZE - bufferOffset));
/* Point to next descriptor */
DmaTxDesc = (stc_eth_dma_desc_t *)(DmaTxDesc->u32Buf2NextDescAddr);
/* Check if the buffer is available */
if (0UL != (DmaTxDesc->u32ControlStatus & ETH_DMA_TXDESC_OWN)) {
i32Ret = (err_t)ERR_USE;
goto error;
}
txBuffer = (uint8_t *)(DmaTxDesc->u32Buf1Addr);
byteCnt = byteCnt - (ETH_TX_BUF_SIZE - bufferOffset);
payloadOffset = payloadOffset + (ETH_TX_BUF_SIZE - bufferOffset);
frameLength = frameLength + (ETH_TX_BUF_SIZE - bufferOffset);
bufferOffset = 0UL;
}
/* Copy the remaining bytes */
(void)memcpy((uint8_t *) & (txBuffer[bufferOffset]), (uint8_t *) & (((uint8_t *)q->payload)[payloadOffset]), byteCnt);
bufferOffset = bufferOffset + byteCnt;
frameLength = frameLength + byteCnt;
}
/* Prepare transmit descriptors to give to DMA */
if(LL_OK != ETH_DMA_SetTransFrame(&EthHandle, frameLength)) {
KPrintf("[%s] Error sending eth DMA frame\n", __func__);
}
i32Ret = (err_t)ERR_OK;
error:
/* When Transmit Underflow flag is set, clear it and issue a Transmit Poll Demand to resume transmission */
if (RESET != ETH_DMA_GetStatus(ETH_DMA_FLAG_UNS)) {
/* Clear DMA UNS flag */
ETH_DMA_ClearStatus(ETH_DMA_FLAG_UNS);
/* Resume DMA transmission */
WRITE_REG32(CM_ETH->DMA_TXPOLLR, 0UL);
}
return i32Ret;
}
/**
* @brief Should allocate a pbuf and transfer the bytes of the incoming packet from the interface into the pbuf.
* @param netif The network interface structure for this ethernetif.
* @retval A pbuf filled with the received packet (including MAC header) or NULL on memory error.
*/
struct pbuf *low_level_input(struct netif *netif)
{
struct pbuf *p = NULL;
struct pbuf *q;
uint32_t len;
uint8_t *rxBuffer;
__IO stc_eth_dma_desc_t *DmaRxDesc;
uint32_t byteCnt;
uint32_t bufferOffset;
uint32_t payloadOffset;
uint32_t i;
/* Get received frame */
if (LL_OK != ETH_DMA_GetReceiveFrame(&EthHandle)) {
return NULL;
}
/* Obtain the size of the packet */
len = (EthHandle.stcRxFrame).u32Len;
rxBuffer = (uint8_t *)(EthHandle.stcRxFrame).u32Buf;
if (len > 0UL) {
/* Allocate a pbuf chain of pbufs from the buffer */
p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL);
// p = pbuf_alloc(PBUF_TRANSPORT, len, PBUF_RAM);
}
if (p != NULL) {
DmaRxDesc = (EthHandle.stcRxFrame).pstcFSDesc;
bufferOffset = 0UL;
for (q = p; q != NULL; q = q->next) {
byteCnt = q->len;
payloadOffset = 0UL;
/* Check if the length of bytes to copy in current pbuf is bigger than Rx buffer size */
while ((byteCnt + bufferOffset) > ETH_RX_BUF_SIZE) {
/* Copy data to pbuf */
(void)memcpy((uint8_t *) & (((uint8_t *)q->payload)[payloadOffset]), (uint8_t *) & (rxBuffer[bufferOffset]), (ETH_RX_BUF_SIZE - bufferOffset));
/* Point to next descriptor */
DmaRxDesc = (stc_eth_dma_desc_t *)(DmaRxDesc->u32Buf2NextDescAddr);
rxBuffer = (uint8_t *)(DmaRxDesc->u32Buf1Addr);
byteCnt = byteCnt - (ETH_RX_BUF_SIZE - bufferOffset);
payloadOffset = payloadOffset + (ETH_RX_BUF_SIZE - bufferOffset);
bufferOffset = 0UL;
}
/* Copy remaining data in pbuf */
(void)memcpy((uint8_t *) & (((uint8_t *)q->payload)[payloadOffset]), (uint8_t *) & (rxBuffer[bufferOffset]), byteCnt);
bufferOffset = bufferOffset + byteCnt;
}
}
/* Release descriptors to DMA */
DmaRxDesc = (EthHandle.stcRxFrame).pstcFSDesc;
for (i = 0UL; i < (EthHandle.stcRxFrame).u32SegCount; i++) {
DmaRxDesc->u32ControlStatus |= ETH_DMA_RXDESC_OWN;
DmaRxDesc = (stc_eth_dma_desc_t *)(DmaRxDesc->u32Buf2NextDescAddr);
}
/* Clear Segment_Count */
(EthHandle.stcRxFrame).u32SegCount = 0UL;
/* When Rx Buffer unavailable flag is set, clear it and resume reception */
if (RESET != ETH_DMA_GetStatus(ETH_DMA_FLAG_RUS)) {
/* Clear DMA RUS flag */
ETH_DMA_ClearStatus(ETH_DMA_FLAG_RUS);
/* Resume DMA reception */
WRITE_REG32(CM_ETH->DMA_RXPOLLR, 0UL);
}
return p;
}
extern void LwipSetIPTest(int argc, char *argv[]);
int HwEthInit(void) {
// lwip_config_tcp(0, lwip_ipaddr, lwip_netmask, lwip_gwaddr);
LwipSetIPTest(1, NULL);
return EOK;
}

View File

@ -46,14 +46,15 @@ Modification:
/*******************************************************************************
* Include files
******************************************************************************/
#include <hardware_ethernetif.h>
#include <hc32_ll_eth.h>
#include <connect_ethernet.h>
#include <hc32_ll_gpio.h>
#include <hc32_ll_utility.h>
#include <hc32_ll_fcg.h>
#include <lwip/timeouts.h>
#include <netif/etharp.h>
#include <xs_isr.h>
/**
* @addtogroup HC32F4A0_DDL_Examples
* @{
@ -71,33 +72,7 @@ Modification:
/*******************************************************************************
* Local pre-processor symbols/macros ('#define')
******************************************************************************/
/* Define those to better describe your network interface. */
#define IFNAME0 'h'
#define IFNAME1 'd'
/* PHY hardware reset time */
#define PHY_HW_RST_DELAY (0x40U)
/* ETH_RST = PH11 */
#define ETH_RST_PORT (GPIO_PORT_H)
#define ETH_RST_PIN (GPIO_PIN_11)
/* ETH_LINK_LED = PD00 LED2 */
#define ETH_LINK_LED_PORT (GPIO_PORT_D)
#define ETH_LINK_LED_PIN (GPIO_PIN_00)
//#define ETHERNET_LOOPBACK_TEST
#ifdef ETHERNET_LOOPBACK_TEST
#define USER_KEY_PORT (GPIO_PORT_I)
#define USER_KEY_PIN (GPIO_PIN_07)
/* ethe global netif */
static struct netif testnetif;
/* eth tx buffer */
static struct pbuf txPbuf;
static char txBuf[] = "Ethernet Loop-Back Test";
#endif
/*******************************************************************************
* Global variable definitions (declared in header file with 'extern')
@ -110,19 +85,7 @@ static char txBuf[] = "Ethernet Loop-Back Test";
/*******************************************************************************
* Local variable definitions ('static')
******************************************************************************/
/* Global Ethernet handle*/
static stc_eth_handle_t EthHandle;
/* Ethernet Tx DMA Descriptor */
__ALIGN_BEGIN static stc_eth_dma_desc_t EthDmaTxDscrTab[ETH_TX_BUF_NUM];
/* Ethernet Rx DMA Descriptor */
__ALIGN_BEGIN static stc_eth_dma_desc_t EthDmaRxDscrTab[ETH_RX_BUF_NUM];
/* Ethernet Transmit Buffer */
__ALIGN_BEGIN static uint8_t EthTxBuff[ETH_TX_BUF_NUM][ETH_TX_BUF_SIZE];
/* Ethernet Receive Buffer */
__ALIGN_BEGIN static uint8_t EthRxBuff[ETH_RX_BUF_NUM][ETH_RX_BUF_SIZE];
/* Ethernet link status */
static uint8_t u8PhyLinkStatus = 0U, u8EthInitStatus = 0U;
/*******************************************************************************
* Function implementation - global ('extern') and local ('static')
@ -132,22 +95,12 @@ static uint8_t u8PhyLinkStatus = 0U, u8EthInitStatus = 0U;
* @{
*/
void *ethernetif_config_enet_set(uint8_t enet_port)
{
return NONE;
}
void Time_Update_LwIP(void)
{
//no need to do
}
/**
* @brief Initializes the Ethernet GPIO.
* @param None
* @retval None
*/
static void Ethernet_GpioInit(void)
void Ethernet_GpioInit(void)
{
/* ETH_RST */
stc_gpio_init_t stcGpioInit;
@ -227,241 +180,12 @@ static void Ethernet_GpioInit(void)
#endif
}
/**
* @brief In this function, the hardware should be initialized.
* @param netif The already initialized network interface structure for this ethernetif.
* @retval int32_t:
* - LL_OK: Initialize success
* - LL_ERR: Initialize failed
*/
static int32_t low_level_init(struct netif *netif)
{
int32_t i32Ret = LL_ERR;
stc_eth_init_t stcEthInit;
uint16_t u16RegVal;
/* Enable ETH clock */
FCG_Fcg1PeriphClockCmd(FCG1_PERIPH_ETHMAC, ENABLE);
/* Init Ethernet GPIO */
Ethernet_GpioInit();
/* Reset ETHERNET */
(void)ETH_DeInit();
/* Configure structure initialization */
(void)ETH_CommStructInit(&EthHandle.stcCommInit);
(void)ETH_StructInit(&stcEthInit);
#ifdef ETH_INTERFACE_RMII
EthHandle.stcCommInit.u32Interface = ETH_MAC_IF_RMII;
#else
EthHandle.stcCommInit.u32Interface = ETH_MAC_IF_MII;
#endif
stcEthInit.stcMacInit.u32ReceiveAll = ETH_MAC_RX_ALL_ENABLE;
/* Configure ethernet peripheral */
if (LL_OK == ETH_Init(&EthHandle, &stcEthInit)) {
u8EthInitStatus = 1U;
i32Ret = LL_OK;
}
#ifdef ETHERNET_LOOPBACK_TEST
/* Enable PHY loopback */
(void)ETH_PHY_LoopBackCmd(&EthHandle, ENABLE);
#endif
/* Initialize Tx Descriptors list: Chain Mode */
(void)ETH_DMA_TxDescListInit(&EthHandle, EthDmaTxDscrTab, &EthTxBuff[0][0], ETH_TX_BUF_NUM);
/* Initialize Rx Descriptors list: Chain Mode */
(void)ETH_DMA_RxDescListInit(&EthHandle, EthDmaRxDscrTab, &EthRxBuff[0][0], ETH_RX_BUF_NUM);
/* set MAC hardware address length */
netif->hwaddr_len = 6U;
/* set MAC hardware address */
netif->hwaddr[0] = (EthHandle.stcCommInit).au8MacAddr[0];
netif->hwaddr[1] = (EthHandle.stcCommInit).au8MacAddr[1];
netif->hwaddr[2] = (EthHandle.stcCommInit).au8MacAddr[2];
netif->hwaddr[3] = (EthHandle.stcCommInit).au8MacAddr[3];
netif->hwaddr[4] = (EthHandle.stcCommInit).au8MacAddr[4];
netif->hwaddr[5] = (EthHandle.stcCommInit).au8MacAddr[5];
/* maximum transfer unit */
netif->mtu = 1500U;
/* device capabilities */
netif->flags |= NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP;
/* Enable MAC and DMA transmission and reception */
(void)ETH_Start();
/* Configure PHY LED mode */
u16RegVal = PHY_PAGE_ADDR_7;
(void)ETH_PHY_WriteReg(&EthHandle, PHY_PSR, u16RegVal);
(void)ETH_PHY_ReadReg(&EthHandle, PHY_P7_IWLFR, &u16RegVal);
MODIFY_REG16(u16RegVal, PHY_LED_SELECT, PHY_LED_SELECT_10);
(void)ETH_PHY_WriteReg(&EthHandle, PHY_P7_IWLFR, u16RegVal);
u16RegVal = PHY_PAGE_ADDR_0;
(void)ETH_PHY_WriteReg(&EthHandle, PHY_PSR, u16RegVal);
#ifdef ETH_INTERFACE_RMII
/* Disable Power Saving Mode */
(void)ETH_PHY_ReadReg(&EthHandle, PHY_PSMR, &u16RegVal);
CLR_REG16_BIT(u16RegVal, PHY_EN_PWR_SAVE);
(void)ETH_PHY_WriteReg(&EthHandle, PHY_PSMR, u16RegVal);
/* Configure PHY to generate an interrupt when Eth Link state changes */
u16RegVal = PHY_PAGE_ADDR_7;
(void)ETH_PHY_WriteReg(&EthHandle, PHY_PSR, u16RegVal);
/* Enable Interrupt on change of link status */
(void)ETH_PHY_ReadReg(&EthHandle, PHY_P7_IWLFR, &u16RegVal);
SET_REG16_BIT(u16RegVal, PHY_INT_LINK_CHANGE);
(void)ETH_PHY_WriteReg(&EthHandle, PHY_P7_IWLFR, u16RegVal);
u16RegVal = PHY_PAGE_ADDR_0;
(void)ETH_PHY_WriteReg(&EthHandle, PHY_PSR, u16RegVal);
#endif
return i32Ret;
void *ethernetif_config_enet_set(uint8_t enet_port) {
return NONE;
}
/**
* @brief This function should do the actual transmission of the packet.
* @param netif The network interface structure for this ethernetif.
* @param p The MAC packet to send.
* @retval int32_t:
* - LL_OK: The packet could be sent
* - LL_ERR: The packet couldn't be sent
*/
err_t low_level_output(struct netif *netif, struct pbuf *p)
{
err_t i32Ret;
struct pbuf *q;
uint8_t *txBuffer;
__IO stc_eth_dma_desc_t *DmaTxDesc;
uint32_t byteCnt;
uint32_t frameLength = 0UL;
uint32_t bufferOffset;
uint32_t payloadOffset;
DmaTxDesc = EthHandle.stcTxDesc;
txBuffer = (uint8_t *)((EthHandle.stcTxDesc)->u32Buf1Addr);
bufferOffset = 0UL;
/* Copy frame from pbufs to driver buffers */
for (q = p; q != NULL; q = q->next) {
/* If this buffer isn't available, goto error */
if (0UL != (DmaTxDesc->u32ControlStatus & ETH_DMA_TXDESC_OWN)) {
i32Ret = LL_ERR;
goto error;
}
/* Get bytes in current buffer */
byteCnt = q->len;
payloadOffset = 0UL;
/* Check if the length of data to copy is bigger than Tx buffer size */
while ((byteCnt + bufferOffset) > ETH_TX_BUF_SIZE) {
/* Copy data to Tx buffer*/
(void)memcpy((uint8_t *) & (txBuffer[bufferOffset]), (uint8_t *) & (((uint8_t *)q->payload)[payloadOffset]), (ETH_TX_BUF_SIZE - bufferOffset));
/* Point to next descriptor */
DmaTxDesc = (stc_eth_dma_desc_t *)(DmaTxDesc->u32Buf2NextDescAddr);
/* Check if the buffer is available */
if (0UL != (DmaTxDesc->u32ControlStatus & ETH_DMA_TXDESC_OWN)) {
i32Ret = LL_ERR;
goto error;
}
txBuffer = (uint8_t *)(DmaTxDesc->u32Buf1Addr);
byteCnt = byteCnt - (ETH_TX_BUF_SIZE - bufferOffset);
payloadOffset = payloadOffset + (ETH_TX_BUF_SIZE - bufferOffset);
frameLength = frameLength + (ETH_TX_BUF_SIZE - bufferOffset);
bufferOffset = 0UL;
}
/* Copy the remaining bytes */
(void)memcpy((uint8_t *) & (txBuffer[bufferOffset]), (uint8_t *) & (((uint8_t *)q->payload)[payloadOffset]), byteCnt);
bufferOffset = bufferOffset + byteCnt;
frameLength = frameLength + byteCnt;
}
/* Prepare transmit descriptors to give to DMA */
(void)ETH_DMA_SetTransFrame(&EthHandle, frameLength);
i32Ret = LL_OK;
error:
/* When Transmit Underflow flag is set, clear it and issue a Transmit Poll Demand to resume transmission */
if (RESET != ETH_DMA_GetStatus(ETH_DMA_FLAG_UNS)) {
/* Clear DMA UNS flag */
ETH_DMA_ClearStatus(ETH_DMA_FLAG_UNS);
/* Resume DMA transmission */
WRITE_REG32(CM_ETH->DMA_TXPOLLR, 0UL);
}
return i32Ret;
}
/**
* @brief Should allocate a pbuf and transfer the bytes of the incoming packet from the interface into the pbuf.
* @param netif The network interface structure for this ethernetif.
* @retval A pbuf filled with the received packet (including MAC header) or NULL on memory error.
*/
static struct pbuf *low_level_input(struct netif *netif)
{
struct pbuf *p = NULL;
struct pbuf *q;
uint32_t len;
uint8_t *rxBuffer;
__IO stc_eth_dma_desc_t *DmaRxDesc;
uint32_t byteCnt;
uint32_t bufferOffset;
uint32_t payloadOffset;
uint32_t i;
/* Get received frame */
if (LL_OK != ETH_DMA_GetReceiveFrame(&EthHandle)) {
return NULL;
}
/* Obtain the size of the packet */
len = (EthHandle.stcRxFrame).u32Len;
rxBuffer = (uint8_t *)(EthHandle.stcRxFrame).u32Buf;
if (len > 0UL) {
/* Allocate a pbuf chain of pbufs from the buffer */
p = pbuf_alloc(PBUF_TRANSPORT, len, PBUF_RAM);
}
if (p != NULL) {
DmaRxDesc = (EthHandle.stcRxFrame).pstcFSDesc;
bufferOffset = 0UL;
for (q = p; q != NULL; q = q->next) {
byteCnt = q->len;
payloadOffset = 0UL;
/* Check if the length of bytes to copy in current pbuf is bigger than Rx buffer size */
while ((byteCnt + bufferOffset) > ETH_RX_BUF_SIZE) {
/* Copy data to pbuf */
(void)memcpy((uint8_t *) & (((uint8_t *)q->payload)[payloadOffset]), (uint8_t *) & (rxBuffer[bufferOffset]), (ETH_RX_BUF_SIZE - bufferOffset));
/* Point to next descriptor */
DmaRxDesc = (stc_eth_dma_desc_t *)(DmaRxDesc->u32Buf2NextDescAddr);
rxBuffer = (uint8_t *)(DmaRxDesc->u32Buf1Addr);
byteCnt = byteCnt - (ETH_RX_BUF_SIZE - bufferOffset);
payloadOffset = payloadOffset + (ETH_RX_BUF_SIZE - bufferOffset);
bufferOffset = 0UL;
}
/* Copy remaining data in pbuf */
(void)memcpy((uint8_t *) & (((uint8_t *)q->payload)[payloadOffset]), (uint8_t *) & (rxBuffer[bufferOffset]), byteCnt);
bufferOffset = bufferOffset + byteCnt;
}
}
/* Release descriptors to DMA */
DmaRxDesc = (EthHandle.stcRxFrame).pstcFSDesc;
for (i = 0UL; i < (EthHandle.stcRxFrame).u32SegCount; i++) {
DmaRxDesc->u32ControlStatus |= ETH_DMA_RXDESC_OWN;
DmaRxDesc = (stc_eth_dma_desc_t *)(DmaRxDesc->u32Buf2NextDescAddr);
}
/* Clear Segment_Count */
(EthHandle.stcRxFrame).u32SegCount = 0UL;
/* When Rx Buffer unavailable flag is set, clear it and resume reception */
if (RESET != ETH_DMA_GetStatus(ETH_DMA_FLAG_RUS)) {
/* Clear DMA RUS flag */
ETH_DMA_ClearStatus(ETH_DMA_FLAG_RUS);
/* Resume DMA reception */
WRITE_REG32(CM_ETH->DMA_RXPOLLR, 0UL);
}
return p;
void Time_Update_LwIP(void) {
//no need to do
}
/**
@ -485,8 +209,8 @@ err_t ethernetif_init(struct netif *netif)
* You can instead declare your own function an call etharp_output()
* from it if you have to do some checks before sending (e.g. if link
* is available...) */
netif->output = &etharp_output;
netif->linkoutput = &low_level_output;
netif->output = etharp_output;
netif->linkoutput = low_level_output;
#endif
/* initialize the hardware */
@ -498,34 +222,38 @@ err_t ethernetif_init(struct netif *netif)
* @param netif The network interface structure for this ethernetif.
* @retval None
*/
void ethernetif_input(struct netif *netif)
void ethernetif_input(void *netif_arg)
{
err_t err;
struct pbuf *p;
struct netif *netif = (struct netif *)netif_arg;
x_base critical_lock;
/* Move received packet into a new pbuf */
p = low_level_input(netif);
while (1) {
sys_arch_sem_wait(get_eth_recv_sem(), WAITING_FOREVER);
while(1) {
p = low_level_input(netif);
#ifndef ETHERNET_LOOPBACK_TEST
/* No packet could be read, silently ignore this */
if (NULL == p) {
return;
}
/* Entry point to the LwIP stack */
err = netif->input(p, netif);
if (err != (err_t)ERR_OK) {
LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: IP input error\n"));
(void)pbuf_free(p);
}
/* Entry point to the LwIP stack */
if (p != NULL) {
if (netif->input(p, netif) != ERR_OK) {
LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: IP input error\n"));
KPrintf("ethernetif_input: IP input error\n");
pbuf_free(p);
p = NULL;
}
} else {
break;
}
#else
/* No packet could be read, silently ignore this */
if (p != NULL) {
EthernetIF_InputCallback(netif, p);
free(p);
}
#endif
#ifdef ETHERNET_LOOPBACK_TEST
/* No packet could be read, silently ignore this */
if (p != NULL) {
EthernetIF_InputCallback(netif, p);
free(p);
}
}
#endif
}
/**
@ -725,8 +453,7 @@ __WEAKDEF void EthernetIF_NotifyLinkChange(struct netif *netif)
* @param p The MAC packet to receive
* @retval None
*/
__WEAKDEF void EthernetIF_InputCallback(struct netif *netif, struct pbuf *p)
{
__WEAKDEF void EthernetIF_InputCallback(struct netif *netif, struct pbuf *p) {
/* This is function could be implemented in user file when the callback is needed */
#ifdef ETHERNET_LOOPBACK_TEST
if ((0 == (memcmp(p->payload, txPbuf.payload, p->len))) && (p->len == txPbuf.len)) {

View File

@ -22,11 +22,49 @@
#define CONNECT_ETHERNET_H
#include "hardware_ethernetif.h"
#include <sys_arch.h>
#include <hc32_ll_eth.h>
#include <hardware_irq.h>
#ifdef __cplusplus
extern "C" {
#endif
struct hc32_irq_config
{
IRQn_Type irq_num;
uint32_t irq_prio;
en_int_src_t int_src;
};
/* Global Ethernet handle*/
static stc_eth_handle_t EthHandle;
/* Ethernet Tx DMA Descriptor */
__ALIGN_BEGIN static stc_eth_dma_desc_t EthDmaTxDscrTab[ETH_TX_BUF_NUM];
/* Ethernet Rx DMA Descriptor */
__ALIGN_BEGIN static stc_eth_dma_desc_t EthDmaRxDscrTab[ETH_RX_BUF_NUM];
/* Ethernet Transmit Buffer */
__ALIGN_BEGIN static uint8_t EthTxBuff[ETH_TX_BUF_NUM][ETH_TX_BUF_SIZE];
/* Ethernet Receive Buffer */
__ALIGN_BEGIN static uint8_t EthRxBuff[ETH_RX_BUF_NUM][ETH_RX_BUF_SIZE];
/* Ethernet link status */
static uint8_t u8PhyLinkStatus = 0U, u8EthInitStatus = 0U;
static struct Hc32IrqConfig eth_irq_config = {
.irq_num = BSP_ETH_IRQ_NUM,
.irq_prio = BSP_ETH_IRQ_PRIO,
.int_src = INT_SRC_ETH_GLB_INT,
};
void Ethernet_GpioInit(void);
int32_t low_level_init(struct netif *netif);
err_t low_level_output(struct netif *netif, struct pbuf *p);
struct pbuf *low_level_input(struct netif *netif);
int HwEthInit(void);
#ifdef __cplusplus
}
#endif

View File

@ -133,9 +133,37 @@ extern "C"
* @addtogroup ETH_IF_Global_Functions
* @{
*/
/* Define those to better describe your network interface. */
#define IFNAME0 'h'
#define IFNAME1 'd'
/* PHY hardware reset time */
#define PHY_HW_RST_DELAY (0x40U)
/* ETH_RST = PH11 */
#define ETH_RST_PORT (GPIO_PORT_H)
#define ETH_RST_PIN (GPIO_PIN_11)
/* ETH_LINK_LED = PD00 LED2 */
#define ETH_LINK_LED_PORT (GPIO_PORT_D)
#define ETH_LINK_LED_PIN (GPIO_PIN_00)
//#define ETHERNET_LOOPBACK_TEST
#ifdef ETHERNET_LOOPBACK_TEST
#define USER_KEY_PORT (GPIO_PORT_I)
#define USER_KEY_PIN (GPIO_PIN_07)
/* ethe global netif */
static struct netif testnetif;
/* eth tx buffer */
static struct pbuf txPbuf;
static char txBuf[] = "Ethernet Loop-Back Test";
#endif
err_t ethernetif_init(struct netif *netif);
void ethernetif_input(struct netif *netif);
err_t low_level_output(struct netif *netif, struct pbuf *p);
void ethernetif_input(void *netif);
// err_t low_level_output(struct netif *netif, struct pbuf *p);
void EthernetIF_CheckLink(struct netif *netif);
void EthernetIF_UpdateLink(struct netif *netif);

View File

@ -163,7 +163,7 @@ static int BoardHwtimerDevBend(void)
return ret;
}
/*K210 BOARD HWTIMER INIT*/
/*HC32F4A0 BOARD HWTIMER INIT*/
int HwTimerInit(void)
{
x_err_t ret = EOK;

View File

@ -2,10 +2,12 @@ SRC_DIR += api
SRC_DIR += arch
SRC_DIR += core
SRC_DIR += netif
SRC_DIR += apps
LWIP_DIR += api
LWIP_DIR += arch
LWIP_DIR += core
LWIP_DIR += netif
LWIP_DIR += apps
include $(KERNEL_ROOT)/compiler.mk

View File

@ -0,0 +1,3 @@
SRC_FILES += lwiperf/lwiperf.c http/http_client.c
include $(KERNEL_ROOT)/compiler.mk

View File

@ -64,7 +64,8 @@
* HTTPC_DEBUG: Enable debugging for HTTP client.
*/
#ifndef HTTPC_DEBUG
#define HTTPC_DEBUG LWIP_DBG_OFF
#define HTTPC_DEBUG LWIP_DBG_ON
// #define HTTPC_DEBUG LWIP_DBG_OFF
#endif
/** Set this to 1 to keep server name and uri in request state */

View File

@ -30,6 +30,193 @@
#ifndef __LWIPOPTS_H__
#define __LWIPOPTS_H__
/* ---------- Debug options ---------- */
#ifndef LWIP_DEBUG
#define LWIP_DEBUG 1
#endif
#ifdef LWIP_DEBUG
#ifdef LWIP_SYS_DEBUG
#define SYS_DEBUG LWIP_DBG_ON
#else
#define SYS_DEBUG LWIP_DBG_OFF
#endif
#ifdef LWIP_ETHARP_DEBUG
#define ETHARP_DEBUG LWIP_DBG_ON
#else
#define ETHARP_DEBUG LWIP_DBG_OFF
#endif
#ifdef LWIP_PPP_DEBUG
#define PPP_DEBUG LWIP_DBG_ON
#else
#define PPP_DEBUG LWIP_DBG_OFF
#endif
#ifdef LWIP_MEM_DEBUG
#define MEM_DEBUG LWIP_DBG_ON
#else
#define MEM_DEBUG LWIP_DBG_OFF
#endif
#ifdef LWIP_MEMP_DEBUG
#define MEMP_DEBUG LWIP_DBG_ON
#else
#define MEMP_DEBUG LWIP_DBG_OFF
#endif
#ifdef LWIP_PBUF_DEBUG
#define PBUF_DEBUG LWIP_DBG_ON
#else
#define PBUF_DEBUG LWIP_DBG_OFF
#endif
#ifdef LWIP_API_LIB_DEBUG
#define API_LIB_DEBUG LWIP_DBG_ON
#else
#define API_LIB_DEBUG LWIP_DBG_OFF
#endif
#ifdef LWIP_API_MSG_DEBUG
#define API_MSG_DEBUG LWIP_DBG_ON
#else
#define API_MSG_DEBUG LWIP_DBG_OFF
#endif
#ifdef LWIP_TCPIP_DEBUG
#define TCPIP_DEBUG LWIP_DBG_ON
#else
#define TCPIP_DEBUG LWIP_DBG_OFF
#endif
#ifdef LWIP_NETIF_DEBUG
#define NETIF_DEBUG LWIP_DBG_ON
#else
#define NETIF_DEBUG LWIP_DBG_OFF
#endif
#ifdef LWIP_SOCKETS_DEBUG
#define SOCKETS_DEBUG LWIP_DBG_ON
#else
#define SOCKETS_DEBUG LWIP_DBG_OFF
#endif
#ifdef LWIP_DNS_DEBUG
#define DNS_DEBUG LWIP_DBG_ON
#else
#define DNS_DEBUG LWIP_DBG_OFF
#endif
#ifdef LWIP_AUTOIP_DEBUG
#define AUTOIP_DEBUG LWIP_DBG_ON
#else
#define AUTOIP_DEBUG LWIP_DBG_OFF
#endif
#ifdef LWIP_DHCP_DEBUG
#define DHCP_DEBUG LWIP_DBG_ON
#else
#define DHCP_DEBUG LWIP_DBG_OFF
#endif
#ifdef LWIP_IP_DEBUG
#define IP_DEBUG LWIP_DBG_ON
#else
#define IP_DEBUG LWIP_DBG_OFF
#endif
#ifdef LWIP_IP_REASS_DEBUG
#define IP_REASS_DEBUG LWIP_DBG_ON
#else
#define IP_REASS_DEBUG LWIP_DBG_OFF
#endif
#ifdef LWIP_ICMP_DEBUG
#define ICMP_DEBUG LWIP_DBG_ON
#else
#define ICMP_DEBUG LWIP_DBG_OFF
#endif
#ifdef LWIP_IGMP_DEBUG
#define IGMP_DEBUG LWIP_DBG_ON
#else
#define IGMP_DEBUG LWIP_DBG_OFF
#endif
#ifdef LWIP_UDP_DEBUG
#define UDP_DEBUG LWIP_DBG_ON
#else
#define UDP_DEBUG LWIP_DBG_OFF
#endif
#ifdef LWIP_TCP_DEBUG
#define TCP_DEBUG LWIP_DBG_ON
#else
#define TCP_DEBUG LWIP_DBG_OFF
#endif
#ifdef LWIP_TCP_INPUT_DEBUG
#define TCP_INPUT_DEBUG LWIP_DBG_ON
#else
#define TCP_INPUT_DEBUG LWIP_DBG_OFF
#endif
#ifdef LWIP_TCP_OUTPUT_DEBUG
#define TCP_OUTPUT_DEBUG LWIP_DBG_ON
#else
#define TCP_OUTPUT_DEBUG LWIP_DBG_OFF
#endif
#ifdef LWIP_TCP_RTO_DEBUG
#define TCP_RTO_DEBUG LWIP_DBG_ON
#else
#define TCP_RTO_DEBUG LWIP_DBG_OFF
#endif
#ifdef LWIP_TCP_CWND_DEBUG
#define TCP_CWND_DEBUG LWIP_DBG_ON
#else
#define TCP_CWND_DEBUG LWIP_DBG_OFF
#endif
#ifdef LWIP_TCP_WND_DEBUG
#define TCP_WND_DEBUG LWIP_DBG_ON
#else
#define TCP_WND_DEBUG LWIP_DBG_OFF
#endif
#ifdef LWIP_TCP_FR_DEBUG
#define TCP_FR_DEBUG LWIP_DBG_ON
#else
#define TCP_FR_DEBUG LWIP_DBG_OFF
#endif
#ifdef LWIP_TCP_QLEN_DEBUG
#define TCP_QLEN_DEBUG LWIP_DBG_ON
#else
#define TCP_QLEN_DEBUG LWIP_DBG_OFF
#endif
#ifdef LWIP_TCP_RST_DEBUG
#define TCP_RST_DEBUG LWIP_DBG_ON
#else
#define TCP_RST_DEBUG LWIP_DBG_OFF
#endif
#endif /* LWIP_DEBUG */
#define LWIP_TIMEVAL_PRIVATE 0
#define LWIP_NO_UNISTD_H 0
#define LWIP_NO_STDDEF_H 0
#define LWIP_NO_STDINT_H 0
#define LWIP_NO_INTTYPES_H 0
#define LWIP_NO_LIMITS_H 0
#define LWIP_NO_CTYPE_H 0
#define LWIP_SOCKET_SELECT 1
#define LWIP_SOCKET_POLL 1
/**
* SYS_LIGHTWEIGHT_PROT==1: if you want inter-task protection for certain
* critical regions during buffer allocation, deallocation and memory
@ -57,35 +244,40 @@
/* MEM_SIZE: the size of the heap memory. If the application will send
a lot of data that needs to be copied, this should be set high. */
#define MEM_SIZE (25*1024)
#define MEM_SIZE (64*1024)
/* MEMP_NUM_PBUF: the number of memp struct pbufs. If the application
sends a lot of data out of ROM (or other static memory), this
should be set high. */
#define MEMP_NUM_PBUF 15
#define MEMP_NUM_PBUF 32
/* MEMP_NUM_UDP_PCB: the number of UDP protocol control blocks. One
per active UDP "connection". */
#define MEMP_NUM_UDP_PCB 4
/* MEMP_NUM_TCP_PCB: the number of simulatenously active TCP
connections. */
#define MEMP_NUM_TCP_PCB 4
#define MEMP_NUM_TCP_PCB 64
/* MEMP_NUM_TCP_PCB_LISTEN: the number of listening TCP
connections. */
#define MEMP_NUM_TCP_PCB_LISTEN 2
/* MEMP_NUM_TCP_SEG: the number of simultaneously queued TCP
segments. */
#define MEMP_NUM_TCP_SEG 20
#define MEMP_NUM_TCP_SEG 256
/* MEMP_NUM_SYS_TIMEOUT: the number of simulateously active
timeouts. */
#define MEMP_NUM_SYS_TIMEOUT 6
// #define MEMP_NUM_SYS_TIMEOUT 6
#define MEMP_NUM_SYS_TIMEOUT (LWIP_TCP + IP_REASSEMBLY + LWIP_ARP + (2*LWIP_DHCP) + LWIP_AUTOIP + LWIP_IGMP + LWIP_DNS + PPP_SUPPORT + (LWIP_IPV6 ? (1 + (2*LWIP_IPV6)) : 0))
/* ---------- Pbuf options ---------- */
/* PBUF_POOL_SIZE: the number of buffers in the pbuf pool. */
#define PBUF_POOL_SIZE 20
#define PBUF_POOL_SIZE 255
/* PBUF_POOL_BUFSIZE: the size of each pbuf in the pbuf pool. */
// #define PBUF_POOL_BUFSIZE 1024
#define PBUF_POOL_BUFSIZE LWIP_MEM_ALIGN_SIZE(TCP_MSS+40+PBUF_LINK_ENCAPSULATION_HLEN+PBUF_LINK_HLEN)
/* ---------- ARP options ---------- */
#define LWIP_ARP 1
#define ARP_TABLE_SIZE 10
#define ARP_QUEUEING 1
/* ---------- TCP options ---------- */
#define LWIP_TCP 1
@ -93,7 +285,7 @@ a lot of data that needs to be copied, this should be set high. */
/* Controls if TCP should queue segments that arrive out of
order. Define to 0 if your device is low on memory. */
#define TCP_QUEUE_OOSEQ 0
#define TCP_QUEUE_OOSEQ 1
/* TCP Maximum segment size. */
#define TCP_MSS (1500 - 40) /* TCP_MSS = (Ethernet MTU - IP header size - TCP header size) */
@ -107,9 +299,69 @@ a lot of data that needs to be copied, this should be set high. */
#define TCP_SND_QUEUELEN (8* TCP_SND_BUF/TCP_MSS)
/* TCP receive window. */
#define TCP_WND (12*TCP_MSS)
#define TCP_WND 8192
// #define TCP_WND (12 * TCP_MSS)
/* Maximum number of retransmissions of data segments. */
#define TCP_MAXRTX 12
/* Maximum number of retransmissions of SYN segments. */
#define TCP_SYNMAXRTX 4
/**
* LWIP_TCP_KEEPALIVE==1: Enable TCP_KEEPIDLE, TCP_KEEPINTVL and TCP_KEEPCNT
* options processing. Note that TCP_KEEPIDLE and TCP_KEEPINTVL have to be set
* in seconds. (does not require sockets.c, and will affect tcp.c)
*/
#ifndef LWIP_TCP_KEEPALIVE
#define LWIP_TCP_KEEPALIVE 1
#endif
/**
* LWIP_NETIF_HOSTNAME==1: Support netif hostname
*/
#ifndef LWIP_NETIF_HOSTNAME
#define LWIP_NETIF_HOSTNAME 1
#endif
/**
* LWIP_NETIF_API==1: Support netif api (in netifapi.c)
*/
#ifndef LWIP_NETIF_API
#define LWIP_NETIF_API 1
#endif
/**
* LWIP_SO_SNDTIMEO==1: Enable send timeout for sockets/netconns and
* SO_SNDTIMEO processing.
*/
#ifndef LWIP_SO_SNDTIMEO
#define LWIP_SO_SNDTIMEO 1
#endif
/**
* LWIP_SO_RCVTIMEO==1: Enable receive timeout for sockets/netconns and
* SO_RCVTIMEO processing.
*/
#ifndef LWIP_SO_RCVTIMEO
#define LWIP_SO_RCVTIMEO 1
#endif
/**
* LWIP_SO_RCVBUF==1: Enable SO_RCVBUF processing.
*/
#ifndef LWIP_SO_RCVBUF
#define LWIP_SO_RCVBUF 1
#endif
/**
* If LWIP_SO_RCVBUF is used, this is the default value for recv_bufsize.
*/
#ifndef RECV_BUFSIZE_DEFAULT
#define RECV_BUFSIZE_DEFAULT 8192
#endif
/* ---------- ICMP options ---------- */
#define LWIP_ICMP 1
@ -127,7 +379,6 @@ a lot of data that needs to be copied, this should be set high. */
/* ---------- Statistics options ---------- */
#define LWIP_STATS 0
#define LWIP_PROVIDE_ERRNO 1
/* ---------- link callback options ---------- */
@ -146,7 +397,7 @@ The STM32F4x7 allows computing and verifying the IP, UDP, TCP and ICMP checksums
- To use this feature let the following define uncommented.
- To disable it and process by CPU comment the the checksum.
*/
//#define CHECKSUM_BY_HARDWARE
#define CHECKSUM_BY_HARDWARE
#ifdef CHECKSUM_BY_HARDWARE
/* CHECKSUM_GEN_IP==0: Generate checksums by hardware for outgoing IP packets.*/
@ -176,7 +427,7 @@ The STM32F4x7 allows computing and verifying the IP, UDP, TCP and ICMP checksums
#define CHECKSUM_CHECK_UDP 1
/* CHECKSUM_CHECK_TCP==1: Check checksums in software for incoming TCP packets.*/
#define CHECKSUM_CHECK_TCP 1
/* CHECKSUM_CHECK_ICMP==1: Check checksums by hardware for incoming ICMP packets.*/
/* CHECKSUM_CHECK_ICMP==1: Check checksums by software for incoming ICMP packets.*/
#define CHECKSUM_GEN_ICMP 1
#endif
@ -225,7 +476,50 @@ The STM32F4x7 allows computing and verifying the IP, UDP, TCP and ICMP checksums
/**
* LWIP_SO_LINGER==1: Enable SO_LINGER processing.
*/
#define LWIP_SO_LINGER 1
// #define LWIP_SO_LINGER 1
/* ---------- IP options ---------- */
/* Define IP_FORWARD to 1 if you wish to have the ability to forward
IP packets across network interfaces. If you are going to run lwIP
on a device with only one network interface, define this to 0. */
#define IP_FORWARD 0
/* IP reassembly and segmentation.These are orthogonal even
* if they both deal with IP fragments */
#ifdef LWIP_REASSEMBLY_FRAG
#define IP_REASSEMBLY 1
#define IP_FRAG 1
#define IP_REASS_MAX_PBUFS 10
#define MEMP_NUM_REASSDATA 10
#else
#define IP_REASSEMBLY 0
#define IP_FRAG 0
#endif
/* ---------- ICMP options ---------- */
#define ICMP_TTL 255
/* ---------- DHCP options ---------- */
/* Define LWIP_DHCP to 1 if you want DHCP configuration of
interfaces. */
#define LWIP_DHCP 1
/* 1 if you want to do an ARP check on the offered address
(recommended). */
#define DHCP_DOES_ARP_CHECK (LWIP_DHCP)
/* ---------- AUTOIP options ------- */
#define LWIP_AUTOIP 0
#define LWIP_DHCP_AUTOIP_COOP (LWIP_DHCP && LWIP_AUTOIP)
#define LWIP_UDPLITE 0
#define UDP_TTL 255
/* ---------- Statistics options ---------- */
#define LWIP_STATS 1
#define LWIP_STATS_DISPLAY 1
/*
---------------------------------
@ -236,23 +530,21 @@ The STM32F4x7 allows computing and verifying the IP, UDP, TCP and ICMP checksums
#define DEFAULT_RAW_RECVMBOX_SIZE 8
#define DEFAULT_UDP_RECVMBOX_SIZE 8
#define DEFAULT_TCP_RECVMBOX_SIZE 8
#define DEFAULT_ACCEPTMBOX_SIZE 8
#define DEFAULT_ACCEPTMBOX_SIZE 10
#define DEFAULT_THREAD_PRIO 20
#define DEFAULT_THREAD_STACKSIZE 1024
#define TCPIP_THREAD_NAME "tcp"
#define TCPIP_THREAD_STACKSIZE 8192
#define TCPIP_MBOX_SIZE 8
#define TCPIP_THREAD_PRIO 15
#define TCPIP_THREAD_STACKSIZE 1024
#define TCPIP_MBOX_SIZE 16
#define TCPIP_THREAD_PRIO 20
/*
----------------------------------------
---------- Lwip Debug options ----------
----------------------------------------
*/
#define LWIP_DEBUG 1
#define LWIP_IPV4 1
#define LWIP_RAW 1
#define LWIP_DNS 1

View File

@ -69,96 +69,58 @@
#include "ethernet.h"
#include "connect_ethernet.h"
char lwip_ipaddr[20] = {192, 168, 131, 77};
char lwip_ipaddr[20] = {192, 168, 130, 77};
char lwip_netmask[20] = {255, 255, 254, 0};
char lwip_gwaddr[20] = {192, 168, 131, 23};
char lwip_gwaddr[20] = {192, 168, 130, 1};
char lwip_eth0_ipaddr[20] = {192, 168, 131, 77};
char lwip_eth0_ipaddr[20] = {192, 168, 130, 77};
char lwip_eth0_netmask[20] = {255, 255, 254, 0};
char lwip_eth0_gwaddr[20] = {192, 168, 131, 23};
char lwip_eth0_gwaddr[20] = {192, 168, 130, 1};
char lwip_eth1_ipaddr[20] = {192, 168, 131, 99};
char lwip_eth1_ipaddr[20] = {192, 168, 130, 99};
char lwip_eth1_netmask[20] = {255, 255, 254, 0};
char lwip_eth1_gwaddr[20] = {192, 168, 131, 23};
char lwip_eth1_gwaddr[20] = {192, 168, 130, 23};
char lwip_flag = 0;
x_ticks_t lwip_sys_now;
struct sys_timeouts {
struct sys_timeo *next;
};
struct timeoutlist
{
struct sys_timeouts timeouts;
int32 pid;
};
#define SYS_THREAD_MAX 4
static struct timeoutlist s_timeoutlist[SYS_THREAD_MAX];
struct netif gnetif;
sys_sem_t* get_eth_recv_sem() {
static sys_sem_t g_recv_sem = 0;
return &g_recv_sem;
}
static u16_t s_nextthread = 0;
void sys_init(void) {
// do nothing
}
u32_t
sys_jiffies(void)
{
sys_jiffies(void) {
lwip_sys_now = CurrentTicksGain();
return lwip_sys_now;
}
u32_t
sys_now(void)
{
sys_now(void) {
lwip_sys_now = CurrentTicksGain();
return lwip_sys_now;
return CalculateTimeMsFromTick(lwip_sys_now);
}
void
sys_init(void)
{
int i;
for(i = 0; i < SYS_THREAD_MAX; i++)
{
s_timeoutlist[i].pid = 0;
s_timeoutlist[i].timeouts.next = NULL;
}
s_nextthread = 0;
}
struct sys_timeouts *sys_arch_timeouts(void)
{
int i;
int32 pid;
struct timeoutlist *tl;
pid = (int32)GetKTaskDescriptor()->id.id;
for(i = 0; i < s_nextthread; i++)
{
tl = &(s_timeoutlist[i]);
if(tl->pid == pid)
{
return &(tl->timeouts);
}
}
return NULL;
}
sys_prot_t sys_arch_protect(void)
{
sys_prot_t sys_arch_protect(void) {
return CriticalAreaLock();
}
void sys_arch_unprotect(sys_prot_t pval)
{
void sys_arch_unprotect(sys_prot_t pval) {
CriticalAreaUnLock(pval);
}
#if !NO_SYS
err_t
sys_sem_new(sys_sem_t *sem, u8_t count)
{
sys_sem_new(sys_sem_t *sem, u8_t count) {
*sem = KSemaphoreCreate((uint16)count);
#if SYS_STATS
@ -170,8 +132,7 @@ sys_sem_new(sys_sem_t *sem, u8_t count)
if(*sem >= 0)
return ERR_OK;
else
{
else {
#if SYS_STATS
++lwip_stats.sys.sem.err;
#endif /* SYS_STATS */
@ -181,8 +142,7 @@ sys_sem_new(sys_sem_t *sem, u8_t count)
}
void
sys_sem_free(sys_sem_t *sem)
{
sys_sem_free(sys_sem_t *sem) {
#if SYS_STATS
--lwip_stats.sys.sem.used;
#endif /* SYS_STATS */
@ -190,19 +150,16 @@ sys_sem_free(sys_sem_t *sem)
*sem = SYS_SEM_NULL;
}
int sys_sem_valid(sys_sem_t *sem)
{
int sys_sem_valid(sys_sem_t *sem) {
return (*sem > SYS_SEM_NULL);
}
void
sys_sem_set_invalid(sys_sem_t *sem)
{
sys_sem_set_invalid(sys_sem_t *sem) {
*sem = SYS_SEM_NULL;
}
u32_t sys_arch_sem_wait(sys_sem_t *sem, u32_t timeout)
{
u32_t sys_arch_sem_wait(sys_sem_t *sem, u32_t timeout) {
x_ticks_t start_tick = 0 ;
int32 wait_time = 0;
@ -220,61 +177,51 @@ u32_t sys_arch_sem_wait(sys_sem_t *sem, u32_t timeout)
if(KSemaphoreObtain(*sem, wait_time) == EOK)
return ((CurrentTicksGain()-start_tick)*MS_PER_SYSTICK);
return CalculateTimeMsFromTick(CurrentTicksGain()-start_tick);
else
return SYS_ARCH_TIMEOUT;
}
void sys_sem_signal(sys_sem_t *sem)
{
if(KSemaphoreAbandon( *sem ) != EOK)
void sys_sem_signal(sys_sem_t *sem) {
if(KSemaphoreAbandon(*sem) != EOK)
KPrintf("[sys_arch]:sem signal fail!\n");
}
err_t sys_mutex_new(sys_mutex_t *mutex)
{
err_t sys_mutex_new(sys_mutex_t *mutex) {
*mutex = KMutexCreate();
if(*mutex > SYS_MRTEX_NULL)
if (*mutex > SYS_MRTEX_NULL)
return ERR_OK;
else
{
else {
KPrintf("[sys_arch]:new mutex fail!\n");
return ERR_MEM;
}
}
void sys_mutex_free(sys_mutex_t *mutex)
{
void sys_mutex_free(sys_mutex_t *mutex) {
KMutexDelete(*mutex);
}
void sys_mutex_set_invalid(sys_mutex_t *mutex)
{
void sys_mutex_set_invalid(sys_mutex_t *mutex) {
*mutex = SYS_MRTEX_NULL;
}
void sys_mutex_lock(sys_mutex_t *mutex)
{
KMutexObtain(*mutex,
WAITING_FOREVER);
void sys_mutex_lock(sys_mutex_t *mutex) {
KMutexObtain(*mutex, WAITING_FOREVER);
}
void sys_mutex_unlock(sys_mutex_t *mutex)
{
KMutexAbandon( *mutex );
void sys_mutex_unlock(sys_mutex_t *mutex) {
KMutexAbandon(*mutex);
}
sys_thread_t sys_thread_new(const char *name, lwip_thread_fn function, void *arg, int stacksize, int prio)
{
sys_thread_t sys_thread_new(const char *name, lwip_thread_fn function, void *arg, int stacksize, int prio) {
sys_thread_t handle = -1;
handle = KTaskCreate(name,
function,
arg,
(uint32)stacksize,
(uint8)prio);
if (handle >= 0)
{
if (handle >= 0) {
StartupKTask(handle);
lw_print("lw: [%s] create %s handle %x\n", __func__, name, handle);
return handle;
@ -283,8 +230,7 @@ sys_thread_t sys_thread_new(const char *name, lwip_thread_fn function, void *arg
return -ERROR;
}
err_t sys_mbox_new(sys_mbox_t *mbox, int size)
{
err_t sys_mbox_new(sys_mbox_t *mbox, int size) {
*mbox = KCreateMsgQueue(sizeof(void *), size);
#if SYS_STATS
@ -293,8 +239,7 @@ err_t sys_mbox_new(sys_mbox_t *mbox, int size)
lwip_stats.sys.mbox.max = lwip_stats.sys.mbox.used;
}
#endif /* SYS_STATS */
if(*mbox < 0)
{
if(*mbox < 0) {
lw_print("lw: [%s] alloc %d mbox %p failed\n", __func__, size, mbox);
return ERR_MEM;
}
@ -303,44 +248,38 @@ err_t sys_mbox_new(sys_mbox_t *mbox, int size)
return ERR_OK;
}
void sys_mbox_free(sys_mbox_t *mbox)
{
void sys_mbox_free(sys_mbox_t *mbox) {
KDeleteMsgQueue(*mbox);
}
int sys_mbox_valid(sys_mbox_t *mbox)
{
int sys_mbox_valid(sys_mbox_t *mbox) {
if (*mbox <= SYS_MBOX_NULL)
return 0;
else
return 1;
}
void sys_mbox_set_invalid(sys_mbox_t *mbox)
{
void sys_mbox_set_invalid(sys_mbox_t *mbox) {
*mbox = SYS_MBOX_NULL;
}
void sys_mbox_post(sys_mbox_t *q, void *msg)
{
while(KMsgQueueSendwait( *q, &msg, sizeof(void *), WAITING_FOREVER) != EOK);
void sys_mbox_post(sys_mbox_t *q, void *msg) {
KMsgQueueSendwait(*q, &msg, sizeof(void *), WAITING_FOREVER);
}
err_t sys_mbox_trypost(sys_mbox_t *q, void *msg)
{
err_t sys_mbox_trypost(sys_mbox_t *q, void *msg) {
// if(KMsgQueueSend(*q, &msg, sizeof(void *)) == EOK)
if(KMsgQueueSend(*q, &msg, sizeof(void *)) == EOK)
return ERR_OK;
else
return ERR_MEM;
}
err_t sys_mbox_trypost_fromisr(sys_mbox_t *q, void *msg)
{
err_t sys_mbox_trypost_fromisr(sys_mbox_t *q, void *msg) {
return sys_mbox_trypost(q, msg);
}
u32_t sys_arch_mbox_fetch(sys_mbox_t *q, void **msg, u32_t timeout)
{
u32_t sys_arch_mbox_fetch(sys_mbox_t *q, void **msg, u32_t timeout) {
x_ticks_t start_tick = 0 ;
int32 wait_time = 0;
@ -351,17 +290,15 @@ u32_t sys_arch_mbox_fetch(sys_mbox_t *q, void **msg, u32_t timeout)
else
wait_time = timeout;
if(KMsgQueueRecv(*q, &(*msg), sizeof(void *), wait_time) == EOK)
return ((CurrentTicksGain()-start_tick)*MS_PER_SYSTICK);
else{
*msg = NULL;
if(KMsgQueueRecv(*q, &(*msg), sizeof(void *), wait_time) == EOK) {
return CalculateTimeMsFromTick(CurrentTicksGain() - start_tick);
} else {
return SYS_ARCH_TIMEOUT;
}
}
u32_t sys_arch_mbox_tryfetch(sys_mbox_t *q, void **msg)
{
if(KMsgQueueRecv(*q, &(*msg), sizeof(void *), 0) == EOK)
u32_t sys_arch_mbox_tryfetch(sys_mbox_t *q, void **msg) {
if (KMsgQueueRecv(*q, &(*msg), sizeof(void *), 0) == EOK)
return ERR_OK;
else
return SYS_MBOX_EMPTY;
@ -374,97 +311,15 @@ u32_t sys_arch_mbox_tryfetch(sys_mbox_t *q, void **msg)
#endif /* !NO_SYS */
/* Variables Initialization */
struct netif gnetif;
ip4_addr_t ipaddr;
ip4_addr_t netmask;
ip4_addr_t gw;
void lwip_tcp_init(void)
{
tcpip_init(NULL, NULL);
/* IP addresses initialization */
/* USER CODE BEGIN 0 */
#if LWIP_DHCP
ip_addr_set_zero_ip4(&ipaddr);
ip_addr_set_zero_ip4(&netmask);
ip_addr_set_zero_ip4(&gw);
#else
IP4_ADDR(&ipaddr, lwip_ipaddr[0], lwip_ipaddr[1], lwip_ipaddr[2], lwip_ipaddr[3]);
IP4_ADDR(&netmask, lwip_netmask[0], lwip_netmask[1], lwip_netmask[2], lwip_netmask[3]);
IP4_ADDR(&gw, lwip_gwaddr[0], lwip_gwaddr[1], lwip_gwaddr[2], lwip_gwaddr[3]);
#endif /* USE_DHCP */
/* USER CODE END 0 */
/* Initilialize the LwIP stack without RTOS */
/* add the network interface (IPv4/IPv6) without RTOS */
#ifdef NETIF_ENET0_INIT_FUNC
netif_add(&gnetif, &ipaddr, &netmask, &gw, NULL, NETIF_ENET0_INIT_FUNC, &tcpip_input);
#endif
/* Registers the default network interface */
netif_set_default(&gnetif);
if (netif_is_link_up(&gnetif))
{
/* When the netif is fully configured this function must be called */
KPrintf("%s : netif_set_up\n", __func__);
netif_set_up(&gnetif);
}
else
{
/* When the netif link is down this function must be called */
KPrintf("%s : netif_set_down\n", __func__);
netif_set_down(&gnetif);
}
#if LWIP_DHCP
int err;
/* Creates a new DHCP client for this interface on the first call.
Note: you must call dhcp_fine_tmr() and dhcp_coarse_tmr() at
the predefined regular intervals after starting the client.
You can peek in the netif->dhcp struct for the actual DHCP status.*/
err = dhcp_start(&gnetif);
if(err == ERR_OK)
KPrintf("lwip dhcp init success...\n\n");
else
KPrintf("lwip dhcp init fail...\n\n");
while(ip_addr_cmp(&(gnetif.ip_addr),&ipaddr))
{
DelayKTask(1);
}
#endif
KPrintf("\n\nIP:%d.%d.%d.%d\n\n", \
((gnetif.ip_addr.addr)&0x000000ff), \
(((gnetif.ip_addr.addr)&0x0000ff00)>>8), \
(((gnetif.ip_addr.addr)&0x00ff0000)>>16), \
((gnetif.ip_addr.addr)&0xff000000)>>24);
}
// lwip input thread to get network packet
void lwip_input_thread(void *param)
{
struct netif *net = param;
while (1)
{
#ifdef FSL_RTOS_XIUOS
if (lwip_obtain_semaphore(net) == EOK)
#endif
{
/* Poll the driver, get any outstanding frames */
ethernetif_input(net);
sys_check_timeouts(); /* Handle all system timeouts for all core protocols */
}
}
}
void lwip_config_input(struct netif *net)
{
void lwip_config_input(struct netif *net) {
sys_thread_t th_id = 0;
th_id = sys_thread_new("eth_input", lwip_input_thread, net, LWIP_TASK_STACK_SIZE, 15);
extern void ethernetif_input(void *netif_arg);
th_id = sys_thread_new("eth_input", ethernetif_input, net, LWIP_TASK_STACK_SIZE, 20);
if (th_id >= 0) {
lw_print("%s %d successfully!\n", __func__, th_id);
@ -473,15 +328,65 @@ void lwip_config_input(struct netif *net)
}
}
void lwip_config_net(uint8_t enet_port, char *ip, char *mask, char *gw)
{
void lwip_config_tcp(uint8_t enet_port, char *ip, char *mask, char *gw) {
ip4_addr_t net_ipaddr, net_netmask, net_gw;
char* eth_cfg;
eth_cfg = ethernetif_config_enet_set(enet_port);
if(chk_lwip_bit(LWIP_INIT_FLAG))
{
if(chk_lwip_bit(LWIP_INIT_FLAG)) {
lw_print("lw: [%s] already ...\n", __func__);
return;
}
set_lwip_bit(LWIP_INIT_FLAG);
tcpip_init(NULL, NULL);
lw_print("lw: [%s] start ...\n", __func__);
IP4_ADDR(&net_ipaddr, ip[0], ip[1], ip[2], ip[3]);
IP4_ADDR(&net_netmask, mask[0], mask[1], mask[2], mask[3]);
IP4_ADDR(&net_gw, gw[0], gw[1], gw[2], gw[3]);
if (0 == enet_port) {
#ifdef NETIF_ENET0_INIT_FUNC
printf("[%s:%d] call netif_add\n", __func__, __LINE__);
netif_add(&gnetif, &net_ipaddr, &net_netmask, &net_gw, eth_cfg, NETIF_ENET0_INIT_FUNC,
tcpip_input);
#endif
} else if (1 == enet_port) {
#ifdef NETIF_ENET1_INIT_FUNC
netif_add(&gnetif, &net_ipaddr, &net_netmask, &net_gw, eth_cfg, NETIF_ENET1_INIT_FUNC,
tcpip_input);
#endif
}
netif_set_default(&gnetif);
netif_set_up(&gnetif);
lw_print("\r\n************************************************\r\n");
lw_print(" Network Configuration\r\n");
lw_print("************************************************\r\n");
lw_print(" IPv4 Address : %u.%u.%u.%u\r\n", ((u8_t *)&net_ipaddr)[0], ((u8_t *)&net_ipaddr)[1],
((u8_t *)&net_ipaddr)[2], ((u8_t *)&net_ipaddr)[3]);
lw_print(" IPv4 Subnet mask : %u.%u.%u.%u\r\n", ((u8_t *)&net_netmask)[0], ((u8_t *)&net_netmask)[1],
((u8_t *)&net_netmask)[2], ((u8_t *)&net_netmask)[3]);
lw_print(" IPv4 Gateway : %u.%u.%u.%u\r\n", ((u8_t *)&net_gw)[0], ((u8_t *)&net_gw)[1],
((u8_t *)&net_gw)[2], ((u8_t *)&net_gw)[3]);
lw_print("************************************************\r\n");
lwip_config_input(&gnetif);
}
void lwip_config_net(uint8_t enet_port, char *ip, char *mask, char *gw) {
ip4_addr_t net_ipaddr, net_netmask, net_gw;
char* eth_cfg;
eth_cfg = ethernetif_config_enet_set(enet_port);
if(chk_lwip_bit(LWIP_INIT_FLAG)) {
lw_print("lw: [%s] already ...\n", __func__);
IP4_ADDR(&net_ipaddr, ip[0], ip[1], ip[2], ip[3]);
@ -521,8 +426,7 @@ void lwip_config_net(uint8_t enet_port, char *ip, char *mask, char *gw)
netif_set_default(&gnetif);
netif_set_up(&gnetif);
if(chk_lwip_bit(LWIP_PRINT_FLAG))
{
if(chk_lwip_bit(LWIP_PRINT_FLAG)) {
lw_notice("\r\n************************************************\r\n");
lw_notice(" Network Configuration\r\n");
lw_notice("************************************************\r\n");
@ -537,55 +441,3 @@ void lwip_config_net(uint8_t enet_port, char *ip, char *mask, char *gw)
lwip_config_input(&gnetif);
}
void lwip_config_tcp(uint8_t enet_port, char *ip, char *mask, char *gw)
{
ip4_addr_t net_ipaddr, net_netmask, net_gw;
char* eth_cfg;
eth_cfg = ethernetif_config_enet_set(enet_port);
if(chk_lwip_bit(LWIP_INIT_FLAG))
{
lw_print("lw: [%s] already ...\n", __func__);
return;
}
set_lwip_bit(LWIP_INIT_FLAG);
tcpip_init(NULL, NULL);
lw_print("lw: [%s] start ...\n", __func__);
IP4_ADDR(&net_ipaddr, ip[0], ip[1], ip[2], ip[3]);
IP4_ADDR(&net_netmask, mask[0], mask[1], mask[2], mask[3]);
IP4_ADDR(&net_gw, gw[0], gw[1], gw[2], gw[3]);
if(0 == enet_port) {
#ifdef NETIF_ENET0_INIT_FUNC
netif_add(&gnetif, &net_ipaddr, &net_netmask, &net_gw, eth_cfg, NETIF_ENET0_INIT_FUNC,
ethernet_input);
#endif
} else if (1 == enet_port) {
#ifdef NETIF_ENET1_INIT_FUNC
netif_add(&gnetif, &net_ipaddr, &net_netmask, &net_gw, eth_cfg, NETIF_ENET1_INIT_FUNC,
ethernet_input);
#endif
}
netif_set_default(&gnetif);
netif_set_up(&gnetif);
lw_print("\r\n************************************************\r\n");
lw_print(" Network Configuration\r\n");
lw_print("************************************************\r\n");
lw_print(" IPv4 Address : %u.%u.%u.%u\r\n", ((u8_t *)&net_ipaddr)[0], ((u8_t *)&net_ipaddr)[1],
((u8_t *)&net_ipaddr)[2], ((u8_t *)&net_ipaddr)[3]);
lw_print(" IPv4 Subnet mask : %u.%u.%u.%u\r\n", ((u8_t *)&net_netmask)[0], ((u8_t *)&net_netmask)[1],
((u8_t *)&net_netmask)[2], ((u8_t *)&net_netmask)[3]);
lw_print(" IPv4 Gateway : %u.%u.%u.%u\r\n", ((u8_t *)&net_gw)[0], ((u8_t *)&net_gw)[1],
((u8_t *)&net_gw)[2], ((u8_t *)&net_gw)[3]);
lw_print("************************************************\r\n");
lwip_config_input(&gnetif);
}

View File

@ -54,7 +54,7 @@
#define LWIP_TARGET_PORT LWIP_LOCAL_PORT
#define LWIP_DEMO_TIMES 10
#define LWIP_TASK_STACK_SIZE 4096
#define LWIP_TASK_STACK_SIZE 1536
#define LWIP_DEMO_TASK_PRIO 20
// /* MAC address configuration. */
@ -72,7 +72,8 @@ typedef int32 sys_mbox_t;
typedef int32 sys_thread_t;
typedef x_base sys_prot_t;
#define MS_PER_SYSTICK (1000 / TICK_PER_SECOND)
#define MS_PER_SYSTICK (float)(1000 / TICK_PER_SECOND)
#define TICKS_PER_MS (TICK_PER_SECOND / 1000)
//debug rtos with IRQ
//#define FSL_RTOS_XIUOS
@ -99,6 +100,7 @@ extern char lwip_eth1_netmask[];
extern char lwip_eth1_gwaddr[];
extern struct netif gnetif;
extern sys_sem_t* get_eth_recv_sem();
void lwip_tcp_init(void);
void lwip_config_net(uint8_t enet_port, char *ip, char *mask, char *gw);

View File

@ -142,18 +142,22 @@
#endif
#ifdef LWIP_DEBUG
#define LWIP_DEBUGF(debug, message) do { \
#define LWIP_DEBUGF(debug_flag, message) do { \
if ( \
((debug) & LWIP_DBG_ON) && \
((debug) & LWIP_DBG_TYPES_ON) && \
((s16_t)((debug) & LWIP_DBG_MASK_LEVEL) >= LWIP_DBG_MIN_LEVEL)) { \
((debug_flag) & LWIP_DBG_ON) && \
((debug_flag) & LWIP_DBG_TYPES_ON) && \
(debug_flag)) { \
LWIP_PLATFORM_DIAG(message); \
if ((debug) & LWIP_DBG_HALT) { \
if ((debug_flag) & LWIP_DBG_HALT) { \
while(1); \
} \
} \
} while(0)
// ((s16_t)((debug_flag) & LWIP_DBG_MASK_LEVEL) >= LWIP_DBG_MIN_LEVEL)) { \
// #define LWIP_DEBUGF(debug, message) do { \
// LWIP_PLATFORM_DIAG(message); \
// } while(0)
#else /* LWIP_DEBUG */
#define LWIP_DEBUGF(debug, message)
#endif /* LWIP_DEBUG */

View File

@ -1,3 +1,4 @@
SRC_FILES := ping.c lwip_ping_demo.c lwip_tcp_demo.c lwip_udp_demo.c tcpecho_raw.c lwip_config_demo.c lwip_dhcp_demo.c
SRC_FILES := ping.c lwip_ping_demo.c lwip_tcp_demo.c tcpecho_raw.c lwip_config_demo.c lwip_dhcp_demo.c iperf.c http_test.c
# SRC_FILES := ping.c lwip_ping_demo.c lwip_tcp_demo.c lwip_udp_demo.c tcpecho_raw.c lwip_config_demo.c lwip_dhcp_demo.c iperf.c
include $(KERNEL_ROOT)/compiler.mk

View File

@ -0,0 +1,68 @@
#include <string.h>
#include <shell.h>
#include <debug.h>
#include "lwip/apps/http_client.h"
void httpc_app_recv_end(void *arg, httpc_result_t httpc_result, u32_t rx_content_len, u32_t srv_res, err_t err) {
httpc_state_t **req = (httpc_state_t**)arg;
LWIP_DEBUGF(LWIP_DEBUG, ("[HTTPC] Transfer finished. rx_content_len is %lu\r\n", rx_content_len));
printf("[HTTPC] Transfer finished. rx_content_len is %lu\r\n", rx_content_len);
*req = NULL;
}
err_t httpc_app_headers_done(httpc_state_t *connection, void *arg, struct pbuf *hdr, u16_t hdr_len, u32_t content_len) {
LWIP_DEBUGF(LWIP_DEBUG, ("[%s] headers done call back.\n", __func__));
printf("[%s] headers done call back, content len: %d.\n", __func__, content_len);
return ERR_OK;
}
err_t httpc_app_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err) {
printf("[%s] Get %d Data\n", __func__, p->len);
pbuf_free(p);
return ERR_OK;
}
ip_addr_t *get_server_ip() {
static ip_addr_t server_ip;
return &server_ip;
}
httpc_state_t **get_conn_state() {
static httpc_state_t *conn_state;
return &conn_state;
}
httpc_connection_t *get_conn_setting() {
static httpc_connection_t conn_setting;
return &conn_setting;
}
void httpc_get_file_app(int argc, char *argv[]) {
// deal input ip
// get file from server
const uint8_t server_ip_by_arr[4] = {39, 156, 66, 10};
// const uint8_t server_ip_by_arr[4] = {114, 215, 151, 106};
IP4_ADDR(get_server_ip(),
server_ip_by_arr[0], server_ip_by_arr[1], server_ip_by_arr[2], server_ip_by_arr[3]);
get_conn_setting()->use_proxy = 0;
get_conn_setting()->result_fn = httpc_app_recv_end;
get_conn_setting()->headers_done_fn = httpc_app_headers_done;
LWIP_DEBUGF(HTTPC_DEBUG, ("[%s] Calling httpc_get_file\n", __func__));
printf("[%s] Calling httpc_get_file\n", __func__);
err_t errnum = httpc_get_file(get_server_ip(), 80, "/index.html", get_conn_setting(), httpc_app_recv, NULL, get_conn_state());
// err_t errnum = httpc_get_file_dns("https://www.baidu.com", 80, "/index.html", get_conn_setting(), httpc_app_recv, NULL, get_conn_state());
if (errnum != ERR_OK) {
printf("httpc_get_file failed (%d)\n", errnum);
}
}
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN) | SHELL_CMD_PARAM_NUM(0),
lwip_http_test, httpc_get_file_app, get file from net server);

View File

@ -0,0 +1,686 @@
/**
* iperf-liked network performance tool
*
*/
#include <xizi.h>
#include <shell.h>
#include <string.h>
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/time.h>
#include <sys/select.h>
#include <sys_arch.h>
#include "lwip/sockets.h"
#include <netdb.h>
#include <lwiperf.h>
#define IPERF_PORT 5001
#define IPERF_BUFSZ (4 * 1024)
#define IPERF_MODE_STOP 0
#define IPERF_MODE_SERVER 1
#define IPERF_MODE_CLIENT 2
typedef struct{
int mode;
char *host;
int port;
} IPERF_PARAM;
static IPERF_PARAM param = {IPERF_MODE_STOP, NULL, IPERF_PORT};
char tcp_iperf_ip[] = {192, 168, 130, 77};
char tcp_iperf_mask[] = {255, 255, 254, 0};
char tcp_iperf_gw[] = {192, 168, 130, 1};
static void iperf_udp_client(void *thread_param)
{
int sock;
uint32 *buffer;
struct sockaddr_in server;
uint32 packet_count = 0;
uint32 tick;
int send_size;
send_size = IPERF_BUFSZ > 1470 ? 1470 : IPERF_BUFSZ;
sock = socket(PF_INET, SOCK_DGRAM, 0);
if(sock < 0){
KPrintf("[%s:%d] can't create socket! exit!\n", __FILE__, __LINE__);
return;
}
server.sin_family = PF_INET;
server.sin_port = htons(param.port);
server.sin_addr.s_addr = inet_addr(param.host);
memset(&(server.sin_zero), 0, sizeof(server.sin_zero));
if (connect(sock, (struct sockaddr *)&server, sizeof(struct sockaddr))){
lw_error("Unable to connect\n");
closesocket(sock);
return;
}
buffer = malloc(IPERF_BUFSZ);
if (buffer == NULL){
printf("[%s:%d] malloc failed\n", __FILE__, __LINE__);
return;
}
memset(buffer, 0x00, IPERF_BUFSZ);
KPrintf("iperf udp mode run...\n");
while (param.mode != IPERF_MODE_STOP){
packet_count++;
tick = CurrentTicksGain();
buffer[0] = htonl(packet_count);
buffer[1] = htonl(tick / TICK_PER_SECOND);
buffer[2] = htonl((tick % TICK_PER_SECOND) * 1000);
sendto(sock, buffer, send_size, 0, (struct sockaddr *)&server, sizeof(struct sockaddr_in));
}
closesocket(sock);
free(buffer);
KPrintf("iperf udp mode exit...\n");
}
static void iperf_udp_server(void *thread_param)
{
int sock;
uint32 *buffer;
struct sockaddr_in server;
struct sockaddr_in sender;
int sender_len, r_size;
uint64 sentlen;
uint32 pcount = 0, last_pcount = 0;
uint32 lost, total;
x_ticks_t tick1, tick2;
struct timeval timeout;
buffer = malloc(IPERF_BUFSZ);
if (buffer == NULL){
return;
}
sock = socket(PF_INET, SOCK_DGRAM, 0);
if(sock < 0){
KPrintf("can't create socket! exit!");
return;
}
server.sin_family = PF_INET;
server.sin_port = htons(param.port);
server.sin_addr.s_addr = inet_addr("0.0.0.0");
timeout.tv_sec = 2;
timeout.tv_usec = 0;
if (setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout)) == -1){
KPrintf("setsockopt failed!");
closesocket(sock);
free(buffer);
return;
}
if (bind(sock, (struct sockaddr *)&server, sizeof(struct sockaddr_in)) < 0){
KPrintf("iperf server bind failed! exit!");
closesocket(sock);
free(buffer);
return;
}
while (param.mode != IPERF_MODE_STOP){
tick1 = CurrentTicksGain();
tick2 = tick1;
lost = 0;
total = 0;
sentlen = 0;
while ((tick2 - tick1) < (TICK_PER_SECOND * 5)){
r_size = recvfrom(sock, buffer, IPERF_BUFSZ, 0, (struct sockaddr *)&sender, (socklen_t*)&sender_len);
if (r_size > 12){
pcount = ntohl(buffer[0]);
if (last_pcount < pcount){
lost += pcount - last_pcount - 1;
total += pcount - last_pcount;
}
else{
last_pcount = pcount;
}
last_pcount = pcount;
sentlen += r_size;
}
tick2 = CurrentTicksGain();
}
if (sentlen > 0){
long data;
int integer, decimal;
KTaskDescriptorType tid;
tid = GetKTaskDescriptor();
data = sentlen * TICK_PER_SECOND / 125 / (tick2 - tick1);
integer = data/1000;
decimal = data%1000;
KPrintf("%s: %d.%03d0 Mbps! lost:%d total:%d\n", tid->task_base_info.name, integer, decimal, lost, total);
}
}
free(buffer);
closesocket(sock);
}
static void iperf_client(void *thread_param)
{
int i;
int sock;
int ret;
int tips = 1;
uint8_t *send_buf;
uint64 sentlen;
x_ticks_t tick1, tick2;
struct sockaddr_in addr;
send_buf = (uint8_t *) malloc(IPERF_BUFSZ);
if (!send_buf) return ;
for (i = 0; i < IPERF_BUFSZ; i ++)
send_buf[i] = i & 0xff;
while (param.mode != IPERF_MODE_STOP)
{
sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock < 0){
KPrintf("create socket failed!");
DelayKTask(TICK_PER_SECOND);
continue;
}
addr.sin_family = PF_INET;
addr.sin_port = htons(param.port);
addr.sin_addr.s_addr = inet_addr((char *)param.host);
ret = connect(sock, (const struct sockaddr *)&addr, sizeof(addr));
if (ret == -1){
if (tips){
KPrintf("Connect to iperf server faile, Waiting for the server to open!");
tips = 0;
}
closesocket(sock);
DelayKTask(TICK_PER_SECOND);
continue;
}
KPrintf("Connect to iperf server successful!\n");
{
int flag = 1;
setsockopt(sock,
IPPROTO_TCP, /* set option at TCP level */
TCP_NODELAY, /* name of option */
(void *) &flag, /* the cast is historical cruft */
sizeof(int)); /* length of option value */
}
sentlen = 0;
tick1 = CurrentTicksGain();
while (param.mode != IPERF_MODE_STOP){
tick2 = CurrentTicksGain();
if (tick2 - tick1 >= TICK_PER_SECOND * 5){
double speed;
// int integer, decimal;
KTaskDescriptorType tid;
tid = GetKTaskDescriptor();
speed = (double)(sentlen * TICK_PER_SECOND / 125 / (tick2 - tick1));
speed = speed / 1000.0f;
printf("%s: %2.4f Mbps!\n", tid->task_base_info.name, speed);
tick1 = tick2;
sentlen = 0;
}
ret = send(sock, send_buf, IPERF_BUFSZ, 0);
if (ret > 0){
sentlen += ret;
}
if (ret < 0) break;
}
closesocket(sock);
DelayKTask(TICK_PER_SECOND * 2);
KPrintf("Disconnected, iperf server shut down!");
tips = 1;
}
free(send_buf);
}
// iperf tcp server running thread
struct sock_conn_cb {
struct sockaddr_in server_addr;
struct sockaddr_in client_addr;
int connected;
int parent_id;
};
void iperf_sever_worker(void* arg) {
struct sock_conn_cb *sccb = (struct sock_conn_cb *)arg;
x_ticks_t tick1, tick2;
uint8_t *recv_data = (uint8_t *)malloc(IPERF_BUFSZ);
if(recv_data == NULL) {
KPrintf("[%s] No Memory.\n", __func__);
goto exit__;
}
uint64 recvlen = 0;
int32_t bytes_received = 0;
int flag = 1;
setsockopt(sccb->connected,
IPPROTO_TCP, /* set option at TCP level */
TCP_NODELAY, /* name of option */
(void *) &flag, /* the cast is historical cruft */
sizeof(int)); /* length of option value */
int cur_tid = GetKTaskDescriptor()->id.id;
tick1 = CurrentTicksGain();
while (param.mode != IPERF_MODE_STOP){
bytes_received = recv(sccb->connected, recv_data, IPERF_BUFSZ, 0);
if (bytes_received == 0) {
KPrintf("client disconnected (%s, %d)\n",
inet_ntoa(sccb->client_addr.sin_addr), ntohs(sccb->client_addr.sin_port));
break;
} else if (bytes_received < 0) {
KPrintf("recv error, client: (%s, %d)\n",
inet_ntoa(sccb->client_addr.sin_addr), ntohs(sccb->client_addr.sin_port));
break;
}
recvlen += bytes_received;
tick2 = CurrentTicksGain();
if (tick2 - tick1 >= TICK_PER_SECOND * 5) {
double speed;
// int integer, decimal;
KTaskDescriptorType tid;
tid = GetKTaskDescriptor();
speed = (double)(recvlen * TICK_PER_SECOND / (125 * (tick2 - tick1)));
speed = speed / 1000.0f;
printf("%s%d: %2.4f Mbps!\n",
tid->task_base_info.name, cur_tid - sccb->parent_id, speed);
tick1 = tick2;
recvlen = 0;
}
}
free(recv_data);
exit__:
if (sccb->connected >= 0) closesocket(sccb->connected);
sccb->connected = -1;
free(sccb);
KPrintf("iperf server %d quiting.\n", cur_tid - sccb->parent_id);
}
void iperf_server_multithread(void *thread_param)
{
socklen_t sin_size;
x_ticks_t tick1, tick2;
int sock;
int connected;
struct sockaddr_in server_addr, client_addr;
fd_set readset;
struct timeval timeout;
sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock < 0){
KPrintf("[%s:%d] Socket error!\n", __FILE__, __LINE__);
goto __exit;
}
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(param.port);
server_addr.sin_addr.s_addr = INADDR_ANY;
memset(&(server_addr.sin_zero), 0x0, sizeof(server_addr.sin_zero));
if (bind(sock, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) == -1){
KPrintf("Unable to bind!\n");
goto __exit;
}
if (listen(sock, 5) == -1){
KPrintf("Listen error!\n");
goto __exit;
}
int cur_tid = GetKTaskDescriptor()->id.id;
timeout.tv_sec = 5;
timeout.tv_usec = 0;
while (param.mode != IPERF_MODE_STOP){
FD_ZERO(&readset);
FD_SET(sock, &readset);
if (select(sock + 1, &readset, NULL, NULL, &timeout) == 0) {
continue;
}
sin_size = sizeof(struct sockaddr_in);
connected = accept(sock, (struct sockaddr *)&client_addr, &sin_size);
printf("new client connected from (%s, %d)\n",
inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));
struct sock_conn_cb *sccb = malloc(sizeof(struct sock_conn_cb));
sccb->connected = connected;
sccb->client_addr = client_addr;
sccb->server_addr = server_addr;
sccb->parent_id = cur_tid;
int tid = KTaskCreate("iperf server", iperf_sever_worker, sccb, LWIP_TASK_STACK_SIZE, 20);
// iperf_sever_worker(sccb);
if (tid) {
StartupKTask(tid);
} else {
KPrintf("[%s] Failed to create server worker.\n", __func__);
free(sccb);
}
}
__exit:
if (sock >= 0) closesocket(sock);
}
void iperf_server(void *thread_param)
{
uint8_t *recv_data;
socklen_t sin_size;
x_ticks_t tick1, tick2;
int sock = -1, connected, bytes_received;
uint64 recvlen;
struct sockaddr_in server_addr, client_addr;
fd_set readset;
struct timeval timeout;
sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock < 0){
KPrintf("[%s:%d] Socket error!\n", __FILE__, __LINE__);
goto __exit;
}
recv_data = (uint8_t *)malloc(IPERF_BUFSZ);
if (recv_data == NULL){
KPrintf("No memory!\n");
goto __exit;
}
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(param.port);
server_addr.sin_addr.s_addr = INADDR_ANY;
memset(&(server_addr.sin_zero), 0x0, sizeof(server_addr.sin_zero));
if (bind(sock, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) == -1){
KPrintf("Unable to bind!\n");
goto __exit;
}
if (listen(sock, 5) == -1){
KPrintf("Listen error!\n");
goto __exit;
}
timeout.tv_sec = 3;
timeout.tv_usec = 0;
while (param.mode != IPERF_MODE_STOP){
FD_ZERO(&readset);
FD_SET(sock, &readset);
if (select(sock + 1, &readset, NULL, NULL, &timeout) == 0) {
continue;
}
sin_size = sizeof(struct sockaddr_in);
connected = accept(sock, (struct sockaddr *)&client_addr, &sin_size);
printf("new client connected from (%s, %d)\n",
inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));
int flag = 1;
setsockopt(connected,
IPPROTO_TCP, /* set option at TCP level */
TCP_NODELAY, /* name of option */
(void *) &flag, /* the cast is historical cruft */
sizeof(int)); /* length of option value */
recvlen = 0;
tick1 = CurrentTicksGain();
while (param.mode != IPERF_MODE_STOP){
bytes_received = recv(connected, recv_data, IPERF_BUFSZ, 0);
if (bytes_received == 0) {
KPrintf("client disconnected (%s, %d)\n",
inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));
break;
} else if (bytes_received < 0) {
KPrintf("recv error, client: (%s, %d)\n",
inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));
break;
}
recvlen += bytes_received;
tick2 = CurrentTicksGain();
if (tick2 - tick1 >= TICK_PER_SECOND * 5) {
double speed;
// int integer, decimal;
KTaskDescriptorType tid;
tid = GetKTaskDescriptor();
speed = (double)(recvlen * TICK_PER_SECOND / (125 * (tick2 - tick1)));
speed = speed / 1000.0f;
printf("%s: %2.4f Mbps!\n", tid->task_base_info.name, speed);
tick1 = tick2;
recvlen = 0;
}
}
if (connected >= 0) closesocket(connected);
connected = -1;
}
__exit:
if (sock >= 0) closesocket(sock);
if (recv_data) free(recv_data);
}
void iperf_usage(void)
{
KPrintf("Usage: iperf [-s|-c host] [options] [multi-threaded]\n");
KPrintf(" iperf [-h|--stop]\n");
KPrintf("\n");
KPrintf("Client/Server:\n");
KPrintf(" -p # server port to listen on/connect to\n");
KPrintf("\n");
KPrintf("Server specific:\n");
KPrintf(" -s run in server mode\n");
KPrintf("\n");
KPrintf("Client specific:\n");
KPrintf(" -c <host> run in client mode, connecting to <host>\n");
KPrintf("\n");
KPrintf("Miscellaneous:\n");
KPrintf(" -h print this message and quit\n");
KPrintf(" --stop stop iperf program\n");
KPrintf(" -u testing UDP protocol\n");
KPrintf(" -m <time> the number of multi-threaded \ns");
return;
}
int iperf(int argc, char **argv)
{
int mode = 0; /* server mode */
char *host = NULL;
int port = IPERF_PORT;
int numtid = 1;
int use_udp = 0;
int index = 1;
if (argc == 1)
{
goto __usage;
}
if (strcmp(argv[1], "-u") == 0)
{
index = 2;
use_udp = 1;
}
if (strcmp(argv[index], "-h") == 0) goto __usage;
else if (strcmp(argv[index], "--stop") == 0)
{
/* stop iperf */
param.mode = IPERF_MODE_STOP;
printf("iperf stop.\n");
return 0;
}
else if (strcmp(argv[index], "-s") == 0)
{
mode = IPERF_MODE_SERVER; /* server mode */
/* iperf -s -p 5000 */
if (argc >= 4)
{
if (strcmp(argv[index + 1], "-p") == 0)
{
port = atoi(argv[index + 2]);
}
else goto __usage;
}
}
else if (strcmp(argv[index], "-c") == 0)
{
mode = IPERF_MODE_CLIENT; /* client mode */
if (argc < 3) goto __usage;
host = argv[index + 1];
if (argc >= 5)
{
/* iperf -c host -p port */
if (strcmp(argv[index + 2], "-p") == 0)
{
port = atoi(argv[index + 3]);
}
else goto __usage;
}
}
else goto __usage;
if (argc >= 7)
{
if(strcmp(argv[argc - 2], "-m") == 0)
{
numtid = atoi(argv[argc - 1]);
}
else goto __usage;
}
/* start iperf */
if (param.mode == IPERF_MODE_STOP)
{
int i = 0;
char tid_name[NAME_NUM_MAX + 1] = {0};
param.mode = mode;
param.port = port;
if (param.host)
{
free(param.host);
param.host = NULL;
}
if (host) param.host = strdup(host);
for (i = 0; i < numtid; i++)
{
int32 tid = 0;
void (*function)(void *parameter);
if (use_udp)
{
if (mode == IPERF_MODE_CLIENT)
{
snprintf(tid_name, sizeof(tid_name), "iperfc%02d", i + 1);
function = iperf_udp_client;
}
else if (mode == IPERF_MODE_SERVER)
{
snprintf(tid_name, sizeof(tid_name), "iperfd%02d", i + 1);
function = iperf_udp_server;
}
}
else
{
if (mode == IPERF_MODE_CLIENT)
{
snprintf(tid_name, sizeof(tid_name), "iperfc%02d", i + 1);
function = iperf_client;
}
else if (mode == IPERF_MODE_SERVER)
{
snprintf(tid_name, sizeof(tid_name), "iperfd%02d", i + 1);
function = iperf_server_multithread;
}
}
tid = KTaskCreate(tid_name, function, NULL, LWIP_TASK_STACK_SIZE, 20);
if (tid) StartupKTask(tid);
}
}
else
{
KPrintf("Please stop iperf firstly, by:\n");
KPrintf("iperf --stop\n");
}
return 0;
__usage:
iperf_usage();
return 0;
}
#if LWIP_TCP
static void
lwiperf_report(void *arg, enum lwiperf_report_type report_type,
const ip_addr_t* local_addr, u16_t local_port, const ip_addr_t* remote_addr, u16_t remote_port,
u32_t bytes_transferred, u32_t ms_duration, u32_t bandwidth_kbitpsec)
{
LWIP_UNUSED_ARG(arg);
LWIP_UNUSED_ARG(local_addr);
LWIP_UNUSED_ARG(local_port);
printf("IPERF report: type=%d, remote: %s:%d, total bytes: %"U32_F", duration in ms: %"U32_F", kbits/s: %"U32_F"\n",
(int)report_type, ipaddr_ntoa(remote_addr), (int)remote_port, bytes_transferred, ms_duration, bandwidth_kbitpsec);
}
#endif /* LWIP_TCP */
void
lwiperf_example_init(void)
{
#if LWIP_TCP
ip4_addr_t ipaddr;
lwiperf_start_tcp_server_default(lwiperf_report, NULL);
// IP4_ADDR(&ipaddr,192,168,0,181);
// lwiperf_start_tcp_client_default(&ipaddr, lwiperf_report, NULL);
#endif
}
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN) | SHELL_CMD_PARAM_NUM(8),
iperf, iperf, netutils iperf);
extern void *lwiperf_start_tcp_server_default(lwiperf_report_fn report_fn, void *report_arg);
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN) | SHELL_CMD_PARAM_NUM(8),
lwiperf_tcp_server, lwiperf_example_init, netutils lwipperf);

View File

@ -30,7 +30,8 @@ static void LwipSetIPTask(void *param)
{
uint8_t enet_port = *(uint8_t *)param; ///< test enet port
printf("lw: [%s] config netport id[%d]\n", __func__, enet_port);
lwip_config_net(enet_port, lwip_ipaddr, lwip_netmask, lwip_gwaddr);
// lwip_config_net(enet_port, lwip_ipaddr, lwip_netmask, lwip_gwaddr);
lwip_config_tcp(enet_port, lwip_ipaddr, lwip_netmask, lwip_gwaddr);
}
void LwipSetIPTest(int argc, char *argv[])
@ -64,7 +65,8 @@ void LwipSetIPTest(int argc, char *argv[])
sscanf(argv[1], "%d.%d.%d.%d", &lwip_ipaddr[0], &lwip_ipaddr[1], &lwip_ipaddr[2], &lwip_ipaddr[3]);
memcpy(lwip_eth0_ipaddr, lwip_ipaddr, strlen(lwip_ipaddr));
}
sys_thread_new("SET ip address", LwipSetIPTask, &enet_id, LWIP_TASK_STACK_SIZE, LWIP_DEMO_TASK_PRIO);
// sys_thread_new("SET ip address", LwipSetIPTask, &enet_id, LWIP_TASK_STACK_SIZE, LWIP_DEMO_TASK_PRIO);
LwipSetIPTask(&enet_id);
}
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN) | SHELL_CMD_PARAM_NUM(5),

View File

@ -37,59 +37,17 @@
ip4_addr_t ping_addr;
/******************************************************************************/
char arg_ip[20] = {192, 168, 130, 50};
void LwipPingTest(int argc, char *argv[])
{
int result = 0;
uint8_t enet_port = 0; ///< test enet port 0
if(argc >= 4)
{
printf("lw: [%s] ip %s mask %s gw %s for netport %s\n", __func__, argv[1], argv[2], argv[3], argv[4]);
sscanf(argv[1], "%d.%d.%d.%d", &lwip_ipaddr[0], &lwip_ipaddr[1], &lwip_ipaddr[2], &lwip_ipaddr[3]);
sscanf(argv[2], "%d.%d.%d.%d", &lwip_netmask[0], &lwip_netmask[1], &lwip_netmask[2], &lwip_netmask[3]);
sscanf(argv[3], "%d.%d.%d.%d", &lwip_gwaddr[0], &lwip_gwaddr[1], &lwip_gwaddr[2], &lwip_gwaddr[3]);
sscanf(argv[4], "%d", &enet_port);
if(0 == enet_port)
{
memcpy(lwip_eth0_ipaddr, lwip_ipaddr, strlen(lwip_ipaddr));
memcpy(lwip_eth0_netmask, lwip_netmask, strlen(lwip_netmask));
memcpy(lwip_eth0_gwaddr, lwip_gwaddr, strlen(lwip_gwaddr));
}
if(1 == enet_port)
{
memcpy(lwip_eth1_ipaddr, lwip_ipaddr, strlen(lwip_ipaddr));
memcpy(lwip_eth1_netmask, lwip_netmask, strlen(lwip_netmask));
memcpy(lwip_eth1_gwaddr, lwip_gwaddr, strlen(lwip_gwaddr));
}
}
else if(argc == 3)
{
sscanf(argv[2], "%d", &enet_port);
printf("lw: [%s] gw %s netport %d\n", __func__, argv[1], enet_port);
if (argc == 2) {
printf("lw: [%s] ping %s\n", __func__, argv[1]);
if(isdigit(argv[1][0]))
{
if(sscanf(argv[1], "%d.%d.%d.%d", &lwip_gwaddr[0], &lwip_gwaddr[1], &lwip_gwaddr[2], &lwip_gwaddr[3]) == EOF)
{
lw_notice("input wrong ip\n");
return;
}
}
#if (LWIP_DHCP) && (PING_USE_SOCKETS)
else
{
get_url_ip(argv[1]);
return;
}
#endif
}
else if(argc == 2)
{
printf("lw: [%s] gw %s\n", __func__, argv[1]);
if(isdigit(argv[1][0]))
{
if(sscanf(argv[1], "%d.%d.%d.%d", &lwip_gwaddr[0], &lwip_gwaddr[1], &lwip_gwaddr[2], &lwip_gwaddr[3]) == EOF)
if(sscanf(argv[1], "%d.%d.%d.%d", &arg_ip[0], &arg_ip[1], &arg_ip[2], &arg_ip[3]) == EOF)
{
lw_notice("input wrong ip\n");
return;
@ -106,12 +64,11 @@ void LwipPingTest(int argc, char *argv[])
printf("lw: [%s] argc %d\n", __func__, argc);
IP4_ADDR(&ping_addr, lwip_gwaddr[0], lwip_gwaddr[1], lwip_gwaddr[2], lwip_gwaddr[3]);
lwip_config_net(enet_port, lwip_ipaddr, lwip_netmask, lwip_gwaddr);
IP4_ADDR(&ping_addr, arg_ip[0], arg_ip[1], arg_ip[2], arg_ip[3]);
ping_init(&ping_addr);
}
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN) | SHELL_CMD_PARAM_NUM(5),
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN) | SHELL_CMD_PARAM_NUM(2),
ping, LwipPingTest, ping [IP] 10 times);
#endif

View File

@ -19,15 +19,19 @@
*/
#include "board.h"
#include "lwip_demo.h"
#include "sys_arch.h"
#include "lwip/sockets.h"
#include "tcpecho_raw.h"
#include <shell.h>
#include <sys.h>
#include <xizi.h>
#include "lwip_demo.h"
#include "lwip/sockets.h"
#include "tcpecho_raw.h"
char tcp_demo_msg[LWIP_TEST_MSG_SIZE] = { 0 };
char tcp_demo_ip[] = {192, 168, 250, 252};
u16_t tcp_demo_port = LWIP_TARGET_PORT;
u16_t tcp_demo_port = 80;
int tcp_send_num = 0;
int tcp_send_task_on = 0;
uint32 tcp_interval = 50;
/******************************************************************************/
@ -58,17 +62,34 @@ static void LwipTcpSendTask(void *arg)
lw_notice("tcp connect success, start to send.\n");
lw_notice("\n\nTarget Port:%d\n\n", tcp_sock.sin_port);
tcp_send_task_on = 1;
sendto(fd, tcp_demo_msg, strlen(tcp_demo_msg), 0, (struct sockaddr*)&tcp_sock, sizeof(struct sockaddr));
lw_notice("Send tcp msg: %s ", tcp_demo_msg);
while(tcp_send_num > 0 || tcp_send_num == -1)
{
sendto(fd, tcp_demo_msg, strlen(tcp_demo_msg), 0, (struct sockaddr*)&tcp_sock, sizeof(struct sockaddr));
lw_notice("Send tcp msg: %s \n", tcp_demo_msg);
if(tcp_send_num > 0)
{
tcp_send_num--;
}
DelayKTask(tcp_interval);
}
closesocket(fd);
tcp_send_task_on = 0;
return;
}
void LwipTcpSendTest(int argc, char *argv[])
{
if(tcp_send_task_on){
tcp_send_num = 0;
printf("waitting send task exit...\n");
while(tcp_send_task_on){
DelayKTask(1000);
}
tcp_send_num = 1;
}
LwipTcpSocketParamType param;
uint8_t enet_port = 0;
memset(tcp_demo_msg, 0, LWIP_TEST_MSG_SIZE);
@ -88,8 +109,10 @@ void LwipTcpSendTest(int argc, char *argv[])
{
sscanf(argv[2], "%d.%d.%d.%d", &tcp_demo_ip[0], &tcp_demo_ip[1], &tcp_demo_ip[2], &tcp_demo_ip[3]);
}
sscanf(argv[3], "%d", &tcp_send_num);
sscanf(argv[4], "%d", &tcp_interval);
}
lw_notice("get ipaddr %d.%d.%d.%d:%d\n", tcp_demo_ip[0], tcp_demo_ip[1], tcp_demo_ip[2], tcp_demo_ip[3], tcp_demo_port);
lw_notice("get ipaddr %d.%d.%d.%d:%d send msg %d times\n", tcp_demo_ip[0], tcp_demo_ip[1], tcp_demo_ip[2], tcp_demo_ip[3], tcp_demo_port, tcp_send_num);
lwip_config_tcp(enet_port, lwip_ipaddr, lwip_netmask, tcp_demo_ip);
memcpy(param.ip, tcp_demo_ip, 4);
@ -101,7 +124,7 @@ void LwipTcpSendTest(int argc, char *argv[])
}
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN) | SHELL_CMD_PARAM_NUM(3),
TCPSend, LwipTcpSendTest, TCP Send message);
TCPSend, LwipTcpSendTest, TCPSend msg [ip:port [num [interval]]]);
void LwipTcpRecvTest(void)
{

View File

@ -23,14 +23,18 @@
#include "lwip/sockets.h"
#include <shell.h>
#include <sys.h>
#include <xizi.h>
#define PBUF_SIZE 27
static struct udp_pcb *udpecho_raw_pcb;
char udp_demo_ip[] = {192, 168, 250, 252};
char udp_demo_ip[] = {192, 168, 131, 1};
u16_t udp_demo_port = LWIP_TARGET_PORT;
int32 udp_send_num = 0;
int8 udp_send_task_on = 0;
uint32 udp_interval = 50;
char hello_str[] = {"hello world\r\n"};
char udp_demo_msg[] = "\nThis one is UDP package!!!\n";
@ -66,21 +70,37 @@ static void LwipUDPSendTask(void *arg)
lw_notice("UDP connect success, start to send.\n");
lw_notice("\n\nTarget Port:%d\n\n", udp_sock.sin_port);
udp_send_task_on = 1;
sendto(socket_fd, udp_demo_msg, strlen(udp_demo_msg), 0, (struct sockaddr*)&udp_sock, sizeof(struct sockaddr));
lw_notice("Send UDP msg: %s ", udp_demo_msg);
while(udp_send_num > 0 || udp_send_num == -1)
{
sendto(socket_fd, udp_demo_msg, strlen(udp_demo_msg), 0, (struct sockaddr*)&udp_sock, sizeof(struct sockaddr));
lw_notice("Send UDP msg: %s \n", udp_demo_msg);
DelayKTask(udp_interval);
udp_send_num--;
}
closesocket(socket_fd);
udp_send_task_on = 0;
return;
}
void *LwipUdpSendTest(int argc, char *argv[])
{
if(udp_send_task_on){
udp_send_num = 0;
printf("waitting send task exit...\n");
while(udp_send_task_on){
DelayKTask(1000);
}
udp_send_num = 1;
}
uint8_t enet_port = 0; ///< test enet port 0
memset(udp_demo_msg, 0, sizeof(udp_demo_msg));
if(argc == 1)
{
lw_print("lw: [%s] gw %d.%d.%d.%d\n", __func__, udp_demo_ip[0], udp_demo_ip[1], udp_demo_ip[2], udp_demo_ip[3]);
lw_print("lw: [%s] gw %d.%d.%d.%d:%d\n", __func__, udp_demo_ip[0], udp_demo_ip[1], udp_demo_ip[2], udp_demo_ip[3], udp_demo_port);
strncpy(udp_demo_msg, hello_str, strlen(hello_str));
}
else
@ -89,18 +109,23 @@ void *LwipUdpSendTest(int argc, char *argv[])
strncat(udp_demo_msg, "\r\n", 2);
if(argc == 3)
{
sscanf(argv[2], "%d.%d.%d.%d", &udp_demo_ip[0], &udp_demo_ip[1], &udp_demo_ip[2], &udp_demo_ip[3]);
sscanf(argv[2], "%d.%d.%d.%d:%d", &udp_demo_ip[0], &udp_demo_ip[1], &udp_demo_ip[2], &udp_demo_ip[3], &udp_demo_port);
}
if(argc > 3)
{
sscanf(argv[3], "%d", &udp_send_num);
sscanf(argv[4], "%d", &udp_interval);
}
}
lw_print("lw: [%s] gw %d.%d.%d.%d\n", __func__, udp_demo_ip[0], udp_demo_ip[1], udp_demo_ip[2], udp_demo_ip[3]);
lw_print("lw: [%s] gw %d.%d.%d.%d:%d send time %d udp_interval %d\n", __func__, udp_demo_ip[0], udp_demo_ip[1], udp_demo_ip[2], udp_demo_ip[3], udp_demo_port, udp_send_num, udp_interval);
lwip_config_net(enet_port, lwip_ipaddr, lwip_netmask, udp_demo_ip);
sys_thread_new("udp send", LwipUDPSendTask, NULL, LWIP_TASK_STACK_SIZE, LWIP_DEMO_TASK_PRIO);
}
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN) | SHELL_CMD_PARAM_NUM(3),
UDPSend, LwipUdpSendTest, UDP send echo);
UDPSend, LwipUdpSendTest, UDPSend msg [ip:port [num [interval]]]);
static void LwipUdpRecvTask(void *arg, struct udp_pcb *upcb, struct pbuf *p,
const ip_addr_t *addr, u16_t port)

View File

@ -38,6 +38,7 @@
*
*/
#include <sys/time.h>
#include <xs_ktask.h>
#include "lwip/opt.h"
@ -123,7 +124,9 @@ ping_prepare_echo( struct icmp_echo_hdr *iecho, u16_t len)
((char*)iecho)[sizeof(struct icmp_echo_hdr) + i] = (char)i;
}
#ifndef CHECKSUM_GEN_ICMP
iecho->chksum = inet_chksum(iecho, len);
#endif
}
#if PING_USE_SOCKETS
@ -208,7 +211,9 @@ ping_recv(int s)
LWIP_DEBUGF( PING_DEBUG, ("ping: recv "));
ip_addr_debug_print_val(PING_DEBUG, fromaddr);
#ifdef LWIP_DEBUG
LWIP_DEBUGF( PING_DEBUG, (" %"U32_F" ms\n", (sys_now() - ping_time)));
#endif
/* todo: support ICMP6 echo */
#if LWIP_IPV4
@ -232,7 +237,9 @@ ping_recv(int s)
}
if (len == 0) {
#ifdef LWIP_DEBUG
LWIP_DEBUGF( PING_DEBUG, ("ping: recv - %"U32_F" ms - timeout\n", (sys_now()-ping_time)));
#endif
}
/* do some ping result processing */
@ -274,7 +281,7 @@ ping_thread(void *arg)
lw_print("lw: [%s] ping start!\n", __func__);
ret = lwip_setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout));
LWIP_ASSERT("setting receive timeout failed", ret != 0);
LWIP_ASSERT("setting receive timeout failed", ret == 0);
LWIP_UNUSED_ARG(ret);
while (cnt --) {
@ -521,8 +528,10 @@ int get_url_ip(char* url)
#endif /* LWIP_DEBUG */
if ((recv_len = lwip_ping_recv(s, &ttl)) >= 0)
{
#ifdef LWIP_DEBUG
lw_notice("%d bytes from %s icmp_seq=%d ttl=%d time=%d ms\n", recv_len, inet_ntoa(ina), cnt,
ttl, sys_now() - ping_time);
#endif
}
else
{