When creating a va_list containing a 64bit number, and later on popping this number off, it isnt the same value anymore.
Doing this before the kernel is started works like expected, but doing the same thing from within a thread fails.
So all this does is passing a 64bit number through var args to a processing function that checks if the received value equals the value that was passed to it.
Attached is a quickly made MPLABX project demonstrating this if it’s not clear.
CPU is the PIC32MX695F512L, compiler XC32.
I think it has to be a FreeRTOS problem (or at least in its PIC32MX port) because again, it does work like expected when doing this if FreeRTOS is not used. Also it works when using another RTOS.
The MZ port had a problem with byte alignment in an interrupt, but not
in a task. Is the code you post being called from a task? Please check
the stack alignment inside the task is 8-byte aligned and report back.
Check the stack alignment on the first instruction in the task - before
anything has been pushed to the stack by the compiler.
unsigned long long n = va_arg(args, unsigned long long);
if(n == BIGNUMBER){
LED_GREEN();
}else{
LED_RED();
}
But you do not tell what happens. Do you see an exception (alignment), or a red or a green LED?
And also: are you able to make a work-around, by calling va_arg() two times for the type unsigned long?
If I’m not mistaken:
unsigned long n1 = va_arg( args, unsigned long );
unsigned long n2 = va_arg( args, unsigned long );
#if( ffconfigBYTE_ORDER == pdFREERTOS_BIG_ENDIAN )
unsigned long long n = ( ( ( unsigned long long )n1 ) << 32 ) | ( unsigned long long ) n2;
#elif( ffconfigBYTE_ORDER == pdFREERTOS_LITTLE_ENDIAN )
unsigned long long n = ( ( ( unsigned long long )n2 ) << 32 ) | ( unsigned long long ) n1;
#else
#error ffconfigBYTE_ORDER not defined
#endif
If the code is running from a task, the LED is RED, meaning the test failed.
If the code is NOT running from a task, the LED is GREEN, meaning the test passed.
The LED_ functions arent really relevant here, its just to have visual feedback on the if statement.
No runtime exceptions happen.
I ran your suggestion, but the behaviour is the same (as in: test fails when running from a task, passes when not running from a task).
With BIGNUMBER set to 0xFFFFFFFFFFFFFFFFUL, debugger shows the following at the if statement:
From within a task
With the 1x unsigned long long: <-- FAILS n = 0xFFFFFFFFA5A5A5A5
With the 2x unsigned long: <-- FAILS n1 = 0xA5A5A5A5 n2 = 0xFFFFFFFF n = 0xFFFFFFFFA5A5A5A5
Could the 0xA5 come from #define tskSTACK_FILL_BYTE ( 0xa5U ) (in tasks:c) ?
From outside a task (before starting kernel)
With the 1x unsigned long long: <-- PASSES n = 0xFFFFFFFFFFFFFFFF
With the 2x unsigned long: <-- FAILS n1 = 0x00000000 n2 = 0xFFFFFFFF n = 0xFFFFFFFF00000000
/* Ensure byte alignment is maintained when leaving this function. */
pxTopOfStack--;
as the first line in the function pxPortInitialiseStack from tasks.c
In the current version (FreeRTOS 9.0.0), it is already there so I commented it, and the test passed. The 64bit parameter seems to be correctly aligned on the stack now.
I’m not sure which one of the two (pxTopOfStack-- or not) is correct, but in the project I’m using this in (lots of hardware, libraries, modules,…) nothing is breaking so far. This makes me quite confident that this fix is okay, at least for the project I’m working on. But it might not be guaranteed for everyone…
What do you guys think? Is this compiler-related (I’m on XC32 v1.42) or even an error in the PIC32MX port?
This is what the second post in this thread is referring to. If you put
a break point on the first instruction in a task (by which I mean the
first assembly instruction - the function entry point - before any
function pre-able added by the compiler) then stop on the break point -
what is the stack pointer value? The alignment is the important bit.