Mini printf implemented and tested

This commit is contained in:
lcbcFoo 2018-03-25 21:45:42 -03:00
parent be0d492e0b
commit d04f4233af
15 changed files with 47903 additions and 492 deletions

View file

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

View file

@ -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

View file

@ -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){

Binary file not shown.

52
riscv/mini-printf.h Normal file
View 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

View file

@ -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
View 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

Binary file not shown.

47
riscv/posix_c.h Normal file
View 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

File diff suppressed because it is too large Load diff

View file

@ -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 */

View file

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

View file

@ -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

Binary file not shown.