Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers ns_event_loop.c Source File

ns_event_loop.c

00001 /*
00002  * Copyright (c) 2016 ARM Limited, All Rights Reserved
00003  */
00004 
00005 #include <mbed_assert.h>
00006 #include "cmsis.h"
00007 #include "cmsis_os2.h"
00008 #include "mbed_rtos_storage.h"
00009 #include "ns_trace.h"
00010 
00011 #include "eventOS_scheduler.h"
00012 
00013 #include "ns_event_loop.h"
00014 
00015 #define TRACE_GROUP "evlp"
00016 
00017 
00018 #if MBED_CONF_NANOSTACK_HAL_EVENT_LOOP_DISPATCH_FROM_APPLICATION
00019 
00020 static mbed_rtos_storage_event_flags_t event_flag_cb;
00021 static const osEventFlagsAttr_t event_flags_attr = {
00022     .name = "nanostack_event_flags",
00023     .cb_mem = &event_flag_cb,
00024     .cb_size = sizeof event_flag_cb
00025 };
00026 static osEventFlagsId_t event_flag_id;
00027 
00028 #else
00029 
00030 static void event_loop_thread(void *arg);
00031 
00032 static uint64_t event_thread_stk[MBED_CONF_NANOSTACK_HAL_EVENT_LOOP_THREAD_STACK_SIZE/8];
00033 static mbed_rtos_storage_thread_t event_thread_tcb;
00034 static const osThreadAttr_t event_thread_attr = {
00035     .name = "nanostack_event_thread",
00036     .priority = osPriorityNormal,
00037     .stack_mem = &event_thread_stk[0],
00038     .stack_size = sizeof event_thread_stk,
00039     .cb_mem = &event_thread_tcb,
00040     .cb_size = sizeof event_thread_tcb,
00041 };
00042 #endif
00043 
00044 static osThreadId_t event_thread_id;
00045 static mbed_rtos_storage_mutex_t event_mutex;
00046 static const osMutexAttr_t event_mutex_attr = {
00047   .name = "nanostack_event_mutex",
00048   .attr_bits = osMutexRecursive | osMutexPrioInherit | osMutexRobust,
00049   .cb_mem = &event_mutex,
00050   .cb_size = sizeof event_mutex,
00051 };
00052 static osMutexId_t event_mutex_id;
00053 static osThreadId_t event_mutex_owner_id = NULL;
00054 static uint32_t owner_count = 0;
00055 
00056 void eventOS_scheduler_mutex_wait(void)
00057 {
00058     osMutexAcquire(event_mutex_id, osWaitForever);
00059     if (0 == owner_count) {
00060         event_mutex_owner_id = osThreadGetId();
00061     }
00062     owner_count++;
00063 }
00064 
00065 void eventOS_scheduler_mutex_release(void)
00066 {
00067     owner_count--;
00068     if (0 == owner_count) {
00069         event_mutex_owner_id = NULL;
00070     }
00071     osMutexRelease(event_mutex_id);
00072 }
00073 
00074 uint8_t eventOS_scheduler_mutex_is_owner(void)
00075 {
00076     return osThreadGetId() == event_mutex_owner_id ? 1 : 0;
00077 }
00078 
00079 void eventOS_scheduler_signal(void)
00080 {
00081     // XXX why does signal set lock if called with irqs disabled?
00082     //__enable_irq();
00083     //tr_debug("signal %p", (void*)event_thread_id);
00084 #if MBED_CONF_NANOSTACK_HAL_EVENT_LOOP_DISPATCH_FROM_APPLICATION
00085     osEventFlagsSet(event_flag_id, 1);
00086 #else
00087     osThreadFlagsSet(event_thread_id, 1);
00088 #endif
00089     //tr_debug("signalled %p", (void*)event_thread_id);
00090 }
00091 
00092 void eventOS_scheduler_idle(void)
00093 {
00094     //tr_debug("idle");
00095     eventOS_scheduler_mutex_release();
00096 
00097 #if MBED_CONF_NANOSTACK_HAL_EVENT_LOOP_DISPATCH_FROM_APPLICATION
00098     osEventFlagsWait(event_flag_id, 1, osFlagsWaitAny, osWaitForever);
00099 #else
00100     osThreadFlagsWait(1, 0, osWaitForever);
00101 #endif
00102 
00103     eventOS_scheduler_mutex_wait();
00104 }
00105 
00106 #if !MBED_CONF_NANOSTACK_HAL_EVENT_LOOP_DISPATCH_FROM_APPLICATION
00107 static void event_loop_thread(void *arg)
00108 {
00109     (void)arg;
00110     eventOS_scheduler_mutex_wait();
00111     eventOS_scheduler_run(); //Does not return
00112 }
00113 #endif
00114 
00115 // This is used to initialize the lock used by event loop even
00116 // if it is not ran in a separate thread.
00117 void ns_event_loop_init(void)
00118 {
00119     event_mutex_id = osMutexNew(&event_mutex_attr);
00120     MBED_ASSERT(event_mutex_id != NULL);
00121 
00122     // If a separate event loop thread is not used, the signaling
00123     // happens via event flags instead of thread flags. This allows one to
00124     // perform the initialization from any thread and removes need to know the id
00125     // of event loop dispatch thread.
00126 #if MBED_CONF_NANOSTACK_HAL_EVENT_LOOP_DISPATCH_FROM_APPLICATION
00127     event_flag_id  = osEventFlagsNew(&event_flags_attr);
00128     MBED_ASSERT(event_flag_id != NULL);
00129 #endif
00130 }
00131 
00132 #if !MBED_CONF_NANOSTACK_HAL_EVENT_LOOP_DISPATCH_FROM_APPLICATION
00133 void ns_event_loop_thread_create(void)
00134 {
00135     event_thread_id = osThreadNew(event_loop_thread, NULL, &event_thread_attr);
00136     MBED_ASSERT(event_thread_id != NULL);
00137 }
00138 
00139 void ns_event_loop_thread_start(void)
00140 {
00141 }
00142 #endif