#![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;
#[cfg(not(feature = "tick-64bit"))]
use core::sync::atomic::AtomicU32;
#[cfg(feature = "tick-64bit")]
use core::sync::atomic::AtomicU64;
use core::sync::atomic::Ordering;
use crate::config::*;
use crate::kernel::list::*;
use crate::kernel::tasks::*;
#[cfg(any(feature = "alloc", feature = "heap-4", feature = "heap-5"))]
use crate::memory::{pvPortMalloc, vPortFree};
use crate::trace::*;
use crate::types::*;
#[cfg(not(feature = "tick-64bit"))]
pub const eventCLEAR_EVENTS_ON_EXIT_BIT: EventBits_t = 0x0100_0000;
#[cfg(feature = "tick-64bit")]
pub const eventCLEAR_EVENTS_ON_EXIT_BIT: EventBits_t = 0x0100_0000_0000_0000;
#[cfg(not(feature = "tick-64bit"))]
pub const eventUNBLOCKED_DUE_TO_BIT_SET: EventBits_t = 0x0200_0000;
#[cfg(feature = "tick-64bit")]
pub const eventUNBLOCKED_DUE_TO_BIT_SET: EventBits_t = 0x0200_0000_0000_0000;
#[cfg(not(feature = "tick-64bit"))]
pub const eventWAIT_FOR_ALL_BITS: EventBits_t = 0x0400_0000;
#[cfg(feature = "tick-64bit")]
pub const eventWAIT_FOR_ALL_BITS: EventBits_t = 0x0400_0000_0000_0000;
#[cfg(not(feature = "tick-64bit"))]
pub const eventEVENT_BITS_CONTROL_BYTES: EventBits_t = 0xFF00_0000;
#[cfg(feature = "tick-64bit")]
pub const eventEVENT_BITS_CONTROL_BYTES: EventBits_t = 0xFF00_0000_0000_0000;
pub type EventBits_t = TickType_t;
#[cfg(not(feature = "tick-64bit"))]
pub type AtomicEventBits_t = AtomicU32;
#[cfg(feature = "tick-64bit")]
pub type AtomicEventBits_t = AtomicU64;
const _: () =
assert!(core::mem::size_of::<AtomicEventBits_t>() == core::mem::size_of::<EventBits_t>());
const _: () =
assert!(core::mem::align_of::<AtomicEventBits_t>() == core::mem::align_of::<EventBits_t>());
#[repr(C)]
pub struct EventGroupDef_t {
pub uxEventBits: AtomicEventBits_t,
pub xTasksWaitingForBits: List_t,
#[cfg(feature = "trace-facility")]
pub uxEventGroupNumber: UBaseType_t,
#[cfg(any(feature = "alloc", feature = "heap-4", feature = "heap-5"))]
pub ucStaticallyAllocated: u8,
}
pub type EventGroup_t = EventGroupDef_t;
#[repr(C)]
pub struct StaticEventGroup_t {
pub xDummy1: AtomicEventBits_t,
pub xDummy2: StaticList_t,
#[cfg(feature = "trace-facility")]
pub uxDummy3: UBaseType_t,
#[cfg(any(feature = "alloc", feature = "heap-4", feature = "heap-5"))]
pub ucDummy4: u8,
}
impl StaticEventGroup_t {
pub const fn new() -> Self {
StaticEventGroup_t {
xDummy1: AtomicEventBits_t::new(0),
xDummy2: StaticList_t::new(),
#[cfg(feature = "trace-facility")]
uxDummy3: 0,
#[cfg(any(feature = "alloc", feature = "heap-4", feature = "heap-5"))]
ucDummy4: 0,
}
}
}
#[repr(C)]
pub struct StaticList_t {
_data: List_t,
}
impl StaticList_t {
pub const fn new() -> Self {
StaticList_t {
_data: List_t::new(),
}
}
}
const _: () =
assert!(core::mem::size_of::<StaticEventGroup_t>() == core::mem::size_of::<EventGroup_t>());
const _: () =
assert!(core::mem::align_of::<StaticEventGroup_t>() == core::mem::align_of::<EventGroup_t>());
const _: () = assert!(
core::mem::offset_of!(StaticEventGroup_t, xDummy2)
== core::mem::offset_of!(EventGroup_t, xTasksWaitingForBits)
);
#[cfg(feature = "trace-facility")]
const _: () = assert!(
core::mem::offset_of!(StaticEventGroup_t, uxDummy3)
== core::mem::offset_of!(EventGroup_t, uxEventGroupNumber)
);
#[cfg(any(feature = "alloc", feature = "heap-4", feature = "heap-5"))]
const _: () = assert!(
core::mem::offset_of!(StaticEventGroup_t, ucDummy4)
== core::mem::offset_of!(EventGroup_t, ucStaticallyAllocated)
);
#[inline(always)]
fn mtCOVERAGE_TEST_MARKER() {}
#[inline(always)]
unsafe fn prvLoadEventBits(pxEventBits: *const EventGroup_t) -> EventBits_t {
unsafe { (*pxEventBits).uxEventBits.load(Ordering::Relaxed) }
}
#[inline(always)]
unsafe fn prvStoreEventBits(pxEventBits: *mut EventGroup_t, uxBits: EventBits_t) {
unsafe { (*pxEventBits).uxEventBits.store(uxBits, Ordering::Relaxed) };
}
#[cfg(any(feature = "alloc", feature = "heap-4", feature = "heap-5"))]
pub unsafe fn xEventGroupCreate() -> EventGroupHandle_t {
traceENTER_xEventGroupCreate();
let pxEventBits: *mut EventGroup_t =
unsafe { pvPortMalloc(core::mem::size_of::<EventGroup_t>()) as *mut EventGroup_t };
if !pxEventBits.is_null() {
unsafe {
ptr::write(
pxEventBits,
EventGroup_t {
uxEventBits: AtomicEventBits_t::new(0),
xTasksWaitingForBits: List_t::new(),
#[cfg(feature = "trace-facility")]
uxEventGroupNumber: 0,
ucStaticallyAllocated: pdFALSE as u8,
},
);
vListInitialise(ptr::addr_of_mut!((*pxEventBits).xTasksWaitingForBits));
}
traceEVENT_GROUP_CREATE(pxEventBits as *mut c_void);
} else {
traceEVENT_GROUP_CREATE_FAILED();
}
traceRETURN_xEventGroupCreate(pxEventBits);
pxEventBits as EventGroupHandle_t
}
pub unsafe fn xEventGroupCreateStatic(
pxEventGroupBuffer: *mut StaticEventGroup_t,
) -> EventGroupHandle_t {
traceENTER_xEventGroupCreateStatic(pxEventGroupBuffer);
if pxEventGroupBuffer.is_null() {
traceEVENT_GROUP_CREATE_FAILED();
traceRETURN_xEventGroupCreateStatic(ptr::null_mut());
return ptr::null_mut();
}
#[cfg(debug_assertions)]
{
let static_size = core::mem::size_of::<StaticEventGroup_t>();
let event_group_size = core::mem::size_of::<EventGroup_t>();
configASSERT(static_size == event_group_size);
}
let pxEventBits = pxEventGroupBuffer as *mut EventGroup_t;
if !pxEventBits.is_null() {
unsafe {
ptr::write(
pxEventBits,
EventGroup_t {
uxEventBits: AtomicEventBits_t::new(0),
xTasksWaitingForBits: List_t::new(),
#[cfg(feature = "trace-facility")]
uxEventGroupNumber: 0,
#[cfg(any(feature = "alloc", feature = "heap-4", feature = "heap-5"))]
ucStaticallyAllocated: pdTRUE as u8,
},
);
vListInitialise(ptr::addr_of_mut!((*pxEventBits).xTasksWaitingForBits));
}
traceEVENT_GROUP_CREATE(pxEventBits as *mut c_void);
} else {
traceEVENT_GROUP_CREATE_FAILED();
}
traceRETURN_xEventGroupCreateStatic(pxEventBits);
pxEventBits as EventGroupHandle_t
}
pub unsafe fn xEventGroupWaitBits(
xEventGroup: EventGroupHandle_t,
uxBitsToWaitFor: EventBits_t,
xClearOnExit: BaseType_t,
xWaitForAllBits: BaseType_t,
mut xTicksToWait: TickType_t,
) -> EventBits_t {
let pxEventBits = xEventGroup as *mut EventGroup_t;
let mut uxReturn: EventBits_t;
let mut uxControlBits: EventBits_t = 0;
let xWaitConditionMet: BaseType_t;
let xAlreadyYielded: BaseType_t;
let mut xTimeoutOccurred: BaseType_t = pdFALSE;
traceENTER_xEventGroupWaitBits(
xEventGroup,
uxBitsToWaitFor,
xClearOnExit,
xWaitForAllBits,
xTicksToWait,
);
configASSERT(!xEventGroup.is_null());
configASSERT((uxBitsToWaitFor & eventEVENT_BITS_CONTROL_BYTES) == 0);
configASSERT(uxBitsToWaitFor != 0);
configASSERT(!(xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED && xTicksToWait != 0));
unsafe { vTaskSuspendAll() };
unsafe {
let uxCurrentEventBits = prvLoadEventBits(pxEventBits);
xWaitConditionMet =
prvTestWaitCondition(uxCurrentEventBits, uxBitsToWaitFor, xWaitForAllBits);
if xWaitConditionMet != pdFALSE {
uxReturn = uxCurrentEventBits;
xTicksToWait = 0;
if xClearOnExit != pdFALSE {
prvStoreEventBits(pxEventBits, uxCurrentEventBits & !uxBitsToWaitFor);
}
} else if xTicksToWait == 0 {
uxReturn = uxCurrentEventBits;
xTimeoutOccurred = pdTRUE;
} else {
if xClearOnExit != pdFALSE {
uxControlBits |= eventCLEAR_EVENTS_ON_EXIT_BIT;
}
if xWaitForAllBits != pdFALSE {
uxControlBits |= eventWAIT_FOR_ALL_BITS;
}
vTaskPlaceOnUnorderedEventList(
ptr::addr_of_mut!((*pxEventBits).xTasksWaitingForBits),
uxBitsToWaitFor | uxControlBits,
xTicksToWait,
);
uxReturn = 0;
traceEVENT_GROUP_WAIT_BITS_BLOCK(
xEventGroup as *mut c_void,
uxBitsToWaitFor as UBaseType_t,
);
}
}
xAlreadyYielded = unsafe { xTaskResumeAll() };
if xTicksToWait != 0 {
if xAlreadyYielded == pdFALSE {
portYIELD_WITHIN_API();
}
uxReturn = uxTaskResetEventItemValue();
if (uxReturn & eventUNBLOCKED_DUE_TO_BIT_SET) == 0 {
taskENTER_CRITICAL();
unsafe {
uxReturn = prvLoadEventBits(pxEventBits);
if prvTestWaitCondition(uxReturn, uxBitsToWaitFor, xWaitForAllBits) != pdFALSE {
if xClearOnExit != pdFALSE {
prvStoreEventBits(pxEventBits, uxReturn & !uxBitsToWaitFor);
}
}
xTimeoutOccurred = pdTRUE;
}
taskEXIT_CRITICAL();
}
uxReturn &= !eventEVENT_BITS_CONTROL_BYTES;
}
traceEVENT_GROUP_WAIT_BITS_END(
xEventGroup as *mut c_void,
uxBitsToWaitFor as UBaseType_t,
xTimeoutOccurred,
);
traceRETURN_xEventGroupWaitBits(uxReturn);
uxReturn
}
pub unsafe fn xEventGroupSync(
xEventGroup: EventGroupHandle_t,
uxBitsToSet: EventBits_t,
uxBitsToWaitFor: EventBits_t,
mut xTicksToWait: TickType_t,
) -> EventBits_t {
let pxEventBits = xEventGroup as *mut EventGroup_t;
let uxOriginalBitValue: EventBits_t;
let mut uxReturn: EventBits_t;
let xAlreadyYielded: BaseType_t;
let mut xTimeoutOccurred: BaseType_t = pdFALSE;
traceENTER_xEventGroupSync(xEventGroup, uxBitsToSet, uxBitsToWaitFor, xTicksToWait);
configASSERT(!xEventGroup.is_null());
configASSERT((uxBitsToSet & eventEVENT_BITS_CONTROL_BYTES) == 0);
configASSERT((uxBitsToWaitFor & eventEVENT_BITS_CONTROL_BYTES) == 0);
configASSERT(uxBitsToWaitFor != 0);
configASSERT(!(xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED && xTicksToWait != 0));
unsafe { vTaskSuspendAll() };
unsafe {
uxOriginalBitValue = prvLoadEventBits(pxEventBits);
let _ = xEventGroupSetBits(xEventGroup, uxBitsToSet);
if ((uxOriginalBitValue | uxBitsToSet) & uxBitsToWaitFor) == uxBitsToWaitFor {
uxReturn = uxOriginalBitValue | uxBitsToSet;
let uxCurrentEventBits = prvLoadEventBits(pxEventBits);
prvStoreEventBits(pxEventBits, uxCurrentEventBits & !uxBitsToWaitFor);
xTicksToWait = 0;
} else {
if xTicksToWait != 0 {
traceEVENT_GROUP_SYNC_BLOCK(
xEventGroup as *mut c_void,
uxBitsToSet as UBaseType_t,
uxBitsToWaitFor as UBaseType_t,
);
vTaskPlaceOnUnorderedEventList(
ptr::addr_of_mut!((*pxEventBits).xTasksWaitingForBits),
uxBitsToWaitFor | eventCLEAR_EVENTS_ON_EXIT_BIT | eventWAIT_FOR_ALL_BITS,
xTicksToWait,
);
uxReturn = 0;
} else {
uxReturn = prvLoadEventBits(pxEventBits);
xTimeoutOccurred = pdTRUE;
}
}
}
xAlreadyYielded = unsafe { xTaskResumeAll() };
if xTicksToWait != 0 {
if xAlreadyYielded == pdFALSE {
portYIELD_WITHIN_API();
}
uxReturn = uxTaskResetEventItemValue();
if (uxReturn & eventUNBLOCKED_DUE_TO_BIT_SET) == 0 {
taskENTER_CRITICAL();
unsafe {
uxReturn = prvLoadEventBits(pxEventBits);
if (uxReturn & uxBitsToWaitFor) == uxBitsToWaitFor {
prvStoreEventBits(pxEventBits, uxReturn & !uxBitsToWaitFor);
}
}
taskEXIT_CRITICAL();
xTimeoutOccurred = pdTRUE;
}
uxReturn &= !eventEVENT_BITS_CONTROL_BYTES;
}
traceEVENT_GROUP_SYNC_END(
xEventGroup as *mut c_void,
uxBitsToSet as UBaseType_t,
uxBitsToWaitFor as UBaseType_t,
xTimeoutOccurred,
);
traceRETURN_xEventGroupSync(uxReturn);
uxReturn
}
#[allow(unused_assignments)] pub unsafe fn xEventGroupSetBits(
xEventGroup: EventGroupHandle_t,
uxBitsToSet: EventBits_t,
) -> EventBits_t {
let pxEventBits = xEventGroup as *mut EventGroup_t;
let mut uxBitsToClear: EventBits_t = 0;
let mut xMatchFound: BaseType_t = pdFALSE;
let uxReturnBits: EventBits_t;
traceENTER_xEventGroupSetBits(xEventGroup, uxBitsToSet);
configASSERT(!xEventGroup.is_null());
configASSERT((uxBitsToSet & eventEVENT_BITS_CONTROL_BYTES) == 0);
unsafe {
let pxList = ptr::addr_of!((*pxEventBits).xTasksWaitingForBits);
let pxListEnd = listGET_END_MARKER(pxList);
vTaskSuspendAll();
traceEVENT_GROUP_SET_BITS(xEventGroup as *mut c_void, uxBitsToSet as UBaseType_t);
let mut pxListItem = listGET_HEAD_ENTRY(pxList);
let mut uxCurrentEventBits = prvLoadEventBits(pxEventBits);
uxCurrentEventBits |= uxBitsToSet;
prvStoreEventBits(pxEventBits, uxCurrentEventBits);
while pxListItem != pxListEnd as *mut ListItem_t {
let pxNext = listGET_NEXT(pxListItem);
let mut uxBitsWaitedFor = listGET_LIST_ITEM_VALUE(pxListItem);
xMatchFound = pdFALSE;
let uxControlBits = uxBitsWaitedFor & eventEVENT_BITS_CONTROL_BYTES;
uxBitsWaitedFor &= !eventEVENT_BITS_CONTROL_BYTES;
if (uxControlBits & eventWAIT_FOR_ALL_BITS) == 0 {
if (uxBitsWaitedFor & uxCurrentEventBits) != 0 {
xMatchFound = pdTRUE;
}
} else if (uxBitsWaitedFor & uxCurrentEventBits) == uxBitsWaitedFor {
xMatchFound = pdTRUE;
}
if xMatchFound != pdFALSE {
if (uxControlBits & eventCLEAR_EVENTS_ON_EXIT_BIT) != 0 {
uxBitsToClear |= uxBitsWaitedFor;
}
let _ = xTaskRemoveFromUnorderedEventList(
pxListItem,
uxCurrentEventBits | eventUNBLOCKED_DUE_TO_BIT_SET,
);
}
pxListItem = pxNext;
}
uxCurrentEventBits &= !uxBitsToClear;
prvStoreEventBits(pxEventBits, uxCurrentEventBits);
uxReturnBits = uxCurrentEventBits;
}
let _ = unsafe { xTaskResumeAll() };
traceRETURN_xEventGroupSetBits(uxReturnBits);
uxReturnBits
}
pub unsafe fn xEventGroupClearBits(
xEventGroup: EventGroupHandle_t,
uxBitsToClear: EventBits_t,
) -> EventBits_t {
let pxEventBits = xEventGroup as *mut EventGroup_t;
let uxReturn: EventBits_t;
traceENTER_xEventGroupClearBits(xEventGroup, uxBitsToClear);
configASSERT(!xEventGroup.is_null());
configASSERT((uxBitsToClear & eventEVENT_BITS_CONTROL_BYTES) == 0);
taskENTER_CRITICAL();
unsafe {
traceEVENT_GROUP_CLEAR_BITS(xEventGroup as *mut c_void, uxBitsToClear as UBaseType_t);
uxReturn = prvLoadEventBits(pxEventBits);
prvStoreEventBits(pxEventBits, uxReturn & !uxBitsToClear);
}
taskEXIT_CRITICAL();
traceRETURN_xEventGroupClearBits(uxReturn);
uxReturn
}
pub unsafe fn xEventGroupGetBitsFromISR(xEventGroup: EventGroupHandle_t) -> EventBits_t {
let pxEventBits = xEventGroup as *const EventGroup_t;
let uxReturn: EventBits_t;
traceENTER_xEventGroupGetBitsFromISR(xEventGroup);
configASSERT(!xEventGroup.is_null());
unsafe {
let uxSavedInterruptStatus = taskENTER_CRITICAL_FROM_ISR();
uxReturn = prvLoadEventBits(pxEventBits);
taskEXIT_CRITICAL_FROM_ISR(uxSavedInterruptStatus);
}
traceRETURN_xEventGroupGetBitsFromISR(uxReturn);
uxReturn
}
#[inline(always)]
pub unsafe fn xEventGroupGetBits(xEventGroup: EventGroupHandle_t) -> EventBits_t {
xEventGroupClearBits(xEventGroup, 0)
}
pub unsafe fn vEventGroupDelete(xEventGroup: EventGroupHandle_t) {
let pxEventBits = xEventGroup as *mut EventGroup_t;
traceENTER_vEventGroupDelete(xEventGroup);
configASSERT(!pxEventBits.is_null());
unsafe {
let pxTasksWaitingForBits = ptr::addr_of!((*pxEventBits).xTasksWaitingForBits);
vTaskSuspendAll();
traceEVENT_GROUP_DELETE(xEventGroup as *mut c_void);
while listCURRENT_LIST_LENGTH(pxTasksWaitingForBits) > 0 {
configASSERT(
(*pxTasksWaitingForBits).xListEnd.pxNext
!= ptr::addr_of!((*pxTasksWaitingForBits).xListEnd).cast_mut(),
);
let _ = xTaskRemoveFromUnorderedEventList(
(*pxTasksWaitingForBits).xListEnd.pxNext,
eventUNBLOCKED_DUE_TO_BIT_SET,
);
}
}
let _ = unsafe { xTaskResumeAll() };
#[cfg(any(feature = "alloc", feature = "heap-4", feature = "heap-5"))]
unsafe {
if (*pxEventBits).ucStaticallyAllocated == pdFALSE as u8 {
vPortFree(pxEventBits as *mut c_void);
}
}
traceRETURN_vEventGroupDelete();
}
pub unsafe fn xEventGroupGetStaticBuffer(
xEventGroup: EventGroupHandle_t,
ppxEventGroupBuffer: *mut *mut StaticEventGroup_t,
) -> BaseType_t {
let pxEventBits = xEventGroup as *mut EventGroup_t;
let xReturn: BaseType_t;
traceENTER_xEventGroupGetStaticBuffer(xEventGroup, ppxEventGroupBuffer);
configASSERT(!pxEventBits.is_null());
configASSERT(!ppxEventGroupBuffer.is_null());
#[cfg(any(feature = "alloc", feature = "heap-4", feature = "heap-5"))]
{
xReturn = unsafe {
if (*pxEventBits).ucStaticallyAllocated == pdTRUE as u8 {
*ppxEventGroupBuffer = pxEventBits as *mut StaticEventGroup_t;
pdTRUE
} else {
pdFALSE
}
};
}
#[cfg(not(any(feature = "alloc", feature = "heap-4", feature = "heap-5")))]
{
xReturn = unsafe {
*ppxEventGroupBuffer = pxEventBits as *mut StaticEventGroup_t;
pdTRUE
};
}
traceRETURN_xEventGroupGetStaticBuffer(xReturn);
xReturn
}
#[cfg(all(feature = "pend-function-call", feature = "timers"))]
pub unsafe extern "C" fn vEventGroupSetBitsCallback(
pvEventGroup: *mut c_void,
ulBitsToSet: crate::kernel::timers::PendedFunctionParameter_t,
) {
traceENTER_vEventGroupSetBitsCallback(pvEventGroup, ulBitsToSet);
let _ = xEventGroupSetBits(
pvEventGroup as EventGroupHandle_t,
ulBitsToSet as EventBits_t,
);
traceRETURN_vEventGroupSetBitsCallback();
}
#[cfg(all(feature = "pend-function-call", feature = "timers"))]
pub unsafe extern "C" fn vEventGroupClearBitsCallback(
pvEventGroup: *mut c_void,
ulBitsToClear: crate::kernel::timers::PendedFunctionParameter_t,
) {
traceENTER_vEventGroupClearBitsCallback(pvEventGroup, ulBitsToClear);
let _ = xEventGroupClearBits(
pvEventGroup as EventGroupHandle_t,
ulBitsToClear as EventBits_t,
);
traceRETURN_vEventGroupClearBitsCallback();
}
#[cfg(all(feature = "pend-function-call", feature = "timers"))]
pub unsafe fn xEventGroupSetBitsFromISR(
xEventGroup: EventGroupHandle_t,
uxBitsToSet: EventBits_t,
pxHigherPriorityTaskWoken: *mut BaseType_t,
) -> BaseType_t {
use crate::kernel::timers::xTimerPendFunctionCallFromISR;
traceENTER_xEventGroupSetBitsFromISR(xEventGroup, uxBitsToSet, pxHigherPriorityTaskWoken);
if xEventGroup.is_null() || (uxBitsToSet & eventEVENT_BITS_CONTROL_BYTES) != 0 {
traceRETURN_xEventGroupSetBitsFromISR(pdFAIL);
return pdFAIL;
}
traceEVENT_GROUP_SET_BITS_FROM_ISR(xEventGroup as *mut c_void, uxBitsToSet as UBaseType_t);
let xReturn = unsafe {
xTimerPendFunctionCallFromISR(
vEventGroupSetBitsCallback,
xEventGroup as *mut c_void,
uxBitsToSet as crate::kernel::timers::PendedFunctionParameter_t,
pxHigherPriorityTaskWoken,
)
};
traceRETURN_xEventGroupSetBitsFromISR(xReturn);
xReturn
}
#[cfg(all(feature = "pend-function-call", feature = "timers"))]
pub unsafe fn xEventGroupClearBitsFromISR(
xEventGroup: EventGroupHandle_t,
uxBitsToClear: EventBits_t,
) -> BaseType_t {
use crate::kernel::timers::xTimerPendFunctionCallFromISR;
traceENTER_xEventGroupClearBitsFromISR(xEventGroup, uxBitsToClear);
if xEventGroup.is_null() || (uxBitsToClear & eventEVENT_BITS_CONTROL_BYTES) != 0 {
traceRETURN_xEventGroupClearBitsFromISR(pdFAIL);
return pdFAIL;
}
traceEVENT_GROUP_CLEAR_BITS_FROM_ISR(xEventGroup as *mut c_void, uxBitsToClear as UBaseType_t);
let xReturn = unsafe {
xTimerPendFunctionCallFromISR(
vEventGroupClearBitsCallback,
xEventGroup as *mut c_void,
uxBitsToClear as crate::kernel::timers::PendedFunctionParameter_t,
ptr::null_mut(),
)
};
traceRETURN_xEventGroupClearBitsFromISR(xReturn);
xReturn
}
#[cfg(feature = "trace-facility")]
pub unsafe fn uxEventGroupGetNumber(xEventGroup: EventGroupHandle_t) -> UBaseType_t {
let xReturn: UBaseType_t;
traceENTER_uxEventGroupGetNumber(xEventGroup);
if xEventGroup.is_null() {
xReturn = 0;
} else {
let pxEventBits = xEventGroup as *const EventGroup_t;
xReturn = unsafe { (*pxEventBits).uxEventGroupNumber };
}
traceRETURN_uxEventGroupGetNumber(xReturn);
xReturn
}
#[cfg(feature = "trace-facility")]
pub unsafe fn vEventGroupSetNumber(
xEventGroup: EventGroupHandle_t,
uxEventGroupNumber: UBaseType_t,
) {
traceENTER_vEventGroupSetNumber(xEventGroup, uxEventGroupNumber);
configASSERT(!xEventGroup.is_null());
unsafe {
(*(xEventGroup as *mut EventGroup_t)).uxEventGroupNumber = uxEventGroupNumber;
}
traceRETURN_vEventGroupSetNumber();
}
fn prvTestWaitCondition(
uxCurrentEventBits: EventBits_t,
uxBitsToWaitFor: EventBits_t,
xWaitForAllBits: BaseType_t,
) -> BaseType_t {
let mut xWaitConditionMet: BaseType_t = pdFALSE;
if xWaitForAllBits == pdFALSE {
if (uxCurrentEventBits & uxBitsToWaitFor) != 0 {
xWaitConditionMet = pdTRUE;
}
} else {
if (uxCurrentEventBits & uxBitsToWaitFor) == uxBitsToWaitFor {
xWaitConditionMet = pdTRUE;
}
}
xWaitConditionMet
}
#[inline(always)]
fn traceENTER_xEventGroupCreate() {}
#[inline(always)]
fn traceRETURN_xEventGroupCreate(_pxEventBits: *mut EventGroup_t) {}
#[inline(always)]
fn traceENTER_xEventGroupCreateStatic(_pxEventGroupBuffer: *mut StaticEventGroup_t) {}
#[inline(always)]
fn traceRETURN_xEventGroupCreateStatic(_pxEventBits: *mut EventGroup_t) {}
#[inline(always)]
fn traceENTER_xEventGroupWaitBits(
_xEventGroup: EventGroupHandle_t,
_uxBitsToWaitFor: EventBits_t,
_xClearOnExit: BaseType_t,
_xWaitForAllBits: BaseType_t,
_xTicksToWait: TickType_t,
) {
}
#[inline(always)]
fn traceRETURN_xEventGroupWaitBits(_uxReturn: EventBits_t) {}
#[inline(always)]
fn traceENTER_xEventGroupSync(
_xEventGroup: EventGroupHandle_t,
_uxBitsToSet: EventBits_t,
_uxBitsToWaitFor: EventBits_t,
_xTicksToWait: TickType_t,
) {
}
#[inline(always)]
fn traceRETURN_xEventGroupSync(_uxReturn: EventBits_t) {}
#[inline(always)]
fn traceENTER_xEventGroupSetBits(_xEventGroup: EventGroupHandle_t, _uxBitsToSet: EventBits_t) {}
#[inline(always)]
fn traceRETURN_xEventGroupSetBits(_uxReturnBits: EventBits_t) {}
#[inline(always)]
fn traceENTER_xEventGroupClearBits(_xEventGroup: EventGroupHandle_t, _uxBitsToClear: EventBits_t) {}
#[inline(always)]
fn traceRETURN_xEventGroupClearBits(_uxReturn: EventBits_t) {}
#[inline(always)]
fn traceENTER_xEventGroupGetBitsFromISR(_xEventGroup: EventGroupHandle_t) {}
#[inline(always)]
fn traceRETURN_xEventGroupGetBitsFromISR(_uxReturn: EventBits_t) {}
#[inline(always)]
fn traceENTER_vEventGroupDelete(_xEventGroup: EventGroupHandle_t) {}
#[inline(always)]
fn traceRETURN_vEventGroupDelete() {}
#[inline(always)]
fn traceENTER_xEventGroupGetStaticBuffer(
_xEventGroup: EventGroupHandle_t,
_ppxEventGroupBuffer: *mut *mut StaticEventGroup_t,
) {
}
#[inline(always)]
fn traceRETURN_xEventGroupGetStaticBuffer(_xReturn: BaseType_t) {}
#[inline(always)]
#[cfg(all(feature = "pend-function-call", feature = "timers"))]
fn traceENTER_vEventGroupSetBitsCallback(
_pvEventGroup: *mut c_void,
_ulBitsToSet: crate::kernel::timers::PendedFunctionParameter_t,
) {
}
#[inline(always)]
#[cfg(all(feature = "pend-function-call", feature = "timers"))]
fn traceRETURN_vEventGroupSetBitsCallback() {}
#[inline(always)]
#[cfg(all(feature = "pend-function-call", feature = "timers"))]
fn traceENTER_vEventGroupClearBitsCallback(
_pvEventGroup: *mut c_void,
_ulBitsToClear: crate::kernel::timers::PendedFunctionParameter_t,
) {
}
#[inline(always)]
#[cfg(all(feature = "pend-function-call", feature = "timers"))]
fn traceRETURN_vEventGroupClearBitsCallback() {}
#[cfg(all(feature = "pend-function-call", feature = "timers"))]
#[inline(always)]
fn traceENTER_xEventGroupSetBitsFromISR(
_xEventGroup: EventGroupHandle_t,
_uxBitsToSet: EventBits_t,
_pxHigherPriorityTaskWoken: *mut BaseType_t,
) {
}
#[cfg(all(feature = "pend-function-call", feature = "timers"))]
#[inline(always)]
fn traceRETURN_xEventGroupSetBitsFromISR(_xReturn: BaseType_t) {}
#[cfg(all(feature = "pend-function-call", feature = "timers"))]
#[inline(always)]
fn traceENTER_xEventGroupClearBitsFromISR(
_xEventGroup: EventGroupHandle_t,
_uxBitsToClear: EventBits_t,
) {
}
#[cfg(all(feature = "pend-function-call", feature = "timers"))]
#[inline(always)]
fn traceRETURN_xEventGroupClearBitsFromISR(_xReturn: BaseType_t) {}
#[cfg(feature = "trace-facility")]
#[inline(always)]
fn traceENTER_uxEventGroupGetNumber(_xEventGroup: EventGroupHandle_t) {}
#[cfg(feature = "trace-facility")]
#[inline(always)]
fn traceRETURN_uxEventGroupGetNumber(_xReturn: UBaseType_t) {}
#[cfg(feature = "trace-facility")]
#[inline(always)]
fn traceENTER_vEventGroupSetNumber(
_xEventGroup: EventGroupHandle_t,
_uxEventGroupNumber: UBaseType_t,
) {
}
#[cfg(feature = "trace-facility")]
#[inline(always)]
fn traceRETURN_vEventGroupSetNumber() {}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn static_event_group_storage_matches_internal_layout() {
assert_eq!(
core::mem::size_of::<AtomicEventBits_t>(),
core::mem::size_of::<EventBits_t>()
);
assert_eq!(
core::mem::align_of::<AtomicEventBits_t>(),
core::mem::align_of::<EventBits_t>()
);
assert_eq!(
core::mem::size_of::<StaticEventGroup_t>(),
core::mem::size_of::<EventGroup_t>()
);
assert_eq!(
core::mem::align_of::<StaticEventGroup_t>(),
core::mem::align_of::<EventGroup_t>()
);
}
#[cfg(feature = "port-test")]
#[test]
fn task_side_stores_and_isr_reads_share_one_atomic_event_word() {
use core::sync::atomic::AtomicBool;
const FIRST: EventBits_t = 0x0055_5555;
const SECOND: EventBits_t = 0x00aa_aaaa;
#[cfg(miri)]
const TRANSFERS: usize = 500;
#[cfg(not(miri))]
const TRANSFERS: usize = 20_000;
struct SendHandle(*mut EventGroup_t);
impl SendHandle {
fn into_raw(self) -> *mut EventGroup_t {
self.0
}
}
unsafe impl Send for SendHandle {}
crate::port::test_port_reset();
let storage = std::boxed::Box::leak(std::boxed::Box::new(StaticEventGroup_t::new()));
let event_group = unsafe { xEventGroupCreateStatic(storage) };
assert!(!event_group.is_null());
unsafe { prvStoreEventBits(event_group.cast(), FIRST) };
let writer_handle = SendHandle(event_group.cast());
let start = AtomicBool::new(false);
crate::port::test_port_set_inside_interrupt(true);
std::thread::scope(|scope| {
let start_ref = &start;
scope.spawn(move || {
while !start_ref.load(Ordering::Acquire) {
core::hint::spin_loop();
}
let event_group = writer_handle.into_raw();
for index in 0..TRANSFERS {
let bits = if index & 1 == 0 { SECOND } else { FIRST };
unsafe { prvStoreEventBits(event_group, bits) };
}
});
start.store(true, Ordering::Release);
for _ in 0..TRANSFERS {
let observed = unsafe { xEventGroupGetBitsFromISR(event_group) };
assert!(observed == FIRST || observed == SECOND);
}
});
crate::port::test_port_set_inside_interrupt(false);
}
#[cfg(all(
feature = "port-test",
feature = "pend-function-call",
feature = "timers"
))]
#[test]
fn deferred_callbacks_preserve_all_usable_32_bit_event_bits() {
let mut storage = StaticEventGroup_t::new();
unsafe {
let event_group = xEventGroupCreateStatic(&mut storage);
assert!(!event_group.is_null());
let highest_usable_bit = 0x0080_0000 as EventBits_t;
vEventGroupSetBitsCallback(
event_group,
highest_usable_bit as crate::kernel::timers::PendedFunctionParameter_t,
);
assert_eq!(xEventGroupGetBits(event_group), highest_usable_bit);
vEventGroupClearBitsCallback(
event_group,
highest_usable_bit as crate::kernel::timers::PendedFunctionParameter_t,
);
assert_eq!(xEventGroupGetBits(event_group), 0);
}
}
#[cfg(all(
feature = "port-test",
feature = "pend-function-call",
feature = "timers"
))]
#[test]
fn from_isr_calls_reject_reserved_control_bits_before_queueing() {
crate::port::test_port_reset();
let mut storage = StaticEventGroup_t::new();
let event_group = unsafe { xEventGroupCreateStatic(&mut storage) };
assert!(!event_group.is_null());
crate::port::test_port_set_inside_interrupt(true);
unsafe {
assert_eq!(
xEventGroupSetBitsFromISR(
event_group,
eventEVENT_BITS_CONTROL_BYTES,
ptr::null_mut(),
),
pdFAIL,
);
assert_eq!(
xEventGroupClearBitsFromISR(event_group, eventEVENT_BITS_CONTROL_BYTES),
pdFAIL,
);
}
crate::port::test_port_set_inside_interrupt(false);
}
}