Trying to implement stdout for printf

This commit is contained in:
lcbcFoo 2018-02-27 15:24:34 -03:00
parent ff2eae4ea1
commit 4c56d9eb49
5 changed files with 3086 additions and 0 deletions

154
riscv/console.c Normal file
View file

@ -0,0 +1,154 @@
#include <stdlib.h>
#include <assert.h>
#include <stdio.h>
#define LEON_REG_UART_CONTROL_RTD 0x000000FF /* RX/TX data */
/*
* The following defines the bits in the LEON UART Status Register.
*/
#define LEON_REG_UART_STATUS_DR 0x00000001 /* Data Ready */
#define LEON_REG_UART_STATUS_TSE 0x00000002 /* TX Send Register Empty */
#define LEON_REG_UART_STATUS_THE 0x00000004 /* TX Hold Register Empty */
#define LEON_REG_UART_STATUS_BR 0x00000008 /* Break Error */
#define LEON_REG_UART_STATUS_OE 0x00000010 /* RX Overrun Error */
#define LEON_REG_UART_STATUS_PE 0x00000020 /* RX Parity Error */
#define LEON_REG_UART_STATUS_FE 0x00000040 /* RX Framing Error */
#define LEON_REG_UART_STATUS_TF 0x00000200 /* FIFO Full */
#define LEON_REG_UART_STATUS_ERR 0x00000078 /* Error Mask */
/*
* The following defines the bits in the LEON UART Control Register.
*/
#define LEON_REG_UART_CTRL_RE 0x00000001 /* Receiver enable */
#define LEON_REG_UART_CTRL_TE 0x00000002 /* Transmitter enable */
#define LEON_REG_UART_CTRL_RI 0x00000004 /* Receiver interrupt enable */
#define LEON_REG_UART_CTRL_TI 0x00000008 /* Transmitter interrupt enable */
#define LEON_REG_UART_CTRL_PS 0x00000010 /* Parity select */
#define LEON_REG_UART_CTRL_PE 0x00000020 /* Parity enable */
#define LEON_REG_UART_CTRL_FL 0x00000040 /* Flow control enable */
#define LEON_REG_UART_CTRL_LB 0x00000080 /* Loop Back enable */
#define LEON_REG_UART_CTRL_DB 0x00000800 /* Debug FIFO enable */
#define LEON_REG_UART_CTRL_SI 0x00004000 /* TX shift register empty IRQ enable */
#define LEON_REG_UART_CTRL_FA 0x80000000 /* FIFO Available */
#define LEON_REG_UART_CTRL_FA_BIT 31
#define APBUART_CTRL_RE 0x1
#define APBUART_CTRL_TE 0x2
#define APBUART_CTRL_RI 0x4
#define APBUART_CTRL_TI 0x8
#define APBUART_CTRL_PS 0x10
#define APBUART_CTRL_PE 0x20
#define APBUART_CTRL_FL 0x40
#define APBUART_CTRL_LB 0x80
#define APBUART_CTRL_EC 0x100
#define APBUART_CTRL_TF 0x200
#define APBUART_CTRL_RF 0x400
#define APBUART_CTRL_BI 0x1000
#define APBUART_CTRL_DI 0x2000
#define APBUART_CTRL_FA 0x80000000
#define APBUART_STATUS_DR 0x1
#define APBUART_STATUS_TS 0x2
#define APBUART_STATUS_TE 0x4
#define APBUART_STATUS_BR 0x8
#define APBUART_STATUS_OV 0x10
#define APBUART_STATUS_PE 0x20
#define APBUART_STATUS_FE 0x40
#define APBUART_STATUS_ERR 0x78
#define APBUART_STATUS_TH 0x80
#define APBUART_STATUS_RH 0x100
#define APBUART_STATUS_TF 0x200
#define APBUART_STATUS_RF 0x400
/* APB UART */
typedef struct apbuart_regs {
volatile unsigned int data;
volatile unsigned int status;
volatile unsigned int ctrl;
volatile unsigned int scaler;
} apbuart_regs;
struct apbuart_regs *uart_regs = (struct apbuart_regs*) 0x80000100;
/* Before UART driver has registered (or when no UART is available), calls to
* printk that gets to bsp_out_char() will be filling data into the
* pre_printk_dbgbuf[] buffer, hopefully the buffer can help debugging the
* early BSP boot.. At least the last printk() will be caught.
*/
static char pre_printk_dbgbuf[32] = {0};
static int pre_printk_pos = 0;
void apbuart_outbyte_polled(unsigned char ch, int do_cr_on_newline, int wait_sent){
send:
while ( (uart_regs->status & APBUART_STATUS_TE) == 0 ) {
/* Lower bus utilization while waiting for UART */
__asm__ volatile ("nop"::); __asm__ volatile ("nop"::);
__asm__ volatile ("nop"::); __asm__ volatile ("nop"::);
__asm__ volatile ("nop"::); __asm__ volatile ("nop"::);
__asm__ volatile ("nop"::); __asm__ volatile ("nop"::);
}
if ((ch == '\n') && do_cr_on_newline) {
uart_regs->data = (unsigned int) '\r';
do_cr_on_newline = 0;
goto send;
}
uart_regs->data = (unsigned int) ch;
/* Wait until the character has been sent? */
if (wait_sent) {
while ((uart_regs->status & APBUART_STATUS_TE) == 0);
}
}
void apbuart_write_polled(const char *buf, size_t len)
{
size_t nwrite = 0;
while (nwrite < len) {
apbuart_outbyte_polled(*buf++, 0, 1);
nwrite++;
}
}
void bsp_debug_uart_init(void)
{
// int i;
// struct ambapp_dev *adev;
// struct ambapp_apb_info *apb;
//
// /* Update uart_regs_index to index used as debug console. Let user
// * select Debug console by setting uart_regs_index. If the BSP is to
// * provide the default UART (uart_regs_index==0):
// * non-MP: APBUART[0] is debug console
// * MP: LEON CPU index select UART
// */
// if (uart_regs_index == 0) {
// uart_regs_index = 0;
// } else {
// uart_regs_index--; /* User selected dbg-console */
// }
//
// /* Find APBUART core for System Debug Console */
// i = uart_regs_index;
// adev = (void *)ambapp_for_each(&ambapp_plb, (OPTIONS_ALL|OPTIONS_APB_SLVS),
// VENDOR_GAISLER, GAISLER_APBUART,
// ambapp_find_by_idx, (void *)&i);
// if (adev) {
// /* Found a matching debug console, initialize debug uart if present
// * for printk
// */
// apb = (struct ambapp_apb_info *)adev->devinfo;
// uart_regs = (struct apbuart_regs *)apb->start;
uart_regs->ctrl |= APBUART_CTRL_RE | APBUART_CTRL_TE;
uart_regs->status = 0;
//}
}

2371
riscv/log Normal file

File diff suppressed because it is too large Load diff

BIN
riscv/main.out Executable file

Binary file not shown.

176
riscv/main.read Normal file
View file

@ -0,0 +1,176 @@
93000000
13010000
93010000
13020000
93020000
13030000
93030000
13040000
93040000
13050000
93050000
13060000
93060000
13070000
93070000
13080000
93080000
13090000
93090000
130A0000
930A0000
130B0000
930B0000
130C0000
930C0000
130D0000
930D0000
130E0000
930E0000
130F0000
930F0000
37010044
130101FF
EF000014
EF004000
EF004001
EF00800B
EF00C00E
EF004006
EF008002
130101FE
232E8100
13040102
2326A4FE
73001000
13000000
0324C101
13010102
67800000
130101FE
232E8100
13040102
2326A4FE
2324B4FE
2322C4FE
8322C4FE
032384FE
832344FE
93870200
13850700
0324C101
13010102
67800000
130101FE
232E8100
13040102
2326A4FE
2324B4FE
2322C4FE
8322C4FE
032384FE
832344FE
B7070040
83A70720
37572341
13078767
23A0E700
832744FE
13850700
0324C101
13010102
67800000
130101FE
232E8100
13040102
2326A4FE
2324B4FE
2322C4FE
8322C4FE
032384FE
832344FE
93070000
13850700
0324C101
13010102
67800000
130101FE
232E8100
13040102
2326A4FE
8322C4FE
93070000
13850700
0324C101
13010102
67800000
00000000
A0896745
4743433A
2028474E
55292037
2E322E30
00000000
130101FE
232E1100
232C8100
13040102
93073000
2326F4FE
232404FE
B7373334
93871723
2320F4FE
230204FE
930704FE
13064000
93850700
13050000
EFF09FE9
8327C4FE
13850700
8320C101
03248101
13010102
67800000
130101FE
232E1100
232C8100
232A9100
13040102
2326A4FE
0327C4FE
93071000
6308F700
0327C4FE
93072000
6316F700
93071000
6F000003
8327C4FE
9387F7FF
13850700
EFF0DFFB
93040500
8327C4FE
9387E7FF
13850700
EFF09FFA
93070500
B387F400
13850700
8320C101
03248101
83244101
13010102
67800000
130101FE
232E8100
13040102
2326A4FE
2324B4FE
93070000
13850700
0324C101
13010102
67800000

385
riscv/reonv_print.c Normal file
View file

@ -0,0 +1,385 @@
/*
* Copyright (c) 2011 Aeroflex Gaisler
*
* BSD license:
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
/* This is a modified version of some files on leon3 compiler bcc 2.0.2 source
* code, avaiable with GPL license on Aeroflex Gaisler website.
*/
#include <stdlib.h>
#include <ctype.h>
#include <stdarg.h>
/*
* The following defines the bits in the UART Control Registers.
*
*/
#define LEON_REG_UART_CONTROL_RTD 0x000000FF /* RX/TX data */
/*
* The following defines the bits in the LEON UART Status Registers.
*/
#define LEON_REG_UART_STATUS_DR 0x00000001 /* Data Ready */
#define LEON_REG_UART_STATUS_TSE 0x00000002 /* TX Send Register Empty */
#define LEON_REG_UART_STATUS_THE 0x00000004 /* TX Hold Register Empty */
#define LEON_REG_UART_STATUS_BR 0x00000008 /* Break Error */
#define LEON_REG_UART_STATUS_OE 0x00000010 /* RX Overrun Error */
#define LEON_REG_UART_STATUS_PE 0x00000020 /* RX Parity Error */
#define LEON_REG_UART_STATUS_FE 0x00000040 /* RX Framing Error */
#define LEON_REG_UART_STATUS_ERR 0x00000078 /* Error Mask */
/*
* The following defines the bits in the LEON UART Status Registers.
*/
#define LEON_REG_UART_CTRL_RE 0x00000001 /* Receiver enable */
#define LEON_REG_UART_CTRL_TE 0x00000002 /* Transmitter enable */
#define LEON_REG_UART_CTRL_RI 0x00000004 /* Receiver interrupt enable */
#define LEON_REG_UART_CTRL_TI 0x00000008 /* Transmitter interrupt enable */
#define LEON_REG_UART_CTRL_PS 0x00000010 /* Parity select */
#define LEON_REG_UART_CTRL_PE 0x00000020 /* Parity enable */
#define LEON_REG_UART_CTRL_FL 0x00000040 /* Flow control enable */
#define LEON_REG_UART_CTRL_LB 0x00000080 /* Loop Back enable */
typedef struct
{
volatile unsigned int data;
volatile unsigned int status;
volatile unsigned int ctrl;
volatile unsigned int scaler;
} LEON23_APBUART_Regs_Map;
extern volatile LEON23_APBUART_Regs_Map *leon23_uarts[2]; /* in console.c */
typedef struct amba_apb_device
{
unsigned int start, irq;
} amba_apb_device;
static size_t
lo_strnlen (const char *s, size_t count)
{
const char *sc;
for (sc = s; count-- && *sc != '\0'; ++sc)
/* nothing */ ;
return sc - s;
}
static int
lo_vsnprintf (char *buf, size_t size, const char *fmt, va_list args)
{
int len;
unsigned long long num;
int i, j, n;
char *str, *end, c;
const char *s;
int flags;
int field_width;
int precision;
int qualifier;
int filler;
str = buf;
end = buf + size - 1;
if (end < buf - 1)
{
end = ((void *) -1);
size = end - buf + 1;
}
for (; *fmt; ++fmt)
{
if (*fmt != '%')
{
if (*fmt == '\n')
{
if (str <= end)
{
*str = '\r';
}
str++;
}
if (str <= end)
*str = *fmt;
++str;
continue;
}
/* process flags */
flags = 0;
/* get field width */
field_width = 0;
/* get the precision */
precision = -1;
/* get the conversion qualifier */
qualifier = 'l';
filler = ' ';
++fmt;
if (*fmt == '0')
{
filler = '0';
++fmt;
}
while (isdigit (*fmt))
{
field_width = field_width * 10 + ((*fmt) - '0');
++fmt;
}
/* default base */
switch (*fmt)
{
case 'c':
c = (unsigned char) va_arg (args, int);
if (str <= end)
*str = c;
++str;
while (--field_width > 0)
{
if (str <= end)
*str = ' ';
++str;
}
continue;
case 's':
s = va_arg (args, char *);
if (!s)
s = "<NULL>";
len = lo_strnlen (s, precision);
for (i = 0; i < len; ++i)
{
if (str <= end)
*str = *s;
++str;
++s;
}
while (len < field_width--)
{
if (str <= end)
*str = ' ';
++str;
}
continue;
case '%':
if (str <= end)
*str = '%';
++str;
continue;
case 'x':
break;
case 'd':
break;
default:
if (str <= end)
*str = '%';
++str;
if (*fmt)
{
if (str <= end)
*str = *fmt;
++str;
}
else
{
--fmt;
}
continue;
}
num = va_arg (args, unsigned long);
if (*fmt == 'd')
{
j = 0;
while (num && str <= end)
{
*str = (num % 10) + '0';
num = num / 10;
++str;
j++;
}
/* flip */
for (i = 0; i < (j / 2); i++)
{
n = str[(-j) + i];
str[(-j) + i] = str[-(i + 1)];
str[-(i + 1)] = n;
}
/* shift */
if (field_width > j)
{
i = field_width - j;
for (n = 1; n <= j; n++)
{
if (str + i - n <= end)
{
str[i - n] = str[-n];
}
}
for (i--; i >= 0; i--)
{
str[i - j] = filler;
}
str += field_width - j;
j = 1;
}
}
else
{
for (j = 0, i = 0; i < 8 && str <= end; i++)
{
if ((n =
((unsigned long) (num & (0xf0000000ul >> (i * 4)))) >>
((7 - i) * 4)) || j != 0)
{
if (n >= 10)
n += 'a' - 10;
else
n += '0';
*str = n;
++str;
j++;
}
}
/* shift */
if (field_width > j)
{
i = field_width - j;
for (n = 1; n <= j; n++)
{
if (str + i - n <= end)
{
str[i - n] = str[-n];
}
}
for (i--; i >= 0; i--)
{
str[i - j] = filler;
}
str += field_width - j;
j = 1;
}
}
if (j == 0 && str <= end)
{
*str = '0';
++str;
}
}
if (str <= end)
*str = '\0';
else if (size > 0)
/* don't write out a null byte if the buf size is zero */
*end = '\0';
/* the trailing null byte doesn't count towards the total
* ++str;
*/
return str - buf;
}
/**
* lo_vsprintf - Format a string and place it in a buffer
* @buf: The buffer to place the result into
* @fmt: The format string to use
* @args: Arguments for the format string
*
* Call this function if you are already dealing with a va_list.
* You probably want lo_sprintf instead.
*/
static int
lo_vsprintf (char *buf, const char *fmt, va_list args)
{
return lo_vsnprintf (buf, 0xFFFFFFFFUL, fmt, args);
}
int
dbgleon_sprintf (char *buf, size_t size, const char *fmt, ...)
{
va_list args;
int printed_len;
va_start (args, fmt);
printed_len = lo_vsnprintf (buf, size, fmt, args);
va_end (args);
return printed_len;
}
#define UART_TIMEOUT 100000
static LEON23_APBUART_Regs_Map *uart_regs = 0;
//int *console = (int *) 0x80000100;
int
dbgleon_printf (const char *fmt, ...)
{
unsigned int i, loops, ch;
amba_apb_device apbdevs[1];
va_list args;
int printed_len;
char printk_buf[1024];
char *p = printk_buf;
/* Emit the output into the temporary buffer */
va_start (args, fmt);
printed_len = lo_vsnprintf (printk_buf, sizeof (printk_buf), fmt, args);
va_end (args);
uart_regs = (LEON23_APBUART_Regs_Map*) 0x80000100;
if (uart_regs){
while (printed_len-- != 0){
ch = *p++;
if (uart_regs){
loops = 0;
while (!(uart_regs->status & LEON_REG_UART_STATUS_THE) && (loops < UART_TIMEOUT))
loops++;
uart_regs->data = ch;
loops = 0;
while (!(uart_regs->status & LEON_REG_UART_STATUS_TSE) && (loops < UART_TIMEOUT))
loops++;
}
}
}
//---------------------
}