3 * Copyright (c) 2020 Project CHIP Authors
4 * Copyright (c) 2019 Nest Labs, Inc.
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
21 * Provides an implementation of the ThreadStackManager object for
22 * CC13X2_26X2 platforms using the Texas Instruments SDK and the
27 /* this file behaves like a config.h, comes first */
28 #include <platform/internal/CHIPDeviceLayerInternal.h>
30 #include <platform/FreeRTOS/GenericThreadStackManagerImpl_FreeRTOS.cpp>
31 #include <platform/OpenThread/GenericThreadStackManagerImpl_OpenThread_LwIP.cpp>
33 #include <mbedtls/platform.h>
34 #include <openthread/heap.h>
35 #include <platform/OpenThread/OpenThreadUtils.h>
36 #include <platform/ThreadStackManager.h>
38 // platform folder in the TI SDK example application
39 #include <platform/system.h>
43 #include "ti_dmm_application_policy.h"
44 #include <dmm/dmm_policy.h>
45 #include <dmm/dmm_priority_ble_thread.h>
46 #include <dmm/dmm_scheduler.h>
50 namespace DeviceLayer {
52 using namespace ::chip::DeviceLayer::Internal;
54 ThreadStackManagerImpl ThreadStackManagerImpl::sInstance;
56 #if OPENTHREAD_CONFIG_HEAP_EXTERNAL_ENABLE != 0
57 static void * ot_calloc(size_t n, size_t size)
61 p_ptr = pvPortMalloc(n * size);
63 memset(p_ptr, 0, n * size);
68 static void ot_free(void * p_ptr)
72 #endif /* OPENTHREAD_CONFIG_HEAP_EXTERNAL_ENABLE != 0 */
74 CHIP_ERROR ThreadStackManagerImpl::_InitThreadStack(void)
76 return InitThreadStack(NULL);
79 CHIP_ERROR ThreadStackManagerImpl::InitThreadStack(otInstance * otInst)
81 CHIP_ERROR err = CHIP_NO_ERROR;
83 // Create FreeRTOS queue for platform driver messages
84 procQueue = xQueueCreate(16U, sizeof(ThreadStackManagerImpl::procQueueMsg));
86 #if OPENTHREAD_CONFIG_HEAP_EXTERNAL_ENABLE != 0
87 mbedtls_platform_set_calloc_free(ot_calloc, ot_free);
88 #endif /* OPENTHREAD_CONFIG_HEAP_EXTERNAL_ENABLE != 0 */
90 // Initialize the OpenThread platform layer
95 DMMSch_registerClient(xTaskGetCurrentTaskHandle(), DMMPolicy_StackRole_threadFtd);
96 DMMPolicy_updateStackState(DMMPolicy_StackRole_threadFtd, DMMPOLICY_THREAD_IDLE);
99 // Initialize the generic implementation base classes.
100 err = GenericThreadStackManagerImpl_FreeRTOS<ThreadStackManagerImpl>::DoInit();
102 err = GenericThreadStackManagerImpl_OpenThread_LwIP<ThreadStackManagerImpl>::DoInit(otInst);
109 bool ThreadStackManagerImpl::IsInitialized()
111 return sInstance.mThreadStackLock != NULL;
114 void ThreadStackManagerImpl::_OnCHIPoBLEAdvertisingStart(void)
116 // If Thread-over-BLE is enabled, ensure that ToBLE advertising is stopped before
117 // starting CHIPoBLE advertising. This is accomplished by disabling the OpenThread
118 // IPv6 interface via a call to otIp6SetEnabled(false).
120 #if OPENTHREAD_CONFIG_ENABLE_TOBLE
122 otIp6SetEnabled(OTInstance(), false);
127 void ThreadStackManagerImpl::_OnCHIPoBLEAdvertisingStop(void)
129 // If Thread-over-BLE is enabled, and a Thread provision exists, ensure that ToBLE
130 // advertising is re-activated once CHIPoBLE advertising stops.
132 #if OPENTHREAD_CONFIG_ENABLE_TOBLE
134 if (otThreadGetDeviceRole(OTInstance()) != OT_DEVICE_ROLE_DISABLED && otDatasetIsCommissioned(OTInstance()))
136 otIp6SetEnabled(OTInstance(), true);
142 void ThreadStackManagerImpl::_SendProcMessage(ThreadStackManagerImpl::procQueueMsg & procMsg)
144 xQueueSendFromISR(procQueue, &procMsg, NULL);
146 // signal processing loop
147 SignalThreadActivityPendingFromISR();
150 void ThreadStackManagerImpl::_ProcMessage(otInstance * aInstance)
152 procQueueMsg procMsg;
153 while (pdTRUE == xQueueReceive(procQueue, &procMsg, 0U))
157 case procQueueCmd_alarm: {
158 platformAlarmProcess(aInstance);
162 case procQueueCmd_radio: {
163 platformRadioProcess(aInstance, procMsg.arg);
167 case procQueueCmd_tasklets: {
168 otTaskletsProcess(aInstance);
172 case procQueueCmd_uart: {
173 platformUartProcess(procMsg.arg);
177 case procQueueCmd_random: {
178 platformRandomProcess();
182 case procQueueCmd_alarmu: {
183 platformAlarmMicroProcess(aInstance);
194 } // namespace DeviceLayer
197 using namespace ::chip::DeviceLayer;
200 * Glue function called by alarm processing layer to notify OpenThread the driver needs processing.
202 extern "C" void platformAlarmSignal()
204 ThreadStackManagerImpl::procQueueMsg msg;
205 msg.cmd = ThreadStackManagerImpl::procQueueCmd_alarm;
206 ThreadStackMgrImpl()._SendProcMessage(msg);
210 * Glue function called by alarm processing layer to notify OpenThread the driver needs processing.
212 extern "C" void platformAlarmMicroSignal()
214 ThreadStackManagerImpl::procQueueMsg msg;
215 msg.cmd = ThreadStackManagerImpl::procQueueCmd_alarmu;
216 ThreadStackMgrImpl()._SendProcMessage(msg);
220 * Glue function called by radio processing layer to notify OpenThread the driver needs processing.
222 extern "C" void platformRadioSignal(uintptr_t arg)
224 ThreadStackManagerImpl::procQueueMsg msg;
225 msg.cmd = ThreadStackManagerImpl::procQueueCmd_radio;
227 ThreadStackMgrImpl()._SendProcMessage(msg);
231 * Glue function called by UART processing layer to notify OpenThread the driver needs processing.
233 extern "C" void platformUartSignal(uintptr_t arg)
235 ThreadStackManagerImpl::procQueueMsg msg;
236 msg.cmd = ThreadStackManagerImpl::procQueueCmd_uart;
238 ThreadStackMgrImpl()._SendProcMessage(msg);
242 * Glue function called directly by the OpenThread stack when tasklet processing work
245 extern "C" void otTaskletsSignalPending(otInstance * p_instance)
247 ThreadStackMgrImpl().SignalThreadActivityPending();
251 * Process events from the drivers
253 extern "C" void otSysProcessDrivers(otInstance * aInstance)
255 ThreadStackMgrImpl()._ProcMessage(aInstance);