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 */