/*
* 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 .
*/
/* Author: Lucas C. B. Castro
* Description: This file contains minimal implementations of some posix
* functions for ReonV.
*/
#include
#include "reonv.h"
#include "mini_printf.h"
#define POSIC_C
#include "posix_c.h"
// External
char* console_buffer;
// Internal
static char* heap;
char* out_mem;
static LEON23_APBUART_Regs_Map *uart_regs;
/* Sends output via UART, adapted from BCC source code */
int send_uart (char *fmt, unsigned int len){
unsigned int i, loops, ch;
char *p = fmt;
if (uart_regs){
while (len-- != 0){
ch = *p++;
if (uart_regs){
loops = 0;
while (!((uart_regs->status >> 24) & LEON_REG_UART_STATUS_THE) && (loops < UART_TIMEOUT))
loops++;
// Moves byte to beginning of TX buffer
unsigned int outdata = (unsigned int) ch;
outdata <<= 24;
uart_regs->data = outdata;
loops = 0;
while (!((uart_regs->status >> 24) & 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);
}
int memcmp(const void* s1, const void* s2,size_t n){
const unsigned char *p1 = s1, *p2 = s2;
while(n--)
if( *p1 != *p2 )
return *p1 - *p2;
else
p1++,p2++;
return 0;
}
void *memcpy(void *dest, const void *src, unsigned int n){
for(int i = 0; i < n; i++){
*((char*)dest++) = *((char*)src++);
}
}
// Exit application
void _exit(int status) {
__asm("ebreak");
while(1);
}
// Repositions the offset of memory section (no file descriptor implemented)
int _lseek( int fd, int offset, int whence ) {
if(whence == SEEK_SET)
out_mem = (char*) (OUT_MEM_BEGIN + offset);
else if(whence == SEEK_CUR)
out_mem = (char*) (out_mem + offset);
else if(whence == SEEK_END)
out_mem = (char*) (OUT_MEM_END + offset);
else
return -1;
if(out_mem < (char*) OUT_MEM_BEGIN)
return -1;
else if(out_mem > (char*) OUT_MEM_END)
return -1;
return out_mem - (char*) OUT_MEM_BEGIN;
}
// Read from output memory section (no file descriptor implemented)
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];
}
out_mem += i;
return i;
}
// Write to output memory section (no file descriptor implemented)
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];
}
out_mem += i;
return i;
}
// Open a file (no file descriptor implemented)
int _open( const char *path, int flags, int mode ) {
return 0;
}
// Close fd (no file descriptor implemented)
int _close( int fd ) {
return 0;
}
// Allocate space on heap
void* _sbrk( int incr ) {
void* addr = (void*) heap;
heap += incr;
// Keep heap byte aligned
while((int)heap % 4 != 0)
heap++;
return addr;
}