Skip to content

Commit

Permalink
Merge pull request BlackCAT-CubeSat#26 from zec/0809-misc
Browse files Browse the repository at this point in the history
Mixture of improvements and fixes
  • Loading branch information
dmopalmer authored Aug 9, 2023
2 parents ec78438 + 76ac9fc commit 873e893
Show file tree
Hide file tree
Showing 5 changed files with 216 additions and 11 deletions.
3 changes: 2 additions & 1 deletion cfs-sys/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,9 @@ fn main() {
let api_header = pb(&[&in_dir, "cfs-api.h"]).to_string_unwrap();
let shims_header = pb(&[&in_dir, "cfs-shims.h"]).to_string_unwrap();
let out_file = pb(&[&out_dir, "cfs-all.rs"]).to_string_unwrap();
let shims_c = pb(&[&out_dir, "cfs-shims.c"]).to_string_unwrap();

for f in [&api_header, &shims_header] {
for f in [&api_header, &shims_header, &shims_c] {
println!("cargo:rerun-if-changed={}", f);
}

Expand Down
10 changes: 9 additions & 1 deletion cfs-sys/cfs-api.h
Original file line number Diff line number Diff line change
Expand Up @@ -181,13 +181,21 @@ S(CFE_TIME_BAD_ARGUMENT)

#define X(IDENT, TYPE) const TYPE X_ ## IDENT = IDENT;

X(CFE_ES_TASK_STACK_ALLOCATE, CFE_ES_StackPointer_t)
X(CFE_ES_APPID_UNDEFINED, CFE_ES_AppId_t)
X(CFE_ES_CDS_BAD_HANDLE, CFE_ES_CDSHandle_t)
X(CFE_ES_COUNTERID_UNDEFINED, CFE_ES_CounterId_t)
X(CFE_ES_LIBID_UNDEFINED, CFE_ES_LibId_t)
X(CFE_ES_MEMHANDLE_UNDEFINED, CFE_ES_MemHandle_t)
X(CFE_ES_TASKID_UNDEFINED, CFE_ES_TaskId_t)
X(CFE_RESOURCEID_RESERVED, CFE_ResourceId_t)
X(CFE_RESOURCEID_UNDEFINED, CFE_ResourceId_t)
X(CFE_SB_MSGID_RESERVED, CFE_SB_MsgId_t)
X(CFE_SB_INVALID_MSG_ID, CFE_SB_MsgId_t)
X(CFE_TBL_BAD_TABLE_HANDLE, CFE_TBL_Handle_t)
X(OS_OBJECT_ID_UNDEFINED, osal_id_t)

/* see cfs-shims.c */
extern CFE_ES_StackPointer_t X_CFE_ES_TASK_STACK_ALLOCATE;

const uint8 X_CFE_SB_DEFAULT_QOS_PRIORITY = CFE_SB_DEFAULT_QOS.Priority;
const uint8 X_CFE_SB_DEFAULT_QOS_RELIABILITY = CFE_SB_DEFAULT_QOS.Reliability;
3 changes: 3 additions & 0 deletions cfs-sys/cfs-shims.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,6 @@
}

#include "cfs-shims.h"

/* Bindgen *really* doesn't want to handle pointer constants. This is a workaround for that. */
CFE_ES_StackPointer_t X_CFE_ES_TASK_STACK_ALLOCATE = CFE_ES_TASK_STACK_ALLOCATE;
197 changes: 195 additions & 2 deletions n2o4/src/cfe/es.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
//! Executive Services system.

use super::{ResourceId, Status};
use crate::utils::CStrBuf;
use cfs_sys::*;
use core::ffi::{c_char, c_void, CStr};
use core::marker::PhantomData;
Expand Down Expand Up @@ -443,7 +444,7 @@ extern "C" fn task_main_func<F: FnOnce() + Send + Sized + 'static>() {
/// Wraps `CFE_ES_CreateChildTask` (and `CFE_ES_ExitChildTask` in the child task).
#[doc(alias("CFE_ES_CreateChildTask", "CFE_ES_ExitChildTask"))]
#[inline]
pub fn create_child_task<F: FnOnce() + Send + Sized + 'static, S: AsRef<CStr>>(
pub fn create_child_task<F: FnOnce() + Send + Sized + 'static, S: AsRef<CStr> + ?Sized>(
function: F,
task_name: &S,
stack_size: usize,
Expand Down Expand Up @@ -582,7 +583,7 @@ get_shared_sem!(child_signal_sem, crate::osal::sync::BinSem, CHILD_SIGNAL_SEM_ID
/// Wraps `CFE_ES_CreateChildTask`.
#[doc(alias = "CFE_ES_CreateChildTask")]
#[inline]
pub fn create_child_task_c<S: AsRef<CStr>>(
pub fn create_child_task_c<S: AsRef<CStr> + ?Sized>(
function: unsafe extern "C" fn(),
task_name: &S,
stack_size: usize,
Expand Down Expand Up @@ -646,3 +647,195 @@ pub fn increment_task_counter() {
CFE_ES_IncrementTaskCounter();
}
}

/// A handle to a block in the Critical Data Store (CDS).
///
/// Wraps `CFE_ES_CDSHandle_t`.
#[doc(alias = "CFE_ES_CDSHandle_t")]
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub struct CdsHandle<T: Copy + Sized + 'static> {
handle: CFE_ES_CDSHandle_t,
_pd: PhantomData<T>,
}

/// A buffer size that is longer than any CDS block name.
const CDS_NAME_BUF_LEN: usize = (CFE_MISSION_ES_CDS_MAX_NAME_LENGTH as usize) + 1;

impl<T: Copy + Sized + 'static> CdsHandle<T> {
/// The backend of [`register`](CdsHandle::register),
/// [`register_with`](CdsHandle::register_with),
/// and [`register_with_default`](CdsHandle::register_with_default).
#[inline]
fn register_gen<S: AsRef<CStr> + ?Sized, F: FnOnce() -> T>(
name: &S,
initial_closure: F,
) -> Result<(Self, CdsRegisterResult), Status> {
let mut cds_handle: CFE_ES_CDSHandle_t = X_CFE_ES_CDS_BAD_HANDLE;
let s: Status = unsafe {
CFE_ES_RegisterCDS(&mut cds_handle, core::mem::size_of::<T>(), name.as_ref().as_ptr())
}
.into();

// make sure a valid handle was stored in cds_handle:
if cds_handle == X_CFE_ES_CDS_BAD_HANDLE {
return Err(s);
}

match s {
Status::ES_CDS_ALREADY_EXISTS => Ok((
Self {
handle: cds_handle,
_pd: PhantomData,
},
CdsRegisterResult::AlreadyExists,
)),
Status::SUCCESS => {
let initial_value = initial_closure();
let s2: Status = unsafe {
CFE_ES_CopyToCDS(cds_handle, &initial_value as *const T as *const c_void)
}
.into();
s2.as_result(|| ())?;
Ok((
Self {
handle: cds_handle,
_pd: PhantomData,
},
CdsRegisterResult::Created,
))
}
_ => Err(s),
}
}

/// Requests that a block of memory be allocated from the CDS, where the block has name `name` and is sized to hold a `T`,
/// or retrieves the block if a block with the correct name and size already exists.
///
/// On success, a handle for the block is returned.
/// If the block is created by this call, it is initialized with `initial_value`.
///
/// Wraps `CFE_ES_RegisterCDS` (and `CFE_ES_CopyToCDS` if the block doesn't already exist).
///
/// # Safety
///
/// This function does not check if, when the CDS block already exists, its contents represent a valid `T`.
/// The programmer and/or system operator must ensure that by, e.g., either making sure all versions of
/// the calling application use the same `#[repr(C)]` type, never rebuilding the application and hot-upgrading
/// it in a running cFS system, etc.
#[doc(alias = "CFE_ES_RegisterCDS")]
#[inline]
pub unsafe fn register<S: AsRef<CStr> + ?Sized>(
name: &S,
initial_value: T,
) -> Result<(Self, CdsRegisterResult), Status> {
Self::register_gen(name, || initial_value)
}

/// Requests that a block of memory be allocated from the CDS, where the block has name `name` and is sized to hold a `T`,
/// or retrieves the block if a block with the correct name and size already exists.
///
/// On success, a handle for the block is returned.
/// If the block is created by this call, it is initialized with the result of calling `initial_value_fn`.
///
/// Wraps `CFE_ES_RegisterCDS` (and `CFE_ES_CopyToCDS` if the block doesn't already exist).
///
/// # Safety
///
/// This function does not check if, when the CDS block already exists, its contents represent a valid `T`.
/// The programmer and/or system operator must ensure that by, e.g., either making sure all versions of
/// the calling application use the same `#[repr(C)]` type, never rebuilding the application and hot-upgrading
/// it in a running cFS system, etc.
///
/// `initial_value_fn` must not panic; otherwise the CDS block will not be properly initialized with a valid value.
#[doc(alias = "CFE_ES_RegisterCDS")]
#[inline]
pub unsafe fn register_with<S: AsRef<CStr> + ?Sized, F: FnOnce() -> T>(
name: &S,
initial_value_fn: F,
) -> Result<(Self, CdsRegisterResult), Status> {
Self::register_gen(name, initial_value_fn)
}

/// Requests that a block of memory be allocated from the CDS, where the block has name `name` and is sized to hold a `T`,
/// or retrieves the block if a block with the correct name and size already exists.
///
/// On success, a handle for the block is returned.
/// If the block is created by this call, it is initialized with the result of calling [`Default::default`].
///
/// Wraps `CFE_ES_RegisterCDS` (and `CFE_ES_CopyToCDS` if the block doesn't already exist).
///
/// # Safety
///
/// This function does not check if, when the CDS block already exists, its contents represent a valid `T`.
/// The programmer and/or system operator must ensure that by, e.g., either making sure all versions of
/// the calling application use the same `#[repr(C)]` type, never rebuilding the application and hot-upgrading
/// it in a running cFS system, etc.
///
/// `Default::default` must not panic; otherwise the CDS block will not be properly initialized with a valid value.
#[doc(alias = "CFE_ES_RegisterCDS")]
#[inline]
pub unsafe fn register_with_default<S: AsRef<CStr> + ?Sized>(
name: &S,
) -> Result<(Self, CdsRegisterResult), Status>
where
T: Default,
{
Self::register_gen(name, Default::default)
}

/// Retrieves the name of the CDS block.
///
/// Wraps `CFE_ES_GetCDSBlockName`.
#[doc(alias = "CFE_ES_GetCDSBlockName")]
#[inline]
pub fn block_name(&self) -> Result<crate::utils::CStrBuf<CDS_NAME_BUF_LEN>, Status> {
let mut name = [b'\0' as c_char; CDS_NAME_BUF_LEN];

let status: Status =
unsafe { CFE_ES_GetCDSBlockName(name.as_mut_ptr(), self.handle, CDS_NAME_BUF_LEN) }
.into();

status.as_result(|| CStrBuf::new_into(name))
}

/// Copies `data_to_copy` into the CDS block.
///
/// Wraps `CFE_ES_CopyToCDS`.
#[doc(alias = "CFE_ES_CopyToCDS")]
#[inline]
pub fn copy_to_cds(&self, data_to_copy: &T) -> Result<(), Status> {
let status: Status =
unsafe { CFE_ES_CopyToCDS(self.handle, data_to_copy as *const T as *const c_void) }
.into();

status.as_result(|| ())
}

/// Fetches the contents of the CDS block.
///
/// Wraps `CFE_ES_RestoreFromCDS`.
#[doc(alias = "CFE_ES_RestoreFromCDS")]
#[inline]
pub fn restore_from_cds(&self) -> Result<T, Status> {
use core::mem::MaybeUninit;

let mut value = MaybeUninit::uninit();

let status: Status =
unsafe { CFE_ES_RestoreFromCDS(value.as_mut_ptr() as *mut c_void, self.handle) }.into();

// Safety: the only non-error return value for this is "successful exection", in which case
// a value was copied into `value`.
status.as_result(|| unsafe { value.assume_init() })
}
}

/// The possible varieties of successful outcome of [`CdsHandle::register`]/[`register_with`](CdsHandle::register_with)/[`register_with_default`](CdsHandle::register_with_default).
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub enum CdsRegisterResult {
/// No CDS block with that name existed, and one was created.
Created,

/// A CDS block with that name already existed, with the same size as requested.
AlreadyExists,
}
14 changes: 7 additions & 7 deletions n2o4/src/osal/sync.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ impl BinSem {
/// Wraps `OS_BinSemCreate`.
#[doc(alias = "OS_BinSemCreate")]
#[inline]
pub fn new<S: AsRef<CStr>>(name: &S, initial_value: BinSemState) -> Result<Self, i32> {
pub fn new<S: AsRef<CStr> + ?Sized>(name: &S, initial_value: BinSemState) -> Result<Self, i32> {
let mut id: osal_id_t = X_OS_OBJECT_ID_UNDEFINED;

let retval =
Expand All @@ -46,7 +46,7 @@ impl BinSem {
/// Wraps `OS_BinSemGetIdByName`.
#[doc(alias = "OS_BinSemGetIdByName")]
#[inline]
pub fn find_by_name<S: AsRef<CStr>>(name: &S) -> Result<Option<Self>, i32> {
pub fn find_by_name<S: AsRef<CStr> + ?Sized>(name: &S) -> Result<Option<Self>, i32> {
let mut id: osal_id_t = X_OS_OBJECT_ID_UNDEFINED;

match unsafe { OS_BinSemGetIdByName(&mut id, name.as_ref().as_ptr()) } {
Expand Down Expand Up @@ -213,7 +213,7 @@ impl CountSem {
/// Wraps `OS_CountSemCreate`.
#[doc(alias = "OS_CountSemCreate")]
#[inline]
pub fn new<S: AsRef<CStr>>(sem_name: &S, initial_value: u32) -> Result<Self, i32> {
pub fn new<S: AsRef<CStr> + ?Sized>(sem_name: &S, initial_value: u32) -> Result<Self, i32> {
let mut id: osal_id_t = X_OS_OBJECT_ID_UNDEFINED;

let retval =
Expand All @@ -234,7 +234,7 @@ impl CountSem {
/// Wraps `OS_CountSemGetIdByName`.
#[doc(alias = "OS_CountSemGetIdByName")]
#[inline]
pub fn find_by_name<S: AsRef<CStr>>(name: &S) -> Result<Option<Self>, i32> {
pub fn find_by_name<S: AsRef<CStr> + ?Sized>(name: &S) -> Result<Option<Self>, i32> {
let mut id: osal_id_t = X_OS_OBJECT_ID_UNDEFINED;

match unsafe { OS_CountSemGetIdByName(&mut id, name.as_ref().as_ptr()) } {
Expand Down Expand Up @@ -378,7 +378,7 @@ impl MutSem {
/// Wraps `OS_MutSemCreate`.
#[doc(alias = "OS_MutSemCreate")]
#[inline]
pub fn new<S: AsRef<CStr>>(sem_name: &S) -> Result<Self, i32> {
pub fn new<S: AsRef<CStr> + ?Sized>(sem_name: &S) -> Result<Self, i32> {
let mut id: osal_id_t = X_OS_OBJECT_ID_UNDEFINED;

let retval = unsafe { OS_MutSemCreate(&mut id, sem_name.as_ref().as_ptr(), 0) };
Expand All @@ -398,7 +398,7 @@ impl MutSem {
/// Wraps `OS_MutSemGetIdByName`.
#[doc(alias = "OS_MutSemGetIdByName")]
#[inline]
pub fn find_by_name<S: AsRef<CStr>>(name: &S) -> Result<Option<Self>, i32> {
pub fn find_by_name<S: AsRef<CStr> + ?Sized>(name: &S) -> Result<Option<Self>, i32> {
let mut id: osal_id_t = X_OS_OBJECT_ID_UNDEFINED;

match unsafe { OS_MutSemGetIdByName(&mut id, name.as_ref().as_ptr()) } {
Expand Down Expand Up @@ -542,7 +542,7 @@ macro_rules! owned_sem_variant {
#[doc = "\n\n"]
#[doc = concat!("Wraps `", stringify!($constructor), "`.")]
#[inline]
pub fn new<S: AsRef<CStr>>(sem_name: &S $(, $cparam: $ctype )*) -> Result<Self, i32> {
pub fn new<S: AsRef<CStr> + ?Sized>(sem_name: &S $(, $cparam: $ctype )*) -> Result<Self, i32> {
<$wrapped_type>::new(sem_name $(, $cparam)*).map(|sem| $type_name { sem })
}
}
Expand Down

0 comments on commit 873e893

Please sign in to comment.