Skip to main content
AMars.4
Associate III
May 2, 2024
Solved

TouchGFX - Library functions used (maths, strings).

  • May 2, 2024
  • 4 replies
  • 3713 views

Hi all,

I currently working on a project using TouchGFX, multiple tasks are using functions from <math.h> which are not re-entrant, so I have them mutex protected. The drivers using these functions are written in C.

Does anyone know if the TouchGFX library uses any non re-entrant library functions? Do I need to be careful with anything I use in the application?

Kind Regards,

Anthony 

Best answer by Tesla DeLorean

These should all be thread and interrupt safe on ARM processors. May be need a different library?

4 replies

Senior
May 4, 2024

What do you think is the relationship between TouchGFX and <math.h>

You have one FreeRTOS task with which the TouchGFX layer is started.

what is the role of this mutex?!?

These are functions that do not use a shared resource

Use the MPV.
In most projects I've done, there are several functions in the Screen classes that update variables on the display. Everything else is in the model

AMars.4
AMars.4Author
Associate III
May 4, 2024

I have multiple other tasks using the maths functions, not just the TouchGFX task.

Some functions in <math.h> are #defined out by _REENT_ONLY, such as sqrt(). So if I want to use this function from multiple tasks safely I need to make sure access to this function is mutex protected.

I do use MVP, just that some of the calculations I am doing in the other tasks so that the UI task doesn't have to handle everything.

I was curious as to whether the renderer core library makes use of these maths functions, but source code is not provided, maybe there is another way to find out.

From <math.h>

/* Reentrant ANSI C functions. */

#ifndef __math_68881
extern double atan (double);
extern double cos (double);
extern double sin (double);
extern double tan (double);
extern double tanh (double);
extern double frexp (double, int *);
extern double modf (double, double *);
extern double ceil (double);
extern double fabs (double);
extern double floor (double);
#endif /* ! defined (__math_68881) */

/* Non reentrant ANSI C functions. */

#ifndef _REENT_ONLY
#ifndef __math_68881
extern double acos (double);
extern double asin (double);
extern double atan2 (double, double);
extern double cosh (double);
extern double sinh (double);
extern double exp (double);
extern double ldexp (double, int);
extern double log (double);
extern double log10 (double);
extern double pow (double, double);
extern double sqrt (double);
extern double fmod (double, double);
#endif /* ! defined (__math_68881) */
#endif /* ! defined (_REENT_ONLY) */

 

Tesla DeLorean
Guru
May 4, 2024

Which functions in math.h ?

I can see string.h perhaps strtok() it would be better to use strsep()

Tips, Buy me a coffee, or three.. PayPal VenmoUp vote any posts that you find helpful, it shows what's working..
AMars.4
AMars.4Author
Associate III
May 4, 2024

Yes, I avoid strtok() and use a function similar to what you suggest. 

Maths functions include sqrt, atan2, cosh, sinh, and some of the other hyperbolic functions, but I noticed the issue through two tasks both using sqrt().

Tesla DeLorean
Tesla DeLoreanBest answer
Guru
May 4, 2024

These should all be thread and interrupt safe on ARM processors. May be need a different library?

Tips, Buy me a coffee, or three.. PayPal VenmoUp vote any posts that you find helpful, it shows what's working..
Senior
May 5, 2024

Sorry, I haven't had a similar problem. For me, the only solution is a wrapper with mutexes

Tesla DeLorean
Guru
May 5, 2024

The routines and the task swapping should push and save MCU and FPU context.

If the FPU context isn't saved all the math using it will be compromised,  by interrupts or task changes.

Build without the FPU, so it uses the software math library.

Tips, Buy me a coffee, or three.. PayPal VenmoUp vote any posts that you find helpful, it shows what's working..
AMars.4
AMars.4Author
Associate III
May 5, 2024

I will double check this, I am currently building with FPU.

At some point I noticed my project didn't have ENABLE_FPU (CubeMX freertos option), but this is now enabled, I should remove the mutexes and see if it now works with this defined.

It sounds very much like the FPU context not being saved, so will investigate based on that.

Thanks.

AMars.4
AMars.4Author
Associate III
May 29, 2024

Update:

My issue has been resolved, it turned out to be an issue with I2C which is being shared by two sensors, the data was being corrupted... looking at the comments in the <math.h> file confused me, it turns out most of these functions are thread safe according to ARM (as Tesla Delorean mentions above).

https://developer.arm.com/documentation/dui0475/m/the-c-and-c---library-functions-reference/thread-safe-c-library-functions

 

abs(), acos(), asin(),atan(), atan2(), atof(),atol(), atoi(), bsearch(),ceil(), cos(), cosh(),difftime(), div(), exp(),fabs(), floor(), fmod(),frexp(), labs(), ldexp(),ldiv(), log(), log10(),memchr(), memcmp(), memcpy(),memmove(), memset(), mktime(),modf(), pow(), qsort(),sin(), sinh(), sqrt(),strcat(), strchr(), strcmp(),strcpy(), strcspn(), strlcat(),strlcpy(), strlen(), strncat(),strncmp(), strncpy(), strpbrk(),strrchr(), strspn(), strstr(),strxfrm(), tan(), tanh()

These functions are inherently thread-safe.

I removed the mutexes after resolving the I2C issue and all is working.

Missing from the list, which I am using but not from multiple threads, I'm assuming they require a mutex unless ARM just missed them off the list (not tested yet).

  • asinh()
  • atanh()

Apologies for any confusion, lesson learnt... don't trust anything, don't jump to conclusions. :)

 

 

Tesla DeLorean
Guru
May 29, 2024

Yes, I think the inherent danger here is the lack of a proper context push at the interrupt handler or context switch when using the FPU (ARM, or 6888x). Normal ABI rules would have routines using FPU to VPUSH/VPOP things they need, but higher level routines wouldn't if they don't explicitly use the FPU registers, and would similarly be unaware of the deeper call-tree.

Interrupts might by default not push them, as the MCU pushes R0-R3, and normal ABI rules would have you pushing R4-R8, R14, etc.

I'd anticipate asinh(), atanh(), asoch(), atan2() etc to be safe. Functions are going to use the stack for auto/local variables and storage of intermediate solutions, if not in registers. They might use static/const tables to speed computations, but aren't going to stash thing in singular global memories.

I'd watch _set_errno() and exception handling

Tips, Buy me a coffee, or three.. PayPal VenmoUp vote any posts that you find helpful, it shows what's working..