2 * Copyright © 2012 Keith Packard <keithp@keithp.com>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; version 2 of the License.
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * General Public License for more details.
13 * You should have received a copy of the GNU General Public License along
14 * with this program; if not, write to the Free Software Foundation, Inc.,
15 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
20 __xdata struct ao_fifo ao_usart1_rx_fifo;
21 __xdata struct ao_fifo ao_usart1_tx_fifo;
28 while (!(stm_usart1.sr & (1 << STM_USART_SR_TXE)));
38 static __xdata uint8_t ao_serial_tx1_started;
41 ao_serial_tx1_start(void)
43 if (!ao_fifo_empty(ao_usart1_tx_fifo) &&
44 !ao_serial_tx1_started)
46 ao_serial_tx1_started = 1;
47 ao_fifo_remove(ao_usart1_tx_fifo, stm_usart1.dr);
51 void stm_usart1_isr(void)
58 if (sr & (1 << STM_USART_SR_RXNE)) {
59 char c = stm_usart1.dr;
60 if (!ao_fifo_full(ao_usart1_rx_fifo))
61 ao_fifo_insert(ao_usart1_rx_fifo, c);
62 ao_wakeup(&ao_usart1_rx_fifo);
64 ao_wakeup(&ao_stdin_ready);
67 if (sr & (1 << STM_USART_SR_TC)) {
68 ao_serial_tx1_started = 0;
69 ao_serial_tx1_start();
70 ao_wakeup(&ao_usart1_tx_fifo);
75 ao_serial_getchar(void) __critical
79 while (ao_fifo_empty(ao_usart1_rx_fifo))
80 ao_sleep(&ao_usart1_rx_fifo);
81 ao_fifo_remove(ao_usart1_rx_fifo, c);
88 ao_serial_pollchar(void) __critical
92 if (ao_fifo_empty(ao_usart1_rx_fifo)) {
96 ao_fifo_remove(ao_usart1_rx_fifo,c);
103 ao_serial_putchar(char c) __critical
106 while (ao_fifo_full(ao_usart1_tx_fifo))
107 ao_sleep(&ao_usart1_tx_fifo);
108 ao_fifo_insert(ao_usart1_tx_fifo, c);
109 ao_serial_tx1_start();
114 ao_serial_drain(void) __critical
117 while (!ao_fifo_empty(ao_usart1_tx_fifo))
118 ao_sleep(&ao_usart1_tx_fifo);
122 int _write(int file, char *ptr, int len)
126 ao_debug_out(*ptr++);
130 static const struct {
132 } ao_serial_speeds[] = {
133 [AO_SERIAL_SPEED_4800] = {
136 [AO_SERIAL_SPEED_9600] = {
139 [AO_SERIAL_SPEED_19200] = {
142 [AO_SERIAL_SPEED_57600] = {
148 ao_serial_set_speed(uint8_t speed)
153 if (speed > AO_SERIAL_SPEED_57600)
155 stm_usart1.brr = ao_serial_speeds[speed].brr;
161 stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOAEN);
163 stm_moder_set(&stm_gpioa, 9, STM_MODER_ALTERNATE);
164 stm_moder_set(&stm_gpioa, 10, STM_MODER_ALTERNATE);
165 stm_afr_set(&stm_gpioa, 9, STM_AFR_AF7);
166 stm_afr_set(&stm_gpioa, 10, STM_AFR_AF7);
169 stm_rcc.apb2enr |= (1 << STM_RCC_APB2ENR_USART1EN);
171 stm_usart1.cr1 = ((0 << STM_USART_CR1_OVER8) |
172 (1 << STM_USART_CR1_UE) |
173 (0 << STM_USART_CR1_M) |
174 (0 << STM_USART_CR1_WAKE) |
175 (0 << STM_USART_CR1_PCE) |
176 (0 << STM_USART_CR1_PS) |
177 (0 << STM_USART_CR1_PEIE) |
178 (0 << STM_USART_CR1_TXEIE) |
179 (1 << STM_USART_CR1_TCIE) |
180 (1 << STM_USART_CR1_RXNEIE) |
181 (0 << STM_USART_CR1_IDLEIE) |
182 (1 << STM_USART_CR1_TE) |
183 (1 << STM_USART_CR1_RE) |
184 (0 << STM_USART_CR1_RWU) |
185 (0 << STM_USART_CR1_SBK));
187 stm_usart1.cr2 = ((0 << STM_USART_CR2_LINEN) |
188 (STM_USART_CR2_STOP_1 << STM_USART_CR2_STOP) |
189 (0 << STM_USART_CR2_CLKEN) |
190 (0 << STM_USART_CR2_CPOL) |
191 (0 << STM_USART_CR2_CPHA) |
192 (0 << STM_USART_CR2_LBCL) |
193 (0 << STM_USART_CR2_LBDIE) |
194 (0 << STM_USART_CR2_LBDL) |
195 (0 << STM_USART_CR2_ADD));
197 stm_usart1.cr3 = ((0 << STM_USART_CR3_ONEBITE) |
198 (0 << STM_USART_CR3_CTSIE) |
199 (0 << STM_USART_CR3_CTSE) |
200 (0 << STM_USART_CR3_RTSE) |
201 (0 << STM_USART_CR3_DMAT) |
202 (0 << STM_USART_CR3_DMAR) |
203 (0 << STM_USART_CR3_SCEN) |
204 (0 << STM_USART_CR3_NACK) |
205 (0 << STM_USART_CR3_HDSEL) |
206 (0 << STM_USART_CR3_IRLP) |
207 (0 << STM_USART_CR3_IREN) |
208 (0 << STM_USART_CR3_EIE));
210 /* Pick a 9600 baud rate */
211 ao_serial_set_speed(AO_SERIAL_SPEED_9600);
213 printf ("serial initialized\n");
215 ao_add_stdio(ao_serial_pollchar,
220 stm_nvic_set_enable(STM_ISR_USART1_POS);
221 stm_nvic_set_priority(STM_ISR_USART1_POS, 4);