2023-01-12 07:03 AM
First of all..... is anyone actually using the Azure RTOS package? I'm drinking the cool-aid provided by STM marketing. But, geez! ....how do you get started? I've been reading...and reading...and reading...but can't seem to crack the code (so to speak...:)
Specifically, I have been trying to figure out how the modify the NX_Tcp_Echo_Server example so that it DOESN'T echo the data received from the network. Instead I am forwarding the received data_buffer array ("command") to USART2 which goes to a second board. The second board then responds to the command with a 64 byte "response". I use the HAL_UART_Transmit and Receive functions to do this, which (after fixing the USART2 bug in the example code) works fine. The Receive function returns the 64 bytes in the same data_buffer that was used to send the command.
My problem is....how to I "inject" this data_buffer response into the nx_tcp_socket_send() function? I'm sure there must be a simple process for this, but the information provide is a bit overwhelming, to say the least.
So my problem boils down to, how do I send 64 bytes of data through an existing socket? I'm sure it MUST be simple....right?
Here's the modified thread. After the HAL_Receive funtion returns, the data_buffer contains the 64 bytes of data that I want to return to the socket.
static VOID App_TCP_Thread_Entry(ULONG thread_input)
{
UINT ret;
UCHAR data_buffer[512];
ULONG source_ip_address;
NX_PACKET *data_packet;
UINT source_port;
ULONG bytes_read;
/* create the TCP socket */
ret = nx_tcp_socket_create(&IpInstance, &TCPSocket, "TCP Server Socket", NX_IP_NORMAL, NX_FRAGMENT_OKAY,
NX_IP_TIME_TO_LIVE, WINDOW_SIZE, NX_NULL, NX_NULL);
if (ret)
{
Error_Handler();
}
/*
* listen to new client connections.
* the TCP_listen_callback will release the 'Semaphore' when a new connection is available
*/
ret = nx_tcp_server_socket_listen(&IpInstance, DEFAULT_PORT, &TCPSocket, MAX_TCP_CLIENTS, tcp_listen_callback);
if (ret)
{
Error_Handler();
}
else
{
printf("TCP Server listening on PORT %d ..\n", DEFAULT_PORT);
}
if(tx_semaphore_get(&Semaphore, TX_WAIT_FOREVER) != TX_SUCCESS)
{
Error_Handler();
}
else
{
/* accept the new client connection before starting data exchange */
ret = nx_tcp_server_socket_accept(&TCPSocket, TX_WAIT_FOREVER);
if (ret)
{
Error_Handler();
}
}
while(1)
{
ULONG socket_state;
TX_MEMSET(data_buffer, '\0', sizeof(data_buffer));
/* get the socket state */
nx_tcp_socket_info_get(&TCPSocket, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &socket_state, NULL, NULL, NULL);
/* if the connections is not established then accept new ones, otherwise start receiving data */
if(socket_state != NX_TCP_ESTABLISHED)
{
ret = nx_tcp_server_socket_accept(&TCPSocket, NX_IP_PERIODIC_RATE);
}
if(ret == NX_SUCCESS)
{
/* receive the TCP packet send by the client */
ret = nx_tcp_socket_receive(&TCPSocket, &data_packet, NX_WAIT_FOREVER);
if (ret == NX_SUCCESS)
{
BSP_LED_Toggle(LED_GREEN);
/* get the client IP address and port */
nx_udp_source_extract(data_packet, &source_ip_address, &source_port);
/* retrieve the data sent by the client */
nx_packet_data_retrieve(data_packet, data_buffer, &bytes_read);
/* print the received data */
PRINT_DATA(source_ip_address, source_port, data_buffer);
HAL_UART_Transmit(&huart2, data_buffer, cmdLen, 0xFFFFFFFFU);
HAL_UART_Receive(&huart2, data_buffer,cmdLen,0x3E8U );//0x3E8U = 1000msec = 1Sec timeout
//Forward response to network
ret = nx_tcp_socket_send(&TCPSocket, data_packet, NX_IP_PERIODIC_RATE);
if (ret == NX_SUCCESS)
{
BSP_LED_Toggle(LED_GREEN);
}
}
else
{
nx_tcp_socket_disconnect(&TCPSocket, NX_WAIT_FOREVER);
nx_tcp_server_socket_unaccept(&TCPSocket);
nx_tcp_server_socket_relisten(&IpInstance, DEFAULT_PORT, &TCPSocket);
}
}
else
{
/*toggle the green led to indicate the idle state */
BSP_LED_Toggle(LED_GREEN);
}
}
}
Thanks,
MikeH
2023-01-14 11:00 AM
I guess since no one has answered by first question.... it answered itself...:)
I am still stuck on trying sending a response from my server to a client in an established socket using Netx Duo. I have 64 bytes in the data_buffer that I have received from the client, but when I attempt to use nx_tcp_socket_send to send the packet back to the client, the "send" simply echoes the same data back that was just received.
I have played around with setting the append and prepend pointer to the same location, thinking that "append" merely adds the appended data to the end of the data section of the data_packet
data_packet->nx_packet_append_ptr = data_packet->nx_packet_prepend_ptr;
This seems to work for getting the new data into the correct location in memory. But when I then attempt to Send the updated data_packet by calling nx_tcp_socket_send, the pointers get scrambled and the new data does not get sent. I have tried stepping through the code, but it is too confusing and I can't find what's getting corrupted.
I then attempted to set data_packet->nx_packet_length = 64 in hopes that it would let nx_tcp_socket_send know that the data_packet had changed. This seems to work for the first attempt, but does not work for subsequent packets.
I'm very surprised that there are no good (specific) examples, and step-by-step walkthroughs of now to do this. It seems like this would be one of the most common uses of NetX Duo.
It appears that STM is hitching its wagon to Azure RTOS. If you want folks to adopt it, I highly recommend more detailed examples (with code).
/rant
2023-01-16 09:26 AM
Ok...making progress.
I added a few function calls as shown below. This code creates a new data_packet which gets sent in the nx_tcp_socket_send function instead of modifying the original data_packet. After it is sent, I release the new packet as shown below.
ret = nx_packet_allocate(&AppPool,&data_packet,NX_TCP_PACKET,NX_WAIT_FOREVER);
ret = nx_packet_data_append(data_packet,data_buffer,cmdLen,&AppPool,NX_WAIT_FOREVER);
ret = nx_tcp_socket_send(&TCPSocket, data_packet, NX_WAIT_FOREVER);
nx_packet_release(data_packet);
These seem to work since I can now send an entire command/response transaction from my remote client through my NUCLEO H7 board, through the USART2 to/from my secondary board.
HOWEVER, it only works for 8 transactions. After that the thread gets suspended and the program no longer receives transactions.
How do I determine how/why the thread get suspended?
Below is the App_TCP_Thread_Entry portion of the app_netxduo.c code file.
static VOID App_TCP_Thread_Entry(ULONG thread_input)
{
UINT uret;
UINT ret;
UCHAR data_buffer[512];
ULONG source_ip_address;
NX_PACKET *data_packet;
UINT source_port;
ULONG bytes_read;
/* create the TCP socket */
ret = nx_tcp_socket_create(&IpInstance, &TCPSocket, "TCP Server Socket", NX_IP_NORMAL, NX_FRAGMENT_OKAY,
NX_IP_TIME_TO_LIVE, WINDOW_SIZE, NX_NULL, NX_NULL);
if (ret)
{
Error_Handler();
}
/*
* listen to new client connections.
* the TCP_listen_callback will release the 'Semaphore' when a new connection is available
*/
ret = nx_tcp_server_socket_listen(&IpInstance, DEFAULT_PORT, &TCPSocket, MAX_TCP_CLIENTS, tcp_listen_callback);
if (ret)
{
Error_Handler();
}
else
{
printf("TCP Server listening on PORT %d ..\n", DEFAULT_PORT);
}
if(tx_semaphore_get(&Semaphore, TX_WAIT_FOREVER) != TX_SUCCESS)
{
Error_Handler();
}
else
{
/* accept the new client connection before starting data exchange */
ret = nx_tcp_server_socket_accept(&TCPSocket, TX_WAIT_FOREVER);
if (ret)
{
Error_Handler();
}
}
while(1)
{
ULONG socket_state;
TX_MEMSET(data_buffer, '\0', sizeof(data_buffer));
/* get the socket state */
nx_tcp_socket_info_get(&TCPSocket, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &socket_state, NULL, NULL, NULL);
/* if the connections is not established then accept new ones, otherwise start receiving data */
if(socket_state != NX_TCP_ESTABLISHED)
{
ret = nx_tcp_server_socket_accept(&TCPSocket, NX_IP_PERIODIC_RATE);
}
if(ret == NX_SUCCESS)
{
/* receive the TCP packet send by the client */
ret = nx_tcp_socket_receive(&TCPSocket, &data_packet, NX_WAIT_FOREVER);
if (ret == NX_SUCCESS)
{
BSP_LED_Toggle(LED_GREEN);
/* get the client IP address and port */
nx_udp_source_extract(data_packet, &source_ip_address, &source_port);
/* retrieve the data sent by the client */
nx_packet_data_retrieve(data_packet, data_buffer, &bytes_read);
int i;
printf("Command: ");
for(i=0; i<16; i++)
printf("%d,", data_buffer[i] );
printf("\n");
uret = HAL_UART_Transmit(&huart2, data_buffer, cmdLen, 0xFFFFFFFFU);
if(!uret)
{
uret = HAL_UART_Receive(&huart2, data_buffer, cmdLen, 2000 );//0x3E8U = 1000msec = 1Sec timeout
usart_data_available=false;
}
printf("Response: ");
for(i=0; i<16; i++) printf("%d,", data_buffer[i] );
printf("\n");
if(uret)
{
printf("USART Error %d.\n", ret);
nx_packet_release(send_packet);
}
else
{
ret = nx_packet_allocate(&AppPool,&data_packet,NX_TCP_PACKET,NX_WAIT_FOREVER);
ret = nx_packet_data_append(data_packet,data_buffer,cmdLen,&AppPool,NX_WAIT_FOREVER);
ret = nx_tcp_socket_send(&TCPSocket, data_packet, NX_WAIT_FOREVER);
nx_packet_release(data_packet);
}
if (ret == NX_SUCCESS)
{
BSP_LED_Toggle(LED_GREEN);
}
}
else
{
nx_tcp_socket_disconnect(&TCPSocket, NX_WAIT_FOREVER);
nx_tcp_server_socket_unaccept(&TCPSocket);
nx_tcp_server_socket_relisten(&IpInstance, DEFAULT_PORT, &TCPSocket);
}
}
else
{
/*toggle the green led to indicate the idle state */
BSP_LED_Toggle(LED_GREEN);
}
}
}
2024-04-30 01:14 AM
I know there is long time since you posted your question, but is now that I have been suffering the same issue and, even I think it is not going to be useful for you already, at least, it may be helpful for someone else in the future.
All the information I could find was about sending more bytes than the pool size, but what I wanted was to modify the frame received before sending it back inside the pool limits, so the info on the web was not useful for me.
First of all, I tried inserting my data bytes in the packet data sector and changing the packet lenght, in your case, that would be:
NX_PACKET * data_packet;
nx_tcp_socket_receive(p_sck, &data_packet, NX_NO_WAIT);
/* The received data starts at data_packet->nx_packet_prepend_ptr, just insert the data here */
p_packet->nx_packet_length=NEW_LENGHT;
nx_tcp_socket_send(p_sck, data_packet, NX_NO_WAIT);
But if the received data lenght was less that the data to send, the connection was closed and the TCP side got crazy...
So I tried your code, but I also was having your exactly same problem...
Finally, I went deep into the NetXDuo code and resolved the problem in a really easy way, just as you wanted.
NX_PACKET * data_packet;
uint16_t N_Bytes;
int16_t Dif_N_Bytes;
nx_tcp_socket_receive(p_sck, &data_packet, NX_NO_WAIT);
/* The received data starts at data_packet->nx_packet_prepend_ptr, just insert the data here */
N_Bytes=p_packet->nx_packet_length;
data_packet->nx_packet_length=NEW_LENGHT;
Dif_N_Bytes=p_packet->nx_packet_length-N_Bytes;
data_packet -> nx_packet_append_ptr =data_packet -> nx_packet_append_ptr + Dif_N_Bytes;
nx_tcp_socket_send(p_sck, data_packet, NX_NO_WAIT);
For me, with this simple way the comunication works fine.
Best Regards.
Egoitz