mirror of
https://github.com/lcbcFoo/ReonV.git
synced 2025-04-18 18:44:43 -04:00
Mini printf implemented and tested
This commit is contained in:
parent
be0d492e0b
commit
d04f4233af
15 changed files with 47903 additions and 492 deletions
|
@ -2457,10 +2457,10 @@ end;
|
|||
|
||||
|
||||
case r.e.aluop is
|
||||
when EXE_STB => miscout := bpdata(7 downto 0) & bpdata(7 downto 0) &
|
||||
bpdata(7 downto 0) & bpdata(7 downto 0);
|
||||
when EXE_STB => miscout := bpdata(31 downto 24) & bpdata(31 downto 24) &
|
||||
bpdata(31 downto 24) & bpdata(31 downto 24);
|
||||
edata := miscout;
|
||||
when EXE_STH => miscout := bpdata(15 downto 0) & bpdata(15 downto 0);
|
||||
when EXE_STH => miscout := bpdata(31 downto 16) & bpdata(31 downto 16);
|
||||
edata := miscout;
|
||||
when EXE_PASS1 => miscout := bpdata; edata := miscout;
|
||||
when EXE_PASS2 => miscout := aluin2;
|
||||
|
@ -2642,22 +2642,26 @@ end;
|
|||
rdata(7 downto 0) := align_data(7 downto 0);
|
||||
if signed = '1' then rdata(31 downto 8) := (others => align_data(7)); end if;
|
||||
end case;
|
||||
outdata := rdata;
|
||||
|
||||
when "01" => -- half-word read
|
||||
if laddr(1) = '1' then
|
||||
rdata(15 downto 0) := align_data(15 downto 0);
|
||||
rdata(15 downto 0) := align_data(31 downto 16);
|
||||
if signed = '1' then rdata(31 downto 15) := (others => align_data(15)); end if;
|
||||
else
|
||||
rdata(15 downto 0) := align_data(31 downto 16);
|
||||
rdata(15 downto 0) := align_data(15 downto 0);
|
||||
if signed = '1' then rdata(31 downto 15) := (others => align_data(31)); end if;
|
||||
end if;
|
||||
outdata := rdata;
|
||||
|
||||
when others => -- single and double word read
|
||||
rdata := align_data;
|
||||
outdata(7 downto 0) := rdata(31 downto 24);
|
||||
outdata(15 downto 8) := rdata(23 downto 16);
|
||||
outdata(23 downto 16) := rdata(15 downto 8);
|
||||
outdata(31 downto 24) := rdata(7 downto 0);
|
||||
end case;
|
||||
|
||||
outdata(7 downto 0) := rdata(31 downto 24);
|
||||
outdata(15 downto 8) := rdata(23 downto 16);
|
||||
outdata(23 downto 16) := rdata(15 downto 8);
|
||||
outdata(31 downto 24) := rdata(7 downto 0);
|
||||
return(outdata);
|
||||
end;
|
||||
|
||||
|
|
|
@ -28,9 +28,14 @@ WRAP=-Wl,-wrap,exit,-wrap,open,-wrap,close,-wrap,write,-wrap,read,-wrap,lseek,-w
|
|||
#
|
||||
# Targets for compiling
|
||||
#
|
||||
MAIN_OBJS=reonv_crt0.o posix.o main.o
|
||||
|
||||
# Compiled binary linked with reonv_crt0
|
||||
%.out : %.c reonv_crt0.o posix.o
|
||||
${CROSS}${CC} -static -march=rv32i ${WRAP} -T${LD_SCRIPT} $< -o $@
|
||||
#%.out : %.c reonv_crt0.o posix.o
|
||||
# ${CROSS}${CC} -static -static-libgcc -march=rv32i ${WRAP} -T${LD_SCRIPT} $< -o $@
|
||||
%.out : $(MAIN_OBJS)
|
||||
${CROSS}gcc -static -nostartfiles $(MAIN_OBJS) ${WRAP},--no-relax,-melf32lriscv,-Ttext=0x40001000,-e,__reonv_start \
|
||||
-o $@
|
||||
|
||||
# Targets for .S.
|
||||
# .o is for linking programs (i.e. crt0.S)
|
||||
|
@ -38,11 +43,17 @@ WRAP=-Wl,-wrap,exit,-wrap,open,-wrap,close,-wrap,write,-wrap,read,-wrap,lseek,-w
|
|||
%.hex : %.S
|
||||
${CROSS}$(AS) $< -o $@
|
||||
|
||||
main.o : main.c
|
||||
${CROSS}${CC} -c $< -o $@
|
||||
|
||||
# mini_printf.o : mini_printf.c
|
||||
# ${CROSS}${CC} -c $< -o $@
|
||||
|
||||
posix.o : posix.c
|
||||
${CROSS}${CC} -c $< -o $@ -nostdlib ${WRAP}
|
||||
${CROSS}${CC} -c $< -o $@ -nostdlib
|
||||
|
||||
reonv_crt0.o : reonv_crt0.S
|
||||
${CROSS}${CC} -c $< -o $@ -nostdlib ${WRAP}
|
||||
${CROSS}${CC} -c $< -o $@ -nostdlib
|
||||
|
||||
# Target raw binary to avoid grmon2 errors saying this is not SPARC '-'
|
||||
%.bin : %.out
|
||||
|
|
45
riscv/main.c
45
riscv/main.c
|
@ -1,36 +1,59 @@
|
|||
int fib();
|
||||
#include <stdio.h>
|
||||
#include "mini-printf.h"
|
||||
|
||||
int main(){
|
||||
int n = 8;
|
||||
int n = 20;
|
||||
|
||||
printf("Testing fib calculator, array dealing, write, read and lseek functions\n\n");
|
||||
// Allocates memory for arrays
|
||||
int* array = (int*)sbrk(n * sizeof(int));
|
||||
int* array2 = (int*)sbrk(n * sizeof(int));
|
||||
int* array = sbrk(n * sizeof(int));
|
||||
int* array2 = sbrk(n * sizeof(int));
|
||||
|
||||
printf("Address array 1: 0x%x\n", array);
|
||||
printf("Address array 2: 0x%x\n", array2);
|
||||
|
||||
// Calculates fib(i), 1 <= i <= n
|
||||
for(int i = 1; i <= n; i++)
|
||||
array[i-1] = fib(i);
|
||||
|
||||
// Uses console
|
||||
for(int i = 1; i <= n; i++)
|
||||
printf("Fib(%02d) = %04d\n", i, array[i-1]);
|
||||
|
||||
// Writes results on output memory section
|
||||
write(0, array,n * sizeof(int));
|
||||
write(3, array,n * sizeof(int));
|
||||
|
||||
// Sets pointer to beginning of output memory section
|
||||
lseek(0, -n*sizeof(int), SEEK_CUR);
|
||||
lseek(3, -n*sizeof(int), SEEK_CUR);
|
||||
|
||||
// Reads the results into array2
|
||||
read(0, array2, n * sizeof(int));
|
||||
read(3, array2, n * sizeof(int));
|
||||
|
||||
// Checks if they were copied correctly
|
||||
int correct = 0xAAAAAAAA;
|
||||
int correct = 1;
|
||||
for(int i = 0; i < n; i++)
|
||||
if(array[i] != array2[i])
|
||||
correct = 0xBBBBBBBB;
|
||||
correct = 0;
|
||||
|
||||
// Writes the check into output memory section
|
||||
write(0, &correct, sizeof(int));
|
||||
if(correct)
|
||||
printf("Copied array1 into array2!\n");
|
||||
else
|
||||
printf("Oh no, error!\n");
|
||||
|
||||
dbgleon_printf("CARAI PRINT");
|
||||
printf("\n\nTesting printf\n\n");
|
||||
int d = 1234567890;
|
||||
int neg = -987654321;
|
||||
unsigned int u = 0xff123456;
|
||||
char s[] = "This is a string";
|
||||
char a = 'A';
|
||||
printf("Testing big int: 1234567890 = %d\nBig int in hex: 0x499602d2 = 0x%x\n", d, d);
|
||||
printf("Testing negative: -987654321 = %d\nNegative in hex: 0xC521974F = 0x%x\n", neg, neg);
|
||||
printf("Testing unsigned: 4279383126 = %u\nUnsigned in hex: 0xff123456 = 0x%x\n", u, u);
|
||||
printf("This is a string = %s\n", s);
|
||||
printf("%c comes after %c which comes after %c!\n", a + 2, a + 1, a);
|
||||
printf("\n\nFinished main!\n\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int fib(int i){
|
||||
|
|
BIN
riscv/main.out
BIN
riscv/main.out
Binary file not shown.
52
riscv/mini-printf.h
Normal file
52
riscv/mini-printf.h
Normal file
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
* The Minimal snprintf() implementation
|
||||
*
|
||||
* Copyright (c) 2013 Michal Ludvig <michal@logix.cz>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the auhor nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __MINI_PRINTF__
|
||||
#define __MINI_PRINTF__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
int mini_vsnprintf(char* buffer, unsigned int buffer_len, const char *fmt, char** va);
|
||||
int mini_snprintf(char* buffer, unsigned int buffer_len, const char *fmt, ...);
|
||||
int reonv_printf(const char* fmt, ...);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#define vsnprintf mini_vsnprintf
|
||||
#define snprintf mini_snprintf
|
||||
#define printf reonv_printf
|
||||
|
||||
#endif
|
324
riscv/posix.c
324
riscv/posix.c
|
@ -22,98 +22,303 @@
|
|||
|
||||
#include <unistd.h>
|
||||
#include "reonv.h"
|
||||
|
||||
// Currently only reads/writes data from output section of memory
|
||||
static char* heap = (char*) HEAP_START;
|
||||
static char* out_mem = (char*)OUT_MEM_BEGIN;
|
||||
#include "mini-printf.h"
|
||||
#define POSIC_C
|
||||
#include "posix_c.h"
|
||||
|
||||
|
||||
static char* heap;
|
||||
static char* out_mem;
|
||||
static char* console_buffer;
|
||||
static LEON23_APBUART_Regs_Map *uart_regs;
|
||||
|
||||
|
||||
#define LEON_REG_UART_CONTROL_RTD 0x000000FF /* RX/TX data */
|
||||
/* PRINTF ********************/
|
||||
|
||||
/*
|
||||
* 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.
|
||||
* The Minimal snprintf() implementation
|
||||
*
|
||||
* Copyright (c) 2013,2014 Michal Ludvig <michal@logix.cz>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the auhor nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* ----
|
||||
*
|
||||
* This is a minimal snprintf() implementation optimised
|
||||
* for embedded systems with a very limited program memory.
|
||||
* mini_snprintf() doesn't support _all_ the formatting
|
||||
* the glibc does but on the other hand is a lot smaller.
|
||||
* Here are some numbers from my STM32 project (.bin file size):
|
||||
* no snprintf(): 10768 bytes
|
||||
* mini snprintf(): 11420 bytes (+ 652 bytes)
|
||||
* glibc snprintf(): 34860 bytes (+24092 bytes)
|
||||
* Wasting nearly 24kB of memory just for snprintf() on
|
||||
* a chip with 32kB flash is crazy. Use mini_snprintf() instead.
|
||||
*
|
||||
*/
|
||||
|
||||
#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 */
|
||||
#include <unistd.h>
|
||||
#include "posix_c.h"
|
||||
#include "mini-printf.h"
|
||||
#include "reonv.h"
|
||||
|
||||
|
||||
typedef struct
|
||||
static unsigned int
|
||||
mini_strlen(const char *s)
|
||||
{
|
||||
volatile unsigned int data;
|
||||
volatile unsigned int status;
|
||||
volatile unsigned int ctrl;
|
||||
volatile unsigned int scaler;
|
||||
} LEON23_APBUART_Regs_Map;
|
||||
unsigned int len = 0;
|
||||
while (s[len] != '\0') len++;
|
||||
return len;
|
||||
}
|
||||
|
||||
|
||||
#define UART_TIMEOUT 100000
|
||||
static LEON23_APBUART_Regs_Map *uart_regs = 0;
|
||||
//int *console = (int *) 0x80000100;
|
||||
int
|
||||
dbgleon_printf (const char *fmt, ...)
|
||||
static unsigned int
|
||||
mini_itoa(int value, unsigned int radix, unsigned int uppercase, unsigned int unsig,
|
||||
char *buffer, unsigned int zero_pad)
|
||||
{
|
||||
unsigned int i, loops, ch;
|
||||
int printed_len;
|
||||
char printk_buf[1024];
|
||||
char *p = printk_buf;
|
||||
//__asm("ebreak");
|
||||
char *pbuffer = buffer;
|
||||
int negative = 0;
|
||||
unsigned int i, len;
|
||||
|
||||
/* Emit the output into the temporary buffer */
|
||||
p = fmt;
|
||||
printed_len = 10;
|
||||
/* No support for unusual radixes. */
|
||||
if (radix > 16)
|
||||
return 0;
|
||||
|
||||
if (value < 0 && !unsig) {
|
||||
negative = 1;
|
||||
value = -value;
|
||||
}
|
||||
|
||||
/* This builds the string back to front ... */
|
||||
do {
|
||||
int digit = value % radix;
|
||||
*(pbuffer++) = (digit < 10 ? '0' + digit : (uppercase ? 'A' : 'a') + digit - 10);
|
||||
value /= radix;
|
||||
} while (value > 0);
|
||||
|
||||
for (i = (pbuffer - buffer); i < zero_pad; i++)
|
||||
*(pbuffer++) = '0';
|
||||
|
||||
if (negative)
|
||||
*(pbuffer++) = '-';
|
||||
|
||||
*(pbuffer) = '\0';
|
||||
|
||||
/* ... now we reverse it (could do it recursively but will
|
||||
* conserve the stack space) */
|
||||
len = (pbuffer - buffer);
|
||||
for (i = 0; i < len / 2; i++) {
|
||||
char j = buffer[i];
|
||||
buffer[i] = buffer[len-i-1];
|
||||
buffer[len-i-1] = j;
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
struct mini_buff {
|
||||
char *buffer, *pbuffer;
|
||||
unsigned int buffer_len;
|
||||
};
|
||||
|
||||
static int my_putc(int ch, struct mini_buff *b){
|
||||
if ((unsigned int)((b->pbuffer - b->buffer) + 1) >= b->buffer_len)
|
||||
return 0;
|
||||
*(b->pbuffer++) = ch;
|
||||
*(b->pbuffer) = '\0';
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int my_puts(char *s, unsigned int len, struct mini_buff *b){
|
||||
unsigned int i;
|
||||
|
||||
if (b->buffer_len - (b->pbuffer - b->buffer) - 1 < len)
|
||||
len = b->buffer_len - (b->pbuffer - b->buffer) - 1;
|
||||
|
||||
/* Copy to buffer */
|
||||
for (i = 0; i < len; i++)
|
||||
*(b->pbuffer++) = s[i];
|
||||
*(b->pbuffer) = '\0';
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
int mini_vsnprintf(char *buffer, unsigned int buffer_len, const char *fmt, char** va){
|
||||
char* args = (*va);
|
||||
//__asm("ebreak");
|
||||
struct mini_buff b;
|
||||
char bf[24];
|
||||
char ch;
|
||||
|
||||
b.buffer = buffer;
|
||||
b.pbuffer = buffer;
|
||||
b.buffer_len = buffer_len;
|
||||
|
||||
while ((ch=*(fmt++))) {
|
||||
if ((unsigned int)((b.pbuffer - b.buffer) + 1) >= b.buffer_len)
|
||||
break;
|
||||
if(ch == '\n'){
|
||||
my_putc(ch, &b);
|
||||
ch = '\r';
|
||||
my_putc(ch, &b);
|
||||
}
|
||||
else if (ch!='%'){
|
||||
my_putc(ch, &b);
|
||||
}
|
||||
else {
|
||||
char zero_pad = 0;
|
||||
char *ptr;
|
||||
unsigned int len;
|
||||
unsigned int d;
|
||||
|
||||
ch=*(fmt++);
|
||||
|
||||
/* Zero padding requested, supported up to 9 zeros */
|
||||
if (ch=='0') {
|
||||
ch=*(fmt++);
|
||||
if (ch == '\0')
|
||||
goto end;
|
||||
if(ch >= '0' && ch <= '9')
|
||||
zero_pad = ch - '0';
|
||||
ch=*(fmt++);
|
||||
}
|
||||
|
||||
switch (ch) {
|
||||
case 0:
|
||||
goto end;
|
||||
|
||||
case 'u':
|
||||
case 'd':
|
||||
d = (unsigned int) *((int*)args);
|
||||
args += sizeof(unsigned int);
|
||||
len = mini_itoa(d, 10, 0, (ch=='u'), bf, zero_pad);
|
||||
my_puts(bf, len, &b);
|
||||
break;
|
||||
|
||||
case 'x':
|
||||
case 'X':
|
||||
d = (unsigned int) *((int*)args);
|
||||
args += sizeof(unsigned int);
|
||||
len = mini_itoa(d, 16, (ch=='X'), 1, bf, zero_pad);
|
||||
my_puts(bf, len, &b);
|
||||
break;
|
||||
|
||||
case 'c' :
|
||||
ch = (char) *args;
|
||||
args += sizeof(int);
|
||||
my_putc(ch, &b);
|
||||
break;
|
||||
|
||||
case 's' :
|
||||
ptr = (char*) *((int*)args);
|
||||
args += sizeof(int);
|
||||
my_puts(ptr, mini_strlen(ptr), &b);
|
||||
break;
|
||||
|
||||
default:
|
||||
my_putc(ch, &b);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
end:
|
||||
return b.pbuffer - b.buffer;
|
||||
}
|
||||
|
||||
|
||||
int mini_snprintf(char* buffer, unsigned int buffer_len, const char *fmt, ...){
|
||||
int ret;
|
||||
va_list va;
|
||||
va_start(va, fmt);
|
||||
ret = mini_vsnprintf(buffer, buffer_len, fmt, va);
|
||||
va_end(va);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int reonv_printf (const char *fmt, ...){
|
||||
va_list args;
|
||||
|
||||
/* Emit the output into the temporary buffer */
|
||||
va_start (args, fmt);
|
||||
//__asm("ebreak");
|
||||
unsigned int printed_len = mini_snprintf (console_buffer, CONSOLE_BUFFER_SIZE * sizeof (char), fmt, args);
|
||||
va_end (args);
|
||||
|
||||
write(STDOUT_FILENO, console_buffer, printed_len);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* END PRINTF*/
|
||||
|
||||
|
||||
int send_uart (char *fmt, unsigned int len){
|
||||
unsigned int i, loops, ch;
|
||||
char *p = fmt;
|
||||
|
||||
uart_regs = (LEON23_APBUART_Regs_Map*) 0x80000100;
|
||||
if (uart_regs){
|
||||
while (printed_len-- != 0){
|
||||
while (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;
|
||||
unsigned int outdata = (unsigned int) ch;
|
||||
outdata <<= 24;
|
||||
uart_regs->data = outdata;
|
||||
loops = 0;
|
||||
while (!(uart_regs->status & LEON_REG_UART_STATUS_TSE) && (loops < UART_TIMEOUT))
|
||||
loops++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return p - fmt;
|
||||
//---------------------
|
||||
}
|
||||
|
||||
|
||||
void _init_reonv(){
|
||||
uart_regs = (LEON23_APBUART_Regs_Map*) 0x80000100;
|
||||
heap = (char*) HEAP_START;
|
||||
out_mem = (char*)OUT_MEM_BEGIN;
|
||||
console_buffer = (char*) sbrk(CONSOLE_BUFFER_SIZE);
|
||||
}
|
||||
|
||||
|
||||
// Exit application
|
||||
void _exit_c( int status ) {
|
||||
void _exit( int status ) {
|
||||
__asm("ebreak");
|
||||
}
|
||||
|
||||
// Repositions the offset of memory section (no file descriptor implemented)
|
||||
int _lseek_c( int fd, int offset, int whence ) {
|
||||
int _lseek( int fd, int offset, int whence ) {
|
||||
|
||||
if(whence == SEEK_SET)
|
||||
out_mem = (char*) (OUT_MEM_BEGIN + offset);
|
||||
|
@ -134,7 +339,7 @@ int _lseek_c( int fd, int offset, int whence ) {
|
|||
|
||||
|
||||
// Read from output memory section (no file descriptor implemented)
|
||||
int _read_c( int fd, char *buffer, int len ) {
|
||||
int _read( int fd, char *buffer, int len ) {
|
||||
int i;
|
||||
for(i = 0; (i < len) && (&out_mem[i] < (char*)OUT_MEM_END); i++){
|
||||
buffer[i] = out_mem[i];
|
||||
|
@ -145,8 +350,13 @@ int _read_c( int fd, char *buffer, int len ) {
|
|||
}
|
||||
|
||||
// Write to output memory section (no file descriptor implemented)
|
||||
int _write_c( int fd, char *buffer, int len ) {
|
||||
int _write( int fd, char *buffer, int len ) {
|
||||
int i;
|
||||
|
||||
if(fd == STDOUT_FILENO){
|
||||
return send_uart(buffer, len);
|
||||
}
|
||||
|
||||
for(i = 0; (i < len) && (&out_mem[i] < (char*)OUT_MEM_END); i++){
|
||||
out_mem[i] = buffer[i];
|
||||
}
|
||||
|
@ -156,18 +366,18 @@ int _write_c( int fd, char *buffer, int len ) {
|
|||
}
|
||||
|
||||
// Open a file (no file descriptor implemented)
|
||||
int _open_c( const char *path, int flags, int mode ) {
|
||||
int _open( const char *path, int flags, int mode ) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Close fd (no file descriptor implemented)
|
||||
int _close_c( int fd ) {
|
||||
int _close( int fd ) {
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Allocate space on heap
|
||||
void* _sbrk_c( int incr ) {
|
||||
void* _sbrk( int incr ) {
|
||||
void* addr = (void*) heap;
|
||||
heap += incr;
|
||||
return addr;
|
||||
|
|
48
riscv/posix.h
Normal file
48
riscv/posix.h
Normal file
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
* This file is part of the ReonV distribution (https://github.com/lcbcFoo/ReonV).
|
||||
* Copyright (c) 2018 to Lucas C. B. Castro.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, version 3.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* Author: Lucas C. B. Castro
|
||||
* Description: This file contains minimal implementations of some posix
|
||||
* functions for ReonV.
|
||||
*/
|
||||
|
||||
|
||||
//int *console = (int *) 0x80000100;
|
||||
.globl send_uart
|
||||
|
||||
|
||||
// Exit application
|
||||
.globl _exit
|
||||
|
||||
// Repositions the offset of memory section (no file descriptor implemented)
|
||||
.globl _lseek
|
||||
|
||||
|
||||
// Read from output memory section (no file descriptor implemented)
|
||||
.globl _read
|
||||
|
||||
// Write to output memory section (no file descriptor implemented)
|
||||
.globl _write
|
||||
|
||||
// Open a file (no file descriptor implemented)
|
||||
.globl _open
|
||||
|
||||
// Close fd (no file descriptor implemented)
|
||||
.globl lose
|
||||
|
||||
// Allocate space on heap
|
||||
.globl _sbrk
|
BIN
riscv/posix.o
BIN
riscv/posix.o
Binary file not shown.
47
riscv/posix_c.h
Normal file
47
riscv/posix_c.h
Normal file
|
@ -0,0 +1,47 @@
|
|||
#ifndef POSIXC_H_INCLUDED
|
||||
#define POSIXC_H_INCLUDED
|
||||
|
||||
typedef struct
|
||||
{
|
||||
volatile unsigned int data;
|
||||
volatile unsigned int status;
|
||||
volatile unsigned int ctrl;
|
||||
volatile unsigned int scaler;
|
||||
} LEON23_APBUART_Regs_Map;
|
||||
|
||||
|
||||
#ifndef POSIC_C
|
||||
|
||||
extern char* heap;
|
||||
extern char* out_mem;
|
||||
extern char* console_buffer;
|
||||
extern LEON23_APBUART_Regs_Map *uart_regs;
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
int send_uart (char *fmt, unsigned int len);
|
||||
|
||||
void _init_reonv();
|
||||
|
||||
// Exit application
|
||||
void _exit( int status );
|
||||
|
||||
// Repositions the offset of memory section (no file descriptor implemented)
|
||||
int _lseek( int fd, int offset, int whence );
|
||||
|
||||
// Read from output memory section (no file descriptor implemented)
|
||||
int _read( int fd, char *buffer, int len );
|
||||
// Write to output memory section (no file descriptor implemented)
|
||||
int _write( int fd, char *buffer, int len );
|
||||
|
||||
// Open a file (no file descriptor implemented)
|
||||
int _open( const char *path, int flags, int mode );
|
||||
|
||||
// Close fd (no file descriptor implemented)
|
||||
int _close( int fd );
|
||||
|
||||
// Allocate space on heap
|
||||
void* _sbrk( int incr );
|
||||
|
||||
#endif
|
47375
riscv/read
Normal file
47375
riscv/read
Normal file
File diff suppressed because it is too large
Load diff
|
@ -1,6 +1,39 @@
|
|||
#define RAM_START 0x40000000
|
||||
#define RAM_SIZE 0x08000000
|
||||
#define SP_START 0x43FFFFF0
|
||||
#define HEAP_START 0x43000000
|
||||
#define OUT_MEM_BEGIN 0x44000000
|
||||
#define OUT_MEM_END 0x45000000
|
||||
#define RAM_START 0x40000000
|
||||
#define RAM_SIZE 0x08000000
|
||||
#define SP_START 0x43FFFFF0
|
||||
#define HEAP_START 0x43000000
|
||||
#define OUT_MEM_BEGIN 0x44000000
|
||||
#define OUT_MEM_END 0x45000000
|
||||
#define CONSOLE_BUFFER_SIZE 1024
|
||||
|
||||
/* Following defines were removed from Leon3 compiler bcc */
|
||||
#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 */
|
||||
|
||||
#define UART_TIMEOUT 5000 /* Timeout for TX */
|
||||
|
|
|
@ -21,12 +21,12 @@
|
|||
|
||||
|
||||
#include "reonv.h"
|
||||
#include "posix.h"
|
||||
|
||||
.file "reonv_crt0.S"
|
||||
.extern _start
|
||||
.extern main
|
||||
|
||||
.globl __reonv_start
|
||||
.globl __wrap_write
|
||||
.globl __wrap_exit
|
||||
.globl __wrap_read
|
||||
|
@ -34,7 +34,6 @@
|
|||
.globl __wrap_close
|
||||
.globl __wrap_lseek
|
||||
.globl __wrap_sbrk
|
||||
.type "__reonv_start",@function
|
||||
.type "__wrap_exit",@function
|
||||
.type "__wrap_open",@function
|
||||
.type "__wrap_close",@function
|
||||
|
@ -43,8 +42,10 @@
|
|||
.type "__wrap_lseek",@function
|
||||
.type "__wrap_sbrk", @function
|
||||
|
||||
.org 0x0
|
||||
|
||||
// Reset Function
|
||||
.section .text
|
||||
.globl __reonv_start
|
||||
__reonv_start:
|
||||
mv x1,x0
|
||||
mv x2,x0
|
||||
|
@ -79,28 +80,30 @@ __reonv_start:
|
|||
mv x31,x0
|
||||
|
||||
li sp,SP_START
|
||||
la gp,__global_pointer$
|
||||
call _init_reonv
|
||||
call main
|
||||
call __wrap_exit
|
||||
|
||||
// Wrap some existent glibc posix functions to force linker to use our
|
||||
// implementation
|
||||
__wrap_exit:
|
||||
jal x0,_exit_c
|
||||
call x0,_exit
|
||||
|
||||
__wrap_open:
|
||||
jal x0,_open_c
|
||||
call x0,_open
|
||||
|
||||
__wrap_close:
|
||||
jal x0,_close_c
|
||||
call x0,_close
|
||||
|
||||
__wrap_write:
|
||||
jal x0,_write_c
|
||||
call x0,_write
|
||||
|
||||
__wrap_read:
|
||||
jal x0,_read_c
|
||||
call x0,_read
|
||||
|
||||
__wrap_lseek:
|
||||
jal x0,_lseek_c
|
||||
call x0,_lseek
|
||||
|
||||
__wrap_sbrk:
|
||||
jal x0,_sbrk_c
|
||||
call x0,_sbrk
|
||||
|
|
Binary file not shown.
|
@ -1,395 +0,0 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* REONV - CONSOLE SUPPORT
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Console via UART is not supported yet on ReonV, this code may be used in
|
||||
* future only.
|
||||
*
|
||||
*******************************************************************************
|
||||
*/
|
||||
|
||||
#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++;
|
||||
}
|
||||
}
|
||||
}
|
||||
//---------------------
|
||||
}
|
BIN
riscv/teste
Executable file
BIN
riscv/teste
Executable file
Binary file not shown.
Loading…
Add table
Reference in a new issue