pm_sample.c 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. /*
  2. * Copyright (C) 2018 Shanghai Eastsoft Microelectronics Co., Ltd.
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Licensed under the Apache License, Version 2.0 (the License); you may
  7. * not use this file except in compliance with the License.
  8. * You may obtain a copy of the License at
  9. *
  10. * www.apache.org/licenses/LICENSE-2.0
  11. *
  12. * Unless required by applicable law or agreed to in writing, software
  13. * distributed under the License is distributed on an AS IS BASIS, WITHOUT
  14. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15. * See the License for the specific language governing permissions and
  16. * limitations under the License.
  17. *
  18. * Change Logs:
  19. * Date Author Notes
  20. * 2020-12-15 liuhy first implementation.
  21. */
  22. /*
  23. * 程序清单:这是一个 pm睡眠唤醒的使用例程
  24. * 例程导出了 pm_sample 命令到控制终端
  25. * 命令调用格式:pm_sample
  26. * 命令解释:进入不同的睡眠模式,然后用按键唤醒。
  27. * 程序功能:通过串口输出字符串,告知进入睡眠和唤醒睡眠的情况。
  28. * 注意:进入睡眠前,如果有中断挂起(SYSTICK、UART、EXTI等),睡眠将被瞬间唤醒。
  29. */
  30. #include <rtthread.h>
  31. #include <rtdevice.h>
  32. #include "drv_pm.h"
  33. #include "ald_gpio.h"
  34. #ifdef RT_USING_PM
  35. #define PM_NAME "pm" /* 设备名称 */
  36. #define WAKE_UP_PIN 51 /* 唤醒源 */
  37. #define SLEEP_TIMES 12 /* 进入睡眠次数,轮流进入不同的睡眠模式,包括无睡眠模式 */
  38. /*部分芯片进入深度睡眠后,部分外设的部分寄存器可能会丢失*/
  39. #define SAVE_REG UART0
  40. #define SAVE_REG_TYPE UART_TypeDef
  41. struct pm_callback_t
  42. {
  43. volatile int in_fun_times; /*进入函数的次数*/
  44. volatile char flag; /*标志*/
  45. volatile int mode; /*需要打印的模式*/
  46. };
  47. volatile struct pm_callback_t g_pm_data;
  48. uint32_t save_load_mem[1024] __attribute__ ((aligned(4))); /*备份的空间*/
  49. /*进入睡眠前,睡眠唤醒后,都会进入。*/
  50. /*函数打印睡眠相关的信息*/
  51. void sleep_in_out_callback(rt_uint8_t event, rt_uint8_t mode, void *data)
  52. {
  53. /*没有标志,不处理*/
  54. if(!(g_pm_data.flag))
  55. {
  56. return;
  57. }
  58. /*标志不正常,清空标志*/
  59. if((g_pm_data.flag) > 2)
  60. {
  61. (g_pm_data.flag) = 0;
  62. return;
  63. }
  64. /*模式不匹配*/
  65. if(g_pm_data.mode != mode )
  66. {
  67. return;
  68. }
  69. /*进入的事件*/
  70. switch(event)
  71. {
  72. /*进入睡眠前*/
  73. case RT_PM_ENTER_SLEEP: g_pm_data.flag = 1;
  74. rt_kprintf("\n\r##%d : ENTER ",g_pm_data.in_fun_times);
  75. /*进入深度睡眠后,部分外设的部分寄存器可能会丢失*/
  76. save_register(SAVE_REG,sizeof(SAVE_REG_TYPE),save_load_mem); /*备份寄存器的值*/
  77. g_pm_data.in_fun_times++; /*进入睡眠次数+1*/
  78. break;
  79. /*睡眠唤醒后*/
  80. case RT_PM_EXIT_SLEEP: g_pm_data.flag = 0; /*睡眠唤醒后*/
  81. load_register(SAVE_REG,sizeof(SAVE_REG_TYPE),save_load_mem); /*还原寄存器的值*/
  82. rt_kprintf("\n\rEXIT\n\r");
  83. rt_pm_request(PM_SLEEP_MODE_NONE); /*进无休眠模式*/
  84. return;
  85. default: break;
  86. };
  87. /*当前的睡眠模式*/
  88. switch(mode)
  89. {
  90. case PM_SLEEP_MODE_NONE: rt_kprintf("PM_SLEEP_MODE_NONE\n\r");
  91. break;
  92. case PM_SLEEP_MODE_IDLE: rt_kprintf("PM_SLEEP_MODE_IDLE\n\r");
  93. break;
  94. case PM_SLEEP_MODE_LIGHT: rt_kprintf("PM_SLEEP_MODE_LIGHT\n\r");
  95. break;
  96. case PM_SLEEP_MODE_DEEP: rt_kprintf("PM_SLEEP_MODE_DEEP\n\r");
  97. break;
  98. case PM_SLEEP_MODE_STANDBY: rt_kprintf("PM_SLEEP_MODE_STANDBY\n\r");
  99. break;
  100. case PM_SLEEP_MODE_SHUTDOWN: rt_kprintf("PM_SLEEP_MODE_SHUTDOWN\n\r");
  101. break;
  102. case PM_SLEEP_MODE_MAX: rt_kprintf("PM_SLEEP_MODE_MAX\n\r");
  103. break;
  104. default: break;
  105. }
  106. }
  107. /* pm测试函数 */
  108. static void pm_test(void *parameter)
  109. {
  110. int in_mode[7],i = 0;
  111. g_pm_data.in_fun_times = 0;
  112. g_pm_data.flag = 0;
  113. in_mode[0] = PM_SLEEP_MODE_NONE;
  114. in_mode[1] = PM_SLEEP_MODE_IDLE;
  115. in_mode[2] = PM_SLEEP_MODE_LIGHT;
  116. in_mode[3] = PM_SLEEP_MODE_DEEP;
  117. in_mode[4] = PM_SLEEP_MODE_STANDBY;
  118. in_mode[5] = PM_SLEEP_MODE_SHUTDOWN;
  119. in_mode[6] = PM_SLEEP_MODE_MAX;
  120. /*设置回调函数和私有数据*/
  121. rt_pm_notify_set(sleep_in_out_callback,RT_NULL);
  122. while(i < SLEEP_TIMES)
  123. {
  124. g_pm_data.mode = in_mode[i%6];
  125. /*无休眠模式,不赋予标志*/
  126. if(g_pm_data.mode != PM_SLEEP_MODE_NONE)
  127. {
  128. g_pm_data.flag = 2;
  129. }
  130. /*彻底释放无休眠模式*/
  131. rt_pm_release_all(PM_SLEEP_MODE_NONE);
  132. /*请求选择的休眠模式*/
  133. rt_pm_request(in_mode[i%6]);
  134. rt_thread_mdelay(500);
  135. /*无休眠模式,不需要额外的等待*/
  136. while(( g_pm_data.flag != 0 )&&(g_pm_data.mode != PM_SLEEP_MODE_NONE))
  137. {
  138. rt_thread_mdelay(500);
  139. }
  140. /*释放选择的休眠模式 ,彻底释放*/
  141. rt_pm_release_all(in_mode[i%6]);
  142. i++;
  143. }
  144. /*切换为无睡眠模式*/
  145. rt_pm_request(PM_SLEEP_MODE_NONE);
  146. /*清除回调函数和私有数据*/
  147. rt_pm_notify_set(RT_NULL,RT_NULL);
  148. rt_kprintf("thread pm_test close\n\r");
  149. }
  150. /*按键唤醒的回调函数*/
  151. void wake_by_pin(void *args)
  152. {
  153. }
  154. static int pm_sample(int argc, char *argv[])
  155. {
  156. rt_thread_t thread;
  157. /* 按键引脚为输入模式 */
  158. rt_pin_mode(WAKE_UP_PIN, PIN_MODE_INPUT_PULLUP);
  159. /* 绑定中断,下降沿模式,回调函数名为wake_by_pin */
  160. rt_pin_attach_irq(WAKE_UP_PIN, PIN_IRQ_MODE_RISING, wake_by_pin, RT_NULL);
  161. /* 使能中断 */
  162. rt_pin_irq_enable(WAKE_UP_PIN, PIN_IRQ_ENABLE);
  163. thread = rt_thread_create("pm_test", pm_test, RT_NULL, 1024, 25, 10);
  164. if (thread != RT_NULL)
  165. {
  166. rt_thread_startup(thread);
  167. }
  168. else
  169. {
  170. rt_kprintf("create pm_test thread failed!\n\r");
  171. }
  172. return RT_EOK;
  173. }
  174. /* 导出到 msh 命令列表中 */
  175. MSH_CMD_EXPORT(pm_sample, pm sample);
  176. #endif