printf does not work in one of my programs

cancel
Showing results for 
Search instead for 
Did you mean: 

printf does not work in one of my programs

1,546 Views
Contributor III

Hi Everyone,

I am using MCUXpresso and have been able to write/run several C/C++ projects on my MCU. In all of these projects I use the printf statement which delivers the output to the console log window in the MCUXpresso IDE. Normally printf would be called in functions defined outside of main and I never had any issues up until now with the current project I am working on. 

It is a kind of bizarre problem, if I call printf inside of main then I can see in the output in the console window, otherwise if printf is called outside of main, then I see no output. 

I tried searching the forum for similar problems, but I only found similar issues that pertained to the Kinetis Design Studio IDE. As anyone run into a similar issue like this for the MCUXpresso?

Any help is greatly appreciated! 

Tags (2)
10 Replies

469 Views
Contributor III

Is there any particular way to determine how much memory xTaskCreate() uses for each call or is that answer given by the stacksize you pass as a argument in the function call?

0 Kudos

469 Views
NXP Employee
NXP Employee

Yes, that's mostly given by the amount of stack you specify for the task size. Keep in myind that the number is in 'stack units' so for an ARM as 32bit machine for 1024 it it is 4x1024 bytes. In addition each task needs space for a TCB (Task Control Block).

You can see the task stacks in the Tasks view:

pastedImage_1.png

There is an article about FreeRTOS stacks here: Understanding FreeRTOS Task Stack Usage and Kernel Awareness Information | MCU on Eclipse 

In the Heap view you have the information about the memory allocated (if using dynamic memory):

pastedImage_3.png

I hope this helps,

Erich

469 Views
Contributor III

Upon more testing, I created three integer variables to store the returned value of each xTaskCreate() call and printed out their values. The first two tasks returned a value of 1 while the 3rd task returned a value of -1. I'm assuming that is an indication there was not enough heap memory to create the third task? I am using the Kinetis K65 which has 256KB SRAM.  

Here is an updated version of my project with the testing code included: 

#include <stdio.h>
#include "board.h"
#include "peripherals.h"
#include "pin_mux.h"
#include "clock_config.h"
#include "MK65F18.h"
#include "fsl_debug_console.h"
/* TODO: insert other include files here. */

#include <FreeRTOS.h>
#include "task.h"
#include "event_groups.h"

/* TODO: insert other definitions and declarations here. */

EventGroupHandle_t task_watchdog;

const uint32_t good_task_id = (1 << 0);  // 0x01
const uint32_t bad_task_id = (1 << 1);  //0x02
const uint32_t tasks_all_bits = (good_task_id | bad_task_id);  // 0x03


void good_task(void *p)
{
     while(1) {
          // Good task, so let's always set the event group
          xEventGroupSetBits(task_watchdog, good_task_id);
          vTaskDelay(1000);
     }
}


void bad_task(void *p)
{
     int x = 0;
     while(1) {
          ++x;
          if (x >= 3 && x <= 6) {
               // Stop setting the task bit at the task_watchdog event group
               continue;
          }
          else {
               xEventGroupSetBits(task_watchdog, bad_task_id);
          }

          vTaskDelay(1000);
     }
}


void sw_watchdog(void *p)
{


     while(1) {
          uint32_t result = xEventGroupWaitBits(task_watchdog, tasks_all_bits,
                    pdTRUE,   // Clear bits on exit
                    pdTRUE,  // Wait for all bits to be set
                    2000);

          if ((result & tasks_all_bits) == tasks_all_bits) {
               printf("System is healthy\n");
          }
          else {
               if ((result & good_task_id) != good_task_id) {
                    printf("Good task stopped responding\n");
               }
               if ((result & bad_task_id) != bad_task_id) {
                    printf("Bad task stopped responding\n");
               }
          }
     }
}


 /* @brief Application entry point.
 */

int main(void) {
       /* Init board hardware. */

     BOARD_InitBootPins();
    BOARD_InitBootClocks();
    BOARD_InitBootPeripherals();
       /* Init FSL debug console. */
     BOARD_InitDebugConsole();

     int firstTask, secondTask, thirdTask = 0;

     printf("%lu %lu %lu\n", good_task_id, bad_task_id, tasks_all_bits);

   task_watchdog = xEventGroupCreate();

   firstTask = xTaskCreate(sw_watchdog,"sw_watchdog", 1024, NULL, 2, NULL);
   secondTask = xTaskCreate(good_task, "good_task", 1024, NULL, 1, NULL);
   thirdTask = xTaskCreate(bad_task, "bad_task", 1024, NULL, 1, NULL);

   printf("The value of the first task is: %d\n", firstTask);
   printf("The value of the second task is: %d\n", secondTask);
   printf("The value of the third task is: %d\n", thirdTask);

   vTaskStartScheduler();

   return 0;

}
0 Kudos

469 Views
Contributor III

Hello,  @Alice_Yang and lpcxpresso_support

Over the weekend I was playing around my code and something interesting happened. Referring back to my code, there is 3 tasks that I created: good_task, bad_task, and sw_watchdog in that exact order. Now when I cut/past the sw_watchdog task creation above the other tasks, sw_watchdog function is called hence the printf statement inside that function is executed. 

In other words if I re-arranged the task creation in the following order: sw_watchdog, good_task, and bad_task, it is the bad_task function that is never called aka the project never runs "bad_task". If I re-arrange the task creation in the following order: sw_watchdog, bad_task, and good_task, it is the good_task function that is never called, etc. 

So for some bizarre reason the project is not executing the third task. In other words, the printf statements for the functions that are called in the first two created tasks, are executed. 

0 Kudos

469 Views
NXP Employee
NXP Employee

So thinking about this some more, if all you want to do is print a const status string out to the IDE's semihosting console, you could actually just call the underlying Redlib semihosting operation directly using something like the following:

#include <string.h>

int __sys_write (int, char *, int);

int consoleprint(char *cpstring) {

  int slen, res;

  // Calculate length of string

  slen = strlen (cpstring);

  // Call function to carry out semihosting "SYS_WRITE" operation

  res = __sys_write (1, cpstring,slen); // Note that '1' represents stdout

  return res;

}

void foo (void) {

    consoleprint ("**** Foo status message\n");

}

Remember that semihosting is blocking whilst the message is transferred though. You will also need to make sure that you are linking against a semihost variant of the Redlib C library.

Regards,

MCUXpresso IDE Support

0 Kudos

469 Views
NXP Employee
NXP Employee

printf inside a task is generally a bad idea (there are quite a few posts about this on the FreeRTOS forums - just do an internet search for "FreeRTOS printf" or similar). And certainly the Redlib printf is not thread safe - so if you get a task switch in the middle of a printf operation - things are very likely to go wrong.

Regards,

MCUXpresso IDE Support

0 Kudos

469 Views
NXP Employee
NXP Employee

As Alice says, knowing the MCU you are using would be helpful.

But the most likely reason I can think of for this is that the print's that are working are direct calls to the C library "printf" function. And those that appear not to be working are using the SDK's "PRINTF" macro - which your project is configured to redirect to the UART debug console rather than to the IDE"s semihosting console.

If this is the case, then the easiest way to reconfigured an existing project so that "PRINTF" macro directs to the C library "printf' function is to select the project in the Project Explorer view, then use:

Quickstart Panel -> Quick Settings -> SDK Debug Console -> Semihost console

For more information, please see the MCUXpresso IDE v10.2 User Guide, section 15.5.5, "Printf when using SDK".

Regards,

MCUXpresso IDE Support

0 Kudos

469 Views
Contributor III

I am using the Kinetis K65 MCU. 

Here is the code (which I got from youtube) that I'm trying to run. It is an example on using event groups with a software watchdog.

I noticed printf calls works in good_task and bad_task functions, but not in the sw_watchdog function. That is the only function I can't get printf to work normally.

I also tried your suggestion: Quickstart Panel -> Quick Settings  -> SDK debug console -> Semihost console , but to no avail (I also made sure the Event_Groups project was selected before trying the above approach). 

/**
 * @file    K65_FreeRTOS_Demo_Event_Groups.cpp
 * @brief   Application entry point.
 */
#include <stdio.h>
#include "board.h"
#include "peripherals.h"
#include "pin_mux.h"
#include "clock_config.h"
#include "MK65F18.h"
#include "fsl_debug_console.h"
/* TODO: insert other include files here. */

#include <FreeRTOS.h>
#include "task.h"
#include "event_groups.h"

/* TODO: insert other definitions and declarations here. */

EventGroupHandle_t task_watchdog;

const uint32_t good_task_id = (1 << 0);  // 0x01
const uint32_t bad_task_id = (1 << 1);  //0x02
const uint32_t tasks_all_bits = (good_task_id | bad_task_id);  // 0x03


void good_task(void *p)
{
     while(1) {
          // Good task, so let's always set the event group
          xEventGroupSetBits(task_watchdog, good_task_id);
          vTaskDelay(1000);
     }
}


void bad_task(void *p)
{
     int x = 0;
     while(1) {
          ++x;
          if (x >= 3 && x <= 6) {
                  // Stop setting the task bit at the task_watchdog event group
          }
          else {
               xEventGroupSetBits(task_watchdog, bad_task_id);
          }

          vTaskDelay(1000);
     }
}


void sw_watchdog(void *p)
{
     printf("hello\n");

     while(1) {
          uint32_t result = xEventGroupWaitBits(task_watchdog, tasks_all_bits,
                    pdTRUE,   // Clear bits on exit
                    pdTRUE,  // Wait for all bits to be set
                    2000);

          if ((result & tasks_all_bits) == tasks_all_bits) {
               printf("System is healthy\n");
          }
          else {
               if (!(result & good_task_id)) {
                    printf("Good task stopped responding\n");
               }
               if (!(result & bad_task_id)) {
                    printf("Bad task stopped responding\n");
               }
          }
     }
}


 /* @brief Application entry point.
 */

int main(void) {
       /* Init board hardware. */

    BOARD_InitBootPins();
    BOARD_InitBootClocks();
    BOARD_InitBootPeripherals();
       /* Init FSL debug console. */
     BOARD_InitDebugConsole();

     printf("%u %u %u\n", good_task_id, bad_task_id, tasks_all_bits);

   task_watchdog = xEventGroupCreate();

   xTaskCreate(good_task, "good_task", 1024, NULL, 1, NULL);
   xTaskCreate(bad_task, "bad_task", 1024, NULL, 1, NULL);
   xTaskCreate(sw_watchdog,"sw_watchdog", 1024, NULL, 2, NULL);

   vTaskStartScheduler();

   return 0;

}
0 Kudos

469 Views
NXP TechSupport
NXP TechSupport

Hello   Joseph Jean-Jacques,

It seems your project haven't run into the task of  "sw_watchdog", what about on your side?

Set a breakpoint on it to have a test . After delete the other tasks , only leave "sw_watchdog"(to make sure run into this task), the printf can print "hello" on Console view :

pastedImage_1.png


Have a great day,
TIC

-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

0 Kudos

469 Views
NXP TechSupport
NXP TechSupport

Hello Joseph Jean-Jacques ,

Could you please tell us the chip you used , and your project ,

then we can reproduce your issue .

BR

Alice

0 Kudos