PlatformIO package of the Teensy core framework compatible with GCC 10 & C++20
Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

404 linhas
9.3KB

  1. #include <Arduino.h>
  2. #include "TeensyThreads.h"
  3. volatile int p1 = 0;
  4. volatile int p2 = 0;
  5. volatile int p3 = 0;
  6. volatile int p4 = 0;
  7. void my_priv_func1(int data){
  8. p1 = 0;
  9. data *= 1000; // convert sec to ms;
  10. int mx = millis();
  11. while(1) {
  12. p1++;
  13. if ((int)millis() - mx > data) break;
  14. }
  15. }
  16. void my_priv_func2() {
  17. p2 = 0;
  18. while(1) p2++;
  19. }
  20. void my_priv_func3() {
  21. p3 = 0;
  22. while(1) p3++;
  23. }
  24. void my_priv_func_lock(void *lock) {
  25. Threads::Mutex *m = (Threads::Mutex *) lock;
  26. p4 = 0;
  27. m->lock();
  28. uint32_t mx = millis();
  29. while(millis() - mx < 500) p1++;
  30. m->unlock();
  31. }
  32. Threads::Mutex count_lock;
  33. volatile int count1 = 0;
  34. volatile int count2 = 0;
  35. volatile int count3 = 0;
  36. void lock_test1() {
  37. while(1) {
  38. count_lock.lock();
  39. for(int i=0; i<500; i++) count1++;
  40. count_lock.unlock();
  41. }
  42. }
  43. void lock_test2() {
  44. while(1) {
  45. count_lock.lock();
  46. for(int i=0; i<1000; i++) count2++;
  47. count_lock.unlock();
  48. }
  49. }
  50. void lock_test3() {
  51. while(1) {
  52. count_lock.lock();
  53. for(int i=0; i<100; i++) count3++;
  54. count_lock.unlock();
  55. }
  56. }
  57. int ratio_test(int a, int b, float r) {
  58. float f = (float)a / (float)b;
  59. if (a < b) f = 1.0/f;
  60. if (f > r) return 1;
  61. return 0;
  62. }
  63. void showp() {
  64. Serial.print(p1);
  65. Serial.print(" ");
  66. Serial.print(p2);
  67. Serial.print(" ");
  68. Serial.print(p3);
  69. Serial.println();
  70. }
  71. int id1, id2, id3;
  72. void delay2(uint32_t ms)
  73. {
  74. int mx = millis();
  75. while(millis() - mx < ms);
  76. }
  77. #define delayx delay
  78. class subtest {
  79. public:
  80. int value;
  81. void h(int x) { value = x; }
  82. int test(Threads::Mutex *lk) { return lk->getState(); }
  83. int getValue() { return value; }
  84. } subinst;
  85. class WireTest {
  86. public:
  87. bool beginTransaction() { return 1; }
  88. bool endTransaction() { return 1; }
  89. bool other() { return 1; }
  90. };
  91. int stack_fault = 0;
  92. int stack_id = 0;
  93. void stack_overflow_isr(void) {
  94. stack_fault = 1;
  95. threads.kill(threads.id());
  96. }
  97. // turn off optimizations or the optimizer will remove the recursion because
  98. // it is smart enough to know it doesn't do anything
  99. void __attribute__((optimize("O0"))) recursive_thread(int level) {
  100. if (stack_fault) return;
  101. char x[128]; // use up some stack space
  102. delay(20);
  103. recursive_thread(level+1);
  104. }
  105. void runtest() {
  106. int save_p;
  107. int save_time;
  108. float rate;
  109. // benchmark with no threading
  110. my_priv_func1(1);
  111. save_time = p1;
  112. Serial.print("CPU speed consistency ");
  113. my_priv_func1(1);
  114. rate = (float)p1 / (float)save_time;
  115. if (rate < 1.2 && rate > 0.8) Serial.println("OK");
  116. else Serial.println("***FAIL***");
  117. Serial.print("Test thread start ");
  118. id1 = threads.addThread(my_priv_func1, 1);
  119. delayx(300);
  120. if (p1 != 0) Serial.println("OK");
  121. else Serial.println("***FAIL***");
  122. Serial.print("Test thread run state ");
  123. if (threads.getState(id1) == Threads::RUNNING) Serial.println("OK");
  124. else Serial.println("***FAIL***");
  125. Serial.print("Test thread return ");
  126. delayx(1000);
  127. save_p = p1;
  128. delayx(300);
  129. if (p1 != 0 && p1 == save_p) Serial.println("OK");
  130. else Serial.println("***FAIL***");
  131. Serial.print("Test thread speed ");
  132. rate = (float)p1 / (float)save_time;
  133. if (rate < 0.7 && rate > 0.3) Serial.println("OK");
  134. else Serial.println("***FAIL***");
  135. Serial.print("Speed no threads: ");
  136. Serial.println(save_time);
  137. Serial.print("Speed 1 thread: ");
  138. Serial.println(p1);
  139. Serial.print("Ratio: ");
  140. Serial.println(rate);
  141. Serial.print("Test set time slice ");
  142. id1 = threads.addThread(my_priv_func1, 1);
  143. delayx(2000);
  144. save_p = p1;
  145. id1 = threads.addThread(my_priv_func1, 1);
  146. threads.setTimeSlice(id1, 200);
  147. delayx(2000);
  148. float expected = (float)save_p * 2.0*200.0 / ((float)threads.DEFAULT_TICKS + 200.0);
  149. rate = (float)p1 / (float)expected;
  150. if (rate > 0.9 && rate < 1.1) Serial.println("OK");
  151. else Serial.println("***FAIL***");
  152. Serial.print("Speed default ticks: ");
  153. Serial.println(save_p);
  154. Serial.print("Speed 200 ticks: ");
  155. Serial.println(p1);
  156. Serial.print("Expected: ");
  157. Serial.println(expected);
  158. Serial.print("Ratio with expected: ");
  159. Serial.println(rate);
  160. Serial.print("Test delay yield ");
  161. id1 = threads.addThread(my_priv_func1, 1);
  162. threads.delay(1100);
  163. rate = (float)p1 / (float)save_time;
  164. if (rate > 0.7 && rate < 1.4) Serial.println("OK");
  165. else Serial.println("***FAIL***");
  166. Serial.print("Yield wait ratio: ");
  167. Serial.println(rate);
  168. Serial.print("Test thread end state ");
  169. if (threads.getState(id1) == Threads::ENDED) Serial.println("OK");
  170. else Serial.println("***FAIL***");
  171. Serial.print("Test thread reinitialize ");
  172. p2 = 0;
  173. id2 = threads.addThread(my_priv_func2);
  174. delayx(200);
  175. if (p2 != 0) Serial.println("OK");
  176. else Serial.println("***FAIL***");
  177. Serial.print("Test stack usage ");
  178. int sz = threads.getStackUsed(id2);
  179. // Seria.println(sz);
  180. if (sz>=40 && sz<=48) Serial.println("OK");
  181. else Serial.println("***FAIL***");
  182. Serial.print("Test thread suspend ");
  183. delayx(200);
  184. threads.suspend(id2);
  185. delayx(200);
  186. save_p = p2;
  187. delayx(200);
  188. if (p2 != 0 && p2 == save_p) Serial.println("OK");
  189. else Serial.println("***FAIL***");
  190. Serial.print("Test thread restart ");
  191. p2 = 0;
  192. threads.restart(id2);
  193. delayx(1000);
  194. if (p2 != 0) Serial.println("OK");
  195. else Serial.println("***FAIL***");
  196. Serial.print("Test thread stop ");
  197. threads.stop();
  198. delayx(200);
  199. p2 = 0;
  200. delayx(200);
  201. if (p2 == 0) Serial.println("OK");
  202. else Serial.println("***FAIL***");
  203. Serial.print("Test thread start ");
  204. threads.start();
  205. delayx(200);
  206. if (p2 != 0) Serial.println("OK");
  207. else Serial.println("***FAIL***");
  208. Serial.print("Test thread wait ");
  209. id3 = threads.addThread(my_priv_func1, 1);
  210. int time = millis();
  211. int r = threads.wait(id3);
  212. delayx(100);
  213. time = millis() - time;
  214. if (r==id3) Serial.println("OK");
  215. else Serial.println("***FAIL***");
  216. Serial.print("Test thread wait time ");
  217. if (time > 1000 && time < 2000) Serial.println("OK");
  218. else Serial.println("***FAIL***");
  219. Serial.print("Test thread kill ");
  220. id3 = threads.addThread(my_priv_func1, 2);
  221. delayx(300);
  222. threads.kill(id3);
  223. delayx(300);
  224. save_p = p1;
  225. delayx(300);
  226. if (save_p==p1) Serial.println("OK");
  227. else Serial.println("***FAIL***");
  228. delayx(1000);
  229. Serial.print("Test std::thread scope ");
  230. {
  231. std::thread th2(my_priv_func3);
  232. delayx(500);
  233. }
  234. delayx(500);
  235. save_p = p3;
  236. delayx(500);
  237. if (p3 != 0 && p3 == save_p) Serial.println("OK");
  238. else Serial.println("***FAIL***");
  239. Serial.print("Test basic lock ");
  240. id1 = threads.addThread(my_priv_func1, 2);
  241. delayx(500);
  242. {
  243. Threads::Suspend lock;
  244. save_p = p1;
  245. delayx(500);
  246. if (save_p == p1) Serial.println("OK");
  247. else Serial.println("***FAIL***");
  248. }
  249. Serial.print("Test basic unlock ");
  250. delayx(500);
  251. if (save_p != p1) Serial.println("OK");
  252. else Serial.println("***FAIL***");
  253. Serial.print("Test mutex lock state ");
  254. Threads::Mutex mx;
  255. mx.lock();
  256. r = mx.try_lock();
  257. if (r == 0) Serial.println("OK");
  258. else Serial.println("***FAIL***");
  259. Serial.print("Test mutex lock thread ");
  260. id1 = threads.addThread(my_priv_func_lock, &mx);
  261. delayx(200);
  262. if (p4 == 0) Serial.println("OK");
  263. else Serial.println("***FAIL***");
  264. Serial.print("Test mutex unlock ");
  265. mx.unlock();
  266. delayx(500);
  267. if (p1 != 0) Serial.println("OK");
  268. else Serial.println("***FAIL***");
  269. Serial.print("Test fast locks ");
  270. id1 = threads.addThread(lock_test1);
  271. id2 = threads.addThread(lock_test2);
  272. id3 = threads.addThread(lock_test3);
  273. delayx(3000);
  274. threads.kill(id1);
  275. threads.kill(id2);
  276. threads.kill(id3);
  277. if (ratio_test(count1, count2, 1.2)) Serial.println("***FAIL***");
  278. //else if (ratio_test(count1, count3, 1.2)) Serial.println("***FAIL***");
  279. else Serial.println("OK");
  280. Serial.print(count1);
  281. Serial.print(" ");
  282. Serial.print(count2);
  283. Serial.print(" ");
  284. Serial.print(count3);
  285. Serial.println();
  286. Serial.print("Test std::mutex lock ");
  287. std::mutex g_mutex;
  288. {
  289. std::lock_guard<std::mutex> lock(g_mutex);
  290. if (g_mutex.try_lock() == 0) Serial.println("OK");
  291. else Serial.println("***FAIL***");
  292. }
  293. Serial.print("Test std::mutex unlock ");
  294. if (g_mutex.try_lock() == 1) Serial.println("OK");
  295. else Serial.println("***FAIL***");
  296. g_mutex.unlock();
  297. Serial.print("Test Grab init ");
  298. subinst.h(10);
  299. ThreadWrap(subinst, sub2);
  300. #define subinst ThreadClone(sub2)
  301. if(subinst.getValue() == 10) Serial.println("OK");
  302. else Serial.println("***FAIL***");
  303. Serial.print("Test Grab set ");
  304. subinst.h(25);
  305. if(subinst.getValue() == 25) Serial.println("OK");
  306. else Serial.println("***FAIL***");
  307. Serial.print("Test Grab lock ");
  308. if (subinst.test(&(sub2.getLock())) == 1) Serial.println("OK");
  309. else Serial.println("***FAIL***");
  310. Serial.print("Test thread stack overflow ");
  311. uint8_t *mstack = new uint8_t[1024];
  312. stack_id = threads.addThread(recursive_thread, 0, 512, mstack+512);
  313. threads.delay(2000);
  314. threads.kill(stack_id);
  315. if (stack_fault) Serial.println("OK");
  316. else Serial.println("***FAIL***");
  317. delete[] mstack;
  318. }
  319. void runloop() {
  320. static int timeloop = millis();
  321. static int mx = 0;
  322. static int count = 0;
  323. if (millis() - mx > 5000) {
  324. Serial.print(count);
  325. Serial.print(": ");
  326. Serial.print((millis() - timeloop)/1000);
  327. Serial.print(" sec ");
  328. showp();
  329. count++;
  330. mx = millis();
  331. }
  332. }
  333. void setup() {
  334. delay(1000);
  335. runtest();
  336. Serial.println("Test infinite loop (will not end)");
  337. }
  338. void loop() {
  339. runloop();
  340. }