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