Import Mbed OS hard-float snapshot
This commit is contained in:
186
connectivity/nfc/libraries/stack/platform/nfc_scheduler.c
Normal file
186
connectivity/nfc/libraries/stack/platform/nfc_scheduler.c
Normal file
@@ -0,0 +1,186 @@
|
||||
/*
|
||||
* Copyright (c) 2015-2018, ARM Limited, All Rights Reserved
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
/**
|
||||
* \file nfc_scheduler.c
|
||||
* \copyright Copyright (c) ARM Ltd 2015
|
||||
* \author Donatien Garnier
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#define __DEBUG__ 0
|
||||
#ifndef __MODULE__
|
||||
#define __MODULE__ "nfc_scheduler.c"
|
||||
#endif
|
||||
|
||||
#include "platform/nfc_scheduler.h"
|
||||
|
||||
void nfc_scheduler_init(nfc_scheduler_t *pScheduler, nfc_scheduler_timer_t *pTimer)
|
||||
{
|
||||
pScheduler->pNext = NULL;
|
||||
pScheduler->pTimer = pTimer;
|
||||
|
||||
//Start timer
|
||||
nfc_scheduler_timer_start(pTimer);
|
||||
}
|
||||
|
||||
#define MAX_TIMEOUT UINT32_MAX
|
||||
|
||||
uint32_t nfc_scheduler_iteration(nfc_scheduler_t *pScheduler, uint32_t events)
|
||||
{
|
||||
while (true) {
|
||||
nfc_task_t *pPrioTask = NULL;
|
||||
nfc_task_t *pPrioTaskPrevious = NULL;
|
||||
uint32_t prioTaskEvent = 0;
|
||||
int64_t timeout;
|
||||
nfc_task_t *pPreviousTask = NULL;
|
||||
nfc_task_t *pTask = pScheduler->pNext;
|
||||
|
||||
if (pTask == NULL) {
|
||||
NFC_DBG("Empty queue, %lu ms elapsed", nfc_scheduler_timer_get(pScheduler->pTimer));
|
||||
//Empty queue, return
|
||||
return MAX_TIMEOUT;
|
||||
}
|
||||
|
||||
//Get timer value
|
||||
uint32_t timeElapsed = nfc_scheduler_timer_get(pScheduler->pTimer);
|
||||
NFC_DBG("%lu ms elapsed", timeElapsed);
|
||||
nfc_scheduler_timer_reset(pScheduler->pTimer);
|
||||
|
||||
do {
|
||||
//Apply timeouts
|
||||
if (pTask->events & EVENT_TIMEOUT) {
|
||||
pTask->timeout -= timeElapsed;
|
||||
}
|
||||
pPreviousTask = pTask;
|
||||
pTask = pTask->pNext;
|
||||
} while (pTask != NULL);
|
||||
|
||||
pTask = pScheduler->pNext;
|
||||
pPreviousTask = NULL;
|
||||
timeout = MAX_TIMEOUT;
|
||||
do {
|
||||
//Check which task should be woken up first
|
||||
if ((events & EVENT_HW_INTERRUPT) && (pTask->events & EVENT_HW_INTERRUPT)) {
|
||||
//Hardware interrupts have prio
|
||||
pPrioTask = pTask;
|
||||
pPrioTaskPrevious = pPreviousTask;
|
||||
timeout = 0;
|
||||
events &= ~EVENT_HW_INTERRUPT; //Only one task gets triggered per event
|
||||
prioTaskEvent = EVENT_HW_INTERRUPT;
|
||||
break;
|
||||
} else if ((pTask->events & EVENT_TIMEOUT) && (pTask->timeout < timeout)) {
|
||||
pPrioTask = pTask;
|
||||
pPrioTaskPrevious = pPreviousTask;
|
||||
timeout = pTask->timeout;
|
||||
prioTaskEvent = EVENT_TIMEOUT;
|
||||
}
|
||||
pPreviousTask = pTask;
|
||||
pTask = pTask->pNext;
|
||||
} while (pTask != NULL);
|
||||
|
||||
if (pPrioTask == NULL) {
|
||||
//No task to wake up, exit
|
||||
NFC_DBG("No task to wake up");
|
||||
return MAX_TIMEOUT;
|
||||
}
|
||||
|
||||
if (timeout > 0) {
|
||||
//No task to wake up yet
|
||||
if (timeout > MAX_TIMEOUT) {
|
||||
NFC_DBG("No task to wake up");
|
||||
return MAX_TIMEOUT;
|
||||
} else {
|
||||
NFC_DBG("No task to wake up, wait %lu ms", timeout);
|
||||
return timeout;
|
||||
}
|
||||
}
|
||||
|
||||
//Dequeue task
|
||||
if (pPrioTaskPrevious == NULL) {
|
||||
pScheduler->pNext = pPrioTask->pNext;
|
||||
} else {
|
||||
pPrioTaskPrevious->pNext = pPrioTask->pNext;
|
||||
}
|
||||
pPrioTask->pNext = NULL;
|
||||
|
||||
//Execute task
|
||||
NFC_DBG("Calling task %p - events %02X", pPrioTask, prioTaskEvent);
|
||||
pPrioTask->fn(prioTaskEvent, pPrioTask->pUserData);
|
||||
events &= ~EVENT_HW_INTERRUPT; //Only one task gets triggered per event
|
||||
}
|
||||
return MAX_TIMEOUT;
|
||||
}
|
||||
|
||||
void nfc_scheduler_queue_task(nfc_scheduler_t *pScheduler, nfc_task_t *pTask)
|
||||
{
|
||||
pTask->timeout = pTask->timeoutInitial + nfc_scheduler_timer_get(pScheduler->pTimer);
|
||||
NFC_DBG("Queuing task %p: events %1X, timeout %lu ms", pTask, pTask->events, pTask->timeout);
|
||||
//Find last task
|
||||
nfc_task_t *pPrevTask = pScheduler->pNext;
|
||||
pTask->pNext = NULL;
|
||||
if (pPrevTask == NULL) {
|
||||
pScheduler->pNext = pTask;
|
||||
return;
|
||||
}
|
||||
while (pPrevTask->pNext != NULL) {
|
||||
pPrevTask = pPrevTask->pNext;
|
||||
}
|
||||
pPrevTask->pNext = pTask;
|
||||
}
|
||||
|
||||
void nfc_scheduler_dequeue_task(nfc_scheduler_t *pScheduler, bool abort, nfc_task_t *pTask)
|
||||
{
|
||||
NFC_DBG("Dequeuing task %p", pTask);
|
||||
//Find task
|
||||
nfc_task_t *pPrevTask = pScheduler->pNext;
|
||||
if (pPrevTask == NULL) {
|
||||
pTask->pNext = NULL;
|
||||
return;
|
||||
}
|
||||
if (pPrevTask == pTask) {
|
||||
if (abort) {
|
||||
pTask->fn(EVENT_ABORTED, pTask->pUserData);
|
||||
}
|
||||
pScheduler->pNext = pTask->pNext;
|
||||
pTask->pNext = NULL;
|
||||
return;
|
||||
}
|
||||
while (pPrevTask->pNext != NULL) {
|
||||
if (pPrevTask->pNext == pTask) {
|
||||
if (abort) {
|
||||
pTask->fn(EVENT_ABORTED, pTask->pUserData);
|
||||
}
|
||||
pPrevTask->pNext = pTask->pNext;
|
||||
pTask->pNext = NULL;
|
||||
return;
|
||||
}
|
||||
pPrevTask = pPrevTask->pNext;
|
||||
}
|
||||
pTask->pNext = NULL;
|
||||
}
|
||||
|
||||
void task_init(nfc_task_t *pTask, uint32_t events, uint32_t timeout, nfc_task_fn fn, void *pUserData)
|
||||
{
|
||||
pTask->events = events;
|
||||
pTask->timeoutInitial = timeout;
|
||||
pTask->fn = fn;
|
||||
pTask->pUserData = pUserData;
|
||||
pTask->pNext = NULL;
|
||||
}
|
||||
Reference in New Issue
Block a user