cancel
Showing results for 
Search instead for 
Did you mean: 

getchar not working

RHerm.3
Associate III

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

5 REPLIES 5
KnarfB
Principal III

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

RHerm.3
Associate III

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;

}

Pavel A.
Evangelist III

Is there a summary of changes for the newlib 4.1.0 shipped with new toolchain? What we need to know?

RHerm.3
Associate III

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.

> 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