diff --git a/ARM.CMSIS-Compiler.pdsc b/ARM.CMSIS-Compiler.pdsc
index c16f249..e0e3b3e 100644
--- a/ARM.CMSIS-Compiler.pdsc
+++ b/ARM.CMSIS-Compiler.pdsc
@@ -15,6 +15,8 @@
Active Development ...
+ CLANG:
+ - Added standard I/O stream support for LLVM-libc
@@ -245,7 +247,7 @@
-
+
Standard C Library Retarget Core
diff --git a/source/core/clang/retarget_syscalls.c b/source/core/clang/retarget_syscalls.c
index 96260e3..834b74a 100644
--- a/source/core/clang/retarget_syscalls.c
+++ b/source/core/clang/retarget_syscalls.c
@@ -41,6 +41,181 @@
#endif
#endif
+#ifndef STDIN_ECHO
+#define STDIN_ECHO 0 /* STDIN: echo to STDOUT */
+#endif
+#ifndef STDOUT_CR_LF
+#define STDOUT_CR_LF 0 /* STDOUT: add CR for LF */
+#endif
+#ifndef STDERR_CR_LF
+#define STDERR_CR_LF 0 /* STDERR: add CR for LF */
+#endif
+
+#if defined(__LLVM_LIBC__)
+
+/* Symbols used as cookie values to identify standard I/O stream */
+void *__llvm_libc_stdin_cookie = NULL;
+void *__llvm_libc_stdout_cookie = NULL;
+void *__llvm_libc_stderr_cookie = NULL;
+
+/**
+ Write bytes to a standard output stream.
+
+ Called by LLVM-libc for all stdout/stderr writes. The cookie parameter
+ identifies the target stream: it matches the address of the
+ __llvm_libc_stdout_cookie or __llvm_libc_stderr_cookie symbol.
+
+ \param[in] cookie Stream identifier
+ \param[in] buf Pointer to data buffer
+ \param[in] size Number of bytes to write
+ \return Number of bytes written, or -1 on error.
+*/
+__attribute__((weak))
+ssize_t __llvm_libc_stdio_write(void *cookie, const char *buf, size_t size) {
+#if (defined(RTE_CMSIS_Compiler_STDOUT) || defined(RTE_CMSIS_Compiler_STDERR))
+ int ch;
+ ssize_t sz = 0;
+ const char *p = buf;
+#else
+ (void)cookie;
+ (void)buf;
+ (void)size;
+#endif
+
+#if defined(RTE_CMSIS_Compiler_STDOUT)
+ if (cookie == &__llvm_libc_stdout_cookie) {
+ while (sz < (ssize_t)size) {
+ ch = *p++;
+#if (STDOUT_CR_LF != 0)
+ if (ch == '\n') {
+ if (stdout_putchar('\r') == -1) {
+ break;
+ }
+ }
+#endif
+ if (stdout_putchar(ch) == -1) {
+ break;
+ }
+ sz++;
+ }
+ return (sz);
+ }
+#endif
+
+#if defined(RTE_CMSIS_Compiler_STDERR)
+ if (cookie == &__llvm_libc_stderr_cookie) {
+ while (sz < (ssize_t)size) {
+ ch = *p++;
+#if (STDERR_CR_LF != 0)
+ if (ch == '\n') {
+ if (stderr_putchar('\r') == -1) {
+ break;
+ }
+ }
+#endif
+ if (stderr_putchar(ch) == -1) {
+ break;
+ }
+ sz++;
+ }
+ return (sz);
+ }
+#endif
+ /* Not implemented */
+ return (-1);
+}
+
+/**
+ Read bytes from stdin.
+
+ Called by LLVM-libc for all stdin reads. The cookie parameter matches the
+ address of the __llvm_libc_stdin_cookie symbol.
+
+ \param[in] cookie Stream identifier
+ \param[out] buf Pointer to data buffer
+ \param[in] size Maximum number of bytes to read
+ \return Number of bytes read (> 0), 0 on end of input,
+ or a negative errno value on error.
+*/
+__attribute__((weak))
+ssize_t __llvm_libc_stdio_read(void *cookie, char *buf, size_t size) {
+#if defined(RTE_CMSIS_Compiler_STDIN)
+ int ch;
+ ssize_t sz = 0;
+ char *p = buf;
+#else
+ (void)cookie;
+ (void)buf;
+ (void)size;
+#endif
+
+#if defined(RTE_CMSIS_Compiler_STDIN)
+ if (cookie == &__llvm_libc_stdin_cookie) {
+ while (sz < (ssize_t)size) {
+ ch = stdin_getchar();
+ if (ch < 0) {
+ break;
+ }
+ *p++ = (char)ch;
+#if (STDIN_ECHO != 0)
+ stdout_putchar(ch);
+#endif
+ sz++;
+ }
+ return sz;
+ }
+#endif
+ /* Not implemented */
+ return (-1);
+}
+
+/**
+ Terminate a process.
+
+ Called by LLVM-libc for all process termination.
+ The status parameter is the exit code passed to the exit() function. This
+ implementation does not support process termination, so it simply enters
+ an infinite loop.
+
+ \param[in] status Exit code passed to exit()
+*/
+__attribute__((weak, __noreturn__))
+void __llvm_libc_exit(int status) {
+ (void)status;
+ for (;;) { ; }
+}
+
+/**
+ Set up the exceptions table and enable relevant interrupts.
+
+ This function overrides crt0's _platform_setup_exceptions which sets VTOR
+ to its own minimal 16-entry vector table, breaking device IRQ handlers.
+ Restoring VTOR to the full CMSIS vector table (256 entries) ensures device-
+ specific interrupt vectors are resolved correctly.
+*/
+__attribute__((weak))
+void _platform_setup_exceptions (void) {}
+
+/**
+ Set up the Memory Management Unit and caches.
+
+ This function overrides crt0's _platform_setup_memory which may override settings
+ applied in vendor specific SystemInit.
+*/
+__attribute__((weak))
+void _platform_setup_memory (void) {}
+
+/**
+ Set up architecture extensions that require special initialization.
+
+ This function overrides crt0's _platform_setup_arch_extensions which may override
+ settings applied in vendor specific SystemInit.
+*/
+__attribute__((weak))
+void _platform_setup_arch_extensions (void) {}
+
+#elif defined(__PICOLIBC_VERSION__)
+
#if defined(RTE_CMSIS_Compiler_STDIN)
/**
Get a character from the stdio
@@ -93,7 +268,6 @@ static FILE __stdout = FDEV_SETUP_STREAM(stdout_putc,
FILE *const stdout = &__stdout;
#endif
-
#if defined(RTE_CMSIS_Compiler_STDERR)
/**
Put a character to the stderr
@@ -125,3 +299,4 @@ __attribute__((weak, __noreturn__))
void _exit (int status) {
for(;;){ ; }
}
+#endif /* __LLVM_LIBC__ */