2 * (C) Copyright 2014 Leo C. <erbl259-lmu@yahoo.de>
4 * SPDX-License-Identifier: GPL-2.0+
11 #include <libopencm3/stm32/gpio.h>
12 #include <libopencm3/stm32/usart.h>
13 #include <libopencm3/cm3/nvic.h>
17 #define USART_CONSOLE USART1
19 int _write(int fd
, char *ptr
, int len
) __attribute__((used
));
30 #define BUFFER_SIZE 256
34 uint8_t rx_ring_buffer
[BUFFER_SIZE
];
35 uint8_t tx_ring_buffer
[BUFFER_SIZE
];
38 static void ring_init(struct ring
*ring
, uint8_t *buf
, int size
)
46 static int ring_write_ch(struct ring
*ring
, uint8_t ch
)
48 int ep
= (ring
->end
+ 1) % ring
->size
;
50 if ((ep
) != ring
->begin
) {
51 ring
->data
[ring
->end
] = ch
;
59 static int ring_write(struct ring
*ring
, uint8_t *data
, int size
)
63 for (i
= 0; i
< size
; i
++) {
64 if (ring_write_ch(ring
, data
[i
]) < 0)
71 static int ring_read_ch(struct ring
*ring
)
75 if (ring
->begin
!= ring
->end
) {
76 ret
= ring
->data
[ring
->begin
];
77 ring
->begin
= (ring
->begin
+1) % ring
->size
;
83 void usart_setup(void)
85 /* Initialize output ring buffer. */
86 ring_init(&rx_ring
, rx_ring_buffer
, BUFFER_SIZE
);
87 ring_init(&tx_ring
, tx_ring_buffer
, BUFFER_SIZE
);
89 /* Enable the USART1 interrupt. */
90 nvic_enable_irq(NVIC_USART1_IRQ
);
92 /* Setup GPIO pin GPIO_USART1_TX/LED_GREEN_PIN on GPIO port A for transmit. */
93 /* TODO: USART1 --> USART_CONSOLE */
95 gpio_set_mode(GPIOA
, GPIO_MODE_OUTPUT_50_MHZ
,
96 GPIO_CNF_OUTPUT_ALTFN_PUSHPULL
, GPIO_USART1_TX
);
98 /* Setup GPIO pin GPIO_USART1_RE_RX on GPIO port B for receive. */
99 gpio_set_mode(GPIOA
, GPIO_MODE_INPUT
,
100 GPIO_CNF_INPUT_FLOAT
, GPIO_USART1_RX
);
102 /* Setup UART parameters. */
103 // usart_set_baudrate(USART_CONSOLE, 38400);
104 usart_set_baudrate(USART_CONSOLE
, 115200);
105 usart_set_databits(USART_CONSOLE
, 8);
106 usart_set_stopbits(USART_CONSOLE
, USART_STOPBITS_1
);
107 usart_set_parity(USART_CONSOLE
, USART_PARITY_NONE
);
108 usart_set_flow_control(USART_CONSOLE
, USART_FLOWCONTROL_NONE
);
109 usart_set_mode(USART_CONSOLE
, USART_MODE_TX_RX
);
111 /* Enable USART1 Receive interrupt. */
112 USART_CR1(USART1
) |= USART_CR1_RXNEIE
;
114 /* Finally enable the USART. */
115 usart_enable(USART_CONSOLE
);
118 void usart1_isr(void)
120 /* Check if we were called because of RXNE. */
121 if (((USART_CR1(USART1
) & USART_CR1_RXNEIE
) != 0) &&
122 ((USART_SR(USART1
) & USART_SR_RXNE
) != 0)) {
124 /* Retrieve the data from the peripheral. */
125 ring_write_ch(&rx_ring
, usart_recv(USART1
));
129 /* Check if we were called because of TXE. */
130 if (((USART_CR1(USART1
) & USART_CR1_TXEIE
) != 0) &&
131 ((USART_SR(USART1
) & USART_SR_TXE
) != 0)) {
135 data
= ring_read_ch(&tx_ring
);
138 /* Disable the TXE interrupt, it's no longer needed. */
139 USART_CR1(USART1
) &= ~USART_CR1_TXEIE
;
141 /* Put data into the transmit register. */
142 usart_send(USART1
, data
);
147 /*--------------------------------------------------------------------------*/
149 void serial_setup(void)
154 /*--------------------------------------------------------------------------*/
157 * Use USART_CONSOLE as a console.
158 * This is a syscall for newlib
164 int _write(int fd
, char *ptr
, int len
)
168 if (fd
== STDOUT_FILENO
|| fd
== STDERR_FILENO
) {
169 for (i
= 0; i
< len
; i
++) {
170 if (ptr
[i
] == '\n') {
181 int serial_getc(void)
183 return ring_read_ch(&rx_ring
);
186 void serial_putc(uint8_t data
)
188 while (ring_write_ch(&tx_ring
, data
) < 0)
191 /* Enable the TXE interrupt. */
192 USART_CR1(USART1
) |= USART_CR1_TXEIE
;