mirror of
https://github.com/espressif/ESP8266_RTOS_SDK.git
synced 2025-12-16 02:43:47 +08:00
Revert "Merge branch 'feature/support_gcc_v8.x' into 'master'"
This reverts merge request !1539
This commit is contained in:
@@ -1,54 +0,0 @@
|
||||
// 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 <stddef.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include "FreeRTOS.h"
|
||||
|
||||
void *malloc(size_t n)
|
||||
{
|
||||
void *return_addr = (void *)__builtin_return_address(0);
|
||||
|
||||
return _heap_caps_malloc(n, MALLOC_CAP_32BIT, return_addr, 0);
|
||||
}
|
||||
|
||||
void *realloc(void *old_ptr, size_t n)
|
||||
{
|
||||
void *return_addr = (void *)__builtin_return_address(0);
|
||||
|
||||
return _heap_caps_realloc(old_ptr, n, MALLOC_CAP_32BIT, return_addr, 0);
|
||||
}
|
||||
|
||||
void *zalloc(size_t n)
|
||||
{
|
||||
void *return_addr = (void *)__builtin_return_address(0);
|
||||
|
||||
return _heap_caps_zalloc(n, MALLOC_CAP_32BIT, return_addr, 0);
|
||||
}
|
||||
|
||||
void *calloc(size_t c, size_t s)
|
||||
{
|
||||
void *return_addr = (void *)__builtin_return_address(0);
|
||||
|
||||
return _heap_caps_calloc(c, s, MALLOC_CAP_32BIT, return_addr, 0);
|
||||
}
|
||||
|
||||
void free(void *ptr)
|
||||
{
|
||||
void *return_addr = (void *)__builtin_return_address(0);
|
||||
|
||||
_heap_caps_free(ptr, return_addr, 0);
|
||||
}
|
||||
|
||||
@@ -1,212 +0,0 @@
|
||||
// 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 <sys/lock.h>
|
||||
#include <stdlib.h>
|
||||
#include <reent.h>
|
||||
|
||||
#include "FreeRTOS.h"
|
||||
#include "semphr.h"
|
||||
#include "task.h"
|
||||
|
||||
/* Initialize the given lock by allocating a new mutex semaphore
|
||||
as the _lock_t value.
|
||||
|
||||
Called by _lock_init*, also called by _lock_acquire* to lazily initialize locks that might have
|
||||
been initialised (to zero only) before the RTOS scheduler started.
|
||||
*/
|
||||
|
||||
static void lock_init_generic(_lock_t *lock, uint8_t mutex_type) {
|
||||
portENTER_CRITICAL();
|
||||
if (xTaskGetSchedulerState() == taskSCHEDULER_NOT_STARTED) {
|
||||
/* nothing to do until the scheduler is running */
|
||||
portEXIT_CRITICAL();
|
||||
return;
|
||||
}
|
||||
|
||||
if (*lock) {
|
||||
/* Lock already initialised (either we didn't check earlier,
|
||||
or it got initialised while we were waiting for the
|
||||
spinlock.) */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Create a new semaphore
|
||||
|
||||
this is a bit of an API violation, as we're calling the
|
||||
private function xQueueCreateMutex(x) directly instead of
|
||||
the xSemaphoreCreateMutex / xSemaphoreCreateRecursiveMutex
|
||||
wrapper functions...
|
||||
|
||||
The better alternative would be to pass pointers to one of
|
||||
the two xSemaphoreCreate___Mutex functions, but as FreeRTOS
|
||||
implements these as macros instead of inline functions
|
||||
(*party like it's 1998!*) it's not possible to do this
|
||||
without writing wrappers. Doing it this way seems much less
|
||||
spaghetti-like.
|
||||
*/
|
||||
xSemaphoreHandle new_sem = xQueueCreateMutex(mutex_type);
|
||||
if (!new_sem) {
|
||||
abort(); /* No more semaphores available or OOM */
|
||||
}
|
||||
*lock = (_lock_t)new_sem;
|
||||
}
|
||||
portEXIT_CRITICAL();
|
||||
}
|
||||
|
||||
void _lock_init(_lock_t *lock) {
|
||||
*lock = 0; // In case lock's memory is uninitialized
|
||||
lock_init_generic(lock, queueQUEUE_TYPE_MUTEX);
|
||||
}
|
||||
|
||||
void _lock_init_recursive(_lock_t *lock) {
|
||||
*lock = 0; // In case lock's memory is uninitialized
|
||||
lock_init_generic(lock, queueQUEUE_TYPE_RECURSIVE_MUTEX);
|
||||
}
|
||||
|
||||
/* Free the mutex semaphore pointed to by *lock, and zero it out.
|
||||
|
||||
Note that FreeRTOS doesn't account for deleting mutexes while they
|
||||
are held, and neither do we... so take care not to delete newlib
|
||||
locks while they may be held by other tasks!
|
||||
|
||||
Also, deleting a lock in this way will cause it to be lazily
|
||||
re-initialised if it is used again. Caller has to avoid doing
|
||||
this!
|
||||
*/
|
||||
static void lock_close_generic(_lock_t *lock, uint8_t mutex_type) {
|
||||
portENTER_CRITICAL();
|
||||
if (*lock) {
|
||||
xSemaphoreHandle h = (xSemaphoreHandle)(*lock);
|
||||
#if (INCLUDE_xSemaphoreGetMutexHolder == 1)
|
||||
configASSERT(xSemaphoreGetMutexHolder(h) == NULL); /* mutex should not be held */
|
||||
#endif
|
||||
vSemaphoreDelete(h);
|
||||
*lock = 0;
|
||||
}
|
||||
portEXIT_CRITICAL();
|
||||
}
|
||||
|
||||
void _lock_close(_lock_t *lock) {
|
||||
lock_close_generic(lock, queueQUEUE_TYPE_MUTEX);
|
||||
}
|
||||
|
||||
void _lock_close_recursive(_lock_t *lock) {
|
||||
lock_close_generic(lock, queueQUEUE_TYPE_RECURSIVE_MUTEX);
|
||||
}
|
||||
|
||||
/* Acquire the mutex semaphore for lock. wait up to delay ticks.
|
||||
mutex_type is queueQUEUE_TYPE_RECURSIVE_MUTEX or queueQUEUE_TYPE_MUTEX
|
||||
*/
|
||||
static int lock_acquire_generic(_lock_t *lock, uint32_t delay, uint8_t mutex_type) {
|
||||
/* If application function has disabled interrupt, then it must not acquire the mutex */
|
||||
if (interrupt_is_disable() == true && !xPortInIsrContext())
|
||||
return 0;
|
||||
|
||||
xSemaphoreHandle h = (xSemaphoreHandle)(*lock);
|
||||
if (!h) {
|
||||
if (xTaskGetSchedulerState() == taskSCHEDULER_NOT_STARTED) {
|
||||
return 0; /* locking is a no-op before scheduler is up, so this "succeeds" */
|
||||
}
|
||||
/* lazy initialise lock - might have had a static initializer in newlib (that we don't use),
|
||||
or _lock_init might have been called before the scheduler was running... */
|
||||
lock_init_generic(lock, mutex_type);
|
||||
h = (xSemaphoreHandle)(*lock);
|
||||
configASSERT(h != NULL);
|
||||
}
|
||||
|
||||
BaseType_t success;
|
||||
if (xPortInIsrContext()) {
|
||||
/* In ISR Context */
|
||||
if (mutex_type == queueQUEUE_TYPE_RECURSIVE_MUTEX) {
|
||||
abort(); /* recursive mutexes make no sense in ISR context */
|
||||
}
|
||||
BaseType_t higher_task_woken = false;
|
||||
success = xSemaphoreTakeFromISR(h, &higher_task_woken);
|
||||
if (!success && delay > 0) {
|
||||
abort(); /* Tried to block on mutex from ISR, couldn't... rewrite your program to avoid libc interactions in ISRs! */
|
||||
}
|
||||
if (higher_task_woken) {
|
||||
portYIELD_FROM_ISR();
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* In task context */
|
||||
if (mutex_type == queueQUEUE_TYPE_RECURSIVE_MUTEX) {
|
||||
success = xSemaphoreTakeRecursive(h, delay);
|
||||
} else {
|
||||
success = xSemaphoreTake(h, delay);
|
||||
}
|
||||
}
|
||||
|
||||
return (success == pdTRUE) ? 0 : -1;
|
||||
}
|
||||
|
||||
void _lock_acquire(_lock_t *lock) {
|
||||
lock_acquire_generic(lock, portMAX_DELAY, queueQUEUE_TYPE_MUTEX);
|
||||
}
|
||||
|
||||
void _lock_acquire_recursive(_lock_t *lock) {
|
||||
lock_acquire_generic(lock, portMAX_DELAY, queueQUEUE_TYPE_RECURSIVE_MUTEX);
|
||||
}
|
||||
|
||||
int _lock_try_acquire(_lock_t *lock) {
|
||||
return lock_acquire_generic(lock, 0, queueQUEUE_TYPE_MUTEX);
|
||||
}
|
||||
|
||||
int _lock_try_acquire_recursive(_lock_t *lock) {
|
||||
return lock_acquire_generic(lock, 0, queueQUEUE_TYPE_RECURSIVE_MUTEX);
|
||||
}
|
||||
|
||||
/* Release the mutex semaphore for lock.
|
||||
mutex_type is queueQUEUE_TYPE_RECURSIVE_MUTEX or queueQUEUE_TYPE_MUTEX
|
||||
*/
|
||||
static void lock_release_generic(_lock_t *lock, uint8_t mutex_type) {
|
||||
/* If application function has disabled interrupt, then it must not release the mutex */
|
||||
if (interrupt_is_disable() == true && !xPortInIsrContext())
|
||||
return ;
|
||||
|
||||
xSemaphoreHandle h = (xSemaphoreHandle)(*lock);
|
||||
if (h == NULL) {
|
||||
/* This is probably because the scheduler isn't running yet,
|
||||
or the scheduler just started running and some code was
|
||||
"holding" a not-yet-initialised lock... */
|
||||
return;
|
||||
}
|
||||
|
||||
if (xPortInIsrContext()) {
|
||||
if (mutex_type == queueQUEUE_TYPE_RECURSIVE_MUTEX) {
|
||||
abort(); /* indicates logic bug, it shouldn't be possible to lock recursively in ISR */
|
||||
}
|
||||
BaseType_t higher_task_woken = false;
|
||||
xSemaphoreGiveFromISR(h, &higher_task_woken);
|
||||
if (higher_task_woken) {
|
||||
portYIELD_FROM_ISR();
|
||||
}
|
||||
} else {
|
||||
if (mutex_type == queueQUEUE_TYPE_RECURSIVE_MUTEX) {
|
||||
xSemaphoreGiveRecursive(h);
|
||||
} else {
|
||||
xSemaphoreGive(h);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void _lock_release(_lock_t *lock) {
|
||||
lock_release_generic(lock, queueQUEUE_TYPE_MUTEX);
|
||||
}
|
||||
|
||||
void _lock_release_recursive(_lock_t *lock) {
|
||||
lock_release_generic(lock, queueQUEUE_TYPE_RECURSIVE_MUTEX);
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
// Copyright 2019-2020 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 <sys/random.h>
|
||||
#include <sys/param.h>
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include "esp_system.h"
|
||||
#include "esp_log.h"
|
||||
|
||||
static const char *TAG = "RANDOM";
|
||||
|
||||
ssize_t getrandom(void *buf, size_t buflen, unsigned int flags)
|
||||
{
|
||||
// Flags are ignored because:
|
||||
// - esp_random is non-blocking so it works for both blocking and non-blocking calls,
|
||||
// - don't have opportunity so set som other source of entropy.
|
||||
|
||||
ESP_LOGD(TAG, "getrandom(buf=0x%x, buflen=%d, flags=%u)", (int) buf, buflen, flags);
|
||||
|
||||
if (buf == NULL) {
|
||||
errno = EFAULT;
|
||||
ESP_LOGD(TAG, "getrandom returns -1 (EFAULT)");
|
||||
return -1;
|
||||
}
|
||||
|
||||
esp_fill_random(buf, buflen);
|
||||
|
||||
ESP_LOGD(TAG, "getrandom returns %d", buflen);
|
||||
return buflen;
|
||||
}
|
||||
@@ -1,155 +0,0 @@
|
||||
// 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 <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/reent.h>
|
||||
#include "esp_attr.h"
|
||||
#include "esp_vfs_dev.h"
|
||||
|
||||
#define _STR(_s) #_s
|
||||
#define STR(_s) _STR(_s)
|
||||
|
||||
static struct _reent impure_data;
|
||||
|
||||
/* This function is not part on newlib API, it is defined in libc/stdio/local.h
|
||||
* There is no nice way to get __cleanup member populated while avoiding __sinit,
|
||||
* so extern declaration is used here.
|
||||
*/
|
||||
extern void _cleanup_r(struct _reent* r);
|
||||
|
||||
/**
|
||||
* This is the replacement for newlib's _REENT_INIT_PTR and __sinit.
|
||||
* The problem with __sinit is that it allocates three FILE structures
|
||||
* (stdin, stdout, stderr). Having individual standard streams for each task
|
||||
* is a bit too much on a small embedded system. So we point streams
|
||||
* to the streams of the global struct _reent, which are initialized in
|
||||
* startup code.
|
||||
*/
|
||||
void esp_reent_init(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;
|
||||
r->__sdidinit = 1;
|
||||
r->__sglue._next = NULL;
|
||||
r->__sglue._niobs = 0;
|
||||
r->__sglue._iobs = NULL;
|
||||
}
|
||||
|
||||
/* only declared in private stdio header file, local.h */
|
||||
extern void __sfp_lock_acquire(void);
|
||||
extern void __sfp_lock_release(void);
|
||||
|
||||
void esp_reent_cleanup(void)
|
||||
{
|
||||
struct _reent* r = __getreent();
|
||||
/* Clean up storage used by mprec functions */
|
||||
if (r->_mp) {
|
||||
if (_REENT_MP_FREELIST(r)) {
|
||||
for (int i = 0; i < _Kmax; ++i) {
|
||||
struct _Bigint *cur, *next;
|
||||
next = _REENT_MP_FREELIST(r)[i];
|
||||
while (next) {
|
||||
cur = next;
|
||||
next = next->_next;
|
||||
free(cur);
|
||||
}
|
||||
}
|
||||
}
|
||||
free(_REENT_MP_FREELIST(r));
|
||||
free(_REENT_MP_RESULT(r));
|
||||
}
|
||||
|
||||
/* Clean up "glue" (lazily-allocated FILE objects) */
|
||||
struct _glue* prev = &_GLOBAL_REENT->__sglue;
|
||||
for (struct _glue* cur = _GLOBAL_REENT->__sglue._next; cur != NULL;) {
|
||||
if (cur->_niobs == 0) {
|
||||
cur = cur->_next;
|
||||
continue;
|
||||
}
|
||||
bool has_open_files = false;
|
||||
for (int i = 0; i < cur->_niobs; ++i) {
|
||||
FILE* fp = &cur->_iobs[i];
|
||||
if (fp->_flags != 0) {
|
||||
has_open_files = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (has_open_files) {
|
||||
prev = cur;
|
||||
cur = cur->_next;
|
||||
continue;
|
||||
}
|
||||
struct _glue* next = cur->_next;
|
||||
prev->_next = next;
|
||||
free(cur);
|
||||
cur = next;
|
||||
}
|
||||
|
||||
/* Clean up various other buffers */
|
||||
free(r->_mp);
|
||||
r->_mp = NULL;
|
||||
free(r->_r48);
|
||||
r->_r48 = NULL;
|
||||
free(r->_localtime_buf);
|
||||
r->_localtime_buf = NULL;
|
||||
free(r->_asctime_buf);
|
||||
r->_asctime_buf = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* @brief Initialize newlib's platform object data
|
||||
*/
|
||||
int esp_newlib_init(void)
|
||||
{
|
||||
const char *default_uart_dev = "/dev/uart/" STR(CONFIG_CONSOLE_UART_NUM);
|
||||
|
||||
_global_impure_ptr = &impure_data;
|
||||
esp_reent_init(_global_impure_ptr);
|
||||
|
||||
#ifdef CONFIG_USING_ESP_VFS
|
||||
esp_vfs_dev_uart_register();
|
||||
#endif
|
||||
|
||||
_GLOBAL_REENT->_stdout = fopen(default_uart_dev, "w");
|
||||
if (!_GLOBAL_REENT->_stdout)
|
||||
goto err;
|
||||
|
||||
_GLOBAL_REENT->_stderr = fopen(default_uart_dev, "w");
|
||||
if (!_GLOBAL_REENT->_stderr)
|
||||
goto err_fail;
|
||||
|
||||
_GLOBAL_REENT->_stdin = fopen(default_uart_dev, "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;
|
||||
}
|
||||
|
||||
struct _reent* __getreent()
|
||||
{
|
||||
return _global_impure_ptr;
|
||||
}
|
||||
@@ -1,65 +0,0 @@
|
||||
// Copyright 2018 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 <sys/select.h>
|
||||
#include "sdkconfig.h"
|
||||
|
||||
#include "esp_vfs.h"
|
||||
|
||||
#ifdef CONFIG_USE_ONLY_LWIP_SELECT
|
||||
#include "lwip/sockets.h"
|
||||
|
||||
#ifdef CONFIG_SUPPRESS_SELECT_DEBUG_OUTPUT
|
||||
#define LOG_LOCAL_LEVEL ESP_LOG_NONE
|
||||
#endif //CONFIG_SUPPRESS_SELECT_DEBUG_OUTPUT
|
||||
#include "esp_log.h"
|
||||
|
||||
static const char *TAG = "newlib_select";
|
||||
|
||||
static void log_fd_set(const char *fds_name, const fd_set *fds)
|
||||
{
|
||||
if (fds_name && fds) {
|
||||
ESP_LOGD(TAG, "FDs in %s =", fds_name);
|
||||
for (int i = 0; i < MAX_FDS; ++i) {
|
||||
if (FD_ISSET(i, fds)) {
|
||||
ESP_LOGD(TAG, "%d", i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif //CONFIG_USE_ONLY_LWIP_SELECT
|
||||
|
||||
int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *errorfds, struct timeval *timeout)
|
||||
{
|
||||
#ifdef CONFIG_USE_ONLY_LWIP_SELECT
|
||||
ESP_LOGD(TAG, "lwip_select starts with nfds = %d", nfds);
|
||||
if (timeout) {
|
||||
ESP_LOGD(TAG, "timeout is %lds + %ldus", timeout->tv_sec, timeout->tv_usec);
|
||||
}
|
||||
log_fd_set("readfds", readfds);
|
||||
log_fd_set("writefds", writefds);
|
||||
log_fd_set("errorfds", errorfds);
|
||||
|
||||
int ret = lwip_select(nfds, readfds, writefds, errorfds, timeout);
|
||||
|
||||
ESP_LOGD(TAG, "lwip_select returns %d", ret);
|
||||
log_fd_set("readfds", readfds);
|
||||
log_fd_set("writefds", writefds);
|
||||
log_fd_set("errorfds", errorfds);
|
||||
|
||||
return ret;
|
||||
#else
|
||||
return esp_vfs_select(nfds, readfds, writefds, errorfds, timeout);
|
||||
#endif
|
||||
}
|
||||
@@ -1,92 +0,0 @@
|
||||
// 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 "sdkconfig.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <reent.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/errno.h>
|
||||
#include <sys/fcntl.h>
|
||||
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
|
||||
#include "esp_libc.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_vfs.h"
|
||||
|
||||
#define ERRNO_TLS_INDEX (configNUM_THREAD_LOCAL_STORAGE_POINTERS - 1)
|
||||
|
||||
void *_malloc_r(struct _reent *r, size_t n)
|
||||
{
|
||||
void *return_addr = (void *)__builtin_return_address(0);
|
||||
|
||||
return _heap_caps_malloc(n, MALLOC_CAP_32BIT, return_addr, 0);
|
||||
}
|
||||
|
||||
void *_realloc_r(struct _reent *r, void *old_ptr, size_t n)
|
||||
{
|
||||
void *return_addr = (void *)__builtin_return_address(0);
|
||||
|
||||
return _heap_caps_realloc(old_ptr, n, MALLOC_CAP_32BIT, return_addr, 0);
|
||||
}
|
||||
|
||||
void *_calloc_r(struct _reent *r, size_t c, size_t s)
|
||||
{
|
||||
void *return_addr = (void *)__builtin_return_address(0);
|
||||
|
||||
return _heap_caps_calloc(c, s, MALLOC_CAP_32BIT, return_addr, 0);
|
||||
}
|
||||
|
||||
void _free_r(struct _reent *r, void *ptr)
|
||||
{
|
||||
void *return_addr = (void *)__builtin_return_address(0);
|
||||
|
||||
_heap_caps_free(ptr, return_addr, 0);
|
||||
}
|
||||
|
||||
void abort(void)
|
||||
{
|
||||
#ifndef CONFIG_ESP_PANIC_SILENT_REBOOT
|
||||
ets_printf("abort() was called at PC %p on core %d\r\n", __builtin_return_address(0) - 3, xPortGetCoreID());
|
||||
#endif
|
||||
|
||||
/* cause a exception to jump into panic function */
|
||||
while (1) {
|
||||
*((int *)NULL) = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void _exit(int status)
|
||||
{
|
||||
abort();
|
||||
}
|
||||
|
||||
void *_sbrk_r(struct _reent *r, ptrdiff_t incr)
|
||||
{
|
||||
abort();
|
||||
}
|
||||
|
||||
int _getpid_r(struct _reent *r)
|
||||
{
|
||||
__errno_r(r) = ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int *__errno(void)
|
||||
{
|
||||
return (int *)pvTaskGetThreadLocalStorageBufferPointer(NULL, ERRNO_TLS_INDEX);
|
||||
}
|
||||
@@ -1,54 +0,0 @@
|
||||
// Copyright 2018 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 "sdkconfig.h"
|
||||
|
||||
#ifdef CONFIG_SUPPORT_TERMIOS
|
||||
|
||||
#include <sys/termios.h>
|
||||
#include <sys/errno.h>
|
||||
|
||||
speed_t cfgetispeed(const struct termios *p)
|
||||
{
|
||||
return p ? p->c_ispeed : B0;
|
||||
}
|
||||
|
||||
speed_t cfgetospeed(const struct termios *p)
|
||||
{
|
||||
return p ? p->c_ospeed : B0;
|
||||
}
|
||||
|
||||
int cfsetispeed(struct termios *p, speed_t sp)
|
||||
{
|
||||
if (p) {
|
||||
p->c_ispeed = sp;
|
||||
return 0;
|
||||
} else {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
int cfsetospeed(struct termios *p, speed_t sp)
|
||||
{
|
||||
if (p) {
|
||||
p->c_ospeed = sp;
|
||||
return 0;
|
||||
} else {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // CONFIG_SUPPORT_TERMIOS
|
||||
@@ -1,263 +0,0 @@
|
||||
// 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 <stdint.h>
|
||||
#include <reent.h>
|
||||
#include <time.h>
|
||||
#include <sys/times.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/errno.h>
|
||||
|
||||
#include "esp_system.h"
|
||||
#include "esp_timer.h"
|
||||
#include "rom/ets_sys.h"
|
||||
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
#include "driver/soc.h"
|
||||
|
||||
#include "limits.h"
|
||||
#include "sdkconfig.h"
|
||||
|
||||
#ifdef CONFIG_ESP8266_TIME_SYSCALL_USE_FRC1
|
||||
#define WITH_FRC 1
|
||||
#endif
|
||||
|
||||
static uint64_t s_boot_time;
|
||||
|
||||
#if defined(WITH_RTC) || defined(WITH_FRC)
|
||||
// stores the start time of the slew
|
||||
static uint64_t adjtime_start = 0;
|
||||
// is how many microseconds total to slew
|
||||
static int64_t adjtime_total_correction = 0;
|
||||
#define ADJTIME_CORRECTION_FACTOR 6
|
||||
static uint64_t get_time_since_boot(void);
|
||||
#endif
|
||||
// Offset between FRC timer and the RTC.
|
||||
// Initialized after reset or light sleep.
|
||||
#if defined(WITH_RTC) && defined(WITH_FRC)
|
||||
uint64_t s_microseconds_offset;
|
||||
#endif
|
||||
|
||||
static inline void set_boot_time(uint64_t time_us)
|
||||
{
|
||||
esp_irqflag_t flag;
|
||||
|
||||
flag = soc_save_local_irq();
|
||||
s_boot_time = time_us;
|
||||
soc_restore_local_irq(flag);
|
||||
}
|
||||
|
||||
static inline uint64_t get_boot_time()
|
||||
{
|
||||
uint64_t result;
|
||||
esp_irqflag_t flag;
|
||||
|
||||
flag = soc_save_local_irq();
|
||||
result = s_boot_time;
|
||||
soc_restore_local_irq(flag);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// This function gradually changes boot_time to the correction value and immediately updates it.
|
||||
static uint64_t adjust_boot_time(void)
|
||||
{
|
||||
uint64_t boot_time = get_boot_time();
|
||||
if ((boot_time == 0) || (get_time_since_boot() < adjtime_start)) {
|
||||
adjtime_start = 0;
|
||||
}
|
||||
if (adjtime_start > 0) {
|
||||
uint64_t since_boot = get_time_since_boot();
|
||||
// If to call this function once per second, then (since_boot - adjtime_start) will be 1_000_000 (1 second),
|
||||
// and the correction will be equal to (1_000_000us >> 6) = 15_625 us.
|
||||
// The minimum possible correction step can be (64us >> 6) = 1us.
|
||||
// Example: if the time error is 1 second, then it will be compensate for 1 sec / 0,015625 = 64 seconds.
|
||||
int64_t correction = (since_boot >> ADJTIME_CORRECTION_FACTOR) - (adjtime_start >> ADJTIME_CORRECTION_FACTOR);
|
||||
if (correction > 0) {
|
||||
adjtime_start = since_boot;
|
||||
if (adjtime_total_correction < 0) {
|
||||
if ((adjtime_total_correction + correction) >= 0) {
|
||||
boot_time = boot_time + adjtime_total_correction;
|
||||
adjtime_start = 0;
|
||||
} else {
|
||||
adjtime_total_correction += correction;
|
||||
boot_time -= correction;
|
||||
}
|
||||
} else {
|
||||
if ((adjtime_total_correction - correction) <= 0) {
|
||||
boot_time = boot_time + adjtime_total_correction;
|
||||
adjtime_start = 0;
|
||||
} else {
|
||||
adjtime_total_correction -= correction;
|
||||
boot_time += correction;
|
||||
}
|
||||
}
|
||||
set_boot_time(boot_time);
|
||||
}
|
||||
}
|
||||
return boot_time;
|
||||
}
|
||||
|
||||
#if defined( WITH_FRC ) || defined( WITH_RTC )
|
||||
static uint64_t get_time_since_boot(void)
|
||||
{
|
||||
uint64_t microseconds = 0;
|
||||
#ifdef WITH_FRC
|
||||
#ifdef WITH_RTC
|
||||
microseconds = s_microseconds_offset + esp_timer_get_time();
|
||||
#else
|
||||
microseconds = esp_timer_get_time();
|
||||
#endif // WITH_RTC
|
||||
#elif defined(WITH_RTC)
|
||||
microseconds = get_rtc_time_us();
|
||||
#endif // WITH_FRC
|
||||
return microseconds;
|
||||
}
|
||||
#endif // defined( WITH_FRC ) || defined( WITH_RTC
|
||||
|
||||
int adjtime(const struct timeval *delta, struct timeval *outdelta)
|
||||
{
|
||||
#if defined( WITH_FRC ) || defined( WITH_RTC )
|
||||
esp_irqflag_t flag;
|
||||
if(delta != NULL){
|
||||
int64_t sec = delta->tv_sec;
|
||||
int64_t usec = delta->tv_usec;
|
||||
if(llabs(sec) > ((INT_MAX / 1000000L) - 1L)) {
|
||||
return -1;
|
||||
}
|
||||
/*
|
||||
* If adjusting the system clock by adjtime () is already done during the second call adjtime (),
|
||||
* and the delta of the second call is not NULL, the earlier tuning is stopped,
|
||||
* but the already completed part of the adjustment is not canceled.
|
||||
*/
|
||||
flag = soc_save_local_irq();
|
||||
// If correction is already in progress (adjtime_start != 0), then apply accumulated corrections.
|
||||
adjust_boot_time();
|
||||
adjtime_start = get_time_since_boot();
|
||||
adjtime_total_correction = sec * 1000000L + usec;
|
||||
soc_restore_local_irq(flag);
|
||||
}
|
||||
if(outdelta != NULL){
|
||||
flag = soc_save_local_irq();
|
||||
adjust_boot_time();
|
||||
if (adjtime_start != 0) {
|
||||
outdelta->tv_sec = adjtime_total_correction / 1000000L;
|
||||
outdelta->tv_usec = adjtime_total_correction % 1000000L;
|
||||
} else {
|
||||
outdelta->tv_sec = 0;
|
||||
outdelta->tv_usec = 0;
|
||||
}
|
||||
soc_restore_local_irq(flag);
|
||||
}
|
||||
return 0;
|
||||
#else
|
||||
return -1;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
int _gettimeofday_r(struct _reent* r, struct timeval* tv, void* tz)
|
||||
{
|
||||
(void) tz;
|
||||
|
||||
if (tv) {
|
||||
uint64_t microseconds = get_boot_time() + (uint64_t)esp_timer_get_time();
|
||||
tv->tv_sec = microseconds / 1000000;
|
||||
tv->tv_usec = microseconds % 1000000;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int settimeofday(const struct timeval* tv, const struct timezone* tz)
|
||||
{
|
||||
(void) tz;
|
||||
|
||||
if (tv) {
|
||||
uint64_t now = ((uint64_t) tv->tv_sec) * 1000000LL + tv->tv_usec;
|
||||
uint64_t since_boot = (uint64_t)esp_timer_get_time();
|
||||
set_boot_time(now - since_boot);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
clock_t _times_r(struct _reent *r, struct tms *tms)
|
||||
{
|
||||
tms->tms_utime = xTaskGetTickCount();
|
||||
tms->tms_stime = 0;
|
||||
tms->tms_cutime = 0;
|
||||
tms->tms_cstime = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int usleep(useconds_t us)
|
||||
{
|
||||
const int us_per_tick = portTICK_PERIOD_MS * 1000;
|
||||
|
||||
if (us < us_per_tick) {
|
||||
ets_delay_us((uint32_t) us);
|
||||
} else {
|
||||
/* since vTaskDelay(1) blocks for anywhere between 0 and portTICK_PERIOD_MS,
|
||||
* round up to compensate.
|
||||
*/
|
||||
vTaskDelay((us + us_per_tick - 1) / us_per_tick);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned int sleep(unsigned int seconds)
|
||||
{
|
||||
vTaskDelay(seconds * (1000 / portTICK_PERIOD_MS));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int clock_gettime (clockid_t clock_id, struct timespec *tp)
|
||||
{
|
||||
#if defined( WITH_FRC ) || defined( WITH_RTC )
|
||||
if (tp == NULL) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
struct timeval tv;
|
||||
uint64_t monotonic_time_us = 0;
|
||||
switch (clock_id) {
|
||||
case CLOCK_REALTIME:
|
||||
_gettimeofday_r(NULL, &tv, NULL);
|
||||
tp->tv_sec = tv.tv_sec;
|
||||
tp->tv_nsec = tv.tv_usec * 1000L;
|
||||
break;
|
||||
case CLOCK_MONOTONIC:
|
||||
#if defined( WITH_FRC )
|
||||
monotonic_time_us = (uint64_t) esp_timer_get_time();
|
||||
#elif defined( WITH_RTC )
|
||||
monotonic_time_us = get_rtc_time_us();
|
||||
#endif // WITH_FRC
|
||||
tp->tv_sec = monotonic_time_us / 1000000LL;
|
||||
tp->tv_nsec = (monotonic_time_us % 1000000LL) * 1000L;
|
||||
break;
|
||||
default:
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
#else
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
Reference in New Issue
Block a user