diff --git a/include/libopenstm32/usart.h b/include/libopenstm32/usart.h index 237a58f6..422a8936 100644 --- a/include/libopenstm32/usart.h +++ b/include/libopenstm32/usart.h @@ -132,6 +132,11 @@ #define PARITY_ODD 0x02 #define PARITY_EVEN 0x03 +/* CR1_TE/CR1_RE combined values */ +#define MODE_RX 0x01 +#define MODE_TX 0x02 +#define MODE_TX_RX 0x03 + /* --- USART_CR2 values ---------------------------------------------------- */ #define CR2_LINEN (1 << 14) /* LIN mode enable */ @@ -177,4 +182,17 @@ /* TODO */ +/* --- Function prototypes ------------------------------------------------- */ + +void usart_set_baudrate(u32 usart, u32 baud); +void usart_set_databits(u32 usart, u32 bits); +void usart_set_stopbits(u32 usart, u32 stopbits); +void usart_set_parity(u32 usart, u32 parity); +void usart_set_mode(u32 usart, u32 mode); +void usart_set_flow_control(u32 usart, u32 flowcontrol); +void usart_enable(u32 usart); +void usart_disable(u32 usart); +void usart_send(u32 usart, u16 data); +u16 usart_recv(u32 usart); + #endif diff --git a/lib/usart.c b/lib/usart.c index 02edd86e..fdcc9321 100644 --- a/lib/usart.c +++ b/lib/usart.c @@ -19,5 +19,83 @@ #include -/* TODO */ +void usart_set_baudrate(u32 usart, u32 baud) +{ + u32 clock = 36000000; /* FIXME: Don't hardcode this clock! */ + + /* TODO: Document and explain calculation. */ + USART_BRR(usart) = (u16)((clock << 4) / (baud * 16)); +} + +void usart_set_databits(u32 usart, u32 bits) +{ + if (bits == 8) + USART_CR1(usart) &= ~CR1_M; /* 8 data bits */ + else + USART_CR1(usart) |= CR1_M; /* 9 data bits */ +} + +void usart_set_stopbits(u32 usart, u32 stopbits) +{ + u32 reg32; + + reg32 = USART_CR2(usart); + reg32 = (reg32 & ~((1 << 13) | (1 << 12))) | (stopbits << 12); + USART_CR2(usart) = reg32; +} + +void usart_set_parity(u32 usart, u32 parity) +{ + u32 reg32; + + reg32 = USART_CR1(usart); + reg32 = (reg32 & ~((1 << 10) | (1 << 9))) | (parity << 9); + USART_CR1(usart) = reg32; +} + +void usart_set_mode(u32 usart, u32 mode) +{ + u32 reg32; + + reg32 = USART_CR1(usart); + reg32 = (reg32 & ~((1 << 3) | (1 << 2))) | (mode << 2); + USART_CR1(usart) = reg32; +} + +void usart_set_flow_control(u32 usart, u32 flowcontrol) +{ + u32 reg32; + + reg32 = USART_CR3(usart); + reg32 = (reg32 & ~((1 << 9) | (1 << 8))) | (flowcontrol << 2); + USART_CR3(usart) = reg32; +} + +void usart_enable(u32 usart) +{ + USART_CR1(usart) |= CR1_UE; +} + +void usart_disable(u32 usart) +{ + USART_CR1(usart) &= ~CR1_UE; +} + +void usart_send(u32 usart, u16 data) +{ + /* Send data. */ + USART_DR(usart) = (data & 0x1ff); + + /* Wait until the data has been transferred into the shift register. */ + while ((USART_SR(usart) & SR_TXE) == 0); +} + +u16 usart_recv(u32 usart) +{ + /* Wait until the data is ready to be received. */ + while ((USART_SR(usart) & SR_RXNE) == 0); + + /* Receive data. */ + return USART_DR(usart) & 0x1ff; +}