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_cmn.h" 22 23 /* Link Layer deep sleep status */ 24 uint8_t is_Radio_DeepSleep = 0U; 25 26 /* Link Layer deep sleep timer */ 27 os_timer_id radio_dp_slp_tmr_id = NULL; 28 29 /* Link Layer deep sleep state */ 30 ll_sys_dp_slp_state_t linklayer_dp_slp_state = LL_SYS_DP_SLP_DISABLED; 31 32 /** 33 * @brief Initialize resources to handle deep sleep entry/exit 34 * @param None 35 * @retval LL_SYS status 36 */ ll_sys_dp_slp_init(void)37ll_sys_status_t ll_sys_dp_slp_init(void) 38 { 39 ll_sys_status_t return_status = LL_SYS_ERROR; 40 41 /* Create link layer timer for handling IP DEEP SLEEP mode */ 42 radio_dp_slp_tmr_id = os_timer_create((t_timer_callbk)ll_sys_dp_slp_wakeup_evt_clbk, os_timer_once, NULL); 43 44 /* Set priority of deep sleep timer */ 45 os_timer_set_prio(radio_dp_slp_tmr_id, hg_prio_tmr); 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; 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 cmd_status = ll_intf_cmn_le_set_dp_slp_mode(DEEP_SLEEP_ENABLE); 92 if(cmd_status == SUCCESS){ 93 linklayer_dp_slp_state = LL_SYS_DP_SLP_ENABLED; 94 return_status = LL_SYS_OK; 95 } 96 } 97 98 return return_status; 99 } 100 101 /** 102 * @brief The Link Layer IP exits deep sleep mode 103 * @param None 104 * @retval LL_SYS status 105 */ ll_sys_dp_slp_exit(void)106ll_sys_status_t ll_sys_dp_slp_exit(void){ 107 ble_stat_t cmd_status; 108 ll_sys_status_t return_status = LL_SYS_ERROR; 109 110 /* Disable radio interrupt */ 111 LINKLAYER_PLAT_DisableRadioIT(); 112 113 if(linklayer_dp_slp_state == LL_SYS_DP_SLP_DISABLED) 114 { 115 /* Radio not in sleep mode */ 116 return_status = LL_SYS_OK; 117 } 118 else 119 { 120 /* Stop the deep sleep wake-up timer if running */ 121 if(os_get_tmr_state(radio_dp_slp_tmr_id) != (os_timer_state)osTimerStopped) 122 { 123 os_timer_stop(radio_dp_slp_tmr_id); 124 } 125 126 /* Switch Link Layer IP to SLEEP mode (by deactivate DEEP SLEEP mode) */ 127 cmd_status = ll_intf_cmn_le_set_dp_slp_mode(DEEP_SLEEP_DISABLE); 128 if(cmd_status == SUCCESS) 129 { 130 linklayer_dp_slp_state = LL_SYS_DP_SLP_DISABLED; 131 return_status = LL_SYS_OK; 132 } 133 } 134 135 /* Re-enable radio interrupt */ 136 LINKLAYER_PLAT_EnableRadioIT(); 137 138 return return_status; 139 } 140 141 /** 142 * @brief Link Layer deep sleep wake-up timer callback 143 * @param ptr_arg pointer passed through the callback 144 * @retval LL_SYS status 145 */ ll_sys_dp_slp_wakeup_evt_clbk(void const * ptr_arg)146void ll_sys_dp_slp_wakeup_evt_clbk(void const *ptr_arg){ 147 int32_t os_status; 148 149 /* Stop the Link Layer IP DEEP SLEEP wake-up timer */ 150 os_status = os_timer_stop(radio_dp_slp_tmr_id); 151 if(os_status != SUCCESS){ 152 return; 153 } 154 155 /* Link Layer IP exits from DEEP SLEEP mode */ 156 ll_sys_dp_slp_exit(); 157 } 158