2021-08-12 01:57 PM
I have a STM32L4R5 STM32CubeIde project using FreeRTOS.
I have implemented _read(), _write() etc. to use UART for I/O.
printf() is working fine.
I can read characters from stdin using read(0, &mychar, 1) but getchar() does not work.
I've traced through getchar() execution and found that it is only calling _read() the first time it is called when it is doing a bunch of initialization.
On subsequent calls __sresill_r() is not calling _read().
I tried making stdin unbufferd by calling setvbuf(stdin, NULL, _IONBF, 0) before getchar(). Didn't change anything.
Any suggestions on how to fix this?
If not can I get the library source and project that builds it.
Randy
2021-08-14 10:47 PM
STMCubeIde uses newlib https://sourceware.org/git/newlib-cygwin.git. You may look at the implementation (newlib/libc), but I'm not aware of official patch+build instructions. How did you implement _read, what is the return value?
hth
KnarfB
2021-08-16 08:35 AM
Is ST using the latest newlib, 4.1.0? Have they done anything to port it to their processors?.
The uart driver called by _read() is pulling characters from a ring buffer. The ST HAL RX callback that places characters into the ring buffer.
If I use read(x,*char, 1) it works fine. Only having a problem with getchar().
Here is my _read() implementation:
int _read(int file, char *ptr, int len)
{
int uartRtn;
// check file for valid value
if ((file < 0) || (file >= ioNumHandles))
{ // bad handle
return BAD_FILE_ID;
}
// read from the uart
uartRtn = uartRead(ioHandleArray[file].hUart, (BYTE*) ptr, len);
if (file == 0)
{
STDINreads++;
}
return uartRtn;
}
And here is my uartRead implementation:
int uartRead(UART_HandleTypeDef *hUart, BYTE *buffer, int nbytes)
{
int numBytes = 0;
uartDrvStruct *drv = NULL;
// find the matching uart driver structure
drv = uartGetDrvStruct(hUart);
// bad handle
if (drv == NULL)
{
return UART_BAD_UART;
}
// Driver will not be Opened unless intialized
// Only check open state
if (drv->opened != TRUE)
{
return UART_NOT_OPEN;
}
// disable the uart interrupt
HAL_NVIC_DisableIRQ(drv->irq);
// get bytes from RX ring buffer
numBytes = rngBufGet(drv->rxRingBuf, buffer, nbytes);
// enable interrupt
HAL_NVIC_EnableIRQ(drv->irq);
if (hUart == &hDEBUGSIO)
{
DebugUartReads++;
}
return numBytes;
}
2021-08-16 09:04 AM
Is there a summary of changes for the newlib 4.1.0 shipped with new toolchain? What we need to know?
2021-08-16 09:10 AM
I plan on going through the newlib source for getchar() to determine why it on;y works on the 1st call.
Need to know if ST modified anything or provided port implementations that are called.
2021-08-16 10:03 AM
> Is ST using the latest newlib, 4.1.0?
No. There is a version file. On my STM32CubeIDE 1.7.0 (STM32CubeIDE\plugins\com.st.stm32cube.ide.mcu.externaltools.gnu-tools-for-stm32.9-2020-q2-update.win32_2.0.0.202105311346\tools\arm-none-eabi\include\_newlib_version.h), it says
#define _NEWLIB_VERSION "3.3.0"
> Have they done anything to port it to their processors?
Wish I knew where to look for that.
man getchar says: "return the character read as an unsigned char cast to an int or EOF on end of file or error." So, there is simply no third option returning "there is currently no character available". Think the issue is when your ring buffer is empty and you return 0 for numBytes. You could implement an additional chars_avail() function returning the momentary size of the read buffer.
hth
KnarfB