Added printf and use it thruout the firmware.

(Proof of concept, not yet final.)
This commit is contained in:
René Rebe 2020-01-13 21:49:05 +01:00
parent e308982e18
commit 71c33777e1
2 changed files with 161 additions and 155 deletions

View File

@ -40,7 +40,7 @@ hx8kdemo_sections.lds: sections.lds
$(CROSS)cpp -P -DHX8KDEMO -o $@ $^ $(CROSS)cpp -P -DHX8KDEMO -o $@ $^
hx8kdemo_fw.elf: hx8kdemo_sections.lds start.s firmware.c hx8kdemo_fw.elf: hx8kdemo_sections.lds start.s firmware.c
$(CROSS)gcc $(CFLAGS) -DHX8KDEMO -march=rv32imc -Wl,-Bstatic,-T,hx8kdemo_sections.lds,--strip-debug -ffreestanding -nostdlib -o hx8kdemo_fw.elf start.s firmware.c $(CROSS)gcc $(CFLAGS) -DHX8KDEMO -march=rv32imc -Wl,-Bstatic,-T,hx8kdemo_sections.lds,--strip-debug -ffreestanding -nostdlib -o hx8kdemo_fw.elf start.s firmware.c -lgcc
hx8kdemo_fw.hex: hx8kdemo_fw.elf hx8kdemo_fw.hex: hx8kdemo_fw.elf
$(CROSS)objcopy -O verilog hx8kdemo_fw.elf hx8kdemo_fw.hex $(CROSS)objcopy -O verilog hx8kdemo_fw.elf hx8kdemo_fw.hex
@ -86,7 +86,7 @@ icebreaker_sections.lds: sections.lds
$(CROSS)cpp -P -DICEBREAKER -o $@ $^ $(CROSS)cpp -P -DICEBREAKER -o $@ $^
icebreaker_fw.elf: icebreaker_sections.lds start.s firmware.c icebreaker_fw.elf: icebreaker_sections.lds start.s firmware.c
$(CROSS)gcc $(CFLAGS) -DICEBREAKER -march=rv32ic -Wl,-Bstatic,-T,icebreaker_sections.lds,--strip-debug -ffreestanding -nostdlib -o icebreaker_fw.elf start.s firmware.c $(CROSS)gcc $(CFLAGS) -DICEBREAKER -march=rv32ic -Wl,-Bstatic,-T,icebreaker_sections.lds,--strip-debug -ffreestanding -nostdlib -o icebreaker_fw.elf start.s firmware.c -lgcc
icebreaker_fw.hex: icebreaker_fw.elf icebreaker_fw.hex: icebreaker_fw.elf
$(CROSS)objcopy -O verilog icebreaker_fw.elf icebreaker_fw.hex $(CROSS)objcopy -O verilog icebreaker_fw.elf icebreaker_fw.hex

View File

@ -2,6 +2,7 @@
* PicoSoC - A simple example SoC using PicoRV32 * PicoSoC - A simple example SoC using PicoRV32
* *
* Copyright (C) 2017 Clifford Wolf <clifford@clifford.at> * Copyright (C) 2017 Clifford Wolf <clifford@clifford.at>
* Copyright (C) 2020 René Rebe <rene@exactcode.de>
* *
* Permission to use, copy, modify, and/or distribute this software for any * Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above * purpose with or without fee is hereby granted, provided that the above
@ -19,6 +20,7 @@
#include <stdint.h> #include <stdint.h>
#include <stdbool.h> #include <stdbool.h>
#include <stdarg.h>
#ifdef ICEBREAKER #ifdef ICEBREAKER
# define MEM_TOTAL 0x20000 /* 128 KB */ # define MEM_TOTAL 0x20000 /* 128 KB */
@ -157,8 +159,9 @@ void enable_flash_crm()
void putchar(char c) void putchar(char c)
{ {
if (c == '\n') if (c == '\n') {
putchar('\r'); reg_uart_data = '\r';
}
reg_uart_data = c; reg_uart_data = c;
} }
@ -168,53 +171,132 @@ void print(const char *p)
putchar(*(p++)); putchar(*(p++));
} }
void print_hex(uint32_t v, int digits) // 1st and early for debug prints, ...
{ int printf(const char* format, ...)
for (int i = 7; i >= 0; i--) { __attribute__ ((format (printf, 1, 2)));
char c = "0123456789abcdef"[(v >> (4*i)) & 15];
if (c == '0' && i >= digits) continue; int isdigit(int c) {
putchar(c); if (c >= '0' && c <= '9')
digits = i; return c;
} return 0;
} }
void print_dec(uint32_t v) int sprintf(char* out, const char* format, ...)
__attribute__ ((format (printf, 2, 3)));
int vsprintf(char* out, const char* format, va_list argp)
{ {
if (v >= 1000) { const char* _out = out;
print(">=1000"); char temp[23]; // temp. formating buffer
return; uint8_t tempi = sizeof(temp);
for (; *format; ++format) {
// TODO: >9 (single digit) format and precision!
// TODO: and support for more formats, ...
uint8_t precision = 0, width = 0, zeros = 0;
if (*format == '%') {
++format;
if (*format == '0') {
zeros = *format++;
}
if (isdigit(*format)) {
width = *format++ - '0';
}
if (format[0] == '.' && isdigit(format[1])) {
precision = format[1] - '0';
format += 2;
}
const char fmt = *format;
if (fmt == '%') {
*out++ = '%';
} else if (fmt == 'c') {
char char_to_print = va_arg(argp, int);
*out++ = char_to_print;
} else if (fmt == 's') {
char* str_to_print = va_arg(argp, char*);
while (*str_to_print) {
*out++ = *str_to_print++;
if (precision && --precision == 0) break;
}
} else if (fmt == 'd' || fmt == 'i') {
int int_to_print = va_arg(argp, int);
if (int_to_print < 0) {
*out++ = '-';
int_to_print = -int_to_print;
}
// format int
do {
int _ = int_to_print % 10;
temp[--tempi] = '0' + _;
int_to_print /= 10;
} while (int_to_print);
goto output;
} else if (fmt == 'u') {
unsigned int_to_print = va_arg(argp, unsigned);
// format unsigned
do {
int _ = int_to_print % 10;
temp[--tempi] = '0' + _;
int_to_print /= 10;
} while (int_to_print);
goto output;
} else if (fmt == 'x' || fmt == 'p' || fmt == 'X') {
unsigned hex_to_print = va_arg(argp, int);
// hex format int
do {
int _ = hex_to_print & 0xf;
if (_ > 9) _ += (fmt == 'X' ? 'A' : 'a') - '9' - 1;
temp[--tempi] = '0' + _;
hex_to_print >>= 4;
} while (hex_to_print);
goto output;
} else {
out += sprintf(out, "NIY: %%%c", fmt);
}
} else {
*out++ = *format;
}
continue;
output:
// copy to output buffer and implicitly reset tempi
if (width) {
const int w = sizeof(temp) - tempi;
for (int i = 0; i < width - w; ++i)
*out++ = zeros ? '0' : ' ';
}
for (; tempi < sizeof(temp); ++tempi)
*out++ = temp[tempi];
} }
if (v >= 900) { putchar('9'); v -= 900; } *out = 0;
else if (v >= 800) { putchar('8'); v -= 800; } return out - _out;
else if (v >= 700) { putchar('7'); v -= 700; } }
else if (v >= 600) { putchar('6'); v -= 600; }
else if (v >= 500) { putchar('5'); v -= 500; }
else if (v >= 400) { putchar('4'); v -= 400; }
else if (v >= 300) { putchar('3'); v -= 300; }
else if (v >= 200) { putchar('2'); v -= 200; }
else if (v >= 100) { putchar('1'); v -= 100; }
if (v >= 90) { putchar('9'); v -= 90; } int sprintf(char* text, const char* format, ...)
else if (v >= 80) { putchar('8'); v -= 80; } __attribute__ ((format (printf, 2, 3)));
else if (v >= 70) { putchar('7'); v -= 70; } int sprintf(char* text, const char* format, ...)
else if (v >= 60) { putchar('6'); v -= 60; } {
else if (v >= 50) { putchar('5'); v -= 50; } va_list argp, argp2;
else if (v >= 40) { putchar('4'); v -= 40; } va_start(argp, format);
else if (v >= 30) { putchar('3'); v -= 30; } va_copy(argp2, argp);
else if (v >= 20) { putchar('2'); v -= 20; } int ret = vsprintf(text, format, argp2);
else if (v >= 10) { putchar('1'); v -= 10; } va_end(argp2);
if (v >= 9) { putchar('9'); v -= 9; } return ret;
else if (v >= 8) { putchar('8'); v -= 8; } }
else if (v >= 7) { putchar('7'); v -= 7; }
else if (v >= 6) { putchar('6'); v -= 6; } int printf(const char* format, ...)
else if (v >= 5) { putchar('5'); v -= 5; } {
else if (v >= 4) { putchar('4'); v -= 4; } char text[120]; // TODO: dynamic!
else if (v >= 3) { putchar('3'); v -= 3; }
else if (v >= 2) { putchar('2'); v -= 2; } va_list argp, argp2;
else if (v >= 1) { putchar('1'); v -= 1; } va_start(argp, format);
else putchar('0'); va_copy(argp2, argp);
int ret = vsprintf(text, format, argp2);
va_end(argp2);
print(text);
return ret;
} }
char getchar_prompt(char *prompt) char getchar_prompt(char *prompt)
@ -253,28 +335,10 @@ char getchar()
void cmd_print_spi_state() void cmd_print_spi_state()
{ {
print("SPI State:\n"); print("SPI State:\n");
printf(" LATENCY %d\n", (reg_spictrl >> 16) & 15);
print(" LATENCY "); printf(" DDR %s\n", (reg_spictrl & (1 << 22)) != 0 ? "ON" : "OFF");
print_dec((reg_spictrl >> 16) & 15); printf(" QSPI %s\n", (reg_spictrl & (1 << 21)) != 0 ? "ON" : "OFF");
print("\n"); printf(" CRM %s\n", (reg_spictrl & (1 << 20)) != 0 ? "ON" : "OFF");
print(" DDR ");
if ((reg_spictrl & (1 << 22)) != 0)
print("ON\n");
else
print("OFF\n");
print(" QSPI ");
if ((reg_spictrl & (1 << 21)) != 0)
print("ON\n");
else
print("OFF\n");
print(" CRM ");
if ((reg_spictrl & (1 << 20)) != 0)
print("ON\n");
else
print("OFF\n");
} }
uint32_t xorshift32(uint32_t *state) uint32_t xorshift32(uint32_t *state)
@ -312,9 +376,7 @@ void cmd_memtest()
for (int word = 0; word < MEM_TOTAL / sizeof(int); word += stride) { for (int word = 0; word < MEM_TOTAL / sizeof(int); word += stride) {
if (*(base_word + word) != xorshift32(&state)) { if (*(base_word + word) != xorshift32(&state)) {
print(" ***FAILED WORD*** at "); printf(" ***FAILED WORD*** at %x\n", 4*word);
print_hex(4*word, 4);
print("\n");
return; return;
} }
} }
@ -329,9 +391,7 @@ void cmd_memtest()
for (int byte = 0; byte < 128; byte++) { for (int byte = 0; byte < 128; byte++) {
if (*(base_byte + byte) != (uint8_t) byte) { if (*(base_byte + byte) != (uint8_t) byte) {
print(" ***FAILED BYTE*** at "); printf(" ***FAILED BYTE*** at %x\n", byte);
print_hex(byte, 4);
print("\n");
return; return;
} }
} }
@ -347,8 +407,7 @@ void cmd_read_flash_id()
flashio(buffer, 17, 0); flashio(buffer, 17, 0);
for (int i = 1; i <= 16; i++) { for (int i = 1; i <= 16; i++) {
putchar(' '); printf(" %x", buffer[i]);
print_hex(buffer[i], 2);
} }
putchar('\n'); putchar('\n');
} }
@ -363,13 +422,7 @@ uint8_t cmd_read_flash_regs_print(uint32_t addr, const char *name)
uint8_t buffer[6] = {0x65, addr >> 16, addr >> 8, addr, 0, 0}; uint8_t buffer[6] = {0x65, addr >> 16, addr >> 8, addr, 0, 0};
flashio(buffer, 6, 0); flashio(buffer, 6, 0);
print("0x"); printf("0x%x &s 0x%x\n", addr, name, buffer[5]);
print_hex(addr, 6);
print(" ");
print(name);
print(" 0x");
print_hex(buffer[5], 2);
print("\n");
return buffer[5]; return buffer[5];
} }
@ -488,17 +541,9 @@ uint32_t cmd_benchmark(bool verbose, uint32_t *instns_p)
if (verbose) if (verbose)
{ {
print("Cycles: 0x"); printf("Cycles: 0x%x\n", cycles_end - cycles_begin);
print_hex(cycles_end - cycles_begin, 8); printf("Instns: 0x%x\n", instns_end - instns_begin);
putchar('\n'); printf("Chksum: 0x%x\n", x32);
print("Instns: 0x");
print_hex(instns_end - instns_begin, 8);
putchar('\n');
print("Chksum: 0x");
print_hex(x32, 8);
putchar('\n');
} }
if (instns_p) if (instns_p)
@ -516,97 +561,69 @@ void cmd_benchmark_all()
print("default "); print("default ");
reg_spictrl = (reg_spictrl & ~0x00700000) | 0x00000000; reg_spictrl = (reg_spictrl & ~0x00700000) | 0x00000000;
print(": "); printf(": %x\n", cmd_benchmark(false, &instns));
print_hex(cmd_benchmark(false, &instns), 8);
putchar('\n');
for (int i = 8; i > 0; i--) for (int i = 8; i > 0; i--)
{ {
print("dspi-"); printf("dspi-%d ", i);
print_dec(i); set_flash_latency(i);
print(" ");
set_flash_latency(i);
reg_spictrl = (reg_spictrl & ~0x00700000) | 0x00400000; reg_spictrl = (reg_spictrl & ~0x00700000) | 0x00400000;
print(": "); printf(": %x\n", cmd_benchmark(false, &instns));
print_hex(cmd_benchmark(false, &instns), 8);
putchar('\n');
} }
for (int i = 8; i > 0; i--) for (int i = 8; i > 0; i--)
{ {
print("dspi-crm-"); printf("dspi-crm-%d ", i);;
print_dec(i);
print(" ");
set_flash_latency(i); set_flash_latency(i);
reg_spictrl = (reg_spictrl & ~0x00700000) | 0x00500000; reg_spictrl = (reg_spictrl & ~0x00700000) | 0x00500000;
print(": "); printf(": %x\n", cmd_benchmark(false, &instns));
print_hex(cmd_benchmark(false, &instns), 8);
putchar('\n');
} }
for (int i = 8; i > 0; i--) for (int i = 8; i > 0; i--)
{ {
print("qspi-"); printf("qspi-%d ", i);
print_dec(i);
print(" ");
set_flash_latency(i); set_flash_latency(i);
reg_spictrl = (reg_spictrl & ~0x00700000) | 0x00200000; reg_spictrl = (reg_spictrl & ~0x00700000) | 0x00200000;
print(": "); printf(": %x\n", cmd_benchmark(false, &instns));
print_hex(cmd_benchmark(false, &instns), 8);
putchar('\n');
} }
for (int i = 8; i > 0; i--) for (int i = 8; i > 0; i--)
{ {
print("qspi-crm-"); printf("qspi-crm-%d ", i);
print_dec(i);
print(" ");
set_flash_latency(i); set_flash_latency(i);
reg_spictrl = (reg_spictrl & ~0x00700000) | 0x00300000; reg_spictrl = (reg_spictrl & ~0x00700000) | 0x00300000;
print(": "); printf(": %x\n", cmd_benchmark(false, &instns));
print_hex(cmd_benchmark(false, &instns), 8);
putchar('\n');
} }
for (int i = 8; i > 0; i--) for (int i = 8; i > 0; i--)
{ {
print("qspi-ddr-"); printf("qspi-ddr-%d ", i);
print_dec(i);
print(" ");
set_flash_latency(i); set_flash_latency(i);
reg_spictrl = (reg_spictrl & ~0x00700000) | 0x00600000; reg_spictrl = (reg_spictrl & ~0x00700000) | 0x00600000;
print(": "); printf(": %x\n", cmd_benchmark(false, &instns));
print_hex(cmd_benchmark(false, &instns), 8);
putchar('\n');
} }
for (int i = 8; i > 0; i--) for (int i = 8; i > 0; i--)
{ {
print("qspi-ddr-crm-"); printf("qspi-ddr-crm-%d ", i);
print_dec(i);
print(" ");
set_flash_latency(i); set_flash_latency(i);
reg_spictrl = (reg_spictrl & ~0x00700000) | 0x00700000; reg_spictrl = (reg_spictrl & ~0x00700000) | 0x00700000;
print(": "); printf(": %x\n", cmd_benchmark(false, &instns));
print_hex(cmd_benchmark(false, &instns), 8);
putchar('\n');
} }
print("instns : "); print("instns ");
print_hex(instns, 8); printf(": %x\n", instns);
putchar('\n');
} }
#endif #endif
@ -617,39 +634,31 @@ void cmd_benchmark_all()
print("default "); print("default ");
set_flash_mode_spi(); set_flash_mode_spi();
print_hex(cmd_benchmark(false, &instns), 8); printf("%x\n", cmd_benchmark(false, &instns));
putchar('\n');
print("dual "); print("dual ");
set_flash_mode_dual(); set_flash_mode_dual();
print_hex(cmd_benchmark(false, &instns), 8); printf("%x\n", cmd_benchmark(false, &instns));
putchar('\n');
// print("dual-crm "); // print("dual-crm ");
// enable_flash_crm(); // enable_flash_crm();
// print_hex(cmd_benchmark(false, &instns), 8); // printf("%x\n", cmd_benchmark(false, &instns));
// putchar('\n');
print("quad "); print("quad ");
set_flash_mode_quad(); set_flash_mode_quad();
print_hex(cmd_benchmark(false, &instns), 8); printf("%x\n", cmd_benchmark(false, &instns));
putchar('\n');
print("quad-crm "); print("quad-crm ");
enable_flash_crm(); enable_flash_crm();
print_hex(cmd_benchmark(false, &instns), 8); printf("%x\n", cmd_benchmark(false, &instns));
putchar('\n');
print("qddr "); print("qddr ");
set_flash_mode_qddr(); set_flash_mode_qddr();
print_hex(cmd_benchmark(false, &instns), 8); printf("%x\n", cmd_benchmark(false, &instns));
putchar('\n');
print("qddr-crm "); print("qddr-crm ");
enable_flash_crm(); enable_flash_crm();
print_hex(cmd_benchmark(false, &instns), 8); printf("%x\n", cmd_benchmark(false, &instns));
putchar('\n');
} }
#endif #endif
@ -683,10 +692,7 @@ void main()
print(" |_| |_|\\___\\___/____/ \\___/ \\____|\n"); print(" |_| |_|\\___\\___/____/ \\___/ \\____|\n");
print("\n"); print("\n");
print("Total memory: "); printf("Total memory: %dKiB\n\n", MEM_TOTAL / 1024);
print_dec(MEM_TOTAL / 1024);
print(" KiB\n");
print("\n");
cmd_memtest(); cmd_memtest();
print("\n"); print("\n");