forked from xuos/xiuos
Merge branch 'prepare_for_master' of https://gitlink.org.cn/xuos/xiuos into lorawan_develop
This commit is contained in:
commit
02b676e910
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
*
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
SRC_FILES := task.c schedule.c ipc.c
|
||||
SRC_FILES := schedule.c ipc.c
|
||||
|
||||
include $(KERNEL_ROOT)/compiler.mk
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
|
@ -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
|
|
@ -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 },
|
||||
};
|
||||
|
|
|
@ -1 +1,3 @@
|
|||
|
||||
config BSP_USING_ETH
|
||||
bool
|
||||
default y
|
|
@ -1,3 +1,3 @@
|
|||
SRC_FILES := ethernetif.c
|
||||
SRC_FILES := ethernetif.c eth_driver.c
|
||||
|
||||
include $(KERNEL_ROOT)/compiler.mk
|
||||
|
|
|
@ -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(ð_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;
|
||||
}
|
||||
|
||||
|
|
@ -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 = ðarp_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)) {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -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
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
SRC_FILES += lwiperf/lwiperf.c http/http_client.c
|
||||
|
||||
include $(KERNEL_ROOT)/compiler.mk
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
|
@ -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);
|
|
@ -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),
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue