blob: 63620ab6c1e0a504c3c7753bedeafac7f2264c8a [file] [log] [blame]
Brian Silvermanaa9183a2013-12-08 10:33:47 -08001#include "cape/uart.h"
2#include "cape/uart_common_private.h"
3
4#include "cape/util.h"
5#include "cape/uart_common.h"
6
7// TODO(brians): Add error checking.
8
9static void default_callback(int bytes) {}
10
11void uart_transmit_callback(int bytes_transmitted) ALIAS_WEAK(default_callback);
12void uart_receive_callback(int bytes_received) ALIAS_WEAK(default_callback);
13
14static int transmit_bytes, receive_bytes;
15// These actually contain 1 less than the indicated number to make the common
16// path through the ISR faster.
17static int transmitted_bytes, received_bytes;
18static uint8_t *transmit_data, *receive_data;
19
20// Enable the transmitter and interrupt when we can write.
21static const uint32_t kTransmitBits = USART_CR1_TE | USART_CR1_TXEIE;
22// Enable the receive and interrupt when there's data to read.
23static const uint32_t kReceiveBits = USART_CR1_RE | USART_CR1_RXNEIE;
24
25void USART1_IRQHandler(void) {
26 uint32_t status = UART->SR;
27 if (status & USART_SR_TXE) {
28 if ((transmitted_bytes + 1) < transmit_bytes) {
29 UART->DR = transmit_data[++transmitted_bytes];
30 } else {
31 // Get another interrupt when it's done writing that last byte.
32 UART->CR1 = (UART->CR1 & ~USART_CR1_TXEIE) | USART_CR1_TCIE;
33 }
34 } else if (status & USART_SR_RXNE) {
35 receive_data[++received_bytes] = UART->DR;
36 if ((received_bytes + 1) >= receive_bytes) {
37 UART->CR1 &= ~kReceiveBits;
38 uart_receive_callback(receive_bytes);
39 }
40 } else if (status & USART_SR_TC) {
41 UART->CR1 &= ~(USART_CR1_TCIE | USART_CR1_TE);
42 uart_transmit_callback(transmit_bytes);
43 }
44}
45
Brian Silvermandf49fe32013-12-11 14:21:37 -080046void uart_configure(void) {
Brian Silvermanaa9183a2013-12-08 10:33:47 -080047 NVIC_SetPriority(USART1_IRQn, 3);
48 NVIC_EnableIRQ(USART1_IRQn);
49}
50
51void uart_transmit(int bytes, uint8_t *data) {
52 transmit_bytes = bytes;
53 transmitted_bytes = 0;
54 transmit_data = data;
55 compiler_memory_barrier();
56 UART->CR1 |= kTransmitBits;
57 UART->DR = data[0];
58}
59
60void uart_receive(int bytes, uint8_t *data) {
61 receive_bytes = bytes;
62 received_bytes = -1;
63 receive_data = data;
64 compiler_memory_barrier();
65 UART->CR1 |= kReceiveBits;
66}