From 04f2912a6b0373e6a19f8586541fc9fe03ed79d9 Mon Sep 17 00:00:00 2001 From: MattiaPT Date: Fri, 26 Jul 2024 14:33:30 +0200 Subject: [PATCH] further implemented --- fsw/freertos/CMakeLists.txt | 11 +- fsw/freertos/inc/cmsis_os.h | 771 ++++++++++++++++++++++++++++ fsw/freertos/src/cfe_psp_memory.c | 18 +- fsw/freertos/src/cfe_psp_start.c | 105 ++-- fsw/freertos/src/cfe_psp_support.c | 24 +- fsw/freertos/src/cfe_psp_timer.c | 36 +- fsw/freertos/src/cfe_psp_watchdog.c | 63 ++- 7 files changed, 931 insertions(+), 97 deletions(-) create mode 100644 fsw/freertos/inc/cmsis_os.h diff --git a/fsw/freertos/CMakeLists.txt b/fsw/freertos/CMakeLists.txt index 584c038c..2dd00de4 100644 --- a/fsw/freertos/CMakeLists.txt +++ b/fsw/freertos/CMakeLists.txt @@ -1,5 +1,3 @@ -include_directories(inc) - add_library(psp-${CFE_PSP_TARGETNAME}-impl OBJECT src/cfe_psp_exceptions.c src/cfe_psp_memory.c @@ -8,3 +6,12 @@ add_library(psp-${CFE_PSP_TARGETNAME}-impl OBJECT src/cfe_psp_timer.c src/cfe_psp_watchdog.c ) + +target_compile_definitions(psp-${CFE_SYSTEM_PSPNAME}-impl PRIVATE + $ +) + +target_include_directories(psp-${CFE_PSP_TARGETNAME}-impl PRIVATE + inc + $ +) diff --git a/fsw/freertos/inc/cmsis_os.h b/fsw/freertos/inc/cmsis_os.h new file mode 100644 index 00000000..7244dcb4 --- /dev/null +++ b/fsw/freertos/inc/cmsis_os.h @@ -0,0 +1,771 @@ +/* ---------------------------------------------------------------------- + * $Date: 5. February 2013 + * $Revision: V1.02 + * + * Project: CMSIS-RTOS API + * Title: cmsis_os.h template header file + * + * Version 0.02 + * Initial Proposal Phase + * Version 0.03 + * osKernelStart added, optional feature: main started as thread + * osSemaphores have standard behavior + * osTimerCreate does not start the timer, added osTimerStart + * osThreadPass is renamed to osThreadYield + * Version 1.01 + * Support for C++ interface + * - const attribute removed from the osXxxxDef_t typedef's + * - const attribute added to the osXxxxDef macros + * Added: osTimerDelete, osMutexDelete, osSemaphoreDelete + * Added: osKernelInitialize + * Version 1.02 + * Control functions for short timeouts in microsecond resolution: + * Added: osKernelSysTick, osKernelSysTickFrequency, osKernelSysTickMicroSec + * Removed: osSignalGet + *---------------------------------------------------------------------------- + * + * Copyright (c) 2013-2017 ARM LIMITED + * + * 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 + * + * 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. + *---------------------------------------------------------------------------*/ + +#ifndef _CMSIS_OS_H +#define _CMSIS_OS_H + +/// \note MUST REMAIN UNCHANGED: \b osCMSIS identifies the CMSIS-RTOS API +/// version. +#define osCMSIS 0x10002 ///< API version (main [31:16] .sub [15:0]) + +/// \note CAN BE CHANGED: \b osCMSIS_KERNEL identifies the underlying RTOS +/// kernel and version number. +#define osCMSIS_KERNEL \ + 0x10000 ///< RTOS identification and version (main [31:16] .sub [15:0]) + +/// \note MUST REMAIN UNCHANGED: \b osKernelSystemId shall be consistent in +/// every CMSIS-RTOS. +#define osKernelSystemId "KERNEL V1.00" ///< RTOS identification string + +/// \note MUST REMAIN UNCHANGED: \b osFeature_xxx shall be consistent in every +/// CMSIS-RTOS. +#define osFeature_MainThread \ + 1 ///< main thread 1=main can be thread, 0=not available +#define osFeature_Pool 1 ///< Memory Pools: 1=available, 0=not available +#define osFeature_MailQ 1 ///< Mail Queues: 1=available, 0=not available +#define osFeature_MessageQ 1 ///< Message Queues: 1=available, 0=not available +#define osFeature_Signals \ + 8 ///< maximum number of Signal Flags available per thread +#define osFeature_Semaphore \ + 30 ///< maximum count for \ref osSemaphoreCreate function +#define osFeature_Wait 1 ///< osWait function: 1=available, 0=not available +#define osFeature_SysTick \ + 1 ///< osKernelSysTick functions: 1=available, 0=not available + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +// ==== Enumeration, structures, defines ==== + +/// Priority used for thread control. +/// \note MUST REMAIN UNCHANGED: \b osPriority shall be consistent in every +/// CMSIS-RTOS. +typedef enum { + osPriorityIdle = -3, ///< priority: idle (lowest) + osPriorityLow = -2, ///< priority: low + osPriorityBelowNormal = -1, ///< priority: below normal + osPriorityNormal = 0, ///< priority: normal (default) + osPriorityAboveNormal = +1, ///< priority: above normal + osPriorityHigh = +2, ///< priority: high + osPriorityRealtime = +3, ///< priority: realtime (highest) + osPriorityError = + 0x84 ///< system cannot determine priority or thread has illegal priority +} osPriority; + +/// Timeout value. +/// \note MUST REMAIN UNCHANGED: \b osWaitForever shall be consistent in every +/// CMSIS-RTOS. +#define osWaitForever 0xFFFFFFFF ///< wait forever timeout value + +/// Status code values returned by CMSIS-RTOS functions. +/// \note MUST REMAIN UNCHANGED: \b osStatus shall be consistent in every +/// CMSIS-RTOS. +typedef enum { + osOK = 0, ///< function completed; no error or event occurred. + osEventSignal = 0x08, ///< function completed; signal event occurred. + osEventMessage = 0x10, ///< function completed; message event occurred. + osEventMail = 0x20, ///< function completed; mail event occurred. + osEventTimeout = 0x40, ///< function completed; timeout occurred. + osErrorParameter = 0x80, ///< parameter error: a mandatory parameter was + ///< missing or specified an incorrect object. + osErrorResource = + 0x81, ///< resource not available: a specified resource was not available. + osErrorTimeoutResource = + 0xC1, ///< resource not available within given time: a specified resource + ///< was not available within the timeout period. + osErrorISR = 0x82, ///< not allowed in ISR context: the function cannot be + ///< called from interrupt service routines. + osErrorISRRecursive = + 0x83, ///< function called multiple times from ISR with same object. + osErrorPriority = 0x84, ///< system cannot determine priority or thread has + ///< illegal priority. + osErrorNoMemory = 0x85, ///< system is out of memory: it was impossible to + ///< allocate or reserve memory for the operation. + osErrorValue = 0x86, ///< value of a parameter is out of range. + osErrorOS = 0xFF, ///< unspecified RTOS error: run-time error but no other + ///< error message fits. + os_status_reserved = + 0x7FFFFFFF ///< prevent from enum down-size compiler optimization. +} osStatus; + +/// Timer type value for the timer definition. +/// \note MUST REMAIN UNCHANGED: \b os_timer_type shall be consistent in every +/// CMSIS-RTOS. +typedef enum { + osTimerOnce = 0, ///< one-shot timer + osTimerPeriodic = 1 ///< repeating timer +} os_timer_type; + +/// Entry point of a thread. +/// \note MUST REMAIN UNCHANGED: \b os_pthread shall be consistent in every +/// CMSIS-RTOS. +typedef void (*os_pthread)(void const *argument); + +/// Entry point of a timer call back function. +/// \note MUST REMAIN UNCHANGED: \b os_ptimer shall be consistent in every +/// CMSIS-RTOS. +typedef void (*os_ptimer)(void const *argument); + +// >>> the following data type definitions may shall adapted towards a specific +// RTOS + +/// Thread ID identifies the thread (pointer to a thread control block). +/// \note CAN BE CHANGED: \b os_thread_cb is implementation specific in every +/// CMSIS-RTOS. +typedef struct os_thread_cb *osThreadId; + +/// Timer ID identifies the timer (pointer to a timer control block). +/// \note CAN BE CHANGED: \b os_timer_cb is implementation specific in every +/// CMSIS-RTOS. +typedef struct os_timer_cb *osTimerId; + +/// Mutex ID identifies the mutex (pointer to a mutex control block). +/// \note CAN BE CHANGED: \b os_mutex_cb is implementation specific in every +/// CMSIS-RTOS. +typedef struct os_mutex_cb *osMutexId; + +/// Semaphore ID identifies the semaphore (pointer to a semaphore control +/// block). \note CAN BE CHANGED: \b os_semaphore_cb is implementation specific +/// in every CMSIS-RTOS. +typedef struct os_semaphore_cb *osSemaphoreId; + +/// Pool ID identifies the memory pool (pointer to a memory pool control block). +/// \note CAN BE CHANGED: \b os_pool_cb is implementation specific in every +/// CMSIS-RTOS. +typedef struct os_pool_cb *osPoolId; + +/// Message ID identifies the message queue (pointer to a message queue control +/// block). \note CAN BE CHANGED: \b os_messageQ_cb is implementation specific +/// in every CMSIS-RTOS. +typedef struct os_messageQ_cb *osMessageQId; + +/// Mail ID identifies the mail queue (pointer to a mail queue control block). +/// \note CAN BE CHANGED: \b os_mailQ_cb is implementation specific in every +/// CMSIS-RTOS. +typedef struct os_mailQ_cb *osMailQId; + +/// Thread Definition structure contains startup information of a thread. +/// \note CAN BE CHANGED: \b os_thread_def is implementation specific in every +/// CMSIS-RTOS. +typedef struct os_thread_def { + os_pthread pthread; ///< start address of thread function + osPriority tpriority; ///< initial thread priority + uint32_t instances; ///< maximum number of instances of that thread function + uint32_t + stacksize; ///< stack size requirements in bytes; 0 is default stack size +} osThreadDef_t; + +/// Timer Definition structure contains timer parameters. +/// \note CAN BE CHANGED: \b os_timer_def is implementation specific in every +/// CMSIS-RTOS. +typedef struct os_timer_def { + os_ptimer ptimer; ///< start address of a timer function +} osTimerDef_t; + +/// Mutex Definition structure contains setup information for a mutex. +/// \note CAN BE CHANGED: \b os_mutex_def is implementation specific in every +/// CMSIS-RTOS. +typedef struct os_mutex_def { + uint32_t dummy; ///< dummy value. +} osMutexDef_t; + +/// Semaphore Definition structure contains setup information for a semaphore. +/// \note CAN BE CHANGED: \b os_semaphore_def is implementation specific in +/// every CMSIS-RTOS. +typedef struct os_semaphore_def { + uint32_t dummy; ///< dummy value. +} osSemaphoreDef_t; + +/// Definition structure for memory block allocation. +/// \note CAN BE CHANGED: \b os_pool_def is implementation specific in every +/// CMSIS-RTOS. +typedef struct os_pool_def { + uint32_t pool_sz; ///< number of items (elements) in the pool + uint32_t item_sz; ///< size of an item + void *pool; ///< pointer to memory for pool +} osPoolDef_t; + +/// Definition structure for message queue. +/// \note CAN BE CHANGED: \b os_messageQ_def is implementation specific in every +/// CMSIS-RTOS. +typedef struct os_messageQ_def { + uint32_t queue_sz; ///< number of elements in the queue + uint32_t item_sz; ///< size of an item + void *pool; ///< memory array for messages +} osMessageQDef_t; + +/// Definition structure for mail queue. +/// \note CAN BE CHANGED: \b os_mailQ_def is implementation specific in every +/// CMSIS-RTOS. +typedef struct os_mailQ_def { + uint32_t queue_sz; ///< number of elements in the queue + uint32_t item_sz; ///< size of an item + void *pool; ///< memory array for mail +} osMailQDef_t; + +/// Event structure contains detailed information about an event. +/// \note MUST REMAIN UNCHANGED: \b os_event shall be consistent in every +/// CMSIS-RTOS. +/// However the struct may be extended at the end. +typedef struct { + osStatus status; ///< status code: event or error information + union { + uint32_t v; ///< message as 32-bit value + void *p; ///< message or mail as void pointer + int32_t signals; ///< signal flags + } value; ///< event value + union { + osMailQId mail_id; ///< mail id obtained by \ref osMailCreate + osMessageQId message_id; ///< message id obtained by \ref osMessageCreate + } def; ///< event definition +} osEvent; + +// ==== Kernel Control Functions ==== + +/// Initialize the RTOS Kernel for creating objects. +/// \return status code that indicates the execution status of the function. +/// \note MUST REMAIN UNCHANGED: \b osKernelInitialize shall be consistent in +/// every CMSIS-RTOS. +osStatus osKernelInitialize(void); + +/// Start the RTOS Kernel. +/// \return status code that indicates the execution status of the function. +/// \note MUST REMAIN UNCHANGED: \b osKernelStart shall be consistent in every +/// CMSIS-RTOS. +osStatus osKernelStart(void); + +/// Check if the RTOS kernel is already started. +/// \note MUST REMAIN UNCHANGED: \b osKernelRunning shall be consistent in every +/// CMSIS-RTOS. \return 0 RTOS is not started, 1 RTOS is started. +int32_t osKernelRunning(void); + +#if (defined(osFeature_SysTick) && \ + (osFeature_SysTick != 0)) // System Timer available + +/// Get the RTOS kernel system timer counter +/// \note MUST REMAIN UNCHANGED: \b osKernelSysTick shall be consistent in every +/// CMSIS-RTOS. \return RTOS kernel system timer as 32-bit value +uint32_t osKernelSysTick(void); + +/// The RTOS kernel system timer frequency in Hz +/// \note Reflects the system timer setting and is typically defined in a +/// configuration file. +#define osKernelSysTickFrequency 100000000 + +/// Convert a microseconds value to a RTOS kernel system timer value. +/// \param microsec time value in microseconds. +/// \return time value normalized to the \ref osKernelSysTickFrequency +#define osKernelSysTickMicroSec(microsec) \ + (((uint64_t)microsec * (osKernelSysTickFrequency)) / 1000000) + +#endif // System Timer available + +// ==== Thread Management ==== + +/// Create a Thread Definition with function, priority, and stack requirements. +/// \param name name of the thread function. +/// \param priority initial priority of the thread function. +/// \param instances number of possible thread instances. +/// \param stacksz stack size (in bytes) requirements for the +/// thread function. \note CAN BE CHANGED: The parameters to \b osThreadDef +/// shall be consistent but the +/// macro body is implementation specific in every CMSIS-RTOS. +#if defined(osObjectsExternal) // object is external +#define osThreadDef(name, priority, instances, stacksz) \ + extern const osThreadDef_t os_thread_def_##name +#else // define the object +#define osThreadDef(name, priority, instances, stacksz) \ + const osThreadDef_t os_thread_def_##name = {(name), (priority), (instances), \ + (stacksz)} +#endif + +/// Access a Thread definition. +/// \param name name of the thread definition object. +/// \note CAN BE CHANGED: The parameter to \b osThread shall be consistent but +/// the +/// macro body is implementation specific in every CMSIS-RTOS. +#define osThread(name) &os_thread_def_##name + +/// Create a thread and add it to Active Threads and set it to state READY. +/// \param[in] thread_def thread definition referenced with \ref +/// osThread. \param[in] argument pointer that is passed to the thread +/// function as start argument. \return thread ID for reference by other +/// functions or NULL in case of error. \note MUST REMAIN UNCHANGED: \b +/// osThreadCreate shall be consistent in every CMSIS-RTOS. +osThreadId osThreadCreate(const osThreadDef_t *thread_def, void *argument); + +/// Return the thread ID of the current running thread. +/// \return thread ID for reference by other functions or NULL in case of error. +/// \note MUST REMAIN UNCHANGED: \b osThreadGetId shall be consistent in every +/// CMSIS-RTOS. +osThreadId osThreadGetId(void); + +/// Terminate execution of a thread and remove it from Active Threads. +/// \param[in] thread_id thread ID obtained by \ref osThreadCreate or \ref +/// osThreadGetId. \return status code that indicates the execution status of +/// the function. \note MUST REMAIN UNCHANGED: \b osThreadTerminate shall be +/// consistent in every CMSIS-RTOS. +osStatus osThreadTerminate(osThreadId thread_id); + +/// Pass control to next thread that is in state \b READY. +/// \return status code that indicates the execution status of the function. +/// \note MUST REMAIN UNCHANGED: \b osThreadYield shall be consistent in every +/// CMSIS-RTOS. +osStatus osThreadYield(void); + +/// Change priority of an active thread. +/// \param[in] thread_id thread ID obtained by \ref osThreadCreate or +/// \ref osThreadGetId. \param[in] priority new priority value for the +/// thread function. \return status code that indicates the execution status of +/// the function. \note MUST REMAIN UNCHANGED: \b osThreadSetPriority shall be +/// consistent in every CMSIS-RTOS. +osStatus osThreadSetPriority(osThreadId thread_id, osPriority priority); + +/// Get current priority of an active thread. +/// \param[in] thread_id thread ID obtained by \ref osThreadCreate or +/// \ref osThreadGetId. \return current priority value of the thread function. +/// \note MUST REMAIN UNCHANGED: \b osThreadGetPriority shall be consistent in +/// every CMSIS-RTOS. +osPriority osThreadGetPriority(osThreadId thread_id); + +// ==== Generic Wait Functions ==== + +/// Wait for Timeout (Time Delay). +/// \param[in] millisec \ref CMSIS_RTOS_TimeOutValue "time delay" value +/// \return status code that indicates the execution status of the function. +osStatus osDelay(uint32_t millisec); + +#if (defined(osFeature_Wait) && (osFeature_Wait != 0)) // Generic Wait available + +/// Wait for Signal, Message, Mail, or Timeout. +/// \param[in] millisec \ref CMSIS_RTOS_TimeOutValue or 0 in case of no +/// time-out \return event that contains signal, message, or mail information or +/// error code. \note MUST REMAIN UNCHANGED: \b osWait shall be consistent in +/// every CMSIS-RTOS. +osEvent osWait(uint32_t millisec); + +#endif // Generic Wait available + +// ==== Timer Management Functions ==== +/// Define a Timer object. +/// \param name name of the timer object. +/// \param function name of the timer call back function. +/// \note CAN BE CHANGED: The parameter to \b osTimerDef shall be consistent but +/// the +/// macro body is implementation specific in every CMSIS-RTOS. +#if defined(osObjectsExternal) // object is external +#define osTimerDef(name, function) extern const osTimerDef_t os_timer_def_##name +#else // define the object +#define osTimerDef(name, function) \ + const osTimerDef_t os_timer_def_##name = {(function)} +#endif + +/// Access a Timer definition. +/// \param name name of the timer object. +/// \note CAN BE CHANGED: The parameter to \b osTimer shall be consistent but +/// the +/// macro body is implementation specific in every CMSIS-RTOS. +#define osTimer(name) &os_timer_def_##name + +/// Create a timer. +/// \param[in] timer_def timer object referenced with \ref osTimer. +/// \param[in] type osTimerOnce for one-shot or osTimerPeriodic for +/// periodic behavior. \param[in] argument argument to the timer call +/// back function. \return timer ID for reference by other functions or NULL in +/// case of error. \note MUST REMAIN UNCHANGED: \b osTimerCreate shall be +/// consistent in every CMSIS-RTOS. +osTimerId osTimerCreate(const osTimerDef_t *timer_def, os_timer_type type, + void *argument); + +/// Start or restart a timer. +/// \param[in] timer_id timer ID obtained by \ref osTimerCreate. +/// \param[in] millisec \ref CMSIS_RTOS_TimeOutValue "time delay" value +/// of the timer. \return status code that indicates the execution status of the +/// function. \note MUST REMAIN UNCHANGED: \b osTimerStart shall be consistent +/// in every CMSIS-RTOS. +osStatus osTimerStart(osTimerId timer_id, uint32_t millisec); + +/// Stop the timer. +/// \param[in] timer_id timer ID obtained by \ref osTimerCreate. +/// \return status code that indicates the execution status of the function. +/// \note MUST REMAIN UNCHANGED: \b osTimerStop shall be consistent in every +/// CMSIS-RTOS. +osStatus osTimerStop(osTimerId timer_id); + +/// Delete a timer that was created by \ref osTimerCreate. +/// \param[in] timer_id timer ID obtained by \ref osTimerCreate. +/// \return status code that indicates the execution status of the function. +/// \note MUST REMAIN UNCHANGED: \b osTimerDelete shall be consistent in every +/// CMSIS-RTOS. +osStatus osTimerDelete(osTimerId timer_id); + +// ==== Signal Management ==== + +/// Set the specified Signal Flags of an active thread. +/// \param[in] thread_id thread ID obtained by \ref osThreadCreate or +/// \ref osThreadGetId. \param[in] signals specifies the signal flags +/// of the thread that should be set. \return previous signal flags of the +/// specified thread or 0x80000000 in case of incorrect parameters. \note MUST +/// REMAIN UNCHANGED: \b osSignalSet shall be consistent in every CMSIS-RTOS. +int32_t osSignalSet(osThreadId thread_id, int32_t signals); + +/// Clear the specified Signal Flags of an active thread. +/// \param[in] thread_id thread ID obtained by \ref osThreadCreate or +/// \ref osThreadGetId. \param[in] signals specifies the signal flags +/// of the thread that shall be cleared. \return previous signal flags of the +/// specified thread or 0x80000000 in case of incorrect parameters or call from +/// ISR. \note MUST REMAIN UNCHANGED: \b osSignalClear shall be consistent in +/// every CMSIS-RTOS. +int32_t osSignalClear(osThreadId thread_id, int32_t signals); + +/// Wait for one or more Signal Flags to become signaled for the current \b +/// RUNNING thread. \param[in] signals wait until all specified signal +/// flags set or 0 for any single signal flag. \param[in] millisec \ref +/// CMSIS_RTOS_TimeOutValue or 0 in case of no time-out. \return event flag +/// information or error code. \note MUST REMAIN UNCHANGED: \b osSignalWait +/// shall be consistent in every CMSIS-RTOS. +osEvent osSignalWait(int32_t signals, uint32_t millisec); + +// ==== Mutex Management ==== + +/// Define a Mutex. +/// \param name name of the mutex object. +/// \note CAN BE CHANGED: The parameter to \b osMutexDef shall be consistent but +/// the +/// macro body is implementation specific in every CMSIS-RTOS. +#if defined(osObjectsExternal) // object is external +#define osMutexDef(name) extern const osMutexDef_t os_mutex_def_##name +#else // define the object +#define osMutexDef(name) const osMutexDef_t os_mutex_def_##name = {0} +#endif + +/// Access a Mutex definition. +/// \param name name of the mutex object. +/// \note CAN BE CHANGED: The parameter to \b osMutex shall be consistent but +/// the +/// macro body is implementation specific in every CMSIS-RTOS. +#define osMutex(name) &os_mutex_def_##name + +/// Create and Initialize a Mutex object. +/// \param[in] mutex_def mutex definition referenced with \ref osMutex. +/// \return mutex ID for reference by other functions or NULL in case of error. +/// \note MUST REMAIN UNCHANGED: \b osMutexCreate shall be consistent in every +/// CMSIS-RTOS. +osMutexId osMutexCreate(const osMutexDef_t *mutex_def); + +/// Wait until a Mutex becomes available. +/// \param[in] mutex_id mutex ID obtained by \ref osMutexCreate. +/// \param[in] millisec \ref CMSIS_RTOS_TimeOutValue or 0 in case of no +/// time-out. \return status code that indicates the execution status of the +/// function. \note MUST REMAIN UNCHANGED: \b osMutexWait shall be consistent in +/// every CMSIS-RTOS. +osStatus osMutexWait(osMutexId mutex_id, uint32_t millisec); + +/// Release a Mutex that was obtained by \ref osMutexWait. +/// \param[in] mutex_id mutex ID obtained by \ref osMutexCreate. +/// \return status code that indicates the execution status of the function. +/// \note MUST REMAIN UNCHANGED: \b osMutexRelease shall be consistent in every +/// CMSIS-RTOS. +osStatus osMutexRelease(osMutexId mutex_id); + +/// Delete a Mutex that was created by \ref osMutexCreate. +/// \param[in] mutex_id mutex ID obtained by \ref osMutexCreate. +/// \return status code that indicates the execution status of the function. +/// \note MUST REMAIN UNCHANGED: \b osMutexDelete shall be consistent in every +/// CMSIS-RTOS. +osStatus osMutexDelete(osMutexId mutex_id); + +// ==== Semaphore Management Functions ==== + +#if (defined(osFeature_Semaphore) && \ + (osFeature_Semaphore != 0)) // Semaphore available + +/// Define a Semaphore object. +/// \param name name of the semaphore object. +/// \note CAN BE CHANGED: The parameter to \b osSemaphoreDef shall be consistent +/// but the +/// macro body is implementation specific in every CMSIS-RTOS. +#if defined(osObjectsExternal) // object is external +#define osSemaphoreDef(name) \ + extern const osSemaphoreDef_t os_semaphore_def_##name +#else // define the object +#define osSemaphoreDef(name) \ + const osSemaphoreDef_t os_semaphore_def_##name = {0} +#endif + +/// Access a Semaphore definition. +/// \param name name of the semaphore object. +/// \note CAN BE CHANGED: The parameter to \b osSemaphore shall be consistent +/// but the +/// macro body is implementation specific in every CMSIS-RTOS. +#define osSemaphore(name) &os_semaphore_def_##name + +/// Create and Initialize a Semaphore object used for managing resources. +/// \param[in] semaphore_def semaphore definition referenced with \ref +/// osSemaphore. \param[in] count number of available resources. +/// \return semaphore ID for reference by other functions or NULL in case of +/// error. \note MUST REMAIN UNCHANGED: \b osSemaphoreCreate shall be consistent +/// in every CMSIS-RTOS. +osSemaphoreId osSemaphoreCreate(const osSemaphoreDef_t *semaphore_def, + int32_t count); + +/// Wait until a Semaphore token becomes available. +/// \param[in] semaphore_id semaphore object referenced with \ref +/// osSemaphoreCreate. \param[in] millisec \ref CMSIS_RTOS_TimeOutValue +/// or 0 in case of no time-out. \return number of available tokens, or -1 in +/// case of incorrect parameters. \note MUST REMAIN UNCHANGED: \b +/// osSemaphoreWait shall be consistent in every CMSIS-RTOS. +int32_t osSemaphoreWait(osSemaphoreId semaphore_id, uint32_t millisec); + +/// Release a Semaphore token. +/// \param[in] semaphore_id semaphore object referenced with \ref +/// osSemaphoreCreate. \return status code that indicates the execution status +/// of the function. \note MUST REMAIN UNCHANGED: \b osSemaphoreRelease shall be +/// consistent in every CMSIS-RTOS. +osStatus osSemaphoreRelease(osSemaphoreId semaphore_id); + +/// Delete a Semaphore that was created by \ref osSemaphoreCreate. +/// \param[in] semaphore_id semaphore object referenced with \ref +/// osSemaphoreCreate. \return status code that indicates the execution status +/// of the function. \note MUST REMAIN UNCHANGED: \b osSemaphoreDelete shall be +/// consistent in every CMSIS-RTOS. +osStatus osSemaphoreDelete(osSemaphoreId semaphore_id); + +#endif // Semaphore available + +// ==== Memory Pool Management Functions ==== + +#if (defined(osFeature_Pool) && \ + (osFeature_Pool != 0)) // Memory Pool Management available + +/// \brief Define a Memory Pool. +/// \param name name of the memory pool. +/// \param no maximum number of blocks (objects) in the +/// memory pool. \param type data type of a single block +/// (object). \note CAN BE CHANGED: The parameter to \b osPoolDef shall be +/// consistent but the +/// macro body is implementation specific in every CMSIS-RTOS. +#if defined(osObjectsExternal) // object is external +#define osPoolDef(name, no, type) extern const osPoolDef_t os_pool_def_##name +#else // define the object +#define osPoolDef(name, no, type) \ + const osPoolDef_t os_pool_def_##name = {(no), sizeof(type), NULL} +#endif + +/// \brief Access a Memory Pool definition. +/// \param name name of the memory pool +/// \note CAN BE CHANGED: The parameter to \b osPool shall be consistent but the +/// macro body is implementation specific in every CMSIS-RTOS. +#define osPool(name) &os_pool_def_##name + +/// Create and Initialize a memory pool. +/// \param[in] pool_def memory pool definition referenced with \ref +/// osPool. \return memory pool ID for reference by other functions or NULL in +/// case of error. \note MUST REMAIN UNCHANGED: \b osPoolCreate shall be +/// consistent in every CMSIS-RTOS. +osPoolId osPoolCreate(const osPoolDef_t *pool_def); + +/// Allocate a memory block from a memory pool. +/// \param[in] pool_id memory pool ID obtain referenced with \ref +/// osPoolCreate. \return address of the allocated memory block or NULL in case +/// of no memory available. \note MUST REMAIN UNCHANGED: \b osPoolAlloc shall be +/// consistent in every CMSIS-RTOS. +void *osPoolAlloc(osPoolId pool_id); + +/// Allocate a memory block from a memory pool and set memory block to zero. +/// \param[in] pool_id memory pool ID obtain referenced with \ref +/// osPoolCreate. \return address of the allocated memory block or NULL in case +/// of no memory available. \note MUST REMAIN UNCHANGED: \b osPoolCAlloc shall +/// be consistent in every CMSIS-RTOS. +void *osPoolCAlloc(osPoolId pool_id); + +/// Return an allocated memory block back to a specific memory pool. +/// \param[in] pool_id memory pool ID obtain referenced with \ref +/// osPoolCreate. \param[in] block address of the allocated memory +/// block that is returned to the memory pool. \return status code that +/// indicates the execution status of the function. \note MUST REMAIN UNCHANGED: +/// \b osPoolFree shall be consistent in every CMSIS-RTOS. +osStatus osPoolFree(osPoolId pool_id, void *block); + +#endif // Memory Pool Management available + +// ==== Message Queue Management Functions ==== + +#if (defined(osFeature_MessageQ) && \ + (osFeature_MessageQ != 0)) // Message Queues available + +/// \brief Create a Message Queue Definition. +/// \param name name of the queue. +/// \param queue_sz maximum number of messages in the queue. +/// \param type data type of a single message element (for +/// debugger). \note CAN BE CHANGED: The parameter to \b osMessageQDef shall be +/// consistent but the +/// macro body is implementation specific in every CMSIS-RTOS. +#if defined(osObjectsExternal) // object is external +#define osMessageQDef(name, queue_sz, type) \ + extern const osMessageQDef_t os_messageQ_def_##name +#else // define the object +#define osMessageQDef(name, queue_sz, type) \ + const osMessageQDef_t os_messageQ_def_##name = {(queue_sz), sizeof(type)} +#endif + +/// \brief Access a Message Queue Definition. +/// \param name name of the queue +/// \note CAN BE CHANGED: The parameter to \b osMessageQ shall be consistent but +/// the +/// macro body is implementation specific in every CMSIS-RTOS. +#define osMessageQ(name) &os_messageQ_def_##name + +/// Create and Initialize a Message Queue. +/// \param[in] queue_def queue definition referenced with \ref +/// osMessageQ. \param[in] thread_id thread ID (obtained by \ref +/// osThreadCreate or \ref osThreadGetId) or NULL. \return message queue ID for +/// reference by other functions or NULL in case of error. \note MUST REMAIN +/// UNCHANGED: \b osMessageCreate shall be consistent in every CMSIS-RTOS. +osMessageQId osMessageCreate(const osMessageQDef_t *queue_def, + osThreadId thread_id); + +/// Put a Message to a Queue. +/// \param[in] queue_id message queue ID obtained with \ref +/// osMessageCreate. \param[in] info message information. +/// \param[in] millisec \ref CMSIS_RTOS_TimeOutValue or 0 in case of no +/// time-out. \return status code that indicates the execution status of the +/// function. \note MUST REMAIN UNCHANGED: \b osMessagePut shall be consistent +/// in every CMSIS-RTOS. +osStatus osMessagePut(osMessageQId queue_id, uint32_t info, uint32_t millisec); + +/// Get a Message or Wait for a Message from a Queue. +/// \param[in] queue_id message queue ID obtained with \ref +/// osMessageCreate. \param[in] millisec \ref CMSIS_RTOS_TimeOutValue +/// or 0 in case of no time-out. \return event information that includes status +/// code. \note MUST REMAIN UNCHANGED: \b osMessageGet shall be consistent in +/// every CMSIS-RTOS. +osEvent osMessageGet(osMessageQId queue_id, uint32_t millisec); + +#endif // Message Queues available + +// ==== Mail Queue Management Functions ==== + +#if (defined(osFeature_MailQ) && \ + (osFeature_MailQ != 0)) // Mail Queues available + +/// \brief Create a Mail Queue Definition. +/// \param name name of the queue +/// \param queue_sz maximum number of messages in queue +/// \param type data type of a single message element +/// \note CAN BE CHANGED: The parameter to \b osMailQDef shall be consistent but +/// the +/// macro body is implementation specific in every CMSIS-RTOS. +#if defined(osObjectsExternal) // object is external +#define osMailQDef(name, queue_sz, type) \ + extern const osMailQDef_t os_mailQ_def_##name +#else // define the object +#define osMailQDef(name, queue_sz, type) \ + const osMailQDef_t os_mailQ_def_##name = {(queue_sz), sizeof(type)} +#endif + +/// \brief Access a Mail Queue Definition. +/// \param name name of the queue +/// \note CAN BE CHANGED: The parameter to \b osMailQ shall be consistent but +/// the +/// macro body is implementation specific in every CMSIS-RTOS. +#define osMailQ(name) &os_mailQ_def_##name + +/// Create and Initialize mail queue. +/// \param[in] queue_def reference to the mail queue definition obtain +/// with \ref osMailQ \param[in] thread_id thread ID (obtained by \ref +/// osThreadCreate or \ref osThreadGetId) or NULL. \return mail queue ID for +/// reference by other functions or NULL in case of error. \note MUST REMAIN +/// UNCHANGED: \b osMailCreate shall be consistent in every CMSIS-RTOS. +osMailQId osMailCreate(const osMailQDef_t *queue_def, osThreadId thread_id); + +/// Allocate a memory block from a mail. +/// \param[in] queue_id mail queue ID obtained with \ref osMailCreate. +/// \param[in] millisec \ref CMSIS_RTOS_TimeOutValue or 0 in case of no +/// time-out \return pointer to memory block that can be filled with mail or +/// NULL in case of error. \note MUST REMAIN UNCHANGED: \b osMailAlloc shall be +/// consistent in every CMSIS-RTOS. +void *osMailAlloc(osMailQId queue_id, uint32_t millisec); + +/// Allocate a memory block from a mail and set memory block to zero. +/// \param[in] queue_id mail queue ID obtained with \ref osMailCreate. +/// \param[in] millisec \ref CMSIS_RTOS_TimeOutValue or 0 in case of no +/// time-out \return pointer to memory block that can be filled with mail or +/// NULL in case of error. \note MUST REMAIN UNCHANGED: \b osMailCAlloc shall be +/// consistent in every CMSIS-RTOS. +void *osMailCAlloc(osMailQId queue_id, uint32_t millisec); + +/// Put a mail to a queue. +/// \param[in] queue_id mail queue ID obtained with \ref osMailCreate. +/// \param[in] mail memory block previously allocated with \ref +/// osMailAlloc or \ref osMailCAlloc. \return status code that indicates the +/// execution status of the function. \note MUST REMAIN UNCHANGED: \b osMailPut +/// shall be consistent in every CMSIS-RTOS. +osStatus osMailPut(osMailQId queue_id, void *mail); + +/// Get a mail from a queue. +/// \param[in] queue_id mail queue ID obtained with \ref osMailCreate. +/// \param[in] millisec \ref CMSIS_RTOS_TimeOutValue or 0 in case of no +/// time-out \return event that contains mail information or error code. \note +/// MUST REMAIN UNCHANGED: \b osMailGet shall be consistent in every CMSIS-RTOS. +osEvent osMailGet(osMailQId queue_id, uint32_t millisec); + +/// Free a memory block from a mail. +/// \param[in] queue_id mail queue ID obtained with \ref osMailCreate. +/// \param[in] mail pointer to the memory block that was obtained +/// with \ref osMailGet. \return status code that indicates the execution status +/// of the function. \note MUST REMAIN UNCHANGED: \b osMailFree shall be +/// consistent in every CMSIS-RTOS. +osStatus osMailFree(osMailQId queue_id, void *mail); + +#endif // Mail Queues available + +#ifdef __cplusplus +} +#endif + +#endif // _CMSIS_OS_H diff --git a/fsw/freertos/src/cfe_psp_memory.c b/fsw/freertos/src/cfe_psp_memory.c index 2d579bdb..166737a3 100644 --- a/fsw/freertos/src/cfe_psp_memory.c +++ b/fsw/freertos/src/cfe_psp_memory.c @@ -1,8 +1,6 @@ -#include - +#include "cfe_psp_memory.h" #include "cfe_psp.h" #include "cfe_psp_config.h" // TODO: set up (for reservedbootrecord and memalign mask) -#include "cfe_psp_memory.h" #include "common_types.h" // defined in osal/src/os/inc /* macros */ @@ -22,17 +20,14 @@ #define memalign(x) (x + CFE_PSP_MEMALIGN_MASK) & ~CFE_PSP_MEMALIGN_MASK -/* ------ */ - -/* Global Variables */ +extern char __text_start__; +extern char __text_end__; CFE_PSP_ReservedMemoryMap_t CFE_PSP_ReservedMemoryMap = {0}; __attribute__((section(".psp_reserved"))) __attribute__(( aligned(8))) char pspReservedMemoryAlloc[CFE_PSP_RESERVED_MEMORY_SIZE]; -/* ---------------- */ - /* * CDS related functions */ @@ -134,6 +129,7 @@ int32 CFE_PSP_GetVolatileDiskMem(cpuaddr *PtrToVolDisk, uint32 *SizeOfVolDisk) { /* * Kernel Memory functions + * TODO: relies on __text_start__ and __text_end__ defined in linker */ int32 CFE_PSP_GetKernelTextSegmentInfo(cpuaddr *PtrToKernelSegment, @@ -145,8 +141,8 @@ int32 CFE_PSP_GetKernelTextSegmentInfo(cpuaddr *PtrToKernelSegment, return CFE_PSP_ERROR; } - StartAddress = 0; // TODO: get kernel start address - EndAddress = 0; // TODO: get kernel end address + StartAddress = (cpuaddr)&__text_start__; + EndAddress = (cpuaddr)&__text_end__; *PtrToKernelSegment = StartAddress; *SizeOfKernelSegment = (uint32)(EndAddress - StartAddress); @@ -217,5 +213,5 @@ void CFE_PSP_SetupReservedMemoryMap(void) { ReservedMemoryAddr += UserReservedSize; } -// TODO: is an action needed? +// no action needed void CFE_PSP_DeleteProcessorReservedMemory(void) {} diff --git a/fsw/freertos/src/cfe_psp_start.c b/fsw/freertos/src/cfe_psp_start.c index 7127e7db..1f555399 100644 --- a/fsw/freertos/src/cfe_psp_start.c +++ b/fsw/freertos/src/cfe_psp_start.c @@ -7,62 +7,67 @@ #define CFE_PSP_MAIN_FUNCTION (*GLOBAL_CONFIGDATA.CfeConfig->SystemMain) -#define CFE_PSP_NONVOL_STARTUP_FILE (GLOBAL_CONFIGDATA.CfeConfig->NonvolStartupFile) - - -void CFE_PSP_Restart(uint32 resetType) -{ - if (resetType == CFE_PSP_RST_TYPE_POWERON) - { - CFE_PSP_ReservedMemoryMap.BootPtr->bsp_reset_type = CFE_PSP_RST_TYPE_POWERON; - CFE_PSP_FlushCaches(1, ReservedMemBlock.BlockPtr, ReservedMemBlock.BlockSize); - - NVIC_SystemReset(); - } - else - { - CFE_PSP_ReservedMemoryMap.BootPtr->bsp_reset_type = CFE_PSP_RST_TYPE_PROCESSOR; - CFE_PSP_FlushCaches(1, ReservedMemBlock.BlockPtr, ReservedMemBlock.BlockSize); - /* FIXME: reboot without wiping memory */ - } +#define CFE_PSP_NONVOL_STARTUP_FILE \ + (GLOBAL_CONFIGDATA.CfeConfig->NonvolStartupFile) + +void CFE_PSP_Restart(uint32 resetType) { + if (resetType == CFE_PSP_RST_TYPE_POWERON) { + CFE_PSP_ReservedMemoryMap.BootPtr->bsp_reset_type = + CFE_PSP_RST_TYPE_POWERON; + CFE_PSP_FlushCaches(1, ReservedMemBlock.BlockPtr, + ReservedMemBlock.BlockSize); + + NVIC_SystemReset(); + } else { + CFE_PSP_ReservedMemoryMap.BootPtr->bsp_reset_type = + CFE_PSP_RST_TYPE_PROCESSOR; + CFE_PSP_FlushCaches(1, ReservedMemBlock.BlockPtr, + ReservedMemBlock.BlockSize); + /* FIXME: reboot without wiping memory */ + } } +uint32 CFE_PSP_GetRestartType(uint32 *restartSubType) { + if (restartSubType != NULL) { + restartSubType = CFE_PSP_ReservedMemoryMap.BootPtr->bsp_reset_type; + } -/* TODO: review this implementation by pztrick */ - -int CFE_PSP_Setup(void){ - return CFE_PSP_SUCCESS; + return CFE_PSP_ReservedMemoryMap.BootPtr->bsp_reset_type; } -void CFE_PSP_Panic(int32 ErrorCode){ - __asm("bkpt 1"); - // vTaskEndScheduler(); - OS_ApplicationExit(ErrorCode); +/* TODO: review this implementation by pztrick */ +int CFE_PSP_Setup(void) { return CFE_PSP_SUCCESS; } + +void CFE_PSP_Panic(int32 ErrorCode) { + __asm("bkpt 1"); + // vTaskEndScheduler(); + OS_ApplicationExit(ErrorCode); } // OSAL:main() invokes PSP:OS_Application_Startup() inside a FreeRTOS task -void OS_Application_Startup(void){ - int32 status; - uint32 reset_type; - uint32 reset_subtype; - - CFE_PSP_SetupReservedMemoryMap(); - - status = OS_API_Init(); - if(status != OS_SUCCESS){ - OS_ApplicationExit(status); - } - - if(CFE_PSP_Setup() != CFE_PSP_SUCCESS){ - CFE_PSP_Panic(CFE_PSP_ERROR); - } - - // @FIXME should try to read reset_type from NVM BootPtr - reset_type = CFE_PSP_RST_TYPE_POWERON; - reset_subtype = CFE_PSP_RST_SUBTYPE_POWER_CYCLE; - CFE_PSP_InitProcessorReservedMemory(reset_type); - - CFE_PSP_MAIN_FUNCTION(reset_type, reset_subtype, 1, CFE_PSP_NONVOL_STARTUP_FILE); - - vTaskDelete(NULL); +void OS_Application_Startup(void) { + int32 status; + uint32 reset_type; + uint32 reset_subtype; + + CFE_PSP_SetupReservedMemoryMap(); + + status = OS_API_Init(); + if (status != OS_SUCCESS) { + OS_ApplicationExit(status); + } + + if (CFE_PSP_Setup() != CFE_PSP_SUCCESS) { + CFE_PSP_Panic(CFE_PSP_ERROR); + } + + // FIXME: should try to read reset_type from NVM BootPtr + reset_type = CFE_PSP_RST_TYPE_POWERON; + reset_subtype = CFE_PSP_RST_SUBTYPE_POWER_CYCLE; + CFE_PSP_InitProcessorReservedMemory(reset_type); + + CFE_PSP_MAIN_FUNCTION(reset_type, reset_subtype, 1, + CFE_PSP_NONVOL_STARTUP_FILE); + + vTaskDelete(NULL); } diff --git a/fsw/freertos/src/cfe_psp_support.c b/fsw/freertos/src/cfe_psp_support.c index 5a499e5f..f683fcdd 100644 --- a/fsw/freertos/src/cfe_psp_support.c +++ b/fsw/freertos/src/cfe_psp_support.c @@ -17,14 +17,16 @@ ************************************************************************/ #include "cmsis_os.h" - #include "target_config.h" +#include + +#define CHUNK 16384 + #define CFE_PSP_CPU_ID (GLOBAL_CONFIGDATA.CpuId) #define CFE_PSP_CPU_NAME (GLOBAL_CONFIGDATA.CpuName) #define CFE_PSP_SPACECRAFT_ID (GLOBAL_CONFIGDATA.SpacecraftId) -// TODO void CFE_PSP_FlushCaches(uint32 type, void *address, uint32 size) { if (type != 1) { return; @@ -47,4 +49,20 @@ uint32 CFE_PSP_GetSpacecraftId(void) { return CFE_PSP_SPACECRAFT_ID; } const char *CFE_PSP_GetProcessorName(void) { return CFE_PSP_CPU_NAME; } -uint32 CFE_PSP_Get_Timer_Tick(void) { /* TODO */ } +void CFE_PSP_Decompress(char *srcFileName, char *dstFileName) { + char buffer[CHUNK]; + int bytes_read; + + // Open the gzip file + gzFile gz = gzopen(input_file, "rb"); + FILE *out = fopen(output_file, "wb"); + + // Decompress the file + while ((bytes_read = gzread(gz, buffer, CHUNK)) > 0) { + fwrite(buffer, 1, bytes_read, out); + } + + // Close the files + gzclose(gz); + fclose(out); +} diff --git a/fsw/freertos/src/cfe_psp_timer.c b/fsw/freertos/src/cfe_psp_timer.c index 5da372a2..9501b8ee 100644 --- a/fsw/freertos/src/cfe_psp_timer.c +++ b/fsw/freertos/src/cfe_psp_timer.c @@ -1,17 +1,31 @@ -#define CFE_PSP_TIMER_TICKS_PER_SECOND ((int32) configTICK_RATE_HZ) +#include "common_types.h" -uint32 CFE_PSP_GetTimerTicksPerSecond(void) -{ - return CFE_PSP_TIMER_TICKS_PER_SECOND; +#define CFE_PSP_TIMER_TICKS_PER_SECOND ((int32)configTICK_RATE_HZ) + +uint32 CFE_PSP_GetTimerTicksPerSecond(void) { + return CFE_PSP_TIMER_TICKS_PER_SECOND; } -uint32 CFE_PSP_GetTimerLow32Rollover(void) -{ - return 0; +uint32 CFE_PSP_GetTimerLow32Rollover(void) { return 0; } + +void CFE_PSP_Get_Timebase(uint32 *Tbu, uint32 *Tbl) { + *Tbu = 0; + *Tbl = HAL_GetTick(); } -void CFE_PSP_Get_Timebase(uint32 *Tbu, uint32 *Tbl) -{ - // SysTick is set up in HAL_Init - return xTaskGetTickCount; +uint32 CFE_PSP_Get_Timer_Tick(void) { return HAL_GetTick(); } + +void CFE_PSP_GetTime(OS_time_t *LocalTime) { + uint64 NormalizedTicks; + uint32 RegUpper, RegLower; + + CFE_PSP_Get_Timebase(&RegUpper, &RegLower); + + NormalizedTicks = RegUpper; + NormalizedTicks <<= 32; + NormalizedTicks |= RegLower; + + NormalizedTicks *= portTICK_PERIOD_MS; + + *LocalTime = (OS_time_t){NormalizedTicks}; } diff --git a/fsw/freertos/src/cfe_psp_watchdog.c b/fsw/freertos/src/cfe_psp_watchdog.c index 78865b7b..9c826694 100644 --- a/fsw/freertos/src/cfe_psp_watchdog.c +++ b/fsw/freertos/src/cfe_psp_watchdog.c @@ -1,34 +1,57 @@ +#include "FreeRTOS.h" #include "cfe_psp.h" #include "cfe_psp_config.h" +#include "stm32h7xx_hal.h" +#include "task.h" -uint32 CFE_PSP_WatchdogValue = CFE_PSP_WATCHDOG_MAX; +bool watchdog_enabled = false; +IWDG_HandleTypeDef IwdgHandle; -void CFE_PSP_WatchdogInit(void) -{ - CFE_PSP_WatchdogValue = CFE_PSP_WATCHDOG_MAX; -} +// TODO: relies on already called in main HAL_Init() and SystemClock_Config() +void CFE_PSP_WatchdogInit(void) { + __HAL_RCC_WWDG_CLK_ENABLE(); + + // Set up the IWDG handle + IwdgHandle.Instance = IWDG1; + IwdgHandle.Init.Prescaler = IWDG_PRESCALER_64; + IwdgHandle.Init.Reload = CFE_PSP_WATCHDOG_MAX; // Maximum timeout ms -void CFE_PSP_WatchdogEnable(void) -{ - /* TODO */ + // Initialize the IWDG + if (HAL_IWDG_Init(&IwdgHandle) != HAL_OK) { + return CFE_PSP_ERROR; + } } -void CFE_PSP_WatchdogDisable(void) -{ - /* TODO */ +void WatchdogTask(void *pvParameters) { + for (;;) { + if (watchdog_enabled) { + HAL_IWDG_Refresh(&IwdgHandle); + } + // Delay for a period shorter than the watchdog timeout + vTaskDelay(pdMS_TO_TICKS(1000)); + } } -void CFE_PSP_WatchdogService(void) -{ - /* TODO */ +void CFE_PSP_WatchdogEnable(void) { + xTaskCreate(WatchdogTask, "WatchdogTask", configMINIMAL_STACK_SIZE, NULL, + tskIDLE_PRIORITY, NULL); } -uint32 CFE_PSP_WatchdogGet(void) -{ - return CFE_PSP_WatchdogValue; +void CFE_PSP_WatchdogDisable(void) { watchdog_enabled = true; } + +void CFE_PSP_WatchdogService(void) { /* TODO: What to do when a timer expires */ } -void CFE_PSP_WatchdogSet(uint32 WatchdogValue) -{ - CFE_PSP_WatchdogValue = WatchdogValue; +uint32 CFE_PSP_WatchdogGet(void) { return IwdgHandle->SR; } + +void CFE_PSP_WatchdogSet(uint32 WatchdogValue) { + CFE_PSP_WatchdogDisable(); + + // Reinitialize the IWDG with new configuration + IwdgHandle.Init.Reload = WatchdogValue; + if (HAL_IWDG_Init(&IwdgHandle) != HAL_OK) { + return CFE_PSP_ERROR; + } + + Enable_Watchdog(); }