35#ifndef _DEFAULT_SOURCE
36#define _DEFAULT_SOURCE
40#define OS_INLINE extern
45#if !defined (GCC_MEGA_AVR)
49#if defined (__FreeRTOS__)
54#elif defined(__WIN32__)
61#elif defined(ESP_NONOS)
63#include <sys/select.h>
66#include <user_interface.h>
70#include <sys/select.h>
102#define DELETED_TASK_MAGIC 0xb5c5d5e5
109#if defined(TARGET_PIC32MX) || defined(ESP_NONOS)
112#ifndef _READ_WRITE_RETURN_TYPE
113#define _READ_WRITE_RETURN_TYPE ssize_t
116int open(
const char* b,
int flags, ...)
118 return _open_r(_impure_ptr, b, flags, 0);
122 return _close_r(_impure_ptr, fd);
124_READ_WRITE_RETURN_TYPE read(
int fd,
void* buf,
size_t count)
126 return _read_r(_impure_ptr, fd, buf, count);
128_READ_WRITE_RETURN_TYPE write(
int fd,
const void* buf,
size_t count)
130 return _write_r(_impure_ptr, fd, buf, count);
132off_t lseek(
int fd, off_t offset,
int whence)
134 return _lseek_r(_impure_ptr, fd, offset, whence);
136int fstat(
int fd,
struct stat* buf)
138 return _fstat_r(_impure_ptr, fd, buf);
144#if OPENMRN_FEATURE_THREAD_FREERTOS
146typedef struct task_list
151 struct task_list *next;
158 void *(*entry)(
void*);
164static TaskList *taskList = NULL;
167static os_mutex_t onceMutex = OS_MUTEX_INITIALIZER;
172void hw_init(
void) __attribute__ ((weak));
182void hw_postinit(
void) __attribute__ ((weak));
183void hw_postinit(
void)
194 if (xTaskGetSchedulerState() == taskSCHEDULER_RUNNING)
198 if (once->state == OS_THREAD_ONCE_NEVER)
200 once->state = OS_THREAD_ONCE_INPROGRESS;
204 once->state = OS_THREAD_ONCE_DONE;
207 while (once->state == OS_THREAD_ONCE_INPROGRESS)
219 if (once->state == OS_THREAD_ONCE_NEVER)
221 once->state = OS_THREAD_ONCE_INPROGRESS;
223 once->state = OS_THREAD_ONCE_DONE;
231#if defined (__WIN32__)
236int pipe(
int fildes[2])
239 int listener, connector, acceptor;
249 closesocket(listener);
254 memset(&addr, 0,
sizeof(addr));
256 addr.sin_addr.s_addr =
htonl(INADDR_LOOPBACK);
261 (
char*)&reuse, (
socklen_t)
sizeof(reuse)) < 0)
263 closesocket(listener);
264 closesocket(connector);
269 if (
bind(listener, (
const struct sockaddr*)&addr,
sizeof(addr)) < 0)
271 closesocket(listener);
272 closesocket(connector);
279 closesocket(listener);
280 closesocket(connector);
285 if (
listen(listener, 1) < 0)
287 closesocket(listener);
288 closesocket(connector);
295 closesocket(listener);
296 closesocket(connector);
301 if ((acceptor =
accept(listener, NULL, NULL)) < 0)
303 closesocket(listener);
304 closesocket(connector);
313 fildes[0] = connector;
314 fildes[1] = acceptor;
315 closesocket(listener);
320#if OPENMRN_FEATURE_THREAD_FREERTOS
326void add_thread_to_task_list(TaskList *task_new)
329 task_new->next = taskList;
337void del_thread_from_task_list(TaskHandle_t task_handle)
341 for (tl = taskList; tl != NULL && tl->task != task_handle; tl = tl->next)
355void __attribute__((weak)) os_thread_start_entry_hook(
void)
362void __attribute__((weak)) os_thread_start_exit_hook(
void *context)
370void os_thread_start(
void *arg)
372 os_thread_start_entry_hook();
375 OSThreadStartPriv *priv = (OSThreadStartPriv*)arg;
376 priv->taskList->task = xTaskGetCurrentTaskHandle();
377 add_thread_to_task_list(priv->taskList);
379#if OPENMRN_FEATURE_DEVICE_SELECT
381#if tskKERNEL_VERSION_MAJOR >= 9
383 vTaskSetThreadLocalStoragePointer(NULL, TLS_INDEX_SELECT_EVENT_BIT, NULL);
386 vTaskSetApplicationTaskTag(NULL, NULL);
391 void *result = (*priv->entry)(priv->arg);
394 del_thread_from_task_list(xTaskGetCurrentTaskHandle());
401 os_thread_start_exit_hook(result);
405#ifndef OPENMRN_FEATURE_SINGLE_THREADED
407#if OPENMRN_FEATURE_THREAD_FREERTOS
417int __attribute__((weak)) os_thread_create_helper(os_thread_t *thread,
424#if (configSUPPORT_DYNAMIC_ALLOCATION == 1)
425 xTaskCreate(os_thread_start, (
const char *
const)name,
426 stack_size/
sizeof(portSTACK_TYPE), priv, priority, thread);
427#elif (configSUPPORT_STATIC_ALLOCATION == 1)
428 *thread = xTaskCreateStatic(os_thread_start, (
const char *
const)name,
429 stack_size/
sizeof(portSTACK_TYPE), priv,
432 (StaticTask_t *) malloc(
sizeof(StaticTask_t)));
434#error FREERTOS version v9.0.0 or later required
451 size_t stack_size,
void *(*start_routine) (
void *),
454 static unsigned int count = 0;
459 strcpy(auto_name,
"thread.");
461 auto_name[8] =
'0' + (count % 10);
462 auto_name[7] =
'0' + (count / 10);
467#if OPENMRN_FEATURE_THREAD_FREERTOS
468 OSThreadStartPriv *priv =
469 (OSThreadStartPriv*)malloc(
sizeof(OSThreadStartPriv));
471 priv->taskList = (TaskList*)malloc(
sizeof(TaskList));
472 priv->taskList->name = NULL;
473 priv->entry = start_routine;
476 priv->taskList->unused = stack_size;
479 priority = configMAX_PRIORITIES / 2;
481 else if (priority >= configMAX_PRIORITIES)
483 priority = configMAX_PRIORITIES - 1;
491 os_thread_t local_thread;
492 int result = os_thread_create_helper(&local_thread, name, priority,
496 priv->taskList->task = local_thread;
497 priv->taskList->name = (
char*)pcTaskGetTaskName(local_thread);
500 *thread = local_thread;
505#if OPENMRN_FEATURE_THREAD_PTHREAD
508 int result = pthread_attr_init(&attr);
513 result = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
519#if OPENMRN_FEATURE_PTHREAD_SETSTACK
520 struct sched_param sched_param;
521 result = pthread_attr_setstacksize(&attr, stack_size);
527 sched_param.sched_priority = 0;
528 result = pthread_attr_setschedparam(&attr, &sched_param);
534 result = pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED);
540 result = pthread_attr_setschedpolicy(&attr, SCHED_FIFO);
546 pthread_t local_thread_handle;
549 thread = &local_thread_handle;
551 result = pthread_create(thread, &attr, start_routine, arg);
553#if OPENMRN_HAVE_PTHREAD_SETNAME
556 pthread_setname_np(*thread, name);
573 static long long last = 0;
575#if defined (__FreeRTOS__)
576 portTickType tick = xTaskGetTickCount();
577 time = ((
long long)tick) << NSEC_TO_TICK_SHIFT;
579#elif defined (__MACH__)
581 mach_timebase_info_data_t info;
582 mach_timebase_info(&info);
585 time = (
long long)mach_absolute_time();
590#elif defined (__WIN32__)
592 gettimeofday(&tv, NULL);
593 time = ((
long long)tv.tv_sec * 1000LL * 1000LL * 1000LL) +
594 ((
long long)tv.tv_usec * 1000LL);
595#elif defined(ARDUINO)
597 unsigned long micros();
599 static uint32_t last_micros = 0;
600 static uint32_t overflow_micros = 0;
603 uint32_t new_micros = (uint32_t) micros();
604 if (new_micros < last_micros)
608 last_micros = new_micros;
611 time = overflow_micros;
615#elif defined(ESP_NONOS)
616 static uint32_t clockmul = 0;
618 clockmul = system_rtc_clock_cali_proc();
622 time = system_get_rtc_time();
628#if defined (__nuttx__)
629 clock_gettime(CLOCK_REALTIME, &ts);
631 clock_gettime(CLOCK_MONOTONIC, &ts);
633 time = ((
long long)ts.tv_sec * 1000000000LL) + ts.tv_nsec;
662#if defined(__EMSCRIPTEN__)
665 if (once->state == OS_THREAD_ONCE_NEVER)
667 once->state = OS_THREAD_ONCE_INPROGRESS;
669 once->state = OS_THREAD_ONCE_DONE;
671 else if (once->state == OS_THREAD_ONCE_INPROGRESS)
673 DIE(
"Recursive call to os_thread_once.");
679#if defined (__FreeRTOS__)
684void __malloc_lock(
void)
686 if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED)
694void __malloc_unlock(
void)
696 if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED)
702#if defined (_REENT_SMALL)
703void *__real__malloc_r(
size_t size);
704void __real__free_r(
void *address);
710void *__wrap__malloc_r(
size_t size)
714 result = __real__malloc_r(size);
722void __wrap__free_r(
void *address)
725 __real__free_r(address);
733unsigned sleep(
unsigned seconds)
735 vTaskDelay(seconds * configTICK_RATE_HZ);
742int usleep(useconds_t usec)
744 long long nsec = usec;
746 vTaskDelay(nsec >> NSEC_TO_TICK_SHIFT);
752#if defined(TARGET_LPC2368) || defined(TARGET_LPC11Cxx) || \
753 defined(TARGET_LPC1768) || defined(GCC_ARMCM3) || defined (GCC_ARMCM0) || \
754 defined(TARGET_PIC32MX)
763char __attribute__((weak)) __heap2_start_alias;
764extern char __heap2_start __attribute__((weak, alias (
"__heap2_start_alias")));
765extern char __heap2_end __attribute__((weak, alias (
"__heap2_start_alias")));
767extern char *heap_end;
769extern char *heap2_end;
771void* _sbrk_r(
struct _reent *reent, ptrdiff_t incr)
774 extern char __cs3_heap_start;
775 extern char __cs3_heap_end;
779 heap_end = &__cs3_heap_start;
783 heap2_end = &__heap2_start;
785 prev_heap_end = heap_end;
786 if ((heap_end + incr) > &__cs3_heap_end)
788 if (&__heap2_start != &__heap2_end)
791 char *prev_heap2_end;
792 prev_heap2_end = heap2_end;
793 if ((heap2_end + incr) <= &__heap2_end)
796 return (caddr_t) prev_heap2_end;
804 return (caddr_t) prev_heap_end;
810 extern char __cs3_heap_end;
811 uint32_t fh = &__cs3_heap_end - heap_end;
812 fh += (&__heap2_end - heap2_end);
816xTaskHandle
volatile overflowed_task = 0;
817signed portCHAR *
volatile overflowed_task_name = 0;
823void vApplicationStackOverflowHook(xTaskHandle task,
signed portCHAR *name)
825 overflowed_task = task;
826 overflowed_task_name = name;
833void hw_idle_hook(
void) __attribute__((weak));
835void hw_idle_hook(
void)
841void vApplicationIdleHook(
void )
846 for (TaskList **ptl = &taskList; *ptl != NULL;)
856 ptl = &((*ptl)->next);
860 for (TaskList *tl = taskList; tl != NULL; tl = tl->next)
864 tl->unused = uxTaskGetStackHighWaterMark(tl->task) *
865 sizeof(portSTACK_TYPE);
874static void __attribute__((nomips16)) os_yield_trampoline(
void)
879void __attribute__((nomips16)) os_isr_exit_yield_test(
int woken)
881 portEND_SWITCHING_ISR(woken);
885static inline void __attribute__((always_inline)) os_yield_trampoline(
void)
895static void *main_thread(
void *unused)
897 char *argv[2] = {(
char*)
"openmrn", NULL};
900 os_yield_trampoline();
928#if !defined(ARDUINO) && !defined(ESP_PLATFORM)
930#if !defined (__MINGW32__)
931int main(
int argc,
char *argv[]) __attribute__ ((weak));
939int main(
int argc,
char *argv[])
941#if defined (__FreeRTOS__)
945#ifndef TARGET_LPC11Cxx
949 open(
"/dev/null", O_RDWR);
954 open(
"/dev/null", O_RDWR);
959 open(
"/dev/null", O_WRONLY);
964 if (config_main_thread_priority() == 0xdefa01)
966 priority = configMAX_PRIORITIES / 2;
970 priority = config_main_thread_priority();
974 config_main_thread_stack_size(), main_thread, NULL);
976 vTaskStartScheduler();
978#if defined (__WIN32__)
981 WSAStartup(WINSOCK_VERSION, &wsa_data);
990unsigned critical_nesting;
993#if 0 && defined(ESP_NONOS)
994struct _reent *_impure_ptr = NULL;
int getsockname(int socket, struct sockaddr &addr, socklen_t &namelen)
Get the socket name.
int pipe(int pipefds[2])
Create a Unix style pipe.
int accept(int socket, struct sockaddr *address, socklen_t *address_len)
Accept a new connection on a socket.
int setsockopt(int socket, int level, int option_name, const void *option_value, socklen_t option_len)
Set the socket options.
int bind(int socket, const struct sockaddr *address, socklen_t address_len)
Bind a name to a socket.
int listen(int socket, int backlog)
Mark a connection-mode socket, specified by the socket argument, as accepting connections.
int connect(int socket, const struct sockaddr *address, socklen_t address_len)
Connect a socket.
int socket(int domain, int type, int protocol)
Create an unbound socket in a communications domain.
void diewith(uint32_t pattern)
Sets a blinking pattern and never returns.
#define BLINK_DIE_STACKOVERFLOW
Stack overflow.
#define BLINK_DIE_ABORT
abort() was called (usually due to an assertion failure or an uncaught C++ exception).
#define BLINK_DIE_OUTOFMEM
Out of memory. (sbrk failed to allocate memory).
void * stack_malloc(unsigned long length)
Custom malloc function for stack spaces.
#define IPPROTO_TCP
TCP Raw Socket.
#define htonl(x)
Converts a host endian long value to network endian.
#define HASSERT(x)
Checks that the value of expression x is true, else terminates the current process.
#define DIE(MSG)
Unconditionally terminates the current process with a message.
int main(int argc, char *argv[])
Entry point to program.
long long rtcOffset
clock management
const char * STDERR_DEVICE
default stderr
long long hw_get_partial_tick_time_nsec(void)
Implement this function to read timing more accurately than 1 msec in FreeRTOS.
int g_death_lineno
Captures point of death (line).
const char * STDIN_DEVICE
default stdin
int ignore_fn(void)
This function does nothing.
#define DELETED_TASK_MAGIC
This magic value is written to a task's taskList entry in order to signal the idle task to pick it ou...
const char * STDOUT_DEVICE
default stdout
const char * g_death_file
Captures point of death (file).
long long os_get_time_monotonic(void)
Get the monotonic time since the system started.
int os_thread_create(os_thread_t *thread, const char *name, int priority, size_t stack_size, void *(*start_routine)(void *), void *arg)
Create a thread.
ssize_t os_get_free_heap()
OS_INLINE int os_mutex_lock(os_mutex_t *mutex)
Lock a mutex.
OS_INLINE int os_thread_once(os_thread_once_t *once, void(*routine)(void))
One time intialization routine.
int appl_main(int argc, char *argv[])
Entry point to application.
#define MSEC_TO_USEC(_msec)
Convert a millisecond value to a microsecond value.
long long os_get_fake_time(void)
Get the fake time for a unit test.
OS_INLINE int os_mutex_unlock(os_mutex_t *mutex)
Unock a mutex.
void os_atomic_lock(void)
Locks a single global Atomic used to guard some OS structures.
void os_atomic_unlock(void)
Unlocks a single global Atomic used to guard some OS structures.
#define SOCK_STREAM
TCP Socket.
uint32_t socklen_t
type of sockaddr lenth
#define SO_REUSEADDR
socket option to reuse address
#define SOL_SOCKET
socket option category
#define AF_INET
IPv4 Socket (UDP, TCP, etc...)
Structure describing an Internet socket address.
#define TCP_NODELAY
don't delay send to coalesce packets