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.
Dependents: TYBLE16_simple_data_logger TYBLE16_MP3_Air
nfc_scheduler.c
00001 /* 00002 * Copyright (c) 2015-2018, ARM Limited, All Rights Reserved 00003 * SPDX-License-Identifier: Apache-2.0 00004 * 00005 * Licensed under the Apache License, Version 2.0 (the "License"); you may 00006 * not use this file except in compliance with the License. 00007 * You may obtain a copy of the License at 00008 * 00009 * http://www.apache.org/licenses/LICENSE-2.0 00010 * 00011 * Unless required by applicable law or agreed to in writing, software 00012 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 00013 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00014 * See the License for the specific language governing permissions and 00015 * limitations under the License. 00016 */ 00017 /** 00018 * \file nfc_scheduler.c 00019 * \copyright Copyright (c) ARM Ltd 2015 00020 * \author Donatien Garnier 00021 */ 00022 00023 #include <stddef.h> 00024 #include <stdint.h> 00025 #include <stdbool.h> 00026 00027 #define __DEBUG__ 0 00028 #ifndef __MODULE__ 00029 #define __MODULE__ "nfc_scheduler.c" 00030 #endif 00031 00032 #include "platform/nfc_scheduler.h" 00033 00034 void nfc_scheduler_init(nfc_scheduler_t *pScheduler, nfc_scheduler_timer_t *pTimer) 00035 { 00036 pScheduler->pNext = NULL; 00037 pScheduler->pTimer = pTimer; 00038 00039 //Start timer 00040 nfc_scheduler_timer_start(pTimer); 00041 } 00042 00043 #define MAX_TIMEOUT UINT32_MAX 00044 00045 uint32_t nfc_scheduler_iteration(nfc_scheduler_t *pScheduler, uint32_t events) 00046 { 00047 while (true) { 00048 nfc_task_t *pPrioTask = NULL; 00049 nfc_task_t *pPrioTaskPrevious = NULL; 00050 uint32_t prioTaskEvent = 0; 00051 int64_t timeout; 00052 nfc_task_t *pPreviousTask = NULL; 00053 nfc_task_t *pTask = pScheduler->pNext; 00054 00055 if (pTask == NULL) { 00056 NFC_DBG("Empty queue, %lu ms elapsed", nfc_scheduler_timer_get(pScheduler->pTimer)); 00057 //Empty queue, return 00058 return MAX_TIMEOUT; 00059 } 00060 00061 //Get timer value 00062 uint32_t timeElapsed = nfc_scheduler_timer_get(pScheduler->pTimer); 00063 NFC_DBG("%lu ms elapsed", timeElapsed); 00064 nfc_scheduler_timer_reset(pScheduler->pTimer); 00065 00066 do { 00067 //Apply timeouts 00068 if (pTask->events & EVENT_TIMEOUT) { 00069 pTask->timeout -= timeElapsed; 00070 } 00071 pPreviousTask = pTask; 00072 pTask = pTask->pNext; 00073 } while (pTask != NULL); 00074 00075 pTask = pScheduler->pNext; 00076 pPreviousTask = NULL; 00077 timeout = MAX_TIMEOUT; 00078 do { 00079 //Check which task should be woken up first 00080 if ((events & EVENT_HW_INTERRUPT) && (pTask->events & EVENT_HW_INTERRUPT)) { 00081 //Hardware interrupts have prio 00082 pPrioTask = pTask; 00083 pPrioTaskPrevious = pPreviousTask; 00084 timeout = 0; 00085 events &= ~EVENT_HW_INTERRUPT; //Only one task gets triggered per event 00086 prioTaskEvent = EVENT_HW_INTERRUPT; 00087 break; 00088 } else if ((pTask->events & EVENT_TIMEOUT) && (pTask->timeout < timeout)) { 00089 pPrioTask = pTask; 00090 pPrioTaskPrevious = pPreviousTask; 00091 timeout = pTask->timeout; 00092 prioTaskEvent = EVENT_TIMEOUT; 00093 } 00094 pPreviousTask = pTask; 00095 pTask = pTask->pNext; 00096 } while (pTask != NULL); 00097 00098 if (pPrioTask == NULL) { 00099 //No task to wake up, exit 00100 NFC_DBG("No task to wake up"); 00101 return MAX_TIMEOUT; 00102 } 00103 00104 if (timeout > 0) { 00105 //No task to wake up yet 00106 if (timeout > MAX_TIMEOUT) { 00107 NFC_DBG("No task to wake up"); 00108 return MAX_TIMEOUT; 00109 } else { 00110 NFC_DBG("No task to wake up, wait %lu ms", timeout); 00111 return timeout; 00112 } 00113 } 00114 00115 //Dequeue task 00116 if (pPrioTaskPrevious == NULL) { 00117 pScheduler->pNext = pPrioTask->pNext; 00118 } else { 00119 pPrioTaskPrevious->pNext = pPrioTask->pNext; 00120 } 00121 pPrioTask->pNext = NULL; 00122 00123 //Execute task 00124 NFC_DBG("Calling task %p - events %02X", pPrioTask, prioTaskEvent); 00125 pPrioTask->fn(prioTaskEvent, pPrioTask->pUserData); 00126 events &= ~EVENT_HW_INTERRUPT; //Only one task gets triggered per event 00127 } 00128 return MAX_TIMEOUT; 00129 } 00130 00131 void nfc_scheduler_queue_task(nfc_scheduler_t *pScheduler, nfc_task_t *pTask) 00132 { 00133 pTask->timeout = pTask->timeoutInitial + nfc_scheduler_timer_get(pScheduler->pTimer); 00134 NFC_DBG("Queuing task %p: events %1X, timeout %lu ms", pTask, pTask->events, pTask->timeout); 00135 //Find last task 00136 nfc_task_t *pPrevTask = pScheduler->pNext; 00137 pTask->pNext = NULL; 00138 if (pPrevTask == NULL) { 00139 pScheduler->pNext = pTask; 00140 return; 00141 } 00142 while (pPrevTask->pNext != NULL) { 00143 pPrevTask = pPrevTask->pNext; 00144 } 00145 pPrevTask->pNext = pTask; 00146 } 00147 00148 void nfc_scheduler_dequeue_task(nfc_scheduler_t *pScheduler, bool abort, nfc_task_t *pTask) 00149 { 00150 NFC_DBG("Dequeuing task %p", pTask); 00151 //Find task 00152 nfc_task_t *pPrevTask = pScheduler->pNext; 00153 if (pPrevTask == NULL) { 00154 pTask->pNext = NULL; 00155 return; 00156 } 00157 if (pPrevTask == pTask) { 00158 if (abort) { 00159 pTask->fn(EVENT_ABORTED, pTask->pUserData); 00160 } 00161 pScheduler->pNext = pTask->pNext; 00162 pTask->pNext = NULL; 00163 return; 00164 } 00165 while (pPrevTask->pNext != NULL) { 00166 if (pPrevTask->pNext == pTask) { 00167 if (abort) { 00168 pTask->fn(EVENT_ABORTED, pTask->pUserData); 00169 } 00170 pPrevTask->pNext = pTask->pNext; 00171 pTask->pNext = NULL; 00172 return; 00173 } 00174 pPrevTask = pPrevTask->pNext; 00175 } 00176 pTask->pNext = NULL; 00177 } 00178 00179 void task_init(nfc_task_t *pTask, uint32_t events, uint32_t timeout, nfc_task_fn fn, void *pUserData) 00180 { 00181 pTask->events = events; 00182 pTask->timeoutInitial = timeout; 00183 pTask->fn = fn; 00184 pTask->pUserData = pUserData; 00185 pTask->pNext = NULL; 00186 }
Generated on Tue Jul 12 2022 13:54:38 by
