mirror of
https://github.com/saymrwulf/pulp-runtime.git
synced 2026-05-14 20:48:09 +00:00
400 lines
6.4 KiB
C
400 lines
6.4 KiB
C
/*
|
|
* Copyright (C) 2019 ETH Zurich, University of Bologna
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
#include <stdarg.h>
|
|
#include <stddef.h>
|
|
#include <stdio.h>
|
|
#include "hal/pulp.h"
|
|
#include <stdint.h>
|
|
#include "io.h"
|
|
#include <pulp.h>
|
|
|
|
|
|
#if defined(CONFIG_IO_UART) && CONFIG_IO_UART == 1 && defined(ARCHI_HAS_CLUSTER)
|
|
static L1_DATA int io_lock = 0;
|
|
#endif
|
|
|
|
|
|
|
|
#if defined(CONFIG_IO_UART) && CONFIG_IO_UART == 1
|
|
static int pos_io_uart_enabled = 0;
|
|
static PI_L2 uint8_t pos_io_uart_buffer;
|
|
#endif
|
|
|
|
|
|
|
|
static int errno;
|
|
int *__errno() { return &errno; }
|
|
|
|
|
|
|
|
int strcmp(const char *s1, const char *s2)
|
|
{
|
|
while (*s1 != '\0' && *s1 == *s2)
|
|
{
|
|
s1++;
|
|
s2++;
|
|
}
|
|
|
|
return (*(unsigned char *) s1) - (*(unsigned char *) s2);
|
|
}
|
|
|
|
|
|
|
|
int strncmp(const char *s1, const char *s2, size_t n)
|
|
{
|
|
if (n == 0)
|
|
return 0;
|
|
|
|
while (n-- != 0 && *s1 == *s2)
|
|
{
|
|
if (n == 0 || *s1 == '\0')
|
|
break;
|
|
s1++;
|
|
s2++;
|
|
}
|
|
|
|
return (*(unsigned char *) s1) - (*(unsigned char *) s2);
|
|
}
|
|
|
|
|
|
|
|
size_t strlen(const char *str)
|
|
{
|
|
const char *start = str;
|
|
|
|
while (*str)
|
|
str++;
|
|
return str - start;
|
|
}
|
|
|
|
|
|
|
|
int memcmp(const void *m1, const void *m2, size_t n)
|
|
{
|
|
unsigned char *s1 = (unsigned char *) m1;
|
|
unsigned char *s2 = (unsigned char *) m2;
|
|
|
|
while (n--)
|
|
{
|
|
if (*s1 != *s2)
|
|
{
|
|
return *s1 - *s2;
|
|
}
|
|
s1++;
|
|
s2++;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
void *memset(void *m, int c, size_t n)
|
|
{
|
|
char *s = (char *)m;
|
|
while (n--)
|
|
*s++ = (char) c;
|
|
|
|
return m;
|
|
}
|
|
|
|
|
|
|
|
void *memcpy(void *dst0, const void *src0, size_t len0)
|
|
{
|
|
void *save = dst0;
|
|
|
|
char src_aligned = (((size_t) src0) & 3) == 0;
|
|
char dst_aligned = (((size_t) dst0) & 3) == 0;
|
|
char copy_full_words = (len0 & 3) == 0;
|
|
|
|
if (src_aligned && dst_aligned && copy_full_words)
|
|
{
|
|
// all accesses are aligned => can copy full words
|
|
uint32_t *dst = (uint32_t *) dst0;
|
|
uint32_t *src = (uint32_t *) src0;
|
|
|
|
while (len0)
|
|
{
|
|
*dst++ = *src++;
|
|
len0 -= 4;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// copy bytewise
|
|
char *dst = (char *) dst0;
|
|
char *src = (char *) src0;
|
|
|
|
while (len0)
|
|
{
|
|
*dst++ = *src++;
|
|
len0--;
|
|
}
|
|
}
|
|
|
|
return save;
|
|
}
|
|
|
|
|
|
|
|
void *memmove(void *d, const void *s, size_t n)
|
|
{
|
|
char *dest = d;
|
|
const char *src = s;
|
|
|
|
if ((size_t) (dest - src) < n)
|
|
{
|
|
/*
|
|
* The <src> buffer overlaps with the start of the <dest> buffer.
|
|
* Copy backwards to prevent the premature corruption of <src>.
|
|
*/
|
|
|
|
while (n > 0)
|
|
{
|
|
n--;
|
|
dest[n] = src[n];
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* It is safe to perform a forward-copy */
|
|
while (n > 0)
|
|
{
|
|
*dest = *src;
|
|
dest++;
|
|
src++;
|
|
n--;
|
|
}
|
|
}
|
|
|
|
return d;
|
|
}
|
|
|
|
|
|
|
|
char *strcpy(char *d, const char *s)
|
|
{
|
|
char *dest = d;
|
|
while (*s != '\0')
|
|
{
|
|
*d = *s;
|
|
d++;
|
|
s++;
|
|
}
|
|
*d = '\0';
|
|
return dest;
|
|
}
|
|
|
|
|
|
|
|
char *strcat(char *dest, const char *src)
|
|
{
|
|
strcpy(dest + strlen(dest), src);
|
|
return dest;
|
|
}
|
|
|
|
|
|
|
|
char *strchr(const char *s, int c)
|
|
{
|
|
char tmp = (char) c;
|
|
|
|
while ((*s != tmp) && (*s != '\0'))
|
|
s++;
|
|
|
|
return (*s == tmp) ? (char *) s : NULL;
|
|
}
|
|
|
|
|
|
|
|
static void pos_libc_putc_stdout(char c)
|
|
{
|
|
*(volatile uint32_t *)(long)(ARCHI_STDOUT_ADDR + STDOUT_PUTC_OFFSET + (hal_core_id()<<3) + (hal_cluster_id()<<7)) = c;
|
|
}
|
|
|
|
|
|
|
|
#if defined(CONFIG_IO_UART) && CONFIG_IO_UART == 1
|
|
static void pos_libc_putc_uart(char c)
|
|
{
|
|
if (pos_io_uart_enabled)
|
|
{
|
|
pos_io_uart_buffer = c;
|
|
uart_write(CONFIG_IO_UART_ITF, &pos_io_uart_buffer, 1);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
|
|
|
|
static void pos_putc(char c)
|
|
{
|
|
#if defined(CONFIG_IO_UART) && CONFIG_IO_UART == 1
|
|
pos_libc_putc_uart(c);
|
|
#else
|
|
pos_libc_putc_stdout(c);
|
|
#endif
|
|
}
|
|
|
|
|
|
|
|
int puts(const char *s)
|
|
{
|
|
char c;
|
|
do
|
|
{
|
|
c = *s;
|
|
if (c == 0)
|
|
{
|
|
pos_putc('\n');
|
|
break;
|
|
}
|
|
pos_putc(c);
|
|
s++;
|
|
} while(1);
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
int fputc(int c, FILE *stream)
|
|
{
|
|
pos_putc(c);
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
int pos_libc_fputc_locked(int c, FILE *stream)
|
|
{
|
|
pos_putc(c);
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
int putchar(int c)
|
|
{
|
|
return fputc(c, stdout);
|
|
}
|
|
|
|
|
|
#if defined(CONFIG_IO_UART) && CONFIG_IO_UART == 1 && defined(ARCHI_HAS_CLUSTER)
|
|
|
|
static void uart_io_lock()
|
|
{
|
|
while (tas_lock_32((int)&io_lock) == -1)
|
|
{
|
|
volatile int i;
|
|
for (i=0; i<100; i++);
|
|
}
|
|
}
|
|
|
|
static void uart_io_unlock()
|
|
{
|
|
tas_unlock_32((int)&io_lock, 0);
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
int pos_libc_prf_locked(int (*func)(), void *dest, char *format, va_list vargs)
|
|
{
|
|
int err;
|
|
|
|
#if defined(CONFIG_IO_UART) && CONFIG_IO_UART == 1 && defined(ARCHI_HAS_CLUSTER)
|
|
uart_io_lock();
|
|
#endif
|
|
|
|
err = pos_libc_prf(func, dest, format, vargs);
|
|
|
|
#if defined(CONFIG_IO_UART) && CONFIG_IO_UART == 1 && defined(ARCHI_HAS_CLUSTER)
|
|
uart_io_unlock();
|
|
#endif
|
|
|
|
return err;
|
|
}
|
|
|
|
|
|
static void __attribute__((noreturn)) pos_wait_forever()
|
|
{
|
|
#if defined(ITC_VERSION)
|
|
if (hal_is_fc())
|
|
{
|
|
hal_itc_enable_clr(0xffffffff);
|
|
while(1) hal_itc_wait_for_interrupt();
|
|
}
|
|
else
|
|
{
|
|
#if defined(EU_VERSION) && EU_VERSION >=3
|
|
eu_evt_maskClr(0xffffffff);
|
|
eu_evt_wait();
|
|
#endif
|
|
}
|
|
#elif defined(EU_VERSION) && EU_VERSION >=3
|
|
eu_evt_maskClr(0xffffffff);
|
|
eu_evt_wait();
|
|
#endif
|
|
while(1);
|
|
}
|
|
|
|
|
|
void exit(int status)
|
|
{
|
|
apb_soc_status_set(status);
|
|
|
|
pos_wait_forever();
|
|
}
|
|
|
|
|
|
|
|
void abort()
|
|
{
|
|
exit(-1);
|
|
}
|
|
|
|
|
|
|
|
int pos_io_start()
|
|
{
|
|
#if defined(CONFIG_IO_UART) && CONFIG_IO_UART == 1
|
|
|
|
uart_open(CONFIG_IO_UART_ITF, CONFIG_IO_UART_BAUDRATE);
|
|
|
|
pos_io_uart_enabled = 1;
|
|
|
|
#endif
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
int pos_io_stop()
|
|
{
|
|
#if defined(CONFIG_IO_UART) && CONFIG_IO_UART == 1
|
|
|
|
pos_io_uart_enabled = 0;
|
|
|
|
uart_close(CONFIG_IO_UART_ITF);
|
|
|
|
#endif
|
|
|
|
return 0;
|
|
}
|