3 * Copyright (c) 2020 Project CHIP Authors
4 * Copyright (c) 2019 Nest Labs, Inc.
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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.
22 * Contains non-inline method definitions for the
23 * GenericThreadStackManagerImpl_FreeRTOS<> template.
26 #ifndef GENERIC_THREAD_STACK_MANAGER_IMPL_FREERTOS_IPP
27 #define GENERIC_THREAD_STACK_MANAGER_IMPL_FREERTOS_IPP
29 #include <platform/FreeRTOS/GenericThreadStackManagerImpl_FreeRTOS.h>
30 #include <platform/OpenThread/OpenThreadUtils.h>
31 #include <platform/ThreadStackManager.h>
32 #include <platform/internal/CHIPDeviceLayerInternal.h>
33 #include <support/CodeUtils.h>
34 #include <support/logging/CHIPLogging.h>
37 namespace DeviceLayer {
40 // Fully instantiate the generic implementation class in whatever compilation unit includes this file.
41 template class GenericThreadStackManagerImpl_FreeRTOS<ThreadStackManagerImpl>;
43 template <class ImplClass>
44 CHIP_ERROR GenericThreadStackManagerImpl_FreeRTOS<ImplClass>::DoInit(void)
46 CHIP_ERROR err = CHIP_NO_ERROR;
47 mThreadStackLock = xSemaphoreCreateMutex();
49 if (mThreadStackLock == NULL)
51 ChipLogError(DeviceLayer, "Failed to create Thread stack lock");
52 ExitNow(err = CHIP_ERROR_NO_MEMORY);
61 template <class ImplClass>
62 CHIP_ERROR GenericThreadStackManagerImpl_FreeRTOS<ImplClass>::_StartThreadTask(void)
64 if (mThreadTask != NULL)
66 return CHIP_ERROR_INCORRECT_STATE;
68 #if defined(CHIP_CONFIG_FREERTOS_USE_STATIC_TASK) && CHIP_CONFIG_FREERTOS_USE_STATIC_TASK
69 mThreadTask = xTaskCreateStatic(ThreadTaskMain, CHIP_DEVICE_CONFIG_THREAD_TASK_NAME, ArraySize(mThreadStack), this,
70 CHIP_DEVICE_CONFIG_THREAD_TASK_PRIORITY, mThreadStack, &mThreadTaskStruct);
73 xTaskCreate(ThreadTaskMain, CHIP_DEVICE_CONFIG_THREAD_TASK_NAME,
74 CHIP_DEVICE_CONFIG_THREAD_TASK_STACK_SIZE / sizeof(StackType_t), this, CHIP_DEVICE_CONFIG_THREAD_TASK_PRIORITY,
78 if (mThreadTask == NULL)
80 return CHIP_ERROR_NO_MEMORY;
85 template <class ImplClass>
86 void GenericThreadStackManagerImpl_FreeRTOS<ImplClass>::_LockThreadStack(void)
88 xSemaphoreTake(mThreadStackLock, portMAX_DELAY);
91 template <class ImplClass>
92 bool GenericThreadStackManagerImpl_FreeRTOS<ImplClass>::_TryLockThreadStack(void)
94 return xSemaphoreTake(mThreadStackLock, 0) == pdTRUE;
97 template <class ImplClass>
98 void GenericThreadStackManagerImpl_FreeRTOS<ImplClass>::_UnlockThreadStack(void)
100 xSemaphoreGive(mThreadStackLock);
103 template <class ImplClass>
104 void GenericThreadStackManagerImpl_FreeRTOS<ImplClass>::SignalThreadActivityPending()
106 if (mThreadTask != NULL)
108 xTaskNotifyGive(mThreadTask);
112 template <class ImplClass>
113 BaseType_t GenericThreadStackManagerImpl_FreeRTOS<ImplClass>::SignalThreadActivityPendingFromISR()
115 BaseType_t yieldRequired = pdFALSE;
117 if (mThreadTask != NULL)
119 vTaskNotifyGiveFromISR(mThreadTask, &yieldRequired);
122 return yieldRequired;
125 template <class ImplClass>
126 void GenericThreadStackManagerImpl_FreeRTOS<ImplClass>::OnJoinerTimer(TimerHandle_t xTimer)
128 GenericThreadStackManagerImpl_FreeRTOS<ImplClass> * self =
129 static_cast<GenericThreadStackManagerImpl_FreeRTOS<ImplClass> *>(pvTimerGetTimerID(xTimer));
131 ChipLogDetail(DeviceLayer, "Thread joiner timer running");
133 if (xTaskGetTickCount() > self->mJoinerExpire || self->Impl()->IsThreadProvisioned())
135 ChipLogDetail(DeviceLayer, "Thread joiner timer stopped");
137 VerifyOrDie(pdPASS == xTimerStop(xTimer, portMAX_DELAY) && pdPASS == xTimerDelete(xTimer, portMAX_DELAY));
139 else if (!self->mJoinerStartPending)
141 ChipLogDetail(DeviceLayer, "Request Thread joiner start");
143 self->mJoinerStartPending = true;
144 self->Impl()->SignalThreadActivityPending();
148 template <class ImplClass>
149 void GenericThreadStackManagerImpl_FreeRTOS<ImplClass>::ThreadTaskMain(void * arg)
151 GenericThreadStackManagerImpl_FreeRTOS<ImplClass> * self =
152 static_cast<GenericThreadStackManagerImpl_FreeRTOS<ImplClass> *>(arg);
154 ChipLogDetail(DeviceLayer, "Thread task running");
156 // Try starting joiner within 15m.
157 self->mJoinerExpire = xTaskGetTickCount() + pdMS_TO_TICKS(15 * 60 * 1000);
159 TimerHandle_t joinerTimer = xTimerCreate("JoinerTimer", pdMS_TO_TICKS(10000), pdTRUE, self, &OnJoinerTimer);
160 VerifyOrDie(joinerTimer != NULL);
161 VerifyOrDie(pdPASS == xTimerStart(joinerTimer, portMAX_DELAY));
165 self->Impl()->LockThreadStack();
166 self->Impl()->ProcessThreadActivity();
167 self->Impl()->UnlockThreadStack();
169 ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
171 if (self->mJoinerStartPending)
173 self->mJoinerStartPending = false;
174 self->Impl()->JoinerStart();
179 } // namespace Internal
180 } // namespace DeviceLayer
183 #endif // GENERIC_THREAD_STACK_MANAGER_IMPL_FREERTOS_IPP