os_wrapper.c 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440
  1. /*
  2. * Copyright (c) 2017 Actions Semi Co., Ltd.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. * Author: wh<wanghui@actions-semi.com>
  16. *
  17. * Change log:
  18. * 2017/7/7: Created by wh.
  19. */
  20. #include "os_common_api.h"
  21. #include "string.h"
  22. #include <zephyr.h>
  23. #define MAX_THREAD_TERMINAL_NUM 3
  24. struct thread_terminal_info_t{
  25. os_thread *wait_terminal_thread;
  26. os_sem terminal_sem;
  27. };
  28. static struct thread_terminal_info_t thread_terminal_info[MAX_THREAD_TERMINAL_NUM] = {0};
  29. /**thread function */
  30. int os_thread_create(char *stack, size_t stack_size,
  31. void (*entry)(void *, void *, void*),
  32. void *p1, void *p2, void *p3,
  33. int prio, u32_t options, int delay) {
  34. k_tid_t tid = NULL;
  35. os_thread *thread = NULL;
  36. thread = (os_thread *)stack;
  37. tid = k_thread_create(thread, (os_thread_stack_t *)&stack[sizeof(os_thread)],
  38. stack_size - sizeof(os_thread),
  39. entry,
  40. p1, p2, p3,
  41. prio,
  42. options,
  43. SYS_TIMEOUT_MS(delay));
  44. return (int)tid;
  45. }
  46. int os_thread_prepare_terminal(int tid)
  47. {
  48. int ret = 0;
  49. struct thread_terminal_info_t *terminal_info = NULL;
  50. os_sched_lock();
  51. for (int i = 0; i < MAX_THREAD_TERMINAL_NUM; i++){
  52. if(!thread_terminal_info[i].wait_terminal_thread) {
  53. terminal_info = &thread_terminal_info[i];
  54. break;
  55. }
  56. }
  57. if (!terminal_info) {
  58. SYS_LOG_ERR("%d busy\n", tid);
  59. ret = -EBUSY;
  60. goto exit;
  61. }
  62. terminal_info->wait_terminal_thread = (os_thread *)tid;
  63. os_sem_init(&terminal_info->terminal_sem, 0, 1);
  64. SYS_LOG_INF(" 0x%x ok\n",tid);
  65. exit:
  66. os_sched_unlock();
  67. return ret;
  68. }
  69. int os_thread_wait_terminal(int tid)
  70. {
  71. int ret = 0;
  72. struct thread_terminal_info_t *terminal_info = NULL;
  73. os_sched_lock();
  74. for (int i = 0; i < MAX_THREAD_TERMINAL_NUM; i++){
  75. if((uintptr_t)thread_terminal_info[i].wait_terminal_thread == tid) {
  76. terminal_info = &thread_terminal_info[i];
  77. }
  78. }
  79. os_sched_unlock();
  80. if (!terminal_info) {
  81. SYS_LOG_ERR("terminal tid %d not found\n",tid);
  82. ret = -EBUSY;
  83. }
  84. if (k_thread_join(terminal_info->wait_terminal_thread, SYS_TIMEOUT_MS(5000))) {
  85. SYS_LOG_ERR("timeout \n");
  86. ret = -EBUSY;
  87. }
  88. os_sched_lock();
  89. terminal_info->wait_terminal_thread = NULL;
  90. os_sched_unlock();
  91. SYS_LOG_INF(" 0x%x ok\n",tid);
  92. return ret;
  93. }
  94. const char *os_thread_get_name_by_prio(int prio)
  95. {
  96. struct k_thread *thread_list = (struct k_thread *)(_kernel.threads);
  97. unsigned int key = irq_lock();
  98. while (thread_list != NULL) {
  99. int thread_prio = k_thread_priority_get(thread_list);
  100. if (prio == thread_prio) {
  101. break;
  102. }
  103. thread_list = (struct k_thread *)thread_list->next_thread;
  104. }
  105. irq_unlock(key);
  106. if (thread_list) {
  107. return k_thread_name_get(thread_list);
  108. }
  109. return "NULL";
  110. }
  111. /**message function*/
  112. K_MBOX_DEFINE(global_mailbox);
  113. /** message pool */
  114. struct msg_info
  115. {
  116. os_sem msg_sem;
  117. #ifdef CONFIG_MESSAGE_DEBUG
  118. os_tid_t sender;
  119. os_tid_t receiver;
  120. #endif
  121. char msg[MSG_MEM_SIZE];
  122. };
  123. struct msg_pool
  124. {
  125. int pool_size;
  126. struct msg_info *pool;
  127. };
  128. static struct msg_info msg_pool_buff[CONFIG_NUM_MBOX_ASYNC_MSGS];
  129. static struct msg_pool globle_msg_pool= {
  130. .pool_size = CONFIG_NUM_MBOX_ASYNC_MSGS,
  131. .pool = (struct msg_info *)&msg_pool_buff,
  132. };
  133. static struct msg_info *msg_pool_get_free_msg_info(void)
  134. {
  135. struct msg_pool *pool = &globle_msg_pool;
  136. struct msg_info *result = NULL;
  137. for (uint8_t i = 0 ; i < pool->pool_size; i++) {
  138. struct msg_info * msg_content = &pool->pool[i];
  139. if (k_sem_take(&msg_content->msg_sem, SYS_TIMEOUT_MS(OS_NO_WAIT)) == 0) {
  140. memset(&msg_content->msg, 0, MSG_MEM_SIZE);
  141. result = msg_content;
  142. break;
  143. } else {
  144. //SYS_LOG_WRN("msg %d is busy\n", i);
  145. }
  146. }
  147. return result;
  148. }
  149. int msg_pool_get_free_msg_num(void)
  150. {
  151. struct msg_pool *pool = &globle_msg_pool;
  152. int used_num = 0;
  153. unsigned int key = irq_lock();
  154. for (uint8_t i = 0 ; i < pool->pool_size; i++) {
  155. struct msg_info * msg_content = &pool->pool[i];
  156. if (os_sem_take(&msg_content->msg_sem, OS_NO_WAIT) != 0) {
  157. used_num++;
  158. } else {
  159. os_sem_give(&msg_content->msg_sem);
  160. }
  161. }
  162. irq_unlock(key);
  163. return pool->pool_size - used_num;
  164. }
  165. void msg_pool_dump(void(*dump_fn)(os_tid_t sender, os_tid_t receiver,
  166. const char *content, int max_size))
  167. {
  168. struct msg_pool *pool = &globle_msg_pool;
  169. printk("free msg cnt %d/%d\n", msg_pool_get_free_msg_num(), pool->pool_size);
  170. for (uint8_t i = 0 ; i < pool->pool_size; i++) {
  171. struct msg_info * msg_content = &pool->pool[i];
  172. if (os_sem_take(&msg_content->msg_sem, OS_NO_WAIT) != 0) {
  173. printk("busy msg %d:\n", i);
  174. #ifdef CONFIG_MESSAGE_DEBUG
  175. dump_fn(msg_content->sender, msg_content->receiver, msg_content->msg, MSG_MEM_SIZE);
  176. #else
  177. dump_fn(OS_ANY, OS_ANY, msg_content->msg, MSG_MEM_SIZE);
  178. #endif
  179. } else {
  180. os_sem_give(&msg_content->msg_sem);
  181. }
  182. }
  183. }
  184. #if 0
  185. static void os_sync_msg_callback(struct os_app_msg* msg, int result, void* not_used)
  186. {
  187. if (msg->sync_sem) {
  188. #ifdef CONFIG_MESSAGE_DEBUG
  189. printk("--(%s->%s)-- %s %d: type_id %d, msg_id %d, e_time %u\n",
  190. "",
  191. msg_manager_get_current(),
  192. __func__, __LINE__,
  193. msg->type,
  194. msg->cmd,
  195. k_uptime_get_32());
  196. #endif
  197. os_sem_give(msg->sync_sem);
  198. }
  199. }
  200. int os_send_sync_msg(void *receiver, void *msg, int msg_size)
  201. {
  202. os_mbox_msg send_msg;
  203. char msg_content[MSG_MEM_SIZE];
  204. struct k_sem sync_sem;
  205. struct os_app_msg *tmp_msg = NULL;
  206. __ASSERT(!_is_in_isr(),"send messag in isr");
  207. memcpy(&msg_content, msg, msg_size);
  208. tmp_msg = &msg_content;
  209. tmp_msg->callback = os_sync_msg_callback;
  210. tmp_msg->sync_sem = &sync_sem;
  211. k_sem_init(&sync_sem, 0, UINT_MAX);
  212. /* prepare to send message */
  213. send_msg.info = msg_size;
  214. send_msg.size = msg_size;
  215. send_msg.tx_data = &msg_content;
  216. send_msg.tx_target_thread = (os_tid_t)receiver;
  217. /* send message containing most current data and loop around */
  218. os_mbox_put(&global_mailbox, &send_msg, SYS_TIMEOUT_MS(OS_FOREVER));
  219. os_sem_take(&sync_sem, OS_FOREVER);
  220. return 0;
  221. }
  222. #endif
  223. int os_send_async_msg(void *receiver, void *msg, int msg_size)
  224. {
  225. os_mbox_msg send_msg;
  226. struct msg_info *msg_content;
  227. __ASSERT(!k_is_in_isr(),"send messag in isr");
  228. msg_content = msg_pool_get_free_msg_info();
  229. if (!msg_content) {
  230. SYS_LOG_ERR("msg_content is NULL ... ");
  231. return -ENOMEM;
  232. }
  233. memcpy(&msg_content->msg, msg, msg_size);
  234. #ifdef CONFIG_MESSAGE_DEBUG
  235. msg_content->receiver = (os_tid_t)receiver;
  236. msg_content->sender = os_current_get();
  237. #endif
  238. /* prepare to send message */
  239. send_msg.info = msg_size;
  240. send_msg.size = msg_size;
  241. send_msg.tx_data = &msg_content->msg;
  242. send_msg.tx_target_thread = (os_tid_t)receiver;
  243. /* send message containing most current data and loop around */
  244. os_mbox_async_put(&global_mailbox, &send_msg, &msg_content->msg_sem);
  245. return 0;
  246. }
  247. int os_receive_msg(void *msg, int msg_size,int timeout)
  248. {
  249. os_mbox_msg recv_msg;
  250. char buffer[MSG_MEM_SIZE];
  251. memset(buffer, 0, msg_size);
  252. /* prepare to receive message */
  253. recv_msg.info = msg_size;
  254. recv_msg.size = msg_size;
  255. recv_msg.rx_source_thread = OS_ANY;
  256. /* get a data item, waiting as long as needed */
  257. if (os_mbox_get(&global_mailbox, &recv_msg, buffer, SYS_TIMEOUT_MS(timeout))) {
  258. //SYS_LOG_INF("no message");
  259. return -ETIMEDOUT;
  260. }
  261. /* verify that message data was fully received */
  262. if (recv_msg.info != recv_msg.size) {
  263. SYS_LOG_ERR("some message data dropped during transfer! \n ");
  264. SYS_LOG_ERR("sender tried to send %d bytes"
  265. "only received %zu bytes receiver %p \n",
  266. recv_msg.info ,recv_msg.size,os_current_get());
  267. return -EMSGSIZE;
  268. }
  269. /* copy msg from recvied buffer */
  270. memcpy(msg, buffer, msg_size);
  271. return 0;
  272. }
  273. void os_msg_clean(void)
  274. {
  275. os_mbox_clear_msg(&global_mailbox);
  276. }
  277. int os_get_pending_msg_cnt(void)
  278. {
  279. return k_mbox_get_pending_msg_cnt(&global_mailbox, os_current_get());
  280. }
  281. void os_msg_init(void)
  282. {
  283. struct msg_pool *pool = &globle_msg_pool;
  284. for (uint8_t i = 0 ; i < pool->pool_size; i++) {
  285. struct msg_info *msg_content = &pool->pool[i];
  286. os_sem_init(&msg_content->msg_sem, 1, 1);
  287. }
  288. }
  289. static bool low_latency_mode = true;
  290. int system_check_low_latencey_mode(void)
  291. {
  292. #ifdef CONFIG_OS_LOW_LATENCY_MODE
  293. return low_latency_mode ? 1 : 0;
  294. #else
  295. return 0;
  296. #endif
  297. }
  298. void system_set_low_latencey_mode(bool low_latencey)
  299. {
  300. low_latency_mode = low_latencey;
  301. }
  302. s32_t os_sleep(int timeout)
  303. {
  304. return k_sleep(SYS_TIMEOUT_MS(timeout));
  305. }
  306. int os_sem_take(os_sem *sem, s32_t timeout)
  307. {
  308. return k_sem_take(sem, SYS_TIMEOUT_MS(timeout));
  309. }
  310. int os_mutex_lock(os_mutex * mutex, s32_t timeout)
  311. {
  312. return k_mutex_lock(mutex, SYS_TIMEOUT_MS(timeout));
  313. }
  314. int os_delayed_work_submit(os_delayed_work *work, s32_t delay)
  315. {
  316. return k_delayed_work_submit(work, SYS_TIMEOUT_MS(delay));
  317. }
  318. int os_delayed_work_submit_to_queue(os_work_q *work_q, os_delayed_work *work, s32_t delay)
  319. {
  320. return k_delayed_work_submit_to_queue(work_q, work, SYS_TIMEOUT_MS(delay));
  321. }
  322. void *os_fifo_get(os_fifo *fifo, int32_t timeout)
  323. {
  324. return k_fifo_get(fifo, SYS_TIMEOUT_MS(timeout));
  325. }
  326. int os_msgq_put(os_msgq *msgq, const void *data, int32_t timeout)
  327. {
  328. return k_msgq_put(msgq, data, SYS_TIMEOUT_MS(timeout));
  329. }
  330. int os_msgq_get(os_msgq *msgq, void *data, int32_t timeout)
  331. {
  332. return k_msgq_get(msgq, data, SYS_TIMEOUT_MS(timeout));
  333. }
  334. bool os_is_in_isr(void)
  335. {
  336. return k_is_in_isr();
  337. }
  338. void os_printk(const char *fmt, ...)
  339. {
  340. va_list ap;
  341. va_start(ap, fmt);
  342. if (IS_ENABLED(CONFIG_LOG_PRINTK)) {
  343. log_printk(fmt, ap);
  344. } else {
  345. vprintk(fmt, ap);
  346. }
  347. va_end(ap);
  348. }