I’m working with MKL02Z32 which has 4kB RAM. Printf or puts which are almost everywhere make a big problem. I removed them from my fork, but it is not good or nice solution.
If I miss something important around “printing issue” please correct me.
How others deal with this issue? (printf or puts usage like here, is not nessesary in real applications).
AFAIK there has been no work on a solution so far.
However, I thought about this the other day in the context of the function pointer discussion and would like to propose a "logging" API (maybe there is an issue for that as well somewhere) for `core`, which offers things like `log.info(...)` and `log.error(...)`.
Different logging modules can implement this API then, ranging from `printf` over file based logging to network messages.
And then there should also be a `(void) ...` implementation which suits production and ultra low memory needs.
In RIOT framework and application code use exclusively the macro LOG_INFO, LOG_DEBUG, ecc. ecc. so you have one more degree of freedom for easy including/stripping the tracing code from the binary.
Another advantage with the macro usage is obviously the possibility to change to another logging implementation in one place instead of modifying all source lines where log is instrumented.
I really focused to this problem, because I do not have target to duplicate code base only because here missing this “small” things
logging API is good idea, it can by nice to have possibilities implement logging to any output (stdout, file, net, etc.)
macros can have some limitation and can be problem in some cases, but it depend how we use it - I do not have problem with it, it is usual way in many other projects. After short look to source code, there is many places which use DEBUG macro (but more places with printf/puts, too).
if we use macros, there can be easy and fast way how to change logging function. Yes, this way can be dirty but switching between simple printf and “log.error” will be without impact to the resources (code size, mem usage and execution time - call the printf directly opposite call the printf inside logging subsystem).
if we use logging subsystem directly, then we will pay for bigger possibilities/flexibility, it has its price (cpu load, mem usage)
I more incline to use macros, but implement logging API too. Logging functions can be use as default macro value in big MCUs (or MPUs).
personally I think Macros might not be the best idea - one of the design principles of RIOT so far is to limit the use of Macros to the minimum. You can actually get the same results for the code below by using a plain API based approach:
implementation 2:
void log_info() {��� ��� /* this function will be optimized away… /
/ do nothing here */
}
Now when setting up your project, just tell the make file which of the implementations to use:
USEMODULE+=log_implementation1
or
USEMODULE+=log_implementation2
This soultion does not only scale better, but it is IMHO the cleaner approach.
Yes compiler do not optimize (remove out) empty function defined as is suggested.
But if RIOT does not want use macros, we can define empty function as static inline function in header and then will be removed by optimization.
Yes, we came to the same conclusion while driving to embedded world.
I've got the implementation and API specification ready as well and will open a PR later.