File indexing completed on 2025-05-11 08:23:06
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028 #ifdef HAVE_CONFIG_H
0029 #include "config.h"
0030 #endif
0031
0032 #include <stm32h7/hal.h>
0033
0034 #include <bsp.h>
0035 #include <bsp/irq.h>
0036 #include <bsp/fatal.h>
0037 #include <rtems/console.h>
0038
0039 #include <inttypes.h>
0040 #include <stdio.h>
0041 #include <unistd.h>
0042
0043 static stm32h7_uart_context * const stm32h7_uart_instances[] = {
0044 #ifdef STM32H7_CONSOLE_ENABLE_USART1
0045 &stm32h7_usart1_instance,
0046 #endif
0047 #ifdef STM32H7_CONSOLE_ENABLE_USART2
0048 &stm32h7_usart2_instance,
0049 #endif
0050 #ifdef STM32H7_CONSOLE_ENABLE_USART3
0051 &stm32h7_usart3_instance,
0052 #endif
0053 #ifdef STM32H7_CONSOLE_ENABLE_UART4
0054 &stm32h7_uart4_instance,
0055 #endif
0056 #ifdef STM32H7_CONSOLE_ENABLE_UART5
0057 &stm32h7_uart5_instance,
0058 #endif
0059 #ifdef STM32H7_CONSOLE_ENABLE_USART6
0060 &stm32h7_usart6_instance,
0061 #endif
0062 #ifdef STM32H7_CONSOLE_ENABLE_UART7
0063 &stm32h7_uart7_instance,
0064 #endif
0065 #ifdef STM32H7_CONSOLE_ENABLE_UART8
0066 &stm32h7_uart8_instance,
0067 #endif
0068 #if defined(STM32H7_CONSOLE_ENABLE_UART9) && defined(UART9)
0069 &stm32h7_uart9_instance,
0070 #endif
0071 #if defined(STM32H7_CONSOLE_ENABLE_USART10) && defined(USART10)
0072 &stm32h7_usart10_instance
0073 #endif
0074 };
0075
0076 static bool stm32h7_uart_set_attributes(
0077 rtems_termios_device_context *base,
0078 const struct termios *term
0079 )
0080 {
0081 stm32h7_uart_context *ctx;
0082 uint32_t previous_baud;
0083 uint32_t previous_stop_bits;
0084 uint32_t previous_parity;
0085 uint32_t previous_mode;
0086 HAL_StatusTypeDef status;
0087
0088 if ((term->c_cflag & CSIZE) != CS8) {
0089 return false;
0090 }
0091
0092 ctx = stm32h7_uart_get_context(base);
0093
0094 previous_baud = ctx->uart.Init.BaudRate;
0095 ctx->uart.Init.BaudRate = rtems_termios_baud_to_number(term->c_ospeed);
0096
0097 previous_stop_bits = ctx->uart.Init.StopBits;
0098 if ((term->c_cflag & CSTOPB) != 0) {
0099 ctx->uart.Init.StopBits = UART_STOPBITS_2;
0100 } else {
0101 ctx->uart.Init.StopBits = UART_STOPBITS_1;
0102 }
0103
0104 previous_parity = ctx->uart.Init.Parity;
0105 if ((term->c_cflag & PARENB) != 0) {
0106 if ((term->c_cflag & PARODD) != 0) {
0107 ctx->uart.Init.Parity = UART_PARITY_ODD;
0108 } else {
0109 ctx->uart.Init.Parity = UART_PARITY_EVEN;
0110 }
0111 } else {
0112 ctx->uart.Init.Parity = UART_PARITY_NONE;
0113 }
0114
0115 previous_mode = ctx->uart.Init.Mode;
0116 if ((term->c_cflag & CREAD) != 0) {
0117 ctx->uart.Init.Mode = UART_MODE_TX_RX;
0118 } else {
0119 ctx->uart.Init.Mode = UART_MODE_RX;
0120 }
0121
0122 status = UART_SetConfig(&ctx->uart);
0123 if (status != HAL_OK) {
0124 ctx->uart.Init.BaudRate = previous_baud;
0125 ctx->uart.Init.StopBits = previous_stop_bits;
0126 ctx->uart.Init.Parity = previous_parity;
0127 ctx->uart.Init.Mode = previous_mode;
0128 return false;
0129 }
0130
0131 return true;
0132 }
0133
0134 #ifdef BSP_CONSOLE_USE_INTERRUPTS
0135 static void stm32h7_uart_interrupt(void *arg)
0136 {
0137 rtems_termios_tty *tty;
0138 rtems_termios_device_context *base;
0139 stm32h7_uart_context *ctx;
0140 USART_TypeDef *regs;
0141 uint32_t isr;
0142
0143 tty = arg;
0144 base = rtems_termios_get_device_context(tty);
0145 ctx = stm32h7_uart_get_context(base);
0146 regs = ctx->uart.Instance;
0147 isr = regs->ISR;
0148
0149 while ((isr & USART_ISR_RXNE_RXFNE) != 0) {
0150 char c;
0151
0152 c = (uint8_t) regs->RDR;
0153 rtems_termios_enqueue_raw_characters(tty, &c, 1);
0154
0155 isr = regs->ISR;
0156 }
0157
0158 if (ctx->transmitting && (isr & USART_ISR_TXE_TXFNF) != 0) {
0159 rtems_termios_dequeue_characters(tty, 1);
0160 }
0161
0162 regs->ICR = USART_ICR_ORECF;
0163 }
0164 #endif
0165
0166 static bool stm32h7_uart_first_open(
0167 rtems_termios_tty *tty,
0168 rtems_termios_device_context *base,
0169 struct termios *term,
0170 rtems_libio_open_close_args_t *args
0171 )
0172 {
0173 stm32h7_uart_context *ctx;
0174 UART_HandleTypeDef *uart;
0175 #ifdef BSP_CONSOLE_USE_INTERRUPTS
0176 rtems_status_code sc;
0177 #endif
0178
0179 ctx = stm32h7_uart_get_context(base);
0180 uart = &ctx->uart;
0181
0182 rtems_termios_set_initial_baud(tty, BSP_CONSOLE_BAUD);
0183
0184 (void) HAL_UART_Init(uart);
0185 (void) HAL_UARTEx_SetTxFifoThreshold(uart, UART_TXFIFO_THRESHOLD_1_8);
0186 (void) HAL_UARTEx_SetRxFifoThreshold(uart, UART_RXFIFO_THRESHOLD_1_8);
0187 (void) HAL_UARTEx_EnableFifoMode(uart);
0188
0189 #ifdef BSP_CONSOLE_USE_INTERRUPTS
0190 sc = rtems_interrupt_handler_install(
0191 ctx->config->irq,
0192 "UART",
0193 RTEMS_INTERRUPT_SHARED,
0194 stm32h7_uart_interrupt,
0195 tty
0196 );
0197 if (sc != RTEMS_SUCCESSFUL) {
0198 return false;
0199 }
0200
0201 ctx->uart.Instance->CR1 |= USART_CR1_RXNEIE_RXFNEIE;
0202 #endif
0203
0204 stm32h7_uart_set_attributes(base, term);
0205
0206 return true;
0207 }
0208
0209 static void stm32h7_uart_last_close(
0210 rtems_termios_tty *tty,
0211 rtems_termios_device_context *base,
0212 rtems_libio_open_close_args_t *args
0213 )
0214 {
0215 #ifdef BSP_CONSOLE_USE_INTERRUPTS
0216 stm32h7_uart_context *ctx;
0217
0218 ctx = stm32h7_uart_get_context(base);
0219
0220 (void) rtems_interrupt_handler_remove(
0221 ctx->config->irq,
0222 stm32h7_uart_interrupt,
0223 tty
0224 );
0225 #endif
0226 }
0227
0228 static void stm32h7_uart_write(
0229 rtems_termios_device_context *base,
0230 const char *buf,
0231 size_t len
0232 )
0233 {
0234 #ifdef BSP_CONSOLE_USE_INTERRUPTS
0235 stm32h7_uart_context *ctx;
0236 USART_TypeDef *regs;
0237
0238 ctx = stm32h7_uart_get_context(base);
0239 regs = ctx->uart.Instance;
0240
0241 if (len > 0) {
0242 ctx->transmitting = true;
0243 regs->TDR = (uint8_t) buf[0];
0244 regs->CR1 |= USART_CR1_TXEIE_TXFNFIE;
0245 } else {
0246 ctx->transmitting = false;
0247 regs->CR1 &= ~USART_CR1_TXEIE_TXFNFIE;
0248 }
0249 #else
0250 size_t i;
0251
0252 for (i = 0; i < len; ++i) {
0253 stm32h7_uart_polled_write(base, buf[i]);
0254 }
0255 #endif
0256 }
0257
0258 static const rtems_termios_device_handler stm32h7_uart_handler = {
0259 .first_open = stm32h7_uart_first_open,
0260 .last_close = stm32h7_uart_last_close,
0261 .write = stm32h7_uart_write,
0262 .set_attributes = stm32h7_uart_set_attributes,
0263 #ifdef BSP_CONSOLE_USE_INTERRUPTS
0264 .mode = TERMIOS_IRQ_DRIVEN
0265 #else
0266 .poll_read = stm32h7_uart_polled_read,
0267 .mode = TERMIOS_POLLED
0268 #endif
0269 };
0270
0271 rtems_status_code console_initialize(
0272 rtems_device_major_number major,
0273 rtems_device_minor_number minor,
0274 void *arg
0275 )
0276 {
0277 size_t i;
0278
0279 rtems_termios_initialize();
0280
0281 for (i = 0; i < RTEMS_ARRAY_SIZE(stm32h7_uart_instances); ++i) {
0282 stm32h7_uart_context *ctx;
0283 char path[sizeof("/dev/ttySXXX")];
0284
0285 ctx = stm32h7_uart_instances[i];
0286 snprintf(path, sizeof(path), "/dev/ttyS%" PRIu8, ctx->config->device_index);
0287
0288 rtems_termios_device_install(
0289 path,
0290 &stm32h7_uart_handler,
0291 NULL,
0292 &ctx->device
0293 );
0294
0295 if (ctx == &STM32H7_PRINTK_INSTANCE) {
0296 link(path, CONSOLE_DEVICE_NAME);
0297 }
0298 }
0299
0300 return RTEMS_SUCCESSFUL;
0301 }