1 /* USER CODE BEGIN Header */
2 /**
3   ******************************************************************************
4   * @file    rf_timing_synchro.c
5   * @author  MCD Application Team
6   * @brief   The RF Timing Synchronization module provides an interface to
7   *          synchronize the flash processing versus the RF activity to make
8   *          sure the RF timing is not broken
9   ******************************************************************************
10   * @attention
11   *
12   * Copyright (c) 2022 STMicroelectronics.
13   * All rights reserved.
14   *
15   * This software is licensed under terms that can be found in the LICENSE file
16   * in the root directory of this software component.
17   * If no LICENSE file comes with this software, it is provided AS-IS.
18   *
19   ******************************************************************************
20   */
21 /* USER CODE END Header */
22 
23 /* Includes ------------------------------------------------------------------*/
24 #include <stdbool.h>
25 
26 #include "rf_timing_synchro.h"
27 #include "evnt_schdlr_gnrc_if.h"
28 #include "utilities_conf.h"
29 #include "stm32_timer.h"
30 #include "flash_driver.h"
31 
32 /* Global variables ----------------------------------------------------------*/
33 /* Private typedef -----------------------------------------------------------*/
34 /* Private defines -----------------------------------------------------------*/
35 /* Private macros ------------------------------------------------------------*/
36 /* Private variables ---------------------------------------------------------*/
37 
38 #if (DISABLE_RFTS_EXT_EVNT_HNDLR == 0u)
39 /**
40   * @brief Pointer to time window requester's callback
41   */
42 static void (*req_callback)(void);
43 
44 /**
45   * @brief Indicates if a time window has already been requested or not
46   */
47 static bool rfts_window_req_pending = FALSE;
48 
49 /**
50   * @brief Timer used by the RFTS module to prevent time window overrun
51   */
52 static UTIL_TIMER_Object_t rfts_timer;
53 
54 /**
55   * @brief Firmware Link Layer external event handler
56   */
57 static ext_evnt_hndl_t ext_event_handler;
58 
59 /* Private function prototypes -----------------------------------------------*/
60 
61 static void RFTS_WindowAllowed_Callback(void);
62 static void RFTS_Timeout_Callback(void* Argument);
63 static uint32_t event_started_callback(ext_evnt_hndl_t evnt_hndl, uint32_t slot_durn, void* priv_data_ptr);
64 #endif /* (DISABLE_RFTS_EXT_EVNT_HNDLR == 0u) */
65 
66 /* Functions Definition ------------------------------------------------------*/
67 
68 /**
69   * @brief  Request a time window to the Firmware Link Layer
70   * @param  duration: Duration in us of the time window requested
71   * @param  Callback: Callback to be called when time window is allocated
72   * @retval RFTS_Cmd_Status_t: Success or failure of the window request
73   */
RFTS_ReqWindow(uint32_t Duration,void (* Callback)(void))74 RFTS_Cmd_Status_t RFTS_ReqWindow(uint32_t Duration, void (*Callback)(void))
75 {
76 #if (DISABLE_RFTS_EXT_EVNT_HNDLR == 0u)
77   extrnl_evnt_st_t extrnl_evnt_config;
78   bool req_pending = false;
79 
80   if (Callback == NULL)
81   { /* Prevent use of uninitialized callback */
82     return RFTS_WINDOW_REQ_FAILED;
83   }
84 
85   /* Check no request is already pending */
86   UTILS_ENTER_CRITICAL_SECTION();
87   if (rfts_window_req_pending == true)
88   {
89     req_pending = true;
90   }
91   else
92   {
93     rfts_window_req_pending = true;
94   }
95   UTILS_EXIT_CRITICAL_SECTION();
96   if (req_pending == true)
97   { /* A window request is already pending */
98     return RFTS_WINDOW_REQ_FAILED;
99   }
100 
101   /* Register requester's callback */
102   req_callback = Callback;
103 
104   /* Submit request to Firmware Link Layer */
105   extrnl_evnt_config.deadline = 0;
106   extrnl_evnt_config.strt_min = 0;
107   extrnl_evnt_config.strt_max = 0;
108   extrnl_evnt_config.durn_min = Duration;
109   extrnl_evnt_config.durn_max = 0;
110   extrnl_evnt_config.prdc_intrvl = 0;
111   extrnl_evnt_config.priority = PRIORITY_DEFAULT;
112   extrnl_evnt_config.blocked = STATE_NOT_BLOCKED;
113   extrnl_evnt_config.ptr_priv = NULL;
114   extrnl_evnt_config.evnt_strtd_cbk = &event_started_callback;
115   extrnl_evnt_config.evnt_blckd_cbk = NULL;
116   extrnl_evnt_config.evnt_abortd_cbk = NULL;
117 
118   UTIL_TIMER_Create(&rfts_timer,
119                     (Duration/1000),
120                     UTIL_TIMER_ONESHOT,
121                     &RFTS_Timeout_Callback,
122                     NULL);
123 
124   ext_event_handler = evnt_schdlr_rgstr_gnrc_evnt(&extrnl_evnt_config);
125   if (ext_event_handler == NULL)
126   {
127     UTILS_ENTER_CRITICAL_SECTION();
128     rfts_window_req_pending = false;
129     UTILS_EXIT_CRITICAL_SECTION();
130 
131     return RFTS_WINDOW_REQ_FAILED;
132   }
133 #endif /* (DISABLE_RFTS_EXT_EVNT_HNDLR == 0u) */
134 
135   return RFTS_CMD_OK;
136 }
137 
138 /**
139   * @brief  Execute necessary tasks to allow the time window to be released
140   * @param  None
141   * @retval RFTS_Cmd_Status_t: Success or error in the window release procedure
142   */
RFTS_RelWindow(void)143 RFTS_Cmd_Status_t RFTS_RelWindow(void)
144 {
145 #if (DISABLE_RFTS_EXT_EVNT_HNDLR == 0u)
146   RFTS_Cmd_Status_t status;
147 
148   /* Stop RFTS module window overrun control timer */
149   UTIL_TIMER_Stop(&rfts_timer);
150 
151   /* Inform Firmware Link Layer that time window can be released */
152   if (evnt_schdlr_gnrc_evnt_cmplt(ext_event_handler) == 0)
153   {
154     status = RFTS_CMD_OK;
155   }
156   else
157   {
158     status = RFTS_WINDOW_REL_ERROR;
159   }
160 
161   /* Forbid flash operation */
162   FD_SetStatus(FD_FLASHACCESS_RFTS, LL_FLASH_DISABLE);
163 
164   UTILS_ENTER_CRITICAL_SECTION();
165   rfts_window_req_pending = false;
166   UTILS_EXIT_CRITICAL_SECTION();
167 
168   return status;
169 #else
170   return RFTS_CMD_OK;
171 #endif /* (DISABLE_RFTS_EXT_EVNT_HNDLR == 0u) */
172 }
173 
174 #if (DISABLE_RFTS_EXT_EVNT_HNDLR == 0u)
175 /**
176   * @brief  Callback called by Firmware Link Layer when a time window is available
177   * @note   This callback is supposed to be called under interrupt
178   * @param  None
179   * @retval None
180   */
RFTS_WindowAllowed_Callback(void)181 static void RFTS_WindowAllowed_Callback(void)
182 {
183   /* Allow flash operation */
184   FD_SetStatus(FD_FLASHACCESS_RFTS, LL_FLASH_ENABLE);
185 
186   /* Start timer preventing window overrun */
187   UTIL_TIMER_Start(&rfts_timer);
188 
189   /* Call back requester to inform time window is available */
190   req_callback();
191 }
192 
193 /**
194   * @brief  Callback triggered by a timeout when the allocated window time is elapsed
195   * @note   This callback is supposed to be called under interrupt
196   * @param  None
197   * @retval None
198   */
RFTS_Timeout_Callback(void * Argument)199 static void RFTS_Timeout_Callback(void* Argument)
200 {
201   /* Forbid flash operation */
202   FD_SetStatus(FD_FLASHACCESS_RFTS, LL_FLASH_DISABLE);
203 
204   UTILS_ENTER_CRITICAL_SECTION();
205   rfts_window_req_pending = false;
206   UTILS_EXIT_CRITICAL_SECTION();
207 }
208 
event_started_callback(ext_evnt_hndl_t evnt_hndl,uint32_t slot_durn,void * priv_data_ptr)209 static uint32_t event_started_callback(ext_evnt_hndl_t evnt_hndl, uint32_t slot_durn, void* priv_data_ptr)
210 {
211   RFTS_WindowAllowed_Callback();
212   return 0;
213 }
214 #endif /* (DISABLE_RFTS_EXT_EVNT_HNDLR == 0u) */
215