Console input with Processor Expert on FRDM-KLxx

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

Console input with Processor Expert on FRDM-KLxx

Jump to solution
4,875 Views
charlespalmer
Contributor I

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().

Labels (1)
Tags (2)
0 Kudos
1 Solution
2,965 Views
chris_brown
NXP Employee
NXP Employee

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 

View solution in original post

0 Kudos
12 Replies
1,390 Views
ErichStyger
Senior Contributor V

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).

0 Kudos
2,965 Views
jeffersonfpalhe
Contributor I

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.
};

0 Kudos
2,965 Views
charlespalmer
Contributor I

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.

0 Kudos
2,965 Views
matthews
Contributor II

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!

0 Kudos
2,965 Views
matthews
Contributor II

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);

}

0 Kudos
2,965 Views
charlespalmer
Contributor I

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.

0 Kudos
2,966 Views
chris_brown
NXP Employee
NXP Employee

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 

0 Kudos
2,614 Views
JSunil
Contributor I

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?

0 Kudos
2,598 Views
ErichStyger
Senior Contributor V

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).

0 Kudos
2,586 Views
ErichStyger
Senior Contributor V

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?

0 Kudos
2,965 Views
BlackNight
NXP Employee
NXP Employee

I use it with gets(), see

mcuoneclipse/Examples/FRDM-KL25Z/FRDM-KL25Z_printf/Sources at master · ErichStyger/mcuoneclipse · Gi...

Just keep in mind that gets() reads/blocks until there is a \n

0 Kudos
2,965 Views
ZhangJennie
NXP TechSupport
NXP TechSupport

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?

0 Kudos