Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add method Print.printf(). Fixed & tested. #592

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
80 changes: 64 additions & 16 deletions STM32F1/cores/maple/Print.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -208,24 +208,72 @@ size_t Print::println(const Printable& x)
return n;
}

#ifdef SUPPORTS_PRINTF

//#ifdef SUPPORTS_PRINTF
//Note: ifdef not need - not used printf is not linked

// method uses the GLIBS extension fopencookie (), which works on the platforms STM32, SAMD, ESP8266, Linux ..
// And work with any devices: Serial, TFT, Flash &etc.
//( For avr-libc, a similar functional is implemented through specific properties of type FILE, without any functions.)

#define _GNU_SOURCE
#include <stdio.h>
#include <stdarg.h>
// Work in progress to support printf.
// Need to implement stream FILE to write individual chars to chosen serial port
int Print::printf (__const char *__restrict __format, ...)
{
FILE *__restrict __stream;
int ret_status = 0;


va_list args;
va_start(args,__format);
ret_status = vfprintf(__stream, __format, args);
va_end(args);
return ret_status;
}
#endif

/*
//Bug detected
//failed: fopencookie( 0, "w+", { NULL, WR_fn, NULL, NULL })
//failed: fopencookie( 0, "rw+", { NULL, WR_fn, NULL, NULL })
//
//worked: fopencookie( 0, "rw+", { RD_fn, WR_fn, NULL, NULL })
//worked: fopencookie( 0, "rw+", { NULL, WR_fn, NULL, NULL })
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Line 229 (worked) seems to be identical to line 226, which failed.
Btw, do we really need this comment block? I would remove it.
The solution matters, which is implemented below.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So basically this PR doesn't work unless some lines are uncommitted ???

Copy link
Author

@u48 u48 Feb 25, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Block comments should be removed. :)

The GLIBC documentation says that when fopencookie() is called, pointers to BOTH the write() and read() functions must be passed.

That is, if reading is not required, a valid pointer to a dummy function should be passed, and not NULL. Otherwise it does not work.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I understand the reason, I just asked to remove unneeded comment block (which includes contradictory information).

//
//Resume: To fix - you should always specify the cookies_read function, zero is not valid.
*/


// Read/Write blocks to device.
// Non class function for use from libc.printf,
// pointer to class Print passed in argumwent dev.
static ssize_t cookie_read_helper(void *dev __attribute__((unused)) , const char* buff __attribute__((unused)) ,
size_t len __attribute__((unused)) )
{
return 0;
}

static ssize_t cookie_write_helper(void *dev, const char* buff, size_t size)
{
Print* pPrint=(Print*)dev;
ssize_t len=0;
for(char* c = (char*)buff; size-- >0; len++) pPrint->print(*c++);
return len;
}


size_t Print::printf(const char *format, ...)
{
FILE* stream = fopencookie( (void*) this, "rw+", (cookie_io_functions_t) {
(cookie_read_function_t* ) cookie_read_helper,
(cookie_write_function_t*) cookie_write_helper,
(cookie_seek_function_t* ) NULL,
(cookie_close_function_t*) NULL
} );
if(!stream){ print("\nERROR:opencookie - failed\n"); return 0; } // for dbg only

setvbuf(stream, NULL, _IONBF, 0); //turn off buffer
//(Note: Buffer from stdlib need only for multithread code,
// and not alternative for uart buffers and fifo.)

va_list args;
va_start(args,format);
int ret_status = vfprintf(stream, format, args);
va_end(args);
fclose(stream);

return ret_status>0 ? (size_t)ret_status : 0;
}
// #endif


/*
* Private methods
Expand Down
7 changes: 3 additions & 4 deletions STM32F1/cores/maple/Print.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,10 +67,9 @@ class Print {
size_t println(double, int=2);
size_t println(const __FlashStringHelper *);
size_t println(const Printable&);
#ifdef SUPPORTS_PRINTF
// Roger Clark. Work in progress to add printf support
int printf(const char * format, ...);
#endif

size_t printf(const char * format, ...);

Print() : write_error(0) {}

int getWriteError() { return write_error; }
Expand Down