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 if (!ao_fifo_full(ao_usart1_rx_fifo))
60 ao_fifo_insert(ao_usart1_rx_fifo, stm_usart1.dr);
61 ao_wakeup(&ao_usart1_rx_fifo);
63 ao_wakeup(&ao_stdin_ready);
66 if (sr & (1 << STM_USART_SR_TXE)) {
67 ao_serial_tx1_started = 0;
68 ao_serial_tx1_start();
69 ao_wakeup(&ao_usart1_tx_fifo);
74 ao_serial_getchar(void) __critical
78 while (ao_fifo_empty(ao_usart1_rx_fifo))
79 ao_sleep(&ao_usart1_rx_fifo);
80 ao_fifo_remove(ao_usart1_rx_fifo, c);
87 ao_serial_pollchar(void) __critical
91 if (ao_fifo_empty(ao_usart1_rx_fifo)) {
95 ao_fifo_remove(ao_usart1_rx_fifo,c);
102 ao_serial_putchar(char c) __critical
105 while (ao_fifo_full(ao_usart1_tx_fifo))
106 ao_sleep(&ao_usart1_tx_fifo);
107 ao_fifo_insert(ao_usart1_tx_fifo, c);
108 ao_serial_tx1_start();
113 ao_serial_drain(void) __critical
116 while (!ao_fifo_empty(ao_usart1_tx_fifo))
117 ao_sleep(&ao_usart1_tx_fifo);
121 int _write(int file, char *ptr, int len)
125 ao_debug_out(*ptr++);
129 static const struct {
131 } ao_serial_speeds[] = {
132 [AO_SERIAL_SPEED_4800] = {
135 [AO_SERIAL_SPEED_9600] = {
138 [AO_SERIAL_SPEED_19200] = {
141 [AO_SERIAL_SPEED_57600] = {
147 ao_serial_set_speed(uint8_t speed)
152 if (speed > AO_SERIAL_SPEED_57600)
154 stm_usart1.brr = ao_serial_speeds[speed].brr;
160 stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOAEN);
162 stm_moder_set(&stm_gpioa, 9, STM_MODER_ALTERNATE);
163 stm_moder_set(&stm_gpioa, 10, STM_MODER_ALTERNATE);
164 stm_afr_set(&stm_gpioa, 9, STM_AFR_AF7);
165 stm_afr_set(&stm_gpioa, 10, STM_AFR_AF7);
168 stm_rcc.apb2enr |= (1 << STM_RCC_APB2ENR_USART1EN);
170 stm_usart1.cr1 = ((0 << STM_USART_CR1_OVER8) |
171 (1 << STM_USART_CR1_UE) |
172 (0 << STM_USART_CR1_M) |
173 (0 << STM_USART_CR1_WAKE) |
174 (0 << STM_USART_CR1_PCE) |
175 (0 << STM_USART_CR1_PS) |
176 (0 << STM_USART_CR1_PEIE) |
177 (1 << STM_USART_CR1_TXEIE) |
178 (0 << STM_USART_CR1_TCIE) |
179 (1 << STM_USART_CR1_RXNEIE) |
180 (0 << STM_USART_CR1_IDLEIE) |
181 (1 << STM_USART_CR1_TE) |
182 (1 << STM_USART_CR1_RE) |
183 (0 << STM_USART_CR1_RWU) |
184 (0 << STM_USART_CR1_SBK));
186 stm_usart1.cr2 = ((0 << STM_USART_CR2_LINEN) |
187 (STM_USART_CR2_STOP_1 << STM_USART_CR2_STOP) |
188 (0 << STM_USART_CR2_CLKEN) |
189 (0 << STM_USART_CR2_CPOL) |
190 (0 << STM_USART_CR2_CPHA) |
191 (0 << STM_USART_CR2_LBCL) |
192 (0 << STM_USART_CR2_LBDIE) |
193 (0 << STM_USART_CR2_LBDL) |
194 (0 << STM_USART_CR2_ADD));
196 stm_usart1.cr3 = ((0 << STM_USART_CR3_ONEBITE) |
197 (0 << STM_USART_CR3_CTSIE) |
198 (0 << STM_USART_CR3_CTSE) |
199 (0 << STM_USART_CR3_RTSE) |
200 (0 << STM_USART_CR3_DMAT) |
201 (0 << STM_USART_CR3_DMAR) |
202 (0 << STM_USART_CR3_SCEN) |
203 (0 << STM_USART_CR3_NACK) |
204 (0 << STM_USART_CR3_HDSEL) |
205 (0 << STM_USART_CR3_IRLP) |
206 (0 << STM_USART_CR3_IREN) |
207 (0 << STM_USART_CR3_EIE));
209 /* Pick a 9600 baud rate */
210 ao_serial_set_speed(AO_SERIAL_SPEED_9600);
212 printf ("serial initialized\n");
215 ao_add_stdio(ao_serial_pollchar,
221 stm_nvic_set_enable(STM_ISR_USART1_POS);
222 stm_nvic_set_priority(STM_ISR_USART1_POS, 4);