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