FreeRTOS TCP send first message but gets hardfault when sending second message

Hello,

Summary:

  • Abstract
  • Environnement
  • Previous posts
  • What I want to do
  • What I have done
  • What my problem is
  • Trying to fix
  • Terminal output
  • Questions
  • Code sample

##### ABSTRACT #####
My project used to work perfectly, I was sending TCP messages every 100ms from an STM32 to a Rapsberry pi.
I wanted to add authentication through an ID and a hashed password.
Once I made the hashing work, I was surprised to see that I now only receive the first message and that my STM gets stuck while sending the second message.

##### ENVIRONMENT #####
Card : STM32H723ZG
PC : Computer with Windows 10
IDE : stm32cubeIDE
Compiler : GCC 9.2.0
FreeRTOS : 202212.01

##### PREVIOUS POSTS #####

##### WHAT I WANT TO DO #####
I want to send TCP messages from the STM32 (client) to the Raspberry pi (server) receiving them in python.

##### What I have done #####
A server in Python that receives the data (encoded in protobuf) and display them (in the terminal and in a GUI made out of PyQt5).

A client for the STM32 that contains 2 tasks:

  • The sensor task that fetch the data from the sensor, puts them in a global uint8_t array then resume the TCP task.
  • The TCP task that waits to get resumed, then fill in a buffer with the data of the uint8_t array, encodes this data in protobuf using nanopb, sends the encoded message through TCP using FreeRTOS_send function and finaly suspends itself.

##### What my problem is #####
As I am encoding the message sent using protobuf, I made a new proto file to specify the encoding style to add an ID (uint8_t), password (uint8_t) and 2 other uint8_t that are not relevant.
I started programming the authentication loop and got basicaly no feedback from the terminal until the authentication worked.
Once it worked I only received the first frame sensed by the sensor (the first message) but then when the STM tries to send the second frame, it gets stuck in a hardfault.
I am able to see the first frame received in the GUI but then it doesn’t get updated because the update function gets called when receiving a new TCP message.

##### TRYING TO FIX : LOOKING ONLINE #####
Trying to goole “freertos tcp only send once” but I found my previous post haha.
No result found that were relevant.

##### TRYING TO FIX : RANDOM IDEA #####
Since the message got bigger I thought maybe the stack needed to be bigger so I doubled it even thought it is now whay too much. That did not change anything.

##### TRYING TO FIX : DEBUGGING #####
FreeRTOS_send inside main.c
XSendEventToIPTask on line 3752 of FreeRTOS_sockets.c
xSendEventStructToIPTask( &xEventMessage, xDontBlock ); on line 1123 of FreeRTOS_IP.c
xReturn = xQueueSendToBack( xNetworkEventQueue, pxEvent, uxUseTimeout ); 1179 of FreeRTOS_IP.c
if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) 901 queue.c
listREMOVE_ITEM( &( pxUnblockedTCB->xEventListItem ) ); 3189 tasks.c
can’t enter it, directly to hard fault

Here is what I get right before clicking “next step” (trying to enter the function, not to jump it):

Here is what I get right after trying to enter it :

And here are more informations about the hard fault such as PC :

##### TERMINAL OUTPUT #####

prvIPTask started
PHY ID 7C130
xPhyReset: phyBMCR_RESET 0 ready
+TCP: advertise: 01E1 config 3100
prvEthernetUpdateConfig: LS mask 00 Force 1
Autonego ready: 00000004: full duplex 100 mbit high status
Network buffers: 56 lowest 56
Link Status is high
prvInitialiseDHCP: start after 250 ticks
vDHCPProcess: discover
Network buffers: 56 lowest 55
RX descriptors 7/8
vDHCPProcess: offer a0123a6ip
vDHCPProcess: reply a0123a6ip
vDHCPProcess: offer a0123a6ip
vDHCPProcess: acked a0123a6ip
        GG : Entered vCreateTCPClientSocket with GG_CLIENT_TEST value of 2. (main.c)


IP Address: 10.1.35.166
Subnet Mask: 255.255.255.0
Gateway Address: 10.1.35.254
DNS Client Address: 192.168.73.220


FreeRTOS_connect: 585 to a012394ip:50053
ARP for a012394ip (using a012394ip): rc=0 00:00:00 00:00:00
Conn: current 19176d lowest 19176d
                                  out 1: 500 ms
Network buffers: 55 lowest 54
prvSocketSetMSS: 536 bytes for a012394ip:50053
Connect[a012394ip:50053]: next timeout 1: 3000 ms
eCONNECT_SYN: flags 0012 expected, not 0010
Move from eCONNECT_SYN to eCLOSE_WAIT
FreeRTOS_connect() stopped due to an error
GG : Couldn't connect. (main.c)

GG : Disconnecting. (main.c)
FreeRTOS_connect: 585 to a012394ip:50053
prvSocketSetMSS: 536 bytes for a012394ip:50053
Connect[a012394ip:50053]: next timeout 1: 3000 ms
MSS change 536 -> 1460
GG : IsSocketConnected returned true.
GG : Connected. (main.c)

GG : Starting send 0. (main.c)
Network buffers: 56 lowest 536

GG : Starting send 1. (main.c)

We can see that I get a timeout when trying to connect for the first time, but it seems to be solving.

Previously, I would get that (only regarding the connection, not the sending):

prvIPTask started
PHY ID 7C130
xPhyReset: phyBMCR_RESET 0 ready
+TCP: advertise: 01E1 config 3100
prvEthernetUpdateConfig: LS mask 00 Force 1
Autonego ready: 00000004: full duplex 100 mbit high status
Network buffers: 56 lowest 56
Link Status is high
prvInitialiseDHCP: start after 250 ticks
vDHCPProcess: discover
Network buffers: 56 lowest 55
RX descriptors 7/8
vDHCPProcess: offer a012364ip
vDHCPProcess: reply a012364ip
vDHCPProcess: offer a012364ip
vDHCPProcess: acked a012364ip

IP Address: 10.1.35.100
Subnet Mask: 255.255.255.0
Gateway Address: 10.1.35.254
DNS Client Address: 192.168.73.220

GG : c active socket on port 585 (a012394ip:50052)
FreeRTOS_connect: 585 to a012394ip:50053
prvSocketSetMSS: 536 bytes for a012394ip:50053
Connect[a012394ip:50053]: next timeout 1: 3000 ms
MSS change 536 -> 1460
GG : IsSocketConnected returned true.
GG : Connected. (main.c)

##### Question #####
What is causing this behavior?
What does the informations of the hardfault tells us?

##### Code sample #####
I will just share the main.c
I have compared the main.c from the current project (first code sample) with the main.c before adding the authentication method (second code sample).
I don’t think it is usefull to share the server written in python.

Current project’s main.c :

/* Standard includes. */
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <time.h>
#include <ctype.h>

/* cubeMX/HAL includes */
#include "main.h"
#include "string.h"

/* FreeRTOS includes. */
#include "FreeRTOS.h"
#include "task.h"
#include "timers.h"
#include "queue.h"
#include "semphr.h"

/* FreeRTOS+TCP includes. */
#include "FreeRTOS_IP.h"
#include "FreeRTOS_Sockets.h"
#include "FreeRTOS_DHCP.h"
#include "NetworkBufferManagement.h"
#include "NetworkInterface.h"
#include "phyHandling.h"
#if( ipconfigMULTI_INTERFACE != 0 )
	#include "FreeRTOS_Routing.h"
	#include "FreeRTOS_ND.h"
#endif

/* nanopb includes */
#include "pb.h"
#include "pb_common.h"
#include "pb_encode.h"
#include "pb_decode.h"
#include "protoReqPlusAns.pb.h"			//the proto generated file

/* Macro to check if socket is bound, copy pasted from FreeRTOS_Socket.c */
#define socketSOCKET_IS_BOUND( pxSocket )            ( listLIST_ITEM_CONTAINER( &( pxSocket )->xBoundSocketListItem ) != NULL )

#define usUsedStackSize 128
#define BUFFER_SIZE 512

/* cube mx generated handler */
ETH_HandleTypeDef heth;
UART_HandleTypeDef huart3;
ETH_TxPacketConfig TxConfig;
I2C_HandleTypeDef hi2c2;

/* i2c address of the sensor */
static const uint8_t sensorAddress = 0x69 << 1; //address of the sensor

/* The MAC address array is not declared const as the MAC address will
normally be read from an EEPROM and not hard coded (in real deployed applications).*/
static uint8_t ucMACAddress[ 6 ] = { 0x00, 0x80, 0xE2, 0x00, 0x00, 0x00 };

/* Define the network addressing.  These parameters will be used if either
ipconfigUDE_DHCP is 0 or if ipconfigUSE_DHCP is 1 but DHCP auto configuration failed. */
static const uint8_t ucIPAddress[ 4 ];
static const uint8_t ucNetMask[ 4 ];
static const uint8_t ucGatewayAddress[ 4 ];

/* The following is the address of the DNS client. */
static const uint8_t ucDNSClientAddress[ 4 ] = { 192, 168, 73, 220 };

/* Random Number Generator variable. */
static RNG_HandleTypeDef hrng;

/* cube MX generated function definitions */
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_USART3_UART_Init(void);
static void MX_USB_OTG_HS_USB_Init(void);
static void MX_RNG_Init(void);
static void MX_I2C2_Init(void);

/* TCP function definition */
void vApplicationIPNetworkEventHook( eIPCallbackEvent_t eNetworkEvent );
BaseType_t xApplicationGetRandomNumber( uint32_t *pulValue );
void prvClientConnectToServer(Socket_t *xSocket);
void prvClientSendData(Socket_t* xSocket);
void vTCPSend(void);

/* TCP task function definitions (the ones that do tcp thing */
static void vCreateTCPClientSocket(void *pvParameters);

/* Byte functions for sensor*/
uint8_t byteFetchSingleRegisterData (uint16_t startRegister, uint8_t* buffer);
void byteFetchSensorData (uint16_t startRegister, uint8_t* array, uint8_t* buffer);
void byteDataMinus60(uint8_t* array);
void bytePrintArray(uint8_t* array, int n, int m, uint8_t* buffer);
void bytePrintArrayValue(uint8_t* array, int n, int m, uint8_t* buffer);
void byteInterpolateXTimes(uint8_t* dataIn, int n, int m, int ratio, uint8_t* dataOut);
void byteThreshold(int threshold, int n, int m, uint8_t* dataTab);
int byteCheckForPresense(int threshold, int n, int m, uint8_t* dataTab);
void byteSetCenterOfObject(int threshold, int n, int m, uint8_t* dataTab);
uint16_t fetchDoubleRegisterData (uint16_t startRegister, uint8_t* buffer);

/* Handle task */
TaskHandle_t xSensorDataHandle;
TaskHandle_t xCreateSocketHandle;

/* Declaration function */
void vSensorDataTask(void *pvParameters);

/* Global variable (variables used for the messages [request and answer])*/
uint32_t ID = 2;
uint32_t password = 2;
uint8_t byteInterpo[484] = {[0 ... 483] = 3};	// Valid only for gcc based compilers
uint32_t presense = 0;
uint32_t direction = 0;
uint32_t forceOn = 0;
uint32_t forceOff = 0;

int main(void)
{
	/* cube mx init */
	HAL_Init();
	SystemClock_Config();
	MX_GPIO_Init();
	MX_USART3_UART_Init();
	MX_USB_OTG_HS_USB_Init();
	MX_I2C2_Init();
  
    /*Rng init*/
	MX_RNG_Init();

	/* TCP init */
	FreeRTOS_IPInit(ucIPAddress,
	                ucNetMask,
	                ucGatewayAddress,
	                ucDNSClientAddress,
	                ucMACAddress );

	/* task creation */
	NVIC_EnableIRQ(ETH_IRQn);
	NVIC_SetPriority(ETH_IRQn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY);
	/* sensor task */
	xTaskCreate(vSensorDataTask, "Sensor task", 128, NULL, 1, &xSensorDataHandle);

	/* starting rtos scheduler */
	FreeRTOS_printf( ( "\033[2J") );	/* Clean putty */
	FreeRTOS_printf( ( "\r\nGG : Init successful, starting scheduler. (main.c)\r\n") );

	vTaskStartScheduler();
}


/* User task definition */
void vSensorDataTask(void *pvParameters)
{
	uint8_t buffer[20];
	uint8_t byteData[64];
	TickType_t xLastWakeTime;
	int threshold = 115;
	int countCenters = 0;
	int centerPositionOfObject[2][20];

	//suspend itself, wait for TCP to be connected to get resumed
	vTaskSuspend(xSensorDataHandle);

	for(;;)
	{
		xLastWakeTime = xTaskGetTickCount(); /* source : freertos.org/vtaskdelayuntil.html */

		byteFetchSensorData(0x80, byteData, buffer);						//get sensor's values
		byteInterpolateXTimes(byteData, 8, 8, 3, byteInterpo);				//interpolate : 8x8 => 22x22
		byteThreshold(threshold, 22, 22, byteInterpo);						//set values < threshold to 0 else to 127
		/*
		presense = byteCheckForPresense(threshold, 22, 22, byteInterpo);	//check if we consider that there is a human
		if(presense == 1)	//presense detected, let's check the center and the direction
		{
			//byteCheckForDirection
			byteSetCenterOfObject(threshold, 22, 22, byteInterpo);			//measure/calculate the center of the pixels over the threshold
		}
		*/
		presense = 0;
		direction = 0;

		/* Resume TCP task to send byte array */
		vTaskResume(xCreateSocketHandle);

		/* Delay */
		vTaskDelayUntil(&xLastWakeTime, pdMS_TO_TICKS(100));
	}
	for(;;);
}

static void vCreateTCPClientSocket(void *pvParameters)
{
	/* Variables */
	Socket_t xSocket;																	/* The server socket */
	struct freertos_sockaddr xRemoteAddress, xClient;									/* Address of client and remote server */
	socklen_t xSize = sizeof( xClient );												/* The size of a sockaddr, used in bind function */
	BaseType_t xAlreadyTransmitted = 0, xBytesSent = 0;									/* The size already sent */
	size_t xLenToSend;																	/* The lenght to sent for each packet */
	uint8_t nanopbBuffer[600] = {[0 ... 599] = 0};										/* Buffer to encode in protoc using nanopb */
	protoMsgReq nanopbMessage = protoMsgReq_init_zero;									/* The nanopb structure for the message */
	int cnt = 0;
	pb_ostream_t stream;

	FreeRTOS_printf(("\tGG : Entered vCreateTCPClientSocket with GG_CLIENT_TEST value of 2. (main.c)\r\n"));

	for(;;)
	{
		/* Set the IP address and port of the remote socket to which this client socket will transmit. */
		xRemoteAddress.sin_port = FreeRTOS_htons(50053);
		xRemoteAddress.sin_addr = FreeRTOS_inet_addr_quick(10, 1, 35, 148);

		/* Create a socket. */
		xSocket = FreeRTOS_socket(FREERTOS_AF_INET, FREERTOS_SOCK_STREAM, FREERTOS_IPPROTO_TCP);
		configASSERT(xSocket != FREERTOS_INVALID_SOCKET);

		/* Binding (not necessary) */
		xClient.sin_port = FreeRTOS_htons(585);	// en.wikipedia.org/wiki/List_of_TCP_and_UDP_port_numbers
		FreeRTOS_bind(xSocket, &xClient, xSize);

		//Connect to the remote socket.  The socket has not previously been bound to a local port number so will get automatically bound.
		if( FreeRTOS_connect(xSocket, &xRemoteAddress, sizeof(xRemoteAddress)) == 0)
		{
			FreeRTOS_printf(("GG : Connected. (main.c)\r\n"));
			vTaskResume(xSensorDataHandle);

			for(;;)
			{
				vTaskSuspend(xCreateSocketHandle);
				stream = pb_ostream_from_buffer(nanopbBuffer, sizeof(nanopbBuffer));	/* nanopb stream */

				/* Update with new values and encode using nanopb */
				nanopbMessage.ID = ID;
				nanopbMessage.password = password;
				for(int i=0; i<484; ++i){	/* Fill data */
					nanopbMessage.pixels[i] = byteInterpo[i];}
				nanopbMessage.presence = presense;
				nanopbMessage.direction = direction;
				pb_encode(&stream, protoMsgReq_fields, &nanopbMessage);	/* Encode in proto using nanopb */

				/* Reset variables for the send function */
				xAlreadyTransmitted = 0;
				xBytesSent = 0;

				/* Sending data */
				FreeRTOS_printf(("\nGG : Starting send %d. (main.c)\r\n", cnt));
				while(xAlreadyTransmitted < stream.bytes_written) 				/* Keep sending until the entire buffer has been sent. */
				{
					xLenToSend = stream.bytes_written - xAlreadyTransmitted; 	/* How many bytes are left to send? */

					xBytesSent = FreeRTOS_send(xSocket, &(nanopbBuffer[xAlreadyTransmitted]), xLenToSend, 0);

					if(xBytesSent >= 0) xAlreadyTransmitted += xBytesSent;
					else break;
				}
				FreeRTOS_printf(("GG : Finished send. (main.c)\r\n"));
				++cnt;
			}
		}
		else FreeRTOS_printf(("GG : Couldn't connect. (main.c)\r\n"));

		/* Initiate graceful shutdown. */
		FreeRTOS_printf(("\nGG : Disconnecting. (main.c)\r\n"));
		FreeRTOS_shutdown( xSocket, FREERTOS_SHUT_RDWR );

		/* Wait for the socket to disconnect gracefully before closing the socket. */
		/*
		while(FreeRTOS_recv(xSocket, nanopbBuffer, stream.bytes_written, 0) >= 0)
		{
			vTaskDelay(pdMS_TO_TICKS(250)); // Wait for shutdown to complete.
			// Note - real applications should implement a timeout here, not just loop forever.
		}
		*/

		/* The socket has shut down and is safe to close. */
		FreeRTOS_closesocket(xSocket);
	} //end for(;;)
}

void vApplicationIPNetworkEventHook( eIPCallbackEvent_t eNetworkEvent )
{
  static BaseType_t xTasksAlreadyCreated = pdFALSE;
  uint32_t ulIPAddress, ulNetMask, ulGatewayAddress, ulDNSClientAddress;
  char cBuffer[ 16 ];

    /* Both eNetworkUp and eNetworkDown events can be processed here. */
    if( eNetworkEvent == eNetworkUp )
    {
        /* Create the tasks that use the TCP/IP stack if they have not already
        been created. */
        if( xTasksAlreadyCreated == pdFALSE )
        {
            /*
             * For convenience, tasks that use FreeRTOS-Plus-TCP can be created here
             * to ensure they are not created before the network is usable.
             */
        	xTaskCreate(vCreateTCPClientSocket,
        	            "clientSocket",
        	            usUsedStackSize * 2,	/* double stack size because I ran into hard fault that could be related to stackoverflow */
        	            NULL,
        	            4,  /* 4 is the highest priority as I set 5 levels of priority */
						&xCreateSocketHandle);

            xTasksAlreadyCreated = pdTRUE;
            //xIPTaskInitialised = pdTRUE;
        }

        FreeRTOS_GetAddressConfiguration( &ulIPAddress, &ulNetMask, &ulGatewayAddress, &ulDNSClientAddress );

        FreeRTOS_inet_ntoa( ulIPAddress, cBuffer );
        FreeRTOS_printf( ( "\r\n\r\nIP Address: %s\r\n", cBuffer ) );

        FreeRTOS_inet_ntoa( ulNetMask, cBuffer );
        FreeRTOS_printf( ( "Subnet Mask: %s\r\n", cBuffer ) );

        FreeRTOS_inet_ntoa( ulGatewayAddress, cBuffer );
        FreeRTOS_printf( ( "Gateway Address: %s\r\n", cBuffer ) );

        FreeRTOS_inet_ntoa( ulDNSClientAddress, cBuffer );
        FreeRTOS_printf( ( "DNS Client Address: %s\r\n\r\n\r\n", cBuffer ) );
    }
}


//User sensor functions definition
uint8_t byteFetchSingleRegisterData (uint16_t startRegister, uint8_t* buffer)
{
	uint8_t retVal = 0;
	buffer[0] = startRegister;
	if(HAL_I2C_Master_Transmit(&hi2c2, sensorAddress, buffer, 1, HAL_MAX_DELAY) != HAL_OK){
		strcpy((char*)buffer, "Tx error!\r\n");
		HAL_UART_Transmit(&huart3, buffer, strlen((char*)buffer), HAL_MAX_DELAY);}
	else{
		if(HAL_I2C_Master_Receive(&hi2c2, sensorAddress, buffer, 1, HAL_MAX_DELAY) != HAL_OK){
			strcpy((char*)buffer, "Rx error!\r\n");
			HAL_UART_Transmit(&huart3, buffer, strlen((char*)buffer), HAL_MAX_DELAY);}
		else{
			retVal = buffer[0];}}
	return retVal;
}

void byteFetchSensorData (uint16_t startRegister, uint8_t* array, uint8_t* buffer)
{
	for (int i = 0; i<64; ++i){
	  array[i] = byteFetchSingleRegisterData(0x80+(2*i), buffer);}
}

void byteDataMinus60(uint8_t* array)
{
	for (int i = 0; i<64; ++i){
		array[i] -= 60;}
}

void bytePrintArray(uint8_t* array, int n, int m, uint8_t* buffer)
{
	for (int i = 0; i<n; ++i){		/* for each line */
		for(int j = 0; j<m; ++j){	/* for each row */
			if (array[(m*i)+j]-60 <20) sprintf((char*)buffer, ". ");
			else if (array[(m*i)+j]-60 <40) sprintf((char*)buffer, "o ");
			else if (array[(m*i)+j]-60 <60) sprintf((char*)buffer, "0 ");
			else sprintf((char*)buffer, "# ");
			HAL_UART_Transmit(&huart3, buffer, strlen((char*)buffer), HAL_MAX_DELAY);}
		sprintf((char*)buffer, "\r\n");
		HAL_UART_Transmit(&huart3, buffer, strlen((char*)buffer), HAL_MAX_DELAY);}
}

void bytePrintArrayValue(uint8_t* array, int n, int m, uint8_t* buffer)
{
	for (int i = 0; i<n; ++i){
		sprintf((char*)buffer, "[");
		HAL_UART_Transmit(&huart3, buffer, strlen((char*)buffer), HAL_MAX_DELAY);
		for(int j = 0; j<m; ++j){
			sprintf((char*)buffer, "%03u",  array[(n*i)+j]);
			HAL_UART_Transmit(&huart3, buffer, strlen((char*)buffer), HAL_MAX_DELAY);
			if(j!=(m-1)){
			  sprintf((char*)buffer, ", ");
			  HAL_UART_Transmit(&huart3, buffer, strlen((char*)buffer), HAL_MAX_DELAY);}}
		sprintf((char*)buffer, "]");
		HAL_UART_Transmit(&huart3, buffer, strlen((char*)buffer), HAL_MAX_DELAY);
		if(i!=(n-1)){
			sprintf((char*)buffer, ",\r\n");
			HAL_UART_Transmit(&huart3, buffer, strlen((char*)buffer), HAL_MAX_DELAY);}}
	sprintf((char*)buffer, "\r\n\n");
	HAL_UART_Transmit(&huart3, buffer, strlen((char*)buffer), HAL_MAX_DELAY);
}

void byteInterpolateXTimes(uint8_t* dataIn, int n, int m, int ratio, uint8_t* dataOut)
{
	float tempF1, tempF2; //adding temp val for readability
	float* tempTab;
	//tempTab = calloc(((n-1)*ratio+1)*((m-1)*ratio+1), sizeof(float));
	tempTab = pvPortMalloc(((n-1)*ratio+1)*((m-1)*ratio+1)*sizeof(float));

	//Set initial values in bigger array
	for(int i = 0; i<n; ++i){
		for(int j = 0; j<m; ++j){
			tempTab[(i*(m*ratio*ratio-(2*ratio))) + (j*ratio)] = (float)dataIn[(n*i) + (j)];}}

	//Interpolate lines
	for(int i = 0; i<(n-1)*ratio+1; i+=ratio){	//"skip ratio-1 at a time row"
		for(int j = 0; j<(m-1)*ratio; j+=ratio){ //"skip ratio-1 at a time col as well as the last one"
			for(int k = 1; k < ratio; ++k){	//for each space between 2 know value{
				tempF1 = tempTab[(i*(m*ratio-2)) + (j)] * (ratio-k)/ratio;
				tempF2 = tempTab[(i*(m*ratio-2)) + (j) + ratio] * (k)/ratio;
				tempTab[(i*(m*ratio-2)) + (j) + k] = round(tempF1 + tempF2);}}}

	//Interpolate row
	for(int i = 0; i<(n-1)*ratio; i+=ratio){	//"skip ratio-1 at a time row as well as the last one"
		for(int j = 0; j<(m-1)*ratio+1; ++j){
			for(int k = 1; k < ratio; ++k){	//for each space between 2 know value
				tempF1 = tempTab[(i*(m*ratio-2)) + (j)] * (ratio-k)/ratio;
				tempF2 = tempTab[((i+ratio)*(m*ratio-2)) + (j) ] * (k)/ratio;
				tempTab[((i+k)*(m*ratio-2)) + (j)] = round(tempF1 + tempF2);}}}

	//Copy into int tab
	for(int i=0; i<(n-1)*ratio+1; ++i){
		for(int j=0; j<(m-1)*ratio+1; ++j){
			dataOut[i*((m-1)*ratio+1) + j] = (int)tempTab[i*((m-1)*ratio+1) + j];}}

	//free(tempTab);
	vPortFree(tempTab);
}

void byteThreshold(int threshold, int n, int m, uint8_t* dataTab)
{
	for(int i = 0; i<n; ++i){
		for(int j = 0; j<m; ++j){
			if(dataTab[(i*m)+j]<threshold) dataTab[(i*m)+j]=0;
			else dataTab[(i*m)+j]=127;}}
}

int byteCheckForPresense(int threshold, int n, int m, uint8_t* dataTab)
{
	int countPixel=0;
	for(int i = 0; i<n; ++i){
		for(int j = 0; j<m; ++j){
			if(dataTab[(i*m)+j]>threshold) ++countPixel;} }
	if(countPixel>20) return 1;
	else return 0;
}

void byteSetCenterOfObject(int threshold, int n, int m, uint8_t* dataTab)
{
	int xSum=0, ySum=0, countPixel=0;

	for(int i = 0; i<n; ++i){
		for(int j = 0; j<m; ++j){
			if(dataTab[(i*m)+j]>threshold){
				++countPixel;
				xSum+=j;
				ySum+=i;} } }
	if(countPixel>0) dataTab[ ( (ySum/countPixel) * m ) + (xSum/countPixel) ] = 255;
}

uint16_t fetchDoubleRegisterData (uint16_t startRegister, uint8_t* buffer)
{
	uint16_t retVal = 0;
	buffer[0] = startRegister;
	if(HAL_I2C_Master_Transmit(&hi2c2, sensorAddress, buffer, 1, HAL_MAX_DELAY) != HAL_OK){
		  strcpy((char*)buffer, "Tx error!\r\n");
		  HAL_UART_Transmit(&huart3, buffer, strlen((char*)buffer), HAL_MAX_DELAY);}
	  else{
		  if(HAL_I2C_Master_Receive(&hi2c2, sensorAddress, buffer, 2, HAL_MAX_DELAY) != HAL_OK){
			  strcpy((char*)buffer, "Rx error!\r\n");
			  HAL_UART_Transmit(&huart3, buffer, strlen((char*)buffer), HAL_MAX_DELAY);}
		  else{
			  retVal = buffer[0] + (buffer[1]<<8);}}
	return retVal;
}

/* Random Number Generator function*/
BaseType_t xApplicationGetRandomNumber( uint32_t *pulValue )
{
HAL_StatusTypeDef xResult;
BaseType_t xReturn;
uint32_t ulValue;

	xResult = HAL_RNG_GenerateRandomNumber( &hrng, &ulValue );
	if( xResult == HAL_OK )
	{
		xReturn = pdPASS;
		*pulValue = ulValue;
	}
	else
	{
		xReturn = pdFAIL;
	}
	return xReturn;
}

/**
  * @brief I2C2 Initialization Function
  * @param None
  * @retval None
  */
static void MX_I2C2_Init(void)
{

  /* USER CODE BEGIN I2C2_Init 0 */

  /* USER CODE END I2C2_Init 0 */

  /* USER CODE BEGIN I2C2_Init 1 */

  /* USER CODE END I2C2_Init 1 */
  hi2c2.Instance = I2C2;
  hi2c2.Init.Timing = 0x60404E72;
  hi2c2.Init.OwnAddress1 = 0;
  hi2c2.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
  hi2c2.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
  hi2c2.Init.OwnAddress2 = 0;
  hi2c2.Init.OwnAddress2Masks = I2C_OA2_NOMASK;
  hi2c2.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
  hi2c2.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
  if (HAL_I2C_Init(&hi2c2) != HAL_OK)
  {
    Error_Handler();
  }

  /** Configure Analogue filter
  */
  if (HAL_I2CEx_ConfigAnalogFilter(&hi2c2, I2C_ANALOGFILTER_ENABLE) != HAL_OK)
  {
    Error_Handler();
  }

  /** Configure Digital filter
  */
  if (HAL_I2CEx_ConfigDigitalFilter(&hi2c2, 0) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN I2C2_Init 2 */

  /* USER CODE END I2C2_Init 2 */

}

/**
  * @brief RNG Initialization Function
  * @param None
  * @retval None
  */
static void MX_RNG_Init(void)
{
  hrng.Instance = RNG;
  //hrng.Init.ClockErrorDetection = RNG_CED_ENABLE;
  if (HAL_RNG_Init(&hrng) != HAL_OK)
  {
    Error_Handler();
  }
}

/**
  * @brief System Clock Configuration
  * @retval None
  */
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

  /** Supply configuration update enable
  */
  HAL_PWREx_ConfigSupply(PWR_LDO_SUPPLY);

  /** Configure the main internal regulator output voltage
  */
  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE0);

  while(!__HAL_PWR_GET_FLAG(PWR_FLAG_VOSRDY)) {}

  /** Initializes the RCC Oscillators according to the specified parameters
  * in the RCC_OscInitTypeDef structure.
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI48|RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_BYPASS;
  RCC_OscInitStruct.HSI48State = RCC_HSI48_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLM = 4;
  RCC_OscInitStruct.PLL.PLLN = 275;
  RCC_OscInitStruct.PLL.PLLP = 1;
  RCC_OscInitStruct.PLL.PLLQ = 4;
  RCC_OscInitStruct.PLL.PLLR = 2;
  RCC_OscInitStruct.PLL.PLLRGE = RCC_PLL1VCIRANGE_1;
  RCC_OscInitStruct.PLL.PLLVCOSEL = RCC_PLL1VCOWIDE;
  RCC_OscInitStruct.PLL.PLLFRACN = 0;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }

  /** Initializes the CPU, AHB and APB buses clocks
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2
                              |RCC_CLOCKTYPE_D3PCLK1|RCC_CLOCKTYPE_D1PCLK1;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.SYSCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_HCLK_DIV2;
  RCC_ClkInitStruct.APB3CLKDivider = RCC_APB3_DIV2;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_APB1_DIV2;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_APB2_DIV2;
  RCC_ClkInitStruct.APB4CLKDivider = RCC_APB4_DIV2;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_3) != HAL_OK)
  {
    Error_Handler();
  }
}

/**
  * @brief USART3 Initialization Function
  * @param None
  * @retval None
  */
static void MX_USART3_UART_Init(void)
{
  huart3.Instance = USART3;
  huart3.Init.BaudRate = 115200;
  huart3.Init.WordLength = UART_WORDLENGTH_8B;
  huart3.Init.StopBits = UART_STOPBITS_1;
  huart3.Init.Parity = UART_PARITY_NONE;
  huart3.Init.Mode = UART_MODE_TX_RX;
  huart3.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  huart3.Init.OverSampling = UART_OVERSAMPLING_16;
  huart3.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
  huart3.Init.ClockPrescaler = UART_PRESCALER_DIV1;
  huart3.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
  if (HAL_UART_Init(&huart3) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_UARTEx_SetTxFifoThreshold(&huart3, UART_TXFIFO_THRESHOLD_1_8) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_UARTEx_SetRxFifoThreshold(&huart3, UART_RXFIFO_THRESHOLD_1_8) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_UARTEx_DisableFifoMode(&huart3) != HAL_OK)
  {
    Error_Handler();
  }
}

/**
  * @brief USB_OTG_HS Initialization Function
  * @param None
  * @retval None
  */
static void MX_USB_OTG_HS_USB_Init(void)
{
}

/**
  * @brief GPIO Initialization Function
  * @param None
  * @retval None
  */
static void MX_GPIO_Init(void)
{
	GPIO_InitTypeDef GPIO_InitStruct = {0};

  /* GPIO Ports Clock Enable */
  __HAL_RCC_GPIOC_CLK_ENABLE();
  __HAL_RCC_GPIOF_CLK_ENABLE();
  __HAL_RCC_GPIOH_CLK_ENABLE();
  __HAL_RCC_GPIOA_CLK_ENABLE();
  __HAL_RCC_GPIOB_CLK_ENABLE();
  __HAL_RCC_GPIOD_CLK_ENABLE();
  __HAL_RCC_GPIOG_CLK_ENABLE();
  __HAL_RCC_GPIOE_CLK_ENABLE();

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(GPIOB, LED_GREEN_Pin|LED_RED_Pin, GPIO_PIN_RESET);

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(USB_FS_PWR_EN_GPIO_Port, USB_FS_PWR_EN_Pin, GPIO_PIN_RESET);

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(LED_YELLOW_GPIO_Port, LED_YELLOW_Pin, GPIO_PIN_RESET);

  /*Configure GPIO pin : B1_Pin */
  GPIO_InitStruct.Pin = B1_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  HAL_GPIO_Init(B1_GPIO_Port, &GPIO_InitStruct);

  /*Configure GPIO pins : LED_GREEN_Pin LED_RED_Pin */
  GPIO_InitStruct.Pin = LED_GREEN_Pin|LED_RED_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

  /*Configure GPIO pin : USB_FS_PWR_EN_Pin */
  GPIO_InitStruct.Pin = USB_FS_PWR_EN_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(USB_FS_PWR_EN_GPIO_Port, &GPIO_InitStruct);

  /*Configure GPIO pin : USB_FS_OVCR_Pin */
  GPIO_InitStruct.Pin = USB_FS_OVCR_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  HAL_GPIO_Init(USB_FS_OVCR_GPIO_Port, &GPIO_InitStruct);

  /*Configure GPIO pin : USB_FS_VBUS_Pin */
  GPIO_InitStruct.Pin = USB_FS_VBUS_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  HAL_GPIO_Init(USB_FS_VBUS_GPIO_Port, &GPIO_InitStruct);

  /*Configure GPIO pin : USB_FS_ID_Pin */
  GPIO_InitStruct.Pin = USB_FS_ID_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  GPIO_InitStruct.Alternate = GPIO_AF10_OTG1_HS;
  HAL_GPIO_Init(USB_FS_ID_GPIO_Port, &GPIO_InitStruct);

  /*Configure GPIO pin : LED_YELLOW_Pin */
  GPIO_InitStruct.Pin = LED_YELLOW_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(LED_YELLOW_GPIO_Port, &GPIO_InitStruct);
}

/**
  * @brief  Period elapsed callback in non blocking mode
  * @note   This function is called  when TIM1 interrupt took place, inside
  * HAL_TIM_IRQHandler(). It makes a direct call to HAL_IncTick() to increment
  * a global variable "uwTick" used as application time base.
  * @param  htim : TIM handle
  * @retval None
  */
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
  if (htim->Instance == TIM1) {
    HAL_IncTick();
  }
}

/**
  * @brief  This function is executed in case of error occurrence.
  * @retval None
  */
void Error_Handler(void)
{
  __disable_irq();
  while (1)
  {
  }
}

int _write(int file, char *ptr, int len)
{
  HAL_UART_Transmit(&huart3, ( const uint8_t * ) ptr, len, HAL_MAX_DELAY);
  HAL_UART_Transmit(&huart3, "\r", 1, HAL_MAX_DELAY);
  return len;
}

#ifdef  USE_FULL_ASSERT
/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t *file, uint32_t line)
{
  /* USER CODE BEGIN 6 */
  /* User can add his own implementation to report the file name and line number,
     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  /* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */

Previous working main.c without ID and password :

/* Standard includes. */
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <time.h>
#include <ctype.h>

/* cubeMX/HAL includes */
#include "main.h"
#include "string.h"

/* FreeRTOS includes. */
#include "FreeRTOS.h"
#include "task.h"
#include "timers.h"
#include "queue.h"
#include "semphr.h"

/* FreeRTOS+TCP includes. */
#include "FreeRTOS_IP.h"
#include "FreeRTOS_Sockets.h"
#include "FreeRTOS_DHCP.h"
#include "NetworkBufferManagement.h"
#include "NetworkInterface.h"
#include "phyHandling.h"
#if( ipconfigMULTI_INTERFACE != 0 )
	#include "FreeRTOS_Routing.h"
	#include "FreeRTOS_ND.h"
#endif

/* nanopb includes */
#include "pb.h"
#include "pb_common.h"
#include "pb_encode.h"
#include "pb_decode.h"
#include "protoArray484Nanopb41.pb.h"			//the proto generated file

/* Macro to check if socket is bound, copy pasted from FreeRTOS_Socket.c */
#define socketSOCKET_IS_BOUND( pxSocket )            ( listLIST_ITEM_CONTAINER( &( pxSocket )->xBoundSocketListItem ) != NULL )

#define usUsedStackSize 128
#define BUFFER_SIZE 512

/* cube mx generated handler */
ETH_HandleTypeDef heth;
UART_HandleTypeDef huart3;
ETH_TxPacketConfig TxConfig;
I2C_HandleTypeDef hi2c2;

/* i2c address of the sensor */
static const uint8_t sensorAddress = 0x69 << 1; //address of the sensor

/* The MAC address array is not declared const as the MAC address will
normally be read from an EEPROM and not hard coded (in real deployed applications).*/
static uint8_t ucMACAddress[ 6 ] = { 0x00, 0x80, 0xE2, 0x00, 0x00, 0x00 };

/* Define the network addressing.  These parameters will be used if either
ipconfigUDE_DHCP is 0 or if ipconfigUSE_DHCP is 1 but DHCP auto configuration failed. */
static const uint8_t ucIPAddress[ 4 ];
static const uint8_t ucNetMask[ 4 ];
static const uint8_t ucGatewayAddress[ 4 ];

/* The following is the address of the DNS client. */
static const uint8_t ucDNSClientAddress[ 4 ] = { 192, 168, 73, 220 };

/* Random Number Generator variable. */
static RNG_HandleTypeDef hrng;

/* cube MX generated function definitions */
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_USART3_UART_Init(void);
static void MX_USB_OTG_HS_USB_Init(void);
static void MX_RNG_Init(void);
static void MX_I2C2_Init(void);

/* TCP function definition */
void vApplicationIPNetworkEventHook( eIPCallbackEvent_t eNetworkEvent );
BaseType_t xApplicationGetRandomNumber( uint32_t *pulValue );
void prvClientConnectToServer(Socket_t *xSocket);
void prvClientSendData(Socket_t* xSocket);
void vTCPSend(void);

/* TCP task function definitions (the ones that do tcp thing */
static void vCreateTCPClientSocket(void *pvParameters);

/* Byte functions for sensor*/
uint8_t byteFetchSingleRegisterData (uint16_t startRegister, uint8_t* buffer);
void byteFetchSensorData (uint16_t startRegister, uint8_t* array, uint8_t* buffer);
void byteDataMinus60(uint8_t* array);
void bytePrintArray(uint8_t* array, int n, int m, uint8_t* buffer);
void bytePrintArrayValue(uint8_t* array, int n, int m, uint8_t* buffer);
void byteInterpolateXTimes(uint8_t* dataIn, int n, int m, int ratio, uint8_t* dataOut);
void byteThreshold(int threshold, int n, int m, uint8_t* dataTab);
void byteSetCenterOfObject(int threshold, int n, int m, uint8_t* dataTab);
uint16_t fetchDoubleRegisterData (uint16_t startRegister, uint8_t* buffer);

/* Handle task */
TaskHandle_t xSensorDataHandle;
TaskHandle_t xCreateSocketHandle;

/* Declaration function */
void vSensorDataTask(void *pvParameters);

/* Global variable */
uint8_t byteInterpo[484] = {[0 ... 483] = 3};	// Valid only for gcc based compilers

int main(void)
{
	/* cube mx init */
	HAL_Init();
	SystemClock_Config();
	MX_GPIO_Init();
	MX_USART3_UART_Init();
	MX_USB_OTG_HS_USB_Init();
	MX_I2C2_Init();
  
    /*Rng init*/
	MX_RNG_Init();

	/* TCP init */
	FreeRTOS_IPInit(ucIPAddress,
	                ucNetMask,
	                ucGatewayAddress,
	                ucDNSClientAddress,
	                ucMACAddress );

	/* task creation */
	NVIC_EnableIRQ(ETH_IRQn);
	NVIC_SetPriority(ETH_IRQn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY);
	/* sensor task */
	xTaskCreate(vSensorDataTask, "Sensor task", 128, NULL, 1, &xSensorDataHandle);

	/* starting rtos scheduler */
	FreeRTOS_printf( ( "\033[2J") );	/* Clean putty */
	FreeRTOS_printf( ( "\r\nGG : Init successful, starting scheduler. (main.c)\r\n") );

	vTaskStartScheduler();
}


/* User task definition */
void vSensorDataTask(void *pvParameters)
{
	uint8_t buffer[20];
	uint16_t thermistorVal;
	uint8_t byteData[64];
	//uint8_t* byteInterpo;
	//byteInterpo = (uint8_t *) pvParameters;
	TickType_t xLastWakeTime;
	int threshold = 115;

	vTaskSuspend(xSensorDataHandle);

	for (int i=0; i<1000; ++i)
	{
		xLastWakeTime = xTaskGetTickCount(); /* source : freertos.org/vtaskdelayuntil.html */

		//Print thermistor value
		/*
		thermistorVal = fetchDoubleRegisterData (0x0E, buffer);
		sprintf((char*)buffer, "\nThermi :%u\r\n",  thermistorVal);
		HAL_UART_Transmit(&huart3, buffer, strlen((char*)buffer), HAL_MAX_DELAY);
		*/

		//print byte array
		byteFetchSensorData(0x80, byteData, buffer);
		//bytePrintArrayValue(byteData, 8, 8, buffer);
		byteInterpolateXTimes(byteData, 8, 8, 3, byteInterpo);
		byteThreshold(threshold, 22, 22, byteInterpo);
		byteSetCenterOfObject(threshold, 22, 22, byteInterpo);

		/* Resume TCP task to send byte array */
		vTaskResume(xCreateSocketHandle);

		/* Delay */
		vTaskDelayUntil(&xLastWakeTime, pdMS_TO_TICKS(100));
	}
	for(;;);
}

static void vCreateTCPClientSocket(void *pvParameters)
{
	/* Variables */
	Socket_t xSocket;																	/* The server socket */
	struct freertos_sockaddr xRemoteAddress, xClient;									/* Address of client and remote server */
	socklen_t xSize = sizeof( xClient );												/* The size of a sockaddr, used in bind function */
	BaseType_t xAlreadyTransmitted = 0, xBytesSent = 0;									/* The size already sent */
	size_t xLenToSend;																	/* The lenght to sent for each packet */
	uint8_t nanopbBuffer[600] = {[0 ... 599] = 0};										/* Buffer to encode in protoc using nanopb */
	protoMsg nanopbMessage = protoMsg_init_zero;										/* The nanopb structure for the message */
	int cnt = 0;
	pb_ostream_t stream;

	FreeRTOS_printf(("\tGG : Entered vCreateTCPClientSocket with GG_CLIENT_TEST value of 2. (main.c)\r\n"));

	for(;;)
	{
		/* Set the IP address and port of the remote socket to which this client socket will transmit. */
		xRemoteAddress.sin_port = FreeRTOS_htons(50053);
		xRemoteAddress.sin_addr = FreeRTOS_inet_addr_quick(10, 1, 35, 148);

		/* Create a socket. */
		xSocket = FreeRTOS_socket(FREERTOS_AF_INET, FREERTOS_SOCK_STREAM, FREERTOS_IPPROTO_TCP);
		configASSERT(xSocket != FREERTOS_INVALID_SOCKET);

		/* Binding (not necessary) */
		xClient.sin_port = FreeRTOS_htons(585);	// en.wikipedia.org/wiki/List_of_TCP_and_UDP_port_numbers
		FreeRTOS_bind(xSocket, &xClient, xSize);

		//Connect to the remote socket.  The socket has not previously been bound to a local port number so will get automatically bound.
		if( FreeRTOS_connect(xSocket, &xRemoteAddress, sizeof(xRemoteAddress)) == 0)
		{
			FreeRTOS_printf(("GG : Connected. (main.c)\r\n"));
			vTaskResume(xSensorDataHandle);

			for(;;)
			{
				vTaskSuspend(xCreateSocketHandle);
				stream = pb_ostream_from_buffer(nanopbBuffer, sizeof(nanopbBuffer));	/* nanopb stream */

				/* Update with new values and encode using nanopb */
				for(int i=0; i<484; ++i){	/* Fill data */
					nanopbMessage.pixel[i] = byteInterpo[i];}
				pb_encode(&stream, protoMsg_fields, &nanopbMessage);	/* Encode in proto using nanopb */

				/* Reset variables for the send function */
				xAlreadyTransmitted = 0;
				xBytesSent = 0;

				/* Sending data */
				FreeRTOS_printf(("\nGG : Starting send %d. (main.c)\r\n", cnt));
				while(xAlreadyTransmitted < stream.bytes_written) 				/* Keep sending until the entire buffer has been sent. */
				{
					xLenToSend = stream.bytes_written - xAlreadyTransmitted; 	/* How many bytes are left to send? */

					xBytesSent = FreeRTOS_send(xSocket, &(nanopbBuffer[xAlreadyTransmitted]), xLenToSend, 0);

					if(xBytesSent >= 0) xAlreadyTransmitted += xBytesSent;
					else break;
				}
				FreeRTOS_printf(("GG : Finished send. (main.c)\r\n"));
				++cnt;
			}
		}
		else FreeRTOS_printf(("GG : Couldn't connect. (main.c)\r\n"));

		/* Initiate graceful shutdown. */
		FreeRTOS_printf(("\nGG : Disconnecting. (main.c)\r\n"));
		FreeRTOS_shutdown( xSocket, FREERTOS_SHUT_RDWR );

		/* Wait for the socket to disconnect gracefully before closing the socket. */
		/*
		while(FreeRTOS_recv(xSocket, nanopbBuffer, stream.bytes_written, 0) >= 0)
		{
			vTaskDelay(pdMS_TO_TICKS(250)); // Wait for shutdown to complete.
			// Note - real applications should implement a timeout here, not just loop forever.
		}
		*/

		/* The socket has shut down and is safe to close. */
		FreeRTOS_closesocket(xSocket);
	} //end for(;;)
}

void vApplicationIPNetworkEventHook( eIPCallbackEvent_t eNetworkEvent )
{
  static BaseType_t xTasksAlreadyCreated = pdFALSE;
  uint32_t ulIPAddress, ulNetMask, ulGatewayAddress, ulDNSClientAddress;
  char cBuffer[ 16 ];

    /* Both eNetworkUp and eNetworkDown events can be processed here. */
    if( eNetworkEvent == eNetworkUp )
    {
        /* Create the tasks that use the TCP/IP stack if they have not already
        been created. */
        if( xTasksAlreadyCreated == pdFALSE )
        {
            /*
             * For convenience, tasks that use FreeRTOS-Plus-TCP can be created here
             * to ensure they are not created before the network is usable.
             */
        	xTaskCreate(vCreateTCPClientSocket,
        	            "clientSocket",
        	            usUsedStackSize,	/* double stack size because I ran into hard fault that could be related to stackoverflow */
        	            NULL,
        	            4,  /* 4 is the highest priority as I set 5 levels of priority */
						&xCreateSocketHandle);

            xTasksAlreadyCreated = pdTRUE;
            //xIPTaskInitialised = pdTRUE;
        }

        FreeRTOS_GetAddressConfiguration( &ulIPAddress, &ulNetMask, &ulGatewayAddress, &ulDNSClientAddress );

        FreeRTOS_inet_ntoa( ulIPAddress, cBuffer );
        FreeRTOS_printf( ( "\r\n\r\nIP Address: %s\r\n", cBuffer ) );

        FreeRTOS_inet_ntoa( ulNetMask, cBuffer );
        FreeRTOS_printf( ( "Subnet Mask: %s\r\n", cBuffer ) );

        FreeRTOS_inet_ntoa( ulGatewayAddress, cBuffer );
        FreeRTOS_printf( ( "Gateway Address: %s\r\n", cBuffer ) );

        FreeRTOS_inet_ntoa( ulDNSClientAddress, cBuffer );
        FreeRTOS_printf( ( "DNS Client Address: %s\r\n\r\n\r\n", cBuffer ) );
    }
}


//User sensor functions definition
uint8_t byteFetchSingleRegisterData (uint16_t startRegister, uint8_t* buffer)
{
	uint8_t retVal = 0;
	buffer[0] = startRegister;
	if(HAL_I2C_Master_Transmit(&hi2c2, sensorAddress, buffer, 1, HAL_MAX_DELAY) != HAL_OK){
		strcpy((char*)buffer, "Tx error!\r\n");
		HAL_UART_Transmit(&huart3, buffer, strlen((char*)buffer), HAL_MAX_DELAY);}
	else{
		if(HAL_I2C_Master_Receive(&hi2c2, sensorAddress, buffer, 1, HAL_MAX_DELAY) != HAL_OK){
			strcpy((char*)buffer, "Rx error!\r\n");
			HAL_UART_Transmit(&huart3, buffer, strlen((char*)buffer), HAL_MAX_DELAY);}
		else{
			retVal = buffer[0];}}
	return retVal;
}

void byteFetchSensorData (uint16_t startRegister, uint8_t* array, uint8_t* buffer)
{
	for (int i = 0; i<64; ++i){
	  array[i] = byteFetchSingleRegisterData(0x80+(2*i), buffer);}
}

void byteDataMinus60(uint8_t* array)
{
	for (int i = 0; i<64; ++i){
		array[i] -= 60;}
}

void bytePrintArray(uint8_t* array, int n, int m, uint8_t* buffer)
{
	for (int i = 0; i<n; ++i){		/* for each line */
		for(int j = 0; j<m; ++j){	/* for each row */
			if (array[(m*i)+j]-60 <20) sprintf((char*)buffer, ". ");
			else if (array[(m*i)+j]-60 <40) sprintf((char*)buffer, "o ");
			else if (array[(m*i)+j]-60 <60) sprintf((char*)buffer, "0 ");
			else sprintf((char*)buffer, "# ");
			HAL_UART_Transmit(&huart3, buffer, strlen((char*)buffer), HAL_MAX_DELAY);}
		sprintf((char*)buffer, "\r\n");
		HAL_UART_Transmit(&huart3, buffer, strlen((char*)buffer), HAL_MAX_DELAY);}
}

void bytePrintArrayValue(uint8_t* array, int n, int m, uint8_t* buffer)
{
	for (int i = 0; i<n; ++i){
		sprintf((char*)buffer, "[");
		HAL_UART_Transmit(&huart3, buffer, strlen((char*)buffer), HAL_MAX_DELAY);
		for(int j = 0; j<m; ++j){
			sprintf((char*)buffer, "%03u",  array[(n*i)+j]);
			HAL_UART_Transmit(&huart3, buffer, strlen((char*)buffer), HAL_MAX_DELAY);
			if(j!=(m-1)){
			  sprintf((char*)buffer, ", ");
			  HAL_UART_Transmit(&huart3, buffer, strlen((char*)buffer), HAL_MAX_DELAY);}}
		sprintf((char*)buffer, "]");
		HAL_UART_Transmit(&huart3, buffer, strlen((char*)buffer), HAL_MAX_DELAY);
		if(i!=(n-1)){
			sprintf((char*)buffer, ",\r\n");
			HAL_UART_Transmit(&huart3, buffer, strlen((char*)buffer), HAL_MAX_DELAY);}}
	sprintf((char*)buffer, "\r\n\n");
	HAL_UART_Transmit(&huart3, buffer, strlen((char*)buffer), HAL_MAX_DELAY);
}

void byteInterpolateXTimes(uint8_t* dataIn, int n, int m, int ratio, uint8_t* dataOut)
{
	float tempF1, tempF2; //adding temp val for readability
	float* tempTab;
	//tempTab = calloc(((n-1)*ratio+1)*((m-1)*ratio+1), sizeof(float));
	tempTab = pvPortMalloc(((n-1)*ratio+1)*((m-1)*ratio+1)*sizeof(float));

	//Set initial values in bigger array
	for(int i = 0; i<n; ++i){
		for(int j = 0; j<m; ++j){
			tempTab[(i*(m*ratio*ratio-(2*ratio))) + (j*ratio)] = (float)dataIn[(n*i) + (j)];}}

	//Interpolate lines
	for(int i = 0; i<(n-1)*ratio+1; i+=ratio){	//"skip ratio-1 at a time row"
		for(int j = 0; j<(m-1)*ratio; j+=ratio){ //"skip ratio-1 at a time col as well as the last one"
			for(int k = 1; k < ratio; ++k){	//for each space between 2 know value{
				tempF1 = tempTab[(i*(m*ratio-2)) + (j)] * (ratio-k)/ratio;
				tempF2 = tempTab[(i*(m*ratio-2)) + (j) + ratio] * (k)/ratio;
				tempTab[(i*(m*ratio-2)) + (j) + k] = round(tempF1 + tempF2);}}}

	//Interpolate row
	for(int i = 0; i<(n-1)*ratio; i+=ratio){	//"skip ratio-1 at a time row as well as the last one"
		for(int j = 0; j<(m-1)*ratio+1; ++j){
			for(int k = 1; k < ratio; ++k){	//for each space between 2 know value
				tempF1 = tempTab[(i*(m*ratio-2)) + (j)] * (ratio-k)/ratio;
				tempF2 = tempTab[((i+ratio)*(m*ratio-2)) + (j) ] * (k)/ratio;
				tempTab[((i+k)*(m*ratio-2)) + (j)] = round(tempF1 + tempF2);}}}

	//Copy into int tab
	for(int i=0; i<(n-1)*ratio+1; ++i){
		for(int j=0; j<(m-1)*ratio+1; ++j){
			dataOut[i*((m-1)*ratio+1) + j] = (int)tempTab[i*((m-1)*ratio+1) + j];}}

	//free(tempTab);
	vPortFree(tempTab);
}

void byteThreshold(int threshold, int n, int m, uint8_t* dataTab)
{
	for(int i = 0; i<n; ++i){
		for(int j = 0; j<m; ++j){
			if(dataTab[(i*m)+j]<threshold) dataTab[(i*m)+j]=0;
			else dataTab[(i*m)+j]=127;}}
}

void byteSetCenterOfObject(int threshold, int n, int m, uint8_t* dataTab)
{
	int xSum=0, ySum=0, countPixel=0;

	for(int i = 0; i<n; ++i){
		for(int j = 0; j<m; ++j){
			if(dataTab[(i*m)+j]>threshold){
				++countPixel;
				xSum+=j;
				ySum+=i;} } }
	if(countPixel>0) dataTab[ ( (ySum/countPixel) * m ) + (xSum/countPixel) ] = 255;
}

uint16_t fetchDoubleRegisterData (uint16_t startRegister, uint8_t* buffer)
{
	uint16_t retVal = 0;
	buffer[0] = startRegister;
	if(HAL_I2C_Master_Transmit(&hi2c2, sensorAddress, buffer, 1, HAL_MAX_DELAY) != HAL_OK){
		  strcpy((char*)buffer, "Tx error!\r\n");
		  HAL_UART_Transmit(&huart3, buffer, strlen((char*)buffer), HAL_MAX_DELAY);}
	  else{
		  if(HAL_I2C_Master_Receive(&hi2c2, sensorAddress, buffer, 2, HAL_MAX_DELAY) != HAL_OK){
			  strcpy((char*)buffer, "Rx error!\r\n");
			  HAL_UART_Transmit(&huart3, buffer, strlen((char*)buffer), HAL_MAX_DELAY);}
		  else{
			  retVal = buffer[0] + (buffer[1]<<8);}}
	return retVal;
}

/* Random Number Generator function*/
BaseType_t xApplicationGetRandomNumber( uint32_t *pulValue )
{
HAL_StatusTypeDef xResult;
BaseType_t xReturn;
uint32_t ulValue;

	xResult = HAL_RNG_GenerateRandomNumber( &hrng, &ulValue );
	if( xResult == HAL_OK )
	{
		xReturn = pdPASS;
		*pulValue = ulValue;
	}
	else
	{
		xReturn = pdFAIL;
	}
	return xReturn;
}

/**
  * @brief I2C2 Initialization Function
  * @param None
  * @retval None
  */
static void MX_I2C2_Init(void)
{

  /* USER CODE BEGIN I2C2_Init 0 */

  /* USER CODE END I2C2_Init 0 */

  /* USER CODE BEGIN I2C2_Init 1 */

  /* USER CODE END I2C2_Init 1 */
  hi2c2.Instance = I2C2;
  hi2c2.Init.Timing = 0x60404E72;
  hi2c2.Init.OwnAddress1 = 0;
  hi2c2.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
  hi2c2.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
  hi2c2.Init.OwnAddress2 = 0;
  hi2c2.Init.OwnAddress2Masks = I2C_OA2_NOMASK;
  hi2c2.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
  hi2c2.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
  if (HAL_I2C_Init(&hi2c2) != HAL_OK)
  {
    Error_Handler();
  }

  /** Configure Analogue filter
  */
  if (HAL_I2CEx_ConfigAnalogFilter(&hi2c2, I2C_ANALOGFILTER_ENABLE) != HAL_OK)
  {
    Error_Handler();
  }

  /** Configure Digital filter
  */
  if (HAL_I2CEx_ConfigDigitalFilter(&hi2c2, 0) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN I2C2_Init 2 */

  /* USER CODE END I2C2_Init 2 */

}

/**
  * @brief RNG Initialization Function
  * @param None
  * @retval None
  */
static void MX_RNG_Init(void)
{
  hrng.Instance = RNG;
  //hrng.Init.ClockErrorDetection = RNG_CED_ENABLE;
  if (HAL_RNG_Init(&hrng) != HAL_OK)
  {
    Error_Handler();
  }
}

/**
  * @brief System Clock Configuration
  * @retval None
  */
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

  /** Supply configuration update enable
  */
  HAL_PWREx_ConfigSupply(PWR_LDO_SUPPLY);

  /** Configure the main internal regulator output voltage
  */
  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE0);

  while(!__HAL_PWR_GET_FLAG(PWR_FLAG_VOSRDY)) {}

  /** Initializes the RCC Oscillators according to the specified parameters
  * in the RCC_OscInitTypeDef structure.
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI48|RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_BYPASS;
  RCC_OscInitStruct.HSI48State = RCC_HSI48_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLM = 4;
  RCC_OscInitStruct.PLL.PLLN = 275;
  RCC_OscInitStruct.PLL.PLLP = 1;
  RCC_OscInitStruct.PLL.PLLQ = 4;
  RCC_OscInitStruct.PLL.PLLR = 2;
  RCC_OscInitStruct.PLL.PLLRGE = RCC_PLL1VCIRANGE_1;
  RCC_OscInitStruct.PLL.PLLVCOSEL = RCC_PLL1VCOWIDE;
  RCC_OscInitStruct.PLL.PLLFRACN = 0;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }

  /** Initializes the CPU, AHB and APB buses clocks
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2
                              |RCC_CLOCKTYPE_D3PCLK1|RCC_CLOCKTYPE_D1PCLK1;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.SYSCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_HCLK_DIV2;
  RCC_ClkInitStruct.APB3CLKDivider = RCC_APB3_DIV2;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_APB1_DIV2;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_APB2_DIV2;
  RCC_ClkInitStruct.APB4CLKDivider = RCC_APB4_DIV2;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_3) != HAL_OK)
  {
    Error_Handler();
  }
}

/**
  * @brief USART3 Initialization Function
  * @param None
  * @retval None
  */
static void MX_USART3_UART_Init(void)
{
  huart3.Instance = USART3;
  huart3.Init.BaudRate = 115200;
  huart3.Init.WordLength = UART_WORDLENGTH_8B;
  huart3.Init.StopBits = UART_STOPBITS_1;
  huart3.Init.Parity = UART_PARITY_NONE;
  huart3.Init.Mode = UART_MODE_TX_RX;
  huart3.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  huart3.Init.OverSampling = UART_OVERSAMPLING_16;
  huart3.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
  huart3.Init.ClockPrescaler = UART_PRESCALER_DIV1;
  huart3.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
  if (HAL_UART_Init(&huart3) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_UARTEx_SetTxFifoThreshold(&huart3, UART_TXFIFO_THRESHOLD_1_8) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_UARTEx_SetRxFifoThreshold(&huart3, UART_RXFIFO_THRESHOLD_1_8) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_UARTEx_DisableFifoMode(&huart3) != HAL_OK)
  {
    Error_Handler();
  }
}

/**
  * @brief USB_OTG_HS Initialization Function
  * @param None
  * @retval None
  */
static void MX_USB_OTG_HS_USB_Init(void)
{
}

/**
  * @brief GPIO Initialization Function
  * @param None
  * @retval None
  */
static void MX_GPIO_Init(void)
{
	GPIO_InitTypeDef GPIO_InitStruct = {0};

  /* GPIO Ports Clock Enable */
  __HAL_RCC_GPIOC_CLK_ENABLE();
  __HAL_RCC_GPIOF_CLK_ENABLE();
  __HAL_RCC_GPIOH_CLK_ENABLE();
  __HAL_RCC_GPIOA_CLK_ENABLE();
  __HAL_RCC_GPIOB_CLK_ENABLE();
  __HAL_RCC_GPIOD_CLK_ENABLE();
  __HAL_RCC_GPIOG_CLK_ENABLE();
  __HAL_RCC_GPIOE_CLK_ENABLE();

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(GPIOB, LED_GREEN_Pin|LED_RED_Pin, GPIO_PIN_RESET);

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(USB_FS_PWR_EN_GPIO_Port, USB_FS_PWR_EN_Pin, GPIO_PIN_RESET);

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(LED_YELLOW_GPIO_Port, LED_YELLOW_Pin, GPIO_PIN_RESET);

  /*Configure GPIO pin : B1_Pin */
  GPIO_InitStruct.Pin = B1_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  HAL_GPIO_Init(B1_GPIO_Port, &GPIO_InitStruct);

  /*Configure GPIO pins : LED_GREEN_Pin LED_RED_Pin */
  GPIO_InitStruct.Pin = LED_GREEN_Pin|LED_RED_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

  /*Configure GPIO pin : USB_FS_PWR_EN_Pin */
  GPIO_InitStruct.Pin = USB_FS_PWR_EN_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(USB_FS_PWR_EN_GPIO_Port, &GPIO_InitStruct);

  /*Configure GPIO pin : USB_FS_OVCR_Pin */
  GPIO_InitStruct.Pin = USB_FS_OVCR_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  HAL_GPIO_Init(USB_FS_OVCR_GPIO_Port, &GPIO_InitStruct);

  /*Configure GPIO pin : USB_FS_VBUS_Pin */
  GPIO_InitStruct.Pin = USB_FS_VBUS_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  HAL_GPIO_Init(USB_FS_VBUS_GPIO_Port, &GPIO_InitStruct);

  /*Configure GPIO pin : USB_FS_ID_Pin */
  GPIO_InitStruct.Pin = USB_FS_ID_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  GPIO_InitStruct.Alternate = GPIO_AF10_OTG1_HS;
  HAL_GPIO_Init(USB_FS_ID_GPIO_Port, &GPIO_InitStruct);

  /*Configure GPIO pin : LED_YELLOW_Pin */
  GPIO_InitStruct.Pin = LED_YELLOW_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(LED_YELLOW_GPIO_Port, &GPIO_InitStruct);
}

/**
  * @brief  Period elapsed callback in non blocking mode
  * @note   This function is called  when TIM1 interrupt took place, inside
  * HAL_TIM_IRQHandler(). It makes a direct call to HAL_IncTick() to increment
  * a global variable "uwTick" used as application time base.
  * @param  htim : TIM handle
  * @retval None
  */
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
  if (htim->Instance == TIM1) {
    HAL_IncTick();
  }
}

/**
  * @brief  This function is executed in case of error occurrence.
  * @retval None
  */
void Error_Handler(void)
{
  __disable_irq();
  while (1)
  {
  }
}

int _write(int file, char *ptr, int len)
{
  HAL_UART_Transmit(&huart3, ( const uint8_t * ) ptr, len, HAL_MAX_DELAY);
  HAL_UART_Transmit(&huart3, "\r", 1, HAL_MAX_DELAY);
  return len;
}

#ifdef  USE_FULL_ASSERT
/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t *file, uint32_t line)
{
  /* USER CODE BEGIN 6 */
  /* User can add his own implementation to report the file name and line number,
     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  /* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */

Can you try to look at the assembly at addresses in PC and LR and try to find what may have caused this crash?

Also, can you share your complete project?

Still have to change the IP.

STM32 project :

Python server :

If you find something that could be great but at this point I am thinking of grabbing some past commit and start over.

I don"t understand what you mean by looking at the assembly code. They don’t teach that in university and I haven’t seen that on the online guides for debugging.

I downloaded the code and when I build, I get the following errors -

arm-none-eabi-gcc "../Drivers/STM32H7xx_HAL_Driver/Src/stm32hxx_hal_eth.c" -mcpu=cortex-m7 -std=gnu11 -g3 -DDEBUG -DUSE_HAL_DRIVER -DSTM32H723xx -c -I../Core/Inc -I../Drivers/STM32H7xx_HAL_Driver/Inc -I../Drivers/STM32H7xx_HAL_Driver/Inc/Legacy -I../Drivers/CMSIS/Device/ST/STM32H7xx/Include -I../Drivers/CMSIS/Include -I"C:/Users/aggarg/Downloads/H723ZG_freeRtosTcp_testBasic/freeRTOS/FreeRTOS/Source" -I"C:/Users/aggarg/Downloads/H723ZG_freeRtosTcp_testBasic/freeRTOS/FreeRTOS/Source/include" -I"C:/Users/aggarg/Downloads/H723ZG_freeRtosTcp_testBasic/freeRTOS/FreeRTOS/Source/portable" -I"C:/Users/aggarg/Downloads/H723ZG_freeRtosTcp_testBasic/freeRTOS/FreeRTOS-Plus-TCP/source" -I"C:/Users/aggarg/Downloads/H723ZG_freeRtosTcp_testBasic/freeRTOS/FreeRTOS-Plus-TCP/source/include" -I"C:/Users/aggarg/Downloads/H723ZG_freeRtosTcp_testBasic/freeRTOS/FreeRTOS-Plus-TCP/source/portable" -I"C:/Users/aggarg/Downloads/H723ZG_freeRtosTcp_testBasic/freeRTOS/FreeRTOS" -I"C:/Users/aggarg/Downloads/H723ZG_freeRtosTcp_testBasic/freeRTOS/FreeRTOS-Plus-TCP" -I"C:/Users/aggarg/Downloads/H723ZG_freeRtosTcp_testBasic/Drivers/STM32H7xx_HAL_Driver/Inc" -I"C:/Users/aggarg/Downloads/H723ZG_freeRtosTcp_testBasic/Drivers/STM32H7xx_HAL_Driver/Src" -O0 -ffunction-sections -fdata-sections -Wall -fstack-usage -fcyclomatic-complexity -MMD -MP -MF"Drivers/STM32H7xx_HAL_Driver/Src/stm32hxx_hal_eth.d" -MT"Drivers/STM32H7xx_HAL_Driver/Src/stm32hxx_hal_eth.o" --specs=nano.specs -mfpu=fpv5-d16 -mfloat-abi=hard -mthumb -o "Drivers/STM32H7xx_HAL_Driver/Src/stm32hxx_hal_eth.o"
../Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_rng_ex.c:98:64: error: unknown type name 'RNG_ConfigTypeDef'; did you mean 'EXTI_ConfigTypeDef'?
   98 | HAL_StatusTypeDef HAL_RNGEx_SetConfig(RNG_HandleTypeDef *hrng, RNG_ConfigTypeDef *pConf)
      |                                                                ^~~~~~~~~~~~~~~~~
      |                                                                EXTI_ConfigTypeDef
../Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_rng_ex.c:197:64: error: unknown type name 'RNG_ConfigTypeDef'; did you mean 'EXTI_ConfigTypeDef'?
  197 | HAL_StatusTypeDef HAL_RNGEx_GetConfig(RNG_HandleTypeDef *hrng, RNG_ConfigTypeDef *pConf)
      |                                                                ^~~~~~~~~~~~~~~~~
      |                                                                EXTI_ConfigTypeDef
../Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_rng_ex.c: In function 'HAL_RNGEx_LockConfig':
../Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_rng_ex.c:273:9: error: 'RNG_HandleTypeDef' has no member named 'ErrorCode'
  273 |     hrng->ErrorCode = HAL_RNG_ERROR_BUSY;
      |         ^~
../Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_rng_ex.c:273:23: error: 'HAL_RNG_ERROR_BUSY' undeclared (first use in this function); did you mean 'HAL_DMA_ERROR_BUSY'?
  273 |     hrng->ErrorCode = HAL_RNG_ERROR_BUSY;
      |                       ^~~~~~~~~~~~~~~~~~
      |                       HAL_DMA_ERROR_BUSY
../Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_rng_ex.c:273:23: note: each undeclared identifier is reported only once for each function it appears in
../Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_rng_ex.c: In function 'HAL_RNGEx_RecoverSeedError':
../Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_rng_ex.c:322:14: warning: implicit declaration of function 'RNG_RecoverSeedError'; did you mean 'HAL_RNGEx_RecoverSeedError'? [-Wimplicit-function-declaration]
  322 |     status = RNG_RecoverSeedError(hrng);
      |              ^~~~~~~~~~~~~~~~~~~~
      |              HAL_RNGEx_RecoverSeedError
../Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_rng_ex.c:326:9: error: 'RNG_HandleTypeDef' has no member named 'ErrorCode'
  326 |     hrng->ErrorCode = HAL_RNG_ERROR_BUSY;
      |         ^~
../Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_rng_ex.c:326:23: error: 'HAL_RNG_ERROR_BUSY' undeclared (first use in this function); did you mean 'HAL_DMA_ERROR_BUSY'?
  326 |     hrng->ErrorCode = HAL_RNG_ERROR_BUSY;
      |                       ^~~~~~~~~~~~~~~~~~
      |                       HAL_DMA_ERROR_BUSY
make: *** [Drivers/STM32H7xx_HAL_Driver/Src/subdir.mk:88: Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_rng_ex.o] Error 1
make: *** Waiting for unfinished jobs....
"make -j8 all" terminated with exit code 2. Build might be incomplete.

12:11:00 Build Failed. 8 errors, 3 warnings. (took 38s.739ms)

This page provides more details on how to debug a hard fault - Debugging and diagnosing hard faults on ARM Cortex-M CPUs

This is usually a good strategy - develop small piece of code and test it and iterate. That way when something is not working, you have a smaller chunk of code to focus on.

Also, using suspend/resume for synchronization is almost never a good idea. Consider using other synchronization primitives such as task notifications, semaphores etc.

Your problem could be caused by the fact that I manually added the RNG file instead of including RNG in cubeMX.
But either way it should work as it is a modified version of the project you gave me in my first post. ( :

I read this page. From what I understood I should implement the assembly code to see the state of the registers before the fault, but can’t I just see this information in the fault analyzer window (3rd picture) :

I was able to do what I wanted by working on a previous commit.

Thank you for the information.
Since what I am doing is getting a sensor’s informations every 100ms then sending those informations through TCP I need to wait for the sensor to get the new informations to start sending.
Since semaphores are non blocking it doesn’t look to be the most suitable. Mutex are blocking from what I understood so that would be better.
I will look into notifications.

I do not think that this is accurate. Semaphores and mutexes both can block for a given amount of time or forever.

Yes, you are right. The next step usually is to examine the assembly code at the location in PC and LR - there is generally is disassembly view all IDEs.

Just to add to what Anuriddha already mentioned, you can read the following resources to learn more about semaphores -

That is great.