pm.c 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260
  1. /*
  2. * Copyright (c) 2006-2023, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2012-06-02 Bernard the first version
  9. * 2018-08-02 Tanek split run and sleep modes, support custom mode
  10. * 2019-04-28 Zero-Free improve PM mode and device ops interface
  11. * 2020-11-23 zhangsz update pm mode select
  12. * 2020-11-27 zhangsz update pm 2.0
  13. */
  14. #include <rthw.h>
  15. #include <rtthread.h>
  16. #include <drivers/pm.h>
  17. #include <stdlib.h>
  18. #ifdef RT_USING_PM
  19. /* tickless threshold time */
  20. #ifndef PM_TICKLESS_THRESHOLD_TIME
  21. #define PM_TICKLESS_THRESHOLD_TIME 2
  22. #endif
  23. /* tickless threshold : sleep mode */
  24. #ifndef PM_TICKLESS_THRESHOLD_MODE
  25. #define PM_TICKLESS_THRESHOLD_MODE PM_SLEEP_MODE_IDLE
  26. #endif
  27. /* busy : sleep mode */
  28. #ifndef PM_BUSY_SLEEP_MODE
  29. #define PM_BUSY_SLEEP_MODE PM_SLEEP_MODE_IDLE
  30. #endif
  31. /* suspend : suspend sleep mode */
  32. #ifndef PM_SUSPEND_SLEEP_MODE
  33. #define PM_SUSPEND_SLEEP_MODE PM_SLEEP_MODE_IDLE
  34. #endif
  35. #ifdef PM_ENABLE_THRESHOLD_SLEEP_MODE
  36. #ifndef PM_LIGHT_THRESHOLD_TIME
  37. #define PM_LIGHT_THRESHOLD_TIME 5
  38. #endif
  39. #ifndef PM_DEEP_THRESHOLD_TIME
  40. #define PM_DEEP_THRESHOLD_TIME 20
  41. #endif
  42. #ifndef PM_STANDBY_THRESHOLD_TIME
  43. #define PM_STANDBY_THRESHOLD_TIME 100
  44. #endif
  45. #endif
  46. static struct rt_pm _pm;
  47. /* default mode : system power on */
  48. static rt_uint8_t _pm_default_sleep = RT_PM_DEFAULT_SLEEP_MODE;
  49. /* default deepsleep mode : tick-less mode */
  50. static rt_uint8_t _pm_default_deepsleep = RT_PM_DEFAULT_DEEPSLEEP_MODE;
  51. static struct rt_pm_notify _pm_notify;
  52. static rt_uint8_t _pm_init_flag = 0;
  53. rt_weak rt_uint32_t rt_pm_enter_critical(rt_uint8_t sleep_mode)
  54. {
  55. return rt_hw_interrupt_disable();
  56. }
  57. rt_weak void rt_pm_exit_critical(rt_uint32_t ctx, rt_uint8_t sleep_mode)
  58. {
  59. rt_hw_interrupt_enable(ctx);
  60. }
  61. /* lptimer start */
  62. static void pm_lptimer_start(struct rt_pm *pm, uint32_t timeout)
  63. {
  64. if (_pm.ops == RT_NULL)
  65. return;
  66. if (_pm.ops->timer_start != RT_NULL)
  67. _pm.ops->timer_start(pm, timeout);
  68. }
  69. /* lptimer stop */
  70. static void pm_lptimer_stop(struct rt_pm *pm)
  71. {
  72. if (_pm.ops == RT_NULL)
  73. return;
  74. if (_pm.ops->timer_stop != RT_NULL)
  75. _pm.ops->timer_stop(pm);
  76. }
  77. /* lptimer get timeout tick */
  78. static rt_tick_t pm_lptimer_get_timeout(struct rt_pm *pm)
  79. {
  80. if (_pm.ops == RT_NULL)
  81. return RT_TICK_MAX;
  82. if (_pm.ops->timer_get_tick != RT_NULL)
  83. return _pm.ops->timer_get_tick(pm);
  84. return RT_TICK_MAX;
  85. }
  86. /* enter sleep mode */
  87. static void pm_sleep(struct rt_pm *pm, uint8_t sleep_mode)
  88. {
  89. if (_pm.ops == RT_NULL)
  90. return;
  91. if (_pm.ops->sleep != RT_NULL)
  92. _pm.ops->sleep(pm, sleep_mode);
  93. }
  94. /**
  95. * This function will suspend all registered devices
  96. */
  97. static int _pm_device_suspend(rt_uint8_t mode)
  98. {
  99. int index, ret = RT_EOK;
  100. for (index = 0; index < _pm.device_pm_number; index++)
  101. {
  102. if (_pm.device_pm[index].ops->suspend != RT_NULL)
  103. {
  104. ret = _pm.device_pm[index].ops->suspend(_pm.device_pm[index].device, mode);
  105. if(ret != RT_EOK)
  106. break;
  107. }
  108. }
  109. return ret;
  110. }
  111. /**
  112. * This function will resume all registered devices
  113. */
  114. static void _pm_device_resume(rt_uint8_t mode)
  115. {
  116. int index;
  117. for (index = 0; index < _pm.device_pm_number; index++)
  118. {
  119. if (_pm.device_pm[index].ops->resume != RT_NULL)
  120. {
  121. _pm.device_pm[index].ops->resume(_pm.device_pm[index].device, mode);
  122. }
  123. }
  124. }
  125. /**
  126. * This function will update the frequency of all registered devices
  127. */
  128. static void _pm_device_frequency_change(rt_uint8_t mode)
  129. {
  130. rt_uint32_t index;
  131. /* make the frequency change */
  132. for (index = 0; index < _pm.device_pm_number; index ++)
  133. {
  134. if (_pm.device_pm[index].ops->frequency_change != RT_NULL)
  135. _pm.device_pm[index].ops->frequency_change(_pm.device_pm[index].device, mode);
  136. }
  137. }
  138. /**
  139. * This function will update the system clock frequency when idle
  140. */
  141. static void _pm_frequency_scaling(struct rt_pm *pm)
  142. {
  143. rt_base_t level;
  144. if (pm->flags & RT_PM_FREQUENCY_PENDING)
  145. {
  146. level = rt_hw_interrupt_disable();
  147. /* change system runing mode */
  148. pm->ops->run(pm, pm->run_mode);
  149. /* changer device frequency */
  150. _pm_device_frequency_change(pm->run_mode);
  151. pm->flags &= ~RT_PM_FREQUENCY_PENDING;
  152. rt_hw_interrupt_enable(level);
  153. }
  154. }
  155. /**
  156. * judge sleep mode from sleep request
  157. *
  158. * @param none
  159. *
  160. * @return sleep mode
  161. */
  162. static rt_uint8_t _judge_sleep_mode(void)
  163. {
  164. rt_uint16_t index;
  165. rt_uint16_t len;
  166. for (index = 0; index < PM_SLEEP_MODE_MAX -1; index++)
  167. {
  168. for (len = 0; len < ((PM_MODULE_MAX_ID + 31) / 32); len++)
  169. {
  170. if (_pm.sleep_status[index][len] != 0x00)
  171. return index;
  172. }
  173. }
  174. return PM_SLEEP_MODE_MAX; /* default sleep mode */
  175. }
  176. /**
  177. * This function selects the sleep mode according to the rt_pm_request/rt_pm_release count.
  178. */
  179. static rt_uint8_t _pm_select_sleep_mode(struct rt_pm *pm)
  180. {
  181. int index;
  182. rt_uint8_t mode;
  183. mode = _pm_default_deepsleep;
  184. rt_uint8_t request_mode = _judge_sleep_mode();
  185. for (index = PM_SLEEP_MODE_NONE; index < PM_SLEEP_MODE_MAX; index ++)
  186. {
  187. if (pm->modes[index])
  188. {
  189. mode = index;
  190. break;
  191. }
  192. }
  193. /* select the high power mode */
  194. if (request_mode < mode)
  195. mode = request_mode;
  196. return mode;
  197. }
  198. /**
  199. * pm module request delay sleep.
  200. */
  201. void rt_pm_module_delay_sleep(rt_uint8_t module_id, rt_tick_t timeout)
  202. {
  203. rt_base_t level;
  204. struct rt_pm *pm;
  205. if (_pm_init_flag == 0)
  206. return;
  207. if (module_id > (PM_MODULE_MAX_ID - 1))
  208. return;
  209. level = rt_hw_interrupt_disable();
  210. pm = &_pm;
  211. pm->module_status[module_id].busy_flag = RT_TRUE;
  212. pm->module_status[module_id].timeout = timeout;
  213. pm->module_status[module_id].start_time = rt_tick_get();
  214. rt_hw_interrupt_enable(level);
  215. }
  216. /**
  217. * This function check if all modules in idle status.
  218. */
  219. static rt_bool_t _pm_device_check_idle(void)
  220. {
  221. struct rt_pm *pm;
  222. if (_pm_init_flag == 0)
  223. return RT_TRUE;
  224. pm = &_pm;
  225. for (int i = 0; i < PM_MODULE_MAX_ID; i++)
  226. {
  227. if (pm->module_status[i].busy_flag == RT_TRUE)
  228. {
  229. if (rt_tick_get() - pm->module_status[i].start_time > pm->module_status[i].timeout)
  230. {
  231. pm->module_status[i].busy_flag = RT_FALSE;
  232. pm->module_status[i].timeout = 0x00;
  233. }
  234. }
  235. if (pm->module_status[i].busy_flag == RT_TRUE)
  236. {
  237. return RT_FALSE;
  238. }
  239. }
  240. return RT_TRUE;
  241. }
  242. rt_weak rt_tick_t pm_timer_next_timeout_tick(rt_uint8_t mode)
  243. {
  244. switch (mode)
  245. {
  246. case PM_SLEEP_MODE_LIGHT:
  247. return rt_timer_next_timeout_tick();
  248. case PM_SLEEP_MODE_DEEP:
  249. case PM_SLEEP_MODE_STANDBY:
  250. return rt_lptimer_next_timeout_tick();
  251. }
  252. return RT_TICK_MAX;
  253. }
  254. /**
  255. * This function will judge sleep mode from threshold timeout.
  256. *
  257. * @param cur_mode the current pm sleep mode
  258. * @param timeout_tick the threshold timeout
  259. *
  260. * @return none
  261. */
  262. rt_weak rt_uint8_t pm_get_sleep_threshold_mode(rt_uint8_t cur_mode, rt_tick_t timeout_tick)
  263. {
  264. rt_uint8_t sleep_mode = cur_mode;
  265. if (_pm_init_flag == 0)
  266. return sleep_mode;
  267. if (cur_mode >= PM_SLEEP_MODE_MAX)
  268. return sleep_mode;
  269. #ifdef PM_ENABLE_THRESHOLD_SLEEP_MODE
  270. switch (cur_mode)
  271. {
  272. case PM_SLEEP_MODE_NONE:
  273. case PM_SLEEP_MODE_IDLE:
  274. break;
  275. case PM_SLEEP_MODE_LIGHT:
  276. if (timeout_tick < PM_LIGHT_THRESHOLD_TIME)
  277. sleep_mode = PM_SLEEP_MODE_IDLE;
  278. break;
  279. case PM_SLEEP_MODE_DEEP:
  280. if (timeout_tick < PM_LIGHT_THRESHOLD_TIME)
  281. sleep_mode = PM_SLEEP_MODE_IDLE;
  282. else if (timeout_tick < PM_DEEP_THRESHOLD_TIME)
  283. sleep_mode = PM_SLEEP_MODE_LIGHT;
  284. break;
  285. case PM_SLEEP_MODE_STANDBY:
  286. if (timeout_tick < PM_LIGHT_THRESHOLD_TIME)
  287. sleep_mode = PM_SLEEP_MODE_IDLE;
  288. else if (timeout_tick < PM_DEEP_THRESHOLD_TIME)
  289. sleep_mode = PM_SLEEP_MODE_LIGHT;
  290. else if (timeout_tick < PM_STANDBY_THRESHOLD_TIME)
  291. sleep_mode = PM_SLEEP_MODE_DEEP;
  292. }
  293. #else
  294. if (timeout_tick < PM_TICKLESS_THRESHOLD_TIME)
  295. {
  296. cur_mode = PM_SLEEP_MODE_IDLE;
  297. }
  298. #endif
  299. return cur_mode;
  300. }
  301. /**
  302. * This function changes the power sleep mode base on the result of selection
  303. */
  304. static void _pm_change_sleep_mode(struct rt_pm *pm)
  305. {
  306. rt_tick_t timeout_tick, delta_tick;
  307. rt_base_t level;
  308. uint8_t sleep_mode = PM_SLEEP_MODE_DEEP;
  309. level = rt_pm_enter_critical(pm->sleep_mode);
  310. /* judge sleep mode from module request */
  311. pm->sleep_mode = _pm_select_sleep_mode(pm);
  312. /* module busy request check */
  313. if (_pm_device_check_idle() == RT_FALSE)
  314. {
  315. sleep_mode = PM_BUSY_SLEEP_MODE;
  316. if (sleep_mode < pm->sleep_mode)
  317. {
  318. pm->sleep_mode = sleep_mode; /* judge the highest sleep mode */
  319. }
  320. }
  321. if (_pm.sleep_mode == PM_SLEEP_MODE_NONE)
  322. {
  323. pm->ops->sleep(pm, PM_SLEEP_MODE_NONE);
  324. rt_pm_exit_critical(level, pm->sleep_mode);
  325. }
  326. else
  327. {
  328. /* Notify app will enter sleep mode */
  329. if (_pm_notify.notify)
  330. _pm_notify.notify(RT_PM_ENTER_SLEEP, pm->sleep_mode, _pm_notify.data);
  331. /* Suspend all peripheral device */
  332. #ifdef PM_ENABLE_SUSPEND_SLEEP_MODE
  333. int ret = _pm_device_suspend(pm->sleep_mode);
  334. if (ret != RT_EOK)
  335. {
  336. _pm_device_resume(pm->sleep_mode);
  337. if (_pm_notify.notify)
  338. _pm_notify.notify(RT_PM_EXIT_SLEEP, pm->sleep_mode, _pm_notify.data);
  339. if (pm->sleep_mode > PM_SUSPEND_SLEEP_MODE)
  340. {
  341. pm->sleep_mode = PM_SUSPEND_SLEEP_MODE;
  342. }
  343. pm->ops->sleep(pm, pm->sleep_mode); /* suspend failed */
  344. rt_pm_exit_critical(level, pm->sleep_mode);
  345. return;
  346. }
  347. #else
  348. _pm_device_suspend(pm->sleep_mode);
  349. #endif
  350. /* Tickless*/
  351. if (pm->timer_mask & (0x01 << pm->sleep_mode))
  352. {
  353. timeout_tick = pm_timer_next_timeout_tick(pm->sleep_mode);
  354. timeout_tick = timeout_tick - rt_tick_get();
  355. /* Judge sleep_mode from threshold time */
  356. pm->sleep_mode = pm_get_sleep_threshold_mode(pm->sleep_mode, timeout_tick);
  357. if (pm->timer_mask & (0x01 << pm->sleep_mode))
  358. {
  359. if (timeout_tick == RT_TICK_MAX)
  360. {
  361. pm_lptimer_start(pm, RT_TICK_MAX);
  362. }
  363. else
  364. {
  365. pm_lptimer_start(pm, timeout_tick);
  366. }
  367. }
  368. }
  369. /* enter lower power state */
  370. pm_sleep(pm, pm->sleep_mode);
  371. /* wake up from lower power state*/
  372. if (pm->timer_mask & (0x01 << pm->sleep_mode))
  373. {
  374. delta_tick = pm_lptimer_get_timeout(pm);
  375. pm_lptimer_stop(pm);
  376. if (delta_tick)
  377. {
  378. rt_tick_set(rt_tick_get() + delta_tick);
  379. }
  380. }
  381. /* resume all device */
  382. _pm_device_resume(pm->sleep_mode);
  383. if (_pm_notify.notify)
  384. _pm_notify.notify(RT_PM_EXIT_SLEEP, pm->sleep_mode, _pm_notify.data);
  385. rt_pm_exit_critical(level, pm->sleep_mode);
  386. if (pm->timer_mask & (0x01 << pm->sleep_mode))
  387. {
  388. if (delta_tick)
  389. {
  390. rt_timer_check();
  391. }
  392. }
  393. }
  394. }
  395. /**
  396. * This function will enter corresponding power mode.
  397. */
  398. void rt_system_power_manager(void)
  399. {
  400. if (_pm_init_flag == 0)
  401. return;
  402. /* CPU frequency scaling according to the runing mode settings */
  403. _pm_frequency_scaling(&_pm);
  404. /* Low Power Mode Processing */
  405. _pm_change_sleep_mode(&_pm);
  406. }
  407. /**
  408. * Upper application or device driver requests the system
  409. * stall in corresponding power mode.
  410. *
  411. * @param parameter the parameter of run mode or sleep mode
  412. */
  413. void rt_pm_request(rt_uint8_t mode)
  414. {
  415. rt_base_t level;
  416. struct rt_pm *pm;
  417. if (_pm_init_flag == 0)
  418. return;
  419. if (mode > (PM_SLEEP_MODE_MAX - 1))
  420. return;
  421. level = rt_hw_interrupt_disable();
  422. pm = &_pm;
  423. if (pm->modes[mode] < 255)
  424. pm->modes[mode] ++;
  425. rt_hw_interrupt_enable(level);
  426. }
  427. /**
  428. * Upper application or device driver releases the stall
  429. * of corresponding power mode.
  430. *
  431. * @param parameter the parameter of run mode or sleep mode
  432. *
  433. */
  434. void rt_pm_release(rt_uint8_t mode)
  435. {
  436. rt_base_t level;
  437. struct rt_pm *pm;
  438. if (_pm_init_flag == 0)
  439. return;
  440. if (mode > (PM_SLEEP_MODE_MAX - 1))
  441. return;
  442. level = rt_hw_interrupt_disable();
  443. pm = &_pm;
  444. if (pm->modes[mode] > 0)
  445. pm->modes[mode] --;
  446. rt_hw_interrupt_enable(level);
  447. }
  448. /**
  449. * Upper application or device driver releases all the stall
  450. * of corresponding power mode.
  451. *
  452. * @param parameter the parameter of run mode or sleep mode
  453. *
  454. */
  455. void rt_pm_release_all(rt_uint8_t mode)
  456. {
  457. rt_base_t level;
  458. struct rt_pm *pm;
  459. if (_pm_init_flag == 0)
  460. return;
  461. if (mode > (PM_SLEEP_MODE_MAX - 1))
  462. return;
  463. level = rt_hw_interrupt_disable();
  464. pm = &_pm;
  465. pm->modes[mode] = 0;
  466. rt_hw_interrupt_enable(level);
  467. }
  468. /**
  469. * Upper application or device driver requests the system
  470. * stall in corresponding power mode.
  471. *
  472. * @param module_id the application or device module id
  473. * @param mode the system power sleep mode
  474. */
  475. void rt_pm_module_request(uint8_t module_id, rt_uint8_t mode)
  476. {
  477. rt_base_t level;
  478. struct rt_pm *pm;
  479. if (_pm_init_flag == 0)
  480. return;
  481. if (mode > (PM_SLEEP_MODE_MAX - 1))
  482. return;
  483. if (module_id > (PM_MODULE_MAX_ID - 1))
  484. return;
  485. level = rt_hw_interrupt_disable();
  486. pm = &_pm;
  487. pm->module_status[module_id].req_status = 0x01;
  488. if (pm->modes[mode] < 255)
  489. pm->modes[mode] ++;
  490. rt_hw_interrupt_enable(level);
  491. }
  492. /**
  493. * Upper application or device driver releases the stall
  494. * of corresponding power mode.
  495. *
  496. * @param module_id the application or device module id
  497. * @param mode the system power sleep mode
  498. *
  499. */
  500. void rt_pm_module_release(uint8_t module_id, rt_uint8_t mode)
  501. {
  502. rt_base_t level;
  503. struct rt_pm *pm;
  504. if (_pm_init_flag == 0)
  505. return;
  506. if (mode > (PM_SLEEP_MODE_MAX - 1))
  507. return;
  508. if (module_id > (PM_MODULE_MAX_ID - 1))
  509. return;
  510. level = rt_hw_interrupt_disable();
  511. pm = &_pm;
  512. if (pm->modes[mode] > 0)
  513. pm->modes[mode] --;
  514. if (pm->modes[mode] == 0)
  515. pm->module_status[module_id].req_status = 0x00;
  516. rt_hw_interrupt_enable(level);
  517. }
  518. /**
  519. * Upper application or device driver releases all the stall
  520. * of corresponding power mode.
  521. *
  522. * @param module_id the application or device module id
  523. * @param mode the system power sleep mode
  524. *
  525. */
  526. void rt_pm_module_release_all(uint8_t module_id, rt_uint8_t mode)
  527. {
  528. rt_base_t level;
  529. struct rt_pm *pm;
  530. if (_pm_init_flag == 0)
  531. return;
  532. if (mode > (PM_SLEEP_MODE_MAX - 1))
  533. return;
  534. level = rt_hw_interrupt_disable();
  535. pm = &_pm;
  536. pm->modes[mode] = 0;
  537. pm->module_status[module_id].req_status = 0x00;
  538. rt_hw_interrupt_enable(level);
  539. }
  540. /**
  541. * This function will let current module work with specified sleep mode.
  542. *
  543. * @param module_id the pm module id
  544. * @param mode the pm sleep mode
  545. *
  546. * @return none
  547. */
  548. void rt_pm_sleep_request(rt_uint16_t module_id, rt_uint8_t mode)
  549. {
  550. rt_base_t level;
  551. if (module_id >= PM_MODULE_MAX_ID)
  552. {
  553. return;
  554. }
  555. if (mode >= (PM_SLEEP_MODE_MAX - 1))
  556. {
  557. return;
  558. }
  559. level = rt_hw_interrupt_disable();
  560. _pm.sleep_status[mode][module_id / 32] |= 1 << (module_id % 32);
  561. rt_hw_interrupt_enable(level);
  562. }
  563. /**
  564. * This function will let current module work with PM_SLEEP_MODE_NONE mode.
  565. *
  566. * @param module_id the pm module id
  567. *
  568. * @return NULL
  569. */
  570. void rt_pm_sleep_none_request(rt_uint16_t module_id)
  571. {
  572. rt_pm_sleep_request(module_id, PM_SLEEP_MODE_NONE);
  573. }
  574. /**
  575. * This function will let current module work with PM_SLEEP_MODE_IDLE mode.
  576. *
  577. * @param module_id the pm module id
  578. *
  579. * @return NULL
  580. */
  581. void rt_pm_sleep_idle_request(rt_uint16_t module_id)
  582. {
  583. rt_pm_sleep_request(module_id, PM_SLEEP_MODE_IDLE);
  584. }
  585. /**
  586. * This function will let current module work with PM_SLEEP_MODE_LIGHT mode.
  587. *
  588. * @param module_id the pm module id
  589. *
  590. * @return NULL
  591. */
  592. void rt_pm_sleep_light_request(rt_uint16_t module_id)
  593. {
  594. rt_pm_sleep_request(module_id, PM_SLEEP_MODE_LIGHT);
  595. }
  596. /**
  597. * When current module don't work, release requested sleep mode.
  598. *
  599. * @param module_id the pm module id
  600. * @param mode the pm sleep mode
  601. *
  602. * @return NULL
  603. */
  604. void rt_pm_sleep_release(rt_uint16_t module_id, rt_uint8_t mode)
  605. {
  606. rt_base_t level;
  607. if (module_id >= PM_MODULE_MAX_ID)
  608. {
  609. return;
  610. }
  611. if (mode >= (PM_SLEEP_MODE_MAX - 1))
  612. {
  613. return;
  614. }
  615. level = rt_hw_interrupt_disable();
  616. _pm.sleep_status[mode][module_id / 32] &= ~(1 << (module_id % 32));
  617. rt_hw_interrupt_enable(level);
  618. }
  619. /**
  620. * The specified module release the requested PM_SLEEP_MODE_NONE mode
  621. *
  622. * @param module_id the pm module id
  623. *
  624. * @return none
  625. */
  626. void rt_pm_sleep_none_release(rt_uint16_t module_id)
  627. {
  628. rt_pm_sleep_release(module_id, PM_SLEEP_MODE_NONE);
  629. }
  630. /**
  631. * The specified module release the requested PM_SLEEP_MODE_IDLE mode
  632. *
  633. * @param module_id the pm module id
  634. *
  635. * @return none
  636. */
  637. void rt_pm_sleep_idle_release(rt_uint16_t module_id)
  638. {
  639. rt_pm_sleep_release(module_id, PM_SLEEP_MODE_IDLE);
  640. }
  641. /**
  642. * The specified module release the requested PM_SLEEP_MODE_LIGHT mode
  643. *
  644. * @param module_id the pm module id
  645. *
  646. * @return none
  647. */
  648. void rt_pm_sleep_light_release(rt_uint16_t module_id)
  649. {
  650. rt_pm_sleep_release(module_id, PM_SLEEP_MODE_LIGHT);
  651. }
  652. /**
  653. * Register a device with PM feature
  654. *
  655. * @param device the device with PM feature
  656. * @param ops the PM ops for device
  657. */
  658. void rt_pm_device_register(struct rt_device *device, const struct rt_device_pm_ops *ops)
  659. {
  660. rt_base_t level;
  661. struct rt_device_pm *device_pm;
  662. RT_DEBUG_NOT_IN_INTERRUPT;
  663. level = rt_hw_interrupt_disable();
  664. device_pm = (struct rt_device_pm *)RT_KERNEL_REALLOC(_pm.device_pm,
  665. (_pm.device_pm_number + 1) * sizeof(struct rt_device_pm));
  666. if (device_pm != RT_NULL)
  667. {
  668. _pm.device_pm = device_pm;
  669. _pm.device_pm[_pm.device_pm_number].device = device;
  670. _pm.device_pm[_pm.device_pm_number].ops = ops;
  671. _pm.device_pm_number += 1;
  672. }
  673. rt_hw_interrupt_enable(level);
  674. }
  675. /**
  676. * Unregister device from PM manager.
  677. *
  678. * @param device the device with PM feature
  679. */
  680. void rt_pm_device_unregister(struct rt_device *device)
  681. {
  682. rt_base_t level;
  683. rt_uint32_t index;
  684. RT_DEBUG_NOT_IN_INTERRUPT;
  685. level = rt_hw_interrupt_disable();
  686. for (index = 0; index < _pm.device_pm_number; index ++)
  687. {
  688. if (_pm.device_pm[index].device == device)
  689. {
  690. /* remove current entry */
  691. for (; index < _pm.device_pm_number - 1; index ++)
  692. {
  693. _pm.device_pm[index] = _pm.device_pm[index + 1];
  694. }
  695. _pm.device_pm[_pm.device_pm_number - 1].device = RT_NULL;
  696. _pm.device_pm[_pm.device_pm_number - 1].ops = RT_NULL;
  697. _pm.device_pm_number -= 1;
  698. /* break out and not touch memory */
  699. break;
  700. }
  701. }
  702. rt_hw_interrupt_enable(level);
  703. }
  704. /**
  705. * This function set notification callback for application
  706. */
  707. void rt_pm_notify_set(void (*notify)(rt_uint8_t event, rt_uint8_t mode, void *data), void *data)
  708. {
  709. _pm_notify.notify = notify;
  710. _pm_notify.data = data;
  711. }
  712. /**
  713. * This function set default sleep mode when no pm_request
  714. */
  715. void rt_pm_default_set(rt_uint8_t sleep_mode)
  716. {
  717. _pm_default_sleep = sleep_mode;
  718. }
  719. /**
  720. * RT-Thread device interface for PM device
  721. */
  722. static rt_ssize_t _rt_pm_device_read(rt_device_t dev,
  723. rt_off_t pos,
  724. void *buffer,
  725. rt_size_t size)
  726. {
  727. struct rt_pm *pm;
  728. rt_size_t length;
  729. length = 0;
  730. pm = (struct rt_pm *)dev;
  731. RT_ASSERT(pm != RT_NULL);
  732. if (pos < PM_SLEEP_MODE_MAX)
  733. {
  734. int mode;
  735. mode = pm->modes[pos];
  736. length = rt_snprintf(buffer, size, "%d", mode);
  737. }
  738. return length;
  739. }
  740. static rt_ssize_t _rt_pm_device_write(rt_device_t dev,
  741. rt_off_t pos,
  742. const void *buffer,
  743. rt_size_t size)
  744. {
  745. unsigned char request;
  746. if (size)
  747. {
  748. /* get request */
  749. request = *(unsigned char *)buffer;
  750. if (request == 0x01)
  751. {
  752. rt_pm_request(pos);
  753. }
  754. else if (request == 0x00)
  755. {
  756. rt_pm_release(pos);
  757. }
  758. }
  759. return 1;
  760. }
  761. static rt_err_t _rt_pm_device_control(rt_device_t dev,
  762. int cmd,
  763. void *args)
  764. {
  765. rt_uint32_t mode;
  766. switch (cmd)
  767. {
  768. case RT_PM_DEVICE_CTRL_REQUEST:
  769. mode = (rt_uint32_t)(rt_ubase_t)args;
  770. rt_pm_request(mode);
  771. break;
  772. case RT_PM_DEVICE_CTRL_RELEASE:
  773. mode = (rt_uint32_t)(rt_ubase_t)args;
  774. rt_pm_release(mode);
  775. break;
  776. }
  777. return RT_EOK;
  778. }
  779. int rt_pm_run_enter(rt_uint8_t mode)
  780. {
  781. rt_base_t level;
  782. struct rt_pm *pm;
  783. if (_pm_init_flag == 0)
  784. return -RT_EIO;
  785. if (mode > PM_RUN_MODE_MAX)
  786. return -RT_EINVAL;
  787. level = rt_hw_interrupt_disable();
  788. pm = &_pm;
  789. if (mode < pm->run_mode)
  790. {
  791. /* change system runing mode */
  792. pm->ops->run(pm, mode);
  793. /* changer device frequency */
  794. _pm_device_frequency_change(mode);
  795. }
  796. else
  797. {
  798. pm->flags |= RT_PM_FREQUENCY_PENDING;
  799. }
  800. pm->run_mode = mode;
  801. rt_hw_interrupt_enable(level);
  802. return RT_EOK;
  803. }
  804. #ifdef RT_USING_DEVICE_OPS
  805. const static struct rt_device_ops pm_ops =
  806. {
  807. RT_NULL,
  808. RT_NULL,
  809. RT_NULL,
  810. _rt_pm_device_read,
  811. _rt_pm_device_write,
  812. _rt_pm_device_control,
  813. };
  814. #endif
  815. /**
  816. * This function will initialize power management.
  817. *
  818. * @param ops the PM operations.
  819. * @param timer_mask indicates which mode has timer feature.
  820. * @param user_data user data
  821. */
  822. void rt_system_pm_init(const struct rt_pm_ops *ops,
  823. rt_uint8_t timer_mask,
  824. void *user_data)
  825. {
  826. struct rt_device *device;
  827. struct rt_pm *pm;
  828. pm = &_pm;
  829. device = &(_pm.parent);
  830. device->type = RT_Device_Class_PM;
  831. device->rx_indicate = RT_NULL;
  832. device->tx_complete = RT_NULL;
  833. #ifdef RT_USING_DEVICE_OPS
  834. device->ops = &pm_ops;
  835. #else
  836. device->init = RT_NULL;
  837. device->open = RT_NULL;
  838. device->close = RT_NULL;
  839. device->read = _rt_pm_device_read;
  840. device->write = _rt_pm_device_write;
  841. device->control = _rt_pm_device_control;
  842. #endif
  843. device->user_data = user_data;
  844. /* register PM device to the system */
  845. rt_device_register(device, "pm", RT_DEVICE_FLAG_RDWR);
  846. rt_memset(pm->modes, 0, sizeof(pm->modes));
  847. pm->sleep_mode = _pm_default_sleep;
  848. /* when system power on, set default sleep modes */
  849. pm->modes[pm->sleep_mode] = 1;
  850. pm->module_status[PM_POWER_ID].req_status = 1;
  851. pm->run_mode = RT_PM_DEFAULT_RUN_MODE;
  852. pm->timer_mask = timer_mask;
  853. pm->ops = ops;
  854. pm->device_pm = RT_NULL;
  855. pm->device_pm_number = 0;
  856. #if IDLE_THREAD_STACK_SIZE <= 256
  857. #error "[pm.c ERR] IDLE Stack Size Too Small!"
  858. #endif
  859. _pm_init_flag = 1;
  860. }
  861. #ifdef RT_USING_FINSH
  862. #include <finsh.h>
  863. static const char *_pm_sleep_str[] = PM_SLEEP_MODE_NAMES;
  864. static const char *_pm_run_str[] = PM_RUN_MODE_NAMES;
  865. static void rt_pm_release_mode(int argc, char **argv)
  866. {
  867. int mode = 0;
  868. if (argc >= 2)
  869. {
  870. mode = atoi(argv[1]);
  871. }
  872. rt_pm_release(mode);
  873. }
  874. MSH_CMD_EXPORT_ALIAS(rt_pm_release_mode, pm_release, release power management mode);
  875. static void rt_pm_release_mode_all(int argc, char **argv)
  876. {
  877. int mode = 0;
  878. if (argc >= 2)
  879. {
  880. mode = atoi(argv[1]);
  881. }
  882. rt_pm_release_all(mode);
  883. }
  884. MSH_CMD_EXPORT_ALIAS(rt_pm_release_mode_all, pm_release_all, release power management mode count);
  885. static void rt_pm_request_mode(int argc, char **argv)
  886. {
  887. int mode = 0;
  888. if (argc >= 2)
  889. {
  890. mode = atoi(argv[1]);
  891. }
  892. rt_pm_request(mode);
  893. }
  894. MSH_CMD_EXPORT_ALIAS(rt_pm_request_mode, pm_request, request power management mode);
  895. static void rt_module_release_mode(int argc, char **argv)
  896. {
  897. int module = 0;
  898. int mode = 0;
  899. if (argc >= 3)
  900. {
  901. module = atoi(argv[1]);
  902. mode = atoi(argv[2]);
  903. }
  904. rt_pm_module_release(module, mode);
  905. }
  906. MSH_CMD_EXPORT_ALIAS(rt_module_release_mode, pm_module_release, release module power mode);
  907. static void rt_module_release_mode_all(int argc, char **argv)
  908. {
  909. int module = 0;
  910. int mode = 0;
  911. if (argc >= 3)
  912. {
  913. module = atoi(argv[1]);
  914. mode = atoi(argv[2]);
  915. }
  916. rt_pm_module_release_all(module, mode);
  917. }
  918. MSH_CMD_EXPORT_ALIAS(rt_module_release_mode_all, pm_module_release_all, release power management mode count);
  919. static void rt_module_request_mode(int argc, char **argv)
  920. {
  921. int module = 0;
  922. int mode = 0;
  923. if (argc >= 3)
  924. {
  925. module = atoi(argv[1]);
  926. mode = atoi(argv[2]);
  927. }
  928. rt_pm_module_request(module, mode);
  929. }
  930. MSH_CMD_EXPORT_ALIAS(rt_module_request_mode, pm_module_request, request power management mode);
  931. static void rt_module_delay_sleep(int argc, char **argv)
  932. {
  933. int module = 0;
  934. unsigned int timeout = 0;
  935. if (argc >= 3)
  936. {
  937. module = atoi(argv[1]);
  938. timeout = atoi(argv[2]);
  939. }
  940. rt_pm_module_delay_sleep(module, timeout);
  941. }
  942. MSH_CMD_EXPORT_ALIAS(rt_module_delay_sleep, pm_module_delay, module request delay sleep);
  943. static void rt_pm_run_mode_switch(int argc, char **argv)
  944. {
  945. int mode = 0;
  946. if (argc >= 2)
  947. {
  948. mode = atoi(argv[1]);
  949. }
  950. rt_pm_run_enter(mode);
  951. }
  952. MSH_CMD_EXPORT_ALIAS(rt_pm_run_mode_switch, pm_run, switch power management run mode);
  953. rt_uint32_t rt_pm_module_get_status(void)
  954. {
  955. rt_uint8_t index = 0;
  956. struct rt_pm *pm;
  957. rt_uint32_t req_status = 0x00;
  958. pm = &_pm;
  959. for (index = 0; index < PM_MODULE_MAX_ID; index ++)
  960. {
  961. if (pm->module_status[index].req_status == 0x01)
  962. req_status |= 1<<index;
  963. }
  964. return req_status;
  965. }
  966. rt_uint8_t rt_pm_get_sleep_mode(void)
  967. {
  968. struct rt_pm *pm;
  969. pm = &_pm;
  970. return pm->sleep_mode;
  971. }
  972. /* get pm entity pointer */
  973. struct rt_pm *rt_pm_get_handle(void)
  974. {
  975. return &_pm;
  976. }
  977. #ifdef PM_ENABLE_DEBUG
  978. /**
  979. * print current module sleep request list
  980. *
  981. * @param none
  982. *
  983. * @return none
  984. */
  985. void pm_sleep_dump(void)
  986. {
  987. uint8_t index;
  988. uint16_t len;
  989. rt_kprintf("+-------------+--------------+\n");
  990. rt_kprintf("| Sleep Mode | Request List |\n");
  991. rt_kprintf("+-------------+--------------+\n");
  992. for (index = 0; index < PM_SLEEP_MODE_MAX -1; index++)
  993. {
  994. for (len = 0; len < ((PM_MODULE_MAX_ID + 31) / 32); len++)
  995. {
  996. rt_kprintf("| Mode[%d] : %d | 0x%08x |\n", index, len,
  997. _pm.sleep_status[index][len]);
  998. }
  999. }
  1000. rt_kprintf("+-------------+--------------+\n");
  1001. }
  1002. MSH_CMD_EXPORT(pm_sleep_dump, dump pm request list);
  1003. static void pm_sleep_request(int argc, char **argv)
  1004. {
  1005. int module = 0;
  1006. int mode = 0;
  1007. if (argc >= 3)
  1008. {
  1009. module = atoi(argv[1]);
  1010. mode = atoi(argv[2]);
  1011. rt_pm_sleep_request(module, mode);
  1012. }
  1013. }
  1014. MSH_CMD_EXPORT(pm_sleep_request, pm_sleep_request module sleep_mode);
  1015. static void pm_sleep_release(int argc, char **argv)
  1016. {
  1017. int module = 0;
  1018. int mode = 0;
  1019. if (argc >= 3)
  1020. {
  1021. module = atoi(argv[1]);
  1022. mode = atoi(argv[2]);
  1023. rt_pm_sleep_release(module, mode);
  1024. }
  1025. }
  1026. MSH_CMD_EXPORT(pm_sleep_release, pm_sleep_release module sleep_mode);
  1027. #endif
  1028. static void rt_pm_dump_status(void)
  1029. {
  1030. rt_uint32_t index;
  1031. struct rt_pm *pm;
  1032. pm = &_pm;
  1033. rt_kprintf("| Power Management Mode | Counter | Timer |\n");
  1034. rt_kprintf("+-----------------------+---------+-------+\n");
  1035. for (index = 0; index < PM_SLEEP_MODE_MAX; index ++)
  1036. {
  1037. int has_timer = 0;
  1038. if (pm->timer_mask & (1 << index))
  1039. has_timer = 1;
  1040. rt_kprintf("| %021s | %7d | %5d |\n", _pm_sleep_str[index], pm->modes[index], has_timer);
  1041. }
  1042. rt_kprintf("+-----------------------+---------+-------+\n");
  1043. rt_kprintf("pm current sleep mode: %s\n", _pm_sleep_str[pm->sleep_mode]);
  1044. rt_kprintf("pm current run mode: %s\n", _pm_run_str[pm->run_mode]);
  1045. rt_kprintf("\n");
  1046. rt_kprintf("| module | busy | start time | timeout |\n");
  1047. rt_kprintf("+--------+------+------------+-----------+\n");
  1048. for (index = 0; index < PM_MODULE_MAX_ID; index ++)
  1049. {
  1050. if ((pm->module_status[index].busy_flag == RT_TRUE) ||
  1051. (pm->module_status[index].req_status != 0x00))
  1052. {
  1053. rt_kprintf("| %04d | %d | 0x%08x | 0x%08x |\n",
  1054. index, pm->module_status[index].busy_flag,
  1055. pm->module_status[index].start_time,
  1056. pm->module_status[index].timeout);
  1057. }
  1058. }
  1059. rt_kprintf("+--------+------+------------+-----------+\n");
  1060. }
  1061. FINSH_FUNCTION_EXPORT_ALIAS(rt_pm_dump_status, pm_dump, dump power management status);
  1062. MSH_CMD_EXPORT_ALIAS(rt_pm_dump_status, pm_dump, dump power management status);
  1063. #endif
  1064. #endif /* RT_USING_PM */