]> granicus.if.org Git - esp-idf/commitdiff
vfs and newlib: small fixes
authorIvan Grokhotkov <ivan@espressif.com>
Tue, 25 Oct 2016 14:12:07 +0000 (22:12 +0800)
committerIvan Grokhotkov <ivan@espressif.com>
Thu, 27 Oct 2016 09:19:39 +0000 (17:19 +0800)
- spaces->tabs in tasks.c
- update vfs_uart.c to use per-UART locks
- add license to vfs_uart.c
- allocate separate streams for stdout, stdin, stderr, so that they can be independently reassigned
- fix build system test failure

components/esp32/cpu_start.c
components/esp32/include/soc/cpu.h
components/newlib/component.mk
components/newlib/locks.c [moved from components/esp32/syscalls.c with 54% similarity]
components/newlib/platform_include/esp_newlib.h [new file with mode: 0644]
components/newlib/syscall_table.c [new file with mode: 0644]
components/newlib/syscalls.c [new file with mode: 0644]
components/newlib/time.c [new file with mode: 0644]

index a649764ab554be1ad39b71a382e3d2fb189299b2..cbac54d7c3b875621725c3a62962cc9a9c64ea68 100644 (file)
@@ -42,7 +42,7 @@
 #include "esp_spi_flash.h"
 #include "esp_ipc.h"
 #include "esp_log.h"
-
+#include "esp_newlib.h"
 #include "esp_brownout.h"
 #include "esp_int_wdt.h"
 #include "esp_task_wdt.h"
@@ -160,7 +160,7 @@ void start_cpu0_default(void)
 #if CONFIG_TASK_WDT
     esp_task_wdt_init();
 #endif
-    ets_setup_syscalls();
+    esp_setup_syscalls();
     do_global_ctors();
     esp_ipc_init();
     spi_flash_init();
index c74ba317c89662bce53bf9434db1fd9ab3e0acb5..ee2907493e64efbc2c908bb39e5feb422d192e72 100644 (file)
@@ -15,6 +15,9 @@
 #ifndef _SOC_CPU_H
 #define _SOC_CPU_H
 
+#include <stdint.h>
+#include <stdbool.h>
+#include <stddef.h>
 #include "xtensa/corebits.h"
 
 /* C macros for xtensa special register read/write/exchange */
index 7c8c74debebdc731986ac0cfd3145b13c97141b1..3731b5ef0e18a0f17512749b5c0039359f512e84 100644 (file)
@@ -1,8 +1,5 @@
-COMPONENT_ADD_LDFLAGS := $(abspath lib/libc.a) $(abspath lib/libm.a)
+COMPONENT_ADD_LDFLAGS := $(abspath lib/libc.a) $(abspath lib/libm.a) -lnewlib
 
-
-define COMPONENT_BUILDRECIPE
-       #Nothing to do; this does not generate a library.
-endef
+COMPONENT_ADD_INCLUDEDIRS := include platform_include
 
 include $(IDF_PATH)/make/component_common.mk
similarity index 54%
rename from components/esp32/syscalls.c
rename to components/newlib/locks.c
index 052605ee3eed3ad3207d5d0e5ed7d5553bd17e9a..21b974a1f197b4a950111f28a54e3314dd6fbe07 100644 (file)
@@ -3,7 +3,7 @@
 // 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
 // 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 <string.h>
-#include <stdbool.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <errno.h>
-#include <sys/reent.h>
+
+#include <sys/lock.h>
 #include <stdlib.h>
+#include <sys/reent.h>
 #include "esp_attr.h"
-#include "rom/libc_stubs.h"
-#include "rom/uart.h"
 #include "soc/cpu.h"
 #include "freertos/FreeRTOS.h"
 #include "freertos/semphr.h"
 #include "freertos/portmacro.h"
 #include "freertos/task.h"
 
-void abort() {
-    do
-    {
-        __asm__ ("break 0,0");
-        *((int*) 0) = 0;
-    } while(true);
-}
-
-void* _malloc_r(struct _reent *r, size_t size) {
-    return pvPortMalloc(size);
-}
-
-void _free_r(struct _reent *r, void* ptr) {
-    return vPortFree(ptr);
-}
-
-void* _realloc_r(struct _reent *r, void* ptr, size_t size) {
-       void* new_chunk;
-       if (size == 0) {
-               if (ptr) {
-                       vPortFree(ptr);
-               }
-               return NULL;
-       }
-
-       new_chunk = pvPortMalloc(size);
-       if (new_chunk && ptr) {
-               memcpy(new_chunk, ptr, size);
-               vPortFree(ptr);
-       }
-       // realloc behaviour: don't free original chunk if alloc failed
-       return new_chunk;
-}
-
-void* _calloc_r(struct _reent *r, size_t count, size_t size) {
-    void* result = pvPortMalloc(count * size);
-    if (result)
-    {
-       memset(result, 0, count * size);
-    }
-    return result;
-}
-
-int _system_r(struct _reent *r, const char *str) {
-    abort();
-    return 0;
-}
-
-int _rename_r(struct _reent *r, const char *src, const char *dst) {
-    abort();
-    return 0;
-}
-
-clock_t _times_r(struct _reent *r, struct tms *ptms) {
-    abort();
-    return 0;
-}
-
-// TODO: read time from RTC
-int _gettimeofday_r(struct _reent *r, struct timeval *tv, void *tz) {
-    abort();
-    return 0;
-}
-
-void _raise_r(struct _reent *r) {
-    abort();
-}
-
-int _unlink_r(struct _reent *r, const char *path) {
-    abort();
-    return 0;
-}
-
-int _link_r(struct _reent *r, const char* n1, const char* n2) {
-    abort();
-    return 0;
-}
-
-int _stat_r(struct _reent *r, const char * path, struct stat * st) {
-    return 0;
-}
-
-int _fstat_r(struct _reent *r, int fd, struct stat * st) {
-       st->st_mode = S_IFCHR;
-    return 0;
-}
-
-void* _sbrk_r(struct _reent *r, ptrdiff_t sz) {
-    abort();
-    return 0;
-}
-
-int _getpid_r(struct _reent *r) {
-    abort();
-    return 0;
-}
-
-int _kill_r(struct _reent *r, int pid, int sig) {
-    abort();
-    return 0;
-}
-
-void _exit_r(struct _reent *r, int e) {
-    abort();
-}
-
-int _close_r(struct _reent *r, int fd) {
-    return 0;
-}
-
-int _open_r(struct _reent *r, const char * path, int flags, int mode) {
-    return 0;
-}
-
-void _exit(int __status) {
-    abort();
-}
-
-ssize_t _write_r(struct _reent *r, int fd, const void * data, size_t size) {
-    const char *data_c = (const char *)data;
-    if (fd == STDOUT_FILENO) {
-        static _lock_t stdout_lock; /* lazily initialised */
-        /* Even though newlib does stream locking on stdout, we need
-           a dedicated stdout UART lock...
-
-           This is because each task has its own _reent structure with
-           unique FILEs for stdin/stdout/stderr, so these are
-           per-thread (lazily initialised by __sinit the first time a
-           stdio function is used, see findfp.c:235.
-
-           It seems like overkill to allocate a FILE-per-task and lock
-           a thread-local stream, but I see no easy way to fix this
-           (pre-__sinit_, tasks have "fake" FILEs ie __sf_fake_stdout
-           which aren't fully valid.)
-        */
-        _lock_acquire_recursive(&stdout_lock);
-        for (size_t i = 0; i < size; i++) {
-#if CONFIG_NEWLIB_STDOUT_ADDCR
-            if (data_c[i]=='\n') {
-                uart_tx_one_char('\r');
-            }
-#endif
-            uart_tx_one_char(data_c[i]);
-        }
-        _lock_release_recursive(&stdout_lock);
-    }
-    return size;
-}
-
-_off_t _lseek_r(struct _reent *r, int fd, _off_t size, int mode) {
-    return 0;
-}
-
-// TODO: implement reading from UART
-ssize_t _read_r(struct _reent *r, int fd, void * dst, size_t size) {
-    return 0;
-}
-
 /* Notes on our newlib lock implementation:
  *
  * - Use FreeRTOS mutex semaphores as locks.
@@ -369,89 +205,3 @@ void IRAM_ATTR _lock_release(_lock_t *lock) {
 void IRAM_ATTR _lock_release_recursive(_lock_t *lock) {
     lock_release_generic(lock, queueQUEUE_TYPE_RECURSIVE_MUTEX);
 }
-
-// This function is not part on newlib API, it is defined in libc/stdio/local.h
-// It is called as part of _reclaim_reent via a pointer in __cleanup member 
-// of struct _reent.
-// This function doesn't call _fclose_r for _stdin, _stdout, _stderr members
-// of struct reent. Not doing so causes a memory leak each time a task is
-// terminated. We replace __cleanup member with _extra_cleanup_r (below) to work
-// around this.
-extern void _cleanup_r(struct _reent* r);
-
-void _extra_cleanup_r(struct _reent* r)
-{
-    _cleanup_r(r);
-    _fclose_r(r, r->_stdout);
-    _fclose_r(r, r->_stderr);
-    _fclose_r(r, r->_stdin);
-}
-
-static struct _reent s_reent;
-
-/*
- General ToDo that the Xtensa newlib support code did but we do not: Close every open fd a running task had when the task
- is killed. Do we want that too? - JD
-*/
-
-extern int _printf_float(struct _reent *rptr,
-               void *pdata,
-               FILE * fp,
-               int (*pfunc) (struct _reent *, FILE *, _CONST char *, size_t len), 
-               va_list * ap);
-
-
-extern int _scanf_float(struct _reent *rptr,
-              void *pdata,
-              FILE *fp, 
-              va_list *ap);
-
-
-static struct syscall_stub_table s_stub_table = {
-    .__getreent = &__getreent,
-    ._malloc_r = &_malloc_r,
-    ._free_r = &_free_r,
-    ._realloc_r = &_realloc_r,
-    ._calloc_r = &_calloc_r,
-    ._abort = &abort,
-    ._system_r = &_system_r,
-    ._rename_r = &_rename_r,
-    ._times_r = &_times_r,
-    ._gettimeofday_r = &_gettimeofday_r,
-    ._raise_r = &_raise_r,
-    ._unlink_r = &_unlink_r,
-    ._link_r = &_link_r,
-    ._stat_r = &_stat_r,
-    ._fstat_r = &_fstat_r,
-    ._sbrk_r = &_sbrk_r,
-    ._getpid_r = &_getpid_r,
-    ._kill_r = &_kill_r,
-    ._exit_r = &_exit_r,
-    ._close_r = &_close_r,
-    ._open_r = &_open_r,
-    ._write_r = (int (*)(struct _reent *r, int, const void *, int)) &_write_r,
-    ._lseek_r = (int (*)(struct _reent *r, int, int, int)) &_lseek_r,
-    ._read_r = (int (*)(struct _reent *r, int, void *, int)) &_read_r,
-    ._lock_init = &_lock_init,
-    ._lock_init_recursive = &_lock_init_recursive,
-    ._lock_close = &_lock_close,
-    ._lock_close_recursive = &_lock_close,
-    ._lock_acquire = &_lock_acquire,
-    ._lock_acquire_recursive = &_lock_acquire_recursive,
-    ._lock_try_acquire = &_lock_try_acquire,
-    ._lock_try_acquire_recursive = &_lock_try_acquire_recursive,
-    ._lock_release = &_lock_release,
-    ._lock_release_recursive = &_lock_release_recursive,
-    ._printf_float = &_printf_float,
-    ._scanf_float = &_scanf_float,
-};
-
-void ets_setup_syscalls() {
-       syscall_table_ptr_pro = &s_stub_table;
-       syscall_table_ptr_app = &s_stub_table;
-       _GLOBAL_REENT = &s_reent;
-    environ = malloc(sizeof(char*));
-    environ[0] = NULL;
-}
-
-
diff --git a/components/newlib/platform_include/esp_newlib.h b/components/newlib/platform_include/esp_newlib.h
new file mode 100644 (file)
index 0000000..74d0cc5
--- /dev/null
@@ -0,0 +1,27 @@
+// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
+//
+// 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.
+
+#ifndef __ESP_NEWLIB_H__
+#define __ESP_NEWLIB_H__
+
+/**
+ * Function which sets up syscall table used by newlib functions in ROM.
+ *
+ * Called from the startup code, not intended to be called from application
+ * code.
+ */
+void esp_setup_syscalls();
+
+
+#endif //__ESP_NEWLIB_H__
diff --git a/components/newlib/syscall_table.c b/components/newlib/syscall_table.c
new file mode 100644 (file)
index 0000000..b6414af
--- /dev/null
@@ -0,0 +1,91 @@
+// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
+//
+// 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 <string.h>
+#include <stdbool.h>
+#include <unistd.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/signal.h>
+#include <sys/unistd.h>
+#include <sys/reent.h>
+#include "rom/libc_stubs.h"
+#include "esp_vfs.h"
+
+static struct _reent s_reent;
+
+extern int _printf_float(struct _reent *rptr,
+               void *pdata,
+               FILE * fp,
+               int (*pfunc) (struct _reent *, FILE *, _CONST char *, size_t len),
+               va_list * ap);
+
+
+extern int _scanf_float(struct _reent *rptr,
+              void *pdata,
+              FILE *fp,
+              va_list *ap);
+
+
+static struct syscall_stub_table s_stub_table = {
+    .__getreent = &__getreent,
+    ._malloc_r = &_malloc_r,
+    ._free_r = &_free_r,
+    ._realloc_r = &_realloc_r,
+    ._calloc_r = &_calloc_r,
+    ._abort = &abort,
+    ._system_r = &_system_r,
+    ._rename_r = &esp_vfs_rename,
+    ._times_r = &_times_r,
+    ._gettimeofday_r = &_gettimeofday_r,
+    ._raise_r = (void (*)(struct _reent *r)) &_raise_r,
+    ._unlink_r = &esp_vfs_unlink,
+    ._link_r = &esp_vfs_link,
+    ._stat_r = &esp_vfs_stat,
+    ._fstat_r = &esp_vfs_fstat,
+    ._sbrk_r = &_sbrk_r,
+    ._getpid_r = &_getpid_r,
+    ._kill_r = &_kill_r,
+    ._exit_r = NULL,    // never called in ROM
+    ._close_r = &esp_vfs_close,
+    ._open_r = &esp_vfs_open,
+    ._write_r = (int (*)(struct _reent *r, int, const void *, int)) &esp_vfs_write,
+    ._lseek_r = (int (*)(struct _reent *r, int, int, int)) &esp_vfs_lseek,
+    ._read_r = (int (*)(struct _reent *r, int, void *, int)) &esp_vfs_read,
+    ._lock_init = &_lock_init,
+    ._lock_init_recursive = &_lock_init_recursive,
+    ._lock_close = &_lock_close,
+    ._lock_close_recursive = &_lock_close,
+    ._lock_acquire = &_lock_acquire,
+    ._lock_acquire_recursive = &_lock_acquire_recursive,
+    ._lock_try_acquire = &_lock_try_acquire,
+    ._lock_try_acquire_recursive = &_lock_try_acquire_recursive,
+    ._lock_release = &_lock_release,
+    ._lock_release_recursive = &_lock_release_recursive,
+    ._printf_float = &_printf_float,
+    ._scanf_float = &_scanf_float,
+};
+
+void esp_setup_syscalls()
+{
+    syscall_table_ptr_pro = &s_stub_table;
+    syscall_table_ptr_app = &s_stub_table;
+    _GLOBAL_REENT = &s_reent;
+    environ = malloc(sizeof(char*));
+    environ[0] = NULL;
+}
+
+
diff --git a/components/newlib/syscalls.c b/components/newlib/syscalls.c
new file mode 100644 (file)
index 0000000..4d70a39
--- /dev/null
@@ -0,0 +1,105 @@
+// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
+//
+// 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 <string.h>
+#include <stdbool.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <errno.h>
+#include <sys/reent.h>
+#include <stdlib.h>
+#include "esp_attr.h"
+#include "freertos/FreeRTOS.h"
+
+void IRAM_ATTR abort()
+{
+    do
+    {
+        __asm__ ("break 0,0");
+        *((int*) 0) = 0;
+    } while(true);
+}
+
+void* IRAM_ATTR _malloc_r(struct _reent *r, size_t size)
+{
+    return pvPortMalloc(size);
+}
+
+void IRAM_ATTR _free_r(struct _reent *r, void* ptr)
+{
+    return vPortFree(ptr);
+}
+
+void* IRAM_ATTR _realloc_r(struct _reent *r, void* ptr, size_t size)
+{
+       void* new_chunk;
+       if (size == 0) {
+               if (ptr) {
+                       vPortFree(ptr);
+               }
+               return NULL;
+       }
+
+       new_chunk = pvPortMalloc(size);
+       if (new_chunk && ptr) {
+               memcpy(new_chunk, ptr, size);
+               vPortFree(ptr);
+       }
+       // realloc behaviour: don't free original chunk if alloc failed
+       return new_chunk;
+}
+
+void* IRAM_ATTR _calloc_r(struct _reent *r, size_t count, size_t size)
+{
+    void* result = pvPortMalloc(count * size);
+    if (result)
+    {
+       memset(result, 0, count * size);
+    }
+    return result;
+}
+
+int _system_r(struct _reent *r, const char *str)
+{
+    __errno_r(r) = ENOSYS;
+    return -1;
+}
+
+void _raise_r(struct _reent *r)
+{
+    abort();
+}
+
+void* _sbrk_r(struct _reent *r, ptrdiff_t sz)
+{
+    abort();
+}
+
+int _getpid_r(struct _reent *r)
+{
+    __errno_r(r) = ENOSYS;
+    return -1;
+}
+
+int _kill_r(struct _reent *r, int pid, int sig)
+{
+    __errno_r(r) = ENOSYS;
+    return -1;
+}
+
+void _exit(int __status)
+{
+    abort();
+}
+
diff --git a/components/newlib/time.c b/components/newlib/time.c
new file mode 100644 (file)
index 0000000..cb2efb4
--- /dev/null
@@ -0,0 +1,35 @@
+// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
+//
+// 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 <errno.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/reent.h>
+#include <sys/time.h>
+#include <sys/times.h>
+#include "esp_attr.h"
+
+
+clock_t _times_r(struct _reent *r, struct tms *ptms)
+{
+    __errno_r(r) = ENOSYS;
+    return (clock_t) -1;
+}
+
+// TODO: read time from RTC
+int _gettimeofday_r(struct _reent *r, struct timeval *tv, void *tz)
+{
+    __errno_r(r) = ENOSYS;
+    return (clock_t) -1;
+}