Add ping command in letter-shell in ch32v208rbt6

1. add ping.c for ping command.
2. add ping.c in Makefile.
3. move global variable DESP[4] from wch_tcp_test.c to connect_ether.c.
This commit is contained in:
huoyujia081 2024-05-28 16:25:24 +08:00
parent ab8a00ca93
commit 6936e0e565
6 changed files with 489 additions and 18 deletions

View File

@ -81,20 +81,8 @@ void ETH_IRQHandler(void)
*/
void TIM2_IRQHandler(void)
{
// GET_INT_SP();
// /* enter interrupt */
// x_base level;
// level = DisableLocalInterrupt();
// isrManager.done->incCounter();
// EnableLocalInterrupt(level);
// WCHNET_TimeIsr(WCHNETTIMERPERIOD);
// TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
// /* leave interrupt */
// level = DisableLocalInterrupt();
// isrManager.done->decCounter();
// EnableLocalInterrupt(level);
// FREE_INT_SP();
// KPrintf("%s %s %d\n", __FILE__, __FUNCTION__, __LINE__);
extern u32 timeCnt;
timeCnt++;
WCHNET_TimeIsr(WCHNETTIMERPERIOD);
TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
}

View File

@ -1,4 +1,3 @@
SRC_FILES := wch_tcp_test.c
SRC_FILES := wch_tcp_test.c ping.c
include $(KERNEL_ROOT)/compiler.mk

View File

@ -0,0 +1,406 @@
#include "ping.h"
#include "connect_ether.h"
#include "eth_driver.h"
#include "shell.h"
#include "string.h"
#include "wchnet.h"
#include "xs_base.h"
u8 sendErrCnt;
u8 unreachCnt;
u8 timeoutCnt;
u8 sucRecCnt;
u8 sendBuf[100];
u8 ICMPCnt = 0;
u8 ICMPSeq = 0;
u8 ICMPSuc = 0;
u8 ICMPTmpVal = 0;
u32 timeCnt;
int pingSendCount = 0; // the times of ping data sending
extern u8 MACAddr[6]; // MAC address
extern u8 IPAddr[4]; // IP address
extern u8 GWIPAddr[4]; // Gateway IP address
extern u8 IPMask[4]; // subnet mask
extern u8 DESIP[4]; // destination IP address
u8 IPRawProto = 1;
extern u8 SocketId; // socket id
extern u8 SocketRecvBuf[WCHNET_MAX_SOCKET_NUM]
[RECE_BUF_LEN]; // socket receive buffer
extern u8 MyBuf[RECE_BUF_LEN];
/*********************************************************************
* @fn WCHNET_CreateIPRawSocket
*
* @brief Create raw IP Socket
*
* @return none
*/
void WCHNET_CreateIPRawSocket(void) {
u8 i;
SOCK_INF TmpSocketInf;
memset((void *)&TmpSocketInf, 0, sizeof(SOCK_INF));
memcpy((void *)TmpSocketInf.IPAddr, DESIP, 4);
TmpSocketInf.SourPort =
IPRawProto; // In IPRAW mode, SourPort is the protocol type
TmpSocketInf.ProtoType = PROTO_TYPE_IP_RAW;
TmpSocketInf.RecvStartPoint = (u32)(SocketRecvBuf[0]);
TmpSocketInf.RecvBufLen = RECE_BUF_LEN;
i = WCHNET_SocketCreat(&SocketId, &TmpSocketInf);
memset(SocketRecvBuf[0], 0, RECE_BUF_LEN);
mStopIfError(i);
}
/*********************************************************************
* @fn InitParameter
*
* @brief Initializes parameters.
*
* @return none
*/
void InitParameter(void) {
unreachCnt = 0;
timeoutCnt = 0;
sucRecCnt = 0;
ICMPSuc = ICMP_SOKE_CON;
pingSendCount = 0;
}
/*********************************************************************
* @fn InitPING
*
* @brief Initializes PING.
*
* @return none
*/
void InitPING(void) {
IcmpHeader head;
u32 check_sum = 0;
u8 i;
ICMPCnt++;
ICMPSeq += 1;
head.i_type = ICMP_HEAD_TYPE;
head.i_code = ICMP_HEAD_CODE;
head.i_id = ICMP_HEAD_ID;
head.i_seq = ICMP_HEAD_SEQ + ICMPSeq;
memset(head.i_data, 0, sizeof(head.i_data));
for (i = 0; i < ICMP_DATA_BYTES; i++) {
if (i < 26)
head.i_data[i] = i + 'a';
else
head.i_data[i] = i + 'a' - 26;
if (i % 2 == 0)
check_sum += head.i_data[i] << 8;
else
check_sum += head.i_data[i];
}
check_sum += head.i_type << 8;
check_sum += head.i_code;
check_sum += head.i_id;
check_sum += head.i_seq;
head.i_cksum = check_sum >> 16;
head.i_cksum += check_sum & 0xffff;
head.i_cksum = 0xffff - head.i_cksum;
memset(sendBuf, 0, sizeof(sendBuf));
memcpy(sendBuf, &head, sizeof(head));
sendBuf[2] = head.i_cksum >> 8;
sendBuf[3] = head.i_cksum & 0xff;
sendBuf[4] = head.i_id >> 8;
sendBuf[5] = head.i_id & 0xff;
sendBuf[6] = head.i_seq >> 8;
sendBuf[7] = head.i_seq & 0xff;
}
/*********************************************************************
* @fn Respond_PING
*
* @brief Respond to PING request.
*
* @param pDat - ACK data.
*
* @return none
*/
void Respond_PING(u8 *pDat) {
IcmpHeader head;
u32 check_sum = 0;
u8 i;
head.i_type = ICMP_HEAD_REPLY;
head.i_code = pDat[1];
head.i_id = (pDat[4] << 8) + pDat[5];
head.i_seq = (pDat[6] << 8) + pDat[7];
check_sum += head.i_type << 8;
check_sum += head.i_code;
check_sum += head.i_id;
check_sum += head.i_seq;
for (i = 0; i < 32; i++) {
head.i_data[i] = pDat[i + 8];
if (i % 2 == 0)
check_sum += head.i_data[i] << 8;
else
check_sum += head.i_data[i];
}
head.i_cksum = check_sum >> 16;
head.i_cksum += check_sum & 0xffff;
head.i_cksum = 0xffff - head.i_cksum;
memset(sendBuf, 0, sizeof(sendBuf));
memcpy(sendBuf, &head, sizeof(head));
sendBuf[2] = head.i_cksum >> 8;
sendBuf[3] = head.i_cksum & 0xff;
sendBuf[4] = head.i_id >> 8;
sendBuf[5] = head.i_id & 0xff;
sendBuf[6] = head.i_seq >> 8;
sendBuf[7] = head.i_seq & 0xff;
}
/*********************************************************************
* @fn WCHNET_ICMPRecvData
*
* @brief receive and parse data.
*
* @param len - data length.
* pDat - data buff
*
* @return none
*/
void WCHNET_ICMPRecvData(u32 len, u8 *pDat) {
u16 tmp = 0;
ICMPTmpVal = ICMPSuc;
ICMPSuc = 3;
if (len == 40) {
if (pDat[0] == ICMP_HEAD_REPLY) {
if (pDat[1] == ICMP_HEAD_CODE) {
tmp = pDat[4];
tmp = tmp << 8;
tmp += pDat[5];
if (tmp == ICMP_HEAD_ID) {
tmp = pDat[6];
tmp = (tmp << 8);
tmp += pDat[7] - ICMPSeq;
if (tmp == ICMP_HEAD_SEQ) {
ICMPSuc = ICMP_RECV_SUC;
}
}
}
}
if (pDat[0] == ICMP_HEAD_TYPE) {
if (pDat[1] == ICMP_HEAD_CODE) {
Respond_PING(pDat);
ICMPSuc = ICMP_REPLY;
}
}
} else {
if (pDat[0] == 3) {
if (pDat[1] == 1) {
ICMPSuc = ICMP_UNRECH;
}
}
}
}
/*********************************************************************
* @fn WCHNET_PINGSendData
*
* @brief send PING command.
*
* @param PSend - data buff.
* Len - data length
* id - socket id
*
* @return none
*/
void WCHNET_PINGSendData(u8 *PSend, u32 Len, u8 id) {
u32 length;
u8 i, count = 0;
length = Len;
count = 0;
while (1) {
Len = length;
i = WCHNET_SocketSend(id, PSend, &Len);
pingSendCount++;
mStopIfError(i);
if (Len == 0) {
count++;
if (count > 2) {
return;
}
}
length -= Len;
PSend += Len; // offset buffer pointer
if (length) continue; // If the data is not sent, continue to send
break;
}
ICMPSuc++;
}
/*********************************************************************
* @fn WCHNET_PINGCmd
*
* @brief Query status and execute corresponding commands.
*
* @return none
*/
void WCHNET_PINGCmd(void) {
if (ICMPSuc < ICMP_KEEP_NO) {
switch (ICMPSuc) {
case ICMP_SOKE_CON:
ICMPSuc = 1;
timeCnt = 0;
KPrintf("Ping %d.%d.%d.%d with %d bytes of data.\r\n",
(u16)DESIP[0], (u16)DESIP[1], (u16)DESIP[2],
(u16)DESIP[3], (u16)ICMP_DATA_BYTES);
WCHNET_PINGSendData(sendBuf, 40, SocketId);
break;
case ICMP_SEND_ERR:
if (sendErrCnt > 10) {
KPrintf(
"Ping statistics for %d.%d.%d.%d:\r\nPackets: Sent = "
"%d,Received = %d,Lost = %d<%d%% loss>.\r\n",
(u16)DESIP[0], (u16)DESIP[1], (u16)DESIP[2],
(u16)DESIP[3], pingSendCount, (u16)sucRecCnt,
(u16)(pingSendCount - sucRecCnt),
(u16)((pingSendCount - sucRecCnt) * 100 /
pingSendCount));
ICMPSuc = ICMP_KEEP_NO;
sendErrCnt = 0;
}
if (timeCnt > 250) {
KPrintf("send data fail!\n");
timeCnt = 0;
sendErrCnt++;
WCHNET_PINGSendData(sendBuf, 40, SocketId);
}
break;
case ICMP_SEND_SUC:
if (timeCnt > 100) {
KPrintf("Request timeout.\n");
timeoutCnt++;
if (ICMPCnt < PING_SEND_CNT) {
ICMPSuc = 1;
InitPING();
timeCnt = 0;
WCHNET_PINGSendData(sendBuf, 40, SocketId);
} else {
KPrintf("PING end!\r\n");
KPrintf("send = %d Received = %d\n", PING_SEND_CNT,
sucRecCnt);
ICMPSuc = ICMP_KEEP_NO;
}
}
break;
case ICMP_RECV_ERR: // error unknown
KPrintf("receive unknown data.\r\n");
ICMPSuc = ICMP_KEEP_NO;
break;
case ICMP_RECV_SUC: // success
KPrintf("Reply from %d.%d.%d.%d: bytes=%d time<4ms\r\n",
(u16)DESIP[0], (u16)DESIP[1], (u16)DESIP[2],
(u16)DESIP[3], (u16)ICMP_DATA_BYTES);
sucRecCnt++;
if (ICMPCnt < PING_SEND_CNT) {
ICMPSuc = 1;
InitPING();
timeCnt = 0;
WCHNET_PINGSendData(sendBuf, 40, SocketId);
} else {
KPrintf(
"Ping statistics for %d.%d.%d.%d:\r\nPackets: Sent = "
"%d,Received = %d,Lost = %d<%d%% loss>.\r\n",
(u16)DESIP[0], (u16)DESIP[1], (u16)DESIP[2],
(u16)DESIP[3], pingSendCount, (u16)sucRecCnt,
(u16)(pingSendCount - sucRecCnt),
(u16)((pingSendCount - sucRecCnt) * 100 /
pingSendCount));
ICMPSuc = ICMP_KEEP_NO;
}
break;
case ICMP_UNRECH: // unreachable
KPrintf(
"Reply from %d.%d.%d.%d: Destination host unreachable.\r\n",
(u16)DESIP[0], (u16)DESIP[1], (u16)DESIP[2], (u16)DESIP[3]);
unreachCnt++;
if (ICMPCnt < PING_SEND_CNT) {
ICMPSuc = 1;
InitPING();
timeCnt = 0;
WCHNET_PINGSendData(sendBuf, 40, SocketId);
} else {
KPrintf("PING end!\r\n");
KPrintf("send = %d Received = %d", PING_SEND_CNT,
sucRecCnt);
ICMPSuc = ICMP_KEEP_NO;
}
break;
case ICMP_REPLY:
WCHNET_PINGSendData(sendBuf, 40, SocketId);
break;
case ICMP_REPLY_SUC:
KPrintf("Reply ping.\r\n");
ICMPSuc = ICMPTmpVal;
break;
case ICMP_KEEP_NO:
break;
default:
break;
}
}
}
void parseDesIP(char *argv[]) {
char charDesIP[4][4];
int i;
int j = 0;
int k = 0;
for (i = 0;; i++) {
// KPrintf("%c\n", argv[1][i]);
if (argv[1][i] == '\0') {
charDesIP[j][k++] = '\0';
break;
} else if (argv[1][i] == '.') {
charDesIP[j++][k] = '\0';
k = 0;
} else {
charDesIP[j][k++] = argv[1][i];
}
}
for (i = 0; i < 4; i++) {
DESIP[i] = atoi(charDesIP[i]);
}
// KPrintf("%s.%s.%s.%s\n", charDesIP[0], charDesIP[1], charDesIP[2],
// charDesIP[3]); KPrintf("%d.%d.%d.%d\n", DESIP[0], DESIP[1], DESIP[2],
// DESIP[3]);
}
int ping(int argc, char *argv[]) {
if (argc != 2) {
KPrintf("Usage: ping <ip>\r\n");
return 1;
}
parseDesIP(argv);
WCHNET_CreateIPRawSocket();
InitParameter();
InitPING();
while (1) {
/*Ethernet library main task function,
* which needs to be called cyclically*/
WCHNET_MainTask();
/*Query the Ethernet global interrupt,
* if there is an interrupt, call the global interrupt handler*/
if (WCHNET_QueryGlobalInt()) {
WCHNET_HandleGlobalInt();
}
WCHNET_PINGCmd();
if (ICMPSuc == ICMP_KEEP_NO) {
break;
}
}
WCHNET_SocketClose(SocketId, TCP_CLOSE_NORMAL);
ICMPCnt = 0; // restore the original ICMPCnt
}
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN),
ping, ping, test tcp client);

View File

@ -4,10 +4,9 @@
#include "wchnet.h"
#include "xs_base.h"
uint8_t DESIP[4] = { 192, 168, 1, 100 }; // destination IP address
uint16_t desport = 1000; // destination port
uint16_t srcport = 1000; // source port
extern uint8_t DESIP[4];
uint8_t SocketId;
/*********************************************************************

View File

@ -0,0 +1,77 @@
/********************************** (C) COPYRIGHT *******************************
* File Name : main.c
* Author : WCH
* Version : V1.0.0
* Date : 2022/06/11
* Description : Definition for PING.c.
*********************************************************************************
* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
* Attention: This software (modified or not) and binary are used for
* microcontroller manufactured by Nanjing Qinheng Microelectronics.
*******************************************************************************/
#ifndef __PINC_H__
#define __PINC_H__
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include "wchnet.h"
#include "debug.h"
// ICMP常量定义
// 用于标识ICMP消息的不同类型和状态
#define ICMP_SOKE_CON 0 // 初始化状态
#define ICMP_SEND_ERR 1 // 发送错误
#define ICMP_SEND_SUC 2 // 发送成功
#define ICMP_RECV_ERR 3 // 接收错误
#define ICMP_RECV_SUC 4 // 接收成功
#define ICMP_UNRECH 5 // 无法到达
#define ICMP_REPLY 6 // 回复
#define ICMP_REPLY_SUC 7 // 回复成功
#define ICMP_KEEP_NO 10 // 保持连接数
// ICMP头部常量定义
// 用于构建和解析ICMP头部信息
#define ICMP_HEAD_TYPE 8 // ICMP头部类型
#define ICMP_HEAD_REPLY 0 // 回复消息类型
#define ICMP_HEAD_CODE 0 // 头部代码
#define ICMP_HEAD_ID 512 // 消息ID
#define ICMP_HEAD_SEQ 100 // 序列号
#define ICMP_DATA_BYTES 32 // 数据区字节数
// Ping发送计数定义
// 用于控制Ping请求发送的次数
#define PING_SEND_CNT 5 // 默认发送5次请求
/*ICMP header field data structure*/
typedef struct _icmphdr
{
u8 i_type; //ICMP message type
u8 i_code; //code number in the type
u16 i_cksum; //checksum
u16 i_id; //identifier
u16 i_seq; //sequence
u8 i_data[32]; //data area
}IcmpHeader,*IcmpHead;
extern u8 DESIP[4];
extern u8 ICMPSuc;
extern void InitPING( void );
extern void InitParameter( void );
extern void WCHNET_PINGCmd( void );
extern void WCHNET_PINGInit( void );
extern void mStopIfError(u8 iError);
extern void Respond_PING( u8 *pDat );
extern void WCHNET_ICMPRecvData( u32 len, u8 *pDat );
extern void WCHNET_PINGSendData( u8 *PSend, u32 Len,u8 id );
extern void WCHNET_ProcessReceDat( char *recv_buff,u8 check_type,u8 socketid );
#endif

View File

@ -660,6 +660,8 @@ void *x_malloc(x_size_t size)
KPrintf("dynamic_buddy_end:%d\n", ByteManager.dynamic_buddy_manager.dynamic_buddy_end);
KPrintf("dynamic_buddy_start:%d\n", ByteManager.dynamic_buddy_manager.dynamic_buddy_start);
KPrintf("active_memory:%d\n", ByteManager.dynamic_buddy_manager.active_memory);
extern int ShowTask();
ShowTask();
return NONE;
}
#endif