doc: renamed project
This commit is contained in:
committed by
Sylvan Arnold
parent
244e516bd8
commit
32618389d1
679
pico-sensor/McuLib/src/McuUart485.c
Normal file
679
pico-sensor/McuLib/src/McuUart485.c
Normal file
@@ -0,0 +1,679 @@
|
||||
/*
|
||||
* Copyright (c) 2020-2023, Erich Styger
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include "McuUart485.h"
|
||||
#if McuUart485_CONFIG_USE_RS_485
|
||||
#include "McuShell.h"
|
||||
#include "McuRTOS.h"
|
||||
#include "McuUtility.h"
|
||||
#include "McuLog.h"
|
||||
#include "McuGPIO.h"
|
||||
#include <ctype.h> /* for isprint() */
|
||||
|
||||
#if McuLib_CONFIG_CPU_IS_ESP32
|
||||
#include "esp_system.h"
|
||||
#include "driver/uart.h"
|
||||
#endif
|
||||
|
||||
#if !McuUart485_CONFIG_USE_HW_OE_RTS
|
||||
|
||||
static McuGPIO_Handle_t RS485_TxEn; /* LOW: Rx, HIGH: Tx */
|
||||
|
||||
void McuUart485_GPIO_RxEnable(void) {
|
||||
McuGPIO_SetLow(RS485_TxEn);
|
||||
#if McuLib_CONFIG_CPU_IS_RPxxxx
|
||||
uart_get_hw(McuUart485_CONFIG_UART_DEVICE)->cr |= UART_UARTCR_RXE_BITS; /* enable receiver for half duplex communication */
|
||||
#endif
|
||||
}
|
||||
|
||||
void McuUart485_GPIO_TxEnable(void) {
|
||||
#if McuLib_CONFIG_CPU_IS_RPxxxx
|
||||
uart_get_hw(McuUart485_CONFIG_UART_DEVICE)->cr &= ~UART_UARTCR_RXE_BITS; /* disable receiver for half duplex communication */
|
||||
#endif
|
||||
McuGPIO_SetHigh(RS485_TxEn);
|
||||
}
|
||||
|
||||
static void McuUart485_GPIO_Deinit(void) {
|
||||
RS485_TxEn = McuGPIO_DeinitGPIO(RS485_TxEn);
|
||||
}
|
||||
|
||||
static void McuUart485_GPIO_Init(void) {
|
||||
McuGPIO_Config_t config;
|
||||
|
||||
McuGPIO_GetDefaultConfig(&config);
|
||||
#if McuLib_CONFIG_CPU_IS_ESP32
|
||||
config.hw.pin = McuUart485_CONFIG_TX_EN_GPIO;
|
||||
#elif McuLib_CONFIG_CPU_IS_RPxxxx
|
||||
config.hw.pin = McuUart485_CONFIG_TX_EN_PIN;
|
||||
#else
|
||||
config.hw.gpio = McuUart485_CONFIG_TX_EN_GPIO;
|
||||
config.hw.port = McuUart485_CONFIG_TX_EN_PORT;
|
||||
config.hw.pin = McuUart485_CONFIG_TX_EN_PIN;
|
||||
#endif
|
||||
config.isInput = false;
|
||||
config.isHighOnInit = false; /* Tx disabled */
|
||||
RS485_TxEn = McuGPIO_InitGPIO(&config);
|
||||
|
||||
McuUart485_GPIO_RxEnable();
|
||||
}
|
||||
#endif /* McuUart485_CONFIG_USE_HW_OE_RTS */
|
||||
/* -------------------------------------------------------------------------------------- */
|
||||
static QueueHandle_t RS485UartRxQueue; /* queue of the received bytes */
|
||||
#if !McuUart485_CONFIG_USE_MODBUS /* shell response queue only used in non-Modbus mode */
|
||||
static QueueHandle_t RS485UartResponseQueue; /* queue for the OK or NOK response */
|
||||
#endif
|
||||
#if McuUart485_CONFIG_USE_LOGGER
|
||||
static bool McuUart485_doLogging = false; /* if logging is turned on or off */
|
||||
#endif
|
||||
|
||||
void McuUart485_ClearRxQueue(void) {
|
||||
xQueueReset(RS485UartRxQueue);
|
||||
}
|
||||
|
||||
#if !McuUart485_CONFIG_USE_MODBUS
|
||||
void McuUart485_ClearResponseQueue(void) {
|
||||
xQueueReset(RS485UartResponseQueue);
|
||||
}
|
||||
#endif
|
||||
|
||||
uint8_t McuUart485_GetRxQueueByte(unsigned char *data, TickType_t ticksToWait) {
|
||||
if (xQueueReceive(RS485UartRxQueue, data, ticksToWait)==pdPASS ) {
|
||||
return ERR_OK;
|
||||
} else {
|
||||
return ERR_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t McuUart485_GetRxQueueChar(void) {
|
||||
uint8_t ch;
|
||||
|
||||
if (xQueueReceive(RS485UartRxQueue, &ch, 0)==pdPASS ) {
|
||||
/* return received character */
|
||||
} else {
|
||||
ch = '\0'; /* nothing received */
|
||||
}
|
||||
return ch;
|
||||
}
|
||||
|
||||
#if !McuUart485_CONFIG_USE_MODBUS
|
||||
uint8_t McuUart485_GetResponseQueueChar(void) {
|
||||
uint8_t ch;
|
||||
|
||||
if (xQueueReceive(RS485UartResponseQueue, &ch, 0)==pdPASS ) {
|
||||
/* return received character */
|
||||
} else {
|
||||
ch = '\0'; /* nothing received */
|
||||
}
|
||||
return ch;
|
||||
}
|
||||
#endif
|
||||
/* -------------------------------------------------------------------------------------- */
|
||||
|
||||
#if McuLib_CONFIG_CPU_IS_ESP32
|
||||
|
||||
#define RS485_ESP_BUF_SIZE (4*1024) /* buffer for the UART task. The UART driver uses twice of this */
|
||||
|
||||
#if 0 /* not used */
|
||||
void RS485_SendStr(char *str) {
|
||||
size_t len = strlen(str);
|
||||
|
||||
uart_write_bytes(McuUart485_CONFIG_UART_DEVICE, str, len);
|
||||
}
|
||||
|
||||
void RS485_SendChar(char ch) {
|
||||
uart_write_bytes(McuUart485_CONFIG_UART_DEVICE, &ch, 1);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* On the ESP32 we are using a task. On other architectures this would be handled by an interrupt */
|
||||
static void rs485uart_task(void *arg) {
|
||||
static unsigned char data[RS485_ESP_BUF_SIZE]; /* Rx buffer for UART */
|
||||
unsigned char prevChar = '\n';
|
||||
bool responseLine = false;
|
||||
BaseType_t res;
|
||||
|
||||
McuLog_trace("UART start receive loop.\r\n");
|
||||
for(;;) {
|
||||
/* Read data from UART */
|
||||
int len = uart_read_bytes(McuUart485_CONFIG_UART_DEVICE, data, sizeof(data)-1, pdMS_TO_TICKS(100));
|
||||
#if 0 /* for debugging only */
|
||||
if (len>0) {
|
||||
data[len] = '\0';
|
||||
McuLog_trace("rx: %d", len);
|
||||
}
|
||||
#endif
|
||||
/* send to Rx Queue */
|
||||
for(int i=0; i<len; i++) { /* handle received bytes */
|
||||
if (prevChar=='\n' && data[i]=='@') { /* do we have potentially a response for us on the bus? */
|
||||
responseLine = true;
|
||||
}
|
||||
if (responseLine) {
|
||||
res = xQueueSend(RS485UartResponseQueue, &data[i], pdMS_TO_TICKS(10));
|
||||
if (res!=pdPASS) {
|
||||
McuLog_error("failed sending data to response queue");
|
||||
}
|
||||
}
|
||||
prevChar = data[i];
|
||||
if (responseLine && data[i]=='\n') { /* end of line while on response line */
|
||||
responseLine = false;
|
||||
}
|
||||
res = xQueueSend(RS485UartRxQueue, &data[i], pdMS_TO_TICKS(20));
|
||||
if (res!=pdPASS) {
|
||||
McuLog_error("failed sending data to rx queue");
|
||||
}
|
||||
}
|
||||
} /* for */
|
||||
}
|
||||
|
||||
#endif /* McuLib_CONFIG_CPU_IS_ESP32 */
|
||||
|
||||
/*********************************************************************************************************/
|
||||
/* Shell interface */
|
||||
/*********************************************************************************************************/
|
||||
void McuUart485_SendBlock(unsigned char *data, size_t dataSize) {
|
||||
#if McuLib_CONFIG_CPU_IS_ESP32
|
||||
uart_write_bytes(McuUart485_CONFIG_UART_DEVICE, data, dataSize);
|
||||
#else
|
||||
#if !McuUart485_CONFIG_USE_HW_OE_RTS
|
||||
McuUart485_GPIO_TxEnable();
|
||||
#endif
|
||||
McuUart485_CONFIG_UART_WRITE_BLOCKING(McuUart485_CONFIG_UART_DEVICE, data, dataSize);
|
||||
#if !McuUart485_CONFIG_USE_HW_OE_RTS
|
||||
#if McuLib_CONFIG_CPU_IS_RPxxxx
|
||||
uart_tx_wait_blocking(McuUart485_CONFIG_UART_DEVICE); /* wait until all bytes are sent */
|
||||
#endif
|
||||
McuUart485_GPIO_RxEnable();
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
void McuUart485_SendString(unsigned char *str) {
|
||||
McuUart485_SendBlock(str, strlen((char*)str));
|
||||
}
|
||||
|
||||
static void McuUart485_SendChar(unsigned char ch) {
|
||||
static unsigned char McuUart485_SendCharbuf[McuShell_DEFAULT_SHELL_BUFFER_SIZE] = ""; /* only sending after a '\n', to send things as a block for faster transmission */
|
||||
static size_t index = 0;
|
||||
|
||||
McuUart485_SendCharbuf[index++] = ch;
|
||||
if (ch=='\n' || index==sizeof(McuUart485_SendCharbuf)-1) {
|
||||
McuUart485_SendCharbuf[index] = '\0'; /* terminate buffer */
|
||||
McuUart485_SendString(McuUart485_SendCharbuf);
|
||||
McuUart485_SendCharbuf[0] = '\0';
|
||||
index = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void McuUart485_ReadChar(uint8_t *c) {
|
||||
uint8_t ch;
|
||||
|
||||
if (xQueueReceive(RS485UartRxQueue, &ch, 0)==pdPASS ) {
|
||||
*c = ch; /* return received character */
|
||||
} else {
|
||||
*c = '\0'; /* nothing received */
|
||||
}
|
||||
}
|
||||
|
||||
static bool McuUart485_CharPresent(void) {
|
||||
return uxQueueMessagesWaiting(RS485UartRxQueue)!=0;
|
||||
}
|
||||
|
||||
McuShell_ConstStdIOType McuUart485_stdio = {
|
||||
.stdIn = (McuShell_StdIO_In_FctType)McuUart485_ReadChar,
|
||||
.stdOut = (McuShell_StdIO_OutErr_FctType)McuUart485_SendChar,
|
||||
.stdErr = (McuShell_StdIO_OutErr_FctType)McuUart485_SendChar,
|
||||
.keyPressed = McuUart485_CharPresent, /* if input is not empty */
|
||||
#if McuShell_CONFIG_ECHO_ENABLED
|
||||
.echoEnabled = false,
|
||||
#endif
|
||||
};
|
||||
|
||||
uint8_t McuUart485_DefaultShellBuffer[McuShell_DEFAULT_SHELL_BUFFER_SIZE]; /* default buffer which can be used by the application */
|
||||
/*********************************************************************************************************/
|
||||
#if McuLib_CONFIG_CPU_IS_KINETIS || McuLib_CONFIG_CPU_IS_LPC || McuLib_CONFIG_CPU_IS_RPxxxx
|
||||
void McuUart485_CONFIG_UART_IRQ_HANDLER(void) {
|
||||
uint8_t data;
|
||||
#if McuLib_CONFIG_CPU_IS_KINETIS || McuLib_CONFIG_CPU_IS_LPC /* no flags for RPxxxx */
|
||||
uint32_t flags;
|
||||
#endif
|
||||
BaseType_t xHigherPriorityTaskWoken1 = false, xHigherPriorityTaskWoken2 = false;
|
||||
#if !McuUart485_CONFIG_USE_MODBUS
|
||||
static unsigned char prevChar = '\n';
|
||||
static bool responseLine = false;
|
||||
#endif
|
||||
uint8_t count;
|
||||
|
||||
#if McuLib_CONFIG_CPU_IS_KINETIS || McuLib_CONFIG_CPU_IS_LPC /* no flags for RPxxxx */
|
||||
flags = McuUart485_CONFIG_UART_GET_FLAGS(McuUart485_CONFIG_UART_DEVICE);
|
||||
#endif
|
||||
#if McuUart485_CONFIG_HAS_FIFO
|
||||
if (flags&kUART_RxFifoOverflowFlag) {
|
||||
count = 0; /* statement to allow debugger to set a breakpoint here */
|
||||
}
|
||||
#endif
|
||||
/* new data arrived. */
|
||||
#if McuLib_CONFIG_CPU_IS_KINETIS || McuLib_CONFIG_CPU_IS_LPC /* no flags for RPxxxx */
|
||||
if (flags&McuUart485_CONFIG_UART_HW_RX_READY_FLAGS) {
|
||||
#elif McuLib_CONFIG_CPU_IS_RPxxxx
|
||||
while (uart_is_readable(McuUart485_CONFIG_UART_DEVICE)) { /* check if we have data available */
|
||||
#endif
|
||||
|
||||
#if McuUart485_CONFIG_HAS_FIFO
|
||||
count = McuUart485_CONFIG_UART_DEVICE->RCFIFO;
|
||||
#else
|
||||
count = 1;
|
||||
#endif
|
||||
while(count!=0) {
|
||||
data = McuUart485_CONFIG_UART_READ_BYTE(McuUart485_CONFIG_UART_DEVICE);
|
||||
#if !McuUart485_CONFIG_USE_MODBUS
|
||||
if (data!=0) { /* data==0 could happen especially after power-up, ignore it if we are in shell/non-Modbus mode */
|
||||
#endif
|
||||
#if !McuUart485_CONFIG_USE_MODBUS
|
||||
/* only store into RS485UartResponseQueue if we have a line starting with '@' */
|
||||
if (prevChar=='\n' && data=='@') {
|
||||
responseLine = true;
|
||||
}
|
||||
if (responseLine) {
|
||||
(void)xQueueSendFromISR(RS485UartResponseQueue, &data, &xHigherPriorityTaskWoken1);
|
||||
}
|
||||
prevChar = data;
|
||||
if (responseLine && data=='\n') { /* end of line while on response line */
|
||||
responseLine = false;
|
||||
}
|
||||
#endif
|
||||
(void)xQueueSendFromISR(RS485UartRxQueue, &data, &xHigherPriorityTaskWoken2);
|
||||
#if McuUart485_CONFIG_USE_LOGGER
|
||||
if (McuUart485_doLogging) {
|
||||
extern uint8_t McuRTT_SendChar(uint8_t ch);
|
||||
unsigned char buf[3];
|
||||
buf[0] = '\0';
|
||||
McuUtility_strcatNum8Hex(buf, sizeof(buf), data);
|
||||
(void)McuUart485_CONFIG_LOGGER_CALLBACK_NAME(buf[0]);
|
||||
(void)McuUart485_CONFIG_LOGGER_CALLBACK_NAME(buf[1]);
|
||||
if (isprint(data)) {
|
||||
(void)McuUart485_CONFIG_LOGGER_CALLBACK_NAME((unsigned char)' ');
|
||||
(void)McuUart485_CONFIG_LOGGER_CALLBACK_NAME(data);
|
||||
}
|
||||
(void)McuUart485_CONFIG_LOGGER_CALLBACK_NAME((unsigned char)'\n');
|
||||
}
|
||||
#endif
|
||||
#if !McuUart485_CONFIG_USE_MODBUS
|
||||
} /* if data != 0 */
|
||||
#endif
|
||||
count--;
|
||||
} /* while count != 0 */
|
||||
}
|
||||
#if McuLib_CONFIG_CPU_IS_KINETIS
|
||||
flags |= kUART_RxOverrunFlag|kUART_RxFifoOverflowFlag; /* always clear these flags, as they might been set? Not clearing them will not generate future interrupts */
|
||||
#endif
|
||||
#if McuLib_CONFIG_CPU_IS_KINETIS || McuLib_CONFIG_CPU_IS_LPC /* no clearing needed for RPxxxx */
|
||||
McuUart485_CONFIG_CLEAR_STATUS_FLAGS(McuUart485_CONFIG_UART_DEVICE, flags);
|
||||
#endif
|
||||
if (xHigherPriorityTaskWoken1 != pdFALSE || xHigherPriorityTaskWoken2 != pdFALSE) {
|
||||
vPortYieldFromISR();
|
||||
}
|
||||
#if McuLib_CONFIG_CORTEX_M==4
|
||||
__DSB(); /* ARM Cortex-M4 errata Notice 838869: dsb required because "Store immediate overlapping exception return operation might vector to incorrect interrupt" */
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
static void InitUart(void) {
|
||||
#if !McuUart485_CONFIG_USE_HW_OE_RTS
|
||||
McuUart485_GPIO_Init();
|
||||
#endif
|
||||
#if McuLib_CONFIG_CPU_IS_KINETIS || McuLib_CONFIG_CPU_IS_LPC
|
||||
/* NOTE: Muxing of the UART pins needs to be done in the Pins tool! */
|
||||
McuUart485_CONFIG_UART_CONFIG_STRUCT config;
|
||||
status_t res;
|
||||
|
||||
McuUart485_CONFIG_UART_SET_UART_CLOCK();
|
||||
McuUart485_CONFIG_UART_GET_DEFAULT_CONFIG(&config);
|
||||
config.baudRate_Bps = McuUart485_CONFIG_UART_BAUDRATE;
|
||||
config.parityMode = McuUart485_CONFIG_UART_PARITY;
|
||||
config.enableRx = true;
|
||||
config.enableTx = true;
|
||||
#if McuLib_CONFIG_CPU_IS_KINETIS
|
||||
config.enableRxRTS = true; /* using RTS pin to control the transceiver */
|
||||
config.enableTxCTS = false;
|
||||
#endif
|
||||
/* Initialize the USART with configuration. */
|
||||
res = McuUart485_CONFIG_UART_INIT(McuUart485_CONFIG_UART_DEVICE, &config, CLOCK_GetFreq(McuUart485_CONFIG_UART_GET_CLOCK_FREQ_SELECT));
|
||||
if (res!=kStatus_Success) {
|
||||
McuLog_fatal("failed initializing UART");
|
||||
for(;;) {}
|
||||
}
|
||||
#if McuUart485_CONFIG_USE_HW_OE_RTS
|
||||
#if McuLib_CONFIG_CPU_IS_KINETIS /* Kinetis K22FN512 */
|
||||
McuUart485_CONFIG_UART_DEVICE->MODEM |= UART_MODEM_TXRTSPOL(1); /* TXRTSPOL: 1: transmitter RTS polarity is active high */
|
||||
McuUart485_CONFIG_UART_DEVICE->MODEM |= UART_MODEM_TXRTSE(1); /* TXRTSE: Transmitter request-to-send enable, 1: RTS asserted before start bit is transmitted and deasserted after stop bit */
|
||||
#elif McuLib_CONFIG_CPU_IS_LPC /* LPC845 or LPC55S69 */
|
||||
McuUart485_CONFIG_UART_DEVICE->CFG |= USART_CFG_OESEL(1); /* if enabled, use RTS signal for RS-485 transceiver */
|
||||
McuUart485_CONFIG_UART_DEVICE->CFG |= USART_CFG_OEPOL(1); /* 1: the output enable signal is high active */
|
||||
McuUart485_CONFIG_UART_DEVICE->CFG |= USART_CFG_OETA(1); /* output enable turnaround time: if set, the output enable signal remains asserted for 1 char time after the end of the last bit */
|
||||
#endif
|
||||
#endif
|
||||
#if McuUart485_CONFIG_HAS_FIFO
|
||||
UART_EnableRxFIFO(McuUart485_CONFIG_UART_DEVICE, true); /* enable UART Rx FIFO */
|
||||
#endif
|
||||
McuUart485_CONFIG_UART_ENABLE_INTERRUPTS(McuUart485_CONFIG_UART_DEVICE,
|
||||
McuUart485_CONFIG_UART_ENABLE_INTERRUPT_FLAGS
|
||||
);
|
||||
NVIC_SetPriority(McuUart485_CONFIG_UART_IRQ_NUMBER, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY); /* required as we are using FreeRTOS API calls */
|
||||
EnableIRQ(McuUart485_CONFIG_UART_IRQ_NUMBER);
|
||||
#elif McuLib_CONFIG_CPU_IS_ESP32
|
||||
// Timeout threshold for UART = number of symbols (~10 tics) with unchanged state on receive pin
|
||||
#define UART_CONFIG_READ_TOUT (3) // 3.5T * 8 = 28 ticks, TOUT=3 -> ~24..33 ticks
|
||||
|
||||
uart_config_t uart_config = {
|
||||
.baud_rate = McuUart485_CONFIG_UART_BAUDRATE,
|
||||
.data_bits = UART_DATA_8_BITS,
|
||||
.parity = UART_PARITY_DISABLE,
|
||||
.stop_bits = UART_STOP_BITS_1,
|
||||
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE, /* UART_HW_FLOWCTRL_CTS */ /*UART_HW_FLOWCTRL_RTS,*/ /* UART_HW_FLOWCTRL_CTS_RTS, */
|
||||
.rx_flow_ctrl_thresh = 122,
|
||||
.source_clk = UART_SCLK_APB,
|
||||
};
|
||||
|
||||
McuLog_trace("UART set pins, mode and install driver.");
|
||||
|
||||
/* Install UART driver (we don't need an event queue here) */
|
||||
ESP_ERROR_CHECK(uart_driver_install(
|
||||
McuUart485_CONFIG_UART_DEVICE, /* usart device */
|
||||
RS485_ESP_BUF_SIZE*2, /* RX Buffer */
|
||||
RS485_ESP_BUF_SIZE*2, /* TX Buffer */
|
||||
0, /* event queue size */
|
||||
NULL, /* event queue handle */
|
||||
0 /* interrupt alloc flags */
|
||||
)
|
||||
);
|
||||
|
||||
/* Configure UART parameters */
|
||||
ESP_ERROR_CHECK(uart_param_config(McuUart485_CONFIG_UART_DEVICE, &uart_config));
|
||||
|
||||
/* RE (Receiver Enable, IO23) shall be HIGH during Tx, RE (Low Active, IO26) shall be LOW during Tx */
|
||||
ESP_ERROR_CHECK(uart_set_pin(McuUart485_CONFIG_UART_DEVICE,
|
||||
McuUart485_CONFIG_TXD_PIN, /* TX pin */
|
||||
McuUart485_CONFIG_RXD_PIN, /* RX pin */
|
||||
McuUart485_CONFIG_RTS_PIN, /* RTS pin */
|
||||
UART_PIN_NO_CHANGE /* CTS pin */
|
||||
));
|
||||
|
||||
/* Set RS485 half duplex mode */
|
||||
ESP_ERROR_CHECK(uart_set_mode(McuUart485_CONFIG_UART_DEVICE, UART_MODE_RS485_HALF_DUPLEX));
|
||||
|
||||
// Set read timeout of UART TOUT feature
|
||||
ESP_ERROR_CHECK(uart_set_rx_timeout(McuUart485_CONFIG_UART_DEVICE, UART_CONFIG_READ_TOUT));
|
||||
#elif McuLib_CONFIG_CPU_IS_RPxxxx
|
||||
uart_init(McuUart485_CONFIG_UART_DEVICE, McuUart485_CONFIG_UART_BAUDRATE);
|
||||
gpio_set_function(McuUart485_CONFIG_TXD_PIN, GPIO_FUNC_UART);
|
||||
gpio_set_function(McuUart485_CONFIG_RXD_PIN, GPIO_FUNC_UART);
|
||||
uart_set_fifo_enabled(McuUart485_CONFIG_UART_DEVICE, false);
|
||||
uart_set_format(McuUart485_CONFIG_UART_DEVICE, 8, 1, McuUart485_CONFIG_UART_PARITY);
|
||||
uart_set_hw_flow(McuUart485_CONFIG_UART_DEVICE, false, false); /* disable flow control, cannot use CTS/RTS */
|
||||
uart_set_translate_crlf(McuUart485_CONFIG_UART_DEVICE, false); /* do not translate */
|
||||
/* setup interrupt */
|
||||
int UART_IRQ = McuUart485_CONFIG_UART_DEVICE == uart0 ? UART0_IRQ : UART1_IRQ; /* find out which UART is used */
|
||||
irq_set_exclusive_handler(UART_IRQ, McuUart485_CONFIG_UART_IRQ_HANDLER /* on_uart_rx*/); /* setup IRQ handler */
|
||||
irq_set_enabled(UART_IRQ, true); /* enable interrupt */
|
||||
irq_set_priority(UART_IRQ, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY); /* required as we are using FreeRTOS API calls */
|
||||
uart_set_irq_enables(McuUart485_CONFIG_UART_DEVICE, true, false); /* enable UART interrupt output, Rx only */
|
||||
#else
|
||||
#error "need to initialize UART!"
|
||||
#endif
|
||||
}
|
||||
|
||||
#if McuLib_CONFIG_CPU_IS_KINETIS || McuLib_CONFIG_CPU_IS_LPC
|
||||
static void DecodeUARTFlags(uint32_t flags, const McuShell_StdIOType *io) {
|
||||
#if McuLib_CONFIG_CPU_IS_KINETIS
|
||||
if (flags&kUART_TxDataRegEmptyFlag) {
|
||||
McuShell_SendStatusStr((unsigned char*)"", (unsigned char*)"kUART_TxDataRegEmptyFlag\r\n", io->stdOut);
|
||||
}
|
||||
if (flags&kUART_TransmissionCompleteFlag) {
|
||||
McuShell_SendStatusStr((unsigned char*)"", (unsigned char*)"kUART_TransmissionCompleteFlag\r\n", io->stdOut);
|
||||
}
|
||||
if (flags&kUART_RxDataRegFullFlag) {
|
||||
McuShell_SendStatusStr((unsigned char*)"", (unsigned char*)"kUART_RxDataRegFullFlag\r\n", io->stdOut);
|
||||
}
|
||||
if (flags&kUART_IdleLineFlag) {
|
||||
McuShell_SendStatusStr((unsigned char*)"", (unsigned char*)"kUART_IdleLineFlag\r\n", io->stdOut);
|
||||
}
|
||||
if (flags&kUART_RxOverrunFlag) {
|
||||
McuShell_SendStatusStr((unsigned char*)"", (unsigned char*)"kUART_RxOverrunFlag\r\n", io->stdOut);
|
||||
}
|
||||
if (flags&kUART_NoiseErrorFlag) {
|
||||
McuShell_SendStatusStr((unsigned char*)"", (unsigned char*)"kUART_NoiseErrorFlag\r\n", io->stdOut);
|
||||
}
|
||||
if (flags&kUART_FramingErrorFlag) {
|
||||
McuShell_SendStatusStr((unsigned char*)"", (unsigned char*)"kUART_FramingErrorFlag\r\n", io->stdOut);
|
||||
}
|
||||
if (flags&kUART_ParityErrorFlag) {
|
||||
McuShell_SendStatusStr((unsigned char*)"", (unsigned char*)"kUART_ParityErrorFlag\r\n", io->stdOut);
|
||||
}
|
||||
#if defined(FSL_FEATURE_UART_HAS_LIN_BREAK_DETECT) && FSL_FEATURE_UART_HAS_LIN_BREAK_DETECT
|
||||
if (flags&kUART_LinBreakFlag) {
|
||||
McuShell_SendStatusStr((unsigned char*)"", (unsigned char*)"kUART_LinBreakFlag\r\n", io->stdOut);
|
||||
}
|
||||
#endif
|
||||
if (flags&kUART_RxActiveEdgeFlag) {
|
||||
McuShell_SendStatusStr((unsigned char*)"", (unsigned char*)"kUART_RxActiveEdgeFlag\r\n", io->stdOut);
|
||||
}
|
||||
if (flags&kUART_RxActiveFlag) {
|
||||
McuShell_SendStatusStr((unsigned char*)"", (unsigned char*)"kUART_RxActiveFlag\r\n", io->stdOut);
|
||||
}
|
||||
#if defined(FSL_FEATURE_UART_HAS_EXTENDED_DATA_REGISTER_FLAGS) && FSL_FEATURE_UART_HAS_EXTENDED_DATA_REGISTER_FLAGS
|
||||
if (flags&kUART_NoiseErrorInRxDataRegFlag) {
|
||||
McuShell_SendStatusStr((unsigned char*)"", (unsigned char*)"kUART_NoiseErrorInRxDataRegFlag\r\n", io->stdOut);
|
||||
}
|
||||
if (flags&kUART_ParityErrorInRxDataRegFlag) {
|
||||
McuShell_SendStatusStr((unsigned char*)"", (unsigned char*)"kUART_ParityErrorInRxDataRegFlag\r\n", io->stdOut);
|
||||
}
|
||||
#endif
|
||||
#if defined(FSL_FEATURE_UART_HAS_FIFO) && FSL_FEATURE_UART_HAS_FIFO
|
||||
if (flags&kUART_TxFifoEmptyFlag) {
|
||||
McuShell_SendStatusStr((unsigned char*)"", (unsigned char*)"kUART_TxFifoEmptyFlag\r\n", io->stdOut);
|
||||
}
|
||||
if (flags&kUART_RxFifoEmptyFlag) {
|
||||
McuShell_SendStatusStr((unsigned char*)"", (unsigned char*)"kUART_RxFifoEmptyFlag\r\n", io->stdOut);
|
||||
}
|
||||
if (flags&kUART_TxFifoOverflowFlag) {
|
||||
McuShell_SendStatusStr((unsigned char*)"", (unsigned char*)"kUART_TxFifoOverflowFlag\r\n", io->stdOut);
|
||||
}
|
||||
if (flags&kUART_RxFifoOverflowFlag) {
|
||||
McuShell_SendStatusStr((unsigned char*)"", (unsigned char*)"kUART_RxFifoOverflowFlag\r\n", io->stdOut);
|
||||
}
|
||||
if (flags&kUART_RxFifoOverflowFlag) {
|
||||
McuShell_SendStatusStr((unsigned char*)"", (unsigned char*)"kUART_RxFifoOverflowFlag\r\n", io->stdOut);
|
||||
}
|
||||
#endif
|
||||
#elif McuLib_CONFIG_CPU_IS_LPC && McuLib_CONFIG_CPU_VARIANT==McuLib_CONFIG_CPU_VARIANT_NXP_LPC845
|
||||
if (flags&kUSART_RxReady) {
|
||||
McuShell_SendStatusStr((unsigned char*)"", (unsigned char*)"kUSART_RxReady\r\n", io->stdOut);
|
||||
}
|
||||
if (flags&kUSART_RxIdleFlag) {
|
||||
McuShell_SendStatusStr((unsigned char*)"", (unsigned char*)"kUSART_RxIdleFlag\r\n", io->stdOut);
|
||||
}
|
||||
if (flags&kUSART_TxReady) {
|
||||
McuShell_SendStatusStr((unsigned char*)"", (unsigned char*)"kUSART_TxReady\r\n", io->stdOut);
|
||||
}
|
||||
if (flags&kUSART_TxIdleFlag) {
|
||||
McuShell_SendStatusStr((unsigned char*)"", (unsigned char*)"kUSART_TxIdleFlag\r\n", io->stdOut);
|
||||
}
|
||||
if (flags&kUSART_CtsState) {
|
||||
McuShell_SendStatusStr((unsigned char*)"", (unsigned char*)"kUSART_CtsState\r\n", io->stdOut);
|
||||
}
|
||||
if (flags&kUSART_DeltaCtsFlag) {
|
||||
McuShell_SendStatusStr((unsigned char*)"", (unsigned char*)"kUSART_DeltaCtsFlag\r\n", io->stdOut);
|
||||
}
|
||||
if (flags&kUSART_TxDisableFlag) {
|
||||
McuShell_SendStatusStr((unsigned char*)"", (unsigned char*)"kUSART_TxDisableFlag\r\n", io->stdOut);
|
||||
}
|
||||
if (flags&kUSART_HardwareOverrunFlag) {
|
||||
McuShell_SendStatusStr((unsigned char*)"", (unsigned char*)"kUSART_HardwareOverrunFlag\r\n", io->stdOut);
|
||||
}
|
||||
if (flags&kUSART_RxBreakFlag) {
|
||||
McuShell_SendStatusStr((unsigned char*)"", (unsigned char*)"kUSART_RxBreakFlag\r\n", io->stdOut);
|
||||
}
|
||||
if (flags&kUSART_RxStartFlag) {
|
||||
McuShell_SendStatusStr((unsigned char*)"", (unsigned char*)"kUSART_RxStartFlag\r\n", io->stdOut);
|
||||
}
|
||||
if (flags&kUSART_FramErrorFlag) {
|
||||
McuShell_SendStatusStr((unsigned char*)"", (unsigned char*)"kUSART_FramErrorFlag\r\n", io->stdOut);
|
||||
}
|
||||
if (flags&kUSART_ParityErrorFlag) {
|
||||
McuShell_SendStatusStr((unsigned char*)"", (unsigned char*)"kUSART_ParityErrorFlag\r\n", io->stdOut);
|
||||
}
|
||||
if (flags&kUSART_RxNoiseFlag) {
|
||||
McuShell_SendStatusStr((unsigned char*)"", (unsigned char*)"kUSART_RxNoiseFlag\r\n", io->stdOut);
|
||||
}
|
||||
#if defined(FSL_FEATURE_USART_HAS_ABERR_CHECK) && FSL_FEATURE_USART_HAS_ABERR_CHECK
|
||||
if (flags&kUSART_AutoBaudErrorFlag) {
|
||||
McuShell_SendStatusStr((unsigned char*)"", (unsigned char*)"kUSART_AutoBaudErrorFlag\r\n", io->stdOut);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
static uint8_t PrintStatus(const McuShell_StdIOType *io) {
|
||||
uint8_t buf[96];
|
||||
|
||||
McuShell_SendStatusStr((unsigned char*)"McuUart485", (unsigned char*)"RS-485 UART settings\r\n", io->stdOut);
|
||||
#if McuUart485_CONFIG_USE_LOGGER
|
||||
McuShell_SendStatusStr((unsigned char*)" logging", McuUart485_doLogging?(unsigned char*)"on\r\n":(unsigned char*)"off\r\n", io->stdOut);
|
||||
#endif
|
||||
McuShell_SendStatusStr((unsigned char*)" HW TxEn", McuUart485_CONFIG_USE_HW_OE_RTS?(unsigned char*)"yes\r\n":(unsigned char*)"no\r\n", io->stdOut);
|
||||
#if McuLib_CONFIG_CPU_IS_KINETIS || McuLib_CONFIG_CPU_IS_LPC
|
||||
uint32_t flags;
|
||||
|
||||
#if !McuUart485_CONFIG_USE_HW_OE_RTS
|
||||
McuGPIO_GetPinStatusString(RS485_TxEn, buf, sizeof(buf));
|
||||
McuUtility_strcat(buf, sizeof(buf), (unsigned char*)"\r\n");
|
||||
McuShell_SendStatusStr((unsigned char*)" TxEn", buf, io->stdOut);
|
||||
#endif
|
||||
flags = McuUart485_CONFIG_UART_GET_FLAGS(McuUart485_CONFIG_UART_DEVICE);
|
||||
McuUtility_strcpy(buf, sizeof(buf), (unsigned char*)"0x");
|
||||
McuUtility_strcatNum32Hex(buf, sizeof(buf), flags);
|
||||
McuUtility_strcat(buf, sizeof(buf), (unsigned char*)"\r\n");
|
||||
McuShell_SendStatusStr((unsigned char*)" flags", buf, io->stdOut);
|
||||
DecodeUARTFlags(flags, io) ;
|
||||
#endif
|
||||
|
||||
McuUtility_Num32uToStr(buf, sizeof(buf), McuUart485_CONFIG_UART_BAUDRATE);
|
||||
McuUtility_strcat(buf, sizeof(buf), (unsigned char*)"\r\n");
|
||||
McuShell_SendStatusStr((unsigned char*)" baud", buf, io->stdOut);
|
||||
|
||||
#if McuLib_CONFIG_CPU_IS_ESP32
|
||||
McuUtility_strcpy(buf, sizeof(buf), (unsigned char*)"buffer: ");
|
||||
McuUtility_strcatNum32u(buf, sizeof(buf), RS485_ESP_BUF_SIZE);
|
||||
McuUtility_strcat(buf, sizeof(buf), (unsigned char*)" bytes\r\n");
|
||||
McuShell_SendStatusStr((unsigned char*)" uart", buf, io->stdOut);
|
||||
#endif
|
||||
|
||||
McuUtility_strcpy(buf, sizeof(buf), (unsigned char*)"Rx: ");
|
||||
McuUtility_strcatNum32u(buf, sizeof(buf), McuUart485_CONFIG_UART_RX_QUEUE_LENGTH);
|
||||
McuUtility_strcat(buf, sizeof(buf), (unsigned char*)", Response: ");
|
||||
McuUtility_strcatNum32u(buf, sizeof(buf), McuUart485_CONFIG_UART_RESPONSE_QUEUE_LENGTH);
|
||||
McuUtility_strcat(buf, sizeof(buf), (unsigned char*)"\r\n");
|
||||
McuShell_SendStatusStr((unsigned char*)" queues", buf, io->stdOut);
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
static uint8_t PrintHelp(const McuShell_StdIOType *io) {
|
||||
McuShell_SendHelpStr((unsigned char*)"McuUart485", (unsigned char*)"Group of RS-485 commands\r\n", io->stdOut);
|
||||
McuShell_SendHelpStr((unsigned char*)" help|status", (unsigned char*)"Print help or status information\r\n", io->stdOut);
|
||||
#if McuLib_CONFIG_CPU_IS_KINETIS || McuLib_CONFIG_CPU_IS_LPC
|
||||
McuShell_SendHelpStr((unsigned char*)" clear <flags>", (unsigned char*)"Clear UART ISR flags\r\n", io->stdOut);
|
||||
#endif
|
||||
McuShell_SendHelpStr((unsigned char*)" log on|off", (unsigned char*)"Turn logging on or off\r\n", io->stdOut);
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
uint8_t McuUart485_ParseCommand(const unsigned char *cmd, bool *handled, const McuShell_StdIOType *io) {
|
||||
if (McuUtility_strcmp((char*)cmd, McuShell_CMD_HELP)==0 || McuUtility_strcmp((char*)cmd, "McuUart485 help")==0) {
|
||||
*handled = true;
|
||||
return PrintHelp(io);
|
||||
} else if ((McuUtility_strcmp((char*)cmd, McuShell_CMD_STATUS)==0) || (McuUtility_strcmp((char*)cmd, "McuUart485 status")==0)) {
|
||||
*handled = true;
|
||||
return PrintStatus(io);
|
||||
#if McuLib_CONFIG_CPU_IS_KINETIS || McuLib_CONFIG_CPU_IS_LPC
|
||||
} else if (McuUtility_strncmp((char*)cmd, "McuUart485 clear ", sizeof("McuUart485 clear ")-1)==0) {
|
||||
int32_t flags;
|
||||
#if McuLib_CONFIG_CPU_IS_KINETIS
|
||||
status_t status;
|
||||
#endif
|
||||
const unsigned char *p;
|
||||
|
||||
*handled = true;
|
||||
p = cmd + sizeof("McuUart485 clear ")-1;
|
||||
if (McuUtility_xatoi(&p, &flags)==ERR_OK) {
|
||||
#if McuLib_CONFIG_CPU_IS_KINETIS
|
||||
status = McuUart485_CONFIG_CLEAR_STATUS_FLAGS(McuUart485_CONFIG_UART_DEVICE, flags);
|
||||
McuShell_SendStr((unsigned char*)"status: ", io->stdOut);
|
||||
McuShell_SendNum32u(status, io->stdOut);
|
||||
McuShell_SendStr((unsigned char*)"\r\n", io->stdOut);
|
||||
#elif McuLib_CONFIG_CPU_IS_LPC
|
||||
McuUart485_CONFIG_CLEAR_STATUS_FLAGS(McuUart485_CONFIG_UART_DEVICE, flags);
|
||||
#endif
|
||||
return ERR_OK;
|
||||
}
|
||||
return ERR_FAILED;
|
||||
#endif
|
||||
#if McuUart485_CONFIG_USE_LOGGER
|
||||
} else if (McuUtility_strcmp((char*)cmd, "McuUart485 log on")==0) {
|
||||
*handled = TRUE;
|
||||
McuUart485_doLogging = true;
|
||||
return ERR_OK;
|
||||
} else if (McuUtility_strcmp((char*)cmd, "McuUart485 log off")==0) {
|
||||
*handled = TRUE;
|
||||
McuUart485_doLogging = false;
|
||||
return ERR_OK;
|
||||
#endif
|
||||
}
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
void McuUart485_Deinit(void) {
|
||||
vQueueDelete(RS485UartRxQueue);
|
||||
RS485UartRxQueue = NULL;
|
||||
#if !McuUart485_CONFIG_USE_MODBUS
|
||||
vQueueDelete(RS485UartResponseQueue);
|
||||
RS485UartResponseQueue = NULL;
|
||||
#endif
|
||||
#if !McuUart485_CONFIG_USE_HW_OE_RTS
|
||||
McuUart485_GPIO_Deinit();
|
||||
#endif
|
||||
}
|
||||
|
||||
void McuUart485_Init(void) {
|
||||
InitUart();
|
||||
RS485UartRxQueue = xQueueCreate(McuUart485_CONFIG_UART_RX_QUEUE_LENGTH, sizeof(uint8_t));
|
||||
if (RS485UartRxQueue==NULL) {
|
||||
McuLog_fatal("failed creating RS-485 Rx queue");
|
||||
for(;;){} /* out of memory? */
|
||||
}
|
||||
vQueueAddToRegistry(RS485UartRxQueue, "RS485UartRxQueue");
|
||||
#if !McuUart485_CONFIG_USE_MODBUS
|
||||
RS485UartResponseQueue = xQueueCreate(McuUart485_CONFIG_UART_RESPONSE_QUEUE_LENGTH, sizeof(uint8_t));
|
||||
if (RS485UartResponseQueue==NULL) {
|
||||
McuLog_fatal("failed creating RS-485 response queue");
|
||||
for(;;){} /* out of memory? */
|
||||
}
|
||||
vQueueAddToRegistry(RS485UartResponseQueue, "RS485UartResponseQueue");
|
||||
#endif
|
||||
#if McuLib_CONFIG_CPU_IS_ESP32
|
||||
BaseType_t res;
|
||||
|
||||
res = xTaskCreate(rs485uart_task, "rs485uart", (4*1024)/sizeof(StackType_t), NULL, tskIDLE_PRIORITY+3, NULL);
|
||||
if (res==pdPASS) {
|
||||
McuLog_trace("created rs485-uart task");
|
||||
} else {
|
||||
McuLog_fatal("failed creating res485-uart task!");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif /* #ifdef McuUart485_CONFIG_UART_DEVICE */
|
||||
Reference in New Issue
Block a user