xref: /btstack/platform/chibios/btstack_run_loop_chibios.c (revision 065fc9a3d9ed4f0d223eff283968bd32564011a2)
1*065fc9a3SMatthias Ringwald /*
2*065fc9a3SMatthias Ringwald  * Copyright (C) 2022 BlueKitchen GmbH
3*065fc9a3SMatthias Ringwald  *
4*065fc9a3SMatthias Ringwald  * Redistribution and use in source and binary forms, with or without
5*065fc9a3SMatthias Ringwald  * modification, are permitted provided that the following conditions
6*065fc9a3SMatthias Ringwald  * are met:
7*065fc9a3SMatthias Ringwald  *
8*065fc9a3SMatthias Ringwald  * 1. Redistributions of source code must retain the above copyright
9*065fc9a3SMatthias Ringwald  *    notice, this list of conditions and the following disclaimer.
10*065fc9a3SMatthias Ringwald  * 2. Redistributions in binary form must reproduce the above copyright
11*065fc9a3SMatthias Ringwald  *    notice, this list of conditions and the following disclaimer in the
12*065fc9a3SMatthias Ringwald  *    documentation and/or other materials provided with the distribution.
13*065fc9a3SMatthias Ringwald  * 3. Neither the name of the copyright holders nor the names of
14*065fc9a3SMatthias Ringwald  *    contributors may be used to endorse or promote products derived
15*065fc9a3SMatthias Ringwald  *    from this software without specific prior written permission.
16*065fc9a3SMatthias Ringwald  * 4. Any redistribution, use, or modification is done solely for
17*065fc9a3SMatthias Ringwald  *    personal benefit and not for any commercial purpose or for
18*065fc9a3SMatthias Ringwald  *    monetary gain.
19*065fc9a3SMatthias Ringwald  *
20*065fc9a3SMatthias Ringwald  * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS
21*065fc9a3SMatthias Ringwald  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22*065fc9a3SMatthias Ringwald  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23*065fc9a3SMatthias Ringwald  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BLUEKITCHEN
24*065fc9a3SMatthias Ringwald  * GMBH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25*065fc9a3SMatthias Ringwald  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26*065fc9a3SMatthias Ringwald  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
27*065fc9a3SMatthias Ringwald  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
28*065fc9a3SMatthias Ringwald  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29*065fc9a3SMatthias Ringwald  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
30*065fc9a3SMatthias Ringwald  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31*065fc9a3SMatthias Ringwald  * SUCH DAMAGE.
32*065fc9a3SMatthias Ringwald  *
33*065fc9a3SMatthias Ringwald  * Please inquire about commercial licensing options at
34*065fc9a3SMatthias Ringwald  * [email protected]
35*065fc9a3SMatthias Ringwald  *
36*065fc9a3SMatthias Ringwald  */
37*065fc9a3SMatthias Ringwald 
38*065fc9a3SMatthias Ringwald /*
39*065fc9a3SMatthias Ringwald  *  btstack_run_loop_chibios.c
40*065fc9a3SMatthias Ringwald  *
41*065fc9a3SMatthias Ringwald  *  Run loop on dedicated thread on FreeRTOS
42*065fc9a3SMatthias Ringwald  *  The run loop is triggered from other task/ISRs either via Event Groups
43*065fc9a3SMatthias Ringwald  *  or Task Notifications if HAVE_FREERTOS_TASK_NOTIFICATIONS is defined
44*065fc9a3SMatthias Ringwald  */
45*065fc9a3SMatthias Ringwald 
46*065fc9a3SMatthias Ringwald #define BTSTACK_FILE__ "btstack_run_loop_chibios.c"
47*065fc9a3SMatthias Ringwald 
48*065fc9a3SMatthias Ringwald #include <stddef.h> // NULL
49*065fc9a3SMatthias Ringwald 
50*065fc9a3SMatthias Ringwald #include "btstack_run_loop_chibios.h"
51*065fc9a3SMatthias Ringwald 
52*065fc9a3SMatthias Ringwald #include "btstack_linked_list.h"
53*065fc9a3SMatthias Ringwald #include "btstack_debug.h"
54*065fc9a3SMatthias Ringwald #include "btstack_util.h"
55*065fc9a3SMatthias Ringwald #include "hal_time_ms.h"
56*065fc9a3SMatthias Ringwald 
57*065fc9a3SMatthias Ringwald #include "ch.h"
58*065fc9a3SMatthias Ringwald 
59*065fc9a3SMatthias Ringwald 
60*065fc9a3SMatthias Ringwald // main event
61*065fc9a3SMatthias Ringwald #define EVT_TRIGGER EVENT_MASK(0)
62*065fc9a3SMatthias Ringwald 
63*065fc9a3SMatthias Ringwald // checks, assert that these are enabled
64*065fc9a3SMatthias Ringwald // CH_CFG_USE_EVENTS
65*065fc9a3SMatthias Ringwald // CH_CFG_USE_EVENTS_TIMEOUT
66*065fc9a3SMatthias Ringwald 
67*065fc9a3SMatthias Ringwald static thread_t * btstack_thread;
68*065fc9a3SMatthias Ringwald static mutex_t btstack_run_loop_callbacks_mutex;
69*065fc9a3SMatthias Ringwald 
70*065fc9a3SMatthias Ringwald // the run loop
71*065fc9a3SMatthias Ringwald static bool run_loop_exit_requested;
72*065fc9a3SMatthias Ringwald 
btstack_run_loop_chibios_get_time_ms(void)73*065fc9a3SMatthias Ringwald static uint32_t btstack_run_loop_chibios_get_time_ms(void){
74*065fc9a3SMatthias Ringwald     return (uint32_t) chTimeI2MS(chVTGetSystemTime());
75*065fc9a3SMatthias Ringwald }
76*065fc9a3SMatthias Ringwald 
77*065fc9a3SMatthias Ringwald // set timer
btstack_run_loop_chibios_set_timer(btstack_timer_source_t * ts,uint32_t timeout_in_ms)78*065fc9a3SMatthias Ringwald static void btstack_run_loop_chibios_set_timer(btstack_timer_source_t *ts, uint32_t timeout_in_ms){
79*065fc9a3SMatthias Ringwald     ts->timeout = btstack_run_loop_chibios_get_time_ms() + timeout_in_ms + 1;
80*065fc9a3SMatthias Ringwald }
81*065fc9a3SMatthias Ringwald 
btstack_run_loop_chibios_trigger_from_thread(void)82*065fc9a3SMatthias Ringwald static void btstack_run_loop_chibios_trigger_from_thread(void){
83*065fc9a3SMatthias Ringwald     chEvtSignal(btstack_thread, EVT_TRIGGER);
84*065fc9a3SMatthias Ringwald }
85*065fc9a3SMatthias Ringwald 
btstack_run_loop_chibios_poll_data_sources_from_irq(void)86*065fc9a3SMatthias Ringwald static void btstack_run_loop_chibios_poll_data_sources_from_irq(void){
87*065fc9a3SMatthias Ringwald     chSysLockFromISR();
88*065fc9a3SMatthias Ringwald     chEvtSignalI(btstack_thread, EVT_TRIGGER);
89*065fc9a3SMatthias Ringwald     chSysUnlockFromISR();
90*065fc9a3SMatthias Ringwald }
91*065fc9a3SMatthias Ringwald 
btstack_run_loop_chibios_trigger_exit_internal(void)92*065fc9a3SMatthias Ringwald static void btstack_run_loop_chibios_trigger_exit_internal(void){
93*065fc9a3SMatthias Ringwald     run_loop_exit_requested = true;
94*065fc9a3SMatthias Ringwald }
95*065fc9a3SMatthias Ringwald 
96*065fc9a3SMatthias Ringwald /**
97*065fc9a3SMatthias Ringwald  * Execute run_loop
98*065fc9a3SMatthias Ringwald  */
btstack_run_loop_chibios_execute(void)99*065fc9a3SMatthias Ringwald static void btstack_run_loop_chibios_execute(void) {
100*065fc9a3SMatthias Ringwald     log_debug("RL: execute");
101*065fc9a3SMatthias Ringwald 
102*065fc9a3SMatthias Ringwald     run_loop_exit_requested = false;
103*065fc9a3SMatthias Ringwald 
104*065fc9a3SMatthias Ringwald     while (true) {
105*065fc9a3SMatthias Ringwald 
106*065fc9a3SMatthias Ringwald         // process data sources
107*065fc9a3SMatthias Ringwald         btstack_run_loop_base_poll_data_sources();
108*065fc9a3SMatthias Ringwald 
109*065fc9a3SMatthias Ringwald         // execute callbacks - protect list with mutex
110*065fc9a3SMatthias Ringwald         while (1){
111*065fc9a3SMatthias Ringwald             chMtxLock(&btstack_run_loop_callbacks_mutex);
112*065fc9a3SMatthias Ringwald             btstack_context_callback_registration_t * callback_registration = (btstack_context_callback_registration_t *) btstack_linked_list_pop(&btstack_run_loop_base_callbacks);
113*065fc9a3SMatthias Ringwald             chMtxUnlock(&btstack_run_loop_callbacks_mutex);
114*065fc9a3SMatthias Ringwald             if (callback_registration == NULL){
115*065fc9a3SMatthias Ringwald                 break;
116*065fc9a3SMatthias Ringwald             }
117*065fc9a3SMatthias Ringwald             (*callback_registration->callback)(callback_registration->context);
118*065fc9a3SMatthias Ringwald         }
119*065fc9a3SMatthias Ringwald 
120*065fc9a3SMatthias Ringwald         // process timers
121*065fc9a3SMatthias Ringwald         uint32_t now = btstack_run_loop_chibios_get_time_ms();
122*065fc9a3SMatthias Ringwald         btstack_run_loop_base_process_timers(now);
123*065fc9a3SMatthias Ringwald 
124*065fc9a3SMatthias Ringwald         // exit triggered by btstack_run_loop_trigger_exit (main thread or other thread)
125*065fc9a3SMatthias Ringwald         if (run_loop_exit_requested) break;
126*065fc9a3SMatthias Ringwald 
127*065fc9a3SMatthias Ringwald         // wait for timeout or event notification
128*065fc9a3SMatthias Ringwald         int32_t timeout_next_timer_ms = btstack_run_loop_base_get_time_until_timeout(now);
129*065fc9a3SMatthias Ringwald 
130*065fc9a3SMatthias Ringwald         if (timeout_next_timer_ms > 0){
131*065fc9a3SMatthias Ringwald             chEvtWaitOneTimeout(EVT_TRIGGER, chTimeMS2I(timeout_next_timer_ms));
132*065fc9a3SMatthias Ringwald         } else {
133*065fc9a3SMatthias Ringwald             chEvtWaitOne(EVT_TRIGGER);
134*065fc9a3SMatthias Ringwald         }
135*065fc9a3SMatthias Ringwald     }
136*065fc9a3SMatthias Ringwald }
137*065fc9a3SMatthias Ringwald 
btstack_run_loop_chibios_execute_on_main_thread(btstack_context_callback_registration_t * callback_registration)138*065fc9a3SMatthias Ringwald static void btstack_run_loop_chibios_execute_on_main_thread(btstack_context_callback_registration_t * callback_registration){
139*065fc9a3SMatthias Ringwald     // protect list with mutex
140*065fc9a3SMatthias Ringwald     chMtxLock(&btstack_run_loop_callbacks_mutex);
141*065fc9a3SMatthias Ringwald     btstack_run_loop_base_add_callback(callback_registration);
142*065fc9a3SMatthias Ringwald     chMtxUnlock(&btstack_run_loop_callbacks_mutex);
143*065fc9a3SMatthias Ringwald     btstack_run_loop_chibios_trigger_from_thread();
144*065fc9a3SMatthias Ringwald }
145*065fc9a3SMatthias Ringwald 
btstack_run_loop_chibios_init(void)146*065fc9a3SMatthias Ringwald static void btstack_run_loop_chibios_init(void){
147*065fc9a3SMatthias Ringwald     btstack_run_loop_base_init();
148*065fc9a3SMatthias Ringwald     chMtxObjectInit(&btstack_run_loop_callbacks_mutex);
149*065fc9a3SMatthias Ringwald     btstack_thread = chThdGetSelfX();
150*065fc9a3SMatthias Ringwald }
151*065fc9a3SMatthias Ringwald 
152*065fc9a3SMatthias Ringwald /**
153*065fc9a3SMatthias Ringwald  * @brief Provide btstack_run_loop_posix instance for use with btstack_run_loop_init
154*065fc9a3SMatthias Ringwald  */
155*065fc9a3SMatthias Ringwald 
156*065fc9a3SMatthias Ringwald static const btstack_run_loop_t btstack_run_loop_chibios = {
157*065fc9a3SMatthias Ringwald     &btstack_run_loop_chibios_init,
158*065fc9a3SMatthias Ringwald     &btstack_run_loop_base_add_data_source,
159*065fc9a3SMatthias Ringwald     &btstack_run_loop_base_remove_data_source,
160*065fc9a3SMatthias Ringwald     &btstack_run_loop_base_enable_data_source_callbacks,
161*065fc9a3SMatthias Ringwald     &btstack_run_loop_base_disable_data_source_callbacks,
162*065fc9a3SMatthias Ringwald     &btstack_run_loop_chibios_set_timer,
163*065fc9a3SMatthias Ringwald     &btstack_run_loop_base_add_timer,
164*065fc9a3SMatthias Ringwald     &btstack_run_loop_base_remove_timer,
165*065fc9a3SMatthias Ringwald     &btstack_run_loop_chibios_execute,
166*065fc9a3SMatthias Ringwald     &btstack_run_loop_base_dump_timer,
167*065fc9a3SMatthias Ringwald     &btstack_run_loop_chibios_get_time_ms,
168*065fc9a3SMatthias Ringwald     &btstack_run_loop_chibios_poll_data_sources_from_irq,
169*065fc9a3SMatthias Ringwald     &btstack_run_loop_chibios_execute_on_main_thread,
170*065fc9a3SMatthias Ringwald     &btstack_run_loop_chibios_trigger_exit_internal,
171*065fc9a3SMatthias Ringwald };
172*065fc9a3SMatthias Ringwald 
btstack_run_loop_chibios_get_instance(void)173*065fc9a3SMatthias Ringwald const btstack_run_loop_t * btstack_run_loop_chibios_get_instance(void){
174*065fc9a3SMatthias Ringwald     return &btstack_run_loop_chibios;
175*065fc9a3SMatthias Ringwald }
176