File indexing completed on 2025-05-11 08:23:05
0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <libchip/sersupp.h>
0010
0011 #include <bsp.h>
0012 #include <bsp/io.h>
0013 #include <bsp/rcc.h>
0014 #include <bsp/irq.h>
0015 #include <bsp/usart.h>
0016 #include <bsp/stm32f4.h>
0017 #include <termios.h>
0018 #include <string.h>
0019
0020 static volatile stm32f4_usart *usart_get_regs(const console_tbl *ct)
0021 {
0022 return (stm32f4_usart *) ct->ulCtrlPort1;
0023 }
0024
0025 #if 0
0026 static rtems_vector_number usart_get_irq_number(const console_tbl *ct)
0027 {
0028 return ct->ulIntVector;
0029 }
0030 #endif
0031
0032 #ifdef BSP_CONSOLE_USE_INTERRUPTS
0033
0034
0035
0036 static void stm32f4_usart_interrupt(void *arg)
0037 {
0038 rtems_termios_tty *tty = (rtems_termios_tty *) arg;
0039 const console_tbl *ct = Console_Port_Tbl [tty->minor];
0040 volatile stm32f4_usart *usart = usart_get_regs(ct);
0041
0042 while ((usart->sr & STM32F4_USART_SR_RXNE) == STM32F4_USART_SR_RXNE)
0043 {
0044 char data = STM32F4_USART_DR_GET(usart->dr);
0045 rtems_termios_enqueue_raw_characters(tty, &data, sizeof(data));
0046 }
0047 }
0048 #endif
0049
0050 static const stm32f4_rcc_index usart_rcc_index [] = {
0051 STM32F4_RCC_USART1,
0052 STM32F4_RCC_USART2,
0053 STM32F4_RCC_USART3,
0054 STM32F4_RCC_UART4,
0055 STM32F4_RCC_UART5,
0056 #ifdef STM32F4_FAMILY_F4XXXX
0057 STM32F4_RCC_USART6
0058 #endif
0059 };
0060
0061 static stm32f4_rcc_index usart_get_rcc_index(const console_tbl *ct)
0062 {
0063 return usart_rcc_index [ct->ulCtrlPort2];
0064 }
0065
0066 static const uint8_t usart_pclk_index [] = { 1, 0, 0, 0, 0, 1 };
0067
0068 static const uint32_t usart_pclk_by_index [] = {
0069 STM32F4_PCLK1,
0070 STM32F4_PCLK2
0071 };
0072
0073 static uint32_t usart_get_pclk(const console_tbl *ct)
0074 {
0075 return usart_pclk_by_index [usart_pclk_index [ct->ulCtrlPort2]];
0076 }
0077
0078 static uint32_t usart_get_baud(const console_tbl *ct)
0079 {
0080 return ct->ulClock;
0081 }
0082
0083
0084
0085
0086
0087
0088
0089
0090
0091
0092
0093
0094
0095
0096
0097
0098 static uint32_t usart_get_bbr(
0099 volatile stm32f4_usart *usart,
0100 uint32_t pclk,
0101 uint32_t baud
0102 )
0103 {
0104 uint32_t a = 8 * (2 - ((usart->cr1 & STM32F4_USART_CR1_OVER8) != 0));
0105 uint32_t div_mantissa_low = pclk / (a * baud);
0106 uint32_t div_fraction_low = pclk / (baud - a * div_mantissa_low);
0107 uint32_t div_mantissa_high;
0108 uint32_t div_fraction_high;
0109 uint32_t high_err;
0110 uint32_t low_err;
0111 uint32_t div_mantissa;
0112 uint32_t div_fraction;
0113
0114 if (div_fraction_low < a - 1) {
0115 div_mantissa_high = div_fraction_low;
0116 div_fraction_high = div_fraction_low + 1;
0117 } else {
0118 div_mantissa_high = div_fraction_low + 1;
0119 div_fraction_high = 0;
0120 }
0121
0122 high_err = pclk - baud * (a * div_mantissa_high + div_fraction_high);
0123 low_err = baud * (a * div_mantissa_low + div_fraction_low) - pclk;
0124
0125 if (low_err < high_err) {
0126 div_mantissa = div_mantissa_low;
0127 div_fraction = div_fraction_low;
0128 } else {
0129 div_mantissa = div_mantissa_high;
0130 div_fraction = div_fraction_high;
0131 }
0132
0133 return STM32F4_USART_BBR_DIV_MANTISSA(div_mantissa)
0134 | STM32F4_USART_BBR_DIV_FRACTION(div_fraction);
0135 }
0136
0137 static void usart_initialize(int minor)
0138 {
0139 const console_tbl *ct = Console_Port_Tbl [minor];
0140 volatile stm32f4_usart *usart = usart_get_regs(ct);
0141 uint32_t pclk = usart_get_pclk(ct);
0142 uint32_t baud = usart_get_baud(ct);
0143 stm32f4_rcc_index rcc_index = usart_get_rcc_index(ct);
0144
0145 stm32f4_rcc_set_clock(rcc_index, true);
0146
0147 usart->cr1 = 0;
0148 usart->cr2 = 0;
0149 usart->cr3 = 0;
0150 usart->bbr = usart_get_bbr(usart, pclk, baud);
0151 usart->cr1 = STM32F4_USART_CR1_UE
0152 #ifdef BSP_CONSOLE_USE_INTERRUPTS
0153 | STM32F4_USART_CR1_RXNEIE
0154 #endif
0155 | STM32F4_USART_CR1_TE
0156 | STM32F4_USART_CR1_RE;
0157 }
0158
0159 static int usart_first_open(int major, int minor, void *arg)
0160 {
0161 rtems_status_code sc = RTEMS_SUCCESSFUL;
0162 rtems_libio_open_close_args_t *oc = (rtems_libio_open_close_args_t *) arg;
0163 rtems_termios_tty *tty = (struct rtems_termios_tty *) oc->iop->data1;
0164 const console_tbl *ct = Console_Port_Tbl [minor];
0165 console_data *cd = &Console_Port_Data [minor];
0166
0167 cd->termios_data = tty;
0168 rtems_termios_set_initial_baud(tty, ct->ulClock);
0169
0170 #ifdef BSP_CONSOLE_USE_INTERRUPTS
0171 sc = rtems_interrupt_handler_install(ct->ulIntVector,
0172 ct->sDeviceName,
0173 RTEMS_INTERRUPT_UNIQUE,
0174 stm32f4_usart_interrupt,
0175 tty);
0176 #endif
0177
0178 return sc;
0179 }
0180
0181 static int usart_last_close(int major, int minor, void *arg)
0182 {
0183 rtems_status_code sc = RTEMS_SUCCESSFUL;
0184 #ifdef BSP_CONSOLE_USE_INTERRUPTS
0185 rtems_libio_open_close_args_t *oc = (rtems_libio_open_close_args_t *) arg;
0186 rtems_termios_tty *tty = (struct rtems_termios_tty *) oc->iop->data1;
0187 const console_tbl *ct = Console_Port_Tbl [minor];
0188
0189 sc = rtems_interrupt_handler_remove(ct->ulIntVector, stm32f4_usart_interrupt, tty);
0190 #endif
0191 return sc;
0192 }
0193
0194 #ifndef BSP_CONSOLE_USE_INTERRUPTS
0195 static int usart_read_polled(int minor)
0196 {
0197 const console_tbl *ct = Console_Port_Tbl [minor];
0198 volatile stm32f4_usart *usart = usart_get_regs(ct);
0199
0200 if ((usart->sr & STM32F4_USART_SR_RXNE) != 0) {
0201 return STM32F4_USART_DR_GET(usart->dr);
0202 } else {
0203 return -1;
0204 }
0205 }
0206 #endif
0207
0208 static void usart_write_polled(int minor, char c)
0209 {
0210 const console_tbl *ct = Console_Port_Tbl [minor];
0211 volatile stm32f4_usart *usart = usart_get_regs(ct);
0212
0213 while ((usart->sr & STM32F4_USART_SR_TXE) == 0) {
0214
0215 }
0216
0217 usart->dr = STM32F4_USART_DR(c);
0218 }
0219
0220 static ssize_t usart_write_support_polled(
0221 int minor,
0222 const char *s,
0223 size_t n
0224 )
0225 {
0226 ssize_t i = 0;
0227
0228 for (i = 0; i < n; ++i) {
0229 usart_write_polled(minor, s [i]);
0230 }
0231
0232 return n;
0233 }
0234
0235
0236
0237
0238 static int usart_set_attributes(int minor, const struct termios *term)
0239 {
0240 console_tbl *ct = Console_Port_Tbl[minor];
0241 volatile stm32f4_usart *usart = usart_get_regs(ct);
0242 uint32_t pclk = usart_get_pclk(ct);
0243 uint32_t baud = term->c_ispeed;
0244
0245 ct->ulClock = baud;
0246 usart->bbr = usart_get_bbr(usart, pclk, baud);
0247 return 0;
0248 }
0249
0250 const console_fns stm32f4_usart_fns = {
0251 .deviceProbe = libchip_serial_default_probe,
0252 .deviceFirstOpen = usart_first_open,
0253 .deviceLastClose = usart_last_close,
0254 #ifdef BSP_CONSOLE_USE_INTERRUPTS
0255 .deviceRead = NULL,
0256 #else
0257 .deviceRead = usart_read_polled,
0258 #endif
0259 .deviceWrite = usart_write_support_polled,
0260 .deviceInitialize = usart_initialize,
0261 .deviceWritePolled = usart_write_polled,
0262 .deviceSetAttributes = usart_set_attributes,
0263 .deviceOutputUsesInterrupts = false
0264 };