1 /** 2 ****************************************************************************** 3 * @file ll_sys_dp_slp.c 4 * @author MCD Application Team 5 * @brief Link Layer IP system interface deep sleep management 6 ****************************************************************************** 7 * @attention 8 * 9 * Copyright (c) 2022 STMicroelectronics. 10 * All rights reserved. 11 * 12 * This software is licensed under terms that can be found in the LICENSE file 13 * in the root directory of this software component. 14 * If no LICENSE file comes with this software, it is provided AS-IS. 15 * 16 ****************************************************************************** 17 */ 18 19 #include "linklayer_plat.h" 20 #include "ll_sys.h" 21 #include "ll_intf.h" 22 #if defined(MAC) 23 #include "platform.h" 24 #endif 25 26 /* Link Layer deep sleep status */ 27 uint8_t is_Radio_DeepSleep = 0U; 28 29 /* Link Layer deep sleep timer */ 30 os_timer_id radio_dp_slp_tmr_id = NULL; 31 32 /* Link Layer deep sleep state */ 33 ll_sys_dp_slp_state_t linklayer_dp_slp_state = LL_SYS_DP_SLP_DISABLED; 34 35 /** 36 * @brief Initialize resources to handle deep sleep entry/exit 37 * @param None 38 * @retval LL_SYS status 39 */ ll_sys_dp_slp_init(void)40ll_sys_status_t ll_sys_dp_slp_init(void) 41 { 42 ll_sys_status_t return_status = LL_SYS_ERROR; 43 44 /* Create link layer timer for handling IP DEEP SLEEP mode */ 45 radio_dp_slp_tmr_id = os_timer_create((t_timer_callbk)ll_sys_dp_slp_wakeup_evt_clbk, os_timer_once, NULL); 46 47 if (radio_dp_slp_tmr_id != NULL) 48 { 49 return_status = LL_SYS_OK; 50 } 51 52 return return_status; 53 } 54 55 /** 56 * @brief Link Layer deep sleep status getter 57 * @param None 58 * @retval Link Layer deep sleep state 59 */ ll_sys_dp_slp_get_state(void)60ll_sys_dp_slp_state_t ll_sys_dp_slp_get_state(void) 61 { 62 return linklayer_dp_slp_state; 63 } 64 65 /** 66 * @brief The Link Layer IP enters deep sleep mode 67 * @param dp_slp_duration deep sleep duration in us 68 * @retval LL_SYS status 69 */ ll_sys_dp_slp_enter(uint32_t dp_slp_duration)70ll_sys_status_t ll_sys_dp_slp_enter(uint32_t dp_slp_duration){ 71 ble_stat_t cmd_status = GENERAL_FAILURE; 72 int32_t os_status = GENERAL_FAILURE; 73 ll_sys_status_t return_status = LL_SYS_ERROR; 74 75 /* Check if deep sleep timer has to be started */ 76 if(dp_slp_duration < LL_DP_SLP_NO_WAKEUP) 77 { 78 /* Start deep sleep timer */ 79 os_status = os_timer_start(radio_dp_slp_tmr_id, LL_INTERNAL_TMR_US_TO_STEPS(dp_slp_duration)); 80 } 81 82 else 83 { 84 /* No timer started */ 85 os_status = SUCCESS; 86 } 87 88 if(os_status == SUCCESS) 89 { 90 /* Switch Link Layer IP to DEEP SLEEP mode */ 91 #if defined(BLE) 92 /* BLE & Concurrent use case */ 93 cmd_status = ll_intf_le_set_dp_slp_mode(DEEP_SLEEP_ENABLE); 94 #elif defined(MAC) 95 if (radio_set_dp_slp_mode(DEEP_SLEEP_ENABLE) == OT_ERROR_NONE) 96 { 97 cmd_status = SUCCESS; 98 } 99 #else 100 #error "neither MAC not BLE defined" 101 #endif 102 if(cmd_status == SUCCESS){ 103 linklayer_dp_slp_state = LL_SYS_DP_SLP_ENABLED; 104 return_status = LL_SYS_OK; 105 } 106 } 107 108 return return_status; 109 } 110 111 /** 112 * @brief The Link Layer IP exits deep sleep mode 113 * @param None 114 * @retval LL_SYS status 115 */ ll_sys_dp_slp_exit(void)116ll_sys_status_t ll_sys_dp_slp_exit(void){ 117 ble_stat_t cmd_status = GENERAL_FAILURE; 118 ll_sys_status_t return_status = LL_SYS_ERROR; 119 120 /* Disable radio interrupt */ 121 LINKLAYER_PLAT_DisableRadioIT(); 122 123 if(linklayer_dp_slp_state == LL_SYS_DP_SLP_DISABLED) 124 { 125 /* Radio not in sleep mode */ 126 return_status = LL_SYS_OK; 127 } 128 else 129 { 130 /* Stop the deep sleep wake-up timer if running */ 131 if(os_get_tmr_state(radio_dp_slp_tmr_id) != (os_timer_state)osTimerStopped) 132 { 133 os_timer_stop(radio_dp_slp_tmr_id); 134 } 135 136 /* Switch Link Layer IP to SLEEP mode (by deactivate DEEP SLEEP mode) */ 137 #if defined(BLE) 138 /* BLE & Concurrent use case */ 139 cmd_status = ll_intf_le_set_dp_slp_mode(DEEP_SLEEP_DISABLE); 140 #elif defined(MAC) 141 if (radio_set_dp_slp_mode(DEEP_SLEEP_DISABLE) == OT_ERROR_NONE) 142 { 143 cmd_status = SUCCESS; 144 } 145 #else 146 #error "neither MAC not BLE defined" 147 #endif 148 if(cmd_status == SUCCESS) 149 { 150 linklayer_dp_slp_state = LL_SYS_DP_SLP_DISABLED; 151 return_status = LL_SYS_OK; 152 } 153 } 154 155 /* Re-enable radio interrupt */ 156 LINKLAYER_PLAT_EnableRadioIT(); 157 158 return return_status; 159 } 160 161 /** 162 * @brief Link Layer deep sleep wake-up timer callback 163 * @param ptr_arg pointer passed through the callback 164 * @retval LL_SYS status 165 */ ll_sys_dp_slp_wakeup_evt_clbk(void const * ptr_arg)166void ll_sys_dp_slp_wakeup_evt_clbk(void const *ptr_arg){ 167 int32_t os_status = GENERAL_FAILURE; 168 169 /* Stop the Link Layer IP DEEP SLEEP wake-up timer */ 170 os_status = os_timer_stop(radio_dp_slp_tmr_id); 171 if(os_status != SUCCESS){ 172 return; 173 } 174 175 /* Link Layer IP exits from DEEP SLEEP mode */ 176 ll_sys_dp_slp_exit(); 177 } 178