From 2e04e14ca8f9a308cde08d6ff7d84a68574be6c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=98=BF=E5=9F=BA=E7=B1=B3=E4=B8=9C?= Date: Sun, 17 Sep 2023 16:50:26 +0800 Subject: [PATCH] [bsp][mchp] serial support usart sync mode --- bsp/microchip/common/board/serial.c | 197 ++++++++++++++++++ .../samd51-adafruit-metro-m4/board/board.h | 5 + 2 files changed, 202 insertions(+) diff --git a/bsp/microchip/common/board/serial.c b/bsp/microchip/common/board/serial.c index 9878bc468a..a170950d5e 100644 --- a/bsp/microchip/common/board/serial.c +++ b/bsp/microchip/common/board/serial.c @@ -12,10 +12,205 @@ #include #include +#include /* SAM MCU serial device */ static struct rt_serial_device sam_serial; +#ifdef SOC_SAMD51 + +/** + * @brief Configure serial port + * + * This function will configure UART baudrate, parity and so on. + * + * @return RT_EOK. + */ +static rt_err_t serial_configure(struct rt_serial_device *serial, struct serial_configure *cfg) +{ + struct usart_sync_descriptor* desc; + + RT_ASSERT(serial != RT_NULL); + + desc = (struct usart_sync_descriptor *)serial->parent.user_data; + + RT_ASSERT(desc != RT_NULL); + RT_ASSERT(cfg != RT_NULL); + + usart_sync_disable(desc); + + /* Set baudrate */ + usart_sync_set_baud_rate(desc, (const uint32_t)cfg->baud_rate); + + /* Set stop bit */ + if (cfg->stop_bits == STOP_BITS_1) + usart_sync_set_stopbits(desc, USART_STOP_BITS_ONE); + else if (cfg->stop_bits == STOP_BITS_2) + usart_sync_set_stopbits(desc, USART_STOP_BITS_TWO); + + if (cfg->bit_order == BIT_ORDER_LSB) + usart_sync_set_data_order(desc, USART_DATA_ORDER_LSB); + else if (cfg->bit_order == BIT_ORDER_MSB) + usart_sync_set_data_order(desc, USART_DATA_ORDER_MSB); + + /* Set character size */ + switch (cfg->data_bits) + { + case DATA_BITS_5: + usart_sync_set_character_size(desc, USART_CHARACTER_SIZE_5BITS); + break; + case DATA_BITS_6: + usart_sync_set_character_size(desc, USART_CHARACTER_SIZE_6BITS); + break; + case DATA_BITS_7: + usart_sync_set_character_size(desc, USART_CHARACTER_SIZE_7BITS); + break; + case DATA_BITS_8: + usart_sync_set_character_size(desc, USART_CHARACTER_SIZE_8BITS); + break; + case DATA_BITS_9: + usart_sync_set_character_size(desc, USART_CHARACTER_SIZE_9BITS); + break; + default: + break; + } + + if (cfg->parity == PARITY_NONE) + usart_sync_set_parity(desc, USART_PARITY_NONE); + else if (cfg->parity == PARITY_ODD) + usart_sync_set_parity(desc, USART_PARITY_ODD); + else if (cfg->parity == PARITY_EVEN) + usart_sync_set_parity(desc, USART_PARITY_EVEN); + + usart_sync_enable(desc); + + return RT_EOK; +} + +/** + * @brief Control serial port + * + * This function provide UART enable/disable control. + * + * @return RT_EOK. + */ +static rt_err_t serial_control(struct rt_serial_device *serial, int cmd, void *arg) +{ + struct usart_sync_descriptor* desc; + + RT_ASSERT(serial != RT_NULL); + desc = (struct usart_sync_descriptor *)serial->parent.user_data; + + RT_ASSERT(desc != RT_NULL); + + switch (cmd) + { + /* disable interrupt */ + case RT_DEVICE_CTRL_CLR_INT: + usart_sync_disable(desc); + break; + /* enable interrupt */ + case RT_DEVICE_CTRL_SET_INT: + usart_sync_enable(desc); + break; + /* UART config */ + case RT_DEVICE_CTRL_CONFIG: // RT_SERIAL_RX_NON_BLOCKING or RT_SERIAL_RX_BLOCKING + // RT_SERIAL_TX_NON_BLOCKING or RT_SERIAL_TX_BLOCKING + break; +#ifdef RT_USING_SERIAL_V2 + case RT_DEVICE_CHECK_OPTMODE: + break; +#endif + default: + break; + } + + return RT_EOK; +} + +/** + * @brief Serial sends a char + * + * This function will send a char to the UART + * + * @return 1. + */ +static int serial_putc(struct rt_serial_device *serial, char c) +{ + struct usart_sync_descriptor* desc; + + RT_ASSERT(serial != RT_NULL); + desc = (struct usart_sync_descriptor *)serial->parent.user_data; + + RT_ASSERT(desc != RT_NULL); + + while (usart_sync_is_tx_empty(desc) == 0); + _usart_sync_write_byte(&TARGET_IO.device, (uint8_t)c); + + return 1; +} + +/** + * @brief Serial gets a char + * + * This function will get a char from the UART + * + * @return received char character or -1 if no char received. + */ +static int serial_getc(struct rt_serial_device *serial) +{ + char c; + int ch; + struct usart_sync_descriptor* desc; + + RT_ASSERT(serial != RT_NULL); + desc = (struct usart_sync_descriptor *)serial->parent.user_data; + + RT_ASSERT(desc != RT_NULL); + + ch = -1; + if (usart_sync_is_rx_not_empty(desc)) + { + io_read(&desc->io, (uint8_t *)&c, 1); + ch = c & 0xff; + } + + return ch; +} + +static const struct rt_uart_ops sam_serial_ops = +{ + serial_configure, + serial_control, + serial_putc, + serial_getc, +}; + +/** + * @brief Initialize the UART + * + * This function initialize the UART + * + * @return None. + */ +int rt_hw_uart_init(void) +{ + struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT; + config.baud_rate = DEFAULT_USART_BAUD_RATE; + + sam_serial.ops = &sam_serial_ops; + sam_serial.config = config; + sam_serial.serial_rx = RT_NULL; + sam_serial.serial_rx = RT_NULL; + rt_hw_serial_register(&sam_serial, RT_CONSOLE_DEVICE_NAME, + RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX | + RT_DEVICE_FLAG_INT_TX, (void *)&TARGET_IO); + + return 0; +} + +#else + static void serial_rxcallback(const struct usart_async_descriptor *const io_descr) { (void)io_descr; @@ -229,4 +424,6 @@ int rt_hw_uart_init(void) return 0; } +#endif + /*@}*/ diff --git a/bsp/microchip/samd51-adafruit-metro-m4/board/board.h b/bsp/microchip/samd51-adafruit-metro-m4/board/board.h index 6cff3ff8e5..a81ca418dc 100644 --- a/bsp/microchip/samd51-adafruit-metro-m4/board/board.h +++ b/bsp/microchip/samd51-adafruit-metro-m4/board/board.h @@ -73,6 +73,11 @@ extern int __bss_end; #define HEAP_END SAME5x_SRAM_END #endif +#ifdef RT_USING_SERIAL +#include "hpl_sercom_config.h" +#define DEFAULT_USART_BAUD_RATE CONF_SERCOM_3_USART_BAUD_RATE +#endif + void rt_hw_board_init(void); #endif