Are the Redlib versions of getchar() getc() and fgetc() casting EOF to a char by mistake?

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Are the Redlib versions of getchar() getc() and fgetc() casting EOF to a char by mistake?

945 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by Appcon on Fri May 09 13:08:40 MST 2014
I am seeing unexpected values for EOF from Redlib "get" functions. I expect standard io "get" functions to return a 32-bit integer value.  I expect EOF to be the 32-bit twos complement representation for -1 (0xFFFFFFFF). My test app (below and attached) compares the return values of the standard lib "get" functions to the value returned by the low-level Board_UARTGetChar() function:

#include "stdio.h"
#include "string.h"
#include "chip.h"
#include "board.h"


static void UART_Init(void)
{
    /* Setup UART for 115200-8-N-1 */
    Chip_UART_Init(LPC_USART0);
    Chip_UART_SetBaud(LPC_USART0, 115200);
    Chip_UART_ConfigData(LPC_USART0, (UART_LCR_WLEN8 | UART_LCR_SBS_1BIT));
    Chip_UART_SetupFIFOS(LPC_USART0, (UART_FCR_FIFO_EN | UART_FCR_TRG_LEV2));
    Chip_UART_TXEnable(LPC_USART0);

    /* Reset USART FIFO and set trigger level 3 (14 chars) */
    Chip_UART_SetupFIFOS(LPC_USART0, (UART_FCR_FIFO_EN | UART_FCR_RX_RS | UART_FCR_TX_RS | UART_FCR_TRG_LEV3));
}


void EOF_Test(void)
{
    puts("\r\n-------- EOF Test --------\r");
    printf("                EOF = 0x%08X\r\n", EOF);
    printf("          getchar() = 0x%08X\r\n", getchar());
    printf("        getc(stdin) = 0x%08X\r\n", getc(stdin));
    printf("       fgetc(stdin) = 0x%08X\r\n", fgetc(stdin));
    printf("Board_UARTGetChar() = 0x%08X\r\n", Board_UARTGetChar());
}


int main(void)
{
    /* Init hardware drivers */
    SystemCoreClockUpdate();
    Board_Init();
    Board_UART_Init(LPC_USART0);
    Board_LED_Set(0, false);
    UART_Init();

    EOF_Test();

    /* DeInitialize UART0 peripheral */
    NVIC_DisableIRQ(USART0_IRQn);
    Chip_UART_DeInit(LPC_USART0);

    return 1;
}



The above code produced the following on UART0:


-------- EOF Test --------
                EOF = 0xFFFFFFFF
          getchar() = 0x000000FF
        getc(stdin) = 0x000000FF
       fgetc(stdin) = 0x000000FF
Board_UARTGetChar() = 0xFFFFFFFF



It appears the "get" functions cast EOF to a char. The low-level UART function acts as expected.

Can anyone confirm or deny this behavior? Is this as expected?

I am building for the NGX LPC1837 Evaluation Board with the following definitions:
_REDLIB_
_CODE_RED_
_USE_LPCOPEN_
CORE_M3


I am linking with the Redlib(nohost) option.

Any help or redirection is appreciated.

Thanks,
Sean

Original Attachment has been moved to: eof_3.zip

Labels (1)
0 Kudos
4 Replies

732 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by Appcon on Mon May 12 11:22:30 MST 2014
I have no problem avoiding stdio overhead and just using the UART functions directly. (I could also use newlib if needed, we are not constrained on flash.)
Thanks for finding the root cause though!

Sean


0 Kudos

731 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by lpcxpresso-support on Mon May 12 02:55:59 MST 2014

Quote: jonper
I get the same results on a Keil MCB4357, and also tried LPCXpresso Support's retarget.h workaround but it made no difference.



I've tested this on hardware this morning, and agree that my previous suggestion doesn't actually help.

I've now examined what Redlib is doing here, and unfortunately there is a built-in assumption within the interfaces between the high level file/stream handling code and the low level (semihosting) layers that reading a character from stdin will always work and that there isn't an end of file as such. Changing this would be a sizeable job, and given that this area of Redlib has been like this since our first tools release (~8 years ago) I am not sure that this is something we would actually want to do.

To be honest, if you want to read characters over the UART, I would generally recommend using the UART functions directly, rather than using retargeted standard C library functions anyway (should give a noticeable code size reduction).


Quote: jonper

If you search the forums for fsigned you will find that both GCC Arm and Redlib default to char being unsigned which appears to be the root problem, and that LPCXpresso Support is looking into this for a future release.


This is absolutely nothing to do with this issue. Also as noted in the release notes, Redlib's limits.h was updated in LPCXpresso 7.1.0 to cope with signed vs unsigned chars.

Regards,
LPCXpresso Support
0 Kudos

732 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by jonper on Sat May 10 15:41:19 MST 2014
I get the same results on a Keil MCB4357, and also tried LPCXpresso Support's retarget.h workaround but it made no difference.

If the getc macro in Redlib's stdio.h and the __FILE_struct in sys/libconfig-arm.h are valid predictors of the library handling, then regardless of what READFUNC returns to the buffered IO code in Redlib, it seems it will be reverted to unsigned char before returning to the calling xxgetcxx as 0xFF.

If you search the forums for fsigned you will find that both GCC Arm and Redlib default to char being unsigned which appears to be the root problem, and that LPCXpresso Support is looking into this for a future release.

If it's imperative to have a simple ==EOF test for legacy code, company policy, or just aesthetics, you could look at Newlib as an alternate library. A quick test on the MCB4357 with your test code gave the all 0xFFFFFFFF (EOF) results expected with NewlibNano(nohost).

Good luck.
0 Kudos

732 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by lpcxpresso-support on Sat May 10 07:39:00 MST 2014
If you are using the Redlib(nohost), then presumably you are retargeting the IO functions onto your UART, and I suspect that this is where the problem is.

Your project looks like it is linking with the  LPCOpen code for the NGX LPC1830 board. Looking in retarget.h inside the library project lpc_board_ngx_xplorer_1830, you will find:

int READFUNC(void)
{
#if defined(DEBUG_ENABLE)
char c = Board_UARTGetChar();
return (int) c;

#else
return (int) -1;
#endif
}


I don't have the necessary hardware with me to test, but I imagine that if you change the definition of the local c from 'char' to 'int', you will get the behaviour you are looking for.

Regards,
LPCXpresso Support
0 Kudos