librfn
An ad-hoc utility library
console_stm32f1.c
Go to the documentation of this file.
1 /*
2  * console_stm32f1.c
3  *
4  * Part of librfn (a general utility library from redfelineninja.org.uk)
5  *
6  * This file was derived from libopencm3's usart_irq_printf.c example.
7  *
8  * Copyright (C) 2009 Uwe Hermann <uwe@hermann-uwe.de>,
9  * Copyright (C) 2011 Piotr Esden-Tempski <piotr@esden.net>
10  * Copyright (C) 2014 Daniel Thompson <daniel@redfelineninja.org.uk>
11  *
12  * This program is free software; you can redistribute it and/or modify
13  * it under the terms of the GNU Lesser General Public License as published
14  * by the Free Software Foundation; either version 3 of the License, or
15  * (at your option) any later version.
16  */
17 
18 #include <stdio.h>
19 #include <errno.h>
20 
21 #include <libopencm3/stm32/rcc.h>
22 #include <libopencm3/stm32/gpio.h>
23 #include <libopencm3/stm32/usart.h>
24 #include <libopencm3/cm3/nvic.h>
25 #include <libopencm3/cm3/systick.h>
26 
27 #include <librfn/console.h>
28 
29 /* prototype functions not found in the headers (for -Wmissing-prototypes) */
30 int _write(int file, char *ptr, int len);
31 
32 static uint8_t outbuf[1024];
33 static ringbuf_t outring = RINGBUF_VAR_INIT(outbuf, sizeof(outbuf));
34 
35 static console_t *console;
36 
38 {
39  console = c;
40 
41  /* Enable clocks for GPIO port A (for GPIO_USART1_TX) and USART1. */
42  rcc_periph_clock_enable(RCC_GPIOA);
43  rcc_periph_clock_enable(RCC_AFIO);
44  rcc_periph_clock_enable(RCC_USART1);
45 
46  /* Enable the USART1 interrupt. */
47  nvic_enable_irq(NVIC_USART1_IRQ);
48 
49  /* Setup GPIO pin GPIO_USART1_RE_TX on PA9 */
50  gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_50_MHZ,
51  GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, GPIO_USART1_TX);
52 
53  /* Setup GPIO pin GPIO_USART1_RE_RX on PA10 */
54  gpio_set_mode(GPIOA, GPIO_MODE_INPUT,
55  GPIO_CNF_INPUT_FLOAT, GPIO_USART1_RX);
56 
57  /* Setup UART parameters. */
58  usart_set_baudrate(USART1, 38400);
59  usart_set_databits(USART1, 8);
60  usart_set_stopbits(USART1, USART_STOPBITS_1);
61  usart_set_parity(USART1, USART_PARITY_NONE);
62  usart_set_flow_control(USART1, USART_FLOWCONTROL_NONE);
63  usart_set_mode(USART1, USART_MODE_TX_RX);
64 
65  /* Enable USART1 Receive interrupt. */
66  USART_CR1(USART1) |= USART_CR1_RXNEIE;
67 
68  /* Finally enable the USART. */
69  usart_enable(USART1);
70 }
71 
72 void usart1_isr(void)
73 {
74  /* Check if we were called because of RXNE. */
75  if (((USART_CR1(USART1) & USART_CR1_RXNEIE) != 0) &&
76  ((USART_SR(USART1) & USART_SR_RXNE) != 0)) {
77  uint16_t c = usart_recv(USART1);
78  if (c == '\r') {
79  (void) ringbuf_put(&outring, '\r');
80  c = '\n';
81  }
82  (void) ringbuf_put(&outring, c);
83 
84  /* Enable transmit interrupt so it repeats the character back */
85  USART_CR1(USART1) |= USART_CR1_TXEIE;
86 
87 #ifdef CONFIG_CONSOLE_FROM_ISR
88  console_process(console, c);
89 #else
90  console_putchar(console, c);
91 #endif
92  }
93 
94  /* Check if we were called because of TXE. */
95  if (((USART_CR1(USART1) & USART_CR1_TXEIE) != 0) &&
96  ((USART_SR(USART1) & USART_SR_TXE) != 0)) {
97  int data = ringbuf_get(&outring);
98 
99  if (data == -1) {
100  /* Disable the TXE interrupt, it's no longer needed. */
101  USART_CR1(USART1) &= ~USART_CR1_TXEIE;
102  } else {
103  /* Put data into the transmit register. */
104  usart_send(USART1, data);
105  }
106  }
107 }
108 
109 int _write(int file, char *ptr, int len)
110 {
111  if (file == 1 || file == 2) {
112  for (int i=0; i<len; i++) {
113  if (ptr[i] == '\n')
114  (void) ringbuf_put(&outring, '\r');
115  (void) ringbuf_put(&outring, ptr[i]);
116  USART_CR1(USART1) |= USART_CR1_TXEIE;
117  }
118 
119  return 0;
120  }
121 
122  errno = EIO;
123  return -1;
124 }
struct charlie c
#define RINGBUF_VAR_INIT(bufp, buf_len)
Static initializer for a ring buffer descriptor.
Definition: ringbuf.h:48
Console descriptor.
Definition: console.h:66
void console_hwinit(console_t *c)
Platform dependant function that will be called during console_init().
Ring buffer descriptor.
Definition: ringbuf.h:38
void console_putchar(console_t *c, char d)
Asynchronously send a character to the command processor.
Definition: console.c:177
int ringbuf_get(ringbuf_t *rb)
Extract a byte from the ring buffer.
Definition: ringbuf.c:31
const uint8_t data[]
Definition: wavheader.c:26
void console_process(console_t *c, char d)
Synchronous console function for use in threaded environments.
Definition: console.c:254
bool ringbuf_put(ringbuf_t *rb, uint8_t d)
Insert a byte into the ring buffer.
Definition: ringbuf.c:58
int _write(int file, char *ptr, int len)
void usart1_isr(void)