power_demo.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427
  1. /*================================================================
  2. Copyright (c) 2021, Quectel Wireless Solutions Co., Ltd. All rights reserved.
  3. Quectel Wireless Solutions Proprietary and Confidential.
  4. =================================================================*/
  5. /*=================================================================
  6. EDIT HISTORY FOR MODULE
  7. This section contains comments describing changes made to the module.
  8. Notice that changes are listed in reverse chronological order.
  9. WHEN WHO WHAT, WHERE, WHY
  10. ------------ ------- -------------------------------------------------------------------------------
  11. =================================================================*/
  12. /*===========================================================================
  13. * include files
  14. ===========================================================================*/
  15. #include <stdio.h>
  16. #include <string.h>
  17. #include <stdlib.h>
  18. #include "ql_api_osi.h"
  19. #include "ql_log.h"
  20. #include "ql_pin_cfg.h"
  21. #include "power_demo.h"
  22. #ifdef QL_APP_FEATURE_USB
  23. #include "ql_usb.h"
  24. #endif
  25. /*===========================================================================
  26. * Macro Definition
  27. ===========================================================================*/
  28. #define QL_POWERDEMO_LOG_LEVEL QL_LOG_LEVEL_INFO
  29. #define QL_POWERDEMO_LOG(msg, ...) QL_LOG(QL_POWERDEMO_LOG_LEVEL, "ql_POWER", msg, ##__VA_ARGS__)
  30. #define QL_POWERDEMO_LOG_PUSH(msg, ...) QL_LOG_PUSH("ql_POWER", msg, ##__VA_ARGS__)
  31. #if !defined(require_action)
  32. #define require_action(x, action, str) \
  33. do \
  34. { \
  35. if(x != 0) \
  36. { \
  37. QL_POWERDEMO_LOG(str); \
  38. {action;} \
  39. } \
  40. } while( 1==0 )
  41. #endif
  42. /*===========================================================================
  43. * Variate
  44. ===========================================================================*/
  45. ql_task_t power_task = NULL;
  46. ql_timer_t power_timer = NULL;
  47. int wake_lock_1, wake_lock_2;
  48. ql_task_t pwrkey_task = NULL;
  49. /* awakening source */
  50. uint resume_src[] = {
  51. QUEC_RESUME_SRC_PMIC,
  52. QUEC_RESUME_SRC_VAD,
  53. QUEC_RESUME_SRC_KEY,
  54. QUEC_RESUME_SRC_GPIO1,
  55. QUEC_RESUME_SRC_UART1,
  56. QUEC_RESUME_SRC_WCN2SYS,
  57. QUEC_RESUME_SRC_WCN_OSC,
  58. QUEC_RESUME_SRC_IDLE_TIMER1,
  59. QUEC_RESUME_SRC_IDLE_TIMER2,
  60. QUEC_RESUME_SRC_SELF,
  61. QUEC_RESUME_SRC_USB_MON,
  62. };
  63. /*===========================================================================
  64. * Functions
  65. ===========================================================================*/
  66. //Sleep callback function is executed before sleep, custom can close some pins to reduce leakage or saving some information in here
  67. //Caution:callback functions cannot run too much code
  68. void ql_enter_sleep_cb(void* ctx)
  69. {
  70. //QL_POWERDEMO_LOG("enter sleep cb");
  71. }
  72. #if 0
  73. /*
  74. If you get the wake-up source, you can open this interface function.
  75. */
  76. void ql_wakeup_source_handle(uint all_source)
  77. {
  78. int i = 0;
  79. while(i<(sizeof(resume_src)/sizeof(uint)))
  80. {
  81. uint source = all_source & resume_src[i];
  82. i++;
  83. if(!source)
  84. {
  85. continue;
  86. }
  87. switch (source)
  88. {
  89. /* The wake-up call source is pmic */
  90. /* The wake-up source of pmic also prints the gpio wake-up source, so you can ignore the gpio wake-up source. */
  91. case QUEC_RESUME_SRC_PMIC:
  92. QL_POWERDEMO_LOG("wakeup from pmic");
  93. break;
  94. /* Not used, no need to pay attention to */
  95. case QUEC_RESUME_SRC_VAD:
  96. QL_POWERDEMO_LOG("wakeup from vad");
  97. break;
  98. /* The wake-up call source is keyboard */
  99. case QUEC_RESUME_SRC_KEY:
  100. QL_POWERDEMO_LOG("wakeup from key");
  101. break;
  102. /* The wake-up call source is Gpio interrupt */
  103. case QUEC_RESUME_SRC_GPIO1:
  104. QL_POWERDEMO_LOG("wakeup from Gpio interrupt");
  105. break;
  106. /* The wake-up call source is uart1 */
  107. case QUEC_RESUME_SRC_UART1:
  108. QL_POWERDEMO_LOG("wakeup from uart1");
  109. break;
  110. /* The wake-up call source is Bluetooth system */
  111. case QUEC_RESUME_SRC_WCN2SYS:
  112. QL_POWERDEMO_LOG("wakeup from Bluetooth system");
  113. break;
  114. /* The wake-up call source is Bluetooth osc */
  115. case QUEC_RESUME_SRC_WCN_OSC:
  116. QL_POWERDEMO_LOG("wakeup from Bluetooth osc");
  117. break;
  118. /* The wake-up call source is cp timer */
  119. /* The service on the cp side wakes up, and the specific service cannot be specified. */
  120. /* It can only be determined by combining with cp log. */
  121. case QUEC_RESUME_SRC_IDLE_TIMER1:
  122. QL_POWERDEMO_LOG("wakeup from cp timer");
  123. break;
  124. /* The wake-up call source is ap timer */
  125. /* There are two wake-up, timer, and ql_rtos_task_sleep interfaces */
  126. /* It is impossible to further determine which awakening */
  127. case QUEC_RESUME_SRC_IDLE_TIMER2:
  128. QL_POWERDEMO_LOG("wakeup from ap timer");
  129. break;
  130. /* Not used, no need to pay attention to */
  131. case QUEC_RESUME_SRC_SELF:
  132. QL_POWERDEMO_LOG("wakeup from self");
  133. break;
  134. /* Not used, no need to pay attention to */
  135. case QUEC_RESUME_SRC_USB_MON:
  136. QL_POWERDEMO_LOG("wakeup from usb");
  137. break;
  138. default:
  139. QL_POWERDEMO_LOG("wakeup from default");
  140. break;
  141. }
  142. }
  143. }
  144. #endif
  145. //exit sleep callback function is executed after exiting sleep, custom can recover the information before sleep
  146. //Caution:callback functions cannot run too much code
  147. void ql_exit_sleep_cb(void* ctx)
  148. {
  149. //QL_POWERDEMO_LOG("exit sleep cb");
  150. /*
  151. If you want to get the wake-up source, you can open this interface function.
  152. This function does not necessarily need to be called in this callback function.
  153. */
  154. // uint source = ql_get_wakeup_source();
  155. // ql_wakeup_source_handle(source);
  156. }
  157. #ifdef QL_APP_FEATURE_USB
  158. int usb_hotplug_cb(QL_USB_HOTPLUG_E state, void *ctx)
  159. {
  160. if(state == QL_USB_HOTPLUG_OUT)
  161. {
  162. QL_POWERDEMO_LOG("USB plug out");
  163. }
  164. else
  165. {
  166. QL_POWERDEMO_LOG("USB inserted");
  167. }
  168. return 0;
  169. }
  170. #endif
  171. static void ql_power_demo_thread(void *param)
  172. {
  173. //QL_POWERDEMO_LOG("power demo thread enter, param 0x%x", param);
  174. ql_event_t event;
  175. int err;
  176. //register sleep callback function
  177. ql_sleep_register_cb(ql_enter_sleep_cb);
  178. //register wakeup callback function
  179. ql_wakeup_register_cb(ql_exit_sleep_cb);
  180. #ifdef QL_APP_FEATURE_USB
  181. //register usb hotplug callback function
  182. ql_usb_bind_hotplug_cb(usb_hotplug_cb);
  183. #endif
  184. while(1)
  185. {
  186. if(ql_event_try_wait(&event) != 0)
  187. {
  188. continue;
  189. }
  190. QL_POWERDEMO_LOG("receive event, id is %d", event.id);
  191. switch(event.id)
  192. {
  193. case QUEC_SLEEP_ENETR_AUTO_SLEPP:
  194. err = ql_autosleep_enable(QL_ALLOW_SLEEP);
  195. if( err != 0 )
  196. {
  197. QL_POWERDEMO_LOG("failed to set auto sleep");
  198. break;
  199. }
  200. err = ql_lpm_wakelock_unlock(wake_lock_1);
  201. if( err != 0 )
  202. {
  203. QL_POWERDEMO_LOG("lock1 unlocked failed");
  204. break;
  205. }
  206. err = ql_lpm_wakelock_unlock(wake_lock_2);
  207. if( err != 0 )
  208. {
  209. QL_POWERDEMO_LOG("lock2 unlocked failed");
  210. break;
  211. }
  212. QL_POWERDEMO_LOG("set auto sleep mode ok");
  213. break;
  214. case QUEC_SLEEP_EXIT_AUTO_SLEPP:
  215. err = ql_autosleep_enable(QL_NOT_ALLOW_SLEEP);
  216. if( err != 0 )
  217. {
  218. QL_POWERDEMO_LOG("failed to set auto sleep");
  219. break;
  220. }
  221. break;
  222. case QUEC_SLEEP_QUICK_POWER_DOWM:
  223. ql_power_down(POWD_IMMDLY);
  224. break;
  225. case QUEC_SLEEP_NORMAL_POWER_DOWM:
  226. ql_power_down(POWD_NORMAL);
  227. break;
  228. case QUEC_SLEEP_QUICK_RESET:
  229. ql_power_reset(RESET_QUICK);
  230. break;
  231. case QUEC_SLEEP_NORMAL_RESET:
  232. ql_power_reset(RESET_NORMAL);
  233. break;
  234. default:
  235. break;
  236. }
  237. }
  238. ql_rtos_task_delete(NULL);
  239. }
  240. void power_timer_callback(void *ctx)
  241. {
  242. ql_event_t event = {0};
  243. event.id = QUEC_SLEEP_ENETR_AUTO_SLEPP;
  244. ql_rtos_event_send(power_task, &event);
  245. }
  246. void ql_power_app_init(void)
  247. {
  248. QlOSStatus err = QL_OSI_SUCCESS;
  249. err = ql_rtos_task_create(&power_task, 1024, APP_PRIORITY_NORMAL, "ql_powerdemo", ql_power_demo_thread, NULL, 3);
  250. require_action(err, return, "power demo task created failed");
  251. // err = ql_rtos_timer_create(&power_timer, power_task, power_timer_callback, NULL);
  252. // require_action(err, return, "demo_timer created failed");
  253. // err = ql_rtos_timer_start(power_timer, 1000, 0); // 1秒后开启自动休眠
  254. // require_action(err, return, "demo_timer start failed");
  255. // wake_lock_1 = ql_lpm_wakelock_create("my_lock_1", 10);
  256. // require_action((wake_lock_1 <= 0), return, "lock1 created failed");
  257. // wake_lock_2 = ql_lpm_wakelock_create("my_lock_2", 10);
  258. // require_action((wake_lock_2 <= 0), return, "lock2 created failed");
  259. // err = ql_lpm_wakelock_lock(wake_lock_1);
  260. // require_action(err, return, "lock1 locked failed");
  261. // err = ql_lpm_wakelock_lock(wake_lock_2);
  262. // require_action(err, return, "lock2 locked failed");
  263. }
  264. /***** pwrkey demo *****/
  265. static void _pwrkey_demo_callback(void)
  266. {
  267. ql_event_t event;
  268. event.id = QUEC_PWRKEY_SHUTDOWN_START_IND;
  269. ql_rtos_event_send(pwrkey_task, &event);
  270. }
  271. static void _pwrkey_longpress_callback(void)
  272. {
  273. ql_event_t event;
  274. event.id = QUEC_PWRKEY_LONGPRESS_IND;
  275. ql_rtos_event_send(pwrkey_task, &event);
  276. }
  277. static void _pwrkey_press_callback(void)
  278. {
  279. ql_event_t event;
  280. event.id = QUEC_PWRKEY_PRESS_IND;
  281. ql_rtos_event_send(pwrkey_task, &event);
  282. }
  283. static void _pwrkey_release_callback(void)
  284. {
  285. ql_event_t event;
  286. event.id = QUEC_PWRKEY_RELEASE_IND;
  287. ql_rtos_event_send(pwrkey_task, &event);
  288. }
  289. static void ql_pwrkey_demo_thread(void *param)
  290. {
  291. //QL_POWERDEMO_LOG("pwrkey demo thread enter, param 0x%x", param);
  292. ql_event_t event;
  293. ql_pwrkey_shutdown_time_set(3000); // long pressed 3s shutdown
  294. ql_pwrkey_callback_register(_pwrkey_demo_callback); // long press & release trigger
  295. ql_pwrkey_longpress_cb_register(_pwrkey_longpress_callback, 7000); // long press & not release, long pressed 7s trigger
  296. ql_pwrkey_press_cb_register(_pwrkey_press_callback);
  297. ql_pwrkey_release_cb_register(_pwrkey_release_callback);
  298. while(1)
  299. {
  300. if(ql_event_try_wait(&event) != 0)
  301. {
  302. continue;
  303. }
  304. switch(event.id)
  305. {
  306. case QUEC_PWRKEY_SHUTDOWN_START_IND:
  307. QL_POWERDEMO_LOG("customer process");
  308. /* do something */
  309. ql_power_down(POWD_NORMAL);
  310. break;
  311. case QUEC_PWRKEY_LONGPRESS_IND:
  312. QL_POWERDEMO_LOG("pwrkey long press trigger");
  313. /* do something */
  314. ql_power_reset(RESET_NORMAL);
  315. break;
  316. case QUEC_PWRKEY_PRESS_IND:
  317. QL_POWERDEMO_LOG("pwrkey short press");
  318. /* do something */
  319. break;
  320. case QUEC_PWRKEY_RELEASE_IND:
  321. QL_POWERDEMO_LOG("pwrkey short release");
  322. /* do something */
  323. break;
  324. default:
  325. break;
  326. }
  327. }
  328. ql_rtos_task_delete(NULL);
  329. }
  330. void ql_pwrkey_app_init(void)
  331. {
  332. QlOSStatus err = QL_OSI_SUCCESS;
  333. err = ql_rtos_task_create(&pwrkey_task, 1024, APP_PRIORITY_NORMAL, "ql_pwrkeydemo", ql_pwrkey_demo_thread, NULL, 3);
  334. require_action(err, return, "pwrkey demo task created failed");
  335. }