PIC32MX: passing 64bit in a va_list doesnt work when the kernel is started

Hi guys, 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. The routine is something like this: ~~~

define BIGNUMBER ( 1ULL << 63 )

void step2(int ignoreme, valist args){ unsigned long long n = vaarg(args, unsigned long long);
if(n == BIGNUMBER){
    LED_GREEN();
}else{
    LED_RED();
}
} void step1(int ignoreme, …){ valist args; vastart(args, ignoreme); step2(ignoreme, args); va_end(args); } … step1(1234, BIGNUMBER); ~~~ 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. Anyone has ideas about what could be wrong?

PIC32MX: passing 64bit in a va_list doesnt work when the kernel is started

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.

PIC32MX: passing 64bit in a va_list doesnt work when the kernel is started

When that code is being called from a task, it doesn’t work like expected. When that code is NOT being called from a task, it does work like expected. The addresses of an int in both the working and broken version: working version: ->a0010b18 (% 8 is 0) broken version: ->a0010b04 (%8 is 4) Also when declaring the affected functions as static, the problem goes away. You mention the MZ port, but I’m using the MX port. Not sure if that’s related.

PIC32MX: passing 64bit in a va_list doesnt work when the kernel is started

You are showing this test: ~~~ unsigned long long n = vaarg(args, unsigned long long); if(n == BIGNUMBER){ LEDGREEN(); }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 = vaarg( args, unsigned long ); unsigned long n2 = vaarg( args, unsigned long );

if( ffconfigBYTEORDER == pdFREERTOSBIG_ENDIAN )

unsigned long long n = ( ( ( unsigned long long )n1 ) << 32 ) | ( unsigned long long ) n2;

elif( ffconfigBYTEORDER == pdFREERTOSLITTLE_ENDIAN )

unsigned long long n = ( ( ( unsigned long long )n2 ) << 32 ) | ( unsigned long long ) n1;

else

#error ffconfigBYTE_ORDER not defined

endif

~~~

PIC32MX: passing 64bit in a va_list doesnt work when the kernel is started

What happens: – 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 Hope this is clear now

PIC32MX: passing 64bit in a va_list doesnt work when the kernel is started

Think i found it… in this thread from 2011 http://www.freertos.org/FreeRTOSSupportForumArchive/April2011/freertosFreeRTOS7.0.0PIC32alignmentofstack_4480228.html), Richard suggests to add this line /* 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?

PIC32MX: passing 64bit in a va_list doesnt work when the kernel is started

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.

PIC32MX: passing 64bit in a va_list doesnt work when the kernel is started

Not too familiar with this but Disassembly view shows: ~~~ !portTASK_FUNCTION(vTaskCode, vParams){ 0x9D007B80: ADDIU SP, SP, -24 <– BREAKPOINT HERE … ~~~ and in the Variables view, adding a watch on sp shows: address: 0x74 value: 0xA00017AC Doing the same with pxTopOfStack-- commented gives: address: 0x74 value: 0xA0001798