Skip to content

Commit 5bddd88

Browse files
authored
Merge pull request #4406 from kjbracey-arm/shared_equeues
mbed_events.h: Add ability to request a shared event queue
2 parents abafc6e + b55af5c commit 5bddd88

File tree

5 files changed

+181
-31
lines changed

5 files changed

+181
-31
lines changed

events/mbed_events.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@
2828
#include "events/EventQueue.h"
2929
#include "events/Event.h"
3030

31+
#include "events/mbed_shared_queues.h"
32+
3133
using namespace events;
3234

3335
#endif

events/mbed_lib.json

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,26 @@
11
{
22
"name": "events",
33
"config": {
4-
"present": 1
4+
"present": 1,
5+
"shared-stacksize": {
6+
"help": "Stack size (bytes) for shared event queue thread",
7+
"value": 1024
8+
},
9+
"shared-eventsize": {
10+
"help": "Event buffer size (bytes) for shared event queue",
11+
"value": 256
12+
},
13+
"shared-dispatch-from-application": {
14+
"help": "No thread created for shared event queue - application will call dispatch from another thread (eg dispatch_forever at end of main)",
15+
"value": false
16+
},
17+
"shared-highprio-stacksize": {
18+
"help": "Stack size (bytes) for shared high-priority event queue thread",
19+
"value": 1024
20+
},
21+
"shared-highprio-eventsize": {
22+
"help": "Event buffer size (bytes) for shared high-priority event queue",
23+
"value": 256
24+
}
525
}
626
}

events/mbed_shared_queues.cpp

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
/* events
2+
* Copyright (c) 2017 ARM Limited
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
#include "events/mbed_shared_queues.h"
18+
#include "mbed.h"
19+
20+
using namespace events;
21+
22+
namespace mbed {
23+
24+
#ifdef MBED_CONF_RTOS_PRESENT
25+
/* Create an event queue, and start the thread that dispatches it. Static
26+
* variables mean this happens once the first time each template instantiation
27+
* is called. This is currently instantiated no more than twice.
28+
*/
29+
template
30+
<osPriority Priority, size_t QueueSize, size_t StackSize>
31+
EventQueue *do_shared_event_queue_with_thread()
32+
{
33+
static uint64_t queue_buffer[QueueSize / sizeof(uint64_t)];
34+
static EventQueue queue(sizeof queue_buffer, (unsigned char *) queue_buffer);
35+
36+
static uint64_t stack[StackSize / sizeof(uint64_t)];
37+
static Thread thread(Priority, StackSize, (unsigned char *) stack);
38+
39+
Thread::State state = thread.get_state();
40+
if (state == Thread::Inactive || state == Thread::Deleted) {
41+
osStatus status = thread.start(callback(&queue, &EventQueue::dispatch_forever));
42+
MBED_ASSERT(status == osOK);
43+
if (status != osOK) {
44+
return NULL;
45+
}
46+
}
47+
48+
return &queue;
49+
}
50+
#endif
51+
52+
EventQueue *mbed_event_queue()
53+
{
54+
#if MBED_CONF_EVENTS_SHARED_DISPATCH_FROM_APPLICATION || !defined MBED_CONF_RTOS_PRESENT
55+
/* Only create the EventQueue, but no dispatching thread */
56+
static unsigned char queue_buffer[MBED_CONF_EVENTS_SHARED_EVENTSIZE];
57+
static EventQueue queue(sizeof queue_buffer, queue_buffer);
58+
59+
return &queue;
60+
#else
61+
return do_shared_event_queue_with_thread<osPriorityNormal, MBED_CONF_EVENTS_SHARED_EVENTSIZE, MBED_CONF_EVENTS_SHARED_STACKSIZE>();
62+
#endif
63+
}
64+
65+
#ifdef MBED_CONF_RTOS_PRESENT
66+
EventQueue *mbed_highprio_event_queue()
67+
{
68+
return do_shared_event_queue_with_thread<osPriorityHigh, MBED_CONF_EVENTS_SHARED_HIGHPRIO_EVENTSIZE, MBED_CONF_EVENTS_SHARED_HIGHPRIO_STACKSIZE>();
69+
}
70+
#endif
71+
72+
}

events/mbed_shared_queues.h

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
2+
/** \addtogroup events */
3+
/** @{*/
4+
/* events
5+
* Copyright (c) 2017 ARM Limited
6+
*
7+
* Licensed under the Apache License, Version 2.0 (the "License");
8+
* you may not use this file except in compliance with the License.
9+
* You may obtain a copy of the License at
10+
*
11+
* http://www.apache.org/licenses/LICENSE-2.0
12+
*
13+
* Unless required by applicable law or agreed to in writing, software
14+
* distributed under the License is distributed on an "AS IS" BASIS,
15+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+
* See the License for the specific language governing permissions and
17+
* limitations under the License.
18+
*/
19+
#ifndef MBED_SHARED_QUEUES_H
20+
#define MBED_SHARED_QUEUES_H
21+
22+
#include "events/EventQueue.h"
23+
24+
namespace mbed {
25+
26+
/**
27+
* Return a pointer to an EventQueue, on which normal tasks can be queued.
28+
*
29+
* All calls to this return the same EventQueue - it and its dispatch thread
30+
* are created on the first call to this function. The dispatch thread
31+
* runs at default priority (currently osPriorityNormal).
32+
*
33+
* The EventQueue returned may be used to call() Events, or to chain() other
34+
* EventQueues so that they are run in the same context.
35+
*
36+
* Events (or chained EventQueues) executing on the normal event queue should
37+
* normally take less than 10ms to execute, to avoid starving other users. As
38+
* such, users can expect that event latency will typically be 10ms or less,
39+
* but could occasionally be significantly higher if many events are queued.
40+
*
41+
* If an RTOS is not present or the configuration option
42+
* `events.shared-dispatch-from-application` is set to true, then this
43+
* does not create a dedicated dispatch thread - instead the application is
44+
* expected to run the EventQueue's dispatch, eg from main. This is necessary
45+
* for the event loop to work without an RTOS, or an RTOS system can can save
46+
* memory by reusing the main stack.
47+
*
48+
* @return pointer to event queue
49+
*/
50+
events::EventQueue *mbed_event_queue();
51+
52+
#ifdef MBED_CONF_RTOS_PRESENT
53+
/**
54+
* Return a pointer to an EventQueue, on which small high-priority tasks can
55+
* be queues, such as simple deferrals from interrupt.
56+
*
57+
* All calls to this return the same EventQueue - it and its thread are
58+
* created on the first call to this function. The dispatch thread
59+
* runs at a high priority (currently osPriorityHigh).
60+
*
61+
* The EventQueue returned may be used to call() Events, or to chain() other
62+
* EventQueues so that they are run in the same context.
63+
*
64+
* Events (or chained EventQueues) executing on the high-priority event queue
65+
* should normally take less than 100us to execute, to avoid starving other
66+
* users. As such, users can expect that event latency will typically be 100us
67+
* or less, but could occasionally be significantly higher if many events are
68+
* queued.
69+
*
70+
* @return pointer to high-priority event queue
71+
*/
72+
73+
events::EventQueue *mbed_highprio_event_queue();
74+
75+
#endif // MBED_CONF_RTOS_PRESENT
76+
77+
};
78+
79+
#endif
80+
81+
/** @}*/

features/FEATURE_COMMON_PAL/nanostack-hal-mbed-cmsis-rtos/arm_hal_timer.cpp

Lines changed: 5 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -4,48 +4,23 @@
44

55
// Include before mbed.h to properly get UINT*_C()
66
#include "ns_types.h"
7+
78
#include "mbed.h"
8-
#include "cmsis_os2.h"
9-
#include "rtx_os.h"
109
#include "platform/arm_hal_timer.h"
1110
#include "platform/arm_hal_interrupt.h"
1211
#include <mbed_assert.h>
1312

14-
static osThreadId_t timer_thread_id;
15-
static uint64_t timer_thread_stk[2048/sizeof(uint64_t)];
16-
static osRtxThread_t timer_thread_tcb;
17-
1813
static Timer timer;
1914
static Timeout timeout;
15+
static EventQueue *equeue;
2016
static uint32_t due;
2117
static void (*arm_hal_callback)(void);
2218

23-
static void timer_thread(void *arg)
24-
{
25-
(void)arg;
26-
for (;;) {
27-
osThreadFlagsWait(1, osFlagsWaitAny, osWaitForever);
28-
// !!! We don't do our own enter/exit critical - we rely on callback
29-
// doing it (ns_timer_interrupt_handler does)
30-
//platform_enter_critical();
31-
arm_hal_callback();
32-
//platform_exit_critical();
33-
}
34-
}
35-
3619
// Called once at boot
3720
void platform_timer_enable(void)
3821
{
39-
static osThreadAttr_t timer_thread_attr = {0};
40-
timer_thread_attr.name = "pal_timer_thread";
41-
timer_thread_attr.stack_mem = &timer_thread_stk[0];
42-
timer_thread_attr.cb_mem = &timer_thread_tcb;
43-
timer_thread_attr.stack_size = sizeof(timer_thread_stk);
44-
timer_thread_attr.cb_size = sizeof(timer_thread_tcb);
45-
timer_thread_attr.priority = osPriorityRealtime;
46-
timer_thread_id = osThreadNew(timer_thread, NULL, &timer_thread_attr);
47-
MBED_ASSERT(timer_thread_id != NULL);
48-
timer.start();
22+
equeue = mbed_highprio_event_queue();
23+
MBED_ASSERT(equeue != NULL);
4924
}
5025

5126
// Actually cancels a timer, not the opposite of enable
@@ -63,7 +38,7 @@ void platform_timer_set_cb(void (*new_fp)(void))
6338
static void timer_callback(void)
6439
{
6540
due = 0;
66-
osThreadFlagsSet(timer_thread_id, 1);
41+
equeue->call(arm_hal_callback);
6742
}
6843

6944
// This is called from inside platform_enter_critical - IRQs can't happen

0 commit comments

Comments
 (0)