drv_openamp.c 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328
  1. /*
  2. * Copyright (c) 2006-2021, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2020-06-24 thread-liu first version
  9. */
  10. #include <board.h>
  11. #ifdef BSP_USING_OPENAMP
  12. #include <finsh.h>
  13. #include <drv_openamp.h>
  14. #include <openamp.h>
  15. #include <virt_uart.h>
  16. #include <openamp/rpmsg_virtio.h>
  17. //#define DRV_DEBUG
  18. #define LOG_TAG "drv.openamp"
  19. #include <drv_log.h>
  20. IPCC_HandleTypeDef hipcc;
  21. static VIRT_UART_HandleTypeDef huart0;
  22. static rt_uint8_t rx_buffer[MAX_BUFFER_SIZE];
  23. static rt_uint8_t tx_buffer[MAX_BUFFER_SIZE];
  24. struct rthw_openamp
  25. {
  26. struct rt_device parent;
  27. struct rt_openamp serial;
  28. struct rt_semaphore sema;
  29. };
  30. static struct rthw_openamp dev_openamp;
  31. void IPCC_RX1_IRQHandler(void)
  32. {
  33. rt_interrupt_enter();
  34. HAL_IPCC_RX_IRQHandler(&hipcc);
  35. rt_interrupt_leave();
  36. }
  37. void IPCC_TX1_IRQHandler(void)
  38. {
  39. rt_interrupt_enter();
  40. HAL_IPCC_TX_IRQHandler(&hipcc);
  41. rt_interrupt_leave();
  42. }
  43. void VIRT_UART0_RxCpltCallback(VIRT_UART_HandleTypeDef *huart)
  44. {
  45. rt_uint16_t rx_size = 0, i = 0;
  46. rt_size_t count, size, offset;
  47. rt_uint8_t *buf = RT_NULL;
  48. struct rthw_openamp *device;
  49. device = (struct rthw_openamp *)rt_device_find("openamp");
  50. RT_ASSERT(device != RT_NULL);
  51. buf = device->serial.rbuf;
  52. count = device->serial.rbuf_count;
  53. size = device->serial.rbuf_size;
  54. offset = device->serial.rbuf_start + count;
  55. rt_sem_take(&device->sema, RT_WAITING_FOREVER);
  56. rx_size = (huart->RxXferSize < MAX_BUFFER_SIZE) ? huart->RxXferSize : MAX_BUFFER_SIZE - 1;
  57. if (count < size)
  58. {
  59. if (offset >= size)
  60. {
  61. offset -= size;
  62. }
  63. for (i = 0; i < rx_size; i++)
  64. {
  65. buf[offset++] = huart->pRxBuffPtr[i];
  66. count++;
  67. }
  68. }
  69. device->serial.rbuf_count = count;
  70. rt_sem_release(&device->sema);
  71. }
  72. static rt_err_t _init(struct rt_device *dev)
  73. {
  74. struct rthw_openamp *device;
  75. device = (struct rthw_openamp *)dev;
  76. RT_ASSERT(device != RT_NULL);
  77. device->serial.rbuf_start = 0;
  78. device->serial.rbuf_count = 0;
  79. device->serial.tbuf_start = 0;
  80. device->serial.tbuf_count = 0;
  81. device->serial.rbuf_size = MAX_BUFFER_SIZE;
  82. device->serial.tbuf_size = MAX_BUFFER_SIZE;
  83. device->serial.rbuf = rx_buffer;
  84. device->serial.tbuf = tx_buffer;
  85. if (rt_sem_init(&device->sema, "openamplock", 1, RT_IPC_FLAG_FIFO) != RT_EOK)
  86. {
  87. return RT_ERROR;
  88. }
  89. return RT_EOK;
  90. }
  91. static rt_size_t _read(struct rt_device *dev, rt_off_t pos, void *buffer, rt_size_t size)
  92. {
  93. rt_size_t count, rbsize, offset;
  94. rt_uint8_t *buf = RT_NULL;
  95. rt_uint8_t *pBuffer = RT_NULL;
  96. rt_uint16_t i = 0;
  97. struct rthw_openamp *device;
  98. device = (struct rthw_openamp *)dev;
  99. RT_ASSERT(device != RT_NULL);
  100. pBuffer = (unsigned char*)buffer;
  101. count = device->serial.rbuf_count;
  102. buf = device->serial.rbuf;
  103. if (count == 0)
  104. {
  105. return -RT_ERROR;
  106. }
  107. rt_sem_take(&device->sema, RT_WAITING_FOREVER);
  108. if (count >= size)
  109. {
  110. count = size;
  111. }
  112. offset = device->serial.rbuf_start;
  113. rbsize = device->serial.rbuf_size;
  114. for (i = 0; i < count; i++)
  115. {
  116. *pBuffer++ = buf[offset++];
  117. if (offset > rbsize)
  118. {
  119. offset = 0;
  120. }
  121. }
  122. device->serial.rbuf_start = offset;
  123. device->serial.rbuf_count -= count;
  124. rt_sem_release(&device->sema);
  125. return count;
  126. }
  127. static rt_size_t _write(struct rt_device *dev, rt_off_t pos, const void *buffer, rt_size_t size)
  128. {
  129. rt_err_t result = VIRT_UART_OK;
  130. struct rthw_openamp *device;
  131. device = (struct rthw_openamp *)dev;
  132. RT_ASSERT(device != RT_NULL);
  133. rt_sem_take(&device->sema, RT_WAITING_FOREVER);
  134. result = VIRT_UART_Transmit(&huart0, (uint8_t *)buffer, size);
  135. rt_sem_release(&device->sema);
  136. if (result != VIRT_UART_OK)
  137. {
  138. return -RT_ERROR;
  139. }
  140. return size;
  141. }
  142. static rt_err_t rt_hw_openamp_register(struct rthw_openamp *openamp, const char *name, rt_uint32_t flag, void *data)
  143. {
  144. struct rt_device *device;
  145. RT_ASSERT(openamp != RT_NULL);
  146. device = &(openamp->parent);
  147. device->type = RT_Device_Class_Char;
  148. device->rx_indicate = RT_NULL;
  149. device->tx_complete = RT_NULL;
  150. device->init = _init;
  151. device->open = RT_NULL;
  152. device->close = RT_NULL;
  153. device->read = _read;
  154. device->write = _write;
  155. device->control = RT_NULL;
  156. device->user_data = data;
  157. /* register a character device */
  158. return rt_device_register(device, name, flag);
  159. }
  160. static int openamp_init(void)
  161. {
  162. extern int MX_OPENAMP_Init(int RPMsgRole, rpmsg_ns_bind_cb ns_bind_cb);
  163. /* IPCC init */
  164. hipcc.Instance = IPCC;
  165. if (HAL_IPCC_Init(&hipcc) != HAL_OK)
  166. {
  167. return RT_ERROR;
  168. }
  169. /* openamp slave device */
  170. MX_OPENAMP_Init(RPMSG_REMOTE, NULL);
  171. if (VIRT_UART_Init(&huart0) != VIRT_UART_OK)
  172. {
  173. return RT_ERROR;
  174. }
  175. if (VIRT_UART_RegisterCallback(&huart0, VIRT_UART_RXCPLT_CB_ID, VIRT_UART0_RxCpltCallback) != VIRT_UART_OK)
  176. {
  177. return RT_ERROR;
  178. }
  179. return RT_EOK;
  180. }
  181. int rt_hw_openamp_init(void)
  182. {
  183. openamp_init();
  184. rt_hw_openamp_register(&dev_openamp, "openamp", 0, NULL);
  185. if (RT_CONSOLE_DEVICE_NAME == "openamp")
  186. {
  187. rt_console_set_device(RT_CONSOLE_DEVICE_NAME);
  188. }
  189. return RT_EOK;
  190. }
  191. INIT_PREV_EXPORT(rt_hw_openamp_init);
  192. static void openamp_thread_entry(void *parameter)
  193. {
  194. rt_size_t size = 0;
  195. struct rthw_openamp *device = RT_NULL;
  196. device = (struct rthw_openamp *)rt_device_find("openamp");
  197. RT_ASSERT(device != RT_NULL);
  198. for (;;)
  199. {
  200. OPENAMP_check_for_message();
  201. size = device->serial.rbuf_count;
  202. if (size > 0)
  203. {
  204. if (device->parent.rx_indicate != RT_NULL)
  205. {
  206. device->parent.rx_indicate(&device->parent, size);
  207. }
  208. }
  209. rt_thread_mdelay(1);
  210. }
  211. }
  212. static int creat_openamp_thread(void)
  213. {
  214. rt_thread_t tid = RT_NULL;
  215. tid = rt_thread_create("OpenAMP",
  216. openamp_thread_entry,
  217. RT_NULL,
  218. OPENAMP_THREAD_STACK_SIZE,
  219. OPENAMP_THREAD_PRIORITY,
  220. OPENAMP_THREAD_TIMESLICE);
  221. if (tid == RT_NULL)
  222. {
  223. LOG_E("openamp thread create failed!");
  224. return RT_ERROR;
  225. }
  226. rt_thread_startup(tid);
  227. return RT_EOK;
  228. }
  229. INIT_APP_EXPORT(creat_openamp_thread);
  230. #ifdef FINSH_USING_MSH
  231. static int console(int argc, char **argv)
  232. {
  233. rt_err_t result = RT_EOK;
  234. if (argc > 1)
  235. {
  236. if (!strcmp(argv[1], "set"))
  237. {
  238. rt_kprintf("console change to %s\n", argv[2]);
  239. rt_console_set_device(argv[2]);
  240. finsh_set_device(argv[2]);
  241. }
  242. else
  243. {
  244. rt_kprintf("Unknown command. Please enter 'console' for help\n");
  245. result = -RT_ERROR;
  246. }
  247. }
  248. else
  249. {
  250. rt_kprintf("Usage: \n");
  251. rt_kprintf("console set <name> - change console by name\n");
  252. result = -RT_ERROR;
  253. }
  254. return result;
  255. }
  256. MSH_CMD_EXPORT(console, set console name);
  257. #endif /* FINSH_USING_MSH */
  258. #endif