751 lines
13 KiB
C
751 lines
13 KiB
C
/*
|
|
* Copyright (c) 2021-2022 Amlogic, Inc. All rights reserved.
|
|
*
|
|
* SPDX-License-Identifier: MIT
|
|
*/
|
|
|
|
#include <sys/stat.h>
|
|
#include <sys/time.h>
|
|
#include <stdio.h>
|
|
#include <errno.h>
|
|
#include <unistd.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <math.h>
|
|
|
|
#if CONFIG_VFS
|
|
#include <sys_vfs.h>
|
|
#else
|
|
#include <stdarg.h>
|
|
#endif
|
|
#if defined(CONFIG_LOG_BUFFER)
|
|
#include "logbuffer.h"
|
|
#endif
|
|
#if defined(CONFIG_ARM64) || defined(CONFIG_ARM)
|
|
#include <serial.h>
|
|
#else
|
|
#include <uart.h>
|
|
#endif
|
|
#ifdef CONFIG_CHERRYUSB_DEVICE_ADB
|
|
#include "FreeRTOS_CLI_Console.h"
|
|
#endif
|
|
#include "common.h"
|
|
#include <FreeRTOS.h>
|
|
#include <task.h>
|
|
|
|
#if !defined(_COMPILING_NEWLIB) && !defined(_LIBC)
|
|
#define _COMPILING_NEWLIB
|
|
#endif
|
|
|
|
#define UNUSED(x) ((void)(x))
|
|
|
|
int _isatty(int);
|
|
int _stat(const char *, struct stat *);
|
|
int _fstat(int, struct stat *);
|
|
int _close(int);
|
|
int _open(const char *, int, ...);
|
|
int _write(int, const void *, size_t);
|
|
_off_t _lseek(int, _off_t, int);
|
|
int _read(int, void *, size_t);
|
|
|
|
#ifdef _REENT_SMALL_CHECK_INIT
|
|
#define CHECK_INIT(ptr) _REENT_SMALL_CHECK_INIT(ptr)
|
|
#else
|
|
#define CHECK_INIT(ptr) ((void)(ptr))
|
|
#endif
|
|
|
|
#define FILE_TYPE_MASK 0xFF
|
|
#define FILE_TYPE_STDIO 0x00
|
|
#define FILE_TYPE_VFS 0x01
|
|
#define FILE_TYPE_SOCKET 0x02
|
|
#define FILE_VALID 0x80000000
|
|
|
|
struct poslog {
|
|
int handle;
|
|
unsigned int flg;
|
|
};
|
|
|
|
/* Modified the MAX_OPEN_FILES from 512 to 8 inorder to reduce size */
|
|
#define MAX_OPEN_FILES 512
|
|
static struct poslog openfiles[MAX_OPEN_FILES];
|
|
|
|
static inline int _is_stdio(int fh)
|
|
{
|
|
if (fh == STDERR_FILENO || fh == STDOUT_FILENO || fh == STDIN_FILENO)
|
|
return 1;
|
|
return 0;
|
|
}
|
|
|
|
static inline unsigned int _file_type(int fh)
|
|
{
|
|
return (openfiles[fh].flg & FILE_TYPE_MASK);
|
|
}
|
|
|
|
static inline int remap_handle(int fh)
|
|
{
|
|
CHECK_INIT(_REENT);
|
|
|
|
if (_is_stdio(fh))
|
|
return fh;
|
|
|
|
if (fh < 0 || fh >= MAX_OPEN_FILES)
|
|
return -1;
|
|
|
|
if ((openfiles[fh].flg & FILE_VALID) == 0)
|
|
return -1;
|
|
|
|
return openfiles[fh].handle;
|
|
}
|
|
|
|
static inline int remap_handle_r(int fh, unsigned int type)
|
|
{
|
|
int i;
|
|
if (_is_stdio(fh))
|
|
return fh;
|
|
for (i = 0; i < MAX_OPEN_FILES; i++) {
|
|
if (_is_stdio(i))
|
|
continue;
|
|
if ((openfiles[i].flg & FILE_VALID) && _file_type(i) == type &&
|
|
(openfiles[i].handle == fh))
|
|
return i;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
static inline int alloc_file(unsigned int type)
|
|
{
|
|
int i = 0;
|
|
|
|
for (i = 0; i < MAX_OPEN_FILES; i++) {
|
|
if (_is_stdio(i))
|
|
continue;
|
|
if ((openfiles[i].flg & FILE_VALID) == 0) {
|
|
openfiles[i].flg = (FILE_VALID | (type & FILE_TYPE_MASK));
|
|
goto _exit_fun;
|
|
}
|
|
}
|
|
i = -1;
|
|
_exit_fun:
|
|
|
|
return i;
|
|
}
|
|
|
|
static inline void free_file(int fh)
|
|
{
|
|
if (fh > 0 && fh < MAX_OPEN_FILES) {
|
|
openfiles[fh].flg = 0;
|
|
openfiles[fh].handle = 0;
|
|
}
|
|
}
|
|
|
|
int _fstat(int file, struct stat *st)
|
|
{
|
|
int myhan = remap_handle(file);
|
|
|
|
if (myhan < 0) {
|
|
errno = EBADF;
|
|
return -1;
|
|
}
|
|
|
|
memset(st, 0, sizeof(*st));
|
|
|
|
if (_isatty(file)) {
|
|
st->st_mode = S_IFCHR;
|
|
if (file == STDIN_FILENO)
|
|
st->st_mode |= S_IRUSR;
|
|
else
|
|
st->st_mode |= S_IWUSR;
|
|
st->st_blksize = 1024;
|
|
return 0;
|
|
}
|
|
|
|
#if CONFIG_VFS
|
|
if (_file_type(file) == FILE_TYPE_VFS)
|
|
return vfs_fstat(myhan, st);
|
|
#endif
|
|
return -1;
|
|
}
|
|
|
|
int _stat(const char *fname, struct stat *st)
|
|
{
|
|
#if CONFIG_VFS
|
|
return vfs_stat(fname, st);
|
|
#else
|
|
UNUSED(fname);
|
|
UNUSED(st);
|
|
return -1;
|
|
#endif
|
|
}
|
|
|
|
off_t _lseek(int file, off_t ptr, int dir)
|
|
{
|
|
int myhan = remap_handle(file);
|
|
|
|
UNUSED(ptr);
|
|
UNUSED(dir);
|
|
|
|
if (myhan < 0) {
|
|
errno = EBADF;
|
|
return -1;
|
|
}
|
|
|
|
if (_isatty(file)) {
|
|
return 0;
|
|
}
|
|
|
|
#if CONFIG_VFS
|
|
if (_file_type(file) == FILE_TYPE_VFS)
|
|
return vfs_lseek(myhan, ptr, dir);
|
|
#endif
|
|
|
|
return -1;
|
|
}
|
|
|
|
int _isatty(int fd)
|
|
{
|
|
return _is_stdio(fd);
|
|
}
|
|
|
|
int _read(int file, void *ptr, size_t len)
|
|
{
|
|
int myhan = remap_handle(file);
|
|
|
|
UNUSED(ptr);
|
|
UNUSED(len);
|
|
|
|
if (myhan < 0) {
|
|
errno = EBADF;
|
|
return -1;
|
|
}
|
|
|
|
if (file == STDERR_FILENO || file == STDOUT_FILENO) {
|
|
errno = EBADF;
|
|
return -1;
|
|
}
|
|
|
|
if (file == STDIN_FILENO) {
|
|
errno = EBADF;
|
|
return -1;
|
|
}
|
|
|
|
#if CONFIG_VFS
|
|
if (_file_type(file) == FILE_TYPE_VFS)
|
|
return vfs_read(myhan, ptr, len);
|
|
#endif
|
|
|
|
#if ENABLE_MODULE_LWIP
|
|
if (_file_type(file) == FILE_TYPE_SOCKET)
|
|
return lwip_read(myhan, ptr, len);
|
|
#endif
|
|
return -1;
|
|
}
|
|
|
|
int _open(const char *path, int flags, ...)
|
|
{
|
|
int _fhandle = -1;
|
|
int i = alloc_file(FILE_TYPE_VFS);
|
|
va_list args;
|
|
|
|
UNUSED(path);
|
|
UNUSED(flags);
|
|
|
|
if (i < 0) {
|
|
errno = ENFILE;
|
|
return -1;
|
|
}
|
|
|
|
va_start(args, flags);
|
|
#if CONFIG_VFS
|
|
_fhandle = vfs_open(path, flags, va_arg(args, int));
|
|
#endif
|
|
va_end(args);
|
|
|
|
if (_fhandle < 0) {
|
|
free_file(i);
|
|
return -1;
|
|
}
|
|
|
|
openfiles[i].handle = _fhandle;
|
|
return i;
|
|
}
|
|
|
|
int _write(int file, const void *ptr, size_t len)
|
|
{
|
|
int myhan = remap_handle(file);
|
|
signed char *pxNext = NULL;
|
|
size_t i = 0;
|
|
#ifdef CONFIG_CHERRYUSB_DEVICE_ADB
|
|
signed char tmp = '\r';
|
|
#endif
|
|
|
|
#ifdef CONFIG_CHERRYUSB_DEVICE_ADB
|
|
xConsoleIO_t *ConsoleIO;
|
|
|
|
ConsoleIO = getConsoleIO(getCLIUartConsoleId());
|
|
#endif
|
|
|
|
if (myhan < 0) {
|
|
errno = EBADF;
|
|
return -1;
|
|
}
|
|
|
|
if (file == STDIN_FILENO) {
|
|
errno = EBADF;
|
|
return -1;
|
|
}
|
|
|
|
|
|
if (file == STDERR_FILENO || file == STDOUT_FILENO) {
|
|
#if CONFIG_LOG_BUFFER
|
|
if (logbuf_is_enable()) {
|
|
return logbuf_output_len(ptr, len);
|
|
}
|
|
#endif
|
|
/* Send each character in the string, one at a time. */
|
|
pxNext = (signed char *)ptr;
|
|
while (i < len && *pxNext) {
|
|
#if defined(CONFIG_ARM64) || defined(CONFIG_ARM)
|
|
if (*pxNext == '\n') {
|
|
#ifdef CONFIG_CHERRYUSB_DEVICE_ADB
|
|
if (ConsoleIO)
|
|
ConsoleIO->write((const char * const)&tmp, 1);
|
|
else
|
|
#endif
|
|
vSerialPutChar(ConsoleSerial, '\r');
|
|
}
|
|
|
|
#ifdef CONFIG_CHERRYUSB_DEVICE_ADB
|
|
if (ConsoleIO)
|
|
ConsoleIO->write((const char * const)pxNext, 1);
|
|
else
|
|
#endif
|
|
vSerialPutChar(ConsoleSerial, *pxNext);
|
|
#else
|
|
if (*pxNext == '\n')
|
|
vUartPutc('\r');
|
|
vUartPutc(*pxNext);
|
|
#endif
|
|
pxNext++;
|
|
i++;
|
|
}
|
|
|
|
return i;
|
|
}
|
|
|
|
#if CONFIG_VFS
|
|
if (_file_type(file) == FILE_TYPE_VFS)
|
|
return vfs_write(myhan, ptr, len);
|
|
#endif
|
|
#if ENABLE_MODULE_LWIP
|
|
if (_file_type(file) == FILE_TYPE_SOCKET)
|
|
return lwip_write(myhan, ptr, len);
|
|
#endif
|
|
return -1;
|
|
}
|
|
|
|
int _close(int file)
|
|
{
|
|
int myhan = remap_handle(file);
|
|
|
|
if (myhan < 0)
|
|
return 0;
|
|
|
|
if (_isatty(file)) {
|
|
return 0;
|
|
}
|
|
|
|
#if CONFIG_VFS
|
|
if (_file_type(file) == FILE_TYPE_VFS)
|
|
vfs_close(myhan);
|
|
#endif
|
|
|
|
#if ENABLE_MODULE_LWIP
|
|
if (_file_type(file) == FILE_TYPE_SOCKET)
|
|
lwip_close(myhan);
|
|
#endif
|
|
|
|
free_file(file);
|
|
return 0;
|
|
}
|
|
|
|
#if defined(_COMPILING_NEWLIB) || defined(_LIBC)
|
|
#define SECOND_TO_MICROSEC (1000000ULL)
|
|
#define MILISEC_TO_MICROSEC (1000UL)
|
|
|
|
static struct timeval real_tv = {.tv_sec = 0, .tv_usec = 0};
|
|
static struct timezone real_tz = {.tz_dsttime = DST_NONE, .tz_minuteswest = 0};
|
|
|
|
static inline int _settimeofday_imp(const struct timeval *tv, const struct timezone *tz)
|
|
{
|
|
uint64_t ullTickCount = 0ULL;
|
|
uint64_t ullMicroseconds = 0ULL;
|
|
TimeOut_t xCurrentTime = { 0 };
|
|
uint32_t shift_bit = 0;
|
|
|
|
if ((NULL == tv) && (NULL == tz))
|
|
return -1;
|
|
|
|
if (NULL != tv) {
|
|
vTaskSetTimeOutState(&xCurrentTime);
|
|
if ( sizeof( TickType_t ) < 8 )
|
|
shift_bit = sizeof( TickType_t ) * 8;
|
|
ullTickCount = ( uint64_t ) ( xCurrentTime.xOverflowCount ) << shift_bit;
|
|
ullTickCount += xCurrentTime.xTimeOnEntering;
|
|
ullMicroseconds = (tv->tv_sec * SECOND_TO_MICROSEC + tv->tv_usec) - pdTICKS_TO_MS(ullTickCount) * MILISEC_TO_MICROSEC;
|
|
|
|
real_tv.tv_sec = ullMicroseconds / SECOND_TO_MICROSEC;
|
|
real_tv.tv_usec = ullMicroseconds % SECOND_TO_MICROSEC;
|
|
}
|
|
if (NULL != tz) {
|
|
real_tz.tz_dsttime = tz->tz_dsttime;
|
|
real_tz.tz_minuteswest = tz->tz_minuteswest;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static inline int _gettimeofday_imp(struct timeval *tv, struct timezone *tz)
|
|
{
|
|
TimeOut_t xCurrentTime = { 0 };
|
|
uint64_t ullTickCount = 0ULL;
|
|
uint64_t ullMicroseconds = 0ULL;
|
|
uint32_t shift_bit = 0;
|
|
|
|
if (0 == configTICK_RATE_HZ)
|
|
return -1;
|
|
if ((NULL == tv) && (NULL == tz))
|
|
return -1;
|
|
|
|
if (NULL != tv) {
|
|
vTaskSetTimeOutState( &xCurrentTime );
|
|
if ( sizeof( TickType_t ) < 8 )
|
|
shift_bit = sizeof( TickType_t ) * 8;
|
|
ullTickCount = ( uint64_t ) ( xCurrentTime.xOverflowCount ) << shift_bit;
|
|
ullTickCount += xCurrentTime.xTimeOnEntering;
|
|
ullMicroseconds = (real_tv.tv_sec * SECOND_TO_MICROSEC + real_tv.tv_usec) + pdTICKS_TO_MS(ullTickCount) * MILISEC_TO_MICROSEC;
|
|
|
|
tv->tv_sec = ullMicroseconds / SECOND_TO_MICROSEC;
|
|
tv->tv_usec = ullMicroseconds % SECOND_TO_MICROSEC;
|
|
}
|
|
|
|
if (NULL != tz) {
|
|
tz->tz_dsttime = real_tz.tz_dsttime;
|
|
tz->tz_minuteswest = real_tz.tz_minuteswest;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
#endif
|
|
|
|
#ifdef _COMPILING_NEWLIB
|
|
int settimeofday(const struct timeval *tv, const struct timezone *tz)
|
|
{
|
|
return _settimeofday_imp(tv, tz);
|
|
}
|
|
|
|
int _settimeofday(const struct timeval *tv, const struct timezone *tz)
|
|
{
|
|
return _settimeofday_imp(tv, tz);
|
|
}
|
|
|
|
int _gettimeofday(struct timeval *tv, struct timezone *tz)
|
|
{
|
|
return _gettimeofday_imp(tv, tz);
|
|
}
|
|
#endif
|
|
|
|
#ifdef _LIBC
|
|
int settimeofday(const struct timeval *tv, const struct void *tz)
|
|
{
|
|
return _settimeofday_imp(tv, (const struct timezone *)tz);
|
|
}
|
|
|
|
int _settimeofday(const struct timeval *tv, const struct void *tz)
|
|
{
|
|
return _settimeofday_imp(tv, (const struct timezone *)tz);
|
|
}
|
|
|
|
int _gettimeofday(struct timeval *tv, void *tz)
|
|
{
|
|
return _gettimeofday_imp(tv, (struct timezone *)tz);
|
|
}
|
|
#endif
|
|
|
|
int fcntl(int fd, int cmd, ...)
|
|
{
|
|
int ret = -1;
|
|
int myhan = remap_handle(fd);
|
|
va_list args;
|
|
|
|
if (myhan < 0) {
|
|
errno = EBADF;
|
|
return -1;
|
|
}
|
|
|
|
if (_isatty(fd)) {
|
|
errno = EBADF;
|
|
return -1;
|
|
}
|
|
|
|
va_start(args, cmd);
|
|
#if CONFIG_VFS
|
|
if (_file_type(fd) == FILE_TYPE_VFS)
|
|
ret = vfs_vfcntl(myhan, cmd, args);
|
|
#endif
|
|
#if ENABLE_MODULE_LWIP
|
|
if (_file_type(fd) == FILE_TYPE_SOCKET)
|
|
ret = lwip_fcntl(myhan, cmd, va_arg(args, int));
|
|
#endif
|
|
va_end(args);
|
|
return ret;
|
|
}
|
|
|
|
int ioctl(int fd, int cmd, ...)
|
|
{
|
|
int ret = -1;
|
|
int myhan = remap_handle(fd);
|
|
va_list args;
|
|
|
|
if (myhan < 0) {
|
|
errno = EBADF;
|
|
return -1;
|
|
}
|
|
|
|
if (_isatty(fd)) {
|
|
errno = EBADF;
|
|
return -1;
|
|
}
|
|
|
|
va_start(args, cmd);
|
|
#if CONFIG_VFS
|
|
if (_file_type(fd) == FILE_TYPE_VFS)
|
|
ret = vfs_vioctl(myhan, cmd, args);
|
|
#endif
|
|
#if ENABLE_MODULE_LWIP
|
|
if (_file_type(fd) == FILE_TYPE_SOCKET)
|
|
ret = lwip_ioctl(myhan, cmd, va_arg(args, void *));
|
|
#endif
|
|
va_end(args);
|
|
return ret;
|
|
}
|
|
|
|
int fsync(int fd)
|
|
{
|
|
int ret = -1;
|
|
int myhan = remap_handle(fd);
|
|
|
|
if (myhan < 0) {
|
|
errno = EBADF;
|
|
return -1;
|
|
}
|
|
|
|
if (_isatty(fd))
|
|
return 0;
|
|
|
|
#if CONFIG_VFS
|
|
if (_file_type(fd) == FILE_TYPE_VFS)
|
|
ret = vfs_fsync(myhan);
|
|
#endif
|
|
return ret;
|
|
}
|
|
|
|
#if CONFIG_VFS
|
|
int statfs(const char *path, struct statfs *buf)
|
|
{
|
|
return vfs_statfs(path, buf);
|
|
}
|
|
#endif
|
|
|
|
pid_t _getpid(void)
|
|
{
|
|
return (pid_t)1;
|
|
}
|
|
|
|
pid_t __wrap__getpid_r(void)
|
|
{
|
|
return (pid_t)1;
|
|
}
|
|
|
|
int _kill(pid_t pid, int sig)
|
|
{
|
|
UNUSED(pid);
|
|
UNUSED(sig);
|
|
errno = ENOTSUP;
|
|
return -1;
|
|
}
|
|
|
|
int __wrap__kill_r(int pid, int sig)
|
|
{
|
|
UNUSED(pid);
|
|
UNUSED(sig);
|
|
errno = ENOTSUP;
|
|
return -1;
|
|
}
|
|
|
|
#if CONFIG_LIBC_STD_MEMALIGN
|
|
static inline void *memalign(size_t alignment, size_t size)
|
|
{
|
|
uintptr_t start_addr;
|
|
uintptr_t aligned_addr;
|
|
size_t total_size;
|
|
void *real_ptr;
|
|
|
|
total_size = size + alignment - 1 + sizeof(void *);
|
|
real_ptr = pvPortMalloc(total_size);
|
|
if (!real_ptr) {
|
|
errno = ENOMEM;
|
|
return NULL;
|
|
}
|
|
|
|
start_addr = (uintptr_t)real_ptr + sizeof(void *);
|
|
aligned_addr = (start_addr + alignment - 1) & ~(alignment - 1);
|
|
void *aligned_ptr = (void *)aligned_addr;
|
|
((void **)aligned_ptr)[-1] = real_ptr;
|
|
|
|
return aligned_ptr;
|
|
}
|
|
|
|
void *__wrap_memalign(size_t alignment, size_t size)
|
|
{
|
|
return memalign(alignment, size);
|
|
}
|
|
|
|
void *__wrap__memalign_r(struct _reent *reent, size_t alignment, size_t size)
|
|
{
|
|
UNUSED(reent);
|
|
|
|
return memalign(alignment, size);
|
|
}
|
|
#endif
|
|
|
|
void *__wrap_malloc(size_t size)
|
|
{
|
|
return pvPortMalloc(size);
|
|
}
|
|
|
|
void *__wrap__malloc_r(struct _reent *reent, size_t size)
|
|
{
|
|
UNUSED(reent);
|
|
return pvPortMalloc(size);
|
|
}
|
|
|
|
void *__wrap_calloc(size_t nmemb, size_t size)
|
|
{
|
|
size_t total = nmemb * size;
|
|
void *p;
|
|
|
|
if (total <= 0)
|
|
return NULL;
|
|
p = pvPortMalloc(total);
|
|
if (!p)
|
|
return NULL;
|
|
return memset(p, 0, total);
|
|
}
|
|
|
|
void *__wrap__calloc_r(struct _reent *reent, size_t nmemb, size_t size)
|
|
{
|
|
size_t total = nmemb * size;
|
|
void *p;
|
|
|
|
UNUSED(reent);
|
|
|
|
if (!total)
|
|
return NULL;
|
|
p = pvPortMalloc(total);
|
|
if (!p)
|
|
return NULL;
|
|
return memset(p, 0, total);
|
|
}
|
|
|
|
void *__wrap_realloc(void *ptr, size_t size)
|
|
{
|
|
return pvPortRealloc(ptr, size);
|
|
}
|
|
|
|
void *__wrap__realloc_r(struct _reent *reent, void *ptr, size_t size)
|
|
{
|
|
UNUSED(reent);
|
|
return pvPortRealloc(ptr, size);
|
|
}
|
|
|
|
void __wrap_free(void *ptr)
|
|
{
|
|
#if CONFIG_LIBC_STD_MEMALIGN
|
|
extern uint32_t is_memalign_ptr(void *ptr);
|
|
if (is_memalign_ptr(ptr))
|
|
vPortFree(((void **)ptr)[-1]);
|
|
else
|
|
vPortFree(ptr);
|
|
#else
|
|
vPortFree(ptr);
|
|
#endif
|
|
}
|
|
|
|
void __wrap__free_r(struct _reent *reent, void *ptr)
|
|
{
|
|
UNUSED(reent);
|
|
|
|
#if CONFIG_LIBC_STD_MEMALIGN
|
|
extern uint32_t is_memalign_ptr(void *ptr);
|
|
if (is_memalign_ptr(ptr))
|
|
vPortFree(((void **)ptr)[-1]);
|
|
else
|
|
vPortFree(ptr);
|
|
#else
|
|
vPortFree(ptr);
|
|
#endif
|
|
}
|
|
|
|
int _link(const char *oldpath, const char *newpath)
|
|
{
|
|
#if CONFIG_VFS
|
|
return vfs_link(oldpath, newpath);
|
|
#else
|
|
UNUSED_PARAM(oldpath);
|
|
UNUSED_PARAM(newpath);
|
|
|
|
errno = ENOENT;
|
|
return -1;
|
|
#endif
|
|
}
|
|
|
|
int _unlink(const char *__path)
|
|
{
|
|
#if CONFIG_VFS
|
|
return vfs_remove(__path);
|
|
#else
|
|
UNUSED_PARAM(__path);
|
|
|
|
errno = ENOENT;
|
|
return -1;
|
|
#endif
|
|
}
|
|
|
|
void _exit(int status)
|
|
{
|
|
UNUSED_PARAM(status);
|
|
|
|
/* infinity loop for exit syscall */
|
|
while (1)
|
|
;
|
|
}
|
|
|
|
#if CONFIG_BACKTRACE_UT
|
|
void __wrap___aeabi_unwind_cpp_pr0(void)
|
|
{
|
|
/* C++ exception and backtrace not supported */
|
|
}
|
|
|
|
void __wrap___aeabi_unwind_cpp_pr1(void)
|
|
{
|
|
/* C++ exception and backtrace not supported */
|
|
}
|
|
|
|
void __wrap___aeabi_unwind_cpp_pr2(void)
|
|
{
|
|
/* C++ exception and backtrace not supported */
|
|
}
|
|
#endif
|
|
|