1 /*
2  * This file is part of the MicroPython project, http://micropython.org/
3  *
4  * Development of the code in this file was sponsored by Microbric Pty Ltd
5  *
6  * The MIT License (MIT)
7  *
8  * Copyright (c) 2016 Damien P. George
9  *
10  * Permission is hereby granted, free of charge, to any person obtaining a copy
11  * of this software and associated documentation files (the "Software"), to deal
12  * in the Software without restriction, including without limitation the rights
13  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14  * copies of the Software, and to permit persons to whom the Software is
15  * furnished to do so, subject to the following conditions:
16  *
17  * The above copyright notice and this permission notice shall be included in
18  * all copies or substantial portions of the Software.
19  *
20  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
26  * THE SOFTWARE.
27  */
28 
29 #include <stdio.h>
30 
31 #include "aos_hal_uart.h"
32 #include "mpsalport.h"
33 #include "py/mphal.h"
34 #include "py/runtime.h"
35 #include "ulog/ulog.h"
36 
37 #define LOG_TAG "MP_UART_PORT"
38 
39 STATIC uart_dev_t s_repl_uart = { 0 };
40 STATIC aos_task_t uart_recv_task = NULL;
41 STATIC mp_sal_sem_obj_t stdin_sem = NULL;
42 
py_uart_rx_notify(void * buf,uint16_t size)43 STATIC mp_int_t py_uart_rx_notify(void *buf, uint16_t size)
44 {
45     uint8_t *data = (uint8_t *)buf;
46     for (uint16_t index = 0; index < size; index++) {
47         uint8_t c = *(data++);
48         if (c == mp_interrupt_char) {
49             mp_sched_keyboard_interrupt();
50         } else {
51             ringbuf_put(&stdin_ringbuf, c);
52         }
53     }
54     mp_sal_sem_give(&stdin_sem);
55 }
56 
uart_recv_mainloop(void * args)57 STATIC void uart_recv_mainloop(void *args)
58 {
59     uart_dev_t uart = s_repl_uart;
60     uint8_t recv_byte[1] = { 0 };
61     mp_uint_t recv_size;
62     int ret;
63 
64     while (1) {
65         ret = aos_hal_uart_recv_II(&uart, recv_byte, sizeof(recv_byte),
66                                    &recv_size, HAL_WAIT_FOREVER);
67         if (ret != 0 || recv_size == 0) {
68             continue;
69         }
70 
71         py_uart_rx_notify(recv_byte, recv_size);
72     }
73 
74     aos_task_exit(0);
75 }
76 
uart_recv_task_init()77 STATIC mp_int_t uart_recv_task_init()
78 {
79     mp_int_t status = -1;
80 
81     if (uart_recv_task == NULL) {
82         status = aos_task_new_ext(&uart_recv_task, "_uart_recv",
83                                   uart_recv_mainloop, NULL, 1024, 32);
84         if (status != 0) {
85             LOGE(LOG_TAG, "Failed to create task[_uart_recv], status=%d\n",
86                  status);
87             return status;
88         }
89     } else {
90         status = aos_task_resume(&uart_recv_task);
91     }
92 
93     return status;
94 }
95 
uart_recv_task_deinit()96 STATIC mp_int_t uart_recv_task_deinit()
97 {
98     return aos_task_suspend(&uart_recv_task);
99 }
100 
mp_stdin_dev_get()101 uart_dev_t mp_stdin_dev_get()
102 {
103     return s_repl_uart;
104 }
105 
mp_stdin_init(uint8_t port,mp_uint_t baud_rate)106 mp_int_t mp_stdin_init(uint8_t port, mp_uint_t baud_rate)
107 {
108     int ret = uart_recv_task_init();
109     if (ret != 0) {
110         LOGE(LOG_TAG, "Failed to register cb to uart recv");
111         return ret;
112     }
113 
114     ret = mp_sal_sem_create(&stdin_sem);
115     if (ret != 0) {
116         LOGE(LOG_TAG, "Failed to create sem for hal stdin");
117         return ret;
118     }
119 
120     return ret;
121 }
122 
mp_stdin_deinit()123 mp_int_t mp_stdin_deinit()
124 {
125     memset(stdin_ringbuf.buf, 0, stdin_ringbuf.size);
126     stdin_ringbuf.iget = 0;
127     stdin_ringbuf.iput = 0;
128 
129     uart_recv_task_deinit();
130     mp_sal_sem_delete(&stdin_sem);
131 }
132 
mp_stdin_sem_give()133 mp_int_t mp_stdin_sem_give()
134 {
135     return mp_sal_sem_give(&stdin_sem);
136 }
137 
mp_stdin_sem_take(mp_uint_t timeout)138 mp_int_t mp_stdin_sem_take(mp_uint_t timeout)
139 {
140     return mp_sal_sem_take(&stdin_sem, timeout);
141 }
142