-
Notifications
You must be signed in to change notification settings - Fork 3k
Fixed IAR serial fgets fgetc #770
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
Conversation
I have a question if this workaround should not be placed somewhere else.. The toolchain specific things are currently in the retarget code file. |
Hi I think this is what you meant, if the name of the functions is inappropriate you can change them later. |
What problems are there with unbuffered streams? It might be beneficial for users, to have this as part of the commit, also the description provided above. For the next time ;) Or want to rebase? |
setbuf(_file, NULL), and std::setvbuf(_file,NULL,_IONBF,NULL) should both give an unbuffered stream (the data is directly written to the input buffer). IAR sets a buffer anyway of size 512 bytes for these calls. Calling setvbuff(_file,buf,_IONBF,NULL) with a buffer that is not a NULL pointer sets the buffer to size one. Which means that as soon as a char is read it is written to the real buffer. If people are interested in looking at this further they can look at the files under ARM/src/dlib: fgets.c, fflush.c, xfrpep.c and xfwprep.c |
Thanks for an explanation. Please provide it in the commit next time. I'll attach it to the merge commit |
Fix IAR serial fgets fgetc Taken from PR #770: setbuf(_file, NULL), and std::setvbuf(_file,NULL,_IONBF,NULL) should both give an unbuffered stream (the data is directly written to the input buffer). IAR sets a buffer anyway of size 512 bytes for these calls. Calling setvbuff(_file,buf,_IONBF,NULL) with a buffer that is not a NULL pointer sets the buffer to size one. Which means that as soon as a char is read it is written to the real buffer. If people are interested in looking at this further they can look at the files under ARM/src/dlib: fgets.c, fflush.c, xfrpep.c and xfwprep.c
According to the standard, a BUFSIZ sized buffer should be allocated even if setbuf is called with a NULL buffer. The fourth argument to setvbuf is also a size_t, so using a NULL there is semantically incorrect. setvbuf(fp, NULL, _IONBF, 0) will result in a size 1 buffer being used with IAR 8.20.2. I have not checked any older releases. See: |
That POSIX standard reads a bit weird, suggesting the size parameter is somehow significant if mode if _IONBF. The C standard is clearer, just saying
Note size not being specified in the latter case, as it shouldn't matter. So is the issue is that IAR allocates a size-byte buffer that it doesn't use/need because mode is _IONBF, or that it does actually perform buffering when mode is _IONBF and a size was given? |
On top of this - do we need to be manually calling setbuf anyway? The call was there in Stream as a workaround for libraries not checking whether a file is a terminal or not (also Stream not saying that it is a terminal). Does DLIB have a mechanism for us to tell it that an __opened file is a tty or not, so it can default buffering correctly? I can't see it. C library retargeting often has such a mechanism alongside open/read/write as the C standard does require that behaviour:
|
I don't see any mechanism similar to isatty() in Dlib, but will investigate it further. |
IAR's Dlib has some problems with unbuffered stream, however I found a workaround. setvbuf with these params generate a buffer with size 1.