There are plenty of working examples of using printf() for console output with FRDM-KL25Z etc. But I have not managed to find a working example of console input. The following code appears to block at the getchar() call.
printf("Console output works\n");
char c=getchar();
printf("But this line is never executed.\n");
printf("I would like to process incoming character %c.\n", c);
What do I need to do? I am using a Processor Expert ConsoleIO component, which I assume is responsible for the functioning printf().
Solved! Go to Solution.
Hi Charles,
By default, CodeWarrior is setup to use a buffered behavior for the standard I/O functions (i.e., printf, gets, etc.). You can turn that off using this command: setvbuf(stdout, NULL, _IONBF, 0);
The KL25_SC code package has an example of this in the helloworld project (in the Processor Expert code).
Hope this helps,
Chris
I managed to use semihosting directly, see https://mcuoneclipse.com/2023/03/09/using-semihosting-the-direct-way/
The example project used in that article uses both stdout and stdin, and works nicely and efficient (still keep in mind that semihosting stops the target).
You need two terminals opened in linux. One to send data and other to receive and see the data on serial port from computer. I was using minicom to read the serial port and I had anything. So I looked in the minicom serial port setup and changed the Hardware Flow Control to No. After that I can see the string or character that I send from computer serial port according the following:
Read whole string from embedded serial port
char str[10]; //string length
scanf("%s", str);
printf("the str is : %s\n", str); //print the string on serial port
Read char from embedded serial port
char character[1];
scanf("%c", character);
printf("the character is : %c\n",character[0]); //print the string on serial port
To send data from linux terminal to embedded serial port (as root):
echo -e string > /dev/ttyUSB0
check your serial file in /dev (it can be ttyUSB0, ttyUSB1, ttyUSB2... just check if there is anyone like that).
I'm using:
- Processor Expert on Kinetis Design (eclipse)
- Arm7 (mk22fx512xx)
- Console IO component (in the processor expert)
Serial on loop
You can receive the same data that you send in your embedded system to test the serial port, for examplo, and see in debug if it is working. You just need to change the loop while from the _read method in the CsIO1.c founded in Generated_Code from your project (automatically generated by console component).
in
while ((UART_PDD_ReadInterruptStatusReg(UART0_BASE_PTR) & UART_S1_RDRF_MASK) == 0x00) {};
do that:
while ((UART_PDD_ReadInterruptStatusReg(UART0_BASE_PTR) & UART_S1_RDRF_MASK) == 0x00) {
printf("%s", str); //or printf("%c", character[0]') put the data according the code above.
};
Thanks Chris, that fixed it! Both for the scanf() and getchar() in stdin and printf() on stdout (which no longer waits for a newline). I added this code:
setvbuf(stdout, NULL, _IONBF, 0); // no buffering on stdout - for printf()
setvbuf(stdin, NULL, _IONBF, 0); // no buffering on stdin - for getchar() etc
Interestingly, gets(incomingString) does not work, whereas fgets(incomingString, 5, stdin) does work. But getchar() and scanf() are sufficient for me.
For some reason this doesn't work for me. I've added the call to setvbuf(stdin, NULL, _IONBF, 0); but getchar(), scanf() and gets(buf, size, stdin) all continue to block. I even tried recompiling the EWL C Library with #define _EWL_BUFFERED_CONSOLE 0. setvbuf doesn't return an error value. I am running CW 10.4 with the Freedom K25 board. I'm not sure why this isn't working!
All of the underlying stdin reads come down to the following function provided by the CW Processor Expert (see below). In this function it is blocking on the while /* Wait until a char is received */. I replaced the while loop with a break; and I am able to use stdin reads of 1 char at a time. I'm not sure how to instruct the processor expert to generate the function as nonblocking.
/*
** ===================================================================
** Method : CsIO1___read_console (component ConsoleIO)
**
** Description :
** __read_console
** This method is internal. It is used by Processor Expert only.
** ===================================================================
*/
int __read_console(__file_handle handle, unsigned char* buffer, size_t * count)
{
size_t CharCnt = 0x00;
(void)handle; /* Parameter is not used, suppress unused argument warning */
for (;*count > 0x00; --*count) {
/* Clear error flags */
UART0_PDD_ClearInterruptFlags(UART0_BASE_PTR,0x1FU);
if ((UART0_PDD_ReadInterruptStatusReg(UART0_BASE_PTR) & UART0_S1_RDRF_MASK) == 0x00) { /* Any data in receiver buffer */
// MWS 10-11-2013 -- if no data is here, simply return instead of blocking on data
break;
if (CharCnt != 0x00) { /* No, at least one char received? */
break; /* Yes, return received char(s) */
} else { /* Wait until a char is received */
while ((UART0_PDD_ReadInterruptStatusReg(UART0_BASE_PTR) & UART0_S1_RDRF_MASK) == 0x00) {};
}
}
CharCnt++; /* Increase char counter */
/* Save character received by UARTx device into the receive buffer */
*buffer = (unsigned char)UART0_PDD_GetChar8(UART0_BASE_PTR);
/* Stop reading if CR (Ox0D) character is received */
if (*buffer == 0x0DU) { /* New line character (CR) received ? */
*buffer = '\n'; /* Yes, convert LF to '\n' char. */
break; /* Stop loop and return received char(s) */
}
buffer++; /* Increase buffer pointer */
}
*count = CharCnt;
return (__no_io_error);
}
I have tried scanf(), gets(), fgets() and getchar() all with the same result: I get no console output until I have typed 64 characters. Then the for loop executes several times in quick succession, printing the strings (delimited by newline) that I have typed. Then it will sit, apparently unresponsive, until I have typed another 64 characters, at which point it will print the strings in the buffer. Code follows.
char incomingString[256];
printf("Type some characters, please.\n");
for(;;){
//gets(incomingString);
//fgets(incomingString, 5, stdin);
scanf("%s",incomingString);
printf("Received: %s\n",incomingString);
}
The question is why do these routines not return strings immediately, and how do I make them behave normally? I am using an FRDM-KL25Z with Processor Expert, having installed the CPU and ConsoleIO components. Is this some interrupt issue? In the Component Inspector for the Console I/O, the Interrupt service/event property is set to disabled and is greyed out.
Perhaps a related issue: the printf() will not send characters until a newline has been printed.
Hi Charles,
By default, CodeWarrior is setup to use a buffered behavior for the standard I/O functions (i.e., printf, gets, etc.). You can turn that off using this command: setvbuf(stdout, NULL, _IONBF, 0);
The KL25_SC code package has an example of this in the helloworld project (in the Processor Expert code).
Hope this helps,
Chris
Hello @chris_brown , @BlackNight @ZhangJennie
I am using the FRDM-K22F board and I have been facing the same issue. I am trying to read a character from the console terminal using the getchar() function. However, the setvbuf() function call did not seem to work in my case. Is there any workaround for this?
Does it work if you type in more characters?
Keep in mind that the implementation and especially semihosting depends on the debug firmware used (e.g. Segger vs. P&E vs. CMSIS-DAP).
Update: I did some digging (FRDM-K22F, MCUXpresso SDK and IDE), and for me semihosting with getc() and getchar() is not working (tried with newlib and J-Link). But I managed to get it working with native semihosting calls. So to me there are missing calls in the newlib, or it is broken if it ever worked. Normal printf() works.
So if you really need getc(), you probable should do the same as I do, with using direct system calls?
I use it with gets(), see
Just keep in mind that gets() reads/blocks until there is a \n
I ever use scanf with K60 without RTOS it works well. so i think it should also work with Kinetis L. can you please try it?