FreeRTOS + TCP and FPU on STM32F407ZE

bghost4 wrote on Friday, August 02, 2019:

Using FreeRTOS v10.2.1 and FreeRTOS+TCP v2.0.11
grafted onto an STM32CubeIDE Project

Using STM32F407ZE

OK I’m probably doing something stupid, but I had firmware that was working fine until I put some floating point math in it.

quick rundown, I have this board, it has an Ethernet port it and uses ADC1 to read an analog pressure sensor. I’m converting the ADC counts to a KPA value to send back to the computer. its a simple ADC_COUNT / COUNTS_PER_KPA.

the ethernet listens on a port using FreeRTOS+TCP receives a command to do something, processes command then returns the result. one of my commands is get pressure, where I do the ADC->kPa conversion and send it back. this works fine, until the client disconnects then the firmware gets locked at:
configASSERT( ( pxLink->xBlockSize & xBlockAllocatedBit ) != 0 );
in heap_4.c line 278

stack is:
vPortFree() at heap_4.c
prvDeleteTCB() at tasks.c
prvCheckTasksWaitingTermination() at tasks.c
prvIdleTask() at tasks.c
pxPortInitiaseStack at port.c
–end–

upon removing any calls to floating point math, the code runs without problems, and dumps the task accordingly. I was unable to recreate the problem on a new project with no TCP/IP so it may be related to that (FreeRTOS+TCP)?

Thanks for any input I get on this.

below is crapy pseudocode that is similar to what im doing

Pseudo code:

#define COUNTS_PER_KPA 0.00811f

float adcTokPa(uint16_t adv_value) {
        return ((float)adc_value)/COUNTS_PER_KPA;
}

void send_response(Socket_t client,float value) {

            FreeRTOS_Send(client,&value,sizeof(float),0);

}

void connection_handler(void *params) {
      Socket_t *client_ptr = (Socket_t * )params;
       Socket_t client = *client_ptr;
       uint16_t cmd;
       
       for(;;) {
               bytesRecv = FreeRTOS_recv(client,&cmd,sizeof(uint16_t),0);
               if(bytesRecv != sizeof(uint16_t)) {
                      if( bytesRecv < 0 ) {
                              //Some kind of Socket Error
                              //shutdown FreeRTOS Socket
                                  vTaskDelete(NULL); //Should delete this connection handler
                      }
               } else {
                 switch(cmd) {
                         //
                         case 42:
                                 send_response(client,adcTokPa(adv_value));
                                 break;
                          default:
                                  break;
                 }
               }
               
               
       }
       
}

void listen_task(void * params) {
    for(;;) {
            Socket_t client = FreeRTOS_Accept();
            xCreateTask(connection_handler,"ConHandle",128,&client,CON_TASK_PRIO,NULL);
    }
}

}

rtel wrote on Friday, August 02, 2019:

Does your part have an flu? If so you need to be using the FreeRTOS/source/portable/arm_cm4f port and tell the compiler which cpu model is available on the chip. That will enable the fpu, which must be done before use. Not sure if that helps. Do the floating point instructors work from main() before the scheduler starts?

rtel wrote on Friday, August 02, 2019:

FPU, not flu! Auto correct on my cellphone.

aggarg-aws wrote on Friday, August 02, 2019:

The part you mentioned (i.e. STM32F407ZE) does have an FPU (Floating Point Unit) and therefore you need to make sure that you are using CM4F port.

Thanks.

bghost4 wrote on Saturday, August 03, 2019:

but the fpu works fine. its when a client disconnects from the socket that it gets stuck in heap_4 everything works fine, until you try and disconnect.if i take the floating point math out. disconnects work fine. I will double check on monday that the floating point math is correct. as in the math actually works out. sorry if im not being clear on this, it doesn’t seem to be a straightforward problem. I was just really wondering if in FreeRTOS there is some connection between deleting a task and the FPU or deleting a task that has a socket that also used the FPU. it doesn’t make any sense. but if I remove all floating point math, I can delete the task successfully and it doesn’t hang.

hs2sf wrote on Saturday, August 03, 2019:

FreeRTOS must save/restore also FPU registers when switching task context if application is built with (hard) FPU support enabled. Even if no floating point math is directly used, nowadays compilers make use of FPU registers for various purposes if allowed/enabled.
So you must use the matching CM4F Port.

bghost4 wrote on Monday, August 05, 2019:

both port.c and portmacro.h come from the CM4F port, Its possible I missed something else?
everything works fine until it goes to delete the task that uses the FPU registers. then it hangs at :

configASSERT( ( pxLink->xBlockSize & xBlockAllocatedBit ) != 0 ); 
in heap_4.c line 278

I’m working on stripping out all code, and just leaving the code that causes the issue so I can post it.

bghost4 wrote on Monday, August 05, 2019:

ok, added project to github This project uses CubeIDE 1.0
https://github.com/bghost4/FPUFAIL

the code hits a configASSERT after a disconnect deletes the connection_handler task

aggarg-aws wrote on Monday, August 05, 2019:

When floating point math is used, we store FPU registers on the task’s stack during context switch. This means that more stack space is used as compared to the case when FPU is not used. I see that you have 128 words stack size for all the tasks which may not be enough and result in memory corruption because of stack overflow. Would you please try increasing the stack size for the tasks which use floating point math?

Please also set configCHECK_FOR_STACK_OVERFLOW in your FreeRTOSConfig.h to catch stack overflows: www.freertos.org/Stacks-and-stack-overflow-checking.html

Which hardware are you using? Is it a development board or is it your custom hardware?

Thanks.

bghost4 wrote on Monday, August 05, 2019:

it is custom hardware. I do have a f407 discovery board with the add on header I could try and port the code to. at first glance it seems to have worked.

bghost4 wrote on Monday, August 05, 2019:

Indeed thats what it was, Thanks for the help.

aggarg-aws wrote on Monday, August 05, 2019:

I am glad that it worked for you. Just FYI, you can use uxTaskGetStackHighWaterMark to find the minimum stack required for each task: http://www.freertos.org/uxTaskGetStackHighWaterMark.html

Thanks.