os_wrapper.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513
  1. /*
  2. * Copyright (c) 2025 Evlers
  3. *
  4. * Permission is hereby granted, free of charge, to any person obtaining a copy
  5. * of this software and associated documentation files (the "Software"), to deal
  6. * in the Software without restriction, including without limitation the rights
  7. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  8. * copies of the Software, and to permit persons to whom the Software is
  9. * furnished to do so, subject to the following conditions:
  10. *
  11. * The above copyright notice and this permission notice shall be included in all
  12. * copies or substantial portions of the Software.
  13. *
  14. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  19. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  20. * SOFTWARE.
  21. *
  22. * Change Logs:
  23. * Date Author Notes
  24. * 2025-01-01 Evlers first implementation
  25. */
  26. #include <stdio.h>
  27. #include <stdlib.h>
  28. #include <stdarg.h>
  29. #include <string.h>
  30. #include "esp_log_level.h"
  31. #include "esp_hosted_config.h"
  32. #include "esp_hosted_log.h"
  33. #include "os_wrapper.h"
  34. /* Wi-Fi headers are reused at ESP-Hosted */
  35. #include "esp_wifi_crypto_types.h"
  36. // #include "esp_private/wifi_os_adapter.h"
  37. #ifdef CONFIG_ESP_SDIO_HOST_INTERFACE
  38. #include "sdio_wrapper.h"
  39. #endif
  40. #ifdef CONFIG_ESP_SPI_HOST_INTERFACE
  41. #include "spi_wrapper.h"
  42. #endif
  43. #ifdef CONFIG_ESP_SPI_HD_HOST_INTERFACE
  44. #include "spi_hd_wrapper.h"
  45. #endif
  46. #ifdef CONFIG_ESP_UART_HOST_INTERFACE
  47. #include "uart_wrapper.h"
  48. #endif
  49. DEFINE_LOG_TAG(os_wrapper_esp);
  50. struct hosted_config_t g_h = HOSTED_CONFIG_INIT_DEFAULT();
  51. /* -------- Memory ---------- */
  52. void *hosted_memcpy(void* dest, const void* src, uint32_t size)
  53. {
  54. if (size && (!dest || !src)) {
  55. if (!dest)
  56. ESP_LOGE(TAG, "%s:%u dest is NULL\n", __func__, __LINE__);
  57. if (!src)
  58. ESP_LOGE(TAG, "%s:%u dest is NULL\n", __func__, __LINE__);
  59. assert(dest);
  60. assert(src);
  61. return NULL;
  62. }
  63. return memcpy(dest, src, size);
  64. }
  65. void *hosted_memset(void* buf, int val, size_t len)
  66. {
  67. return memset(buf, val, len);
  68. }
  69. void *hosted_malloc(size_t size)
  70. {
  71. return rt_malloc(size);
  72. }
  73. void* hosted_calloc(size_t blk_no, size_t size)
  74. {
  75. return rt_calloc(blk_no, size);
  76. }
  77. void hosted_free(void* ptr)
  78. {
  79. rt_free(ptr);
  80. }
  81. void *hosted_realloc(void *mem, size_t newsize)
  82. {
  83. void *p = NULL;
  84. if (newsize == 0) {
  85. HOSTED_FREE(mem);
  86. return NULL;
  87. }
  88. p = hosted_malloc(newsize);
  89. if (p) {
  90. /* zero the memory */
  91. if (mem != NULL) {
  92. hosted_memcpy(p, mem, newsize);
  93. HOSTED_FREE(mem);
  94. }
  95. }
  96. return p;
  97. }
  98. void *hosted_malloc_align(size_t size, size_t align)
  99. {
  100. return rt_malloc_align(size, align);
  101. }
  102. void hosted_free_align(void* ptr)
  103. {
  104. rt_free_align(ptr);
  105. }
  106. void hosted_init_hook(void)
  107. {
  108. /* This is hook to initialize port specific contexts, if any */
  109. }
  110. /* -------- Threads ---------- */
  111. void *hosted_thread_create(char *tname, uint32_t tprio, uint32_t tstack_size, void (*start_routine)(void const *), void *sr_arg)
  112. {
  113. if (!start_routine) {
  114. ESP_LOGE(TAG, "start_routine is mandatory for thread create\n");
  115. return NULL;
  116. }
  117. thread_handle_t thread = rt_thread_create(tname, (void (*)(void *))start_routine, sr_arg, tstack_size, tprio, 10);
  118. if (!thread) {
  119. ESP_LOGE(TAG, "Failed to allocate thread handle");
  120. return NULL;
  121. }
  122. if (rt_thread_startup(thread) != RT_EOK) {
  123. ESP_LOGE(TAG, "Failed to create ctrl path task");
  124. rt_thread_delete(thread);
  125. return NULL;
  126. }
  127. return thread;
  128. }
  129. int hosted_thread_cancel(void *thread_handle)
  130. {
  131. return rt_thread_suspend(thread_handle);
  132. }
  133. /* -------- Sleeps -------------- */
  134. unsigned int hosted_msleep(unsigned int mseconds)
  135. {
  136. rt_thread_mdelay(mseconds);
  137. return 0;
  138. }
  139. unsigned int hosted_usleep(unsigned int useconds)
  140. {
  141. rt_thread_delay(useconds);
  142. return 0;
  143. }
  144. unsigned int hosted_sleep(unsigned int seconds)
  145. {
  146. return hosted_msleep(seconds * 1000UL);
  147. }
  148. /* Non sleepable delays - BLOCKING dead wait */
  149. unsigned int hosted_for_loop_delay(unsigned int number)
  150. {
  151. volatile int idx = 0;
  152. for (idx=0; idx<100*number; idx++) {
  153. }
  154. return 0;
  155. }
  156. /* -------- Queue --------------- */
  157. void * hosted_create_queue(uint32_t qnum_elem, uint32_t qitem_size)
  158. {
  159. return rt_mq_create("esp-hosted", qitem_size, qnum_elem, RT_IPC_FLAG_PRIO);
  160. }
  161. int hosted_queue_item(void * queue_handle, void *item, int timeout)
  162. {
  163. queue_handle_t mq = queue_handle;
  164. return rt_mq_send_wait((queue_handle_t)queue_handle, item, mq->msg_size, rt_tick_from_millisecond(timeout) * 1000);
  165. }
  166. int hosted_dequeue_item(void * queue_handle, void *item, int timeout)
  167. {
  168. queue_handle_t mq = queue_handle;
  169. return (rt_mq_recv(mq, item, mq->msg_size, rt_tick_from_millisecond(timeout) * 1000) <= 0) ? RET_FAIL_TIMEOUT : RET_OK;
  170. }
  171. int hosted_queue_msg_waiting(void * queue_handle)
  172. {
  173. return RET_FAIL;
  174. }
  175. int hosted_destroy_queue(void * queue_handle)
  176. {
  177. return rt_mq_delete((queue_handle_t)queue_handle);
  178. }
  179. int hosted_reset_queue(void * queue_handle)
  180. {
  181. return rt_mq_control((queue_handle_t)queue_handle, RT_IPC_CMD_RESET, NULL);
  182. }
  183. /* -------- Mutex --------------- */
  184. void * hosted_create_mutex(void)
  185. {
  186. return rt_mutex_create("esp_hosted", RT_IPC_FLAG_PRIO);
  187. }
  188. int hosted_unlock_mutex(void * mutex_handle)
  189. {
  190. return rt_mutex_release((mutex_handle_t)mutex_handle);
  191. }
  192. int hosted_lock_mutex(void * mutex_handle, int timeout)
  193. {
  194. return rt_mutex_take((mutex_handle_t)mutex_handle, rt_tick_from_millisecond(timeout) * 1000);
  195. }
  196. int hosted_destroy_mutex(void * mutex_handle)
  197. {
  198. return rt_mutex_delete((mutex_handle_t)mutex_handle);
  199. }
  200. /* -------- Semaphores ---------- */
  201. void * hosted_create_semaphore(int maxCount)
  202. {
  203. semaphore_handle_t semaphore_handle = rt_sem_create("esp-hosted", 0, RT_IPC_FLAG_PRIO);
  204. if (semaphore_handle != NULL)
  205. {
  206. rt_sem_release(semaphore_handle);
  207. }
  208. return semaphore_handle;
  209. }
  210. int hosted_post_semaphore(void * semaphore_handle)
  211. {
  212. return rt_sem_release((semaphore_handle_t)semaphore_handle);
  213. }
  214. FAST_RAM_ATTR int hosted_post_semaphore_from_isr(void * semaphore_handle)
  215. {
  216. return rt_sem_release((semaphore_handle_t)semaphore_handle);
  217. }
  218. int hosted_get_semaphore(void * semaphore_handle, int timeout)
  219. {
  220. return rt_sem_take((semaphore_handle_t)semaphore_handle, rt_tick_from_millisecond(timeout) * 1000);
  221. }
  222. int hosted_destroy_semaphore(void * semaphore_handle)
  223. {
  224. return rt_sem_delete((semaphore_handle_t)semaphore_handle);
  225. }
  226. #ifdef CONFIG_USE_MEMPOOL
  227. static void * hosted_create_spinlock(void)
  228. {
  229. RT_DEFINE_SPINLOCK(spin_dummy);
  230. spinlock_handle_t *spin_id = NULL;
  231. spin_id = (spinlock_handle_t*)hosted_malloc(
  232. sizeof(spinlock_handle_t));
  233. if (!spin_id) {
  234. ESP_LOGE(TAG, "mut allocation failed\n");
  235. return NULL;
  236. }
  237. spin_id->lock = spin_dummy;
  238. rt_spin_lock_init(spin_id);
  239. return spin_id;
  240. }
  241. void* hosted_create_lock_mempool(void)
  242. {
  243. return hosted_create_spinlock();
  244. }
  245. void hosted_lock_mempool(void *lock_handle)
  246. {
  247. assert(lock_handle);
  248. rt_spin_lock((spinlock_handle_t)lock_handle);
  249. }
  250. void hosted_unlock_mempool(void *lock_handle)
  251. {
  252. assert(lock_handle);
  253. rt_spin_unlock((spinlock_handle_t)lock_handle);
  254. }
  255. #endif
  256. /* -------- Timers ---------- */
  257. void *hosted_timer_start(int duration, int type, void (*timeout_handler)(void *), void *arg)
  258. {
  259. rt_timer_t timer_handle = rt_timer_create("esp-hosted", (void (*)(void *))timeout_handler, arg,
  260. rt_tick_from_millisecond(duration) * 1000,
  261. type);
  262. if (timer_handle == NULL)
  263. {
  264. ESP_LOGE(TAG, "Failed to allocate timer handle");
  265. return NULL;
  266. }
  267. if (rt_timer_start(timer_handle) != RT_EOK)
  268. {
  269. ESP_LOGE(TAG, "Failed to start timer, destroying timer");
  270. rt_timer_delete(timer_handle);
  271. return NULL;
  272. }
  273. return timer_handle;
  274. }
  275. int hosted_timer_stop(void *timer_handle)
  276. {
  277. if (!timer_handle) {
  278. ESP_LOGE(TAG, "Uninitialized timer handle");
  279. return ESP_FAIL;
  280. }
  281. if (rt_timer_stop(timer_handle) != RT_EOK)
  282. {
  283. ESP_LOGE(TAG, "Unable to stop timer");
  284. return ESP_FAIL;
  285. }
  286. if (rt_timer_delete(timer_handle) != RT_EOK)
  287. {
  288. ESP_LOGE(TAG, "Unable to delete timer");
  289. return ESP_FAIL;
  290. }
  291. return ESP_OK;
  292. }
  293. /* GPIO */
  294. int hosted_config_gpio(void* gpio_port, uint32_t gpio_num, uint32_t mode)
  295. {
  296. rt_pin_mode(gpio_num, mode);
  297. return 0;
  298. }
  299. int hosted_config_gpio_as_interrupt(void* gpio_port, uint32_t gpio_num, uint32_t intr_type, void (*new_gpio_isr_handler)(void* arg))
  300. {
  301. rt_pin_mode(gpio_num, PIN_MODE_INPUT);
  302. rt_pin_attach_irq(gpio_num, intr_type, new_gpio_isr_handler, NULL);
  303. rt_pin_irq_enable(gpio_num, RT_TRUE);
  304. return 0;
  305. }
  306. int hosted_read_gpio(void*gpio_port, uint32_t gpio_num)
  307. {
  308. return rt_pin_read(gpio_num);
  309. }
  310. int hosted_write_gpio(void* gpio_port, uint32_t gpio_num, uint32_t value)
  311. {
  312. rt_pin_write(gpio_num, value);
  313. return 0;
  314. }
  315. rt_weak int hosted_wifi_event_post(int32_t event_id, void* event_data, size_t event_data_size, int32_t ticks_to_wait)
  316. {
  317. ESP_LOGI(TAG, "wifi event: %d", event_id);
  318. return 0;
  319. }
  320. void hosted_log_write(int level, const char *tag, const char *format, ...)
  321. {
  322. va_list args;
  323. rt_size_t length = 0;
  324. static char rt_log_buf[RT_CONSOLEBUF_SIZE];
  325. esp_log_level_t level_for_tag = esp_log_level_get(tag);
  326. if ((ESP_LOG_NONE != level_for_tag) && (level <= level_for_tag))
  327. {
  328. va_start(args, format);
  329. length = rt_vsnprintf(rt_log_buf, sizeof(rt_log_buf) - 1, format, args);
  330. if (length > RT_CONSOLEBUF_SIZE - 1)
  331. {
  332. length = RT_CONSOLEBUF_SIZE - 1;
  333. }
  334. #ifdef RT_USING_ULOG
  335. #include "rtdbg.h"
  336. #undef LOG_TAG
  337. #define LOG_TAG tag
  338. switch (level)
  339. {
  340. default: LOG_D("%.*s", length, rt_log_buf); break;
  341. case ESP_LOG_INFO: LOG_I("%.*s", length, rt_log_buf); break;
  342. case ESP_LOG_WARN: LOG_W("%.*s", length, rt_log_buf); break;
  343. case ESP_LOG_ERROR: LOG_E("%.*s", length, rt_log_buf); break;
  344. }
  345. #undef LOG_TAG
  346. #else
  347. char level_char;
  348. switch (level)
  349. {
  350. case ESP_LOG_INFO: level_char = 'I'; break;
  351. case ESP_LOG_WARN: level_char = 'W'; break;
  352. case ESP_LOG_ERROR: level_char = 'E'; break;
  353. default: level_char = 'D'; break;
  354. }
  355. rt_kprintf("[%c/%s] %.*s\n", level_char, tag, length, rt_log_buf);
  356. #endif /* RT_USING_ULOG */
  357. va_end(args);
  358. }
  359. }
  360. /* newlib hooks */
  361. hosted_osi_funcs_t g_hosted_osi_funcs = {
  362. ._h_memcpy = hosted_memcpy ,
  363. ._h_memset = hosted_memset ,
  364. ._h_malloc = hosted_malloc ,
  365. ._h_calloc = hosted_calloc ,
  366. ._h_free = hosted_free ,
  367. ._h_realloc = hosted_realloc ,
  368. ._h_malloc_align = hosted_malloc_align ,
  369. ._h_free_align = hosted_free_align ,
  370. ._h_thread_create = hosted_thread_create ,
  371. ._h_thread_cancel = hosted_thread_cancel ,
  372. ._h_msleep = hosted_msleep ,
  373. ._h_usleep = hosted_usleep ,
  374. ._h_sleep = hosted_sleep ,
  375. ._h_blocking_delay = hosted_for_loop_delay ,
  376. ._h_queue_item = hosted_queue_item ,
  377. ._h_create_queue = hosted_create_queue ,
  378. ._h_queue_msg_waiting = hosted_queue_msg_waiting ,
  379. ._h_dequeue_item = hosted_dequeue_item ,
  380. ._h_destroy_queue = hosted_destroy_queue ,
  381. ._h_reset_queue = hosted_reset_queue ,
  382. ._h_unlock_mutex = hosted_unlock_mutex ,
  383. ._h_create_mutex = hosted_create_mutex ,
  384. ._h_lock_mutex = hosted_lock_mutex ,
  385. ._h_destroy_mutex = hosted_destroy_mutex ,
  386. ._h_post_semaphore = hosted_post_semaphore ,
  387. ._h_post_semaphore_from_isr = hosted_post_semaphore_from_isr ,
  388. ._h_create_semaphore = hosted_create_semaphore ,
  389. ._h_get_semaphore = hosted_get_semaphore ,
  390. ._h_destroy_semaphore = hosted_destroy_semaphore ,
  391. ._h_timer_stop = hosted_timer_stop ,
  392. ._h_timer_start = hosted_timer_start ,
  393. #ifdef CONFIG_USE_MEMPOOL
  394. ._h_create_lock_mempool = hosted_create_lock_mempool ,
  395. ._h_lock_mempool = hosted_lock_mempool ,
  396. ._h_unlock_mempool = hosted_unlock_mempool ,
  397. #endif
  398. ._h_config_gpio = hosted_config_gpio ,
  399. ._h_config_gpio_as_interrupt = hosted_config_gpio_as_interrupt,
  400. ._h_read_gpio = hosted_read_gpio ,
  401. ._h_write_gpio = hosted_write_gpio ,
  402. #ifdef CONFIG_ESP_SPI_HOST_INTERFACE
  403. ._h_bus_init = hosted_spi_init ,
  404. ._h_do_bus_transfer = hosted_do_spi_transfer ,
  405. #endif
  406. ._h_event_wifi_post = hosted_wifi_event_post ,
  407. ._h_printf = hosted_log_write ,
  408. ._h_hosted_init_hook = hosted_init_hook ,
  409. #ifdef CONFIG_ESP_SDIO_HOST_INTERFACE
  410. ._h_bus_init = hosted_sdio_init ,
  411. ._h_sdio_card_init = hosted_sdio_card_init ,
  412. ._h_sdio_read_reg = hosted_sdio_read_reg ,
  413. ._h_sdio_write_reg = hosted_sdio_write_reg ,
  414. ._h_sdio_read_block = hosted_sdio_read_block ,
  415. ._h_sdio_write_block = hosted_sdio_write_block ,
  416. ._h_sdio_wait_slave_intr = hosted_sdio_wait_slave_intr ,
  417. #endif
  418. #ifdef CONFIG_ESP_SPI_HD_HOST_INTERFACE
  419. ._h_bus_init = hosted_spi_hd_init ,
  420. ._h_spi_hd_read_reg = hosted_spi_hd_read_reg ,
  421. ._h_spi_hd_write_reg = hosted_spi_hd_write_reg ,
  422. ._h_spi_hd_read_dma = hosted_spi_hd_read_dma ,
  423. ._h_spi_hd_write_dma = hosted_spi_hd_write_dma ,
  424. ._h_spi_hd_set_data_lines = hosted_spi_hd_set_data_lines ,
  425. ._h_spi_hd_send_cmd9 = hosted_spi_hd_send_cmd9 ,
  426. #endif
  427. #ifdef CONFIG_ESP_UART_HOST_INTERFACE
  428. ._h_bus_init = hosted_uart_init ,
  429. ._h_uart_read = hosted_uart_read ,
  430. ._h_uart_write = hosted_uart_write ,
  431. ._h_uart_wait_rx_data = hosted_wait_rx_data ,
  432. #endif
  433. };