embox
248 строк · 6.1 Кб
1/**
2* @file
3* @brief
4*
5* @author Vadim Deryabkin
6* @date 07.02.2021
7*/
8
9#include <stdint.h>10#include <string.h>11
12#include <hal/reg.h>13#include <kernel/irq.h>14
15#include <drivers/serial/diag_serial.h>16#include <drivers/serial/uart_dev.h>17
18#include "stm32_usart_conf_l0x0.h"19
20// Doc: DocID031151 Rev 1, RM0451, 620/774.
21#define USART_BRR(USART_CLK,USART_BAUDRATE) (2 * USART_CLK / USART_BAUDRATE)22
23// Clock part.
24static const uint32_t HSI_VALUE = 16000000;25extern const uint32_t HSE_VALUE;26
27typedef struct {28volatile uint32_t CR; // 0x0029volatile uint32_t ICSCR; // 0x0430volatile uint32_t RES_1; // 0x0831volatile uint32_t CFGR; // 0x0C32volatile uint32_t CIER; // 0x1033volatile uint32_t CIFR; // 0x1434volatile uint32_t CICR; // 0x1835volatile uint32_t IOPRSTR; // 0x1C36volatile uint32_t AHBRSTR; // 0x2037volatile uint32_t APB2RSTR; // 0x2438volatile uint32_t APB1RSTR; // 0x2839volatile uint32_t IOPENR; // 0x2C40volatile uint32_t AHBENR; // 0x3041volatile uint32_t APB2ENR; // 0x3442volatile uint32_t APB1ENR; // 0x3843volatile uint32_t IOPSMEN; // 0x3C44volatile uint32_t AHBSMENR; // 0x4045volatile uint32_t APB2SMENR; // 0x4446volatile uint32_t APB1SMENR; // 0x4847volatile uint32_t CCIPR; // 0x4C48volatile uint32_t CSR; // 0x5049} rcc_struct; // Doc: DocID031151 Rev 1, RM0451, 185/774.50
51// Doc: DocID031151 Rev 1, RM0451, 39/774.
52#define RCC ((rcc_struct *) 0X40021000)53
54static uint32_t get_hsi_clk () {55if (RCC->CR & (1 << 4)) {56return HSI_VALUE / 4;57} else {58return HSI_VALUE;59}60}
61
62static uint32_t PLLMUL_VALUE[9] = {3, 4, 6, 8, 12, 16, 24, 32, 48};63
64static uint32_t get_pll_clk () {65uint32_t src_clk;66
67if (RCC->CFGR & (1 << 16)) {68src_clk = HSE_VALUE;69} else {70src_clk = get_hsi_clk();71}72
73src_clk *= PLLMUL_VALUE[(RCC->CFGR >> 18) & 0b1111];74src_clk /= ((RCC->CFGR >> 22) & 0b11) + 1;75return src_clk;76}
77
78static uint32_t HPRE_VALUE[8] = {2, 4, 8, 16, 64, 128, 256, 512};79static uint32_t PPRE_VALUE[8] = {2, 4, 8, 16};80
81static uint32_t MSI_CLI_TABLE[8] = {8265536, 131072, 262144, 524288, 1048000, 2097000, 4194000, 083};84
85static uint32_t get_msi_clk () {86return MSI_CLI_TABLE[(RCC->ICSCR & (0b111 << 13)) >> 13];87}
88
89static uint32_t get_usart_clk () {90volatile uint32_t SW_SRC;91
92switch ((RCC->CFGR & (0b11 << 2)) >> 2) {93case 0b00:94SW_SRC = get_msi_clk();95break;96
97case 0b01:98SW_SRC = get_hsi_clk();99break;100
101case 0b10:102SW_SRC = HSE_VALUE;103break;104
105case 0b11:106SW_SRC = get_pll_clk();107break;108}109
110if (RCC->CFGR & (1 << 7)) {111SW_SRC /= HPRE_VALUE[((RCC->CFGR >> 4) & 0b111)];112}113
114if (RCC->CFGR & (1 << 10)) {115SW_SRC /= PPRE_VALUE[((RCC->CFGR >> 8) & 0b111)];116}117
118return SW_SRC;119}
120
121static void set_usart_pwr () {122RCC->APB1ENR |= 1 << 17; // On USART2.123}
124
125// GPIO part.
126static void set_gpio_pwr (uint32_t port) {127RCC->IOPENR |= (1 << port); // Doc: DocID031151 Rev 1, RM0451, 169/774.128}
129
130static gpio_struct *get_gpio (unsigned char port) {131uint8_t *p = (uint8_t *)GPIOA;132p += 1024 * port;133return (gpio_struct *)p;134}
135
136static void set_gpio_af (uint32_t port, uint32_t pin, uint32_t func) {137gpio_struct* GPIO = get_gpio(port);138
139if (pin < PINS_NUMBER / 2) {140GPIO->AFRL &= ~L_AF_MSK(pin);141GPIO->AFRL |= L_AF(pin, func);142} else {143GPIO->AFRH &= ~H_AF_MSK(pin);144GPIO->AFRH |= H_AF(pin, func);145}146
147GPIO->MODER &= ~M_MSK(pin);148GPIO->MODER |= M_ALT(pin);149}
150
151static void set_gpio_high_spped (uint32_t port, uint32_t pin) {152gpio_struct* GPIO = get_gpio(port);153
154GPIO->OSPEEDR &= ~S_MSK(pin);155GPIO->OSPEEDR |= S_HS(pin);156}
157
158static void init_usart_gpio () {159set_gpio_pwr(OPTION_GET(NUMBER,port_tx));160set_gpio_pwr(OPTION_GET(NUMBER,port_rx));161
162set_gpio_af(OPTION_GET(NUMBER,port_tx), OPTION_GET(NUMBER,pin_tx), OPTION_GET(NUMBER,pin_tx_af));163set_gpio_af(OPTION_GET(NUMBER,port_rx), OPTION_GET(NUMBER,pin_rx), OPTION_GET(NUMBER,pin_rx_af));164
165set_gpio_high_spped(OPTION_GET(NUMBER,port_tx), OPTION_GET(NUMBER,pin_tx));166set_gpio_high_spped(OPTION_GET(NUMBER,port_rx), OPTION_GET(NUMBER,pin_rx));167}
168
169// USART part.
170static int stm32_uart_setup(struct uart *dev, const struct uart_params *params) {171init_usart_gpio();172
173usart_struct *USART = (usart_struct *)dev->base_addr;174volatile uint32_t usart_clk = get_usart_clk();175
176set_usart_pwr();177
178USART->BRR = (USART_BRR(usart_clk, dev->params.baud_rate) & 0xFFFFFFF0) |179((USART_BRR(usart_clk, dev->params.baud_rate) & 0xF) >> 1);180
181USART->CR1 = (1 << 15)|(1 << 3)|(1 << 2)|(1 << 0);182
183if (dev->params.uart_param_flags & UART_PARAM_FLAGS_USE_IRQ) {184USART->CR1 |= (1 << 5);185}186
187return 0;188}
189
190static int stm32_uart_putc(struct uart *dev, int ch) {191usart_struct *USART = (usart_struct *)dev->base_addr;192
193while ((USART->ISR & (1 << 7)) == 0);194USART->TDR = (char)ch;195
196return 0;197}
198
199static int stm32_uart_hasrx(struct uart *dev) {200usart_struct *USART = (usart_struct *)dev->base_addr;201return USART->ISR & (1 << 5);202}
203
204static int stm32_uart_getc(struct uart *dev) {205usart_struct *USART = (usart_struct *)dev->base_addr;206return USART->RDR & 0xFF;207}
208
209static int stm32_uart_irq_en(struct uart *dev, const struct uart_params *params) {210if (params->uart_param_flags & UART_PARAM_FLAGS_USE_IRQ) {211usart_struct *USART = (usart_struct *)dev->base_addr;212
213USART->CR1 |= (1 << 5);214}215return 0;216}
217
218static int stm32_uart_irq_dis(struct uart *dev, const struct uart_params *params) {219if (params->uart_param_flags & UART_PARAM_FLAGS_USE_IRQ) {220usart_struct *USART = (usart_struct *)dev->base_addr;221
222USART->CR1 &= ~(1 << 5);223}224return 0;225}
226
227// System part.
228const struct uart_ops stm32_uart_ops = {229.uart_getc = stm32_uart_getc,230.uart_putc = stm32_uart_putc,231.uart_hasrx = stm32_uart_hasrx,232.uart_setup = stm32_uart_setup,233.uart_irq_en = stm32_uart_irq_en,234.uart_irq_dis = stm32_uart_irq_dis,235};236
237static struct uart stm32_diag = {238.uart_ops = &stm32_uart_ops,239.irq_num = USARTx_IRQn,240.base_addr = (unsigned long)USARTx,241};242
243static const struct uart_params diag_defparams = {244.baud_rate = OPTION_GET(NUMBER,baud_rate),245.uart_param_flags = UART_PARAM_FLAGS_8BIT_WORD,246};247
248DIAG_SERIAL_DEF(&stm32_diag, &diag_defparams);249