1 /*! ********************************************************************************* 2 * Copyright (c) 2015, Freescale Semiconductor, Inc. 3 * Copyright 2018-2022 NXP 4 * All rights reserved. 5 * 6 * \file 7 * 8 * SPDX-License-Identifier: BSD-3-Clause 9 ********************************************************************************** */ 10 11 #include "Phy.h" 12 #include "PhyTime.h" 13 #include "EmbeddedTypes.h" 14 15 #include "fsl_os_abstraction.h" 16 #include "fsl_device_registers.h" 17 18 #define gPhyTimeMinSetupTime_c (4) /* symbols */ 19 20 static phyTimeEvent_t maPhyTimers[gMaxPhyTimers_c]; 21 static phyTimeEvent_t *pNextEvent; 22 volatile uint64_t gPhyTimerOverflow; 23 static uint8_t mPhyActiveTimers; 24 static bool bTimerInitDone = false; 25 static void (*gpfPhyTimeNotify)(void) = NULL; 26 27 static void PhyTime_OverflowCB(uint32_t param); 28 static phyTimeEvent_t *PhyTime_GetNextEvent(void); 29 30 PhyTimeGetEventTimeout(void)31phyTime_t PhyTimeGetEventTimeout(void) 32 { 33 return ZLL->T3CMP; 34 } 35 PhyTime_ReadClock()36phyTime_t PhyTime_ReadClock() 37 { 38 return (phyTime_t)(ZLL->EVENT_TMR >> ZLL_EVENT_TMR_EVENT_TMR_SHIFT); 39 } 40 PhyTime_ISR(void)41void PhyTime_ISR(void) 42 { 43 if (pNextEvent->callback == PhyTime_OverflowCB) 44 { 45 gPhyTimerOverflow += (uint64_t)(1 << gPhyTimeShift_c); 46 } 47 48 if (gpfPhyTimeNotify) 49 { 50 gpfPhyTimeNotify(); 51 } 52 else 53 { 54 PhyTime_RunCallback(); 55 PhyTime_Maintenance(); 56 } 57 } 58 PhyTime_TimerInit(void (* cb)(void))59phyTimeStatus_t PhyTime_TimerInit(void (*cb)(void)) 60 { 61 // Check whether timer has already been initialised 62 if (bTimerInitDone == true) 63 { 64 return gPhyTimeError_c; 65 } 66 67 gpfPhyTimeNotify = cb; 68 gPhyTimerOverflow = 0; 69 memset(maPhyTimers, 0, sizeof(maPhyTimers)); 70 71 /* Schedule Overflow Calback */ 72 pNextEvent = &maPhyTimers[0]; 73 pNextEvent->callback = PhyTime_OverflowCB; 74 pNextEvent->timestamp = (uint64_t)(1 << gPhyTimeShift_c); 75 PhyTimeSetWaitTimeout(pNextEvent->timestamp); 76 mPhyActiveTimers = 1; 77 78 // indicate that phytimer layer is initialized 79 bTimerInitDone = true; 80 81 return gPhyTimeOk_c; 82 } 83 PhyTime_TimerDeinit(void)84void PhyTime_TimerDeinit ( void ) 85 { 86 bTimerInitDone = false; 87 gpfPhyTimeNotify = NULL; 88 } 89 PhyTime_GetTimestamp(void)90phyTime_t PhyTime_GetTimestamp(void) 91 { 92 phyTime_t t; 93 94 OSA_InterruptDisable(); 95 t = PhyTime_ReadClock(); 96 t |= gPhyTimerOverflow; 97 /* Check for overflow */ 98 if(pNextEvent != NULL) 99 { 100 if (pNextEvent->callback == PhyTime_OverflowCB) 101 { 102 if (ZLL->IRQSTS & ZLL_IRQSTS_TMR1IRQ_MASK) 103 { 104 t = PhyTime_ReadClock(); 105 t |= gPhyTimerOverflow; 106 t += (1 << gPhyTimeShift_c); 107 } 108 } 109 } 110 OSA_InterruptEnable(); 111 112 return t; 113 } 114 PhyTime_ScheduleEvent(phyTimeEvent_t * pEvent)115phyTimeTimerId_t PhyTime_ScheduleEvent(phyTimeEvent_t *pEvent) 116 { 117 phyTimeTimerId_t tmr; 118 119 if (NULL == pEvent->callback) 120 { 121 return gInvalidTimerId_c; 122 } 123 124 /* Search for a free slot (slot 0 is reserved for the Overflow calback) */ 125 OSA_InterruptDisable(); 126 for (tmr = 1; tmr < gMaxPhyTimers_c; tmr++) 127 { 128 if (maPhyTimers[tmr].callback == NULL) 129 { 130 if (mPhyActiveTimers == 1) 131 { 132 /* PHY_disallow_sleep(); */ 133 } 134 135 mPhyActiveTimers++; 136 maPhyTimers[tmr] = *pEvent; 137 break; 138 } 139 } 140 OSA_InterruptEnable(); 141 142 if (tmr >= gMaxPhyTimers_c) 143 { 144 return gInvalidTimerId_c; 145 } 146 147 /* Program the next event */ 148 if ((NULL == pNextEvent) || ((NULL != pNextEvent) && (maPhyTimers[tmr].timestamp < pNextEvent->timestamp))) 149 { 150 PhyTime_Maintenance(); 151 } 152 153 return tmr; 154 } 155 PhyTime_CancelEvent(phyTimeTimerId_t timerId)156phyTimeStatus_t PhyTime_CancelEvent(phyTimeTimerId_t timerId) 157 { 158 if ((timerId == 0) || (timerId >= gMaxPhyTimers_c) || (NULL == maPhyTimers[timerId].callback)) 159 { 160 return gPhyTimeNotFound_c; 161 } 162 163 OSA_InterruptDisable(); 164 if (pNextEvent == &maPhyTimers[timerId]) 165 { 166 pNextEvent = NULL; 167 } 168 169 maPhyTimers[timerId].callback = NULL; 170 mPhyActiveTimers--; 171 172 if (mPhyActiveTimers == 1) 173 { 174 /* PHY_allow_sleep(); */ 175 } 176 177 OSA_InterruptEnable(); 178 179 return gPhyTimeOk_c; 180 } 181 PhyTime_CancelEventsWithParam(uint32_t param)182phyTimeStatus_t PhyTime_CancelEventsWithParam(uint32_t param) 183 { 184 uint32_t i; 185 phyTimeStatus_t status = gPhyTimeNotFound_c; 186 187 OSA_InterruptDisable(); 188 for (i = 1; i < gMaxPhyTimers_c; i++) 189 { 190 if ((NULL != maPhyTimers[i].callback) && (param == maPhyTimers[i].parameter)) 191 { 192 status = gPhyTimeOk_c; 193 maPhyTimers[i].callback = NULL; 194 mPhyActiveTimers--; 195 196 if (pNextEvent == &maPhyTimers[i]) 197 { 198 pNextEvent = NULL; 199 } 200 } 201 } 202 203 if (mPhyActiveTimers == 1) 204 { 205 /* PHY_allow_sleep(); */ 206 } 207 OSA_InterruptEnable(); 208 209 return status; 210 } 211 PhyTime_RunCallback(void)212void PhyTime_RunCallback(void) 213 { 214 /* for V18 compiler, variable need be given initial value */ 215 uint32_t param =0; 216 phyTimeCallback_t cb = NULL; 217 218 OSA_InterruptDisable(); 219 220 if (pNextEvent) 221 { 222 param = pNextEvent->parameter; 223 cb = pNextEvent->callback; 224 pNextEvent->callback = NULL; 225 pNextEvent = NULL; 226 mPhyActiveTimers--; 227 228 if (mPhyActiveTimers == 1) 229 { 230 /* PHY_allow_sleep(); */ 231 } 232 } 233 234 OSA_InterruptEnable(); 235 236 if (cb) 237 { 238 cb(param); 239 } 240 } 241 PhyTime_Maintenance(void)242void PhyTime_Maintenance(void) 243 { 244 phyTime_t currentTime; 245 phyTimeEvent_t *pEv; 246 247 PhyTimeDisableWaitTimeout(); 248 249 while (1) 250 { 251 OSA_InterruptDisable(); 252 253 pEv = PhyTime_GetNextEvent(); 254 currentTime = PhyTime_GetTimestamp(); 255 256 /* Program next event if exists */ 257 if (pEv) 258 { 259 pNextEvent = pEv; 260 261 if (pEv->timestamp > (currentTime + gPhyTimeMinSetupTime_c)) 262 { 263 PhyTimeSetWaitTimeout(pEv->timestamp); 264 pEv = NULL; 265 } 266 } 267 268 OSA_InterruptEnable(); 269 270 if (!pEv) 271 { 272 break; 273 } 274 275 PhyTime_RunCallback(); 276 } 277 } 278 PhyTime_OverflowCB(uint32_t param)279static void PhyTime_OverflowCB(uint32_t param) 280 { 281 param = param; 282 283 /* Reprogram the next overflow callback */ 284 OSA_InterruptDisable(); 285 mPhyActiveTimers++; 286 maPhyTimers[0].callback = PhyTime_OverflowCB; 287 maPhyTimers[0].timestamp = gPhyTimerOverflow + (1 << gPhyTimeShift_c); 288 OSA_InterruptEnable(); 289 } 290 PhyTime_GetNextEvent(void)291static phyTimeEvent_t *PhyTime_GetNextEvent(void) 292 { 293 phyTimeEvent_t *pEv = NULL; 294 uint32_t i; 295 296 /* Search for the next event to be serviced */ 297 for (i = 0; i < gMaxPhyTimers_c; i++) 298 { 299 if (NULL != maPhyTimers[i].callback) 300 { 301 if (NULL == pEv) 302 { 303 pEv = &maPhyTimers[i]; 304 } 305 /* Check which event expires first */ 306 else 307 { 308 if (maPhyTimers[i].timestamp < pEv->timestamp) 309 { 310 pEv = &maPhyTimers[i]; 311 } 312 } 313 } 314 } 315 316 return pEv; 317 } 318 PhyTime_can_sleep()319bool_t PhyTime_can_sleep() 320 { 321 return (mPhyActiveTimers == 1); 322 } 323