cancel
Showing results for 
Search instead for 
Did you mean: 

NetXDuo and ThreadX : Increasing number of TCP Server response

Nicolas_G
Associate II

Dear Experts,

I’m currently working on a project involving an STM32 board (B-U585I-IOT02A). I would like to use this board as a TCP Server . Therefore, from the STM32CUBEIDE application, I had observed that there is an example project in which it is possible to render this board as a TCP Server (Nx_TCP_Echo_Server). However, my problem was that it only returns the value returned by the TCP Client. So, I wanted to modify this program so as to be able to retrieve the temperature parameters. So, I created a program based on an example (https://wiki.st.com/stm32mcu/wiki/STM32StepByStep:Step4_Sensors_usage). I wanted to combine these two programs to retrieve the temperature data.

To sum up, the diagram is as follows:

Nicolas_G_0-1708684494529.png

After activating the I2C module in the hal_conf.h file, I had no errors during debugging and was able to retrieve the temperature when sending a request from Node-Red. Nevertheless, this program has a number of flaws. The number of requests is limited, as you can see in the image below:

Nicolas_G_1-1708684574247.png

In the image above, I managed to send a total of five requests and collect the temperature, but unfortunately after the sixth request I lost communication with the STM32 board. I also noticed that the number of requests I could send was random. In fact, after resetting the board,  I am able to send more requests and sometimes I can send fewer.

On the application side, I'm using NetX Duo as well as ThreadX.

Would this have anything to do with memory? Would it be possible to increase the number of requests? If so, how could I do it?

You'll find the sections of main.c program and the app_netxduo.c code below.

Program main.c

 

 

int main(void)
{
  /* USER CODE BEGIN 1 */
  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* MPU Configuration--------------------------------------------------------*/
  MPU_Config();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* Configure the System Power */
  SystemPower_Config();

  /* USER CODE BEGIN SysInit */
  HAL_PWREx_EnableVddA();
  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_ICACHE_Init();
  MX_SPI2_Init();
  MX_USART1_UART_Init();
  MX_ADC1_Init();
  MX_ADC4_Init();
  MX_I2C2_Init();
  MX_TIM3_Init();
  MX_DCACHE1_Init();

  BSP_ENV_SENSOR_Init(0, ENV_TEMPERATURE);
  BSP_ENV_SENSOR_Enable(0, ENV_TEMPERATURE);

  /* USER CODE BEGIN 2 */

  HAL_UART_Transmit(&huart1, msg1, sizeof(msg1), 1000);
  //HAL_UART_Transmit(&huart1, msg2, sizeof(msg2), 1000);
  //HAL_UART_Transmit(&huart1, msg3, sizeof(msg3), 1000);

  /* USER CODE END 2 */

  MX_ThreadX_Init();

  //mp_main_fifo();

  /* We should never get here as control is now taken by the scheduler */
  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

 

 

Program App_netduo.c : 

 

 

static VOID App_TCP_Thread_Entry(ULONG thread_input)
{
  UINT ret;
  UCHAR data_buffer[25];


  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); // Problème n°1 : Lorsque j'envoie une première requête, c'est ici que ça bloque (ret =54)
      ret = 0;
    }
    
    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)
      {
        HAL_GPIO_TogglePin(LED_GREEN_GPIO_Port, LED_GREEN_Pin);
        
        /* 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);
        
        BSP_ENV_SENSOR_GetValue(0, ENV_TEMPERATURE, &temp_value);
        int tmpInt1 = temp_value;
        float tmpFrac = temp_value - tmpInt1;
        int tmpInt2 = trunc(tmpFrac *100);

        snprintf((char *) data_buffer, 25, "{\"TEMPERATURE\" : %d.%02d}\r\n", tmpInt1, tmpInt2);

        /* print the received data */
        PRINT_DATA(source_ip_address, source_port, data_buffer);

        nx_packet_allocate(&AppPool, &send_packet, NX_TCP_PACKET, NX_WAIT_FOREVER); // Normalement c'est là le problème

        nx_packet_data_append(send_packet,data_buffer,30,&AppPool,NX_WAIT_FOREVER);


        /* immediately resend the same packet */
        ret = nx_tcp_socket_send(&TCPSocket, send_packet, NX_WAIT_FOREVER);

        nx_packet_release(data_packet);


        tx_thread_sleep(5); /* Delay 50ms between each pub */


        if (ret == NX_SUCCESS)
        {
          HAL_GPIO_TogglePin(LED_GREEN_GPIO_Port, LED_GREEN_Pin);
        }

      }
      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 */
      HAL_GPIO_TogglePin(LED_GREEN_GPIO_Port, LED_GREEN_Pin);
    }
  }
}

 

 

 

I don't really know if it's related or not, but I'm having a problem when I activate the debugger, I get some kind of window informing that it's trying to access an address and that it's outside the memory area :

Nicolas_G_2-1708685721604.png

 

Thanks for your help,

Sincerely,

Nicolas Gnanalingam

5 REPLIES 5
STea
ST Employee

Hello @Nicolas_G ,

you can try increasing the stack size of your project as well as the stack size for the netxduo Handling thread and the ThreadX stack and heap sizes as well .

BR

In order to give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.
Nicolas_G
Associate II

Hello @STea,

Thanks for your reply.

Could you tell me how I can increase the stack size of my project, as well as the NetxDuo and ThreadX Stack an Heap size?

I don't really know how to do this.
However, a colleague and I have seen that you can modify parameters in the following files: app_azure_rtos_config.h and app_netxduo.h.

Unfortunately, changing these parameters didn't improve the situation.

 

STea
ST Employee

Hello @Nicolas_G ,

you need to modify :

in app_azure_rtos_config.h:

  • #define USE_STATIC_ALLOCATION                1
    #define TX_APP_MEM_POOL_SIZE                     2048
    #define NX_APP_MEM_POOL_SIZE                     225280

In the "stm32h5xx_hal_eth.h":

- Depending on the application scenario, the total TX and RX descriptors may need to be increased by updating respectively the "ETH_TX_DESC_CNT" and "ETH_RX_DESC_CNT"  but this will cost extra memory to allocate.

  • #ifndef ETH_TX_DESC_CNT
  • #define ETH_TX_DESC_CNT 8U
  • #endif /* ETH_TX_DESC_CNT */
  • #ifndef ETH_RX_DESC_CNT
  • #define ETH_RX_DESC_CNT 8U
  • #endif /* ETH_RX_DESC_CNT */

in app_netxduo.h :

  • #define NX_APP_THREAD_STACK_SIZE 3 * 1024
  • #define Nx_IP_INSTANCE_THREAD_SIZE 3 * 1024

 

BR

 

In order to give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.
Nicolas_G
Associate II

Hello @STea,

Thank you very much for your reply.

Unfortunately, I made some modifications in the program so I don't really know if it works. Indeed, instead of sending back the temperature data, I would like to push the accelerometer data (ISM330DHCX) into Node-Red. So I've taken a program from a colleague and applied its features to the App_Main_Thread_Entry() function in the app_netxduo.c file. In this function, I've added a new function (which I've called send_raw_data) that lets me display the accelerometer's data in UART.I also store these datas in a two-dimensional array (static char* tab_data[5000];).

So far, I've managed to store around 3,000 pieces of accelerometer data, but the problem is that after a large amount of data (e.g. 5,000), the program stops as if I'd saturated the memory. One line of the array will store the following string ""x":0.021968, "y":0.032501, "z":10.127225 ". The reason I'm storing all this data in an array is that, eventually, I'd like to push the whole array into a single TCP client request.

The send_raw_data function is as follows:

char** send_raw_data(float** p_dataf_axes, int* count){
	char uart_buf[40];

	printf("Value:  %d\n", *count ); //*count = 40960

	int uart_buf_len;
	int i;

	for(i = 0; i < 5000; i++){
	//for(int i = 0; i < 100; i++){
		if(i % FIFO_BUFFER_SIZE == 0){
			uart_buf_len = sprintf(uart_buf,"\r\nG%d", (int)(i / (FIFO_BUFFER_SIZE)));
			HAL_UART_Transmit(&huart1, (uint8_t *)uart_buf, uart_buf_len, 100);
		}

		uart_buf_len = sprintf(uart_buf, //sizeof(uart_buf),
				"\"x\":%f,\"y\":%f,\"z\":%f\r\n",
				*(*p_dataf_axes + i),
				*(*p_dataf_axes + MAX_ACQUISITION_DATA + i),
				*(*p_dataf_axes + MAX_ACQUISITION_DATA * 2 + i));


		// uart_buf_len = sprintf(uart_buf,"a");


		//printf("uart = %s\r\n", uart_buf);


		tab_data[i] = (char *) malloc(sizeof(uart_buf));

		strcpy(tab_data[i], uart_buf);

		//memcpy(tab_data[i], uart_buf, strlen(uart_buf)+1)

		HAL_UART_Transmit(&huart1, (uint8_t *)uart_buf, uart_buf_len, 1000);



	}

	printf("\r\ni vaut %d \n", i);

	uart_buf_len = sprintf(uart_buf,"\r\n");


	HAL_UART_Transmit(&huart1, (uint8_t *)uart_buf, uart_buf_len, 1000);
	HAL_Delay(TEMPO_DELAY);

	return tab_data;

}

 

I'd like to have an array with a size of 40960, each row of which stores x, y and z acceleration data.

I've tried making modifications to the azure_rtos_config.h and app_netxduo.h files as recommended above, but the problem is that I have much less data displayed in UART. On the other hand, when I reduce the size of the NX_APP_MEM_POOL_SIZE in the app_azure_rtos_config.h file, I have a lot more data, but unfortunately it's not enough to reach the 40920 data.

What can I do to store so much accelerometer data because it's essential to be able to push all this accelerometer data to the TCP Client later on?

Please help me because I'm really struggling to find a solution to this problem.

Yours sincerely

Nicolas Gnanalingam

Nicolas_G_0-1710522815860.png

this picture shows that the program stopped after certain data sequences.

****Temperature values measurement **** is the message I display at the start of the program, so there's been a reset. 

Hello @Nicolas_G ,

if you are facing constrains with the memory size i suggest you use the External OCTOSPI memory  MX25LM51245G or the PSRAM in memory mapped mode.

this  Memory can be used to store the data you are willing to store and you can easily access it when you are ready to use it and you can offload the Flash memory to make it handle the Threadx and Netxduo communication .

BR

In order to give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.