mirror of
https://github.com/espressif/ESP8266_RTOS_SDK.git
synced 2025-06-06 13:59:16 +08:00
feat(newlib): Add newlib platform function
This commit is contained in:
@ -7,7 +7,7 @@ COMPONENT_SRCDIRS := driver source
|
|||||||
|
|
||||||
LIBS ?=
|
LIBS ?=
|
||||||
ifndef CONFIG_NO_BLOBS
|
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
|
phy pp pwm smartconfig ssc wpa wps
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
@ -86,7 +86,6 @@ typedef enum {
|
|||||||
#define REG_SET_BIT(_r, _b) (*(volatile uint32 *)(_r) |= (_b))
|
#define REG_SET_BIT(_r, _b) (*(volatile uint32 *)(_r) |= (_b))
|
||||||
#define REG_CLR_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 STORE_ATTR __attribute__((aligned(4)))
|
||||||
|
|
||||||
#define SHMEM_ATTR
|
#define SHMEM_ATTR
|
||||||
|
@ -21,6 +21,10 @@
|
|||||||
#include "freertos/semphr.h"
|
#include "freertos/semphr.h"
|
||||||
#include "freertos/timers.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)
|
static uint32_t enter_critical_wrapper(void)
|
||||||
{
|
{
|
||||||
taskENTER_CRITICAL();
|
taskENTER_CRITICAL();
|
||||||
@ -90,7 +94,9 @@ static void task_resume_all_wrapper(void)
|
|||||||
|
|
||||||
static void os_init_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)
|
static void os_start_wrapper(void)
|
||||||
|
@ -77,6 +77,17 @@ extern "C" {
|
|||||||
#include <xtensa/xtruntime.h>
|
#include <xtensa/xtruntime.h>
|
||||||
#include "xtensa_rtos.h"
|
#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.
|
* Port specific definitions.
|
||||||
*
|
*
|
||||||
|
44
components/freertos/port/impure.c
Normal file
44
components/freertos/port/impure.c
Normal file
@ -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;
|
||||||
|
}
|
@ -12,7 +12,7 @@ LIBC_PATH := $(COMPONENT_PATH)/newlib/lib/libc.a
|
|||||||
LIBM_PATH := $(COMPONENT_PATH)/newlib/lib/libm.a
|
LIBM_PATH := $(COMPONENT_PATH)/newlib/lib/libm.a
|
||||||
ADD_NEW_NEWLIB := 1
|
ADD_NEW_NEWLIB := 1
|
||||||
else
|
else
|
||||||
ifdef NEWLIB_LIBRARY_LEVEL_NANO
|
ifdef CONFIG_NEWLIB_LIBRARY_LEVEL_NANO
|
||||||
LIBC_PATH := $(COMPONENT_PATH)/newlib/lib/libc_nano.a
|
LIBC_PATH := $(COMPONENT_PATH)/newlib/lib/libc_nano.a
|
||||||
LIBM_PATH := $(COMPONENT_PATH)/newlib/lib/libm.a
|
LIBM_PATH := $(COMPONENT_PATH)/newlib/lib/libm.a
|
||||||
ADD_NEW_NEWLIB := 1
|
ADD_NEW_NEWLIB := 1
|
||||||
@ -20,7 +20,8 @@ endif
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(ADD_NEW_NEWLIB),1)
|
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_LDFLAGS := $(LIBC_PATH) $(LIBM_PATH) -lnewlib
|
||||||
COMPONENT_ADD_LINKER_DEPS := $(LIBC_PATH) $(LIBM_PATH)
|
COMPONENT_ADD_LINKER_DEPS := $(LIBC_PATH) $(LIBM_PATH)
|
||||||
endif
|
endif
|
||||||
|
68
components/newlib/newlib/port/esp_newlib.c
Normal file
68
components/newlib/newlib/port/esp_newlib.c
Normal file
@ -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 <reent.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @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;
|
||||||
|
}
|
26
components/newlib/newlib/port/fputc.c
Normal file
26
components/newlib/newlib/port/fputc.c
Normal file
@ -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 <stdio.h>
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
39
components/newlib/newlib/port/include/esp_newlib.h
Normal file
39
components/newlib/newlib/port/include/esp_newlib.h
Normal file
@ -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 <reent.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @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
|
123
components/newlib/newlib/port/syscall.c
Normal file
123
components/newlib/newlib/port/syscall.c
Normal file
@ -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 <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
#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);
|
||||||
|
}
|
@ -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;
|
spiffs_mode sm = 0;
|
||||||
int res;
|
int res;
|
||||||
@ -201,7 +201,7 @@ int _open_r(struct _reent *r, const char *filename, int flags, int mode)
|
|||||||
return res;
|
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;
|
ssize_t res;
|
||||||
@ -215,7 +215,7 @@ _ssize_t _read_r(struct _reent *r, int fd, void *buf, size_t len)
|
|||||||
return res;
|
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) {
|
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;
|
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;
|
ssize_t res;
|
||||||
@ -240,7 +240,7 @@ _off_t _lseek_r(struct _reent *r, int fd, _off_t where, int whence)
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
int _close_r(struct _reent *r, int fd)
|
int _spiffs_close_r(struct _reent *r, int fd)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (fd < NUM_SYS_FD) {
|
if (fd < NUM_SYS_FD) {
|
||||||
@ -251,21 +251,21 @@ int _close_r(struct _reent *r, int fd)
|
|||||||
return 0;
|
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);
|
int res = SPIFFS_rename(&fs, (char *) from, (char *) to);
|
||||||
return res;
|
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);
|
int res = SPIFFS_remove(&fs, (char *) filename);
|
||||||
return res;
|
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;
|
int res;
|
||||||
|
Reference in New Issue
Block a user