Teensy 4.1 core updated for C++20
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

291 lines
6.5KB

  1. /* EventResponder - Simple event-based programming for Arduino
  2. * Copyright 2017 Paul Stoffregen
  3. *
  4. * Permission is hereby granted, free of charge, to any person obtaining
  5. * a copy of this software and associated documentation files (the
  6. * "Software"), to deal in the Software without restriction, including
  7. * without limitation the rights to use, copy, modify, merge, publish,
  8. * distribute, sublicense, and/or sell copies of the Software, and to
  9. * permit persons to whom the Software is furnished to do so, subject to
  10. * the following conditions:
  11. *
  12. * The above copyright notice and this permission notice shall be
  13. * included in all copies or substantial portions of the Software.
  14. *
  15. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  16. * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  17. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  18. * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
  19. * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
  20. * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  21. * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  22. * SOFTWARE.
  23. */
  24. /* EventResponder is an experimental API, almost certain to
  25. * incompatibly change as it develops. Please understand any
  26. * programs you write now using EventResponder may need to be
  27. * updated as EventResponder develops.
  28. *
  29. * Please post EventResponder post your feedback here:
  30. * https://forum.pjrc.com/threads/44723-Arduino-Events
  31. */
  32. #include "EventResponder.h"
  33. EventResponder * EventResponder::firstYield = nullptr;
  34. EventResponder * EventResponder::lastYield = nullptr;
  35. EventResponder * EventResponder::firstInterrupt = nullptr;
  36. EventResponder * EventResponder::lastInterrupt = nullptr;
  37. bool EventResponder::runningFromYield = false;
  38. // TODO: interrupt disable/enable needed in many places!!!
  39. void EventResponder::triggerEventNotImmediate()
  40. {
  41. bool irq = disableInterrupts();
  42. if (_triggered == false) {
  43. // not already triggered
  44. if (_type == EventTypeYield) {
  45. // normal type, called from yield()
  46. if (firstYield == nullptr) {
  47. _next = nullptr;
  48. _prev = nullptr;
  49. firstYield = this;
  50. lastYield = this;
  51. } else {
  52. _next = nullptr;
  53. _prev = lastYield;
  54. _prev->_next = this;
  55. lastYield = this;
  56. }
  57. } else if (_type == EventTypeInterrupt) {
  58. // interrupt, called from software interrupt
  59. if (firstInterrupt == nullptr) {
  60. _next = nullptr;
  61. _prev = nullptr;
  62. firstInterrupt = this;
  63. lastInterrupt = this;
  64. } else {
  65. _next = nullptr;
  66. _prev = lastInterrupt;
  67. _prev->_next = this;
  68. lastInterrupt = this;
  69. }
  70. SCB_ICSR = SCB_ICSR_PENDSVSET; // set PendSV interrupt
  71. } else {
  72. // detached, easy :-)
  73. }
  74. _triggered = true;
  75. }
  76. enableInterrupts(irq);
  77. }
  78. void pendablesrvreq_isr(void)
  79. {
  80. EventResponder::runFromInterrupt();
  81. }
  82. void EventResponder::runFromInterrupt()
  83. {
  84. while (1) {
  85. bool irq = disableInterrupts();
  86. EventResponder *first = firstInterrupt;
  87. if (first) {
  88. firstInterrupt = first->_next;
  89. if (firstInterrupt) {
  90. firstInterrupt->_prev = nullptr;
  91. } else {
  92. lastInterrupt = nullptr;
  93. }
  94. enableInterrupts(irq);
  95. first->_triggered = false;
  96. (*(first->_function))(*first);
  97. } else {
  98. enableInterrupts(irq);
  99. break;
  100. }
  101. }
  102. }
  103. bool EventResponder::clearEvent()
  104. {
  105. bool ret = false;
  106. bool irq = disableInterrupts();
  107. if (_triggered) {
  108. if (_type == EventTypeYield) {
  109. if (_prev) {
  110. _prev->_next = _next;
  111. } else {
  112. firstYield = _next;
  113. }
  114. if (_next) {
  115. _next->_prev = _prev;
  116. } else {
  117. lastYield = _prev;
  118. }
  119. } else if (_type == EventTypeInterrupt) {
  120. if (_prev) {
  121. _prev->_next = _next;
  122. } else {
  123. firstInterrupt = _next;
  124. }
  125. if (_next) {
  126. _next->_prev = _prev;
  127. } else {
  128. lastInterrupt = _prev;
  129. }
  130. }
  131. _triggered = false;
  132. ret = true;
  133. }
  134. enableInterrupts(irq);
  135. return ret;
  136. }
  137. void EventResponder::detach()
  138. {
  139. bool irq = disableInterrupts();
  140. if (_type == EventTypeYield) {
  141. if (_triggered) {
  142. if (_prev) {
  143. _prev->_next = _next;
  144. } else {
  145. firstYield = _next;
  146. }
  147. if (_next) {
  148. _next->_prev = _prev;
  149. } else {
  150. lastYield = _prev;
  151. }
  152. }
  153. _type = EventTypeDetached;
  154. } else if (_type == EventTypeInterrupt) {
  155. if (_triggered) {
  156. if (_prev) {
  157. _prev->_next = _next;
  158. } else {
  159. firstInterrupt = _next;
  160. }
  161. if (_next) {
  162. _next->_prev = _prev;
  163. } else {
  164. lastInterrupt = _prev;
  165. }
  166. }
  167. _type = EventTypeDetached;
  168. }
  169. enableInterrupts(irq);
  170. }
  171. //-------------------------------------------------------------
  172. MillisTimer * MillisTimer::list = nullptr;
  173. void MillisTimer::begin(unsigned long milliseconds, EventResponderRef event)
  174. {
  175. end();
  176. if (!milliseconds) return;
  177. _event = &event;
  178. _ms = milliseconds;
  179. _reload = 0;
  180. addToList();
  181. }
  182. void MillisTimer::beginRepeat(unsigned long milliseconds, EventResponderRef event)
  183. {
  184. end();
  185. if (!milliseconds) return;
  186. _event = &event;
  187. _ms = milliseconds;
  188. _reload = milliseconds;
  189. addToList();
  190. }
  191. void MillisTimer::addToList()
  192. {
  193. if (list == nullptr) {
  194. // list is empty, easy case
  195. _next = nullptr;
  196. _prev = nullptr;
  197. list = this;
  198. } else if (_ms < list->_ms) {
  199. // this timer triggers before any on the list
  200. _next = list;
  201. _prev = nullptr;
  202. list->_prev = this;
  203. list = this;
  204. } else {
  205. // add this timer somewhere after the first already on the list
  206. MillisTimer *timer = list;
  207. while (timer->_next) {
  208. _ms -= timer->_ms;
  209. timer = timer->_next;
  210. if (_ms < timer->_ms) {
  211. // found the right place in the middle of list
  212. _next = timer;
  213. _prev = timer->_prev;
  214. timer->_prev = this;
  215. _prev->_next = this;
  216. isQueued = true;
  217. return;
  218. }
  219. }
  220. // add this time at the end of the list
  221. _ms -= timer->_ms;
  222. _next = nullptr;
  223. _prev = timer;
  224. timer->_next = this;
  225. }
  226. isQueued = true;
  227. }
  228. void MillisTimer::end()
  229. {
  230. if (isQueued) {
  231. if (_next) {
  232. _next->_prev = _prev;
  233. }
  234. if (_prev) {
  235. _prev->_next = _next;
  236. } else {
  237. list = _next;
  238. }
  239. isQueued = false;
  240. }
  241. }
  242. void MillisTimer::runFromTimer()
  243. {
  244. MillisTimer *timer = list;
  245. while (timer) {
  246. if (timer->_ms > 0) {
  247. timer->_ms--;
  248. break;
  249. } else {
  250. MillisTimer *next = timer->_next;
  251. if (next) next->_prev = nullptr;
  252. list = next;
  253. timer->isQueued = false;
  254. EventResponderRef event = *(timer->_event);
  255. event.triggerEvent(0, timer);
  256. if (timer->_reload) {
  257. timer->_ms = timer->_reload;
  258. timer->addToList();
  259. }
  260. timer = list;
  261. }
  262. }
  263. }
  264. extern "C" volatile uint32_t systick_millis_count;
  265. void systick_isr(void)
  266. {
  267. systick_millis_count++;
  268. MillisTimer::runFromTimer();
  269. }