initial revision
[ucgine.git] / examples / test-cmd / uart.c
1 /*
2  * Copyright (c) 2015, Olivier MATZ <zer0@droids-corp.org>
3  * All rights reserved.
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are met:
6  *
7  *     * Redistributions of source code must retain the above copyright
8  *       notice, this list of conditions and the following disclaimer.
9  *     * Redistributions in binary form must reproduce the above copyright
10  *       notice, this list of conditions and the following disclaimer in the
11  *       documentation and/or other materials provided with the distribution.
12  *     * Neither the name of the University of California, Berkeley nor the
13  *       names of its contributors may be used to endorse or promote products
14  *       derived from this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
17  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19  * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
20  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27
28 #if defined(__ARM_EABI__)
29 #include "stm32f4xx.h"
30 #elif defined(__AVR__)
31 #include <avr/io.h>
32 #include <avr/interrupt.h>
33 #include <avr/pgmspace.h>
34 #include <util/delay.h>
35 #endif
36
37 #include <stdio.h>
38 #include <errno.h>
39 #include <ctype.h>
40
41 #include <ucg_irq.h>
42 #include <ucg_cirbuf.h>
43 #include <ucg_uart.h>
44
45 #include "uart.h"
46
47 #if defined(__ARM_EABI__) || defined(__AVR__)
48 /* rx & tx buffers */
49 static char rx_buf[64];
50 static struct ucg_cirbuf rx_cirbuf;
51 static char tx_buf[64];
52 static struct ucg_cirbuf tx_cirbuf;
53 /* generic uart struct */
54 struct ucg_uart main_uart;
55 #endif
56
57 #if defined(__ARM_EABI__)
58
59 #include <ucg_gloss_chardev.h>
60 #include <ucg_stm32_uart.h>
61
62 static struct ucg_stm32_uart stm32_uart_data = {
63         .uart = USART2,
64         .rcc_uart = RCC_APB1Periph_USART2,
65         .rcc_gpio = RCC_AHB1Periph_GPIOA,
66         .gpio = GPIOA,
67         .gpio_af = GPIO_AF_USART2,
68         .gpio_pins = GPIO_Pin_2 | GPIO_Pin_3,
69         .gpio_speed = GPIO_Speed_25MHz,
70         .irq = USART2_IRQn,
71         .irq_preempt_prio = 2,
72         .irq_sub_prio = 0,
73 };
74
75 static _ssize_t
76 uart_write_r(__attribute__((unused)) struct _reent *r,
77         __attribute__((unused)) int fd,
78         const void *ptr, size_t len)
79 {
80         size_t i;
81         const char *buf = ptr;
82
83         for (i = 0; i < len; i++)
84                 ucg_uart_send(&main_uart, buf[i], WAIT);
85
86         return len;
87 }
88
89 static _ssize_t
90 uart_read_r(__attribute__((unused)) struct _reent *r,
91         __attribute__((unused)) int fd,
92         void *ptr, size_t len)
93 {
94         int c;
95         char *buf = ptr;
96
97         (void)len;
98         c = ucg_uart_recv(&main_uart, NOWAIT);
99         if (c < 0) {
100                 r->_errno = EAGAIN;
101                 return 0;
102         }
103         buf[0] = c;
104         return 1;
105 }
106
107 void USART2_IRQHandler(void)
108 {
109         if ((USART2->SR & USART_FLAG_TXE))
110                 ucg_uart_tx_intr(&main_uart);
111         if ((USART2->SR & USART_FLAG_RXNE))
112                 ucg_uart_rx_intr(&main_uart);
113 }
114
115 struct ucg_chardev uart_stdin_dev = {
116         .name = "stdin",
117         .open_r = NULL,
118         .close_r = NULL,
119         .read_r = uart_read_r,
120         .write_r = NULL,
121 };
122
123 struct ucg_chardev uart_stdout_dev = {
124         .name = "stdout",
125         .open_r = NULL,
126         .close_r = NULL,
127         .read_r = NULL,
128         .write_r = uart_write_r,
129 };
130
131 struct ucg_chardev uart_stderr_dev = {
132         .name = "stderr",
133         .open_r = NULL,
134         .close_r = NULL,
135         .read_r = NULL,
136         .write_r = uart_write_r,
137 };
138
139 static void uart_register_stdio(void)
140 {
141         ucg_chardev_register(&uart_stdin_dev);
142         ucg_chardev_register(&uart_stdout_dev);
143         ucg_chardev_register(&uart_stderr_dev);
144
145         /* Disable buffering */
146         setbuf(stdin, NULL);
147         setbuf(stdout, NULL);
148         setbuf(stderr, NULL);
149 }
150
151 #elif defined(__AVR__)
152
153 #include <ucg_avr_uart.h>
154 /* avr-specific uart struct */
155 static struct ucg_avr_uart avr_uart_data = {
156         .reg_udr = &UDR0,
157         .reg_ucsra = &UCSR0A,
158         .reg_ucsrb = &UCSR0B,
159         .reg_ucsrc = &UCSR0C,
160         .reg_ubrrl = &UBRR0L,
161         .reg_ubrrh = &UBRR0H,
162         .bit_udre = UDRE0,
163         .bit_rxc = RXC0,
164         .bit_udrie = UDRIE0,
165         .bit_rxen = RXEN0,
166         .bit_txen = TXEN0,
167         .bit_rxcie = RXCIE0,
168         .bit_u2x = U2X0,
169 };
170
171 /* send on stdout */
172 static int std_send(char c, FILE *f)
173 {
174         (void)f;
175         ucg_uart_send(&main_uart, c, WAIT);
176         return 0;
177 }
178
179 /* recv on stdin */
180 static int std_recv(FILE *f)
181 {
182         int16_t c;
183
184         (void)f;
185         c = ucg_uart_recv(&main_uart, NOWAIT);
186         if (c < 0)
187                 return _FDEV_EOF;
188
189         return c;
190 }
191
192 SIGNAL(USART_RX_vect)
193 {
194         ucg_uart_rx_intr(&main_uart);
195 }
196
197 SIGNAL(USART_UDRE_vect)
198 {
199         ucg_uart_tx_intr(&main_uart);
200 }
201 #endif
202
203 int uart_init(void)
204 {
205         int ret = 0;
206 #if defined(__ARM_EABI__) || defined(__AVR__)
207         struct ucg_uart_config conf;
208         const void *uart_ops;
209         void *uart_data;
210
211 #if defined(__ARM_EABI__)
212         uart_ops = &stm32_uart_ops;
213         uart_data = &stm32_uart_data;
214 #elif defined(__AVR__)
215         uart_ops = &avr_uart_ops;
216         uart_data = &avr_uart_data;
217 #endif
218
219         ret = ucg_uart_init(&main_uart, uart_ops, uart_data,
220                 &rx_cirbuf, rx_buf, sizeof(rx_buf),
221                 &tx_cirbuf, tx_buf, sizeof(tx_buf));
222         if (ret < 0)
223                 return ret;
224
225         ucg_uart_getconf(&main_uart, &conf);
226         conf.baudrate = 57600;
227         ret = ucg_uart_setconf(&main_uart, &conf);
228         if (ret < 0)
229                 return ret;
230
231 #if defined(__ARM_EABI__)
232         uart_register_stdio();
233 #elif defined(__AVR__)
234         fdevopen(std_send, std_recv);
235 #endif
236 #endif
237         return ret;
238 }