]> cloudbase.mooo.com Git - irmp-demo.git/blame - serial.c
Small changes. Convert TABs to spaces.
[irmp-demo.git] / serial.c
CommitLineData
b1a276a1 1/*
b8dc4070 2 * (C) Copyright 2014 - 2017 Leo C. <erbl259-lmu@yahoo.de>
b1a276a1
L
3 *
4 * SPDX-License-Identifier: GPL-2.0
5 */
6
7#include "serial.h"
8#include "config.h"
9#include <errno.h>
10#include <stdio.h>
11#include <unistd.h>
12#include <libopencm3/stm32/rcc.h>
13#include <libopencm3/stm32/gpio.h>
14#include <libopencm3/stm32/usart.h>
15#include <libopencm3/cm3/nvic.h>
16
17#if (USART_CONSOLE == 1)
18#define CON_PORT A
19#define CON_GPIO GPIOA
20#elif (USART_CONSOLE == 2)
21#define CON_PORT A
22#define CON_GPIO GPIOA
23#elif (USART_CONSOLE == 3)
24#define CON_PORT B
25#define CON_GPIO GPIOB
26#else
27#error USART_CONSOLE undefined or invalid value
28#endif
29
30#define CONCAT2(a,b) a##b
31#define CONCAT(a,b) CONCAT2(a,b)
32
33
34#define CON_USART CONCAT(USART,USART_CONSOLE)
35#define CON_IRQ CONCAT(CONCAT(NVIC_USART, USART_CONSOLE), _IRQ)
36#define CON_isr CONCAT(CONCAT(usart, USART_CONSOLE), _isr)
37#define CON_GPIO_RX CONCAT(CONCAT(GPIO_USART, USART_CONSOLE), _RX)
38#define CON_GPIO_TX CONCAT(CONCAT(GPIO_USART, USART_CONSOLE), _TX)
39#define RCC_USART_CON CONCAT(RCC_USART, USART_CONSOLE)
40#define RCC_GPIO_CON CONCAT(RCC_GPIO, CON_PORT)
41
42
43int _write(int fd, char *ptr, int len) __attribute__((used));
44
45
46struct ring {
47 uint8_t *data;
48 int size;
49 volatile int begin;
50 volatile int end;
51};
52
53
54#define BUFFER_SIZE 256
55
56struct ring rx_ring;
57struct ring tx_ring;
58uint8_t rx_ring_buffer[BUFFER_SIZE];
59uint8_t tx_ring_buffer[BUFFER_SIZE];
60
61
62static void ring_init(struct ring *ring, uint8_t *buf, int size)
63{
64 ring->data = buf;
65 ring->size = size;
66 ring->begin = 0;
67 ring->end = 0;
68}
69
70static int ring_write_ch(struct ring *ring, uint8_t ch)
71{
72 int ep = (ring->end + 1) % ring->size;
73
74 if ((ep) != ring->begin) {
75 ring->data[ring->end] = ch;
76 ring->end = ep;
77 return 1;
78 }
79
80 return -1;
81}
82
83#if 0 /* unused */
84static int ring_write(struct ring *ring, uint8_t *data, int size)
85{
86 int i;
87
88 for (i = 0; i < size; i++) {
89 if (ring_write_ch(ring, data[i]) < 0)
90 return -i;
91 }
92
93 return i;
94}
95#endif
96
97static int ring_read_ch(struct ring *ring)
98{
99 int ret = -1;
100
101 if (ring->begin != ring->end) {
102 ret = ring->data[ring->begin];
103 ring->begin = (ring->begin +1) % ring->size;
104 }
105
106 return ret;
107}
108
109void usart_setup(int baud)
110{
111 /* Initialize output ring buffer. */
112 ring_init(&rx_ring, rx_ring_buffer, BUFFER_SIZE);
113 ring_init(&tx_ring, tx_ring_buffer, BUFFER_SIZE);
114
115 rcc_periph_clock_enable(RCC_USART_CON);
116
117 /* Enable the USART_CONSOLE interrupt. */
118 nvic_enable_irq(CON_IRQ);
119 nvic_set_priority(CON_IRQ, 6*16);
120
121 /* Setup GPIO pins for CONSOLE TX/RX */
122 rcc_periph_clock_enable(RCC_GPIO_CON);
123 gpio_set_mode(CON_GPIO, GPIO_MODE_OUTPUT_2_MHZ,
124 GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, CON_GPIO_TX);
125 gpio_set_mode(CON_GPIO, GPIO_MODE_INPUT,
126 GPIO_CNF_INPUT_FLOAT, CON_GPIO_RX);
127
128 /* Setup UART parameters. */
129 usart_set_baudrate(CON_USART, baud);
130 usart_set_databits(CON_USART, 8);
131 usart_set_stopbits(CON_USART, USART_STOPBITS_1);
132 usart_set_parity(CON_USART, USART_PARITY_NONE);
133 usart_set_flow_control(CON_USART, USART_FLOWCONTROL_NONE);
134 usart_set_mode(CON_USART, USART_MODE_TX_RX);
135
136 /* Enable CONSOLE Receive interrupt. */
137 USART_CR1(CON_USART) |= USART_CR1_RXNEIE;
138
139 /* Finally enable the USART. */
140 usart_enable(CON_USART);
141}
142
143
144void CON_isr(void)
145{
146 /* Check if we were called because of RXNE. */
147 if (((USART_CR1(CON_USART) & USART_CR1_RXNEIE) != 0) &&
148 ((USART_SR(CON_USART) & USART_SR_RXNE) != 0)) {
149
150 /* Retrieve the data from the peripheral. */
151 ring_write_ch(&rx_ring, USART_DR(CON_USART) & USART_DR_MASK);
152
153 }
154
155 /* Check if we were called because of TXE. */
156 if (((USART_CR1(CON_USART) & USART_CR1_TXEIE) != 0) &&
157 ((USART_SR(CON_USART) & USART_SR_TXE) != 0)) {
158
159 int data;
160
161 data = ring_read_ch(&tx_ring);
162
163 if (data == -1) {
164 /* Disable the TXE interrupt, it's no longer needed. */
165 USART_CR1(CON_USART) &= ~USART_CR1_TXEIE;
166 } else {
167 /* Put data into the transmit register. */
168 usart_send(CON_USART, data);
169 }
170 }
171}
172
173/*--------------------------------------------------------------------------*/
174
175void serial_setup(int baud)
176{
177 usart_setup(baud);
178}
179
180void serial_setbaudrate(int baud)
181{
182 usart_set_baudrate(CON_USART, baud);
183}
184
185/*--------------------------------------------------------------------------*/
186
187/**
188 * Use USART_CONSOLE as a console.
189 * This is a syscall for newlib
190 * @param fd
191 * @param ptr
192 * @param len
193 * @return
194 */
195int _write(int fd, char *ptr, int len)
196{
197 int i;
198
199 if (fd == STDOUT_FILENO || fd == STDERR_FILENO) {
200 for (i = 0; i < len; i++) {
201 if (ptr[i] == '\n') {
202 serial_putc('\r');
203 }
204 serial_putc(ptr[i]);
205 }
206 return i;
207 }
208 errno = EIO;
209 return -1;
210}
211
212int serial_getc(void)
213{
214 return ring_read_ch(&rx_ring);
215}
216
217void serial_putc(int data)
218{
219 while (ring_write_ch(&tx_ring, data) < 0)
220 ;
221
222 /* Enable the TXE interrupt. */
223 USART_CR1(CON_USART) |= USART_CR1_TXEIE;
224}