snprintf error (PIC32MZ2048EFM064)

cmarmonier wrote on Monday, October 29, 2018:


When I use this code (before to create tasks):

    char dgb_buf[30];
    snprintf(dgb_buf, sizeof(dgb_buf), "%u", 123);
    printf("dgb_buf1 : %s\r\n", dgb_buf);
    snprintf(dgb_buf, sizeof(dgb_buf), "%f", 1.23);
    printf("dgb_buf2 : %s\r\n", dgb_buf);
    snprintf(dgb_buf, sizeof(dgb_buf), "%s", "yolo");
    printf("dgb_buf3 : %s\r\n", dgb_buf);
    printf("dgb_buf1b : %u\r\n", 123);
    printf("dgb_buf2b : %f\r\n", 1.23);

It is displayed :

dgb_buf1 :
dgb_buf2 :
dgb_buf3 : yolo
dgb_buf1b : 123
dgb_buf2b : 1.230000

How can I do to resolve this problem ?

I use FreeRTOS V10.1.1 and XC32 compileur v2.10 with the FreeRTOS PIC32MZ demo project. I use this configuration :

    #pragma config FNOSC = SPLL, FSOSCEN = OFF, IESO = OFF, POSCMOD = OFF
    #pragma config DMTINTV = WIN_127_128, WDTSPGM = STOP, WINDIS = NORMAL
    #pragma config WDTPS = PS1048576, FWDTWINSZ = WINSZ_25, DMTCNT = DMT31
    #pragma config FPLLIDIV = DIV_1, FPLLRNG = RANGE_5_10_MHZ, FPLLICLK = PLL_FRC
    #pragma config FPLLMULT = MUL_50, FPLLODIV = DIV_2, UPLLFSEL = FREQ_24MHZ
    #pragma config BOOTISA = MIPS32, TRCEN = OFF, ICESEL = ICS_PGx1, JTAGEN = OFF

    //#pragma config DEBUG = ON
    #pragma config CP = OFF  

    #pragma config USERID = 0xFFFF
    #pragma config SMCLR = MCLR_NORM
    #pragma config SOSCGAIN = GAIN_2X
    #pragma config SOSCBOOST = ON
    #pragma config POSCGAIN = GAIN_2X
   #pragma config POSCBOOST = ON

cmarmonier wrote on Monday, October 29, 2018:

Also, I change heap siaze (0 -> 20000) and min stack size (0 -> 10000) : I have the same problem

heinbali01 wrote on Monday, October 29, 2018:

This is a forum for FreeRTOS. What makes you think that this problem is related to FreeRTOS?
The function snprintf() is normally provided by the compiler makers, unless you’re using one of the variants of printf-stdarg.c. That module would overwrite the sprintf() functions with a version that is simpler and less stack-hungry.

cmarmonier wrote on Monday, October 29, 2018:

When I use snprintf() in a new project without FreeRTOS, this function operates. Perhaps problem come from configuration of the FreeRTOS PIC32MZ demo project ?
I don’t have a printf-stdarg.c file in my project

cmarmonier wrote on Monday, October 29, 2018:

… I don’t understand why printf operates but not sprintf and snprintf (with and without legacy libc)

friesen wrote on Monday, October 29, 2018:

I’d suggest you ask this question on the microchip forums, either the PIC32 or Harmony. I agree with Tibosch that this isn’t a FreeRTOS related issue, and you will get much better response there.

cmarmonier wrote on Monday, October 29, 2018:

ok I thank you

cmarmonier wrote on Wednesday, October 31, 2018:

For the moment, nobody in microchip forum find a solution :

After some tests, problem appears only when project integrate FreeRTOS : it isn’t a problem of project configuration.
If I don’t create task, I have the problem.

rtel wrote on Friday, November 02, 2018:

Sorry for delay - somehow missed the email notification of your post.

Can you check that your stack is 8-byte aligned. You can do that by
putting break point on the call to the print formatting function and
checking the stack pointer value in the debugger. If it is not 8-byte
aligned then try placing a break point on the opening bracket of a
function that implements a task entry point to see if it is aligned there.

cmarmonier wrote on Monday, November 12, 2018:

Me too, I missed notification.

When I set a break point to snprintf call, PC = 0x9D00CDDC

ldb wrote on Tuesday, November 13, 2018:

Most likely the problem is FreeRTOS is using dynamic memory allocator and it’s clashing with the standard memory allocator. Usually the C memory system positions the heap based on something like a marker in the linker file like _end. It’s likely your FreeRTOS allocator is using the same or an overlapping marker. It is quite normal in many implementations for Printf , snprintf and all the variants to malloc a small buffer.

Option 1: Find out what in the linker file is used to mark the heap in both systems and then change it in FreeRTOS and make the allocators avoid each other.
Option2: Make FreeRTOS use the C system malloc functions.

cmarmonier wrote on Thursday, November 15, 2018:

Option 1:
I don’t have a custom linker file

Option 2 :
There are same results with heap_3.c and heap_4.c

ldb wrote on Friday, November 16, 2018:

So use heap_2.c and make sure you follow the instructions are below, it’s a simply array you put in your main c file and set the flag


You need to set configTOTAL_HEAP_SIZE with some suitable size for the array that is all the memory your allocator has so make sure you make it big enough (AKA what are you allocating for each of your tasks) and add some reasonable overhead.

If that doesn’t work then there is something a lot deeper at play.

By default the FreeRTOS heap is declared by FreeRTOS and placed in memory by the linker. Setting configAPPLICATION_ALLOCATED_HEAP to 1 allows the heap to instead be declared by the application writer, which allows the application writer to place the heap wherever they like in memory.

If heap_1.c, heap_2.c or heap_4.c is used, and configAPPLICATION_ALLOCATED_HEAP is set to 1, then the application writer must provide a uint8_t array with the exact name and dimension as shown below. The array will be used as the FreeRTOS heap. How the array is placed at a specific memory location is dependent on the compiler being used - refer to your compiler's documentation.

uint8_t ucHeap[ configTOTAL_HEAP_SIZE ];

cmarmonier wrote on Friday, November 16, 2018:

it doesn’t operate T_T.

My configuration :
configTOTAL_HEAP_SIZE = 60000
heap_2.c is loaded

cmarmonier wrote on Tuesday, December 04, 2018:


Microchip support found the solution : problem come from fputc() in debug.c, it must replace this function by :

void __attribute__((externally_visible)) _mon_putc (char c){
    //Wait for the transmitter to be ready
    while(U2STA & _U2STA_UTXBF_MASK);
    //Send character
    U2TXREG = c;
    //Wait for the transfer to complete
    while(!(U2STA & _U2STA_TRMT_MASK));