3 * Copyright (c) 2020 Project CHIP Authors
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
20 * Contains non-inline method definitions for the
21 * GenericPlatformManagerImpl_Zephyr<> template.
24 #ifndef GENERIC_PLATFORM_MANAGER_IMPL_ZEPHYR_CPP
25 #define GENERIC_PLATFORM_MANAGER_IMPL_ZEPHYR_CPP
27 #include <platform/PlatformManager.h>
28 #include <platform/internal/CHIPDeviceLayerInternal.h>
29 #include <platform/internal/GenericPlatformManagerImpl_Zephyr.h>
31 // Include the non-inline definitions for the GenericPlatformManagerImpl<> template,
32 // from which the GenericPlatformManagerImpl_Zephyr<> template inherits.
33 #include <platform/internal/GenericPlatformManagerImpl.cpp>
35 #include <system/SystemLayer.h>
37 #define DEFAULT_MIN_SLEEP_PERIOD (60 * 60 * 24 * 30) // Month [sec]
40 namespace DeviceLayer {
43 // Fully instantiate the generic implementation class in whatever compilation unit includes this file.
44 template class GenericPlatformManagerImpl_Zephyr<PlatformManagerImpl>;
46 template <class ImplClass>
47 CHIP_ERROR GenericPlatformManagerImpl_Zephyr<ImplClass>::_InitChipStack(void)
49 CHIP_ERROR err = CHIP_NO_ERROR;
51 k_mutex_init(&mChipStackLock);
53 k_msgq_init(&mChipEventQueue, reinterpret_cast<char *>(&mChipEventRingBuffer), sizeof(ChipDeviceEvent),
54 CHIP_DEVICE_CONFIG_MAX_EVENT_QUEUE_SIZE);
56 // Call up to the base class _InitChipStack() to perform the bulk of the initialization.
57 err = GenericPlatformManagerImpl<ImplClass>::_InitChipStack();
64 template <class ImplClass>
65 void GenericPlatformManagerImpl_Zephyr<ImplClass>::_LockChipStack(void)
67 k_mutex_lock(&mChipStackLock, K_FOREVER);
70 template <class ImplClass>
71 bool GenericPlatformManagerImpl_Zephyr<ImplClass>::_TryLockChipStack(void)
73 return k_mutex_lock(&mChipStackLock, K_NO_WAIT) == 0;
76 template <class ImplClass>
77 void GenericPlatformManagerImpl_Zephyr<ImplClass>::_UnlockChipStack(void)
79 k_mutex_unlock(&mChipStackLock);
82 template <class ImplClass>
83 CHIP_ERROR GenericPlatformManagerImpl_Zephyr<ImplClass>::_StartChipTimer(uint32_t aMilliseconds)
85 // Let SystemLayer.PrepareSelect() handle timers.
89 template <class ImplClass>
90 CHIP_ERROR GenericPlatformManagerImpl_Zephyr<ImplClass>::_Shutdown(void)
92 return CHIP_ERROR_NOT_IMPLEMENTED;
95 template <class ImplClass>
96 void GenericPlatformManagerImpl_Zephyr<ImplClass>::_PostEvent(const ChipDeviceEvent * event)
98 // For some reasons mentioned in https://github.com/zephyrproject-rtos/zephyr/issues/22301
99 // k_msgq_put takes `void*` instead of `const void*`. Nonetheless, it should be safe to
100 // const_cast here and there are components in Zephyr itself which do the same.
101 if (k_msgq_put(&mChipEventQueue, const_cast<ChipDeviceEvent *>(event), K_NO_WAIT) == 0)
102 SystemLayer.WakeSelect(); // Trigger wake select on CHIP thread
104 ChipLogError(DeviceLayer, "Failed to post event to CHIP Platform event queue");
107 template <class ImplClass>
108 void GenericPlatformManagerImpl_Zephyr<ImplClass>::ProcessDeviceEvents()
110 ChipDeviceEvent event;
112 while (k_msgq_get(&mChipEventQueue, &event, K_NO_WAIT) == 0)
113 Impl()->DispatchEvent(&event);
116 template <class ImplClass>
117 void GenericPlatformManagerImpl_Zephyr<ImplClass>::SysUpdate()
124 // Max out this duration and let CHIP set it appropriately.
125 mNextTimeout.tv_sec = DEFAULT_MIN_SLEEP_PERIOD;
126 mNextTimeout.tv_usec = 0;
128 if (SystemLayer.State() == System::kLayerState_Initialized)
130 SystemLayer.PrepareSelect(mMaxFd, &mReadSet, &mWriteSet, &mErrorSet, mNextTimeout);
133 if (InetLayer.State == InetLayer::kState_Initialized)
135 InetLayer.PrepareSelect(mMaxFd, &mReadSet, &mWriteSet, &mErrorSet, mNextTimeout);
139 template <class ImplClass>
140 void GenericPlatformManagerImpl_Zephyr<ImplClass>::SysProcess()
142 Impl()->UnlockChipStack();
143 int selectRes = select(mMaxFd + 1, &mReadSet, &mWriteSet, &mErrorSet, &mNextTimeout);
144 Impl()->LockChipStack();
148 ChipLogError(DeviceLayer, "select failed: %s\n", ErrorStr(System::MapErrorPOSIX(errno)));
152 if (SystemLayer.State() == System::kLayerState_Initialized)
154 SystemLayer.HandleSelectResult(mMaxFd, &mReadSet, &mWriteSet, &mErrorSet);
157 if (InetLayer.State == InetLayer::kState_Initialized)
159 InetLayer.HandleSelectResult(mMaxFd, &mReadSet, &mWriteSet, &mErrorSet);
162 ProcessDeviceEvents();
165 template <class ImplClass>
166 void GenericPlatformManagerImpl_Zephyr<ImplClass>::_RunEventLoop(void)
168 Impl()->LockChipStack();
176 Impl()->UnlockChipStack();
179 template <class ImplClass>
180 void GenericPlatformManagerImpl_Zephyr<ImplClass>::EventLoopTaskMain(void * thisPtr, void *, void *)
182 ChipLogDetail(DeviceLayer, "CHIP task running");
183 static_cast<GenericPlatformManagerImpl_Zephyr<ImplClass> *>(thisPtr)->Impl()->RunEventLoop();
186 template <class ImplClass>
187 CHIP_ERROR GenericPlatformManagerImpl_Zephyr<ImplClass>::_StartEventLoopTask(void)
189 const auto tid = k_thread_create(&mChipThread, mChipThreadStack, K_THREAD_STACK_SIZEOF(mChipThreadStack), EventLoopTaskMain,
190 this, nullptr, nullptr, CHIP_DEVICE_CONFIG_CHIP_TASK_PRIORITY, 0, K_NO_WAIT);
192 #ifdef CONFIG_THREAD_NAME
193 k_thread_name_set(tid, CHIP_DEVICE_CONFIG_CHIP_TASK_NAME);
195 IgnoreUnusedVariable(tid);
198 return CHIP_NO_ERROR;
201 } // namespace Internal
202 } // namespace DeviceLayer
205 #endif // GENERIC_PLATFORM_MANAGER_IMPL_ZEPHYR_CPP