diff --git a/src/Kconfig b/src/Kconfig index ea2300ec..ad2454d8 100644 --- a/src/Kconfig +++ b/src/Kconfig @@ -96,6 +96,9 @@ config HAVE_GPIO_SPI config HAVE_GPIO_I2C bool default n +config HAVE_GPIO_UART + bool + default n config HAVE_GPIO_HARD_PWM bool default n diff --git a/src/Makefile b/src/Makefile index 98c91a30..9ce4b3fe 100644 --- a/src/Makefile +++ b/src/Makefile @@ -6,6 +6,7 @@ src-$(CONFIG_HAVE_GPIO) += initial_pins.c gpiocmds.c stepper.c endstop.c \ src-$(CONFIG_HAVE_GPIO_ADC) += adccmds.c src-$(CONFIG_HAVE_GPIO_SPI) += spicmds.c thermocouple.c src-$(CONFIG_HAVE_GPIO_I2C) += i2ccmds.c +src-$(CONFIG_HAVE_GPIO_UART) += uartcmds.c src-$(CONFIG_HAVE_GPIO_HARD_PWM) += pwmcmds.c bb-src-$(CONFIG_HAVE_GPIO_SPI) := spi_software.c sensor_adxl345.c sensor_angle.c src-$(CONFIG_HAVE_GPIO_BITBANGING) += $(bb-src-y) lcd_st7920.c lcd_hd44780.c \ diff --git a/src/atsam/Kconfig b/src/atsam/Kconfig index 36785cfe..5aa5e72c 100644 --- a/src/atsam/Kconfig +++ b/src/atsam/Kconfig @@ -9,6 +9,7 @@ config ATSAM_SELECT select HAVE_GPIO_ADC select HAVE_GPIO_I2C select HAVE_GPIO_SPI + select HAVE_GPIO_UART select HAVE_GPIO_HARD_PWM if !MACH_SAME70 select HAVE_GPIO_BITBANGING select HAVE_STRICT_TIMING diff --git a/src/atsamd/Kconfig b/src/atsamd/Kconfig index 57c99c9f..d357c385 100644 --- a/src/atsamd/Kconfig +++ b/src/atsamd/Kconfig @@ -9,6 +9,7 @@ config ATSAMD_SELECT select HAVE_GPIO_ADC select HAVE_GPIO_I2C select HAVE_GPIO_SPI + select HAVE_GPIO_UART select HAVE_GPIO_HARD_PWM if MACH_SAMD21 select HAVE_GPIO_BITBANGING select HAVE_STRICT_TIMING diff --git a/src/avr/Kconfig b/src/avr/Kconfig index fd24852d..c36e554c 100644 --- a/src/avr/Kconfig +++ b/src/avr/Kconfig @@ -9,6 +9,7 @@ config AVR_SELECT select HAVE_GPIO_ADC select HAVE_GPIO_SPI select HAVE_GPIO_I2C + select HAVE_GPIO_UART select HAVE_GPIO_HARD_PWM select HAVE_GPIO_BITBANGING if !MACH_atmega168 select HAVE_STRICT_TIMING diff --git a/src/lpc176x/Kconfig b/src/lpc176x/Kconfig index f40c3943..1cdfc007 100644 --- a/src/lpc176x/Kconfig +++ b/src/lpc176x/Kconfig @@ -9,6 +9,7 @@ config LPC_SELECT select HAVE_GPIO_ADC select HAVE_GPIO_I2C select HAVE_GPIO_SPI + select HAVE_GPIO_UART select HAVE_GPIO_BITBANGING select HAVE_STRICT_TIMING select HAVE_CHIPID diff --git a/src/rp2040/Kconfig b/src/rp2040/Kconfig index c2a45e55..f9b68bb2 100644 --- a/src/rp2040/Kconfig +++ b/src/rp2040/Kconfig @@ -8,6 +8,7 @@ config RP2040_SELECT select HAVE_GPIO select HAVE_GPIO_ADC select HAVE_GPIO_SPI + select HAVE_GPIO_UART select HAVE_GPIO_I2C select HAVE_GPIO_BITBANGING select HAVE_STRICT_TIMING diff --git a/src/stm32/Kconfig b/src/stm32/Kconfig index 0e0ffa0e..934a6920 100644 --- a/src/stm32/Kconfig +++ b/src/stm32/Kconfig @@ -7,6 +7,7 @@ config STM32_SELECT default y select HAVE_GPIO select HAVE_GPIO_ADC + select HAVE_GPIO_UART if !MACH_STM32F031 select HAVE_GPIO_I2C if !(MACH_STM32F031 || MACH_STM32H7) select HAVE_GPIO_SPI if !MACH_STM32F031 select HAVE_GPIO_HARD_PWM if MACH_STM32F1 || MACH_STM32F4 || MACH_STM32H7 diff --git a/src/uartcmds.c b/src/uartcmds.c new file mode 100644 index 00000000..b3e25a86 --- /dev/null +++ b/src/uartcmds.c @@ -0,0 +1,118 @@ +// Commands for sending messages on a UART bus +// +// Copyright (C) 2021 Desuuuu +// +// This file may be distributed under the terms of the GNU GPLv3 license. + +#include // memcpy +#include "basecmd.h" // oid_alloc +#include "command.h" // DECL_COMMAND +#include "sched.h" // DECL_SHUTDOWN +#include "board/serial_irq.h" //serial_prepare/send + +struct uartdev_s { + uint8_t id, rx_buf, tx_buf, ready; + uint16_t rx_interval; +}; + +int_fast8_t uart_process(uint8_t id, uint8_t* data, uint_fast8_t len + , uint_fast8_t *pop_count); + +void +command_config_uart(uint32_t *args) +{ + struct uartdev_s *uart = oid_alloc(args[0], command_config_uart, + sizeof(*uart)); + uart->rx_buf = args[1]; + uart->tx_buf = args[2]; + uart->rx_interval = args[3]; + uart->ready = 0; +} +DECL_COMMAND(command_config_uart, + "config_uart oid=%c rx_buffer=%c tx_buffer=%c rx_interval=%hu"); + +struct uartdev_s * +uartdev_oid_lookup(uint8_t oid) +{ + return oid_lookup(oid, command_config_uart); +} + +void +command_uart_set_bus(uint32_t *args) +{ + struct uartdev_s *uart = uartdev_oid_lookup(args[0]); + if (uart->ready) + shutdown("Invalid UART config"); + uart->ready = 1; + uart->id = serial_prepare(args[1], args[2], uart->rx_buf, uart->tx_buf, + uart->rx_interval, &uart_process); +} +DECL_COMMAND(command_uart_set_bus, "uart_set_bus oid=%c uart_bus=%c baud=%u"); + +void +command_uart_send(uint32_t *args) +{ + struct uartdev_s *uart = uartdev_oid_lookup(args[0]); + if (!uart->ready) + return; + uint8_t data_len = args[1]; + uint8_t *data = command_decode_ptr(args[2]); + serial_send(uart->id, data, data_len); +} +DECL_COMMAND(command_uart_send, "uart_send oid=%c data=%*s"); + +int_fast8_t +uart_process(uint8_t id, uint8_t* data, uint_fast8_t len + , uint_fast8_t *pop_count) +{ + uint8_t oid; + struct uartdev_s *uart; + foreach_oid(oid, uart, command_config_uart) { + if (uart->id != id) + continue; + if (!sendf("uart_receive oid=%c data=%*s", oid, len, data)) + return 0; + break; + } + *pop_count = len; + return 1; +} + +/**************************************************************** + * Shutdown handling + ****************************************************************/ + +struct uartdev_shutdown_s { + struct uartdev_s *uart; + uint8_t shutdown_msg_len; + uint8_t shutdown_msg[]; +}; + +void +command_config_uart_shutdown(uint32_t *args) +{ + struct uartdev_s *uart = uartdev_oid_lookup(args[1]); + uint8_t shutdown_msg_len = args[2]; + struct uartdev_shutdown_s *sd = oid_alloc( + args[0], command_config_uart_shutdown, + sizeof(*sd) + shutdown_msg_len); + sd->uart = uart; + sd->shutdown_msg_len = shutdown_msg_len; + uint8_t *shutdown_msg = command_decode_ptr(args[3]); + memcpy(sd->shutdown_msg, shutdown_msg, shutdown_msg_len); +} +DECL_COMMAND(command_config_uart_shutdown, + "config_uart_shutdown oid=%c uart_oid=%c shutdown_msg=%*s"); + +void +uartdev_shutdown(void) +{ + uint8_t oid; + struct uartdev_shutdown_s *sd; + foreach_oid(oid, sd, command_config_uart_shutdown) { + if (!sd->uart->ready) + continue; + serial_send(sd->uart->id, sd->shutdown_msg, sd->shutdown_msg_len); + } +} +DECL_SHUTDOWN(uartdev_shutdown);