#![allow(unused_variables)]
#![allow(non_upper_case_globals)]
#![allow(non_camel_case_types)]
#![allow(dead_code)]
#![allow(static_mut_refs)]
use core::ffi::c_void;
use core::ptr;
use crate::config::*;
use crate::kernel::list::*;
use crate::kernel::queue::*;
use crate::kernel::tasks::*;
use crate::memory::*;
use crate::types::*;
use crate::{
traceENTER_pcTimerGetName, traceENTER_pvTimerGetTimerID, traceENTER_uxTimerGetReloadMode,
traceENTER_vTimerSetReloadMode, traceENTER_vTimerSetTimerID, traceENTER_xTimerCreate,
traceENTER_xTimerCreateStatic, traceENTER_xTimerCreateTimerTask,
traceENTER_xTimerGenericCommandFromISR, traceENTER_xTimerGenericCommandFromTask,
traceENTER_xTimerGetExpiryTime, traceENTER_xTimerGetPeriod, traceENTER_xTimerGetReloadMode,
traceENTER_xTimerGetStaticBuffer, traceENTER_xTimerGetTimerDaemonTaskHandle,
traceENTER_xTimerIsTimerActive, traceRETURN_pcTimerGetName, traceRETURN_pvTimerGetTimerID,
traceRETURN_uxTimerGetReloadMode, traceRETURN_vTimerSetReloadMode,
traceRETURN_vTimerSetTimerID, traceRETURN_xTimerCreate, traceRETURN_xTimerCreateStatic,
traceRETURN_xTimerCreateTimerTask, traceRETURN_xTimerGenericCommandFromISR,
traceRETURN_xTimerGenericCommandFromTask, traceRETURN_xTimerGetExpiryTime,
traceRETURN_xTimerGetPeriod, traceRETURN_xTimerGetReloadMode,
traceRETURN_xTimerGetStaticBuffer, traceRETURN_xTimerGetTimerDaemonTaskHandle,
traceRETURN_xTimerIsTimerActive, traceTIMER_COMMAND_RECEIVED, traceTIMER_COMMAND_SEND,
traceTIMER_CREATE, traceTIMER_EXPIRED,
};
#[cfg(feature = "trace-facility")]
use crate::{
traceENTER_uxTimerGetTimerNumber, traceENTER_vTimerSetTimerNumber,
traceRETURN_uxTimerGetTimerNumber, traceRETURN_vTimerSetTimerNumber,
};
#[cfg(feature = "pend-function-call")]
use crate::{
traceENTER_xTimerPendFunctionCall, traceENTER_xTimerPendFunctionCallFromISR,
tracePEND_FUNC_CALL, tracePEND_FUNC_CALL_FROM_ISR, traceRETURN_xTimerPendFunctionCall,
traceRETURN_xTimerPendFunctionCallFromISR,
};
const tmrNO_DELAY: TickType_t = 0;
const tmrMAX_TIME_BEFORE_OVERFLOW: TickType_t = !0;
pub const configTIMER_SERVICE_TASK_NAME: &[u8] = b"Tmr Svc\0";
const tmrSTATUS_IS_ACTIVE: u8 = 0x01;
const tmrSTATUS_IS_STATICALLY_ALLOCATED: u8 = 0x02;
const tmrSTATUS_IS_AUTORELOAD: u8 = 0x04;
pub const tmrCOMMAND_EXECUTE_CALLBACK_FROM_ISR: BaseType_t = -2;
pub const tmrCOMMAND_EXECUTE_CALLBACK: BaseType_t = -1;
pub const tmrCOMMAND_START_DONT_TRACE: BaseType_t = 0;
pub const tmrCOMMAND_START: BaseType_t = 1;
pub const tmrCOMMAND_RESET: BaseType_t = 2;
pub const tmrCOMMAND_STOP: BaseType_t = 3;
pub const tmrCOMMAND_CHANGE_PERIOD: BaseType_t = 4;
pub const tmrCOMMAND_DELETE: BaseType_t = 5;
pub const tmrFIRST_FROM_ISR_COMMAND: BaseType_t = 6;
pub const tmrCOMMAND_START_FROM_ISR: BaseType_t = 6;
pub const tmrCOMMAND_RESET_FROM_ISR: BaseType_t = 7;
pub const tmrCOMMAND_STOP_FROM_ISR: BaseType_t = 8;
pub const tmrCOMMAND_CHANGE_PERIOD_FROM_ISR: BaseType_t = 9;
pub type TimerCallbackFunction_t = extern "C" fn(TimerHandle_t);
pub type PendedFunction_t = extern "C" fn(*mut c_void, u32);
#[repr(C)]
pub struct xTIMER {
pub pcTimerName: *const u8,
pub xTimerListItem: ListItem_t,
pub xTimerPeriodInTicks: TickType_t,
pub pvTimerID: *mut c_void,
pub pxCallbackFunction: TimerCallbackFunction_t,
#[cfg(feature = "trace-facility")]
pub uxTimerNumber: UBaseType_t,
pub ucStatus: u8,
}
pub type Timer_t = xTIMER;
#[repr(C)]
#[derive(Clone, Copy)]
pub struct TimerParameter_t {
pub xMessageValue: TickType_t,
pub pxTimer: *mut Timer_t,
}
#[repr(C)]
#[derive(Clone, Copy)]
pub struct CallbackParameters_t {
pub pxCallbackFunction: PendedFunction_t,
pub pvParameter1: *mut c_void,
pub ulParameter2: u32,
}
#[repr(C)]
#[derive(Clone, Copy)]
pub union DaemonTaskMessageUnion {
pub xTimerParameters: TimerParameter_t,
pub xCallbackParameters: CallbackParameters_t,
}
#[repr(C)]
pub struct DaemonTaskMessage_t {
pub xMessageID: BaseType_t,
pub u: DaemonTaskMessageUnion,
}
#[repr(C)]
pub struct StaticTimer_t {
pub pvDummy1: *mut c_void,
pub xDummy2: StaticListItem_t,
pub xDummy3: TickType_t,
pub pvDummy4: *mut c_void,
pub pvDummy5: *mut c_void,
#[cfg(feature = "trace-facility")]
pub uxDummy6: UBaseType_t,
pub ucDummy7: u8,
}
static mut xActiveTimerList1: List_t = List_t::new();
static mut xActiveTimerList2: List_t = List_t::new();
static mut pxCurrentTimerList: *mut List_t = ptr::null_mut();
static mut pxOverflowTimerList: *mut List_t = ptr::null_mut();
static mut xTimerQueue: QueueHandle_t = ptr::null_mut();
static mut xTimerTaskHandle: TaskHandle_t = ptr::null_mut();
static mut xLastTime: TickType_t = 0;
pub fn xTimerCreateTimerTask() -> BaseType_t {
let mut xReturn: BaseType_t = pdFAIL;
traceENTER_xTimerCreateTimerTask!();
prvCheckForValidListAndQueue();
unsafe {
if xTimerQueue != ptr::null_mut() {
#[cfg(any(feature = "alloc", feature = "heap-4", feature = "heap-5"))]
{
xReturn = xTaskCreate(
prvTimerTask,
configTIMER_SERVICE_TASK_NAME.as_ptr(),
configTIMER_TASK_STACK_DEPTH,
ptr::null_mut(),
configTIMER_TASK_PRIORITY,
&mut xTimerTaskHandle,
);
}
#[cfg(not(any(feature = "alloc", feature = "heap-4", feature = "heap-5")))]
{
xReturn = pdFAIL;
}
}
}
configASSERT(xReturn != pdFAIL);
traceRETURN_xTimerCreateTimerTask!(xReturn);
xReturn
}
#[cfg(any(feature = "alloc", feature = "heap-4", feature = "heap-5"))]
pub fn xTimerCreate(
pcTimerName: *const u8,
xTimerPeriodInTicks: TickType_t,
xAutoReload: BaseType_t,
pvTimerID: *mut c_void,
pxCallbackFunction: TimerCallbackFunction_t,
) -> TimerHandle_t {
traceENTER_xTimerCreate!(
pcTimerName,
xTimerPeriodInTicks,
xAutoReload,
pvTimerID,
pxCallbackFunction
);
let pxNewTimer: *mut Timer_t =
unsafe { pvPortMalloc(core::mem::size_of::<Timer_t>()) as *mut Timer_t };
if pxNewTimer != ptr::null_mut() {
unsafe {
(*pxNewTimer).ucStatus = 0x00;
}
prvInitialiseNewTimer(
pcTimerName,
xTimerPeriodInTicks,
xAutoReload,
pvTimerID,
pxCallbackFunction,
pxNewTimer,
);
}
traceRETURN_xTimerCreate!(pxNewTimer);
pxNewTimer as TimerHandle_t
}
pub fn xTimerCreateStatic(
pcTimerName: *const u8,
xTimerPeriodInTicks: TickType_t,
xAutoReload: BaseType_t,
pvTimerID: *mut c_void,
pxCallbackFunction: TimerCallbackFunction_t,
pxTimerBuffer: *mut StaticTimer_t,
) -> TimerHandle_t {
traceENTER_xTimerCreateStatic!(
pcTimerName,
xTimerPeriodInTicks,
xAutoReload,
pvTimerID,
pxCallbackFunction,
pxTimerBuffer
);
#[cfg(debug_assertions)]
{
let static_size = core::mem::size_of::<StaticTimer_t>();
let timer_size = core::mem::size_of::<Timer_t>();
configASSERT(static_size == timer_size);
}
configASSERT(pxTimerBuffer != ptr::null_mut());
let pxNewTimer: *mut Timer_t = pxTimerBuffer as *mut Timer_t;
if pxNewTimer != ptr::null_mut() {
unsafe {
(*pxNewTimer).ucStatus = tmrSTATUS_IS_STATICALLY_ALLOCATED;
}
prvInitialiseNewTimer(
pcTimerName,
xTimerPeriodInTicks,
xAutoReload,
pvTimerID,
pxCallbackFunction,
pxNewTimer,
);
}
traceRETURN_xTimerCreateStatic!(pxNewTimer);
pxNewTimer as TimerHandle_t
}
pub fn xTimerGenericCommandFromTask(
xTimer: TimerHandle_t,
xCommandID: BaseType_t,
xOptionalValue: TickType_t,
pxHigherPriorityTaskWoken: *mut BaseType_t,
xTicksToWait: TickType_t,
) -> BaseType_t {
let mut xReturn: BaseType_t = pdFAIL;
traceENTER_xTimerGenericCommandFromTask!(
xTimer,
xCommandID,
xOptionalValue,
pxHigherPriorityTaskWoken,
xTicksToWait
);
unsafe {
if xTimerQueue != ptr::null_mut() && xTimer != ptr::null_mut() {
let mut xMessage: DaemonTaskMessage_t = core::mem::zeroed();
xMessage.xMessageID = xCommandID;
xMessage.u.xTimerParameters.xMessageValue = xOptionalValue;
xMessage.u.xTimerParameters.pxTimer = xTimer as *mut Timer_t;
configASSERT(xCommandID < tmrFIRST_FROM_ISR_COMMAND);
if xCommandID < tmrFIRST_FROM_ISR_COMMAND {
let xTicksToWaitActual = if xTaskGetSchedulerState() == taskSCHEDULER_RUNNING {
xTicksToWait
} else {
tmrNO_DELAY
};
xReturn = xQueueSendToBack(
xTimerQueue,
&xMessage as *const _ as *const c_void,
xTicksToWaitActual,
);
}
traceTIMER_COMMAND_SEND!(xTimer, xCommandID, xOptionalValue, xReturn);
}
}
traceRETURN_xTimerGenericCommandFromTask!(xReturn);
xReturn
}
pub fn xTimerGenericCommandFromISR(
xTimer: TimerHandle_t,
xCommandID: BaseType_t,
xOptionalValue: TickType_t,
pxHigherPriorityTaskWoken: *mut BaseType_t,
_xTicksToWait: TickType_t,
) -> BaseType_t {
let mut xReturn: BaseType_t = pdFAIL;
traceENTER_xTimerGenericCommandFromISR!(
xTimer,
xCommandID,
xOptionalValue,
pxHigherPriorityTaskWoken,
_xTicksToWait
);
unsafe {
if xTimerQueue != ptr::null_mut() && xTimer != ptr::null_mut() {
let mut xMessage: DaemonTaskMessage_t = core::mem::zeroed();
xMessage.xMessageID = xCommandID;
xMessage.u.xTimerParameters.xMessageValue = xOptionalValue;
xMessage.u.xTimerParameters.pxTimer = xTimer as *mut Timer_t;
configASSERT(xCommandID >= tmrFIRST_FROM_ISR_COMMAND);
if xCommandID >= tmrFIRST_FROM_ISR_COMMAND {
xReturn = xQueueSendToBackFromISR(
xTimerQueue,
&xMessage as *const _ as *const c_void,
pxHigherPriorityTaskWoken,
);
}
traceTIMER_COMMAND_SEND!(xTimer, xCommandID, xOptionalValue, xReturn);
}
}
traceRETURN_xTimerGenericCommandFromISR!(xReturn);
xReturn
}
#[inline(always)]
pub fn xTimerGenericCommand(
xTimer: TimerHandle_t,
xCommandID: BaseType_t,
xOptionalValue: TickType_t,
pxHigherPriorityTaskWoken: *mut BaseType_t,
xTicksToWait: TickType_t,
) -> BaseType_t {
if xCommandID < tmrFIRST_FROM_ISR_COMMAND {
xTimerGenericCommandFromTask(
xTimer,
xCommandID,
xOptionalValue,
pxHigherPriorityTaskWoken,
xTicksToWait,
)
} else {
xTimerGenericCommandFromISR(
xTimer,
xCommandID,
xOptionalValue,
pxHigherPriorityTaskWoken,
xTicksToWait,
)
}
}
pub fn xTimerGetTimerDaemonTaskHandle() -> TaskHandle_t {
traceENTER_xTimerGetTimerDaemonTaskHandle!();
unsafe {
configASSERT(xTimerTaskHandle != ptr::null_mut());
traceRETURN_xTimerGetTimerDaemonTaskHandle!(xTimerTaskHandle);
xTimerTaskHandle
}
}
pub fn xTimerGetPeriod(xTimer: TimerHandle_t) -> TickType_t {
let pxTimer = xTimer as *mut Timer_t;
traceENTER_xTimerGetPeriod!(xTimer);
configASSERT(xTimer != ptr::null_mut());
let xReturn = unsafe { (*pxTimer).xTimerPeriodInTicks };
traceRETURN_xTimerGetPeriod!(xReturn);
xReturn
}
pub fn vTimerSetReloadMode(xTimer: TimerHandle_t, xAutoReload: BaseType_t) {
let pxTimer = xTimer as *mut Timer_t;
traceENTER_vTimerSetReloadMode!(xTimer, xAutoReload);
configASSERT(xTimer != ptr::null_mut());
taskENTER_CRITICAL();
unsafe {
if xAutoReload != pdFALSE {
(*pxTimer).ucStatus |= tmrSTATUS_IS_AUTORELOAD;
} else {
(*pxTimer).ucStatus &= !tmrSTATUS_IS_AUTORELOAD;
}
}
taskEXIT_CRITICAL();
traceRETURN_vTimerSetReloadMode!();
}
pub fn xTimerGetReloadMode(xTimer: TimerHandle_t) -> BaseType_t {
let pxTimer = xTimer as *mut Timer_t;
let xReturn: BaseType_t;
traceENTER_xTimerGetReloadMode!(xTimer);
configASSERT(xTimer != ptr::null_mut());
taskENTER_CRITICAL();
unsafe {
if ((*pxTimer).ucStatus & tmrSTATUS_IS_AUTORELOAD) == 0 {
xReturn = pdFALSE;
} else {
xReturn = pdTRUE;
}
}
taskEXIT_CRITICAL();
traceRETURN_xTimerGetReloadMode!(xReturn);
xReturn
}
pub fn uxTimerGetReloadMode(xTimer: TimerHandle_t) -> UBaseType_t {
traceENTER_uxTimerGetReloadMode!(xTimer);
let uxReturn = xTimerGetReloadMode(xTimer) as UBaseType_t;
traceRETURN_uxTimerGetReloadMode!(uxReturn);
uxReturn
}
pub fn xTimerGetExpiryTime(xTimer: TimerHandle_t) -> TickType_t {
let pxTimer = xTimer as *mut Timer_t;
traceENTER_xTimerGetExpiryTime!(xTimer);
configASSERT(xTimer != ptr::null_mut());
let xReturn = unsafe { listGET_LIST_ITEM_VALUE(&(*pxTimer).xTimerListItem) };
traceRETURN_xTimerGetExpiryTime!(xReturn);
xReturn
}
pub fn pcTimerGetName(xTimer: TimerHandle_t) -> *const u8 {
let pxTimer = xTimer as *mut Timer_t;
traceENTER_pcTimerGetName!(xTimer);
configASSERT(xTimer != ptr::null_mut());
let pcName = unsafe { (*pxTimer).pcTimerName };
traceRETURN_pcTimerGetName!(pcName);
pcName
}
pub fn xTimerIsTimerActive(xTimer: TimerHandle_t) -> BaseType_t {
let pxTimer = xTimer as *mut Timer_t;
let xReturn: BaseType_t;
traceENTER_xTimerIsTimerActive!(xTimer);
configASSERT(xTimer != ptr::null_mut());
taskENTER_CRITICAL();
unsafe {
if ((*pxTimer).ucStatus & tmrSTATUS_IS_ACTIVE) == 0 {
xReturn = pdFALSE;
} else {
xReturn = pdTRUE;
}
}
taskEXIT_CRITICAL();
traceRETURN_xTimerIsTimerActive!(xReturn);
xReturn
}
pub fn pvTimerGetTimerID(xTimer: TimerHandle_t) -> *mut c_void {
let pxTimer = xTimer as *mut Timer_t;
traceENTER_pvTimerGetTimerID!(xTimer);
configASSERT(xTimer != ptr::null_mut());
let pvReturn: *mut c_void;
taskENTER_CRITICAL();
unsafe {
pvReturn = (*pxTimer).pvTimerID;
}
taskEXIT_CRITICAL();
traceRETURN_pvTimerGetTimerID!(pvReturn);
pvReturn
}
pub fn vTimerSetTimerID(xTimer: TimerHandle_t, pvNewID: *mut c_void) {
let pxTimer = xTimer as *mut Timer_t;
traceENTER_vTimerSetTimerID!(xTimer, pvNewID);
configASSERT(xTimer != ptr::null_mut());
taskENTER_CRITICAL();
unsafe {
(*pxTimer).pvTimerID = pvNewID;
}
taskEXIT_CRITICAL();
traceRETURN_vTimerSetTimerID!();
}
pub fn xTimerGetStaticBuffer(
xTimer: TimerHandle_t,
ppxTimerBuffer: *mut *mut StaticTimer_t,
) -> BaseType_t {
let pxTimer = xTimer as *mut Timer_t;
let xReturn: BaseType_t;
traceENTER_xTimerGetStaticBuffer!(xTimer, ppxTimerBuffer);
configASSERT(ppxTimerBuffer != ptr::null_mut());
unsafe {
if ((*pxTimer).ucStatus & tmrSTATUS_IS_STATICALLY_ALLOCATED) != 0 {
*ppxTimerBuffer = pxTimer as *mut StaticTimer_t;
xReturn = pdTRUE;
} else {
xReturn = pdFALSE;
}
}
traceRETURN_xTimerGetStaticBuffer!(xReturn);
xReturn
}
pub fn vTimerResetState() {
unsafe {
xTimerQueue = ptr::null_mut();
xTimerTaskHandle = ptr::null_mut();
}
}
#[cfg(feature = "trace-facility")]
pub fn uxTimerGetTimerNumber(xTimer: TimerHandle_t) -> UBaseType_t {
traceENTER_uxTimerGetTimerNumber!(xTimer);
let uxReturn = unsafe { (*(xTimer as *mut Timer_t)).uxTimerNumber };
traceRETURN_uxTimerGetTimerNumber!(uxReturn);
uxReturn
}
#[cfg(feature = "trace-facility")]
pub fn vTimerSetTimerNumber(xTimer: TimerHandle_t, uxTimerNumber: UBaseType_t) {
traceENTER_vTimerSetTimerNumber!(xTimer, uxTimerNumber);
unsafe {
(*(xTimer as *mut Timer_t)).uxTimerNumber = uxTimerNumber;
}
traceRETURN_vTimerSetTimerNumber!();
}
#[cfg(feature = "pend-function-call")]
pub fn xTimerPendFunctionCallFromISR(
xFunctionToPend: PendedFunction_t,
pvParameter1: *mut c_void,
ulParameter2: u32,
pxHigherPriorityTaskWoken: *mut BaseType_t,
) -> BaseType_t {
traceENTER_xTimerPendFunctionCallFromISR!(
xFunctionToPend,
pvParameter1,
ulParameter2,
pxHigherPriorityTaskWoken
);
let mut xMessage: DaemonTaskMessage_t = unsafe { core::mem::zeroed() };
xMessage.xMessageID = tmrCOMMAND_EXECUTE_CALLBACK_FROM_ISR;
xMessage.u.xCallbackParameters.pxCallbackFunction = xFunctionToPend;
xMessage.u.xCallbackParameters.pvParameter1 = pvParameter1;
xMessage.u.xCallbackParameters.ulParameter2 = ulParameter2;
let xReturn = unsafe {
xQueueSendFromISR(
xTimerQueue,
&xMessage as *const _ as *const c_void,
pxHigherPriorityTaskWoken,
)
};
tracePEND_FUNC_CALL_FROM_ISR!(xFunctionToPend, pvParameter1, ulParameter2, xReturn);
traceRETURN_xTimerPendFunctionCallFromISR!(xReturn);
xReturn
}
#[cfg(feature = "pend-function-call")]
pub fn xTimerPendFunctionCall(
xFunctionToPend: PendedFunction_t,
pvParameter1: *mut c_void,
ulParameter2: u32,
xTicksToWait: TickType_t,
) -> BaseType_t {
traceENTER_xTimerPendFunctionCall!(xFunctionToPend, pvParameter1, ulParameter2, xTicksToWait);
unsafe {
configASSERT(xTimerQueue != ptr::null_mut());
}
let mut xMessage: DaemonTaskMessage_t = unsafe { core::mem::zeroed() };
xMessage.xMessageID = tmrCOMMAND_EXECUTE_CALLBACK;
xMessage.u.xCallbackParameters.pxCallbackFunction = xFunctionToPend;
xMessage.u.xCallbackParameters.pvParameter1 = pvParameter1;
xMessage.u.xCallbackParameters.ulParameter2 = ulParameter2;
let xReturn = unsafe {
xQueueSendToBack(
xTimerQueue,
&xMessage as *const _ as *const c_void,
xTicksToWait,
)
};
tracePEND_FUNC_CALL!(xFunctionToPend, pvParameter1, ulParameter2, xReturn);
traceRETURN_xTimerPendFunctionCall!(xReturn);
xReturn
}
fn prvInitialiseNewTimer(
pcTimerName: *const u8,
xTimerPeriodInTicks: TickType_t,
xAutoReload: BaseType_t,
pvTimerID: *mut c_void,
pxCallbackFunction: TimerCallbackFunction_t,
pxNewTimer: *mut Timer_t,
) {
configASSERT(xTimerPeriodInTicks > 0);
prvCheckForValidListAndQueue();
unsafe {
(*pxNewTimer).pcTimerName = pcTimerName;
(*pxNewTimer).xTimerPeriodInTicks = xTimerPeriodInTicks;
(*pxNewTimer).pvTimerID = pvTimerID;
(*pxNewTimer).pxCallbackFunction = pxCallbackFunction;
vListInitialiseItem(&mut (*pxNewTimer).xTimerListItem);
if xAutoReload != pdFALSE {
(*pxNewTimer).ucStatus |= tmrSTATUS_IS_AUTORELOAD;
}
}
traceTIMER_CREATE!(pxNewTimer);
}
fn prvCheckForValidListAndQueue() {
taskENTER_CRITICAL();
unsafe {
if xTimerQueue == ptr::null_mut() {
vListInitialise(&mut xActiveTimerList1);
vListInitialise(&mut xActiveTimerList2);
pxCurrentTimerList = &mut xActiveTimerList1;
pxOverflowTimerList = &mut xActiveTimerList2;
xTimerQueue = xQueueCreate(
configTIMER_QUEUE_LENGTH,
core::mem::size_of::<DaemonTaskMessage_t>() as UBaseType_t,
);
}
}
taskEXIT_CRITICAL();
}
extern "C" fn prvTimerTask(pvParameters: *mut c_void) {
let mut xNextExpireTime: TickType_t;
let mut xListWasEmpty: BaseType_t = pdFALSE;
let _ = pvParameters;
loop {
xNextExpireTime = prvGetNextExpireTime(&mut xListWasEmpty);
prvProcessTimerOrBlockTask(xNextExpireTime, xListWasEmpty);
prvProcessReceivedCommands();
}
}
fn prvGetNextExpireTime(pxListWasEmpty: *mut BaseType_t) -> TickType_t {
let xNextExpireTime: TickType_t;
unsafe {
*pxListWasEmpty = listLIST_IS_EMPTY(pxCurrentTimerList);
if *pxListWasEmpty == pdFALSE {
xNextExpireTime = listGET_ITEM_VALUE_OF_HEAD_ENTRY(pxCurrentTimerList);
} else {
xNextExpireTime = 0;
}
}
xNextExpireTime
}
fn prvSampleTimeNow(pxTimerListsWereSwitched: *mut BaseType_t) -> TickType_t {
let xTimeNow: TickType_t;
xTimeNow = xTaskGetTickCount();
unsafe {
if xTimeNow < xLastTime {
prvSwitchTimerLists();
*pxTimerListsWereSwitched = pdTRUE;
} else {
*pxTimerListsWereSwitched = pdFALSE;
}
xLastTime = xTimeNow;
}
xTimeNow
}
fn prvSwitchTimerLists() {
let mut xNextExpireTime: TickType_t;
unsafe {
while listLIST_IS_EMPTY(pxCurrentTimerList) == pdFALSE {
xNextExpireTime = listGET_ITEM_VALUE_OF_HEAD_ENTRY(pxCurrentTimerList);
prvProcessExpiredTimer(xNextExpireTime, tmrMAX_TIME_BEFORE_OVERFLOW);
}
let pxTemp = pxCurrentTimerList;
pxCurrentTimerList = pxOverflowTimerList;
pxOverflowTimerList = pxTemp;
}
}
fn prvProcessTimerOrBlockTask(xNextExpireTime: TickType_t, xListWasEmpty: BaseType_t) {
let mut xTimerListsWereSwitched: BaseType_t = pdFALSE;
vTaskSuspendAll();
unsafe {
let xTimeNow = prvSampleTimeNow(&mut xTimerListsWereSwitched);
if xTimerListsWereSwitched == pdFALSE {
if (xListWasEmpty == pdFALSE) && (xNextExpireTime <= xTimeNow) {
xTaskResumeAll();
prvProcessExpiredTimer(xNextExpireTime, xTimeNow);
} else {
let mut xListWasEmptyNow = xListWasEmpty;
if xListWasEmptyNow != pdFALSE {
xListWasEmptyNow = listLIST_IS_EMPTY(pxOverflowTimerList);
}
vQueueWaitForMessageRestricted(
xTimerQueue,
xNextExpireTime.wrapping_sub(xTimeNow),
xListWasEmptyNow,
);
if xTaskResumeAll() == pdFALSE {
portYIELD_WITHIN_API();
}
}
} else {
xTaskResumeAll();
}
}
}
fn prvInsertTimerInActiveList(
pxTimer: *mut Timer_t,
xNextExpiryTime: TickType_t,
xTimeNow: TickType_t,
xCommandTime: TickType_t,
) -> BaseType_t {
let mut xProcessTimerNow: BaseType_t = pdFALSE;
unsafe {
listSET_LIST_ITEM_VALUE(&mut (*pxTimer).xTimerListItem, xNextExpiryTime);
listSET_LIST_ITEM_OWNER(&mut (*pxTimer).xTimerListItem, pxTimer as *mut c_void);
if xNextExpiryTime <= xTimeNow {
if xTimeNow.wrapping_sub(xCommandTime) >= (*pxTimer).xTimerPeriodInTicks {
xProcessTimerNow = pdTRUE;
} else {
vListInsert(pxOverflowTimerList, &mut (*pxTimer).xTimerListItem);
}
} else {
if (xTimeNow < xCommandTime) && (xNextExpiryTime >= xCommandTime) {
xProcessTimerNow = pdTRUE;
} else {
vListInsert(pxCurrentTimerList, &mut (*pxTimer).xTimerListItem);
}
}
}
xProcessTimerNow
}
fn prvReloadTimer(pxTimer: *mut Timer_t, mut xExpiredTime: TickType_t, xTimeNow: TickType_t) {
unsafe {
while prvInsertTimerInActiveList(
pxTimer,
xExpiredTime.wrapping_add((*pxTimer).xTimerPeriodInTicks),
xTimeNow,
xExpiredTime,
) != pdFALSE
{
xExpiredTime = xExpiredTime.wrapping_add((*pxTimer).xTimerPeriodInTicks);
traceTIMER_EXPIRED!(pxTimer);
((*pxTimer).pxCallbackFunction)(pxTimer as TimerHandle_t);
}
}
}
fn prvProcessExpiredTimer(xNextExpireTime: TickType_t, xTimeNow: TickType_t) {
unsafe {
let pxTimer = listGET_OWNER_OF_HEAD_ENTRY(pxCurrentTimerList) as *mut Timer_t;
uxListRemove(&mut (*pxTimer).xTimerListItem);
if ((*pxTimer).ucStatus & tmrSTATUS_IS_AUTORELOAD) != 0 {
prvReloadTimer(pxTimer, xNextExpireTime, xTimeNow);
} else {
(*pxTimer).ucStatus &= !tmrSTATUS_IS_ACTIVE;
}
traceTIMER_EXPIRED!(pxTimer);
((*pxTimer).pxCallbackFunction)(pxTimer as TimerHandle_t);
}
}
fn prvProcessReceivedCommands() {
let mut xMessage: DaemonTaskMessage_t = unsafe { core::mem::zeroed() };
let mut pxTimer: *mut Timer_t;
let mut xTimerListsWereSwitched: BaseType_t = pdFALSE;
unsafe {
while xQueueReceive(
xTimerQueue,
&mut xMessage as *mut _ as *mut c_void,
tmrNO_DELAY,
) != pdFAIL
{
#[cfg(feature = "pend-function-call")]
{
if xMessage.xMessageID < 0 {
let pxCallback = &xMessage.u.xCallbackParameters;
(pxCallback.pxCallbackFunction)(
pxCallback.pvParameter1,
pxCallback.ulParameter2,
);
}
}
if xMessage.xMessageID >= 0 {
pxTimer = xMessage.u.xTimerParameters.pxTimer;
if pxTimer != ptr::null_mut() {
if listIS_CONTAINED_WITHIN(ptr::null_mut(), &mut (*pxTimer).xTimerListItem)
== pdFALSE
{
uxListRemove(&mut (*pxTimer).xTimerListItem);
}
traceTIMER_COMMAND_RECEIVED!(
pxTimer,
xMessage.xMessageID,
xMessage.u.xTimerParameters.xMessageValue
);
let xTimeNow = prvSampleTimeNow(&mut xTimerListsWereSwitched);
match xMessage.xMessageID {
x if x == tmrCOMMAND_START
|| x == tmrCOMMAND_START_FROM_ISR
|| x == tmrCOMMAND_RESET
|| x == tmrCOMMAND_RESET_FROM_ISR =>
{
(*pxTimer).ucStatus |= tmrSTATUS_IS_ACTIVE;
let xNextExpiryTime = xMessage
.u
.xTimerParameters
.xMessageValue
.wrapping_add((*pxTimer).xTimerPeriodInTicks);
if prvInsertTimerInActiveList(
pxTimer,
xNextExpiryTime,
xTimeNow,
xMessage.u.xTimerParameters.xMessageValue,
) != pdFALSE
{
if ((*pxTimer).ucStatus & tmrSTATUS_IS_AUTORELOAD) != 0 {
prvReloadTimer(pxTimer, xNextExpiryTime, xTimeNow);
} else {
(*pxTimer).ucStatus &= !tmrSTATUS_IS_ACTIVE;
}
traceTIMER_EXPIRED!(pxTimer);
((*pxTimer).pxCallbackFunction)(pxTimer as TimerHandle_t);
}
}
x if x == tmrCOMMAND_STOP || x == tmrCOMMAND_STOP_FROM_ISR => {
(*pxTimer).ucStatus &= !tmrSTATUS_IS_ACTIVE;
}
x if x == tmrCOMMAND_CHANGE_PERIOD
|| x == tmrCOMMAND_CHANGE_PERIOD_FROM_ISR =>
{
(*pxTimer).ucStatus |= tmrSTATUS_IS_ACTIVE;
(*pxTimer).xTimerPeriodInTicks =
xMessage.u.xTimerParameters.xMessageValue;
configASSERT((*pxTimer).xTimerPeriodInTicks > 0);
prvInsertTimerInActiveList(
pxTimer,
xTimeNow.wrapping_add((*pxTimer).xTimerPeriodInTicks),
xTimeNow,
xTimeNow,
);
}
x if x == tmrCOMMAND_DELETE => {
#[cfg(any(feature = "alloc", feature = "heap-4", feature = "heap-5"))]
{
if ((*pxTimer).ucStatus & tmrSTATUS_IS_STATICALLY_ALLOCATED) == 0 {
vPortFree(pxTimer as *mut c_void);
} else {
(*pxTimer).ucStatus &= !tmrSTATUS_IS_ACTIVE;
}
}
#[cfg(not(any(
feature = "alloc",
feature = "heap-4",
feature = "heap-5"
)))]
{
(*pxTimer).ucStatus &= !tmrSTATUS_IS_ACTIVE;
}
}
_ => {
}
}
}
}
}
}
}
#[inline(always)]
pub fn xTimerStart(xTimer: TimerHandle_t, xTicksToWait: TickType_t) -> BaseType_t {
xTimerGenericCommand(
xTimer,
tmrCOMMAND_START,
xTaskGetTickCount(),
ptr::null_mut(),
xTicksToWait,
)
}
#[inline(always)]
pub fn xTimerStop(xTimer: TimerHandle_t, xTicksToWait: TickType_t) -> BaseType_t {
xTimerGenericCommand(xTimer, tmrCOMMAND_STOP, 0, ptr::null_mut(), xTicksToWait)
}
#[inline(always)]
pub fn xTimerChangePeriod(
xTimer: TimerHandle_t,
xNewPeriod: TickType_t,
xTicksToWait: TickType_t,
) -> BaseType_t {
xTimerGenericCommand(
xTimer,
tmrCOMMAND_CHANGE_PERIOD,
xNewPeriod,
ptr::null_mut(),
xTicksToWait,
)
}
#[inline(always)]
pub fn xTimerDelete(xTimer: TimerHandle_t, xTicksToWait: TickType_t) -> BaseType_t {
xTimerGenericCommand(xTimer, tmrCOMMAND_DELETE, 0, ptr::null_mut(), xTicksToWait)
}
#[inline(always)]
pub fn xTimerReset(xTimer: TimerHandle_t, xTicksToWait: TickType_t) -> BaseType_t {
xTimerGenericCommand(
xTimer,
tmrCOMMAND_RESET,
xTaskGetTickCount(),
ptr::null_mut(),
xTicksToWait,
)
}
#[inline(always)]
pub fn xTimerStartFromISR(
xTimer: TimerHandle_t,
pxHigherPriorityTaskWoken: *mut BaseType_t,
) -> BaseType_t {
xTimerGenericCommand(
xTimer,
tmrCOMMAND_START_FROM_ISR,
xTaskGetTickCountFromISR(),
pxHigherPriorityTaskWoken,
0,
)
}
#[inline(always)]
pub fn xTimerStopFromISR(
xTimer: TimerHandle_t,
pxHigherPriorityTaskWoken: *mut BaseType_t,
) -> BaseType_t {
xTimerGenericCommand(
xTimer,
tmrCOMMAND_STOP_FROM_ISR,
0,
pxHigherPriorityTaskWoken,
0,
)
}
#[inline(always)]
pub fn xTimerChangePeriodFromISR(
xTimer: TimerHandle_t,
xNewPeriod: TickType_t,
pxHigherPriorityTaskWoken: *mut BaseType_t,
) -> BaseType_t {
xTimerGenericCommand(
xTimer,
tmrCOMMAND_CHANGE_PERIOD_FROM_ISR,
xNewPeriod,
pxHigherPriorityTaskWoken,
0,
)
}
#[inline(always)]
pub fn xTimerResetFromISR(
xTimer: TimerHandle_t,
pxHigherPriorityTaskWoken: *mut BaseType_t,
) -> BaseType_t {
xTimerGenericCommand(
xTimer,
tmrCOMMAND_RESET_FROM_ISR,
xTaskGetTickCountFromISR(),
pxHigherPriorityTaskWoken,
0,
)
}