bugfix(uart): uniform AT_CMD char configuration

This commit is contained in:
chenjianqiang
2019-07-01 18:00:10 +08:00
parent 00b33a8e14
commit e43513b610
9 changed files with 311 additions and 265 deletions

View File

@@ -680,44 +680,46 @@ esp_err_t uart_disable_pattern_det_intr(uart_port_t uart_num);
* @brief UART enable pattern detect function.
* Designed for applications like 'AT commands'.
* When the hardware detect a series of one same character, the interrupt will be triggered.
* @note This function only works for esp32. And this function is deprecated, please use
* uart_enable_pattern_det_baud_intr instead.
*
* @param uart_num UART port number.
* @param pattern_chr character of the pattern
* @param pattern_chr character of the pattern.
* @param chr_num number of the character, 8bit value.
* @param chr_tout timeout of the interval between each pattern characters, 24bit value, unit is APB (80Mhz) clock cycle.
* When the duration is less than this value, it will not take this data as at_cmd char
* When the duration is less than this value, it will not take this data as at_cmd char.
* @param post_idle idle time after the last pattern character, 24bit value, unit is APB (80Mhz) clock cycle.
* When the duration is less than this value, it will not take the previous data as the last at_cmd char
* @param pre_idle idle time before the first pattern character, 24bit value, unit is APB (80Mhz) clock cycle.
* When the duration is less than this value, it will not take this data as the first at_cmd char
* When the duration is less than this value, it will not take this data as the first at_cmd char.
*
* @return
* - ESP_OK Success
* - ESP_FAIL Parameter error
*/
esp_err_t uart_enable_pattern_det_intr(uart_port_t uart_num, char pattern_chr, uint8_t chr_num, int chr_tout, int post_idle, int pre_idle);
#elif CONFIG_IDF_TARGET_ESP32S2BETA
esp_err_t uart_enable_pattern_det_intr(uart_port_t uart_num, char pattern_chr, uint8_t chr_num, int chr_tout, int post_idle, int pre_idle) __attribute__((deprecated));
#endif
/**
* @brief UART enable pattern detect function.
* Designed for applications like 'AT commands'.
* When the hardware detect a series of one same character, the interrupt will be triggered.
*
* @param uart_num UART port number.
* @param pattern_chr character of the pattern
* @param pattern_chr character of the pattern.
* @param chr_num number of the character, 8bit value.
* @param chr_tout timeout of the interval between each pattern characters, 16bit value, unit is baud rate.
* When the duration is more than this value, it will not take this data as at_cmd char
* @param post_idle idle time after the last pattern character, 16bit value, unit is baud rate.
* @param chr_tout timeout of the interval between each pattern characters, 16bit value, unit is the baud-rate cycle you configured.
* When the duration is more than this value, it will not take this data as at_cmd char.
* @param post_idle idle time after the last pattern character, 16bit value, unit is the baud-rate cycle you configured.
* When the duration is less than this value, it will not take the previous data as the last at_cmd char
* @param pre_idle idle time before the first pattern character, 16bit value, unit is baud rate.
* When the duration is less than this value, it will not take this data as the first at_cmd char
* @param pre_idle idle time before the first pattern character, 16bit value, unit is the baud-rate cycle you configured.
* When the duration is less than this value, it will not take this data as the first at_cmd char.
*
* @return
* - ESP_OK Success
* - ESP_FAIL Parameter error
*/
esp_err_t uart_enable_pattern_det_intr(uart_port_t uart_num, char pattern_chr, uint8_t chr_num, int chr_tout, int post_idle, int pre_idle);
#endif
esp_err_t uart_enable_pattern_det_baud_intr(uart_port_t uart_num, char pattern_chr, uint8_t chr_num, int chr_tout, int post_idle, int pre_idle);
/**
* @brief Return the nearest detected pattern position in buffer.

View File

@@ -36,8 +36,6 @@
#define UART_NUM SOC_UART_NUM
#define UART_NUM SOC_UART_NUM
#define XOFF (char)0x13
#define XON (char)0x11
@@ -161,7 +159,6 @@ esp_err_t uart_set_stop_bits(uart_port_t uart_num, uart_stop_bits_t stop_bit)
UART_CHECK((stop_bit < UART_STOP_BITS_MAX), "stop bit error", ESP_FAIL);
UART_ENTER_CRITICAL(&uart_spinlock[uart_num]);
#if UART_NUM > 2
//workaround for hardware bug, when uart stop bit set as 2-bit mode.
if (stop_bit == UART_STOP_BITS_2) {
stop_bit = UART_STOP_BITS_1;
@@ -169,7 +166,6 @@ esp_err_t uart_set_stop_bits(uart_port_t uart_num, uart_stop_bits_t stop_bit)
} else {
UART[uart_num]->rs485_conf.dl1_en = 0;
}
#endif
UART[uart_num]->conf0.stop_bit_num = stop_bit;
UART_EXIT_CRITICAL(&uart_spinlock[uart_num]);
return ESP_OK;
@@ -516,8 +512,10 @@ esp_err_t uart_pattern_queue_reset(uart_port_t uart_num, int queue_length)
return ESP_OK;
}
#if CONFIG_IDF_TARGET_ESP32
esp_err_t uart_enable_pattern_det_intr(uart_port_t uart_num, char pattern_chr, uint8_t chr_num, int chr_tout, int post_idle, int pre_idle)
{
//This function is deprecated, please use uart_enable_pattern_det_baud_intr instead.
UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_FAIL);
UART_CHECK(chr_tout >= 0 && chr_tout <= UART_RX_GAP_TOUT_V, "uart pattern set error\n", ESP_FAIL);
UART_CHECK(post_idle >= 0 && post_idle <= UART_POST_IDLE_NUM_V, "uart pattern set error\n", ESP_FAIL);
@@ -529,6 +527,37 @@ esp_err_t uart_enable_pattern_det_intr(uart_port_t uart_num, char pattern_chr, u
UART[uart_num]->at_cmd_precnt.pre_idle_num = pre_idle;
return uart_enable_intr_mask(uart_num, UART_AT_CMD_CHAR_DET_INT_ENA_M);
}
#endif
esp_err_t uart_enable_pattern_det_baud_intr(uart_port_t uart_num, char pattern_chr, uint8_t chr_num, int chr_tout, int post_idle, int pre_idle)
{
UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_FAIL);
UART_CHECK(chr_tout >= 0 && chr_tout <= UART_RX_GAP_TOUT_V, "uart pattern set error\n", ESP_FAIL);
UART_CHECK(post_idle >= 0 && post_idle <= UART_POST_IDLE_NUM_V, "uart pattern set error\n", ESP_FAIL);
UART_CHECK(pre_idle >= 0 && pre_idle <= UART_PRE_IDLE_NUM_V, "uart pattern set error\n", ESP_FAIL);
UART[uart_num]->at_cmd_char.data = pattern_chr;
UART[uart_num]->at_cmd_char.char_num = chr_num;
#if CONFIG_IDF_TARGET_ESP32
int apb_clk_freq = 0;
uint32_t uart_baud = 0;
uint32_t uart_div = 0;
uart_get_baudrate(uart_num, &uart_baud);
apb_clk_freq = esp_clk_apb_freq();
uart_div = apb_clk_freq / uart_baud;
UART[uart_num]->at_cmd_gaptout.rx_gap_tout = chr_tout * uart_div;
UART[uart_num]->at_cmd_postcnt.post_idle_num = post_idle * uart_div;
UART[uart_num]->at_cmd_precnt.pre_idle_num = pre_idle * uart_div;
#elif CONFIG_IDF_TARGET_ESP32S2BETA
UART[uart_num]->at_cmd_gaptout.rx_gap_tout = chr_tout;
UART[uart_num]->at_cmd_postcnt.post_idle_num = post_idle;
UART[uart_num]->at_cmd_precnt.pre_idle_num = pre_idle;
#endif
return uart_enable_intr_mask(uart_num, UART_AT_CMD_CHAR_DET_INT_ENA_M);
}
esp_err_t uart_disable_pattern_det_intr(uart_port_t uart_num)
{
@@ -590,7 +619,9 @@ esp_err_t uart_isr_free(uart_port_t uart_num)
{
esp_err_t ret;
UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_FAIL);
if (p_uart_obj[uart_num]->intr_handle==NULL) return ESP_ERR_INVALID_ARG;
if (p_uart_obj[uart_num]->intr_handle == NULL) {
return ESP_ERR_INVALID_ARG;
}
UART_ENTER_CRITICAL(&uart_spinlock[uart_num]);
ret = esp_intr_free(p_uart_obj[uart_num]->intr_handle);
p_uart_obj[uart_num]->intr_handle = NULL;
@@ -709,7 +740,9 @@ esp_err_t uart_param_config(uart_port_t uart_num, const uart_config_t *uart_conf
#endif
}
r = uart_set_hw_flow_ctrl(uart_num, uart_config->flow_ctrl, uart_config->rx_flow_ctrl_thresh);
if (r != ESP_OK) return r;
if (r != ESP_OK) {
return r;
}
UART[uart_num]->conf0.val =
(uart_config->parity << UART_PARITY_S)
@@ -718,9 +751,13 @@ esp_err_t uart_param_config(uart_port_t uart_num, const uart_config_t *uart_conf
| (uart_config->use_ref_tick ? 0 : UART_TICK_REF_ALWAYS_ON_M);
r = uart_set_baudrate(uart_num, uart_config->baud_rate);
if (r != ESP_OK) return r;
if (r != ESP_OK) {
return r;
}
r = uart_set_tx_idle_num(uart_num, UART_TX_IDLE_NUM_DEFAULT);
if (r != ESP_OK) return r;
if (r != ESP_OK) {
return r;
}
r = uart_set_stop_bits(uart_num, uart_config->stop_bits);
//A hardware reset does not reset the fifo,
//so we need to reset the fifo manually.
@@ -842,8 +879,7 @@ static void uart_rx_intr_handler_default(void *param)
en_tx_flg = true;
p_uart->tx_len_cur = size;
}
}
else {
} else {
//Can not get data from ring buffer, return;
break;
}
@@ -901,8 +937,7 @@ static void uart_rx_intr_handler_default(void *param)
uart_enable_intr_mask_from_isr(uart_num, UART_TXFIFO_EMPTY_INT_ENA_M);
}
}
}
else if ((uart_intr_status & UART_RXFIFO_TOUT_INT_ST_M)
} else if ((uart_intr_status & UART_RXFIFO_TOUT_INT_ST_M)
|| (uart_intr_status & UART_RXFIFO_FULL_INT_ST_M)
|| (uart_intr_status & UART_AT_CMD_CHAR_DET_INT_ST_M)
) {
@@ -1442,7 +1477,9 @@ esp_err_t uart_driver_install(uart_port_t uart_num, int rx_buffer_size, int tx_b
}
r = uart_isr_register(uart_num, uart_rx_intr_handler_default, p_uart_obj[uart_num], intr_alloc_flags, &p_uart_obj[uart_num]->intr_handle);
if (r!=ESP_OK) goto err;
if (r != ESP_OK) {
goto err;
}
uart_intr_config_t uart_intr = {
.intr_enable_mask = UART_RXFIFO_FULL_INT_ENA_M
| UART_RXFIFO_TOUT_INT_ENA_M
@@ -1455,7 +1492,9 @@ esp_err_t uart_driver_install(uart_port_t uart_num, int rx_buffer_size, int tx_b
.txfifo_empty_intr_thresh = UART_EMPTY_THRESH_DEFAULT
};
r = uart_intr_config(uart_num, &uart_intr);
if (r!=ESP_OK) goto err;
if (r != ESP_OK) {
goto err;
}
return r;
err:

View File

@@ -11,8 +11,9 @@
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef _SOC_UART_CAPS_H_
#define _SOC_UART_CAPS_H_
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
@@ -22,5 +23,3 @@ extern "C" {
#ifdef __cplusplus
}
#endif
#endif /* _SOC_UART_CAPS_H_ */

View File

@@ -27,11 +27,19 @@ static wl_handle_t test_wl_handle;
TEST_CASE("Can use access() for UART", "[vfs]")
{
const char *uarts[] = {"/dev/uart/0", "/dev/uart/1", "/dev/uart/2"};
const char *uarts[] = {
"/dev/uart/0",
"/dev/uart/1",
#if SOC_UART_NUM > 2
"/dev/uart/2"
#endif
};
uart_driver_install(UART_NUM_0, 256, 0, 0, NULL, 0);
uart_driver_install(UART_NUM_1, 256, 0, 0, NULL, 0);
#if SOC_UART_NUM > 2
uart_driver_install(UART_NUM_2, 256, 0, 0, NULL, 0);
#endif
for (int i = 0; i < sizeof(uarts)/sizeof(uarts[0]); ++i) {
TEST_ASSERT_EQUAL_MESSAGE(access(uarts[i], F_OK), 0, uarts[i]);
@@ -55,7 +63,9 @@ TEST_CASE("Can use access() for UART", "[vfs]")
uart_driver_delete(UART_NUM_0);
uart_driver_delete(UART_NUM_1);
#if SOC_UART_NUM > 2
uart_driver_delete(UART_NUM_2);
#endif
}
static inline void test_spi_flash_setup()

View File

@@ -169,7 +169,7 @@ The API provides a convenient way to handle specific interrupts discussed above
* **FIFO space threshold or transmission timeout reached** - the interrupts on TX or Rx FIFO buffer being filled with specific number of characters or on a timeout of sending or receiving data. To use these interrupts, first configure respective threshold values of the buffer length and the timeout by entering them in :cpp:type:`uart_intr_config_t` structure and calling :cpp:func:`uart_intr_config`. Then enable interrupts with functions :cpp:func:`uart_enable_rx_intr` and :cpp:func:`uart_enable_tx_intr`. To disable these interrupts there are corresponding functions :cpp:func:`uart_disable_rx_intr` or :cpp:func:`uart_disable_tx_intr`.
* **Pattern detection** - an interrupt triggered on detecting a 'pattern' of the same character being sent number of times. The functions that allow to configure, enable and disable this interrupt are :cpp:func:`uart_enable_pattern_det_intr` and cpp:func:`uart_disable_pattern_det_intr`.
* **Pattern detection** - an interrupt triggered on detecting a 'pattern' of the same character being sent number of times. The functions that allow to configure, enable and disable this interrupt are :cpp:func:`uart_enable_pattern_det_baud_intr` and cpp:func:`uart_disable_pattern_det_intr`.
Macros
^^^^^^

View File

@@ -699,7 +699,7 @@ nmea_parser_handle_t nmea_parser_init(const nmea_parser_config_t *config)
goto err_uart_install;
}
/* Set pattern interrupt, used to detect the end of a line */
uart_enable_pattern_det_intr(esp_gps->uart_port, '\n', 1, 10000, 10, 10);
uart_enable_pattern_det_baud_intr(esp_gps->uart_port, '\n', 1, 9, 0, 0);
/* Set pattern queue size */
uart_pattern_queue_reset(esp_gps->uart_port, config->uart.event_queue_size);
uart_flush(esp_gps->uart_port);

View File

@@ -47,7 +47,7 @@
#define PACKET_READ_TICS (100 / portTICK_RATE_MS)
#define ECHO_TASK_STACK_SIZE (2048)
#define ECHO_TASK_PRIO (10)
#define ECHO_UART_PORT (UART_NUM_2)
#define ECHO_UART_PORT (UART_NUM_MAX - 1)
static const char *TAG = "RS485_ECHO_APP";

View File

@@ -140,11 +140,7 @@ void app_main()
uart_driver_install(EX_UART_NUM, BUF_SIZE * 2, BUF_SIZE * 2, 20, &uart0_queue, 0);
//Set uart pattern detect function.
#if CONFIG_IDF_TARGET_ESP32
uart_enable_pattern_det_intr(EX_UART_NUM, '+', PATTERN_CHR_NUM, 10000, 10, 10);
#elif CONFIG_IDF_TARGET_ESP32S2BETA
uart_enable_pattern_det_intr(EX_UART_NUM, '+', PATTERN_CHR_NUM, 9, 0, 0);
#endif
uart_enable_pattern_det_baud_intr(EX_UART_NUM, '+', PATTERN_CHR_NUM, 9, 0, 0);
//Reset the pattern queue length to record at most 20 pattern positions.
uart_pattern_queue_reset(EX_UART_NUM, 20);

View File

@@ -28,9 +28,9 @@
#define ESP_MODEM_LINE_BUFFER_SIZE (CONFIG_EXAMPLE_UART_RX_BUFFER_SIZE / 2)
#define ESP_MODEM_EVENT_QUEUE_SIZE (16)
#define MIN_PATTERN_INTERVAL (10000)
#define MIN_POST_IDLE (10)
#define MIN_PRE_IDLE (10)
#define MIN_PATTERN_INTERVAL (9)
#define MIN_POST_IDLE (0)
#define MIN_PRE_IDLE (0)
/**
* @brief Macro defined for error checking
@@ -264,12 +264,12 @@ static esp_err_t esp_modem_dte_send_wait(modem_dte_t *dte, const char *data, uin
MODEM_CHECK(res >= len, "wait prompt [%s] timeout", err, prompt);
MODEM_CHECK(!strncmp(prompt, (const char *)buffer, len), "get wrong prompt: %s", err, buffer);
free(buffer);
uart_enable_pattern_det_intr(esp_dte->uart_port, '\n', 1, MIN_PATTERN_INTERVAL, MIN_POST_IDLE, MIN_PRE_IDLE);
uart_enable_pattern_det_baud_intr(esp_dte->uart_port, '\n', 1, MIN_PATTERN_INTERVAL, MIN_POST_IDLE, MIN_PRE_IDLE);
return ESP_OK;
err:
free(buffer);
err_write:
uart_enable_pattern_det_intr(esp_dte->uart_port, '\n', 1, MIN_PATTERN_INTERVAL, MIN_POST_IDLE, MIN_PRE_IDLE);
uart_enable_pattern_det_baud_intr(esp_dte->uart_port, '\n', 1, MIN_PATTERN_INTERVAL, MIN_POST_IDLE, MIN_PRE_IDLE);
err_param:
return ESP_FAIL;
}
@@ -298,7 +298,7 @@ static esp_err_t esp_modem_dte_change_mode(modem_dte_t *dte, modem_mode_t new_mo
case MODEM_COMMAND_MODE:
uart_disable_rx_intr(esp_dte->uart_port);
uart_flush(esp_dte->uart_port);
uart_enable_pattern_det_intr(esp_dte->uart_port, '\n', 1, MIN_PATTERN_INTERVAL, MIN_POST_IDLE, MIN_PRE_IDLE);
uart_enable_pattern_det_baud_intr(esp_dte->uart_port, '\n', 1, MIN_PATTERN_INTERVAL, MIN_POST_IDLE, MIN_PRE_IDLE);
uart_pattern_queue_reset(esp_dte->uart_port, CONFIG_EXAMPLE_UART_PATTERN_QUEUE_SIZE);
MODEM_CHECK(dce->set_working_mode(dce, new_mode) == ESP_OK, "set new working mode:%d failed", err, new_mode);
break;
@@ -392,7 +392,7 @@ modem_dte_t *esp_modem_dte_init(const esp_modem_dte_config_t *config)
CONFIG_EXAMPLE_UART_EVENT_QUEUE_SIZE, &(esp_dte->event_queue), 0);
MODEM_CHECK(res == ESP_OK, "install uart driver failed", err_uart_config);
/* Set pattern interrupt, used to detect the end of a line. */
res = uart_enable_pattern_det_intr(esp_dte->uart_port, '\n', 1, MIN_PATTERN_INTERVAL, MIN_POST_IDLE, MIN_PRE_IDLE);
res = uart_enable_pattern_det_baud_intr(esp_dte->uart_port, '\n', 1, MIN_PATTERN_INTERVAL, MIN_POST_IDLE, MIN_PRE_IDLE);
/* Set pattern queue size */
res |= uart_pattern_queue_reset(esp_dte->uart_port, CONFIG_EXAMPLE_UART_PATTERN_QUEUE_SIZE);
MODEM_CHECK(res == ESP_OK, "config uart pattern failed", err_uart_pattern);