more bpmpfw shenanigans
This commit is contained in:
1 parent
7660650129
commit
b20d20edff
54 files changed
+1275
-30
No files matched your search
@@ -8,15 +8,26 @@ BUILDDIR := build
|
|||||||
OUTPUTDIR := out
|
OUTPUTDIR := out
|
||||||
SOURCEDIR := source
|
SOURCEDIR := source
|
||||||
|
|
||||||
OBJS := $(BUILDDIR)/start.o $(BUILDDIR)/main.o
|
LIBCDIR := $(SOURCEDIR)/libc
|
||||||
|
|
||||||
ARCH := -march=armv4t -mtune=arm7tdmi -mthumb-interwork
|
CPP_SOURCES := $(wildcard $(SOURCEDIR)/*.cpp)
|
||||||
|
C_SOURCES := $(wildcard $(LIBCDIR)/src/*.c)
|
||||||
|
S_SOURCES := $(wildcard $(SOURCEDIR)/*.s)
|
||||||
|
|
||||||
|
OBJS := $(patsubst $(SOURCEDIR)/%.cpp,$(BUILDDIR)/%.o,$(CPP_SOURCES)) \
|
||||||
|
$(patsubst $(LIBCDIR)/src/%.c,$(BUILDDIR)/libc/%.o,$(C_SOURCES)) \
|
||||||
|
$(patsubst $(SOURCEDIR)/%.s,$(BUILDDIR)/%.o,$(S_SOURCES))
|
||||||
|
|
||||||
|
ARCH := -march=armv4t -mtune=arm7tdmi -mthumb-interwork
|
||||||
|
INCLUDE := -I$(SOURCEDIR) -I$(LIBCDIR)/include -I$(LIBCDIR)/include/fslc
|
||||||
|
CFLAGS := $(ARCH) -O2 -g -ffreestanding -nostdlib -ffunction-sections -fdata-sections \
|
||||||
|
-fomit-frame-pointer -std=gnu11 -Wall -Wextra $(CUSTOMDEFINES)
|
||||||
CXXFLAGS := $(ARCH) -O2 -g -ffreestanding -nostdlib -fno-exceptions -fno-rtti \
|
CXXFLAGS := $(ARCH) -O2 -g -ffreestanding -nostdlib -fno-exceptions -fno-rtti \
|
||||||
-fno-unwind-tables -fno-threadsafe-statics -ffunction-sections -fdata-sections \
|
-fno-unwind-tables -fno-threadsafe-statics -ffunction-sections -fdata-sections \
|
||||||
-fomit-frame-pointer -std=gnu++20 -Wall -Wextra $(CUSTOMDEFINES)
|
-fomit-frame-pointer -std=gnu++20 -Wall -Wextra $(CUSTOMDEFINES)
|
||||||
ASFLAGS := $(ARCH) -g
|
ASFLAGS := $(ARCH) -g
|
||||||
LDFLAGS := $(ARCH) -nostartfiles -nodefaultlibs -Wl,--nmagic,--gc-sections \
|
LDFLAGS := $(ARCH) -nostartfiles -nodefaultlibs -Wl,--nmagic,--gc-sections \
|
||||||
-T $(SOURCEDIR)/../bpmpfw.ld -lgcc
|
-T $(SOURCEDIR)/../bpmpfw.ld -lgcc
|
||||||
|
|
||||||
BIN_TARGET := $(OUTPUTDIR)/$(TARGET).bin
|
BIN_TARGET := $(OUTPUTDIR)/$(TARGET).bin
|
||||||
|
|
||||||
@@ -32,13 +43,19 @@ $(BUILDDIR)/$(TARGET).elf: $(OBJS)
|
|||||||
@$(CXX) $(LDFLAGS) $(OBJS) -o $@
|
@$(CXX) $(LDFLAGS) $(OBJS) -o $@
|
||||||
|
|
||||||
$(BUILDDIR)/%.o: $(SOURCEDIR)/%.cpp | $(BUILDDIR)
|
$(BUILDDIR)/%.o: $(SOURCEDIR)/%.cpp | $(BUILDDIR)
|
||||||
@$(CXX) $(CXXFLAGS) -I$(SOURCEDIR) -c $< -o $@
|
@$(CXX) $(CXXFLAGS) $(INCLUDE) -c $< -o $@
|
||||||
|
|
||||||
|
$(BUILDDIR)/libc/%.o: $(LIBCDIR)/src/%.c | $(BUILDDIR)/libc
|
||||||
|
@$(CC) $(CFLAGS) $(INCLUDE) -c $< -o $@
|
||||||
|
|
||||||
$(BUILDDIR)/%.o: $(SOURCEDIR)/%.s | $(BUILDDIR)
|
$(BUILDDIR)/%.o: $(SOURCEDIR)/%.s | $(BUILDDIR)
|
||||||
@$(CXX) $(ASFLAGS) -I$(SOURCEDIR) -c $< -o $@
|
@$(CXX) $(ASFLAGS) $(INCLUDE) -c $< -o $@
|
||||||
|
|
||||||
$(BUILDDIR):
|
$(BUILDDIR):
|
||||||
@mkdir -p $(BUILDDIR)
|
@mkdir -p $(BUILDDIR)
|
||||||
|
|
||||||
|
$(BUILDDIR)/libc: | $(BUILDDIR)
|
||||||
|
@mkdir -p $(BUILDDIR)/libc
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
@rm -rf $(BUILDDIR) $(OUTPUTDIR)
|
@rm -rf $(BUILDDIR) $(OUTPUTDIR)
|
||||||
Binary file not shown.
@@ -0,0 +1,21 @@
|
|||||||
|
The MIT License (MIT)
|
||||||
|
|
||||||
|
Copyright (c) 2015-2016 Jurģis Brigmanis <velko.x@gmail.com>
|
||||||
|
|
||||||
|
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.
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
#ifndef _STD_ASSERT_H
|
||||||
|
#define _STD_ASSERT_H
|
||||||
|
|
||||||
|
#include "fslc/fslc_assert.h"
|
||||||
|
|
||||||
|
#endif /* _STD_ASSERT_H */
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
#ifndef FSLC_ASSERT_H
|
||||||
|
#define FSLC_ASSERT_H
|
||||||
|
|
||||||
|
#ifndef ALT_FSLC_NAMES
|
||||||
|
|
||||||
|
#define fslc_assert assert
|
||||||
|
|
||||||
|
#endif /* ALT_FSLC_NAMES */
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef NDEBUG
|
||||||
|
|
||||||
|
#define fslc_assert(expr) ((void)0)
|
||||||
|
|
||||||
|
#else /* NDEBUG */
|
||||||
|
|
||||||
|
/* Note: __PRETTY_FUNCTION__ is GCC specific */
|
||||||
|
#define fslc_assert(expr) ((expr) ? (void)0 : __fslc_assert_fail(#expr, __FILE__, __LINE__, __PRETTY_FUNCTION__))
|
||||||
|
|
||||||
|
#endif /* NDEBUG */
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
|
|
||||||
|
void __fslc_assert_fail(const char *expr, const char *file, unsigned int line, const char *func);
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
} /* extern "C" */
|
||||||
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
|
#endif /* FSLC_ASSERT_H */
|
||||||
@@ -0,0 +1,74 @@
|
|||||||
|
#ifndef FSLC_STDIO_H
|
||||||
|
#define FSLC_STDIO_H
|
||||||
|
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
#ifndef ALT_FSLC_NAMES
|
||||||
|
|
||||||
|
#define FSLC_FILE FILE
|
||||||
|
#define fslc_stdout stdout
|
||||||
|
#define fslc_stdin stdin
|
||||||
|
#define fslc_putchar putchar
|
||||||
|
#define fslc_fputc fputc
|
||||||
|
#define fslc_fputs fputs
|
||||||
|
#define fslc_puts puts
|
||||||
|
|
||||||
|
#define fslc_vfprintf vfprintf
|
||||||
|
#define fslc_vprintf vprintf
|
||||||
|
#define fslc_fprintf fprintf
|
||||||
|
#define fslc_printf printf
|
||||||
|
|
||||||
|
#define fslc_fwrite fwrite
|
||||||
|
#define fslc_fread fread
|
||||||
|
|
||||||
|
#define fslc_getc getc
|
||||||
|
#define fslc_getchar getchar
|
||||||
|
#define fslc_ungetc ungetc
|
||||||
|
#define fslc_fgets fgets
|
||||||
|
|
||||||
|
#endif /* ALT_FSLC_NAMES */
|
||||||
|
|
||||||
|
typedef struct _FSLC_FILE FSLC_FILE;
|
||||||
|
|
||||||
|
struct _FSLC_FILE
|
||||||
|
{
|
||||||
|
void *user_ptr;
|
||||||
|
int (*putc)(int c, FSLC_FILE *stream);
|
||||||
|
int (*getc)(FSLC_FILE *stream);
|
||||||
|
void (*pre_output)(FSLC_FILE *stream);
|
||||||
|
void (*post_output)(FSLC_FILE *stream);
|
||||||
|
int ungetc_buf;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern FSLC_FILE *fslc_stdout;
|
||||||
|
extern FSLC_FILE *fslc_stdin;
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
|
int fslc_putchar(int c);
|
||||||
|
int fslc_fputc(int c, FSLC_FILE *stream);
|
||||||
|
int fslc_fputs(const char *str, FSLC_FILE *stream);
|
||||||
|
int fslc_puts(const char *str);
|
||||||
|
|
||||||
|
int fslc_vfprintf(FSLC_FILE *stream, const char *format, va_list arg);
|
||||||
|
int fslc_vprintf(const char *format, va_list arg);
|
||||||
|
int fslc_fprintf(FSLC_FILE *stream, const char *format, ...);
|
||||||
|
int fslc_printf(const char *format, ...);
|
||||||
|
|
||||||
|
size_t fslc_fwrite(const void *ptr, size_t size, size_t count, FSLC_FILE *stream);
|
||||||
|
size_t fslc_fread(void *ptr, size_t size, size_t count, FSLC_FILE *stream);
|
||||||
|
|
||||||
|
int fslc_getc(FSLC_FILE *stream);
|
||||||
|
int fslc_getchar(void);
|
||||||
|
int fslc_ungetc(int c, FSLC_FILE *stream);
|
||||||
|
char *fslc_fgets(char *str, int num, FSLC_FILE *stream);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
} /* extern "C" */
|
||||||
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* FSLC_STDIO_H */
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
#ifndef FSLC_STDLIB_H
|
||||||
|
#define FSLC_STDLIB_H
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
#ifndef ALT_FSLC_NAMES
|
||||||
|
|
||||||
|
#define fslc_bsearch bsearch
|
||||||
|
|
||||||
|
#endif /* ALT_FSLC_NAMES */
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
|
|
||||||
|
void *fslc_bsearch(const void *key, const void *base, size_t num, size_t size, int (*cmp_proc)(const void *, const void *));
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
} /* extern "C" */
|
||||||
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
|
#endif /* FSLC_STDLIB_H */
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
#ifndef FSLC_STRING_H
|
||||||
|
#define FSLC_STRING_H
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
#ifndef ALT_FSLC_NAMES
|
||||||
|
#define fslc_memset memset
|
||||||
|
#define fslc_memcpy memcpy
|
||||||
|
#define fslc_memmove memmove
|
||||||
|
#define fslc_memcmp memcmp
|
||||||
|
|
||||||
|
#define fslc_strlen strlen
|
||||||
|
#define fslc_strcpy strcpy
|
||||||
|
#define fslc_strncpy strncpy
|
||||||
|
#define fslc_strcmp strcmp
|
||||||
|
#define fslc_strncmp strncmp
|
||||||
|
#define fslc_strchr strchr
|
||||||
|
#define fslc_strstr strstr
|
||||||
|
#define fslc_strpbrk strpbrk
|
||||||
|
#define fslc_strspn strspn
|
||||||
|
#define fslc_strtok_r strtok_r
|
||||||
|
|
||||||
|
#endif /* ALT_FSLC_NAMES */
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
|
void *fslc_memset(void *ptr, int value, size_t num);
|
||||||
|
void *fslc_memcpy(void *dest, const void *src, size_t len);
|
||||||
|
void *fslc_memmove(void *dest, const void *src, size_t len);
|
||||||
|
int fslc_memcmp(const void *ptr1, const void *ptr2, size_t num);
|
||||||
|
|
||||||
|
size_t fslc_strlen(const char *str);
|
||||||
|
char *fslc_strcpy(char *dest, const char *src);
|
||||||
|
char *fslc_strncpy(char *dest, const char *src, size_t len);
|
||||||
|
int fslc_strcmp(const char *str1, const char *str2);
|
||||||
|
int fslc_strncmp(const char *str1, const char *str2, size_t num);
|
||||||
|
char *fslc_strchr(const char *str, int c);
|
||||||
|
char *fslc_strstr(const char *search_in, const char *search_for);
|
||||||
|
char *fslc_strpbrk(const char *str, const char *delim);
|
||||||
|
size_t fslc_strspn(const char *str, const char *delim);
|
||||||
|
char *fslc_strtok_r(char *str, const char *delim, char **save_p);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
} /* extern "C" */
|
||||||
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* FSLC_STRING_H */
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
#ifndef FSLC_STDLIBX_H
|
||||||
|
#define FSLC_STDLIBX_H
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
#ifndef ALT_FSLC_NAMES
|
||||||
|
|
||||||
|
#define fslc_bsearch_i bsearch_i
|
||||||
|
|
||||||
|
#endif /* ALT_FSLC_NAMES */
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
|
int fslc_bsearch_i(const void *key, const void *base, size_t num, size_t size, int (*cmp_proc)(const void *, const void *));
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
} /* extern "C" */
|
||||||
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
|
#endif /* FSLC_STDLIBX_H */
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
#ifndef FSLC_STRINGX_H
|
||||||
|
#define FSLC_STRINGX_H
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
#ifndef ALT_FSLC_NAMES
|
||||||
|
|
||||||
|
#define fslc_memset_l memset_l
|
||||||
|
#define fslc_strcpy_e strcpy_e
|
||||||
|
#define fslc_strncpy_e strncpy_e
|
||||||
|
|
||||||
|
#endif /* ALT_FSLC_NAMES */
|
||||||
|
|
||||||
|
#if __SIZEOF_LONG__ == 4
|
||||||
|
#define memset_32 memset_l
|
||||||
|
#elif __SIZEOF_LONG__ == 8
|
||||||
|
#define memset_32(A, V, S) memset_l(A, (((unsigned long)(V)<<32)|(V)), S)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
|
void *fslc_memset_l(void *ptr, unsigned long value, size_t num);
|
||||||
|
char *fslc_strcpy_e(char *dest, const char *src);
|
||||||
|
char *fslc_strncpy_e(char *dest, const char *src, size_t len);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
} /* extern "C" */
|
||||||
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
|
#endif /* FSLC_STRINGX_H */
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
#ifndef _STD_STDIO_H
|
||||||
|
#define _STD_STDIO_H
|
||||||
|
|
||||||
|
#include "fslc/fslc_stdio.h"
|
||||||
|
|
||||||
|
#endif /* _STD_STDIO_H */
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
#ifndef _STD_STDLIB_H
|
||||||
|
#define _STD_STDLIB_H
|
||||||
|
|
||||||
|
#include "fslc/fslc_stdlib.h"
|
||||||
|
|
||||||
|
#endif /* _STD_STDLIB_H */
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
#ifndef _STD_STRING_H
|
||||||
|
#define _STD_STRING_H
|
||||||
|
|
||||||
|
#include "fslc/fslc_string.h"
|
||||||
|
|
||||||
|
#endif /* _STD_STRING_H */
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
#include "fslc_stdlib.h"
|
||||||
|
#include "stdlibx.h"
|
||||||
|
|
||||||
|
void *fslc_bsearch(const void *key, const void *base, size_t num, size_t size, int (*cmp_proc)(const void *, const void *))
|
||||||
|
{
|
||||||
|
int sidx = fslc_bsearch_i(key, base, num, size, cmp_proc);
|
||||||
|
|
||||||
|
if (sidx < 0)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return (char *)base + (sidx * size);
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
int fslc_bsearch_i(const void *key, const void *base, size_t num, size_t size, int (*cmp_proc)(const void *, const void *))
|
||||||
|
{
|
||||||
|
int lo = 0;
|
||||||
|
int hi = num - 1;
|
||||||
|
|
||||||
|
char *cbase = (char *)base;
|
||||||
|
|
||||||
|
while (lo <= hi)
|
||||||
|
{
|
||||||
|
int i = lo + ((hi - lo) >> 1);
|
||||||
|
|
||||||
|
char *ptr = cbase + (i * size);
|
||||||
|
int cmp = cmp_proc(key, ptr);
|
||||||
|
|
||||||
|
if (cmp == 0)
|
||||||
|
return i;
|
||||||
|
|
||||||
|
if (cmp > 0)
|
||||||
|
{
|
||||||
|
lo = i + 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
hi = i - 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ~lo;
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
#include "fslc_stdio.h"
|
||||||
|
|
||||||
|
int fslc_fprintf(FSLC_FILE *stream, const char *format, ...)
|
||||||
|
{
|
||||||
|
va_list args;
|
||||||
|
va_start(args, format);
|
||||||
|
int r = fslc_vfprintf(stream, format, args);
|
||||||
|
va_end(args);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
#include "fslc_stdio.h"
|
||||||
|
|
||||||
|
int fslc_fputc(int c, FSLC_FILE *stream)
|
||||||
|
{
|
||||||
|
if (stream->pre_output) stream->pre_output(stream);
|
||||||
|
|
||||||
|
int r = stream->putc(c, stream);
|
||||||
|
|
||||||
|
if (stream->post_output) stream->post_output(stream);
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
#include "fslc_stdio.h"
|
||||||
|
|
||||||
|
int _fslc_fputs_impl(const char *str, FSLC_FILE *stream);
|
||||||
|
|
||||||
|
int fslc_fputs(const char *str, FSLC_FILE *stream)
|
||||||
|
{
|
||||||
|
if (stream->pre_output) stream->pre_output(stream);
|
||||||
|
|
||||||
|
int r = _fslc_fputs_impl(str, stream);
|
||||||
|
|
||||||
|
if (stream->post_output) stream->post_output(stream);
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
#include "fslc_stdio.h"
|
||||||
|
|
||||||
|
int _fslc_fputs_impl(const char *str, FSLC_FILE *stream)
|
||||||
|
{
|
||||||
|
int res = 0;
|
||||||
|
for (;*str; ++str)
|
||||||
|
{
|
||||||
|
int pr = stream->putc(*str, stream);
|
||||||
|
if (pr < 0) return pr;
|
||||||
|
++res;
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
#include "fslc_string.h"
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
int fslc_memcmp(const void *ptr1, const void *ptr2, size_t num)
|
||||||
|
{
|
||||||
|
unsigned char *b_p1 = (unsigned char *)ptr1;
|
||||||
|
unsigned char *b_p2 = (unsigned char *)ptr2;
|
||||||
|
|
||||||
|
for (;((uintptr_t)b_p1 & (sizeof(long)-1)) && num > 0; ++b_p1, ++b_p2, --num)
|
||||||
|
{
|
||||||
|
if (*b_p1 != *b_p2)
|
||||||
|
{
|
||||||
|
return *b_p1 > *b_p2 ? 1 : -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned long *w_p1 = (unsigned long *)b_p1;
|
||||||
|
unsigned long *w_p2 = (unsigned long *)b_p2;
|
||||||
|
for (;num >= sizeof(unsigned long); ++w_p1, ++w_p2, num -= sizeof(unsigned long))
|
||||||
|
{
|
||||||
|
if (*w_p1 != *w_p2)
|
||||||
|
{
|
||||||
|
return *w_p1 > *w_p2 ? 1 : -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
b_p1 = (unsigned char *)w_p1;
|
||||||
|
b_p2 = (unsigned char *)w_p2;
|
||||||
|
for (; num > 0; ++b_p1, ++b_p2, --num)
|
||||||
|
{
|
||||||
|
if (*b_p1 != *b_p2)
|
||||||
|
{
|
||||||
|
return *b_p1 > *b_p2 ? 1 : -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
#include "fslc_string.h"
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
void *fslc_memcpy(void *dest, const void *src, size_t len)
|
||||||
|
{
|
||||||
|
/* Copy byte-by-byte up to word-aligned.
|
||||||
|
*
|
||||||
|
* There's a possibility, that src and dest have different offsets
|
||||||
|
* to word boundary and can not both be used efficiently.
|
||||||
|
*
|
||||||
|
* In this case we use align to dest argument, because it then can be
|
||||||
|
* written in one operation, instead of read-modify-write of 2 words.
|
||||||
|
*
|
||||||
|
* Most of the time both parameters should be word-aligned, however.
|
||||||
|
*/
|
||||||
|
unsigned char *b_src = (unsigned char *)src;
|
||||||
|
unsigned char *b_dst = (unsigned char *)dest;
|
||||||
|
for (;((uintptr_t)b_dst & (sizeof(unsigned long)-1)) && len > 0; b_src++, b_dst++, len--)
|
||||||
|
{
|
||||||
|
*b_dst = *b_src;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Then all word-aligned */
|
||||||
|
unsigned long *w_src = (unsigned long*)b_src;
|
||||||
|
unsigned long *w_dst = (unsigned long*)b_dst;
|
||||||
|
for (;len >= sizeof(unsigned long); w_src++, w_dst++, len -= sizeof(unsigned long))
|
||||||
|
{
|
||||||
|
*w_dst = *w_src;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* And byte-by-byte the rest */
|
||||||
|
b_src = (unsigned char *)w_src;
|
||||||
|
b_dst = (unsigned char *)w_dst;
|
||||||
|
for (; len > 0; b_src++, b_dst++, len--)
|
||||||
|
{
|
||||||
|
*b_dst = *b_src;
|
||||||
|
}
|
||||||
|
|
||||||
|
return dest;
|
||||||
|
}
|
||||||
@@ -0,0 +1,69 @@
|
|||||||
|
#include "fslc_string.h"
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
void *fslc_memmove(void *dest, const void *src, size_t len)
|
||||||
|
{
|
||||||
|
unsigned char *b_dst = (unsigned char *)dest;
|
||||||
|
unsigned char *b_src = (unsigned char *)src;
|
||||||
|
|
||||||
|
/* Need to check if memory regions overlaps. Then if the dest address is
|
||||||
|
* larger than source, we need to copy backwards (or else source regions
|
||||||
|
* ending will be overwritten by writes to dest, before they are read).
|
||||||
|
*
|
||||||
|
* In other cases it works identically as memcpy(). Same considerations
|
||||||
|
* about address alignment applies here.
|
||||||
|
*/
|
||||||
|
if ( b_dst < b_src + len && b_dst > b_src)
|
||||||
|
{
|
||||||
|
b_src += len;
|
||||||
|
b_dst += len;
|
||||||
|
|
||||||
|
/* Byte-by-byte down to word-aligned. */
|
||||||
|
for (;((uintptr_t)b_dst & (sizeof(unsigned long)-1)) && len > 0; )
|
||||||
|
{
|
||||||
|
b_src--, b_dst--, len--;
|
||||||
|
*b_dst = *b_src;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Then all word-aligned */
|
||||||
|
unsigned long *w_src = (unsigned long*)b_src;
|
||||||
|
unsigned long *w_dst = (unsigned long*)b_dst;
|
||||||
|
for (;len >= sizeof(unsigned long); )
|
||||||
|
{
|
||||||
|
w_src--, w_dst--, len -= sizeof(unsigned long);
|
||||||
|
*w_dst = *w_src;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* And byte-by-byte the rest */
|
||||||
|
b_src = (unsigned char *)w_src;
|
||||||
|
b_dst = (unsigned char *)w_dst;
|
||||||
|
for (; len > 0; )
|
||||||
|
{
|
||||||
|
b_src--, b_dst--, len--;
|
||||||
|
*b_dst = *b_src;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* Byte-by-byte up to word-aligned. */
|
||||||
|
for (;((uintptr_t)b_dst & (sizeof(unsigned long)-1)) && len > 0; b_src++, b_dst++, len--)
|
||||||
|
{
|
||||||
|
*b_dst = *b_src;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Then all word-aligned */
|
||||||
|
unsigned long *w_src = (unsigned long *)b_src;
|
||||||
|
unsigned long *w_dst = (unsigned long *)b_dst;
|
||||||
|
for (;len >= sizeof(unsigned long); w_src++, w_dst++, len -= sizeof(unsigned long))
|
||||||
|
{
|
||||||
|
*w_dst = *w_src;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* And byte-by-byte the rest */
|
||||||
|
b_src = (unsigned char *)w_src;
|
||||||
|
b_dst = (unsigned char *)w_dst;
|
||||||
|
for (; len > 0; b_src++, b_dst++, len--)
|
||||||
|
{
|
||||||
|
*b_dst = *b_src;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return dest;
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
#include "fslc_string.h"
|
||||||
|
#include "stringx.h"
|
||||||
|
|
||||||
|
void *fslc_memset(void *ptr, int value, size_t num)
|
||||||
|
{
|
||||||
|
/* Will use memset_l() to actually fill the memory region. If value is non-zero, we need
|
||||||
|
* to replicate lowest byte to all the long's bytes.
|
||||||
|
*/
|
||||||
|
if (value)
|
||||||
|
{
|
||||||
|
unsigned char c_val = value;
|
||||||
|
unsigned long l_val = (c_val << 0) | (c_val << 8) | (c_val << 16) | (c_val << 24);
|
||||||
|
|
||||||
|
#if __SIZEOF_LONG__ == 8
|
||||||
|
l_val |= l_val << 32;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return fslc_memset_l(ptr, l_val, num);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return fslc_memset_l(ptr, value, num);
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
#include "stringx.h"
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
void *fslc_memset_l(void *ptr, unsigned long value, size_t num)
|
||||||
|
{
|
||||||
|
unsigned char *b_src = (unsigned char *)&value;
|
||||||
|
unsigned char *b_dst = (unsigned char *)ptr;
|
||||||
|
|
||||||
|
/* Byte by byte - to aligned word address */
|
||||||
|
b_src += ((uintptr_t)b_dst & (sizeof(unsigned long)-1));
|
||||||
|
for (;((uintptr_t)b_dst & (sizeof(unsigned long)-1)) && num > 0; b_dst++,b_src++,num--)
|
||||||
|
{
|
||||||
|
*b_dst = *b_src;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* All aligned */
|
||||||
|
unsigned long *w_dst = (unsigned long *)b_dst;
|
||||||
|
for (;num >= sizeof(unsigned long); w_dst++,num -= sizeof(unsigned long))
|
||||||
|
{
|
||||||
|
*w_dst= value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Unaligned ending */
|
||||||
|
b_src = (unsigned char *)&value;
|
||||||
|
b_dst = (unsigned char *)w_dst;
|
||||||
|
for (; num > 0; b_dst++,b_src++,num--)
|
||||||
|
{
|
||||||
|
*b_dst = *b_src;
|
||||||
|
}
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
#include "fslc_stdio.h"
|
||||||
|
|
||||||
|
int fslc_printf(const char *format, ...)
|
||||||
|
{
|
||||||
|
va_list args;
|
||||||
|
va_start(args, format);
|
||||||
|
int r = fslc_vfprintf(fslc_stdout, format, args);
|
||||||
|
va_end(args);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
#include "fslc_stdio.h"
|
||||||
|
|
||||||
|
int fslc_putchar(int c)
|
||||||
|
{
|
||||||
|
return fslc_fputc(c, fslc_stdout);
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
#include "fslc_stdio.h"
|
||||||
|
|
||||||
|
int _fslc_fputs_impl(const char *str, FSLC_FILE *stream);
|
||||||
|
|
||||||
|
int fslc_puts(const char *str)
|
||||||
|
{
|
||||||
|
if (fslc_stdout->pre_output) fslc_stdout->pre_output(fslc_stdout);
|
||||||
|
|
||||||
|
int r = _fslc_fputs_impl(str, fslc_stdout);
|
||||||
|
|
||||||
|
if (r >= 0)
|
||||||
|
{
|
||||||
|
int nlr = fslc_stdout->putc('\n', fslc_stdout);
|
||||||
|
if (nlr < 0)
|
||||||
|
r = nlr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fslc_stdout->post_output) fslc_stdout->post_output(fslc_stdout);
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
#include "fslc_stdio.h"
|
||||||
|
|
||||||
|
FSLC_FILE *fslc_stdout;
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
#include "fslc_string.h"
|
||||||
|
|
||||||
|
char *fslc_strchr(const char *str, int c)
|
||||||
|
{
|
||||||
|
for (;*str; ++str)
|
||||||
|
if (*str == c)
|
||||||
|
return (char *)str;
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
#include "fslc_string.h"
|
||||||
|
|
||||||
|
int fslc_strcmp(const char *str1, const char *str2)
|
||||||
|
{
|
||||||
|
for( ; *str1 && *str1 == *str2; ++str1, ++str2);
|
||||||
|
|
||||||
|
return *((unsigned char *)str1) - *((unsigned char *)str2);
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
#include "fslc_string.h"
|
||||||
|
#include "stringx.h"
|
||||||
|
|
||||||
|
char *fslc_strcpy(char *dest, const char *src)
|
||||||
|
{
|
||||||
|
fslc_strcpy_e(dest, src);
|
||||||
|
return dest;
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
#include "stringx.h"
|
||||||
|
|
||||||
|
char *fslc_strcpy_e(char *dest, const char *src)
|
||||||
|
{
|
||||||
|
for(; *src; ++src, ++dest)
|
||||||
|
*dest = *src;
|
||||||
|
|
||||||
|
*dest = 0;
|
||||||
|
return dest;
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
#include "fslc_string.h"
|
||||||
|
|
||||||
|
size_t fslc_strlen(const char *str)
|
||||||
|
{
|
||||||
|
size_t res = 0;
|
||||||
|
for(; *str; ++str) ++res;
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
#include "fslc_string.h"
|
||||||
|
|
||||||
|
int fslc_strncmp(const char *str1, const char *str2, size_t num)
|
||||||
|
{
|
||||||
|
for( ; *str1 && *str1 == *str2 && num > 1; ++str1, ++str2, --num);
|
||||||
|
|
||||||
|
return *((unsigned char *)str1) - *((unsigned char *)str2);
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
#include "fslc_string.h"
|
||||||
|
|
||||||
|
char *_fslc_strncpy_impl(char *dest, const char *src, size_t len);
|
||||||
|
|
||||||
|
char *fslc_strncpy(char *dest, const char *src, size_t len)
|
||||||
|
{
|
||||||
|
_fslc_strncpy_impl(dest, src, len);
|
||||||
|
return dest;
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
#include "stringx.h"
|
||||||
|
|
||||||
|
char *_fslc_strncpy_impl(char *dest, const char *src, size_t len);
|
||||||
|
|
||||||
|
char *fslc_strncpy_e(char *dest, const char *src, size_t len)
|
||||||
|
{
|
||||||
|
char *r = _fslc_strncpy_impl(dest, src, len);
|
||||||
|
return *r ? r + 1: r;
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
char *_fslc_strncpy_impl(char *dest, const char *src, size_t len)
|
||||||
|
{
|
||||||
|
for(; *src && len > 1; ++src, ++dest, --len)
|
||||||
|
*dest = *src;
|
||||||
|
|
||||||
|
*dest = *src;
|
||||||
|
return dest;
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
#include "fslc_string.h"
|
||||||
|
|
||||||
|
char *fslc_strpbrk(const char *str, const char *delim)
|
||||||
|
{
|
||||||
|
for (; *str; ++str)
|
||||||
|
{
|
||||||
|
const char *d;
|
||||||
|
for (d = delim; *d; ++d)
|
||||||
|
if (*str == *d)
|
||||||
|
return (char *)str;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
#include "fslc_string.h"
|
||||||
|
|
||||||
|
size_t fslc_strspn(const char *str, const char *delim)
|
||||||
|
{
|
||||||
|
size_t r;
|
||||||
|
|
||||||
|
for (r = 0; *str; ++str, ++r)
|
||||||
|
{
|
||||||
|
const char *d;
|
||||||
|
for (d = delim; *d; ++d)
|
||||||
|
if (*str == *d) // skip to next if found
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (*d == 0) // inner loop exited on \0 - char was not there
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return r;
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
#include "fslc_string.h"
|
||||||
|
|
||||||
|
char *fslc_strstr(const char *search_in, const char *search_for)
|
||||||
|
{
|
||||||
|
while (*search_in)
|
||||||
|
{
|
||||||
|
char *rc = fslc_strchr(search_in, search_for[0]); // find first char
|
||||||
|
|
||||||
|
if (rc)
|
||||||
|
{
|
||||||
|
const char *si = rc + 1, *sf = search_for + 1; // search strcmp-style from second char
|
||||||
|
for( ; *si && *si == *sf; ++si, ++sf);
|
||||||
|
|
||||||
|
if (*sf == 0) return rc; // end of search-for - found result
|
||||||
|
|
||||||
|
search_in = rc + 1; // not this one, continue from next char
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return NULL; // did not find first char - exit
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL; // reached end of source - did not find
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
#include "fslc_string.h"
|
||||||
|
|
||||||
|
char *fslc_strtok_r(char *str, const char *delim, char **save_p)
|
||||||
|
{
|
||||||
|
if (str)
|
||||||
|
*save_p = str;
|
||||||
|
|
||||||
|
if (*save_p == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
char *r = *save_p + fslc_strspn(*save_p, delim);
|
||||||
|
|
||||||
|
char *p = fslc_strpbrk(r, delim);
|
||||||
|
|
||||||
|
if (p)
|
||||||
|
{
|
||||||
|
*(p++) = 0;
|
||||||
|
*save_p = p;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (*r == 0) r = NULL;
|
||||||
|
*save_p = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
@@ -0,0 +1,347 @@
|
|||||||
|
#include "fslc_stdio.h"
|
||||||
|
|
||||||
|
/* There'a a funny behaviour of va_list and va_arg() macros:
|
||||||
|
* - on x86_64 compiler generates a branch of some sort for each va_arg() macro. Normally it is not a problem,
|
||||||
|
* however it kinda screws up branch coverage analysis. Therefore I decided to move va_arg() accesses into
|
||||||
|
* dedicated functions, minimizing the issue to one untaken branch per access function.
|
||||||
|
* - passing va_list by value works fine on x86_64, but makes some tests to fail on i386. It seems that modifications
|
||||||
|
* done by va_arg() is not passed back to caller. Subsequent calls to va_arg() or access functions returns wrong
|
||||||
|
* values on that platform.
|
||||||
|
* - OK, then. Let's pass pointer to va_list instead. Not so fast. Works fine on i386, but fails to compile on
|
||||||
|
* x86_64. Fine! Wrapping va_list into a dedicated struct and passing around pointer to it.
|
||||||
|
*
|
||||||
|
* Why such a fuss about a few untaken branches in tests? Well, just because! Also, if I ever decide to refactor
|
||||||
|
* _fslc_vfprintf_impl() - the case statement is getting a bit long and messy, it should make things easier if
|
||||||
|
* argument list can be passed around freely (as opposed to using it from single function).
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct va_list_w
|
||||||
|
{
|
||||||
|
va_list arg;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Prototype for printf's internal implementation */
|
||||||
|
static int _fslc_vfprintf_impl(FSLC_FILE *stream, const char *format, struct va_list_w *args);
|
||||||
|
|
||||||
|
|
||||||
|
/* Main exported function */
|
||||||
|
int fslc_vfprintf(FSLC_FILE *stream, const char *format, va_list arg)
|
||||||
|
{
|
||||||
|
if (stream->pre_output) stream->pre_output(stream);
|
||||||
|
|
||||||
|
struct va_list_w argw;
|
||||||
|
va_copy(argw.arg, arg); // can not assign directly, should make a copy
|
||||||
|
|
||||||
|
int res = _fslc_vfprintf_impl(stream, format, &argw);
|
||||||
|
|
||||||
|
va_end(argw.arg); // and free it after use
|
||||||
|
|
||||||
|
if (stream->post_output) stream->post_output(stream);
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Prototype to private FSLIBC function - implemented elsewhere */
|
||||||
|
int _fslc_fputs_impl(const char *str, FSLC_FILE *stream);
|
||||||
|
|
||||||
|
|
||||||
|
/* Prototypes for internal functions */
|
||||||
|
static int _fslc_put_sint_l(signed long v, FSLC_FILE *stream);
|
||||||
|
static int _fslc_put_uint_l(unsigned long v, FSLC_FILE *stream);
|
||||||
|
static int _fslc_put_hex_l(unsigned long v, FSLC_FILE *stream, char alpha);
|
||||||
|
|
||||||
|
static int _get_sint_arg(struct va_list_w *arg);
|
||||||
|
static unsigned _get_uint_arg(struct va_list_w *arg);
|
||||||
|
static long long _get_slonglong_arg(struct va_list_w *arg);
|
||||||
|
static unsigned long long _get_ulonglong_arg(struct va_list_w *arg);
|
||||||
|
static void *_get_ptr_arg(struct va_list_w *arg);
|
||||||
|
|
||||||
|
/* There are some considerations when formatting Integers for output:
|
||||||
|
* - on 32-bit systems integers will mostly be 32 bits long, except when one REALLY
|
||||||
|
* wants to print long long. It should be more optimal to use 32-bit calculations
|
||||||
|
* when possible and invoke 64-bit only when needed. To support that we provide 2
|
||||||
|
* separate implementations.
|
||||||
|
* - on 64-bit systems may be 32 or 64 bits, but there is no real benefit from
|
||||||
|
* using shorter bit size. Hence common implementation.
|
||||||
|
* - this library does not aim to support systems with shorter integer sizes (like 16-bit)
|
||||||
|
* but it it did, it would probably make sense to provide optimized ports for these cases
|
||||||
|
* as well.
|
||||||
|
*
|
||||||
|
* Buffer size calculations:
|
||||||
|
* Max UInt32 fits in 10 bytes (+1 for zero terminator) decimal
|
||||||
|
* 2**32 - 1 == 4294967295z
|
||||||
|
* FFFFFFFFz
|
||||||
|
* 01234567890
|
||||||
|
*
|
||||||
|
* Max UInt64 fits in 10 bytes (and +1 for \0)
|
||||||
|
* 2**64 -1 == 18446744073709551615z
|
||||||
|
* FFFFFFFFFFFFFFFFz
|
||||||
|
* 012345678901234567890
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define BUFSIZE_LONG_LONG_DECIMAL 20
|
||||||
|
#define BUFSIZE_LONG_HEX (__SIZEOF_LONG__ * 2)
|
||||||
|
#define BUFSIZE_LONG_LONG_HEX (__SIZEOF_LONG_LONG__ * 2)
|
||||||
|
#if __SIZEOF_LONG__ == 4
|
||||||
|
|
||||||
|
#define BUFSIZE_LONG_DECIMAL 10
|
||||||
|
static int _fslc_put_sint_ll(signed long long v, FSLC_FILE *stream);
|
||||||
|
static int _fslc_put_uint_ll(unsigned long long v, FSLC_FILE *stream);
|
||||||
|
static int _fslc_put_hex_ll(unsigned long long v, FSLC_FILE *stream, char alpha);
|
||||||
|
|
||||||
|
#define _get_slong_arg _get_sint_arg
|
||||||
|
#define _get_ulong_arg _get_uint_arg
|
||||||
|
|
||||||
|
#elif __SIZEOF_LONG__ == 8
|
||||||
|
|
||||||
|
#define BUFSIZE_LONG_DECIMAL BUFSIZE_LONG_LONG_DECIMAL
|
||||||
|
#define _fslc_put_sint_ll _fslc_put_sint_l
|
||||||
|
#define _fslc_put_uint_ll _fslc_put_uint_l
|
||||||
|
#define _fslc_put_hex_ll _fslc_put_hex_l
|
||||||
|
|
||||||
|
#define _get_slong_arg _get_slonglong_arg
|
||||||
|
#define _get_ulong_arg _get_ulonglong_arg
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define FLAG_LONG 1
|
||||||
|
#define FLAG_VERYLONG 3
|
||||||
|
|
||||||
|
static int _fslc_vfprintf_impl(FSLC_FILE *stream, const char *format, struct va_list_w *arg)
|
||||||
|
{
|
||||||
|
int res = 0;
|
||||||
|
int pr;
|
||||||
|
const char *c;
|
||||||
|
|
||||||
|
for (c = format; *c; ++c)
|
||||||
|
{
|
||||||
|
if (*c == '%')
|
||||||
|
{
|
||||||
|
int flags = 0;
|
||||||
|
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
++c;
|
||||||
|
switch (*c)
|
||||||
|
{
|
||||||
|
case 's':
|
||||||
|
pr = _fslc_fputs_impl((const char *)_get_ptr_arg(arg), stream);
|
||||||
|
if (pr < 0) return pr;
|
||||||
|
res += pr;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'c':
|
||||||
|
pr = stream->putc(_get_sint_arg(arg), stream);
|
||||||
|
if (pr < 0) return pr;
|
||||||
|
++res;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '%':
|
||||||
|
pr = stream->putc('%', stream);
|
||||||
|
if (pr < 0) return pr;
|
||||||
|
++res;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'i':
|
||||||
|
case 'd':
|
||||||
|
if ((flags & FLAG_VERYLONG) == FLAG_VERYLONG)
|
||||||
|
pr = _fslc_put_sint_ll(_get_slonglong_arg(arg), stream);
|
||||||
|
else if (flags & FLAG_LONG)
|
||||||
|
pr = _fslc_put_sint_l(_get_slong_arg(arg), stream);
|
||||||
|
else
|
||||||
|
pr = _fslc_put_sint_l(_get_sint_arg(arg), stream);
|
||||||
|
|
||||||
|
if (pr < 0) return pr;
|
||||||
|
res += pr;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'u':
|
||||||
|
if ((flags & FLAG_VERYLONG) == FLAG_VERYLONG)
|
||||||
|
pr = _fslc_put_uint_ll(_get_ulonglong_arg(arg), stream);
|
||||||
|
else if (flags & FLAG_LONG)
|
||||||
|
pr = _fslc_put_uint_l(_get_ulong_arg(arg), stream);
|
||||||
|
else
|
||||||
|
pr = _fslc_put_uint_l(_get_uint_arg(arg), stream);
|
||||||
|
|
||||||
|
if (pr < 0) return pr;
|
||||||
|
res += pr;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'x':
|
||||||
|
if ((flags & FLAG_VERYLONG) == FLAG_VERYLONG)
|
||||||
|
pr = _fslc_put_hex_ll(_get_ulonglong_arg(arg), stream, 'a');
|
||||||
|
else if (flags & FLAG_LONG)
|
||||||
|
pr = _fslc_put_hex_l(_get_ulong_arg(arg), stream, 'a');
|
||||||
|
else
|
||||||
|
pr = _fslc_put_hex_l(_get_uint_arg(arg), stream, 'a');
|
||||||
|
|
||||||
|
if (pr < 0) return pr;
|
||||||
|
res += pr;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'X':
|
||||||
|
if ((flags & FLAG_VERYLONG) == FLAG_VERYLONG)
|
||||||
|
pr = _fslc_put_hex_ll(_get_ulonglong_arg(arg), stream, 'A');
|
||||||
|
else if (flags & FLAG_LONG)
|
||||||
|
pr = _fslc_put_hex_l(_get_ulong_arg(arg), stream, 'A');
|
||||||
|
else
|
||||||
|
pr = _fslc_put_hex_l(_get_uint_arg(arg), stream, 'A');
|
||||||
|
|
||||||
|
if (pr < 0) return pr;
|
||||||
|
res += pr;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'p':
|
||||||
|
pr = _fslc_fputs_impl("0x", stream);
|
||||||
|
if (pr < 0) return pr;
|
||||||
|
res += pr;
|
||||||
|
|
||||||
|
pr = _fslc_put_hex_l(_get_ulong_arg(arg), stream, 'a');
|
||||||
|
|
||||||
|
if (pr < 0) return pr;
|
||||||
|
res += pr;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'l':
|
||||||
|
if (flags & FLAG_LONG)
|
||||||
|
flags |= FLAG_VERYLONG;
|
||||||
|
else
|
||||||
|
flags |= FLAG_LONG;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
pr = stream->putc(*c, stream);
|
||||||
|
if (pr < 0) return pr;
|
||||||
|
++res;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _get_sint_arg(struct va_list_w *arg)
|
||||||
|
{
|
||||||
|
return va_arg(arg->arg, signed int);
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned _get_uint_arg(struct va_list_w *arg)
|
||||||
|
{
|
||||||
|
return va_arg(arg->arg, unsigned int);
|
||||||
|
}
|
||||||
|
|
||||||
|
static long long _get_slonglong_arg(struct va_list_w *arg)
|
||||||
|
{
|
||||||
|
return va_arg(arg->arg, signed long long);
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned long long _get_ulonglong_arg(struct va_list_w *arg)
|
||||||
|
{
|
||||||
|
return va_arg(arg->arg, unsigned long long);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void *_get_ptr_arg(struct va_list_w *arg)
|
||||||
|
{
|
||||||
|
return va_arg(arg->arg, void *);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _fslc_put_sint_l(signed long v, FSLC_FILE *stream)
|
||||||
|
{
|
||||||
|
if (v < 0)
|
||||||
|
{
|
||||||
|
int pr = stream->putc('-', stream);
|
||||||
|
if (pr < 0) return pr;
|
||||||
|
|
||||||
|
pr = _fslc_put_uint_l(-v, stream);
|
||||||
|
if (pr < 0) return pr;
|
||||||
|
|
||||||
|
return pr+1;
|
||||||
|
} else
|
||||||
|
return _fslc_put_uint_l(v, stream);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _fslc_put_uint_l(unsigned long v, FSLC_FILE *stream)
|
||||||
|
{
|
||||||
|
char dbuff[BUFSIZE_LONG_DECIMAL+1], *p;
|
||||||
|
|
||||||
|
dbuff[BUFSIZE_LONG_DECIMAL] = 0;
|
||||||
|
|
||||||
|
for (p = dbuff + BUFSIZE_LONG_DECIMAL; v ; v /= 10)
|
||||||
|
{
|
||||||
|
*(--p) = (v % 10) + '0';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*p == 0) *(--p) = '0';
|
||||||
|
|
||||||
|
return _fslc_fputs_impl(p, stream);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _fslc_put_hex_l(unsigned long v, FSLC_FILE *stream, char alpha)
|
||||||
|
{
|
||||||
|
char dbuff[BUFSIZE_LONG_HEX+1], *p;
|
||||||
|
|
||||||
|
dbuff[BUFSIZE_LONG_HEX] = 0;
|
||||||
|
|
||||||
|
for (p = dbuff + BUFSIZE_LONG_HEX; v ; v >>= 4)
|
||||||
|
{
|
||||||
|
char digit = (v & 0xF);
|
||||||
|
*(--p) = digit < 10 ? digit + '0' : digit - 10 + alpha;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*p == 0) *(--p) = '0';
|
||||||
|
|
||||||
|
return _fslc_fputs_impl(p, stream);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if __SIZEOF_LONG__ == 4
|
||||||
|
|
||||||
|
static int _fslc_put_sint_ll(signed long long v, FSLC_FILE *stream)
|
||||||
|
{
|
||||||
|
if (v < 0)
|
||||||
|
{
|
||||||
|
int pr = stream->putc('-', stream);
|
||||||
|
if (pr < 0) return pr;
|
||||||
|
|
||||||
|
pr = _fslc_put_uint_ll(-v, stream);
|
||||||
|
if (pr < 0) return pr;
|
||||||
|
|
||||||
|
return pr+1;
|
||||||
|
} else
|
||||||
|
return _fslc_put_uint_ll(v, stream);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _fslc_put_uint_ll(unsigned long long v, FSLC_FILE *stream)
|
||||||
|
{
|
||||||
|
char dbuff[BUFSIZE_LONG_LONG_DECIMAL+1], *p;
|
||||||
|
|
||||||
|
dbuff[BUFSIZE_LONG_LONG_DECIMAL] = 0;
|
||||||
|
|
||||||
|
for (p = dbuff + BUFSIZE_LONG_LONG_DECIMAL; v ; v /= 10)
|
||||||
|
{
|
||||||
|
*(--p) = (v % 10) + '0';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*p == 0) *(--p) = '0';
|
||||||
|
|
||||||
|
return _fslc_fputs_impl(p, stream);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _fslc_put_hex_ll(unsigned long long v, FSLC_FILE *stream, char alpha)
|
||||||
|
{
|
||||||
|
char dbuff[BUFSIZE_LONG_LONG_HEX+1], *p;
|
||||||
|
|
||||||
|
dbuff[BUFSIZE_LONG_LONG_HEX] = 0;
|
||||||
|
|
||||||
|
for (p = dbuff + BUFSIZE_LONG_LONG_HEX; v ; v >>= 4)
|
||||||
|
{
|
||||||
|
char digit = (v & 0xF);
|
||||||
|
*(--p) = digit < 10 ? digit + '0' : digit - 10 + alpha;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*p == 0) *(--p) = '0';
|
||||||
|
|
||||||
|
return _fslc_fputs_impl(p, stream);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
#include "fslc_stdio.h"
|
||||||
|
|
||||||
|
int fslc_vprintf(const char *format, va_list arg)
|
||||||
|
{
|
||||||
|
return fslc_vfprintf(fslc_stdout, format, arg);
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "regs.hpp"
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
int UartStreamPutc(int c, FILE *) {
|
||||||
|
UartPutc(static_cast<char>(c));
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
FILE g_uartStdout = { nullptr, UartStreamPutc, nullptr, nullptr, nullptr, -1 };
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
void InitializeLibc() {
|
||||||
|
stdout = &g_uartStdout;
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
void InitializeLibc();
|
||||||
@@ -1,7 +1,12 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "libc_platform.hpp"
|
||||||
#include "regs.hpp"
|
#include "regs.hpp"
|
||||||
|
|
||||||
extern "C" void main() {
|
extern "C" void main() {
|
||||||
UartPuts("[bpmpfw]: Hello from BPMP-FW\n");
|
InitializeLibc();
|
||||||
|
|
||||||
|
printf("[hoc-bpmpfw] Starting bpmpfw\n");
|
||||||
|
|
||||||
for (;;);
|
for (;;);
|
||||||
}
|
}
|
||||||
@@ -7,6 +7,11 @@ using u32 = std::uint32_t;
|
|||||||
|
|
||||||
#define MMIO32(addr) (*reinterpret_cast<volatile u32 *>(addr))
|
#define MMIO32(addr) (*reinterpret_cast<volatile u32 *>(addr))
|
||||||
|
|
||||||
|
constexpr u32 FwRamStart = 0x40004000;
|
||||||
|
constexpr u32 FwRamEnd = 0x4000C000;
|
||||||
|
constexpr u32 WorkRamStart = FwRamEnd;
|
||||||
|
constexpr u32 WorkRamEnd = 0x40010000;
|
||||||
|
|
||||||
constexpr u32 FlowCtlrBase = 0x60007000;
|
constexpr u32 FlowCtlrBase = 0x60007000;
|
||||||
constexpr u32 FlowCtlrHaltCopEvents = 0x004;
|
constexpr u32 FlowCtlrHaltCopEvents = 0x004;
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
"title_id": "0x00FF0000636C6BFF",
|
"title_id": "0x00FF0000636C6BFF",
|
||||||
"title_id_range_min": "0x00FF0000636C6BFF",
|
"title_id_range_min": "0x00FF0000636C6BFF",
|
||||||
"title_id_range_max": "0x00FF0000636C6BFF",
|
"title_id_range_max": "0x00FF0000636C6BFF",
|
||||||
"main_thread_stack_size": "0x0000C000",
|
"main_thread_stack_size": "0x0000F000",
|
||||||
"main_thread_priority": 16,
|
"main_thread_priority": 16,
|
||||||
"default_cpu_id": 3,
|
"default_cpu_id": 3,
|
||||||
"process_category": 1,
|
"process_category": 1,
|
||||||
|
|||||||
@@ -182,6 +182,7 @@ namespace board {
|
|||||||
if (R_FAILED(bpmpfwRc)) {
|
if (R_FAILED(bpmpfwRc)) {
|
||||||
fileUtils::LogLine("[bpmp] StartBpmfwExecution failed: 0x%x", bpmpfwRc);
|
fileUtils::LogLine("[bpmp] StartBpmfwExecution failed: 0x%x", bpmpfwRc);
|
||||||
}
|
}
|
||||||
|
bpmp::StartSleepMonitorThread();
|
||||||
|
|
||||||
// PMC exosphere check
|
// PMC exosphere check
|
||||||
SecmonArgs args = {};
|
SecmonArgs args = {};
|
||||||
@@ -211,6 +212,8 @@ namespace board {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Exit() {
|
void Exit() {
|
||||||
|
bpmp::StopSleepMonitorThread();
|
||||||
|
|
||||||
if (HOSSVC_HAS_CLKRST) {
|
if (HOSSVC_HAS_CLKRST) {
|
||||||
clkrstExit();
|
clkrstExit();
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -64,6 +64,38 @@ namespace bpmp {
|
|||||||
return *reinterpret_cast<volatile u32 *>(base_va + offset);
|
return *reinterpret_cast<volatile u32 *>(base_va + offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Late in the boot chain, otherwise a fatal will occur from invalid boot state
|
||||||
|
constexpr u32 pscDependencies[] = { PscPmModuleId_Olsc };
|
||||||
|
constexpr PscPmModuleId PscModuleId = (PscPmModuleId)705;
|
||||||
|
|
||||||
|
PscPmModule s_pscModule;
|
||||||
|
bool s_pscPrepared = false;
|
||||||
|
Thread s_pscThread;
|
||||||
|
bool s_pscExit = false;
|
||||||
|
|
||||||
|
void PscThreadFunc(void *) {
|
||||||
|
while (!s_pscExit) {
|
||||||
|
Result rc = eventWait(&s_pscModule.event, 1'000'000'000ULL);
|
||||||
|
if (R_FAILED(rc)) {
|
||||||
|
continue; // Timeout
|
||||||
|
}
|
||||||
|
|
||||||
|
PscPmState state;
|
||||||
|
u32 flags;
|
||||||
|
rc = pscPmModuleGetRequest(&s_pscModule, &state, &flags);
|
||||||
|
if (R_SUCCEEDED(rc)) {
|
||||||
|
if (state == PscPmState_Awake) {
|
||||||
|
Result wrc = StartBpmfwExecution();
|
||||||
|
if (R_FAILED(wrc)) {
|
||||||
|
fileUtils::LogLine("[bpmp] restart after wake failed: 0x%x", wrc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pscPmModuleAcknowledge(&s_pscModule, state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
Result StartBpmfwExecution() {
|
Result StartBpmfwExecution() {
|
||||||
@@ -137,4 +169,48 @@ namespace bpmp {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void StartSleepMonitorThread() {
|
||||||
|
if (!IsPatchedExosphere()) {
|
||||||
|
fileUtils::LogLine("[bpmp] Cant start BPMP without exosphere patch");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result rc = pscmInitialize();
|
||||||
|
if (R_FAILED(rc)) {
|
||||||
|
fileUtils::LogLine("[bpmp] pscmInitialize failed: 0x%x", rc);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = pscmGetPmModule(&s_pscModule, PscModuleId, pscDependencies, sizeof(pscDependencies) / sizeof(u32), true);
|
||||||
|
if (R_FAILED(rc)) {
|
||||||
|
fileUtils::LogLine("[bpmp] pscmGetPmModule failed: 0x%x", rc);
|
||||||
|
pscmExit();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
s_pscPrepared = true;
|
||||||
|
|
||||||
|
rc = threadCreate(&s_pscThread, PscThreadFunc, nullptr, NULL, 0x1000, 0x10, 3);
|
||||||
|
if (R_FAILED(rc)) {
|
||||||
|
fileUtils::LogLine("[bpmp] failed to create psc thread: 0x%x", rc);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
threadStart(&s_pscThread);
|
||||||
|
}
|
||||||
|
|
||||||
|
void StopSleepMonitorThread() {
|
||||||
|
if (!s_pscPrepared) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
s_pscExit = true;
|
||||||
|
eventFire(&s_pscModule.event);
|
||||||
|
threadWaitForExit(&s_pscThread);
|
||||||
|
threadClose(&s_pscThread);
|
||||||
|
|
||||||
|
pscPmModuleFinalize(&s_pscModule);
|
||||||
|
pscPmModuleClose(&s_pscModule);
|
||||||
|
pscmExit();
|
||||||
|
s_pscPrepared = false;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace bpmp
|
} // namespace bpmp
|
||||||
@@ -20,4 +20,7 @@
|
|||||||
|
|
||||||
namespace bpmp {
|
namespace bpmp {
|
||||||
Result StartBpmfwExecution();
|
Result StartBpmfwExecution();
|
||||||
|
|
||||||
|
void StartSleepMonitorThread();
|
||||||
|
void StopSleepMonitorThread();
|
||||||
}
|
}
|
||||||
@@ -103,7 +103,7 @@ namespace fileUtils {
|
|||||||
va_list args;
|
va_list args;
|
||||||
va_start(args, format);
|
va_start(args, format);
|
||||||
|
|
||||||
char buff[0xfff];
|
char buff[0x200];
|
||||||
int len = vsnprintf(buff, sizeof(buff), format, args);
|
int len = vsnprintf(buff, sizeof(buff), format, args);
|
||||||
va_end(args);
|
va_end(args);
|
||||||
|
|
||||||
|
|||||||
@@ -38,7 +38,7 @@
|
|||||||
#include "mgr/clock_manager.hpp"
|
#include "mgr/clock_manager.hpp"
|
||||||
|
|
||||||
|
|
||||||
#define INNER_HEAP_SIZE 0x40000
|
#define INNER_HEAP_SIZE 0x48000
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
void virtmemSetup(void);
|
void virtmemSetup(void);
|
||||||
|
|||||||
@@ -30,7 +30,6 @@
|
|||||||
#include <i2c.h>
|
#include <i2c.h>
|
||||||
|
|
||||||
#include "../board/board.hpp"
|
#include "../board/board.hpp"
|
||||||
#include "../bpmp/bpmp.hpp"
|
|
||||||
#include "../display/aula.hpp"
|
#include "../display/aula.hpp"
|
||||||
#include "../display/display_refresh_rate.hpp"
|
#include "../display/display_refresh_rate.hpp"
|
||||||
#include "../file/config.hpp"
|
#include "../file/config.hpp"
|
||||||
@@ -41,7 +40,6 @@
|
|||||||
#include "../hos/process_management.hpp"
|
#include "../hos/process_management.hpp"
|
||||||
#include "../i2c/i2cDrv.h"
|
#include "../i2c/i2cDrv.h"
|
||||||
#include "../ipc/ipc_service.hpp"
|
#include "../ipc/ipc_service.hpp"
|
||||||
#include "../mapping/mem_map.hpp"
|
|
||||||
#include "../soc/gm20b.hpp"
|
#include "../soc/gm20b.hpp"
|
||||||
#include "../util/lockable_mutex.h"
|
#include "../util/lockable_mutex.h"
|
||||||
#include "clock_manager.hpp"
|
#include "clock_manager.hpp"
|
||||||
@@ -357,23 +355,6 @@ namespace clockManager {
|
|||||||
if (++tick > 10) {
|
if (++tick > 10) {
|
||||||
tick = 0;
|
tick = 0;
|
||||||
|
|
||||||
// Restart BPMP after sleep.
|
|
||||||
if (IsPatchedExosphere()) {
|
|
||||||
svcSleepThread(1'500'000'000);
|
|
||||||
constexpr u32 FlowCtlrPhysBase = 0x60007000;
|
|
||||||
constexpr u32 FlowCtlrHaltCopEvents = 0x004;
|
|
||||||
constexpr u32 HaltCopEventsModeShift = 29;
|
|
||||||
constexpr u32 HaltCopEventsModeStop = 2;
|
|
||||||
|
|
||||||
u32 haltReg = SmcReadWriteRegister(FlowCtlrPhysBase + FlowCtlrHaltCopEvents, 0, 0);
|
|
||||||
if ((haltReg >> HaltCopEventsModeShift) == HaltCopEventsModeStop) {
|
|
||||||
Result rc = bpmp::StartBpmfwExecution();
|
|
||||||
if (R_FAILED(rc)) {
|
|
||||||
fileUtils::LogLine("[bpmp] restart after sleep failed: 0x%x", rc);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (config::GetConfigValue(HocClkConfigValue_BatteryChargeCurrent)) {
|
if (config::GetConfigValue(HocClkConfigValue_BatteryChargeCurrent)) {
|
||||||
I2c_Bq24193_SetFastChargeCurrentLimit(config::GetConfigValue(HocClkConfigValue_BatteryChargeCurrent));
|
I2c_Bq24193_SetFastChargeCurrentLimit(config::GetConfigValue(HocClkConfigValue_BatteryChargeCurrent));
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in new issue
Block a user