can't printf with ESP32-S2 ESP-IDF 5.1

PeteDD
Posts: 45
Joined: Sat Sep 24, 2022 5:22 pm

can't printf with ESP32-S2 ESP-IDF 5.1

Postby PeteDD » Sat Dec 09, 2023 12:20 am

Can't make it any simpler... can't get printf to work on ESP32-S2 with framework = espidf, arduino
This works with ESP32-S3 just fine.

Any clues???

platformio:

Code: Select all

[env:lolin_s2_mini]
platform = espressif32
board = lolin_s2_mini
framework = espidf, arduino
main.cpp:

Code: Select all

#include <Arduino.h>
#include <stdio.h>
#include "sdkconfig.h"

void setup()
{
printf("Hello World\n");
}

void loop()
{}

errors:

Code: Select all

In file included from C:/Users/peted/.platformio/packages/framework-arduinoespressif32-src-16f16f9b46f255eba682607449bb3231/cores/esp32/Arduino.h:196,
                 from C:/Users/peted/.platformio/packages/framework-arduinoespressif32-src-16f16f9b46f255eba682607449bb3231/cores/esp32/chip-debug-report.cpp:17:
C:/Users/peted/.platformio/packages/framework-arduinoespressif32-src-16f16f9b46f255eba682607449bb3231/cores/esp32/chip-debug-report.cpp: In function 'void printBeforeSetupInfo()':     
C:/Users/peted/.platformio/packages/framework-arduinoespressif32-src-16f16f9b46f255eba682607449bb3231/cores/esp32/HardwareSerial.h:360:16: error: 'USBSerial' was not declared in this scope; did you mean 'Serial'?
  360 | #define Serial USBSerial
      |                ^~~~~~~~~
C:/Users/peted/.platformio/packages/framework-arduinoespressif32-src-16f16f9b46f255eba682607449bb3231/cores/esp32/chip-debug-report.cpp:260:3: note: in expansion of macro 'Serial'     
  260 |   Serial.begin(0);

liaifat85
Posts: 200
Joined: Wed Dec 06, 2023 2:46 pm

Re: can't printf with ESP32-S2 ESP-IDF 5.1

Postby liaifat85 » Sat Dec 09, 2023 1:29 pm

As far as I know, printf will not work in Arduino frameworks. Rather it should be Serial.print()

Code: Select all

#include <Arduino.h>

void setup() {
  Serial.begin(115200);
  Serial.println("Hello, world!");
}

void loop() {
  // Your code here
}

PeteDD
Posts: 45
Joined: Sat Sep 24, 2022 5:22 pm

Re: can't printf with ESP32-S2 ESP-IDF 5.1

Postby PeteDD » Sat Dec 09, 2023 1:50 pm

As far as I know, printf will not work in Arduino frameworks.
That is not correct as I am able to use printf and ESP_LOG with other projects buildt boards other than ESP32-S2 lolin_S2_mini with the exact same code and in the Arduino mode.

In fact... not even the following absolutely minimal project will build without generating the same errors so the problem IS NOT just printf. The problem seems to be in HardwareSerial.h for the SES32-S2 lolin_S2_mini: (see the complete case here: https://github.com/espressif/esp-idf/issues/12763

Code: Select all

#include <Arduino.h>

void setup()
{}

void loop()
{}

Code: Select all

In file included from C:/Users/peted/.platformio/packages/framework-arduinoespressif32-src-16f16f9b46f255eba682607449bb3231/cores/esp32/Arduino.h:196,
                 from C:/Users/peted/.platformio/packages/framework-arduinoespressif32-src-16f16f9b46f255eba682607449bb3231/cores/esp32/chip-debug-report.cpp:17:
C:/Users/peted/.platformio/packages/framework-arduinoespressif32-src-16f16f9b46f255eba682607449bb3231/cores/esp32/chip-debug-report.cpp: In function 'void printBeforeSetupInfo()':     
C:/Users/peted/.platformio/packages/framework-arduinoespressif32-src-16f16f9b46f255eba682607449bb3231/cores/esp32/HardwareSerial.h:360:16: error: 'USBSerial' was not declared in this scope; did you mean 'Serial'?
  360 | #define Serial USBSerial
      |                ^~~~~~~~~
C:/Users/peted/.platformio/packages/framework-arduinoespressif32-src-16f16f9b46f255eba682607449bb3231/cores/esp32/chip-debug-report.cpp:260:3: note: in expansion of macro 'Serial'

mikemoy
Posts: 627
Joined: Fri Jan 12, 2018 9:10 pm

Re: can't printf with ESP32-S2 ESP-IDF 5.1

Postby mikemoy » Sun Dec 10, 2023 6:35 am

As far as I know, printf will not work in Arduino frameworks. Rather it should be Serial.print()
FYI, printf works just fine in Arduino.

Silderan
Posts: 1
Joined: Sun Feb 25, 2024 8:04 am

Re: can't printf with ESP32-S2 ESP-IDF 5.1

Postby Silderan » Sun Feb 25, 2024 10:21 am

Hello.

All your doubs are not ESP32 related but C/C++. So all explained here is for C and/or C++ compiling or code details.

Well, first things first:

Yes printf works fine in Arduino and ESP32, in all boards, or so I guess; printf is a C function that doesn't matter where you actually print.
But, it's a C function, so it spects char * type when %s format is used. String type or std::string are not a char *.
You can get the underliying char * by calling .c_str() on them. This way:
  1. #include <Arduino.h>
  2. void setup() {
  3.   Serial.begin(115200);
  4.   String str = "Hello, world!");
  5.   Serial.printf( "%s from ESP32!!", str.c_str() );
  6. }
  7.  
  8. void loop() {
  9.   // Your code here
  10. }
While using Serial.print or Serial.println, with String or str::string type, you actually call the perfect overloaded function so it works as intended.

Hey, you're not alone: takes me 2 months to realize that ;)

Wanna deep dig? continue reading, it will be harder, but interesting for many people (I hope) :

About returning static variables
Back in the 90', Microsoft Visual C++ 6.0, the first version at least, had an error while implementing return statement and returning local non basic variables in C++ doesn't work. I'll explain how return works in the end of the post.
But first, we need some basis. So, let me explain a bit.

- We can return a local int, don't we?
- Yes, of course.
  1. int giveMeANumber()
  2. {
  3.   int i = std::srand(1, 100);
  4.   return i;
  5. }
  6. void loop()
  7. {
  8.   Serial.printf( "Hey, that man gave me the number %d", giveMeANumber() );
  9.   delay(1000);
  10. }
- So, why not to return a string ?
- Who says that? Sure we can! here you have:
  1. #include <string>
  2.  
  3. std::string giveMeANumberAsString()
  4. {
  5.   std::string i = std::to_string( std::srand(1, 100) );
  6.   return i;
  7. }
  8. void loop()
  9. {
  10.   Serial.printf( "Hey, that man gave me the number %s", giveMeANumberAsString().c_str() );
  11.   delay(1000);
  12. }
So, as you can see, there is not any need to use static String variable to return it.
You need a static variable if you return its address, because non static variable address will become invalid after return.

- Great, but I like string to be a char *, can you?
- Nop!
- Hey man, why?

Short answer:
Because char * doesn't have an apropiate copy method, because it's neither a class nor struct nor a basic type; it's an array.

Long answer:
In C and C++, all basic variable types and structs (or classes) make a raw copy of themselfes while you do a simple assignement:
  1. typedef struct {
  2.  int a;
  3.  int b;
  4. }pair_t;
  5.    
  6. int setup()
  7. {
  8.     pair_t pair1;
  9.     pair1.a = 10;
  10.     pair1.b = 20;
  11.     pair_t pair2 = pair1;
  12.  
  13.     Serial.printf("pair1.a is %d, pair2.a is %d.\nAre de same? %s!\n", pair1.a, pair2.a, pair1.a == pair2.a ? "Yes" : "No");
  14.     Serial.printf("pair1.b is %d, pair2.b is %d.\nAre de same? %s!\n", pair1.b, pair2.b, pair1.b == pair2.b ? "Yes" : "No");
  15.  
  16.     return 0;
  17. }
For that reason, you cannot return and array. There is not that "apropiate raw copy". If you do an assignement, you only copy the basic type: the char * (the pointer value)
A raw copy of any variable type is just a memcpy. And a memcopy should be something like this:
  1. void memcpy( *target, *origin, size_t len)
  2. {
  3.   while( --len )
  4.     target[len] = origin[len];
  5. }
When we assign a char * to another char *, the compiler does that:
  1. char *a = "a";
  2. char *b = "b";
  3. a = b; // compiler makes: memcopy(&b, &a, sizeof(a));
&a gets the address of the adresss of the string ( char ** )
Sizeof(a) is the size of a char pointer, not the length of the string.

Now, what about return statement?
Well, return statement does many things and some non-intuitive if you don't think a little.
return statements are in the function scope. Meaning, inside function brakets. That may make you think that at return, the first think that compiler does is to destroy local variables.
But it's not that simple.
If return destroys local variables, the value in them should be not copied because... well.. they have been destroyed. At least, in C, unavailable because stack unwinds and the values are no longer reachable. In C++ it's worse, because of the class destructor that is called before stack unwind. So, in C++ there are more possibilities that class variables gets freed and even zeroed.
Actually, the first thing that returns does is to call the assignement or copy method of the class, if in the caller code there is an assignement, of course. After that, deletes the class (calling destructor) and unwinds the stack, and jumps program pointer back...

Take a look at this: https://onlinegdb.com/VOpyxgT-C

One last thing to think. I promise.
When I'd face this printf "issue", makes me blow my head because if the string were short, it worked:
  1. #include <Arduino.h>
  2. void setup() {
  3.   Serial.begin(115200);
  4.   String str = "A");
  5.   Serial.printf( "Give me an A: %s!!", str );
  6. }
  7.  
  8. void loop() {
  9.   // Your code here
  10. }
So, what the hell is going on?
I guess that it is a compiler optimization work. But not sure...
Remember that compiler is smarter than we. Than me at least. And when it find literals, could mute your code to do the same but optimized.
Compiler and other IA doen't understand fine the "intention".
I remember a friend of mine explaining me that he write a long for loop, just to slow down process.
Something like: for( int i = 0; i < 100000; ++i )
So far so good... but only in debug mode. When in relase, with optimizations activated, compiler just skipped this for loop.


Sorry for this long post!!!!

PeteDD
Posts: 45
Joined: Sat Sep 24, 2022 5:22 pm

Re: can't printf with ESP32-S2 ESP-IDF 5.1

Postby PeteDD » Wed Feb 28, 2024 3:41 pm

Missing the point altogether. Let me try again... For this ONE PROCESSOR, this functionality, being able to print equally with Serial.print(), ESP_LOG*, or printf(), does not work whereas it works for EVERY OTHER ESP family processor I have used, which are many.

Who is online

Users browsing this forum: No registered users and 68 guests