64bit application on FreeRTOS windows port

Hello,

I would like to run my application compiled by MinGW-w64 on FreeRTOS.
Is it possible?
I understand that FreeRTOS-windows-port supports only 32-bit application.
Is there any solution for that? Could anyone help me?

[Motivation]
Originally, my application is running on Xilinx UltraScale+.
I use FreeRTOS-Cortex-A53(64bit)-port for that.
This time, I am trying to run same application on Windows for additional tests.
I have compiled my application with MinGW-w64 except for BSP(Board support package provided by Xilinx) and FreeRTOS. I should prepare some stub modules instead real BSP.
But even if fake BSP is prepared, my application cannot run as multi-task application because there is no FreeRTOS-x64-port.
If anyone knows solution, please let me know.

Any information or opinions are welcome.
Thank you in advance.

wat

I was building the MSVC port as 64-bits for a while. As I recall, it worked, but mismatched types generated warnings. It may also have fallen over if the tick count went over 0xffffffff.

It should be straight forward to create a port that automatically switches between 32 and 64-bits depending on the compiler options - it would be great if you could submit a pull request to do that. It would need to add support for 64-bit here, using the same datatypes as the 64-bit Arm port here. If switching between 32 and 64-bit uses a predefined macro, then it would need to be a macro defined by both MSVC and GCC.

Thank you very much for a kind and valuable advice!
I will try to add 64bit support for TickType_t and portMAX_DELAY based on your instruction. I will report it’s result here. Thank you again.

I added 64bit support for TickType_t and portMAX_DELAY. Then, everything works well! Thank you very much for your help.

It should be straight forward to create a port that automatically switches between 32 and 64-bits depending on the compiler options - it would be great if you could submit a pull request to do that.

I tried it but gave up.
At first, I removed the definition for TickType_t width from FreeRTOSConfig.h and added automatic switching in portmacro.h. But preprocessor showed error here because TickType_t width must be defined before including portmacro.h.
I think modification should be applied in “portmacro.h” only. It means there is no normal way to introduce automatic switching. I can add #undef and re-#define for configTICK_TYPE_WIDTH_IN_BITS in portmacro.h based on compile option. But it is too complicated.

I think the best acceptable solution is making preprocessor show error if TickType_t width does not match compile option. Then, configTICK_TYPE_WIDTH_IN_BITS must be modified manually in FreeRTOSConfig.h.

Could you tell me your opinion? If I misunderstand your idea, please let me know.

Anyway, I reached my original goal because I don’t switch compile option. Thank you again for your help!

Is it necessarily an error to use a narrower type for TickType_t? I think it is inefficient but not necessarily an error. You probably want to suggest something like this -

#if ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_16_BITS )
    typedef uint16_t             TickType_t;
    #define portMAX_DELAY        ( TickType_t ) 0xffff
#elif ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_32_BITS )
    typedef uint32_t             TickType_t;
    #define portMAX_DELAY        ( TickType_t ) 0xffffffffUL

    #if !defined( __x86_64__ ) && !defined( _M_X64 )
        /* 32-bit tick type on a 32-bit architecture, so reads of the tick count do
         * not need to be guarded with a critical section. */
        #define portTICK_TYPE_IS_ATOMIC    1
    #endif
#elif ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_64_BITS )
    typedef uint64_t         TickType_t;
    #define portMAX_DELAY    ( ( TickType_t ) 0xffffffffffffffff )

    #if defined( __x86_64__ ) || defined( _M_X64 )
        /* 64-bit tick type on a 64-bit architecture, so reads of the tick count do
         * not need to be guarded with a critical section. */
        #define portTICK_TYPE_IS_ATOMIC    1
    #endif
#else
    #error configTICK_TYPE_WIDTH_IN_BITS set to unsupported tick type width.
#endif

Is that right?

Thank you for your opinion.
I misunderstood the role of TickType_t. Your idea is correct.

When I built the demo application with 32bit TickType_t on 64bit architecture, I saw several compiler warnings which indicates inappropriate casts between TickType_t and pointer type. Therefore I thought TickType_t variables have address information in such cases. 64bit address should not be cast to 32bit variable. That’s why I suggested preprocessor error in the last post.
But now, I understand pointer type variable here is (void *)pvParameter on task creation. It is not used as address for such cases.(Example) TickType_t variable does not have address information in any case. I understand TickType_t can be different width with architecture.

Thank you for example code. That is exactly what I intend now. But I have only one question. I expected 32bit TickType_t variable is atomic on 64bit system because 64bit register can be used as 32bit register. But portTICK_TYPE_IS_ATOMIC is 0 in such case in your example code. Is there any reason for that?

I have not verified that - Can you verify that by looking at the assembly? If it is atomic, then portTICK_TYPE_IS_ATOMIC should be 1 unconditionally on 32-bit architecture.

Can you verify that by looking at the assembly?

I checked all combinations of TickType_t width and architecture width.
Results are

32bit TickType_t on MinGW32: Atomic
64bit TickType_t on MinGW32: Non atomic
32bit TickType_t on MinGW64: Atomic
64bit TickType_t on MinGW64: Atomic

For example, 32bit TickType_t on MinGW64 is shown below.
C source is

xTicks = xTickCount; (in xTaskGetTickCount() in task.c)

Assembly is

mov     0x11fa1e(%rip),%eax        # 0x7ff7f18ff150 <xTickCount>
mov     %eax,-0x4(%rbp)

32bit value is moved between register and memory atomically.
I also checked all cases for MSVC on Visual Studio. Results are same as MinGW.
I think portTICK_TYPE_IS_ATOMIC can be always 1 if TickType_t is 32bit.

Can I send PR for this change to the repository?

Yes, please. Thank you for your contribution!

@aggarg
Thank you for approving my PR!

Next, I would like to improve 64bit support of Demo applications.(MinGW Demo and MSVC Demo)
I think the following changes are desirable.

  1. Add automatic tick type width switching.
    Tick type is defined as 32bit or 64bit automatically in FreeRTOSConfig.h by using compiler predefined macro. This is the change discussed in the begin of this topic.

Example(MinGW demo)

#ifdef __x86_64__
	#define configTICK_TYPE_WIDTH_IN_BITS			TICK_TYPE_WIDTH_64_BITS
#else
	#define configTICK_TYPE_WIDTH_IN_BITS			TICK_TYPE_WIDTH_32_BITS
#endif
  1. Solve compiler warnings for the cast operation between 32bit and 64bit.
    64bit compiler reports several warnings in current demo application.
    Some of them are the cast operation between pointer type and uint32_t. I think uint32_t should be modified to UBaseType_t in these cases.
    Format specifiers in printf() also bring compiler warnings. “%u” supports only 32bit. It should be modified to “%llu” or “%zu”. Recently, I have wasted time to find the reason I couldn’t get 64bit tick count. I thought it was TickType_t problem but actually it was printf() problem. So, I think it should be modified.

Could you tell me your opinion for these two changes?

1 Like

Both the suggestions look good to me. Please raise a PR.

@aggarg
Thank you for your support. I will send PR.