diff options
| author | Konstantin Kirik (snegovick) <snegovick@uprojects.org> | 2026-01-04 03:47:29 +0300 |
|---|---|---|
| committer | Konstantin Kirik (snegovick) <snegovick@uprojects.org> | 2026-01-04 03:47:29 +0300 |
| commit | e4bd4c86db02d68bcfde2278bf6f2abc6dc80b62 (patch) | |
| tree | a09dc20438ae326c012744205ffd4658aac92960 /os | |
| parent | 9ac2c83df259804fa3f3c492311ea68a9545eef8 (diff) | |
Add basic UART/USART driver for stm32f769
* Currently only probably capable of init and output by polling
Diffstat (limited to 'os')
| -rw-r--r-- | os/drivers/uart/stm32f7_uart.c | 153 | ||||
| -rw-r--r-- | os/drivers/uart/stm32f7_uart.h | 12 | ||||
| -rw-r--r-- | os/drivers/uart/uart.h | 37 |
3 files changed, 202 insertions, 0 deletions
diff --git a/os/drivers/uart/stm32f7_uart.c b/os/drivers/uart/stm32f7_uart.c new file mode 100644 index 00000000..1ba64599 --- /dev/null +++ b/os/drivers/uart/stm32f7_uart.c @@ -0,0 +1,153 @@ +#include "stm32f7_uart.h" + +#define UART_BRR_MIN 0x10U /* UART BRR minimum authorized value */ +#define UART_BRR_MAX 0x0000FFFFU /* UART BRR maximum authorized value */ + +inline static void __uart_disable(struct device *dev) { + USART_TypeDef *p = dev->devptr; + p->CR1 &= ~USART_CR1_UE; +} + +inline static void __uart_enable(struct device *dev) { + USART_TypeDef *p = dev->devptr; + p->CR1 |= USART_CR1_UE; +} + +int stm32f7_uart_init(struct device *dev) { + USART_TypeDef *p = dev->devptr; + stm32f7_uart_deinit(dev); + uint32_t clk_rate = 0; + uint32_t parity = 0; + uint32_t stop_bits = 0; + uint32_t word_length = 0; + + switch (p) { + case USART1: + stm32f769_clock_control_get_rate(STM32F769_CLOCK_USART1, &clk_rate); + break; + case USART2: + stm32f769_clock_control_get_rate(STM32F769_CLOCK_USART2, &clk_rate); + break; + case USART3: + stm32f769_clock_control_get_rate(STM32F769_CLOCK_USART3, &clk_rate); + break; + case UART4: + stm32f769_clock_control_get_rate(STM32F769_CLOCK_UART4, &clk_rate); + break; + case UART5: + stm32f769_clock_control_get_rate(STM32F769_CLOCK_UART5, &clk_rate); + break; + case USART6: + stm32f769_clock_control_get_rate(STM32F769_CLOCK_USART6, &clk_rate); + break; + case UART7: + stm32f769_clock_control_get_rate(STM32F769_CLOCK_UART7, &clk_rate); + break; + case UART8: + stm32f769_clock_control_get_rate(STM32F769_CLOCK_UART8, &clk_rate); + break; + } + + switch (uart->data_bits) { + case UART_CFG_DATA_BITS_7: + word_length = USART_CR1_M1; + break; + case UART_CFG_DATA_BITS_8: + word_length = 0; + break; + case UART_CFG_DATA_BITS_9: + word_length = USART_CR1_M0; + break; + case UART_CFG_DATA_BITS_5: + case UART_CFG_DATA_BITS_6: + default: + return -1; + } + + switch (uart->parity) { + case UART_CFG_PARITY_NONE: + parity = 0; + break; + case UART_CFG_PARITY_ODD: + parity = USART_CR1_PCE; + break; + case UART_CFG_PARITY_EVEN: + parity = (USART_CR1_PCE | USART_CR1_PS); + break; + case UART_CFG_PARITY_MARK: + case UART_CFG_PARITY_SPACE: + default: + return -1; + } + + switch (uart->stop_bits) { + case UART_CFG_STOP_BITS_0_5: + stop_bits = USART_CR2_STOP_0; + break; + case UART_CFG_STOP_BITS_1: + stop_bits = 0; + break; + case UART_CFG_STOP_BITS_1_5: + stop_bits = (USART_CR2_STOP_0 | USART_CR2_STOP_1); + break; + case UART_CFG_STOP_BITS_2: + stop_bits = USART_CR2_STOP_1; + break; + default: + return -1; + } + + uint32_t cr1 = word_length | parity | USART_CR1_TE | USART_CR1_RE; + sys_io_write32(cr1, p->CR1); + cr1 = sys_io_read32(p->CR1); + + uint32_t cr2 = stop_bits; + sys_io_write32(cr2, p->CR2); + cr2 = sys_io_read32(p->CR2); + + uint32_t cr3 = 0; + sys_io_write32(cr3, p->CR3); + cr3 = sys_io_read32(p->CR3); + + uint32_t div = (clk_rate + ((uart->baudrate)/2U)) / (uart->baudrate); + if ((div >= UART_BRR_MIN) && (div <= UART_BRR_MAX)) { + p->BRR = (uint16_t)div; + } else { + return -1; + } + + sys_clear_bits(p->CR2, (USART_CR2_LINEN | USART_CR2_CLKEN)); + sys_clear_bits(p->CR3, (USART_CR3_SCEN | USART_CR3_HDSEL | USART_CR3_IREN)); + + stm32f7_uart_init(dev); + return 0; +} + +int stm32f7_uart_deinit(struct device *dev) { + __uart_disable(dev); + USART_TypeDef *p = dev->devptr; + p->CR1 = 0x0U; + p->CR2 = 0x0U; + p->CR3 = 0x0U; +} + +void stm32f7_uart_poll_out8(const struct device *dev, unsigned char ch) +{ + USART_TypeDef *p = dev->devptr; + + while ((p->ISR & UART_ISR_TXE) == 0) { + } + + p->TDR = ch; +} + +void stm32f7_uart_tx_buffer(const struct device *dev, char *buffer, unsigned int len) { + unsigned int i = 0; + for (;i < len; i++) { + usart_mik32_poll_out(dev, buffer[i]); + } +} + +void stm32f7_uart_tx(const struct device *dev, char *buffer) { + stm32f7_uart_tx_buffer(dev, buffer, strlen(buffer)); +} diff --git a/os/drivers/uart/stm32f7_uart.h b/os/drivers/uart/stm32f7_uart.h new file mode 100644 index 00000000..224f20ea --- /dev/null +++ b/os/drivers/uart/stm32f7_uart.h @@ -0,0 +1,12 @@ +#ifndef __STM32F7_UART_H__ +#define __STM32F7_UART_H__ + +#include <drivers/include/device.h> + +int stm32f7_uart_init(struct device *dev); +int stm32f7_uart_deinit(struct device *dev); +void stm32f7_uart_poll_out8(const struct device *dev, unsigned char ch); +void stm32f7_uart_tx_buffer(const struct device *dev, char *buffer, unsigned int len); +void stm32f7_uart_tx(const struct device *dev, char *buffer); + +#endif/*__STM32F7_UART_H__*/ diff --git a/os/drivers/uart/uart.h b/os/drivers/uart/uart.h new file mode 100644 index 00000000..afde5315 --- /dev/null +++ b/os/drivers/uart/uart.h @@ -0,0 +1,37 @@ +#ifndef __UART_H__ +#define __UART_H__ + +enum uart_config_parity { + UART_CFG_PARITY_NONE, /**< No parity */ + UART_CFG_PARITY_ODD, /**< Odd parity */ + UART_CFG_PARITY_EVEN, /**< Even parity */ + UART_CFG_PARITY_MARK, /**< Mark parity */ + UART_CFG_PARITY_SPACE, /**< Space parity */ +}; + +/** @brief Number of stop bits. */ +enum uart_config_stop_bits { + UART_CFG_STOP_BITS_0_5, /**< 0.5 stop bit */ + UART_CFG_STOP_BITS_1, /**< 1 stop bit */ + UART_CFG_STOP_BITS_1_5, /**< 1.5 stop bits */ + UART_CFG_STOP_BITS_2, /**< 2 stop bits */ +}; + +/** @brief Number of data bits. */ +enum uart_config_data_bits { + UART_CFG_DATA_BITS_5, /**< 5 data bits */ + UART_CFG_DATA_BITS_6, /**< 6 data bits */ + UART_CFG_DATA_BITS_7, /**< 7 data bits */ + UART_CFG_DATA_BITS_8, /**< 8 data bits */ + UART_CFG_DATA_BITS_9, /**< 9 data bits */ +}; + +struct uart_data { + struct device *dev; + int baudrate; + enum uart_config_parity parity; + enum uart_config_stop_bits stop_bits; + enum uart_config_data_bits data_bits; +}; + +#endif/*__UART_H__*/ |
