/* USER CODE BEGIN Header */ /** ****************************************************************************** * @file rf_timing_synchro.c * @author MCD Application Team * @brief The RF Timing Synchronization module provides an interface to * synchronize the flash processing versus the RF activity to make * sure the RF timing is not broken ****************************************************************************** * @attention * * Copyright (c) 2024 STMicroelectronics. * All rights reserved. * * This software is licensed under terms that can be found in the LICENSE file * in the root directory of this software component. * If no LICENSE file comes with this software, it is provided AS-IS. * ****************************************************************************** */ /* USER CODE END Header */ /* Includes ------------------------------------------------------------------*/ #include #include "rf_timing_synchro.h" #include "evnt_schdlr_gnrc_if.h" #include "utilities_conf.h" #include "stm32_timer.h" #include "flash_driver.h" /* Global variables ----------------------------------------------------------*/ /* Private typedef -----------------------------------------------------------*/ /* Private defines -----------------------------------------------------------*/ /* Private macros ------------------------------------------------------------*/ /* Private variables ---------------------------------------------------------*/ #if (DISABLE_RFTS_EXT_EVNT_HNDLR == 0u) /** * @brief Pointer to time window requester's callback */ static void (*req_callback)(void); /** * @brief Indicates if a time window has already been requested or not */ static bool rfts_window_req_pending = FALSE; /** * @brief Timer used by the RFTS module to prevent time window overrun */ static UTIL_TIMER_Object_t rfts_timer; /** * @brief Firmware Link Layer external event handler */ static ext_evnt_hndl_t ext_event_handler; /* Private function prototypes -----------------------------------------------*/ static void RFTS_WindowAllowed_Callback(void); static void RFTS_Timeout_Callback(void* Argument); static uint32_t event_started_callback(ext_evnt_hndl_t evnt_hndl, uint32_t slot_durn, void* priv_data_ptr); #endif /* (DISABLE_RFTS_EXT_EVNT_HNDLR == 0u) */ /* Functions Definition ------------------------------------------------------*/ /** * @brief Request a time window to the Firmware Link Layer * @param duration: Duration in us of the time window requested * @param Callback: Callback to be called when time window is allocated * @retval RFTS_Cmd_Status_t: Success or failure of the window request */ RFTS_Cmd_Status_t RFTS_ReqWindow(uint32_t Duration, void (*Callback)(void)) { #if (DISABLE_RFTS_EXT_EVNT_HNDLR == 0u) extrnl_evnt_st_t extrnl_evnt_config; bool req_pending = false; if (Callback == NULL) { /* Prevent use of uninitialized callback */ return RFTS_WINDOW_REQ_FAILED; } /* Check no request is already pending */ UTILS_ENTER_CRITICAL_SECTION(); if (rfts_window_req_pending == true) { req_pending = true; } else { rfts_window_req_pending = true; } UTILS_EXIT_CRITICAL_SECTION(); if (req_pending == true) { /* A window request is already pending */ return RFTS_WINDOW_REQ_FAILED; } /* Register requester's callback */ req_callback = Callback; /* Submit request to Firmware Link Layer */ extrnl_evnt_config.deadline = 0; extrnl_evnt_config.strt_min = 0; extrnl_evnt_config.strt_max = 0; extrnl_evnt_config.durn_min = Duration; extrnl_evnt_config.durn_max = 0; extrnl_evnt_config.prdc_intrvl = 0; extrnl_evnt_config.priority = PRIORITY_DEFAULT; extrnl_evnt_config.blocked = STATE_NOT_BLOCKED; extrnl_evnt_config.ptr_priv = NULL; extrnl_evnt_config.evnt_strtd_cbk = &event_started_callback; extrnl_evnt_config.evnt_blckd_cbk = NULL; extrnl_evnt_config.evnt_abortd_cbk = NULL; UTIL_TIMER_Create(&rfts_timer, (Duration/1000), UTIL_TIMER_ONESHOT, &RFTS_Timeout_Callback, NULL); ext_event_handler = evnt_schdlr_rgstr_gnrc_evnt(&extrnl_evnt_config); if (ext_event_handler == NULL) { UTILS_ENTER_CRITICAL_SECTION(); rfts_window_req_pending = false; UTILS_EXIT_CRITICAL_SECTION(); return RFTS_WINDOW_REQ_FAILED; } #endif /* (DISABLE_RFTS_EXT_EVNT_HNDLR == 0u) */ return RFTS_CMD_OK; } /** * @brief Execute necessary tasks to allow the time window to be released * @param None * @retval RFTS_Cmd_Status_t: Success or error in the window release procedure */ RFTS_Cmd_Status_t RFTS_RelWindow(void) { #if (DISABLE_RFTS_EXT_EVNT_HNDLR == 0u) RFTS_Cmd_Status_t status; /* Stop RFTS module window overrun control timer */ UTIL_TIMER_Stop(&rfts_timer); /* Inform Firmware Link Layer that time window can be released */ if (evnt_schdlr_gnrc_evnt_cmplt(ext_event_handler) == 0) { status = RFTS_CMD_OK; } else { status = RFTS_WINDOW_REL_ERROR; } /* Forbid flash operation */ FD_SetStatus(FD_FLASHACCESS_RFTS, LL_FLASH_DISABLE); UTILS_ENTER_CRITICAL_SECTION(); rfts_window_req_pending = false; UTILS_EXIT_CRITICAL_SECTION(); return status; #else return RFTS_CMD_OK; #endif /* (DISABLE_RFTS_EXT_EVNT_HNDLR == 0u) */ } #if (DISABLE_RFTS_EXT_EVNT_HNDLR == 0u) /** * @brief Callback called by Firmware Link Layer when a time window is available * @note This callback is supposed to be called under interrupt * @param None * @retval None */ static void RFTS_WindowAllowed_Callback(void) { /* Allow flash operation */ FD_SetStatus(FD_FLASHACCESS_RFTS, LL_FLASH_ENABLE); /* Start timer preventing window overrun */ UTIL_TIMER_Start(&rfts_timer); /* Call back requester to inform time window is available */ req_callback(); } /** * @brief Callback triggered by a timeout when the allocated window time is elapsed * @note This callback is supposed to be called under interrupt * @param None * @retval None */ static void RFTS_Timeout_Callback(void* Argument) { /* Forbid flash operation */ FD_SetStatus(FD_FLASHACCESS_RFTS, LL_FLASH_DISABLE); UTILS_ENTER_CRITICAL_SECTION(); rfts_window_req_pending = false; UTILS_EXIT_CRITICAL_SECTION(); } static uint32_t event_started_callback(ext_evnt_hndl_t evnt_hndl, uint32_t slot_durn, void* priv_data_ptr) { RFTS_WindowAllowed_Callback(); return 0; } #endif /* (DISABLE_RFTS_EXT_EVNT_HNDLR == 0u) */