stm32开发之threadx+netxduo(tcp 客户端使用记录)

05-13 1345阅读

前言

  1. 本篇涉及到的内容: threadx之动态内存的实现记录、stm32开发之实现代码之间解耦(借助链接文件和关键字section)

代码

/*
 * Copyright (c) 2024-2024,shchl
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 2024-4-9     shchl   first version
 */
#include "includes.h"
#if 1
#define     TCP_CLIENT_STACK_SIZE       4096  /*任务栈大小*/
#define     TCP_CLIENT_PRIORITY         4     /*优先级*/
#define     PACKET_SIZE                 1536 /*数据包大小*/
#define     POOL_SIZE                   ((sizeof(NX_PACKET) + PACKET_SIZE) * 16) /*数据包池大小(16个缓冲区)*/
#define     TCP_LOCAL_IP               IP_ADDRESS(192, 168, 8, 9) /*本地ip*/
#define     TCP_LOCAL_PORT             8000
#define     TCP_LOCAL_SUB_MASH         IP_ADDRESS(255,255,255,0) /*本地ip*/
#define     TCP_SERVER_PORT            8080
#define     TCP_SEVER_IP               IP_ADDRESS(192, 168, 8, 2)
static ULONG error_counter;
static NX_IP tcp_client_ip;
static TX_THREAD tcp_client_thread;
static NX_PACKET_POOL tcp_client_packet_pool;
static NX_TCP_SOCKET client_socket;
static void tcp_client_entry(ULONG input);
static inline void status_check(UINT stat) {
    if (stat) {
        error_counter++;
        // todo
    }
}
int app_task_tcp_client_thread_create() {
    UINT status;
    /* Create the main thread.  */
    tx_thread_create(&tcp_client_thread,
                     "tcp client thread",
                     tcp_client_entry,
                     0,
                     app_malloc(TCP_CLIENT_STACK_SIZE),
                     TCP_CLIENT_STACK_SIZE,
                     TCP_CLIENT_PRIORITY,
                     TCP_CLIENT_PRIORITY,
                     TX_NO_TIME_SLICE,
                     TX_AUTO_START);
    /* Create a packet pool.  */
    status = nx_packet_pool_create(&tcp_client_packet_pool,
                                   "NetX Main Packet Pool",
                                   PACKET_SIZE,
                                   app_malloc(POOL_SIZE),
                                   POOL_SIZE);
    status_check(status);
    /* Create an IP instance.  */
    status = nx_ip_create(&tcp_client_ip, "ip instance",
                          TCP_LOCAL_IP,
                          TCP_LOCAL_SUB_MASH,
                          &tcp_client_packet_pool,
                          nx_stm32_eth_driver,
                          app_malloc(2048), 2048, 1);
    status_check(status);
    /* Enable ARP and supply ARP cache memory for IP Instance 0.  */
    status = nx_arp_enable(&tcp_client_ip, app_malloc(1024), 1024);
    /* Check ARP enable status.  */
    status_check(status);
    /* Enable ICMP */
    status = nxd_icmp_enable(&tcp_client_ip);
    status_check(status);
    /* Enable TCP processing for both IP instances.  */
    status = nx_tcp_enable(&tcp_client_ip);
    status_check(status);
    return NX_SUCCESS;
}
static void tcp_client_release_resource(NX_TCP_SOCKET *socket_ptr);
static UINT tcp_client_build_connection(NX_TCP_SOCKET *socket_ptr, NXD_ADDRESS *server_addr);
static void tcp_client_entry(ULONG input) {
    NX_PARAMETER_NOT_USED(input);
    UINT status;
    NX_PACKET *my_packet;
    ULONG length;
    NXD_ADDRESS server_ipv4_address;
    ULONG actual_status;
    /* 确保 IP 实例已初始化。  */
    do {
        /* 等待 1 秒钟,让 内部 IP 线程完成其初始化。. */
        status = nx_ip_status_check(&tcp_client_ip,
                                    NX_IP_INITIALIZE_DONE,
                                    &actual_status,
                                    NX_IP_PERIODIC_RATE);
    } while (status != NX_SUCCESS);
    /* set the TCP server addresses. */
    server_ipv4_address.nxd_ip_version = NX_IP_VERSION_V4;
    server_ipv4_address.nxd_ip_address.v4 = TCP_SEVER_IP;
    /* Loop to repeat things over and over again!  */
    while (1) {
        /*建立连接*/
        do {
            tx_thread_sleep(1000);/*建立连接失败等待1s*/
            status = tcp_client_build_connection(&client_socket, &server_ipv4_address);
        } while (status);
        /*和服务端通讯(todo 业务逻辑切入点)*/
        {
            retry_send:
            status = nx_packet_allocate(&tcp_client_packet_pool,
                                        &my_packet,
                                        NX_TCP_PACKET,
                                        NX_WAIT_FOREVER);
#define SEND_DATA "hello server, i is client"
            /* Check status.  */
            if (status != NX_SUCCESS) {
                tx_log("Error nx_packet_allocate: 0x%x\n", status);
                break;
            }
            /* Write ABCs into the packet payload!  */
            nx_packet_data_append(my_packet,
                                  SEND_DATA,
                                  sizeof(SEND_DATA),
                                  &tcp_client_packet_pool,
                                  TX_WAIT_FOREVER);
            status = nx_packet_length_get(my_packet, &length);
            if ((status) || (length != sizeof(SEND_DATA))) {
                error_counter++;
            }
            /* Send the packet out!  */
            status = nx_tcp_socket_send(&client_socket, my_packet, NX_IP_PERIODIC_RATE);
            /* Determine if the status is valid.  */
            if (status) {
                error_counter++;
                tx_log("send error:%#x\r\n", status);
                nx_packet_release(my_packet);
            } else {
                tx_thread_sleep(200);
                goto retry_send;
            }
        }
        /*释放相关资源*/
        tcp_client_release_resource(&client_socket);
    }
}
NET_X_APP_EXPORT(app_task_tcp_client_thread_create);
// 建立连接
static UINT tcp_client_build_connection(NX_TCP_SOCKET *socket_ptr, NXD_ADDRESS *server_addr) {
    UINT status;
    /* Create a socket.  */
    status = nx_tcp_socket_create(&tcp_client_ip, socket_ptr, "Client Socket",
                                  NX_IP_NORMAL,
                                  NX_FRAGMENT_OKAY,
                                  NX_IP_TIME_TO_LIVE,
                                  PACKET_SIZE,
                                  NX_NULL,
                                  NX_NULL);
    status_check(status);
    /* Bind the socket.  */
    status = nx_tcp_client_socket_bind(socket_ptr, TCP_LOCAL_PORT, NX_WAIT_FOREVER);
    status_check(status);
    /* Attempt to connect the socket.  */
    status = nxd_tcp_client_socket_connect(socket_ptr, server_addr, TCP_SERVER_PORT, NX_IP_PERIODIC_RATE);
    if (status) { // 连接失败,清理资源
        tcp_client_release_resource(socket_ptr);
    }
    return status;
}
// 资源释放
static void tcp_client_release_resource(NX_TCP_SOCKET *socket_ptr) {
    UINT status = 0;
    /*socket 状态处于已经建立连接或等待关闭,则需要关闭连接*/
    if (socket_ptr->nx_tcp_socket_state == NX_TCP_ESTABLISHED || socket_ptr->nx_tcp_socket_state == NX_TCP_CLOSE_WAIT) {
        status = nx_tcp_socket_disconnect(&client_socket, NX_IP_PERIODIC_RATE);
    }
    /* Determine if the status is valid.  */
    if (status) {
        tx_log("nx_tcp_socket_disconnect error:%#x\r\n", status);
        error_counter++;
    }
    /* Unbind the socket.  */
    status = nx_tcp_client_socket_unbind(&client_socket);
    /* Check for error.  */
    if (status) {
        tx_log("nx_tcp_client_socket_unbind error:%#x\r\n", status);
        error_counter++;
    }
    /* Delete the socket.  */
    status = nx_tcp_socket_delete(&client_socket);
    /* Check for error.  */
    if (status) {
        tx_log("nx_tcp_socket_delete error:%#x\r\n", status);
        error_counter++;
    }
}
#endif

测试结果(ok)

stm32开发之threadx+netxduo(tcp 客户端使用记录)

VPS购买请点击我

文章版权声明:除非注明,否则均为主机测评原创文章,转载或复制请以超链接形式并注明出处。

目录[+]