swTimer.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632
  1. /* swTimer.c SDK timer suspend API
  2. *
  3. * SDK software timer API info:
  4. *
  5. * The SDK software timer uses a linked list called `os_timer_t* timer_list` to keep track of
  6. * all currently armed timers.
  7. *
  8. * The SDK software timer API executes in a task. The priority of this task in relation to the
  9. * application level tasks is unknown (at time of writing).
  10. *
  11. *
  12. * To determine when a timer's callback should be executed, the respective timer's `timer_expire`
  13. * variable is compared to the hardware counter(FRC2), then, if the timer's `timer_expire` is
  14. * less than the current FRC2 count, the timer's callback is fired.
  15. *
  16. * The timers in this list are organized in an ascending order starting with the timer
  17. * with the lowest timer_expire.
  18. *
  19. * When a timer expires that has a timer_period greater than 0, timer_expire is changed to
  20. * current FRC2 + timer_period, then the timer is inserted back in to the list in the correct position.
  21. *
  22. * when using millisecond(default) timers, FRC2 resolution is 312.5 ticks per millisecond.
  23. *
  24. *
  25. * TIMER SUSPEND API:
  26. *
  27. * Timer registry:
  28. * void sw_timer_register(void* timer_ptr);
  29. * - Adds timers to the timer registry by adding it to a queue that is later
  30. * processed by timer_register_task that performs the registry maintenance
  31. *
  32. * void sw_timer_unregister(void* timer_ptr);
  33. * - Removes timers from the timer registry by adding it to a queue that is later
  34. * processed by timer_unregister_task that performs the registry maintenance
  35. *
  36. *
  37. * int sw_timer_suspend(os_timer_t* timer_ptr);
  38. * - Suspend a single active timer or suspend all active timers.
  39. * - if no timer pointer is provided, timer_ptr == NULL, then all currently active timers will be suspended.
  40. *
  41. * int sw_timer_resume(os_timer_t* timer_ptr);
  42. * - Resume a single suspended timer or resume all suspended timers.
  43. * - if no timer pointer is provided, timer_ptr == NULL, then all currently suspended timers will be resumed.
  44. *
  45. *
  46. *
  47. */
  48. #include "swTimer/swTimer.h"
  49. #include "c_stdio.h"
  50. #include "misc/dynarr.h"
  51. #include "task/task.h"
  52. #ifdef ENABLE_TIMER_SUSPEND
  53. /* Settings */
  54. #define TIMER_REGISTRY_INITIAL_SIZE 10
  55. #ifdef USE_SWTMR_ERROR_STRINGS
  56. static const char* SWTMR_ERROR_STRINGS[]={
  57. [SWTMR_MALLOC_FAIL] = "Out of memory!",
  58. [SWTMR_TIMER_NOT_ARMED] = "Timer is not armed",
  59. // [SWTMR_NULL_PTR] = "A NULL pointer was passed to timer suspend api",
  60. [SWTMR_REGISTRY_NO_REGISTERED_TIMERS] = "No timers in registry",
  61. // [SWTMR_SUSPEND_ARRAY_INITIALIZATION_FAILED] = "Suspend array init fail",
  62. // [SWTMR_SUSPEND_ARRAY_ADD_FAILED] = "Unable to add suspended timer to array",
  63. // [SWTMR_SUSPEND_ARRAY_REMOVE_FAILED] = "Unable to remove suspended timer from array",
  64. [SWTMR_SUSPEND_TIMER_ALREADY_SUSPENDED] = "Already suspended",
  65. [SWTMR_SUSPEND_TIMER_ALREADY_REARMED] = "Already been re-armed",
  66. [SWTMR_SUSPEND_NO_SUSPENDED_TIMERS] = "No suspended timers",
  67. [SWTMR_SUSPEND_TIMER_NOT_SUSPENDED] = "Not suspended",
  68. };
  69. #endif
  70. /* Private Function Declarations */
  71. static inline bool timer_armed_check(os_timer_t* timer_ptr);
  72. static inline int timer_do_suspend(os_timer_t* timer_ptr);
  73. static inline int timer_do_resume_single(os_timer_t** suspended_timer_ptr);
  74. static void timer_register_task(task_param_t param, uint8 priority);
  75. static inline os_timer_t** timer_registry_check(os_timer_t* timer_ptr);
  76. static inline void timer_registry_remove_unarmed(void);
  77. static inline os_timer_t** timer_suspended_check(os_timer_t* timer_ptr);
  78. static void timer_unregister_task(task_param_t param, uint8 priority);
  79. /* Private Variable Definitions */
  80. static task_handle_t timer_reg_task_id = false;
  81. static task_handle_t timer_unreg_task_id = false;
  82. static dynarr_t timer_registry = {0};
  83. static dynarr_t suspended_timers = {0};
  84. typedef struct registry_queue{
  85. struct registry_queue* next;
  86. os_timer_t* timer_ptr;
  87. }registry_queue_t;
  88. static registry_queue_t* register_queue = NULL;
  89. static registry_queue_t* unregister_queue = NULL;
  90. /* Private Function Definitions */
  91. //NOTE: Interrupts are temporarily blocked during the execution of this function
  92. static inline bool timer_armed_check(os_timer_t* timer_ptr){
  93. bool retval = FALSE;
  94. // we are messing around with the SDK timer structure here, may not be necessary, better safe than sorry though.
  95. ETS_INTR_LOCK();
  96. os_timer_t* timer_list_ptr = timer_list; //get head node pointer of timer_list
  97. //if present find timer_ptr in timer_list rand return result
  98. while(timer_list_ptr != NULL){
  99. if(timer_list_ptr == timer_ptr){
  100. retval = TRUE;
  101. break;
  102. }
  103. timer_list_ptr = timer_list_ptr->timer_next;
  104. }
  105. //we are done with timer_list, it is now safe to unlock interrupts
  106. ETS_INTR_UNLOCK();
  107. //return value
  108. return retval;
  109. }
  110. static inline int timer_do_suspend(os_timer_t* timer_ptr){
  111. if(timer_ptr == NULL){
  112. SWTMR_ERR("timer_ptr is invalid");
  113. return SWTMR_FAIL;
  114. }
  115. volatile uint32 frc2_count = RTC_REG_READ(FRC2_COUNT_ADDRESS);
  116. if(timer_armed_check(timer_ptr) == FALSE){
  117. return SWTMR_TIMER_NOT_ARMED;
  118. }
  119. os_timer_t** suspended_timer_ptr = timer_suspended_check(timer_ptr);
  120. uint32 expire_temp = 0;
  121. uint32 period_temp = timer_ptr->timer_period;
  122. if(timer_ptr->timer_expire < frc2_count){
  123. expire_temp = 5; // 16 us in ticks (1 tick = ~3.2 us) (arbitrarily chosen value)
  124. }
  125. else{
  126. expire_temp = timer_ptr->timer_expire - frc2_count;
  127. }
  128. ets_timer_disarm(timer_ptr);
  129. timer_unregister_task((task_param_t)timer_ptr, false);
  130. timer_ptr->timer_expire = expire_temp;
  131. timer_ptr->timer_period = period_temp;
  132. if(suspended_timers.data_ptr == NULL){
  133. if(!dynarr_init(&suspended_timers, 10, sizeof(os_timer_t*))){
  134. SWTMR_ERR("Suspend array init fail");
  135. return SWTMR_FAIL;
  136. }
  137. }
  138. if(suspended_timer_ptr == NULL){
  139. // return SWTMR_SUSPEND_TIMER_ALREADY_SUSPENDED;
  140. if(!dynarr_add(&suspended_timers, &timer_ptr, sizeof(timer_ptr))){
  141. SWTMR_ERR("Unable to add suspended timer to array");
  142. return SWTMR_FAIL;
  143. }
  144. }
  145. return SWTMR_OK;
  146. }
  147. //NOTE: Interrupts are temporarily blocked during the execution of this function
  148. static inline int timer_do_resume_single(os_timer_t** suspended_timer_ptr){
  149. if(suspended_timer_ptr == NULL){
  150. SWTMR_ERR("suspended_timer_ptr is invalid");
  151. return SWTMR_FAIL;
  152. }
  153. os_timer_t* timer_list_ptr = NULL;
  154. os_timer_t* resume_timer_ptr = *suspended_timer_ptr;
  155. volatile uint32 frc2_count = RTC_REG_READ(FRC2_COUNT_ADDRESS);
  156. //verify timer has not been rearmed
  157. if(timer_armed_check(resume_timer_ptr) == TRUE){
  158. SWTMR_DBG("Timer(%p) already rearmed, removing from array", resume_timer_ptr);
  159. if(!dynarr_remove(&suspended_timers, suspended_timer_ptr)){
  160. SWTMR_ERR("Failed to remove timer from suspend array");
  161. return SWTMR_FAIL;
  162. }
  163. return SWTMR_OK;
  164. }
  165. //Prepare timer for resume
  166. resume_timer_ptr->timer_expire += frc2_count;
  167. timer_register_task((task_param_t)resume_timer_ptr, false);
  168. SWTMR_DBG("Removing timer(%p) from suspend array", resume_timer_ptr);
  169. //This section performs the actual resume of the suspended timer
  170. // we are messing around with the SDK timer structure here, may not be necessary, better safe than sorry though.
  171. ETS_INTR_LOCK();
  172. timer_list_ptr = timer_list;
  173. while(timer_list_ptr != NULL){
  174. if(resume_timer_ptr->timer_expire > timer_list_ptr->timer_expire){
  175. if(timer_list_ptr->timer_next != NULL){
  176. if(resume_timer_ptr->timer_expire < timer_list_ptr->timer_next->timer_expire){
  177. resume_timer_ptr->timer_next = timer_list_ptr->timer_next;
  178. timer_list_ptr->timer_next = resume_timer_ptr;
  179. break;
  180. }
  181. else{
  182. //next timer in timer_list
  183. }
  184. }
  185. else{
  186. timer_list_ptr->timer_next = resume_timer_ptr;
  187. resume_timer_ptr->timer_next = NULL;
  188. break;
  189. }
  190. }
  191. else if(timer_list_ptr == timer_list){
  192. resume_timer_ptr->timer_next=timer_list_ptr;
  193. timer_list = timer_list_ptr = resume_timer_ptr;
  194. break;
  195. }
  196. timer_list_ptr = timer_list_ptr->timer_next;
  197. }
  198. //we no longer need to block interrupts
  199. ETS_INTR_UNLOCK();
  200. return SWTMR_OK;
  201. }
  202. static void timer_register_task(task_param_t param, uint8 priority){
  203. if(timer_registry.data_ptr==NULL){
  204. if(!dynarr_init(&timer_registry, TIMER_REGISTRY_INITIAL_SIZE, sizeof(os_timer_t*))){
  205. SWTMR_ERR("timer registry init Fail!");
  206. return;
  207. }
  208. }
  209. os_timer_t* timer_ptr = NULL;
  210. //if a timer pointer is provided, override normal queue processing behavior
  211. if(param != 0){
  212. timer_ptr = (os_timer_t*)param;
  213. }
  214. else{
  215. //process an item in the register queue
  216. if(register_queue == NULL){
  217. /**/SWTMR_ERR("ERROR: REGISTER QUEUE EMPTY");
  218. return;
  219. }
  220. registry_queue_t* queue_temp = register_queue;
  221. register_queue = register_queue->next;
  222. timer_ptr = queue_temp->timer_ptr;
  223. c_free(queue_temp);
  224. if(register_queue != NULL){
  225. SWTMR_DBG("register_queue not empty, posting task");
  226. task_post_low(timer_reg_task_id, false);
  227. }
  228. }
  229. os_timer_t** suspended_tmr_ptr = timer_suspended_check(timer_ptr);
  230. if(suspended_tmr_ptr != NULL){
  231. if(!dynarr_remove(&suspended_timers, suspended_tmr_ptr)){
  232. SWTMR_ERR("failed to remove %p from suspend registry", suspended_tmr_ptr);
  233. }
  234. SWTMR_DBG("removed timer from suspended timers");
  235. }
  236. if(timer_registry_check(timer_ptr) != NULL){
  237. /**/SWTMR_DBG("timer(%p) found in registry, returning", timer_ptr);
  238. return;
  239. }
  240. if(!dynarr_add(&timer_registry, &timer_ptr, sizeof(timer_ptr))){
  241. /**/SWTMR_ERR("Registry append failed");
  242. return;
  243. }
  244. return;
  245. }
  246. static inline os_timer_t** timer_registry_check(os_timer_t* timer_ptr){
  247. if(timer_registry.data_ptr == NULL){
  248. return NULL;
  249. }
  250. if(timer_registry.used > 0){
  251. os_timer_t** timer_registry_array = timer_registry.data_ptr;
  252. for(uint32 i=0; i < timer_registry.used; i++){
  253. if(timer_registry_array[i] == timer_ptr){
  254. /**/SWTMR_DBG("timer(%p) is registered", timer_registry_array[i]);
  255. return &timer_registry_array[i];
  256. }
  257. }
  258. }
  259. return NULL;
  260. }
  261. static inline void timer_registry_remove_unarmed(void){
  262. if(timer_registry.data_ptr == NULL){
  263. return;
  264. }
  265. if(timer_registry.used > 0){
  266. os_timer_t** timer_registry_array = timer_registry.data_ptr;
  267. for(uint32 i=0; i < timer_registry.used; i++){
  268. if(timer_armed_check(timer_registry_array[i]) == FALSE){
  269. timer_unregister_task((task_param_t)timer_registry_array[i], false);
  270. }
  271. }
  272. }
  273. }
  274. static inline os_timer_t** timer_suspended_check(os_timer_t* timer_ptr){
  275. if(suspended_timers.data_ptr == NULL){
  276. return NULL;
  277. }
  278. if(suspended_timers.used > 0){
  279. os_timer_t** suspended_timer_array = suspended_timers.data_ptr;
  280. for(uint32 i=0; i < suspended_timers.used; i++){
  281. if(suspended_timer_array[i] == timer_ptr){
  282. return &suspended_timer_array[i];
  283. }
  284. }
  285. }
  286. return NULL;
  287. }
  288. static void timer_unregister_task(task_param_t param, uint8 priority){
  289. if(timer_registry.data_ptr == NULL){
  290. return;
  291. }
  292. os_timer_t* timer_ptr = NULL;
  293. if(param != false){
  294. timer_ptr = (os_timer_t*)param;
  295. }
  296. else{
  297. if(unregister_queue == NULL) {
  298. SWTMR_ERR("ERROR register queue empty");
  299. return;
  300. }
  301. registry_queue_t* queue_temp = unregister_queue;
  302. timer_ptr = queue_temp->timer_ptr;
  303. unregister_queue = unregister_queue->next;
  304. c_free(queue_temp);
  305. if(unregister_queue != NULL){
  306. SWTMR_DBG("unregister_queue not empty, posting task");
  307. task_post_low(timer_unreg_task_id, false);
  308. }
  309. }
  310. if(timer_armed_check(timer_ptr) == TRUE){
  311. SWTMR_DBG("%p still armed, can't remove from registry", timer_ptr);
  312. return;
  313. }
  314. os_timer_t** registry_ptr = timer_registry_check(timer_ptr);
  315. if(registry_ptr != NULL){
  316. if(!dynarr_remove(&timer_registry, registry_ptr)){
  317. /**/SWTMR_ERR("Failed to remove timer from registry");
  318. /**/SWTMR_DBG("registry_ptr = %p", registry_ptr);
  319. return;
  320. }
  321. }
  322. else{
  323. //timer not in registry
  324. }
  325. return;
  326. }
  327. /* Global Function Definitions */
  328. #if defined(SWTMR_DEBUG)
  329. void swtmr_print_registry(void){
  330. volatile uint32 frc2_count = RTC_REG_READ(FRC2_COUNT_ADDRESS);
  331. uint32 time_till_fire = 0;
  332. uint32 time = system_get_time();
  333. timer_registry_remove_unarmed();
  334. time = system_get_time()-time;
  335. /**/SWTMR_DBG("registry_remove_unarmed_timers() took %u us", time);
  336. os_timer_t** timer_array = timer_registry.data_ptr;
  337. c_printf("\n array used(%u)/size(%u)\ttotal size(bytes)=%u\n FRC2 COUNT %u\n",
  338. timer_registry.used, timer_registry.array_size, timer_registry.array_size * timer_registry.data_size, frc2_count);
  339. c_printf("\n Registered timer array contents:\n");
  340. c_printf(" %-5s %-10s %-10s %-13s %-10s %-10s %-10s\n", "idx", "ptr", "expire", "period(tick)", "period(ms)", "fire(tick)", "fire(ms)");
  341. for(uint32 i=0; i < timer_registry.used; i++){
  342. time_till_fire = (timer_array[i]->timer_expire - frc2_count);
  343. c_printf(" %-5d %-10p %-10d %-13d %-10d %-10d %-10d\n", i, timer_array[i], timer_array[i]->timer_expire, timer_array[i]->timer_period, (uint32)(timer_array[i]->timer_period/312.5), time_till_fire, (uint32)(time_till_fire/312.5));
  344. }
  345. return;
  346. }
  347. void swtmr_print_suspended(void){
  348. os_timer_t** susp_timer_array = suspended_timers.data_ptr;
  349. c_printf("\n array used(%u)/size(%u)\ttotal size(bytes)=%u\n",
  350. suspended_timers.used, suspended_timers.array_size, suspended_timers.array_size * suspended_timers.data_size);
  351. c_printf("\n Suspended timer array contents:\n");
  352. c_printf(" %-5s %-10s %-15s %-15s %-14s %-10s\n", "idx", "ptr", "time left(tick)", "time left(ms)", "period(tick)", "period(ms)");
  353. for(uint32 i=0; i < suspended_timers.used; i++){
  354. c_printf(" %-5d %-10p %-15d %-15d %-14d %-10d\n", i, susp_timer_array[i], susp_timer_array[i]->timer_expire, (uint32)(susp_timer_array[i]->timer_expire/312.5), susp_timer_array[i]->timer_period, (uint32)(susp_timer_array[i]->timer_period/312.5));
  355. }
  356. return;
  357. }
  358. void swtmr_print_timer_list(void){
  359. volatile uint32 frc2_count=RTC_REG_READ(FRC2_COUNT_ADDRESS);
  360. os_timer_t* timer_list_ptr=NULL;
  361. uint32 time_till_fire=0;
  362. c_printf("\n\tcurrent FRC2 count:%u\n", frc2_count);
  363. c_printf(" timer_list contents:\n");
  364. c_printf(" %-10s %-10s %-10s %-10s %-10s %-10s %-10s\n", "ptr", "expire", "period", "func", "arg", "fire(tick)", "fire(ms)");
  365. ETS_INTR_LOCK();
  366. timer_list_ptr=timer_list;
  367. while(timer_list_ptr != NULL){
  368. time_till_fire=(timer_list_ptr->timer_expire - frc2_count) / 312.5;
  369. c_printf(" %-10p %-10u %-10u %-10p %-10p %-10u %-10u\n",
  370. timer_list_ptr, (uint32)(timer_list_ptr->timer_expire),
  371. (uint32)(timer_list_ptr->timer_period ), timer_list_ptr->timer_func,
  372. timer_list_ptr->timer_arg, (timer_list_ptr->timer_expire - frc2_count), time_till_fire);
  373. timer_list_ptr=timer_list_ptr->timer_next;
  374. }
  375. ETS_INTR_UNLOCK();
  376. c_printf(" NOTE: some timers in the above list belong to the SDK and can not be suspended\n");
  377. return;
  378. }
  379. #endif
  380. int swtmr_suspend(os_timer_t* timer_ptr){
  381. int return_value = SWTMR_OK;
  382. if(timer_ptr != NULL){
  383. // Timer pointer was provided, suspending specified timer
  384. return_value = timer_do_suspend(timer_ptr);
  385. if(return_value != SWTMR_OK){
  386. return return_value;
  387. }
  388. }
  389. else{
  390. //timer pointer not found, suspending all timers
  391. if(timer_registry.data_ptr == NULL){
  392. return SWTMR_REGISTRY_NO_REGISTERED_TIMERS;
  393. }
  394. timer_registry_remove_unarmed();
  395. os_timer_t** tmr_reg_arr = timer_registry.data_ptr;
  396. os_timer_t* temp_ptr = tmr_reg_arr[0];
  397. while(temp_ptr != NULL){
  398. return_value = timer_do_suspend(temp_ptr);
  399. if(return_value != SWTMR_OK){
  400. return return_value;
  401. }
  402. temp_ptr = tmr_reg_arr[0];
  403. }
  404. }
  405. return return_value;
  406. }
  407. int swtmr_resume(os_timer_t* timer_ptr){
  408. if(suspended_timers.data_ptr == NULL){
  409. return SWTMR_SUSPEND_NO_SUSPENDED_TIMERS;
  410. }
  411. os_timer_t** suspended_tmr_array = suspended_timers.data_ptr;
  412. os_timer_t** suspended_timer_ptr = NULL;
  413. int retval=SWTMR_OK;
  414. if(timer_ptr != NULL){
  415. suspended_timer_ptr = timer_suspended_check(timer_ptr);
  416. if(suspended_timer_ptr == NULL){
  417. //timer not suspended
  418. return SWTMR_SUSPEND_TIMER_NOT_SUSPENDED;
  419. }
  420. retval = timer_do_resume_single(suspended_timer_ptr);
  421. if(retval != SWTMR_OK){
  422. return retval;
  423. }
  424. }
  425. else{
  426. suspended_timer_ptr = &suspended_tmr_array[0];
  427. while(suspended_timers.used > 0){
  428. retval = timer_do_resume_single(suspended_timer_ptr);
  429. if(retval != SWTMR_OK){
  430. SWTMR_ERR("Unable to continue resuming timers, error(%u)", retval);
  431. return retval;
  432. }
  433. suspended_timer_ptr = &suspended_tmr_array[0];
  434. }
  435. }
  436. return SWTMR_OK;
  437. }
  438. void swtmr_register(void* timer_ptr){
  439. if(timer_ptr == NULL){
  440. SWTMR_DBG("error: timer_ptr is NULL");
  441. return;
  442. }
  443. registry_queue_t* queue_temp = c_zalloc(sizeof(registry_queue_t));
  444. if(queue_temp == NULL){
  445. SWTMR_ERR("MALLOC FAIL! req:%u, free:%u", sizeof(registry_queue_t), system_get_free_heap_size());
  446. return;
  447. }
  448. queue_temp->timer_ptr = timer_ptr;
  449. if(register_queue == NULL){
  450. register_queue = queue_temp;
  451. if(timer_reg_task_id == false) timer_reg_task_id = task_get_id(timer_register_task);
  452. task_post_low(timer_reg_task_id, false);
  453. SWTMR_DBG("queue empty, adding timer(%p) to queue and posting task", timer_ptr);
  454. }
  455. else{
  456. registry_queue_t* register_queue_tail = register_queue;
  457. while(register_queue_tail->next != NULL){
  458. register_queue_tail = register_queue_tail->next;
  459. }
  460. register_queue_tail->next = queue_temp;
  461. SWTMR_DBG("queue NOT empty, appending timer(%p) to queue", timer_ptr);
  462. }
  463. return;
  464. }
  465. void swtmr_unregister(void* timer_ptr){
  466. if(timer_ptr == NULL){
  467. SWTMR_DBG("error: timer_ptr is NULL");
  468. return;
  469. }
  470. registry_queue_t* queue_temp = c_zalloc(sizeof(registry_queue_t));
  471. if(queue_temp == NULL){
  472. SWTMR_ERR("MALLOC FAIL! req:%u, free:%u", sizeof(registry_queue_t), system_get_free_heap_size());
  473. return;
  474. }
  475. queue_temp->timer_ptr=timer_ptr;
  476. if(unregister_queue == NULL){
  477. unregister_queue = queue_temp;
  478. if(timer_unreg_task_id==false) timer_unreg_task_id=task_get_id(timer_unregister_task);
  479. task_post_low(timer_unreg_task_id, false);
  480. SWTMR_DBG("queue empty, adding timer(%p) to queue and posting task", timer_ptr);
  481. }
  482. else{
  483. registry_queue_t* unregister_queue_tail=unregister_queue;
  484. while(unregister_queue_tail->next != NULL){
  485. unregister_queue_tail=unregister_queue_tail->next;
  486. }
  487. unregister_queue_tail->next = queue_temp;
  488. // SWTMR_DBG("queue NOT empty, appending timer(%p) to queue", timer_ptr);
  489. }
  490. return;
  491. }
  492. const char* swtmr_errorcode2str(int error_value){
  493. #ifdef USE_SWTMR_ERROR_STRINGS
  494. if(SWTMR_ERROR_STRINGS[error_value] == NULL){
  495. SWTMR_ERR("error string %d not found", error_value);
  496. return NULL;
  497. }
  498. else{
  499. return SWTMR_ERROR_STRINGS[error_value];
  500. }
  501. #else
  502. SWTMR_ERR("error(%u)", error_value);
  503. return "ERROR! for more info, use debug build";
  504. #endif
  505. }
  506. bool swtmr_suspended_test(os_timer_t* timer_ptr){
  507. os_timer_t** test_var = timer_suspended_check(timer_ptr);
  508. if(test_var == NULL){
  509. return false;
  510. }
  511. return true;
  512. }
  513. #endif