How do I open an interactive terminal to run Hifive1 Rev B programs?

I am running a program that asks a user for their names and prints them out onto the screen on a Hifive1 Rev B. The terminals provided to debug the programs in FreedomStudio don’t appear to have a way to interact with the program. As a result, when input is asked for, garbage is printed on the screen as opposed to the input the program was supposed to ask for. Is there a way to run the programs so the program actually asks the user for input?

You can use a terminal program such as GNU “screen” or minicom on Linux/Mac or PuTTY on Windows.

1 Like

I tried that. The program does not appear to accept input from the keyboard. The first piece of code I tried was this:

#include <stdio.h>
int main()
{
char chr;
printf(“Enter a character: “);
scanf(”%c”,&chr);
printf(“You entered %c.”, chr);
return 0;
}

and the program would not even stop for input and would print out “Enter a character. You entered .”
I tried clearing the buffer like this

#include <stdio.h>
int main()
{
setbuf(stdout, NULL);
char chr;
printf(“Enter a character: “);
scanf(”%c”,&chr);
printf(“You entered %c.”, chr);
return 0;
}
and now in both terminals, the program only prints out EY. Is the hifive just incapable of accepting user input? I genuinely want to know.

I’m not ver familiar with the HiFive1 Rev B, and have never used FreedomStudio, but the “led_fade” example program in the v1_0 branch of freedom-e-sdk inputs a character from the UART by accessing registers directly.

I expect the hardware ability is probably there on the Rev B also, but the UART has been generally used for logging, not interaction.

1 Like

This code did not work. I tried modifying it, but I don’t really have time to mess around with it right now. Thanks for trying to help. In other news, I actually did find code on this website that accepted user input. However, it requires accessing registers directly and the input shows up only after you’ve entered it in and pressed the spacebar or enter key a bunch of times. It really is interesting.

#include <stdio.h>
#include <string.h>
#include <metal/machine/platform.h>

int main(int argc, char **argv) {
uint32_t i = 0;
uint32_t *reg;

char buffer[50];

printf("uart-test start\n");

reg = (uint32_t *)(METAL_SIFIVE_UART0_0_BASE_ADDRESS + METAL_SIFIVE_UART0_TXCTRL);
printf("reg txctrl: %x, %p\n", *reg, reg);
reg = (uint32_t *)(METAL_SIFIVE_UART0_0_BASE_ADDRESS + METAL_SIFIVE_UART0_RXCTRL);
printf("reg rxctrl: %x, %p\n", *reg, reg);

while (1){
  for (i = 0; i < sizeof(buffer); i++){
    reg = (uint32_t *)(METAL_SIFIVE_UART0_0_BASE_ADDRESS + METAL_SIFIVE_UART0_RXDATA);
    if (!(*reg & (1<<31))){
      buffer[i] = (char)((*reg) & 0xff);
    } else {
      buffer[i] = 0x00;
      break;
    }
  }
  for (i = 0; buffer[i] != 0x00; i++) {
    printf("ret: %c (%x)\n", buffer[i], buffer[i]);
  }
}
memset(buffer, 0x00, sizeof(buffer));

return 0;

}

I’ve really been wanting to port a BASIC or LISP interpreter to the hifive1 rev b. That’s why I wanted this to work so badly. However, on sifive’s github, there is a program called uart-test. Whenever I copy and paste the following main code into the main c file

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>

static char buffer[50];
static int int_buffer;

/* Test for simple output functions */
static void simple_out(void) {
const char one_by_one = “short msg”;
for (int i = 0; i < strlen(one_by_one); i++) {
putchar(one_by_one[i]);
putchar(’\n’);
}
puts(“Print a simple string”);
fputs(“This string is printed to stdout\n”, stdout);
fprintf(stdout, “This formatted string is printed to %s\n”, “stdout”);
printf(“This formatted string is printed using %s\n”, “printf()”);
}

/* Test for simple input functions */
static void simple_in(void) {
puts(“Please input a character:”);
fprintf(stdout, “Your input is a ‘%c’\n”, getchar());
getchar();
puts(“Please input a string:”);
fgets(buffer, 20, stdin);
fprintf(stdout, “The input string using fgets is %s\n”, buffer);
puts(“Please input a string:”);
scanf("%s", buffer);
fprintf(stdout, “The input string using scanf() is %s\n”, buffer);
puts(“Please input an int:”);
scanf("%d", &int_buffer);
fprintf(stdout, “The input integer using scanf() is %d\n”, int_buffer);
}

int main(int argc, char **argv) {
int i = 0;
simple_out();
simple_in();
return 0;
}
,build it, and run it, the scanf and fgets(input functions) are skipped. Since this is on Sifive’s github at

I assume someone got it to work. Does it work with Hifive1 Rev b? Is there a way to get it to work with hifive1 rev b?

This code is wrong.

The variable reg should be volatile as every time you access it you get a new character from the 8 byte hardware input queue. It should be accessed only once in the above code and copied to a local variable.

With those changes it should work properly.

volatile uint32_t *reg = (volatile uint32_t *)(METAL_SIFIVE_UART0_0_BASE_ADDRESS + METAL_SIFIVE_UART0_RXDATA);
uint32_t regval = *reg;
if (!(regval & (1<<31))){
  buffer[i] = (char)((regval) & 0xff);
} else {
  buffer[i] = 0x00;
  break;
}

This code returns with a null-terminated buffer as soon as there are no waiting characters. Another option (often better) would be to keep looping and put real characters into the buffer until the buffer is full (minus space for the null), or maybe until a newline is received.

1 Like