Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: FXAS21002 FXOS8700Q
pal_plat_rtos.c
00001 /******************************************************************************* 00002 * Copyright 2018 ARM Ltd. 00003 * 00004 * Licensed under the Apache License, Version 2.0 (the "License"); 00005 * you may not use this file except in compliance with the License. 00006 * You may obtain a copy of the License at 00007 * 00008 * http://www.apache.org/licenses/LICENSE-2.0 00009 * 00010 * Unless required by applicable law or agreed to in writing, software 00011 * distributed under the License is distributed on an "AS IS" BASIS, 00012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00013 * See the License for the specific language governing permissions and 00014 * limitations under the License. 00015 *******************************************************************************/ 00016 00017 /* PAL-RTOS porting for SXOS SDK 00018 * This is porting code for PAL RTOS APIS for 00019 * SXOS SDK / RSX RTOS. 00020 */ 00021 00022 00023 #include "pal.h" 00024 #include "pal_plat_rtos.h" 00025 00026 #include <cos.h> 00027 #include <tm.h> 00028 #include <dm.h> 00029 00030 #include <stdlib.h> 00031 #include <stdio.h> // snprintf 00032 00033 #define TRACE_GROUP "PAL" 00034 00035 extern palStatus_t pal_plat_getRandomBufferFromHW(uint8_t *randomBuf, size_t bufSizeBytes, size_t* actualRandomSizeBytes); 00036 00037 PAL_PRIVATE void pal_plat_osTimerHelperThreadFunction(const void* param); 00038 00039 //! Internal timer structure 00040 typedef struct palTimer { 00041 palTimerFuncPtr function; 00042 void* functionArgs; 00043 palTimerType_t timerType; 00044 uint32_t periodMs; 00045 } palTimer_t; 00046 00047 //! Internal mutex structure 00048 typedef struct palMutex { 00049 COS_MUTEX osMutex; 00050 } palMutex_t; 00051 00052 //! Internal semaphore structure 00053 typedef struct palSemaphore { 00054 COS_SEMA osSemaphore; 00055 } palSemaphore_t; 00056 00057 //! Internal semaphore structure 00058 typedef struct palThread 00059 { 00060 palThreadFuncPtr userFunction; 00061 void* userFunctionArgument; 00062 char* name; 00063 HANDLE osThread; 00064 } palThread_t; 00065 00066 00067 // XXX: this just has to have space for pal_0xffffffff\0 00068 #define PAL_THREAD_NAME_MAX_LEN 16 // max len for thread name which holds the pointer (as string) to dynamically allocated thread data 00069 00070 // Max attempts to try setting RTC time 00071 #define PAL_MAX_RTC_SET_ATTEMPTS 5 00072 00073 // This define controls if the timer uses the IRQ based timer or task one. In practice 00074 // this affects on the context where the timer callback is called on. Unless the ns-hal-pal and PAL 00075 // sides can implement a recursive critical section without mutexes, the code needs a thread 00076 // context. Note: the mutex code can not be called from IRQ. 00077 #ifndef PAL_SXOS_USE_TIMER_HELPER_THREAD 00078 #define PAL_SXOS_USE_TIMER_HELPER_THREAD 1 00079 #endif 00080 00081 #if PAL_SXOS_USE_TIMER_HELPER_THREAD 00082 00083 // The timer callback thread is having this much stack, which should be plenty as on other OS' even 1KB is 00084 // enough for the client code. But of course the OS itself affects also on the needed stack space 00085 #ifndef PAL_TIMER_THREAD_STACK_SIZE 00086 #define PAL_TIMER_THREAD_STACK_SIZE (4*1024) 00087 #endif 00088 00089 PAL_PRIVATE palThreadID_t g_timer_helper_thread; 00090 #endif 00091 00092 palStatus_t pal_plat_RTOSInitialize(void* opaqueContext) 00093 { 00094 palStatus_t status; 00095 00096 #if PAL_SXOS_USE_TIMER_HELPER_THREAD 00097 status = pal_plat_osThreadCreate(pal_plat_osTimerHelperThreadFunction, 00098 NULL, 00099 PAL_osPriorityReservedHighResTimer , 00100 PAL_TIMER_THREAD_STACK_SIZE, 00101 &g_timer_helper_thread); 00102 #else 00103 status = PAL_SUCCESS; 00104 #endif 00105 00106 #if (PAL_USE_HW_RTC) 00107 if (status == PAL_SUCCESS) 00108 { 00109 status = pal_plat_rtcInit(); 00110 } 00111 #endif 00112 00113 return status; 00114 } 00115 00116 palStatus_t pal_plat_RTOSDestroy(void) 00117 { 00118 palStatus_t status; 00119 00120 #if PAL_SXOS_USE_TIMER_HELPER_THREAD 00121 status = pal_plat_osThreadTerminate(&g_timer_helper_thread); 00122 #else 00123 status = PAL_SUCCESS; 00124 #endif 00125 00126 #if (PAL_USE_HW_RTC) 00127 if (status == PAL_SUCCESS) 00128 { 00129 status = pal_plat_rtcDeInit(); 00130 } 00131 #endif 00132 00133 return status; 00134 } 00135 00136 palStatus_t pal_plat_osDelay(uint32_t milliseconds) 00137 { 00138 palStatus_t status = PAL_SUCCESS; 00139 00140 if (COS_Sleep(milliseconds) == false) { 00141 // according to source, the COS_Sleep() returns unconditionally TRUE, but 00142 // let's be super cautious and pass the error to caller. OTOH, nobody checks 00143 // the return value anyway.. 00144 status = PAL_ERR_RTOS_OS ; 00145 } 00146 return status; 00147 } 00148 00149 00150 uint64_t pal_plat_osKernelSysTick() 00151 { 00152 00153 static uint32_t prevCountLo = 0; 00154 static uint64_t prevCount = 0; 00155 00156 uint32_t osCount = (uint32_t)COS_GetTickCount(); 00157 00158 if (osCount < prevCountLo) { 00159 prevCount = (1LL << 32) + osCount; 00160 } else { 00161 prevCount = osCount; 00162 } 00163 prevCountLo = osCount; 00164 00165 return prevCount; 00166 } 00167 00168 uint64_t pal_plat_osKernelSysTickMicroSec(uint64_t microseconds) 00169 { 00170 uint64_t ticks = (uint64_t)COS_Msec2Tick(microseconds / 1000); 00171 return ticks; 00172 } 00173 00174 uint64_t pal_plat_osKernelSysTickFrequency() 00175 { 00176 uint64_t ticksPerSecond = COS_Sec2Tick(1); 00177 return ticksPerSecond; 00178 } 00179 00180 PAL_PRIVATE void pal_plat_osThreadWarpperFunction(void* param) 00181 { 00182 palThread_t* thread = param; 00183 00184 thread->userFunction(thread->userFunctionArgument); 00185 00186 // COS does not seem to support thread function to return (problems in deleting the thread). 00187 // Therefore if userFunction returns, we stay here waiting for task to be deleted. 00188 HANDLE task = COS_GetCurrentTaskHandle(); 00189 COS_EVENT event; 00190 for (;;) { 00191 COS_WaitEvent(task, &event, COS_WAIT_FOREVER); 00192 } 00193 } 00194 00195 00196 palStatus_t pal_plat_osThreadCreate(palThreadFuncPtr function, void* funcArgument, palThreadPriority_t priority, uint32_t stackSize, palThreadID_t* threadID) 00197 { 00198 palStatus_t status = PAL_SUCCESS; 00199 00200 int bytesWritten; 00201 palThread_t* thread = malloc(sizeof(palThread_t)); 00202 char* threadName = malloc((PAL_THREAD_NAME_MAX_LEN + 1)); // name will hold the address of the dynamically allocated palThread_t (as string) 00203 thread = malloc(sizeof(palThread_t)); 00204 if ((NULL == thread) || (NULL == threadName)) 00205 { 00206 status = PAL_ERR_RTOS_RESOURCE ; 00207 goto clean; 00208 } 00209 00210 // XXX: the thread name really needs to come from the client side, as then we could use meaningful names 00211 bytesWritten = snprintf(threadName, (PAL_THREAD_NAME_MAX_LEN + 1), "pal_%p", thread); 00212 if ((bytesWritten <= 0) || ((PAL_THREAD_NAME_MAX_LEN + 1) <= bytesWritten)) 00213 { 00214 status = PAL_ERR_RTOS_RESOURCE ; 00215 goto clean; 00216 } 00217 00218 // Note: COS_CreateTask() has a pStackAddr -parameter but it actually does not use it and 00219 // it allocates the stack internally. 00220 thread->name = threadName; 00221 thread->userFunction = function; 00222 thread->userFunctionArgument = funcArgument; 00223 00224 // XXX: the priorities need a mapping, so far just use a 0x80 (0 is highest, 0xff lowest priority) 00225 00226 uint8_t taskPriority = 0x80; 00227 00228 // Create and start a task. As the thread cleanup seems to require a COS_StopTask(), 00229 // we use a wrapper to call the user provided function and eventually do the cleanup. 00230 HANDLE threadOs = COS_CreateTask((PTASK_ENTRY)pal_plat_osThreadWarpperFunction, 00231 thread, 00232 NULL, 00233 stackSize, 00234 taskPriority, 00235 COS_CREATE_DEFAULT, 00236 0, 00237 threadName); 00238 00239 if (threadOs == NULL) 00240 { 00241 status = PAL_ERR_NO_MEMORY ; 00242 goto clean; 00243 } 00244 else 00245 { 00246 thread->osThread = threadOs; 00247 *threadID = (palThreadID_t)thread; 00248 } 00249 00250 return status; 00251 00252 clean: 00253 free(thread); 00254 free(threadName); 00255 00256 return status; 00257 } 00258 00259 palThreadID_t pal_plat_osThreadGetId(void) 00260 { 00261 // XXX: the current thread ID is not really a useful value for anything but separating 00262 // threads in debug traces. The given value is NOT the same as returned by pal_osThreadCreate(). 00263 HANDLE currTask = COS_GetCurrentTaskHandle(); 00264 00265 return (palThreadID_t)currTask; 00266 } 00267 00268 palStatus_t pal_plat_osThreadTerminate(palThreadID_t* threadID) 00269 { 00270 palStatus_t status = PAL_SUCCESS; 00271 00272 palThread_t* thread = (palThread_t*)*threadID; 00273 00274 if (COS_GetCurrentTaskHandle() == thread->osThread) // self termination not allowed 00275 { 00276 status = PAL_ERR_RTOS_TASK ; 00277 goto end; 00278 } 00279 00280 // deleting a running task is not supported by COS, so it needs to be stopped first. 00281 COS_StopTask((TASK_HANDLE *)thread->osThread); 00282 00283 // this has a hardcoded "return FALSE", which may or may not be a bug, so pass the return check here 00284 COS_DeleteTask(thread->osThread); 00285 00286 free(thread->name); 00287 free(thread); 00288 00289 end: 00290 00291 return status; 00292 } 00293 00294 // This thread function will be used to serve the timer requests. It will not do 00295 // anything itself but call the COS_WaitEvent(), which internally will handle calling 00296 // the timer callbacks. 00297 PAL_PRIVATE void pal_plat_osTimerHelperThreadFunction(const void* param) 00298 { 00299 HANDLE current_task = COS_GetCurrentTaskHandle(); 00300 00301 while (true) 00302 { 00303 COS_EVENT event; 00304 COS_WaitEvent(current_task, &event, COS_WAIT_FOREVER); 00305 } 00306 } 00307 00308 PAL_PRIVATE void pal_plat_osTimerWarpperFunction(void* param) 00309 { 00310 palTimer_t* timer = param; 00311 00312 if (timer->timerType == palOsTimerPeriodic ) 00313 { 00314 // XXX: by re-starting the periodic timer here we get relatively constant 00315 // interval. But of course this requires the callback to return before the 00316 // timeout or behavior gets bad. But this whole IRQ based timer code really 00317 // expects the timer callback to just behave. 00318 // Having the timer starting here is also convenient for the caller site also, 00319 // as it can stop the timer from callback and this wrapper will not overwrite 00320 // that will. 00321 #if PAL_SXOS_USE_TIMER_HELPER_THREAD 00322 const palThread_t* timer_thread = (palThread_t*)g_timer_helper_thread; 00323 00324 HANDLE timer_thread_handle = timer_thread->osThread; 00325 00326 COS_StartCallbackTimer(timer_thread_handle, timer->periodMs, pal_plat_osTimerWarpperFunction, param); 00327 #else 00328 COS_StartFunctionTimer(timer->periodMs, pal_plat_osTimerWarpperFunction, param); 00329 #endif 00330 } 00331 00332 timer->function(timer->functionArgs); 00333 } 00334 00335 palStatus_t pal_plat_osTimerCreate(palTimerFuncPtr function, void* funcArgument, palTimerType_t timerType, palTimerID_t* timerID) 00336 { 00337 palStatus_t status = PAL_SUCCESS; 00338 00339 // the COS identifies the timer by callback+param tuple. As we pass the PAL timer callback 00340 // and its own timer struct as parameter to COS timer, the uniqueness is guaranteed and there is no 00341 // need to maintain a local timer ID scheme. 00342 00343 palTimer_t* timer = malloc(sizeof(palTimer_t)); 00344 00345 if (NULL == timer) 00346 { 00347 status = PAL_ERR_NO_MEMORY ; 00348 } 00349 00350 if (PAL_SUCCESS == status) 00351 { 00352 timer->function = function; 00353 timer->functionArgs = funcArgument; 00354 timer->timerType = timerType; 00355 00356 *timerID = (palTimerID_t)timer; 00357 } 00358 00359 return status; 00360 } 00361 00362 palStatus_t pal_plat_osTimerStart(palTimerID_t timerID, uint32_t millisec) 00363 { 00364 palStatus_t status = PAL_SUCCESS; 00365 00366 palTimer_t* timer = (palTimer_t*)timerID; 00367 00368 // There is no periodic timer on COS as far as I know, so we need to emulate it 00369 // by storing the period to timer and re-issue the timer from the callback itself. 00370 timer->periodMs = millisec; 00371 00372 #if PAL_SXOS_USE_TIMER_HELPER_THREAD 00373 const palThread_t* timer_thread = (palThread_t*)g_timer_helper_thread; 00374 00375 HANDLE timer_thread_handle = timer_thread->osThread; 00376 00377 COS_StartCallbackTimer(timer_thread_handle, millisec, pal_plat_osTimerWarpperFunction, timer); 00378 #else 00379 // XXX: there is a COS_StartFunctionTimerForcedly(), which will actually 00380 // do less-forced restart of timer than COS_StartFunctionTimer(), which will 00381 // stop existing timer and start another. 00382 COS_StartFunctionTimer(millisec, pal_plat_osTimerWarpperFunction, timer); 00383 #endif 00384 00385 return status; 00386 } 00387 00388 palStatus_t pal_plat_osTimerStop(palTimerID_t timerID) 00389 { 00390 palStatus_t status = PAL_SUCCESS; 00391 00392 palTimer_t* timer = (palTimer_t*)timerID; 00393 00394 #if PAL_SXOS_USE_TIMER_HELPER_THREAD 00395 const palThread_t* timer_thread = (palThread_t*)g_timer_helper_thread; 00396 00397 HANDLE timer_thread_handle = timer_thread->osThread; 00398 00399 COS_StopCallbackTimer(timer_thread_handle, (COS_CALLBACK_FUNC_T)pal_plat_osTimerWarpperFunction, timer); 00400 #else 00401 COS_StopFunctionTimer((COS_CALLBACK_FUNC_T)pal_plat_osTimerWarpperFunction, timer); 00402 #endif 00403 00404 return status; 00405 } 00406 00407 palStatus_t pal_plat_osTimerDelete(palTimerID_t* timerID) 00408 { 00409 palStatus_t status = PAL_SUCCESS; 00410 00411 palTimer_t* timer = (palTimer_t*)*timerID; 00412 00413 free(timer); 00414 00415 *timerID = 0; 00416 00417 return status; 00418 } 00419 00420 00421 palStatus_t pal_plat_osMutexCreate(palMutexID_t* mutexID) 00422 { 00423 // There is a COS_CreateMutex() & COS_DeleteMutex()using HANDLE's, but it is 00424 // marked as deprecated. 00425 // Let's then use the other API, COS_Mutex*, which takes in a COS_MUTEX 00426 00427 palStatus_t status = PAL_SUCCESS; 00428 palMutex_t* mutex; 00429 00430 // the COS_MutexInit() expects a zeroed struct, hence calloc() 00431 mutex = (palMutex_t*)calloc(1, sizeof(palMutex_t)); 00432 if (NULL == mutex) 00433 { 00434 status = PAL_ERR_NO_MEMORY ; 00435 } 00436 00437 if (PAL_SUCCESS == status) 00438 { 00439 // init can not fail 00440 COS_MutexInit(&mutex->osMutex); 00441 00442 // Note: the PAL does not touch the given pointer unless success. 00443 *mutexID = (palMutexID_t)mutex; 00444 } 00445 00446 return status; 00447 } 00448 00449 00450 palStatus_t pal_plat_osMutexWait(palMutexID_t mutexID, uint32_t millisec) 00451 { 00452 palStatus_t status = PAL_SUCCESS; 00453 00454 palMutex_t* mutex = (palMutex_t*)mutexID; 00455 00456 if (millisec == PAL_RTOS_WAIT_FOREVER) { 00457 00458 COS_MutexLock(&mutex->osMutex); 00459 } 00460 else 00461 { 00462 if (COS_MutexTryLock(&mutex->osMutex, millisec) == false) { 00463 00464 status = PAL_ERR_RTOS_TIMEOUT ; 00465 } 00466 } 00467 00468 return status; 00469 } 00470 00471 00472 palStatus_t pal_plat_osMutexRelease(palMutexID_t mutexID) 00473 { 00474 palMutex_t* mutex = (palMutex_t*)mutexID; 00475 00476 COS_MutexUnlock(&mutex->osMutex); 00477 00478 return PAL_SUCCESS; 00479 } 00480 00481 palStatus_t pal_plat_osMutexDelete(palMutexID_t* mutexID) 00482 { 00483 palMutex_t* mutex = (palMutex_t*)*mutexID; 00484 COS_MutexDestroy(&mutex->osMutex); 00485 00486 free(mutex); 00487 00488 *mutexID = NULL; 00489 00490 return PAL_SUCCESS; 00491 } 00492 00493 palStatus_t pal_plat_osSemaphoreCreate(uint32_t count, palSemaphoreID_t* semaphoreID) 00494 { 00495 // There is a COS_CreateSemaphore() & COS_DeleteSemaphore()using HANDLE's, but it is 00496 // marked as deprecated. 00497 // Let's then use the other API, COS_Sema*, which takes in a COS_SEMA 00498 00499 palStatus_t status = PAL_SUCCESS; 00500 palSemaphore_t* semaphore; 00501 00502 // the COS_SemaInit() expects a zeroed struct, hence calloc() 00503 semaphore = (palSemaphore_t*)calloc(1, sizeof(palSemaphore_t)); 00504 if (NULL == semaphore) 00505 { 00506 status = PAL_ERR_NO_MEMORY ; 00507 } 00508 00509 if (PAL_SUCCESS == status) 00510 { 00511 // init can not fail 00512 COS_SemaInit(&semaphore->osSemaphore, count); 00513 00514 // Note: the PAL does not touch the given pointer unless success. 00515 *semaphoreID = (palSemaphoreID_t)semaphore; 00516 } 00517 00518 return status; 00519 } 00520 00521 palStatus_t pal_plat_osSemaphoreWait(palSemaphoreID_t semaphoreID, uint32_t millisec, int32_t* countersAvailable) 00522 { 00523 palStatus_t status = PAL_SUCCESS; 00524 00525 palSemaphore_t* semaphore = (palSemaphore_t*)semaphoreID; 00526 00527 if (millisec == PAL_RTOS_WAIT_FOREVER) 00528 { 00529 COS_SemaTake(&semaphore->osSemaphore); 00530 } 00531 else 00532 { 00533 if (COS_SemaTryTake(&semaphore->osSemaphore, millisec) == false) 00534 { 00535 status = PAL_ERR_RTOS_TIMEOUT ; 00536 } 00537 } 00538 00539 if ((NULL != countersAvailable) && (PAL_SUCCESS == status)) 00540 { 00541 // XXX: this is pointless, only the test code uses the counters value and 00542 // the whole countersAvailable needs to be removed from API. On other OS there are even 00543 // silly hacks to support this misfeature. 00544 *countersAvailable = semaphore->osSemaphore.count; 00545 } 00546 00547 return status; 00548 } 00549 00550 palStatus_t pal_plat_osSemaphoreRelease(palSemaphoreID_t semaphoreID) 00551 { 00552 palSemaphore_t* semaphore = (palSemaphore_t*)semaphoreID; 00553 00554 COS_SemaRelease(&semaphore->osSemaphore); 00555 00556 return PAL_SUCCESS; 00557 } 00558 00559 palStatus_t pal_plat_osSemaphoreDelete(palSemaphoreID_t* semaphoreID) 00560 { 00561 palSemaphore_t* semaphore = (palSemaphore_t*)*semaphoreID; 00562 00563 COS_SemaDestroy(&semaphore->osSemaphore); 00564 00565 free(semaphore); 00566 00567 *semaphoreID = NULL; 00568 00569 return PAL_SUCCESS; 00570 } 00571 00572 00573 void *pal_plat_malloc(size_t len) 00574 { 00575 return malloc(len); 00576 } 00577 00578 00579 void pal_plat_free(void * buffer) 00580 { 00581 free(buffer); 00582 } 00583 00584 int32_t pal_plat_osAtomicIncrement(int32_t* valuePtr, int32_t increment) 00585 { 00586 int32_t res; 00587 00588 HANDLE section = COS_EnterCriticalSection(); 00589 00590 res = *valuePtr + increment; 00591 *valuePtr = res; 00592 00593 COS_ExitCriticalSection(section); 00594 00595 return res; 00596 } 00597 00598 palStatus_t pal_plat_osRandomBuffer(uint8_t *randomBuf, size_t bufSizeBytes, size_t* actualRandomSizeBytes) 00599 { 00600 // XXX: this needs to return success until properly implemented to get the client side into network 00601 //palStatus_t status = PAL_ERR_NOT_IMPLEMENTED; 00602 00603 palStatus_t status = PAL_SUCCESS; 00604 return status; 00605 } 00606 00607 void pal_plat_osReboot(void) 00608 { 00609 DM_DeviceSwithOff(true); 00610 while (1) 00611 { 00612 COS_Sleep(1000); // Wait until reset 00613 } 00614 } 00615 00616 #if defined(PAL_USE_HW_RTC) 00617 00618 PAL_PRIVATE palMutexID_t rtcMutex = NULLPTR; 00619 00620 /* 00621 * Unisoc TM_FILENAME's DateTime is not seconds since 1.1.1970 but 00622 * seconds since 1.1.2000 00623 */ 00624 #define EPOCH_TIME_1_1_2000 (946684800) 00625 00626 palStatus_t pal_plat_osSetRtcTime(uint64_t rtcSetTime) 00627 { 00628 palStatus_t ret = PAL_SUCCESS; 00629 if (rtcSetTime < (uint64_t)PAL_MIN_RTC_SET_TIME) 00630 { 00631 ret = PAL_ERR_INVALID_TIME ; 00632 } 00633 else 00634 { 00635 ret = pal_osMutexWait(rtcMutex, 5 * PAL_MILLI_PER_SECOND * PAL_ONE_SEC); 00636 if (ret == PAL_SUCCESS) 00637 { 00638 TM_FILETIME tm_filetime; 00639 TM_SYSTEMTIME tm_systemtime; 00640 00641 tm_filetime.DateTime = (UINT32)rtcSetTime - EPOCH_TIME_1_1_2000; 00642 if (!TM_FileTimeToSystemTime(tm_filetime, &tm_systemtime)) 00643 { 00644 ret = PAL_ERR_TIME_TRANSLATE ; 00645 } 00646 00647 if (ret == PAL_SUCCESS) 00648 { 00649 // TM_SetSystemTime returns false if platform RTC handler is busy. 00650 // Therefore try couple of times. 00651 bool ret_rtc = false; 00652 for (int attempt = PAL_MAX_RTC_SET_ATTEMPTS; attempt > 0 && !ret_rtc; attempt--) 00653 { 00654 ret_rtc = TM_SetSystemTime(&tm_systemtime); 00655 00656 // Wait a moment before trying again 00657 if (!ret_rtc) 00658 { 00659 COS_Sleep(1); 00660 } 00661 } 00662 00663 if (!ret_rtc) 00664 { 00665 ret = PAL_ERR_RTOS_RTC_SET_TIME_ERROR; 00666 } 00667 } 00668 00669 pal_osMutexRelease(rtcMutex); 00670 } 00671 } 00672 00673 return ret; 00674 } 00675 00676 palStatus_t pal_plat_osGetRtcTime(uint64_t *rtcGetTime) 00677 { 00678 palStatus_t ret = PAL_SUCCESS; 00679 if (rtcGetTime != NULL) 00680 { 00681 TM_FILETIME tm_filetime; 00682 TM_SYSTEMTIME tm_systemtime; 00683 00684 if (!TM_GetSystemTime(&tm_systemtime)) 00685 { 00686 ret = PAL_ERR_RTOS_RTC_GET_TIME_ERROR; 00687 } 00688 00689 if (ret == PAL_SUCCESS && !TM_SystemTimeToFileTime(&tm_systemtime, &tm_filetime)) 00690 { 00691 ret = PAL_ERR_TIME_TRANSLATE ; 00692 } 00693 *rtcGetTime = (uint64_t)tm_filetime.DateTime + EPOCH_TIME_1_1_2000; 00694 } 00695 else 00696 { 00697 ret = PAL_ERR_NULL_POINTER ; 00698 } 00699 00700 return ret; 00701 } 00702 00703 palStatus_t pal_plat_rtcDeInit(void) 00704 { 00705 palStatus_t ret = PAL_SUCCESS; 00706 if (NULLPTR != rtcMutex) 00707 { 00708 ret = pal_osMutexDelete(&rtcMutex); 00709 rtcMutex = NULLPTR; 00710 } 00711 return ret; 00712 } 00713 00714 palStatus_t pal_plat_rtcInit(void) 00715 { 00716 palStatus_t ret = PAL_SUCCESS; 00717 if (NULLPTR == rtcMutex) 00718 { 00719 ret = pal_osMutexCreate(&rtcMutex); 00720 } 00721 return ret; 00722 } 00723 #endif
Generated on Tue Jul 12 2022 20:21:02 by
