From 30de4508164752da6dcaea9186e6b397f8a27d0e Mon Sep 17 00:00:00 2001 From: Dong Heng Date: Fri, 11 May 2018 17:27:54 +0800 Subject: [PATCH] feat(newlib): Add newlib platform function --- components/esp8266/component.mk | 2 +- components/esp8266/include/c_types.h | 1 - .../esp8266/source/esp_wifi_os_adapter.c | 8 +- .../include/port/freertos/portmacro.h | 11 ++ components/freertos/port/impure.c | 44 +++++++ components/newlib/component.mk | 5 +- components/newlib/newlib/port/esp_newlib.c | 68 ++++++++++ components/newlib/newlib/port/fputc.c | 26 ++++ .../newlib/newlib/port/include/esp_newlib.h | 39 ++++++ components/newlib/newlib/port/syscall.c | 123 ++++++++++++++++++ components/spiffs/library/esp_spiffs.c | 16 +-- 11 files changed, 330 insertions(+), 13 deletions(-) create mode 100644 components/freertos/port/impure.c create mode 100644 components/newlib/newlib/port/esp_newlib.c create mode 100644 components/newlib/newlib/port/fputc.c create mode 100644 components/newlib/newlib/port/include/esp_newlib.h create mode 100644 components/newlib/newlib/port/syscall.c diff --git a/components/esp8266/component.mk b/components/esp8266/component.mk index b4c12229..30b35609 100644 --- a/components/esp8266/component.mk +++ b/components/esp8266/component.mk @@ -7,7 +7,7 @@ COMPONENT_SRCDIRS := driver source LIBS ?= ifndef CONFIG_NO_BLOBS -LIBS += airkiss cirom crypto espnow gcc hal core mirom net80211 \ +LIBS += airkiss crypto espnow gcc hal core net80211 \ phy pp pwm smartconfig ssc wpa wps endif diff --git a/components/esp8266/include/c_types.h b/components/esp8266/include/c_types.h index 78934168..54ee4c21 100644 --- a/components/esp8266/include/c_types.h +++ b/components/esp8266/include/c_types.h @@ -86,7 +86,6 @@ typedef enum { #define REG_SET_BIT(_r, _b) (*(volatile uint32 *)(_r) |= (_b)) #define REG_CLR_BIT(_r, _b) (*(volatile uint32 *)(_r) &= ~(_b)) -#define __packed __attribute__((packed)) #define STORE_ATTR __attribute__((aligned(4))) #define SHMEM_ATTR diff --git a/components/esp8266/source/esp_wifi_os_adapter.c b/components/esp8266/source/esp_wifi_os_adapter.c index 561b10f9..1f429232 100644 --- a/components/esp8266/source/esp_wifi_os_adapter.c +++ b/components/esp8266/source/esp_wifi_os_adapter.c @@ -21,6 +21,10 @@ #include "freertos/semphr.h" #include "freertos/timers.h" +#if defined(CONFIG_NEWLIB_LIBRARY_LEVEL_NORMAL) || defined(CONFIG_NEWLIB_LIBRARY_LEVEL_NANO) +#include "esp_newlib.h" +#endif + static uint32_t enter_critical_wrapper(void) { taskENTER_CRITICAL(); @@ -90,7 +94,9 @@ static void task_resume_all_wrapper(void) static void os_init_wrapper(void) { - /* empty function */ +#if defined(CONFIG_NEWLIB_LIBRARY_LEVEL_NORMAL) || defined(CONFIG_NEWLIB_LIBRARY_LEVEL_NANO) + esp_newlib_init(); +#endif } static void os_start_wrapper(void) diff --git a/components/freertos/include/port/freertos/portmacro.h b/components/freertos/include/port/freertos/portmacro.h index 9c60a8fd..222a6952 100644 --- a/components/freertos/include/port/freertos/portmacro.h +++ b/components/freertos/include/port/freertos/portmacro.h @@ -77,6 +77,17 @@ extern "C" { #include #include "xtensa_rtos.h" +#if defined(configUSE_NEWLIB_REENTRANT) && configUSE_NEWLIB_REENTRANT == 1 +#if defined(CONFIG_NEWLIB_LIBRARY_LEVEL_NORMAL) || defined(CONFIG_NEWLIB_LIBRARY_LEVEL_NANO) +#include "esp_newlib.h" + +#define _impure_ptr _global_impure_ptr + +#undef _REENT_INIT_PTR +#define _REENT_INIT_PTR(p) esp_reent_init(p) +#endif +#endif + /*----------------------------------------------------------- * Port specific definitions. * diff --git a/components/freertos/port/impure.c b/components/freertos/port/impure.c new file mode 100644 index 00000000..44e511db --- /dev/null +++ b/components/freertos/port/impure.c @@ -0,0 +1,44 @@ +// Copyright 2018-2019 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 "freertos/FreeRTOS.h" +#include "freertos/task.h" + +static struct _reent impure_data; +struct _reent *_global_impure_ptr = &impure_data; + +struct _reent *__getreent() +{ + extern char _xt_isr_status; + + /* + * Locking mutex(only mutex, not ISR mutex) at the following three + * state may cause OS death. So we use a extra _reent data instead + * of task private reent data. + * + * But although at the state none of "taskSCHEDULER_RUNNING", exception + * can cause CPU swicth context, then Locking mutex may cause OS death. + * So we command that use ets_printf(ROM function) instead of "printf" + * at exception and system kernal critical state. + */ + if (_xt_isr_status + || !xTaskGetCurrentTaskHandle() + || xTaskGetSchedulerState() != taskSCHEDULER_RUNNING) + return &impure_data; + + /* + * When scheduler starts, _global_impure_ptr = pxCurrentTCB->xNewLib_reent. + */ + return _global_impure_ptr; +} diff --git a/components/newlib/component.mk b/components/newlib/component.mk index 8f87cc2b..d3110c83 100644 --- a/components/newlib/component.mk +++ b/components/newlib/component.mk @@ -12,7 +12,7 @@ LIBC_PATH := $(COMPONENT_PATH)/newlib/lib/libc.a LIBM_PATH := $(COMPONENT_PATH)/newlib/lib/libm.a ADD_NEW_NEWLIB := 1 else -ifdef NEWLIB_LIBRARY_LEVEL_NANO +ifdef CONFIG_NEWLIB_LIBRARY_LEVEL_NANO LIBC_PATH := $(COMPONENT_PATH)/newlib/lib/libc_nano.a LIBM_PATH := $(COMPONENT_PATH)/newlib/lib/libm.a ADD_NEW_NEWLIB := 1 @@ -20,7 +20,8 @@ endif endif ifeq ($(ADD_NEW_NEWLIB),1) -COMPONENT_ADD_INCLUDEDIRS += newlib/include +COMPONENT_ADD_INCLUDEDIRS += newlib/include newlib/port/include +COMPONENT_SRCDIRS += newlib/port COMPONENT_ADD_LDFLAGS := $(LIBC_PATH) $(LIBM_PATH) -lnewlib COMPONENT_ADD_LINKER_DEPS := $(LIBC_PATH) $(LIBM_PATH) endif diff --git a/components/newlib/newlib/port/esp_newlib.c b/components/newlib/newlib/port/esp_newlib.c new file mode 100644 index 00000000..3425de64 --- /dev/null +++ b/components/newlib/newlib/port/esp_newlib.c @@ -0,0 +1,68 @@ +// Copyright 2018-2019 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 +#include +#include + +/* + * @brief Initialize global and thread's private reent object data. We add this instead of + * newlib's initialization function to avoid some unnecessary cost and unused function. + */ +void esp_reent_init(struct _reent* r) +{ + extern void _cleanup(struct _reent *r); + + memset(r, 0, sizeof(*r)); + + r->_stdout = _GLOBAL_REENT->_stdout; + r->_stderr = _GLOBAL_REENT->_stderr; + r->_stdin = _GLOBAL_REENT->_stdin; + + r->__cleanup = _cleanup; + r->__sglue._next = NULL; + r->__sglue._niobs = 0; + r->__sglue._iobs = NULL; + r->_current_locale = "C"; + r->__sdidinit = 1; +} + +/* + * @brief Initialize newlib's platform object data + */ +int esp_newlib_init(void) +{ + esp_reent_init(_global_impure_ptr); + + _GLOBAL_REENT->_stdout = fopen("uart/0", "w"); + if (!_GLOBAL_REENT->_stdout) + goto err; + + _GLOBAL_REENT->_stderr = fopen("uart/0", "w"); + if (!_GLOBAL_REENT->_stderr) + goto err_fail; + + _GLOBAL_REENT->_stdin = fopen("uart/0", "r"); + if (!_GLOBAL_REENT->_stdin) + goto err_in; + + return 0; + +err_in: + fclose(_GLOBAL_REENT->_stderr); +err_fail: + fclose(_GLOBAL_REENT->_stdout); +err: + return -1; +} diff --git a/components/newlib/newlib/port/fputc.c b/components/newlib/newlib/port/fputc.c new file mode 100644 index 00000000..a5fada9a --- /dev/null +++ b/components/newlib/newlib/port/fputc.c @@ -0,0 +1,26 @@ +// Copyright 2018-2019 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 <_ansi.h> +#include + +int _fputc_r(struct _reent *ptr, int ch, FILE *fp) +{ + return fp->_write(ptr, fp->_cookie, (char *)&ch, 1); +} + +int fputc(int ch, FILE *fp) +{ + return _fputc_r (_REENT, ch, fp); +} diff --git a/components/newlib/newlib/port/include/esp_newlib.h b/components/newlib/newlib/port/include/esp_newlib.h new file mode 100644 index 00000000..3fa555f2 --- /dev/null +++ b/components/newlib/newlib/port/include/esp_newlib.h @@ -0,0 +1,39 @@ +// Copyright 2018-2019 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 + +#include + +/* + * @brief Initialize global and thread's private reent object data. We add this instead of + * newlib's initialization function to avoid some unnecessary cost and unused function. + * + * @param r reent pointer + * + * @return none + */ +void esp_reent_init(struct _reent* r); + +/* + * @brief Initialize newlib's platform object data + * + * @param none + * + * @return 0 if successful or -1 if failed + */ +int esp_newlib_init(void); + +#endif diff --git a/components/newlib/newlib/port/syscall.c b/components/newlib/newlib/port/syscall.c new file mode 100644 index 00000000..23b9b67e --- /dev/null +++ b/components/newlib/newlib/port/syscall.c @@ -0,0 +1,123 @@ +// Copyright 2018-2019 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 +#include +#include + +#include "c_types.h" + +#include "esp8266/ets_sys.h" +#include "esp8266/eagle_soc.h" +#include "esp8266/uart_register.h" + +#define PANIC_UART 0 + +static inline void panit_putc(char c) +{ + while (1) { + uint32_t fifo_cnt = READ_PERI_REG(UART_STATUS(PANIC_UART)) & (UART_TXFIFO_CNT << UART_TXFIFO_CNT_S); + + if ((fifo_cnt >> UART_TXFIFO_CNT_S & UART_TXFIFO_CNT) < 126) + break; + } + + WRITE_PERI_REG(UART_FIFO(PANIC_UART) , c); +} + +int _open_r(struct _reent *r, const char *filename, int flags, int mode) +{ + return 0; +} + +int _read_r(struct _reent *r, int fd, void *buf, int len) +{ + return 0; +} + +int _write_r(struct _reent *r, int fd, void *buf, int len) +{ + int i; + const char *cbuf = buf; + + for (i = 0; i < len; i++) + panit_putc(cbuf[i]); + + return len; +} + +_off_t _lseek_r(struct _reent *r, int fd, _off_t where, int whence) +{ + return 0; +} + +int _close_r(struct _reent *r, int fd) +{ + return 0; +} + +int _rename_r(struct _reent *r, const char *from, const char *to) +{ + return 0; +} + +int _unlink_r(struct _reent *r, const char *filename) +{ + return 0; +} + +int _fstat_r(struct _reent *r, int fd, struct stat *s) +{ + return 0; +} + +void _sbrk_r(void *ptr, int incr) +{ + return ; +} + +void *_malloc_r(struct _reent *r, size_t n) +{ + return pvPortMalloc(n); +} + +void *_realloc_r(struct _reent *r, void *old_ptr, size_t n) +{ + void *p = pvPortMalloc(n); + if (p && old_ptr) { + memcpy(p, old_ptr, n); + vPortFree(old_ptr); + } + + return p; +} + +void *_calloc_r(struct _reent *r, size_t c, size_t s) +{ + char *p = pvPortMalloc(c * s); + if (p) + memset(p, 0, c * s); + + return p; +} + +void *_free_r(struct _reent *r, void *ptr) +{ + vPortFree(ptr); +} + +void _exit(int status) +{ + while (1); +} diff --git a/components/spiffs/library/esp_spiffs.c b/components/spiffs/library/esp_spiffs.c index 9d3fbbc7..87e4ec1d 100644 --- a/components/spiffs/library/esp_spiffs.c +++ b/components/spiffs/library/esp_spiffs.c @@ -162,7 +162,7 @@ void esp_spiffs_deinit(u8_t format) } } -int _open_r(struct _reent *r, const char *filename, int flags, int mode) +int _spiffs_open_r(struct _reent *r, const char *filename, int flags, int mode) { spiffs_mode sm = 0; int res; @@ -201,7 +201,7 @@ int _open_r(struct _reent *r, const char *filename, int flags, int mode) return res; } -_ssize_t _read_r(struct _reent *r, int fd, void *buf, size_t len) +_ssize_t _spiffs_read_r(struct _reent *r, int fd, void *buf, size_t len) { ssize_t res; @@ -215,7 +215,7 @@ _ssize_t _read_r(struct _reent *r, int fd, void *buf, size_t len) return res; } -_ssize_t _write_r(struct _reent *r, int fd, void *buf, size_t len) +_ssize_t _spiffs_write_r(struct _reent *r, int fd, void *buf, size_t len) { if (fd < NUM_SYS_FD) { @@ -226,7 +226,7 @@ _ssize_t _write_r(struct _reent *r, int fd, void *buf, size_t len) return res; } -_off_t _lseek_r(struct _reent *r, int fd, _off_t where, int whence) +_off_t _spiffs_lseek_r(struct _reent *r, int fd, _off_t where, int whence) { ssize_t res; @@ -240,7 +240,7 @@ _off_t _lseek_r(struct _reent *r, int fd, _off_t where, int whence) return res; } -int _close_r(struct _reent *r, int fd) +int _spiffs_close_r(struct _reent *r, int fd) { if (fd < NUM_SYS_FD) { @@ -251,21 +251,21 @@ int _close_r(struct _reent *r, int fd) return 0; } -int _rename_r(struct _reent *r, const char *from, const char *to) +int _spiffs_rename_r(struct _reent *r, const char *from, const char *to) { int res = SPIFFS_rename(&fs, (char *) from, (char *) to); return res; } -int _unlink_r(struct _reent *r, const char *filename) +int _spiffs_unlink_r(struct _reent *r, const char *filename) { int res = SPIFFS_remove(&fs, (char *) filename); return res; } -int _fstat_r(struct _reent *r, int fd, struct stat *s) +int _spiffs_fstat_r(struct _reent *r, int fd, struct stat *s) { int res;