pm_sample.c 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. /*
  2. * Copyright (C) 2018 Shanghai Eastsoft Microelectronics Co., Ltd.
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2020-12-15 liuhy first implementation.
  9. */
  10. /*
  11. * 程序清单:这是一个 pm睡眠唤醒的使用例程
  12. * 例程导出了 pm_sample 命令到控制终端
  13. * 命令调用格式:pm_sample
  14. * 命令解释:进入不同的睡眠模式,然后用按键唤醒
  15. * 程序功能:通过串口输出字符串,告知进入睡眠和唤醒睡眠的情况。
  16. */
  17. #include <rtthread.h>
  18. #include <rtdevice.h>
  19. #include "drv_pm.h"
  20. #define PM_NAME "pm" /* 设备名称 */
  21. #define WAKE_UP_PIN 51 /* 唤醒源 */
  22. #define SLEEP_TIMES 12 /* 进入睡眠次数,轮流进入不同的睡眠模式,包括无睡眠模式 */
  23. struct pm_callback_t
  24. {
  25. volatile int in_fun_times; /*进入函数的次数*/
  26. volatile char flag; /*标志*/
  27. volatile int mode; /*需要打印的模式*/
  28. };
  29. volatile struct pm_callback_t g_pm_data;
  30. uint32_t save_load_mem[1024] __attribute__ ((aligned(4))); /*备份的空间*/
  31. /*进入睡眠前,睡眠唤醒后,都会进入。*/
  32. /*函数打印睡眠相关的信息*/
  33. void sleep_in_out_callback(rt_uint8_t event, rt_uint8_t mode, void *data)
  34. {
  35. /*没有标志,不处理*/
  36. if(!(g_pm_data.flag))
  37. {
  38. return;
  39. }
  40. /*标志不正常,清空标志*/
  41. if((g_pm_data.flag) > 2)
  42. {
  43. (g_pm_data.flag) = 0;
  44. return;
  45. }
  46. /*模式不匹配*/
  47. if(g_pm_data.mode != mode )
  48. {
  49. return;
  50. }
  51. /*进入的事件*/
  52. switch(event)
  53. {
  54. /*进入睡眠前*/
  55. case RT_PM_ENTER_SLEEP: g_pm_data.flag = 1;
  56. rt_kprintf("\n\r##%d : ENTER ",g_pm_data.in_fun_times);
  57. save_register(UART0,sizeof(UART_TypeDef),save_load_mem); /*备份寄存器的值*/
  58. g_pm_data.in_fun_times++; /*进入睡眠次数+1*/
  59. break;
  60. /*睡眠唤醒后*/
  61. case RT_PM_EXIT_SLEEP: g_pm_data.flag = 0; /*睡眠唤醒后*/
  62. load_register(UART0,sizeof(UART_TypeDef),save_load_mem); /*还原寄存器的值*/
  63. rt_kprintf("\n\rEXIT\n\r");
  64. rt_pm_release(mode); /*释放休眠模式*/
  65. return;
  66. default: break;
  67. };
  68. /*当前的睡眠模式*/
  69. switch(mode)
  70. {
  71. case PM_SLEEP_MODE_NONE: rt_kprintf("PM_SLEEP_MODE_NONE\n\r");
  72. break;
  73. case PM_SLEEP_MODE_IDLE: rt_kprintf("PM_SLEEP_MODE_IDLE\n\r");
  74. break;
  75. case PM_SLEEP_MODE_LIGHT: rt_kprintf("PM_SLEEP_MODE_LIGHT\n\r");
  76. break;
  77. case PM_SLEEP_MODE_DEEP: rt_kprintf("PM_SLEEP_MODE_DEEP\n\r");
  78. break;
  79. case PM_SLEEP_MODE_STANDBY: rt_kprintf("PM_SLEEP_MODE_STANDBY\n\r");
  80. break;
  81. case PM_SLEEP_MODE_SHUTDOWN: rt_kprintf("PM_SLEEP_MODE_SHUTDOWN\n\r");
  82. break;
  83. case PM_SLEEP_MODE_MAX: rt_kprintf("PM_SLEEP_MODE_MAX\n\r");
  84. break;
  85. default: break;
  86. }
  87. }
  88. /* pm测试函数 */
  89. static void pm_test(void *parameter)
  90. {
  91. int in_mode[7],i = 0;
  92. g_pm_data.in_fun_times = 0;
  93. g_pm_data.flag = 0;
  94. in_mode[0] = PM_SLEEP_MODE_NONE;
  95. in_mode[1] = PM_SLEEP_MODE_IDLE;
  96. in_mode[2] = PM_SLEEP_MODE_LIGHT;
  97. in_mode[3] = PM_SLEEP_MODE_DEEP;
  98. in_mode[4] = PM_SLEEP_MODE_STANDBY;
  99. in_mode[5] = PM_SLEEP_MODE_SHUTDOWN;
  100. in_mode[6] = PM_SLEEP_MODE_MAX;
  101. /*设置回调函数和私有数据*/
  102. rt_pm_notify_set(sleep_in_out_callback,RT_NULL);
  103. while(i < SLEEP_TIMES)
  104. {
  105. g_pm_data.mode = in_mode[i%6];
  106. /*无休眠模式,不赋予标志*/
  107. if(g_pm_data.mode != PM_SLEEP_MODE_NONE)
  108. {
  109. g_pm_data.flag = 2;
  110. }
  111. /*请求选择的休眠模式*/
  112. rt_pm_request(in_mode[i%6]);
  113. rt_thread_mdelay(500);
  114. /*无休眠模式,不需要额外的等待*/
  115. while(( g_pm_data.flag != 0 )&&(g_pm_data.mode != PM_SLEEP_MODE_NONE))
  116. {
  117. rt_thread_mdelay(500);
  118. }
  119. /*释放选择的休眠模式*/
  120. rt_pm_release(in_mode[i%6]);
  121. i++;
  122. }
  123. /*清除回调函数和私有数据*/
  124. rt_pm_notify_set(RT_NULL,RT_NULL);
  125. rt_kprintf("thread pm_test close\n\r");
  126. }
  127. /*按键唤醒的回调函数*/
  128. void wake_by_pin(void *args)
  129. {
  130. }
  131. static int pm_sample(int argc, char *argv[])
  132. {
  133. rt_thread_t thread;
  134. /* 按键引脚为输入模式 */
  135. rt_pin_mode(WAKE_UP_PIN, PIN_MODE_INPUT_PULLUP);
  136. /* 绑定中断,下降沿模式,回调函数名为wake_by_pin */
  137. rt_pin_attach_irq(WAKE_UP_PIN, PIN_IRQ_MODE_RISING, wake_by_pin, RT_NULL);
  138. /* 使能中断 */
  139. rt_pin_irq_enable(WAKE_UP_PIN, PIN_IRQ_ENABLE);
  140. thread = rt_thread_create("pm_test", pm_test, RT_NULL, 1024, 25, 10);
  141. if (thread != RT_NULL)
  142. {
  143. rt_thread_startup(thread);
  144. }
  145. else
  146. {
  147. rt_kprintf("create pm_test thread failed!\n\r");
  148. }
  149. return RT_EOK;
  150. }
  151. /* 导出到 msh 命令列表中 */
  152. MSH_CMD_EXPORT(pm_sample, pm sample);