diff --git a/board/BearPi_STM32L431RC/BSP/Src/stm32l4xx_it_module.c b/board/BearPi_STM32L431RC/BSP/Src/stm32l4xx_it_module.c
index 2473e742eba6d1a4bb59dfbf3f1fdfb18a2a9b9b..37c186bd4f607f87437b7daf08f650a7535e23ca 100644
--- a/board/BearPi_STM32L431RC/BSP/Src/stm32l4xx_it_module.c
+++ b/board/BearPi_STM32L431RC/BSP/Src/stm32l4xx_it_module.c
@@ -1,307 +1,327 @@
-/* USER CODE BEGIN Header */
-/**
- ******************************************************************************
- * @file stm32l4xx_it.c
- * @brief Interrupt Service Routines.
- ******************************************************************************
- * @attention
- *
- *
© Copyright (c) 2019 STMicroelectronics.
- * All rights reserved.
- *
- * This software component is licensed by ST under BSD 3-Clause license,
- * the "License"; You may not use this file except in compliance with the
- * License. You may obtain a copy of the License at:
- * opensource.org/licenses/BSD-3-Clause
- *
- ******************************************************************************
- */
-/* USER CODE END Header */
-
-/* Includes ------------------------------------------------------------------*/
-#include "main.h"
-#include "stm32l4xx_it.h"
-#include "tos_k.h"
-#include "tos_at.h"
-/* Private includes ----------------------------------------------------------*/
-/* USER CODE BEGIN Includes */
-/* USER CODE END Includes */
-
-/* Private typedef -----------------------------------------------------------*/
-/* USER CODE BEGIN TD */
-
-/* USER CODE END TD */
-
-/* Private define ------------------------------------------------------------*/
-/* USER CODE BEGIN PD */
-
-/* USER CODE END PD */
-
-/* Private macro -------------------------------------------------------------*/
-/* USER CODE BEGIN PM */
-
-/* USER CODE END PM */
-
-/* Private variables ---------------------------------------------------------*/
-/* USER CODE BEGIN PV */
-
-/* USER CODE END PV */
-
-/* Private function prototypes -----------------------------------------------*/
-/* USER CODE BEGIN PFP */
-
-/* USER CODE END PFP */
-
-/* Private user code ---------------------------------------------------------*/
-/* USER CODE BEGIN 0 */
-
-/* USER CODE END 0 */
-
-/* External variables --------------------------------------------------------*/
-extern UART_HandleTypeDef hlpuart1;
-extern UART_HandleTypeDef huart2;
-extern UART_HandleTypeDef huart3;
-/* USER CODE BEGIN EV */
-
-/* USER CODE END EV */
-
-/******************************************************************************/
-/* Cortex-M4 Processor Interruption and Exception Handlers */
-/******************************************************************************/
-/**
- * @brief This function handles Non maskable interrupt.
- */
-void NMI_Handler(void)
-{
- /* USER CODE BEGIN NonMaskableInt_IRQn 0 */
-
- /* USER CODE END NonMaskableInt_IRQn 0 */
- /* USER CODE BEGIN NonMaskableInt_IRQn 1 */
-
- /* USER CODE END NonMaskableInt_IRQn 1 */
-}
-
-/**
- * @brief This function handles Hard fault interrupt.
- */
-void HardFault_Handler(void)
-{
- /* USER CODE BEGIN HardFault_IRQn 0 */
-
- /* USER CODE END HardFault_IRQn 0 */
- while (1)
- {
- /* USER CODE BEGIN W1_HardFault_IRQn 0 */
- /* USER CODE END W1_HardFault_IRQn 0 */
- }
-}
-
-/**
- * @brief This function handles Memory management fault.
- */
-void MemManage_Handler(void)
-{
- /* USER CODE BEGIN MemoryManagement_IRQn 0 */
-
- /* USER CODE END MemoryManagement_IRQn 0 */
- while (1)
- {
- /* USER CODE BEGIN W1_MemoryManagement_IRQn 0 */
- /* USER CODE END W1_MemoryManagement_IRQn 0 */
- }
-}
-
-/**
- * @brief This function handles Prefetch fault, memory access fault.
- */
-void BusFault_Handler(void)
-{
- /* USER CODE BEGIN BusFault_IRQn 0 */
-
- /* USER CODE END BusFault_IRQn 0 */
- while (1)
- {
- /* USER CODE BEGIN W1_BusFault_IRQn 0 */
- /* USER CODE END W1_BusFault_IRQn 0 */
- }
-}
-
-/**
- * @brief This function handles Undefined instruction or illegal state.
- */
-void UsageFault_Handler(void)
-{
- /* USER CODE BEGIN UsageFault_IRQn 0 */
-
- /* USER CODE END UsageFault_IRQn 0 */
- while (1)
- {
- /* USER CODE BEGIN W1_UsageFault_IRQn 0 */
- /* USER CODE END W1_UsageFault_IRQn 0 */
- }
-}
-
-/**
- * @brief This function handles System service call via SWI instruction.
- */
-void SVC_Handler(void)
-{
- /* USER CODE BEGIN SVCall_IRQn 0 */
-
- /* USER CODE END SVCall_IRQn 0 */
- /* USER CODE BEGIN SVCall_IRQn 1 */
-
- /* USER CODE END SVCall_IRQn 1 */
-}
-
-/**
- * @brief This function handles Debug monitor.
- */
-void DebugMon_Handler(void)
-{
- /* USER CODE BEGIN DebugMonitor_IRQn 0 */
-
- /* USER CODE END DebugMonitor_IRQn 0 */
- /* USER CODE BEGIN DebugMonitor_IRQn 1 */
-
- /* USER CODE END DebugMonitor_IRQn 1 */
-}
-
-/**
- * @brief This function handles Pendable request for system service.
- */
-__weak void PendSV_Handler(void)
-{
- /* USER CODE BEGIN PendSV_IRQn 0 */
-
- /* USER CODE END PendSV_IRQn 0 */
- /* USER CODE BEGIN PendSV_IRQn 1 */
-
- /* USER CODE END PendSV_IRQn 1 */
-}
-
-/**
- * @brief This function handles System tick timer.
- */
-void SysTick_Handler(void)
-{
- /* USER CODE BEGIN SysTick_IRQn 0 */
-
- /* USER CODE END SysTick_IRQn 0 */
- HAL_IncTick();
- if (tos_knl_is_running())
- {
- tos_knl_irq_enter();
- tos_tick_handler();
- tos_knl_irq_leave();
- }
- //HAL_SYSTICK_IRQHandler();
- /* USER CODE BEGIN SysTick_IRQn 1 */
-
- /* USER CODE END SysTick_IRQn 1 */
-}
-
-/******************************************************************************/
-/* STM32L4xx Peripheral Interrupt Handlers */
-/* Add here the Interrupt Handlers for the used peripherals. */
-/* For the available peripheral interrupt handler names, */
-/* please refer to the startup file (startup_stm32l4xx.s). */
-/******************************************************************************/
-
-/**
- * @brief This function handles EXTI line1 interrupt.
- */
-void EXTI1_IRQHandler(void)
-{
- /* USER CODE BEGIN EXTI1_IRQn 0 */
-
- /* USER CODE END EXTI1_IRQn 0 */
- HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_1);
- /* USER CODE BEGIN EXTI1_IRQn 1 */
-
- /* USER CODE END EXTI1_IRQn 1 */
-}
-
-/**
- * @brief This function handles EXTI line2 interrupt.
- */
-void EXTI2_IRQHandler(void)
-{
- /* USER CODE BEGIN EXTI2_IRQn 0 */
-
- /* USER CODE END EXTI2_IRQn 0 */
- HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_2);
- /* USER CODE BEGIN EXTI2_IRQn 1 */
-
- /* USER CODE END EXTI2_IRQn 1 */
-}
-
-/**
- * @brief This function handles EXTI line3 interrupt.
- */
-void EXTI3_IRQHandler(void)
-{
- /* USER CODE BEGIN EXTI3_IRQn 0 */
-
- /* USER CODE END EXTI3_IRQn 0 */
- HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_3);
- /* USER CODE BEGIN EXTI3_IRQn 1 */
-
- /* USER CODE END EXTI3_IRQn 1 */
-}
-
-/**
- * @brief This function handles USART2 global interrupt.
- */
-void USART2_IRQHandler(void)
-{
- /* USER CODE BEGIN USART2_IRQn 0 */
-
- /* USER CODE END USART2_IRQn 0 */
- HAL_UART_IRQHandler(&huart2);
- /* USER CODE BEGIN USART2_IRQn 1 */
-
- /* USER CODE END USART2_IRQn 1 */
-}
-
-/**
- * @brief This function handles USART3 global interrupt.
- */
-void USART3_IRQHandler(void)
-{
- /* USER CODE BEGIN USART3_IRQn 0 */
-
- /* USER CODE END USART3_IRQn 0 */
- HAL_UART_IRQHandler(&huart3);
- /* USER CODE BEGIN USART3_IRQn 1 */
-
- /* USER CODE END USART3_IRQn 1 */
-}
-
-/**
- * @brief This function handles LPUART1 global interrupt.
- */
-void LPUART1_IRQHandler(void)
-{
- /* USER CODE BEGIN LPUART1_IRQn 0 */
-
- /* USER CODE END LPUART1_IRQn 0 */
- tos_knl_irq_enter();
- HAL_UART_IRQHandler(&hlpuart1);
- tos_knl_irq_leave();
- /* USER CODE BEGIN LPUART1_IRQn 1 */
-
- /* USER CODE END LPUART1_IRQn 1 */
-}
-
-/* USER CODE BEGIN 1 */
-void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
-{
- extern uint8_t data;
- if (huart->Instance == LPUART1) {
- HAL_UART_Receive_IT(&hlpuart1, &data, 1);
- tos_at_uart_input_byte(data);
- }
-}
-/* USER CODE END 1 */
-/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
+/* USER CODE BEGIN Header */
+/**
+ ******************************************************************************
+ * @file stm32l4xx_it.c
+ * @brief Interrupt Service Routines.
+ ******************************************************************************
+ * @attention
+ *
+ * © Copyright (c) 2019 STMicroelectronics.
+ * All rights reserved.
+ *
+ * This software component is licensed by ST under BSD 3-Clause license,
+ * the "License"; You may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ * opensource.org/licenses/BSD-3-Clause
+ *
+ ******************************************************************************
+ */
+/* USER CODE END Header */
+
+/* Includes ------------------------------------------------------------------*/
+#include "main.h"
+#include "stm32l4xx_it.h"
+#include "tos_k.h"
+#include "tos_at.h"
+/* Private includes ----------------------------------------------------------*/
+/* USER CODE BEGIN Includes */
+/* USER CODE END Includes */
+
+/* Private typedef -----------------------------------------------------------*/
+/* USER CODE BEGIN TD */
+
+/* USER CODE END TD */
+
+/* Private define ------------------------------------------------------------*/
+/* USER CODE BEGIN PD */
+
+/* USER CODE END PD */
+
+/* Private macro -------------------------------------------------------------*/
+/* USER CODE BEGIN PM */
+
+/* USER CODE END PM */
+
+/* Private variables ---------------------------------------------------------*/
+/* USER CODE BEGIN PV */
+#if AT_INPUT_TYPE_FRAME_EN
+#define UART_FRAME_BUFFER_MAX 1024
+uint8_t uart_frame_buffer[UART_FRAME_BUFFER_MAX];
+uint16_t uart_frame_buffer_index;
+#endif /* AT_INPUT_TYPE_FRAME_EN */
+/* USER CODE END PV */
+
+/* Private function prototypes -----------------------------------------------*/
+/* USER CODE BEGIN PFP */
+
+/* USER CODE END PFP */
+
+/* Private user code ---------------------------------------------------------*/
+/* USER CODE BEGIN 0 */
+
+/* USER CODE END 0 */
+
+/* External variables --------------------------------------------------------*/
+extern UART_HandleTypeDef hlpuart1;
+extern UART_HandleTypeDef huart2;
+extern UART_HandleTypeDef huart3;
+/* USER CODE BEGIN EV */
+
+/* USER CODE END EV */
+
+/******************************************************************************/
+/* Cortex-M4 Processor Interruption and Exception Handlers */
+/******************************************************************************/
+/**
+ * @brief This function handles Non maskable interrupt.
+ */
+void NMI_Handler(void)
+{
+ /* USER CODE BEGIN NonMaskableInt_IRQn 0 */
+
+ /* USER CODE END NonMaskableInt_IRQn 0 */
+ /* USER CODE BEGIN NonMaskableInt_IRQn 1 */
+
+ /* USER CODE END NonMaskableInt_IRQn 1 */
+}
+
+/**
+ * @brief This function handles Hard fault interrupt.
+ */
+void HardFault_Handler(void)
+{
+ /* USER CODE BEGIN HardFault_IRQn 0 */
+
+ /* USER CODE END HardFault_IRQn 0 */
+ while (1)
+ {
+ /* USER CODE BEGIN W1_HardFault_IRQn 0 */
+ /* USER CODE END W1_HardFault_IRQn 0 */
+ }
+}
+
+/**
+ * @brief This function handles Memory management fault.
+ */
+void MemManage_Handler(void)
+{
+ /* USER CODE BEGIN MemoryManagement_IRQn 0 */
+
+ /* USER CODE END MemoryManagement_IRQn 0 */
+ while (1)
+ {
+ /* USER CODE BEGIN W1_MemoryManagement_IRQn 0 */
+ /* USER CODE END W1_MemoryManagement_IRQn 0 */
+ }
+}
+
+/**
+ * @brief This function handles Prefetch fault, memory access fault.
+ */
+void BusFault_Handler(void)
+{
+ /* USER CODE BEGIN BusFault_IRQn 0 */
+
+ /* USER CODE END BusFault_IRQn 0 */
+ while (1)
+ {
+ /* USER CODE BEGIN W1_BusFault_IRQn 0 */
+ /* USER CODE END W1_BusFault_IRQn 0 */
+ }
+}
+
+/**
+ * @brief This function handles Undefined instruction or illegal state.
+ */
+void UsageFault_Handler(void)
+{
+ /* USER CODE BEGIN UsageFault_IRQn 0 */
+
+ /* USER CODE END UsageFault_IRQn 0 */
+ while (1)
+ {
+ /* USER CODE BEGIN W1_UsageFault_IRQn 0 */
+ /* USER CODE END W1_UsageFault_IRQn 0 */
+ }
+}
+
+/**
+ * @brief This function handles System service call via SWI instruction.
+ */
+void SVC_Handler(void)
+{
+ /* USER CODE BEGIN SVCall_IRQn 0 */
+
+ /* USER CODE END SVCall_IRQn 0 */
+ /* USER CODE BEGIN SVCall_IRQn 1 */
+
+ /* USER CODE END SVCall_IRQn 1 */
+}
+
+/**
+ * @brief This function handles Debug monitor.
+ */
+void DebugMon_Handler(void)
+{
+ /* USER CODE BEGIN DebugMonitor_IRQn 0 */
+
+ /* USER CODE END DebugMonitor_IRQn 0 */
+ /* USER CODE BEGIN DebugMonitor_IRQn 1 */
+
+ /* USER CODE END DebugMonitor_IRQn 1 */
+}
+
+/**
+ * @brief This function handles Pendable request for system service.
+ */
+__weak void PendSV_Handler(void)
+{
+ /* USER CODE BEGIN PendSV_IRQn 0 */
+
+ /* USER CODE END PendSV_IRQn 0 */
+ /* USER CODE BEGIN PendSV_IRQn 1 */
+
+ /* USER CODE END PendSV_IRQn 1 */
+}
+
+/**
+ * @brief This function handles System tick timer.
+ */
+void SysTick_Handler(void)
+{
+ /* USER CODE BEGIN SysTick_IRQn 0 */
+
+ /* USER CODE END SysTick_IRQn 0 */
+ HAL_IncTick();
+ if (tos_knl_is_running())
+ {
+ tos_knl_irq_enter();
+ tos_tick_handler();
+ tos_knl_irq_leave();
+ }
+ //HAL_SYSTICK_IRQHandler();
+ /* USER CODE BEGIN SysTick_IRQn 1 */
+
+ /* USER CODE END SysTick_IRQn 1 */
+}
+
+/******************************************************************************/
+/* STM32L4xx Peripheral Interrupt Handlers */
+/* Add here the Interrupt Handlers for the used peripherals. */
+/* For the available peripheral interrupt handler names, */
+/* please refer to the startup file (startup_stm32l4xx.s). */
+/******************************************************************************/
+
+/**
+ * @brief This function handles EXTI line1 interrupt.
+ */
+void EXTI1_IRQHandler(void)
+{
+ /* USER CODE BEGIN EXTI1_IRQn 0 */
+
+ /* USER CODE END EXTI1_IRQn 0 */
+ HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_1);
+ /* USER CODE BEGIN EXTI1_IRQn 1 */
+
+ /* USER CODE END EXTI1_IRQn 1 */
+}
+
+/**
+ * @brief This function handles EXTI line2 interrupt.
+ */
+void EXTI2_IRQHandler(void)
+{
+ /* USER CODE BEGIN EXTI2_IRQn 0 */
+
+ /* USER CODE END EXTI2_IRQn 0 */
+ HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_2);
+ /* USER CODE BEGIN EXTI2_IRQn 1 */
+
+ /* USER CODE END EXTI2_IRQn 1 */
+}
+
+/**
+ * @brief This function handles EXTI line3 interrupt.
+ */
+void EXTI3_IRQHandler(void)
+{
+ /* USER CODE BEGIN EXTI3_IRQn 0 */
+
+ /* USER CODE END EXTI3_IRQn 0 */
+ HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_3);
+ /* USER CODE BEGIN EXTI3_IRQn 1 */
+
+ /* USER CODE END EXTI3_IRQn 1 */
+}
+
+/**
+ * @brief This function handles USART2 global interrupt.
+ */
+void USART2_IRQHandler(void)
+{
+ /* USER CODE BEGIN USART2_IRQn 0 */
+
+ /* USER CODE END USART2_IRQn 0 */
+ HAL_UART_IRQHandler(&huart2);
+ /* USER CODE BEGIN USART2_IRQn 1 */
+
+ /* USER CODE END USART2_IRQn 1 */
+}
+
+/**
+ * @brief This function handles USART3 global interrupt.
+ */
+void USART3_IRQHandler(void)
+{
+ /* USER CODE BEGIN USART3_IRQn 0 */
+
+ /* USER CODE END USART3_IRQn 0 */
+ HAL_UART_IRQHandler(&huart3);
+ /* USER CODE BEGIN USART3_IRQn 1 */
+
+ /* USER CODE END USART3_IRQn 1 */
+}
+
+/**
+ * @brief This function handles LPUART1 global interrupt.
+ */
+void LPUART1_IRQHandler(void)
+{
+ /* USER CODE BEGIN LPUART1_IRQn 0 */
+
+ /* USER CODE END LPUART1_IRQn 0 */
+ tos_knl_irq_enter();
+ HAL_UART_IRQHandler(&hlpuart1);
+ tos_knl_irq_leave();
+ /* USER CODE BEGIN LPUART1_IRQn 1 */
+#if AT_INPUT_TYPE_FRAME_EN
+ if (__HAL_UART_GET_FLAG(&hlpuart1, UART_FLAG_IDLE)){
+ __HAL_UART_CLEAR_IDLEFLAG(&hlpuart1);
+
+ if (uart_frame_buffer_index != 0) {
+ tos_at_uart_input_frame(uart_frame_buffer, uart_frame_buffer_index);
+ uart_frame_buffer_index = 0;
+ memset(uart_frame_buffer, 0, sizeof(uart_frame_buffer));
+ }
+ }
+
+#endif /* AT_INPUT_TYPE_FRAME_EN */
+
+ /* USER CODE END LPUART1_IRQn 1 */
+}
+
+/* USER CODE BEGIN 1 */
+void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
+{
+ extern uint8_t data;
+ if (huart->Instance == LPUART1) {
+ HAL_UART_Receive_IT(&hlpuart1, &data, 1);
+#if AT_INPUT_TYPE_FRAME_EN
+ uart_frame_buffer[uart_frame_buffer_index++] = data;
+#else
+ tos_at_uart_input_byte(data);
+#endif /* AT_INPUT_TYPE_FRAME_EN */
+ }
+}
+/* USER CODE END 1 */
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/board/BearPi_STM32L431RC/BSP/Src/usart.c b/board/BearPi_STM32L431RC/BSP/Src/usart.c
index 0a9b45ead2298769bbd76e6fb8b67c94dde1f5fe..9b0493eb33d70cd50092eb02edc5513a3e29ca11 100644
--- a/board/BearPi_STM32L431RC/BSP/Src/usart.c
+++ b/board/BearPi_STM32L431RC/BSP/Src/usart.c
@@ -1,313 +1,317 @@
-/**
- ******************************************************************************
- * File Name : USART.c
- * Description : This file provides code for the configuration
- * of the USART instances.
- ******************************************************************************
- * @attention
- *
- * © Copyright (c) 2019 STMicroelectronics.
- * All rights reserved.
- *
- * This software component is licensed by ST under BSD 3-Clause license,
- * the "License"; You may not use this file except in compliance with the
- * License. You may obtain a copy of the License at:
- * opensource.org/licenses/BSD-3-Clause
- *
- ******************************************************************************
- */
-
-/* Includes ------------------------------------------------------------------*/
-#include "usart.h"
-
-/* USER CODE BEGIN 0 */
-uint8_t data;
-/* USER CODE END 0 */
-
-UART_HandleTypeDef hlpuart1;
-UART_HandleTypeDef huart1;
-UART_HandleTypeDef huart2;
-UART_HandleTypeDef huart3;
-
-/* LPUART1 init function */
-
-void MX_LPUART1_UART_Init(void)
-{
-
- hlpuart1.Instance = LPUART1;
- hlpuart1.Init.BaudRate = 115200;
- hlpuart1.Init.WordLength = UART_WORDLENGTH_8B;
- hlpuart1.Init.StopBits = UART_STOPBITS_1;
- hlpuart1.Init.Parity = UART_PARITY_NONE;
- hlpuart1.Init.Mode = UART_MODE_TX_RX;
- hlpuart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
- hlpuart1.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
- hlpuart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
- if (HAL_UART_Init(&hlpuart1) != HAL_OK)
- {
- Error_Handler();
- }
- HAL_UART_Receive_IT(&hlpuart1, &data, 1);
-}
-/* USART1 init function */
-
-void MX_USART1_UART_Init(void)
-{
-
- huart1.Instance = USART1;
- huart1.Init.BaudRate = 115200;
- huart1.Init.WordLength = UART_WORDLENGTH_8B;
- huart1.Init.StopBits = UART_STOPBITS_1;
- huart1.Init.Parity = UART_PARITY_NONE;
- huart1.Init.Mode = UART_MODE_TX_RX;
- huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
- huart1.Init.OverSampling = UART_OVERSAMPLING_16;
- huart1.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
- huart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
- if (HAL_UART_Init(&huart1) != HAL_OK)
- {
- Error_Handler();
- }
-
-}
-/* USART2 init function */
-
-void MX_USART2_UART_Init(void)
-{
-
- huart2.Instance = USART2;
- huart2.Init.BaudRate = 115200;
- huart2.Init.WordLength = UART_WORDLENGTH_8B;
- huart2.Init.StopBits = UART_STOPBITS_1;
- huart2.Init.Parity = UART_PARITY_NONE;
- huart2.Init.Mode = UART_MODE_TX_RX;
- huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE;
- huart2.Init.OverSampling = UART_OVERSAMPLING_16;
- huart2.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
- huart2.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
- if (HAL_UART_Init(&huart2) != HAL_OK)
- {
- Error_Handler();
- }
-
-}
-/* USART3 init function */
-
-void MX_USART3_UART_Init(void)
-{
-
- huart3.Instance = USART3;
- huart3.Init.BaudRate = 115200;
- huart3.Init.WordLength = UART_WORDLENGTH_8B;
- huart3.Init.StopBits = UART_STOPBITS_1;
- huart3.Init.Parity = UART_PARITY_NONE;
- huart3.Init.Mode = UART_MODE_TX_RX;
- huart3.Init.HwFlowCtl = UART_HWCONTROL_NONE;
- huart3.Init.OverSampling = UART_OVERSAMPLING_16;
- huart3.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
- huart3.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
- if (HAL_UART_Init(&huart3) != HAL_OK)
- {
- Error_Handler();
- }
-
-}
-
-void HAL_UART_MspInit(UART_HandleTypeDef* uartHandle)
-{
-
- GPIO_InitTypeDef GPIO_InitStruct = {0};
- if(uartHandle->Instance==LPUART1)
- {
- /* USER CODE BEGIN LPUART1_MspInit 0 */
-
- /* USER CODE END LPUART1_MspInit 0 */
- /* LPUART1 clock enable */
- __HAL_RCC_LPUART1_CLK_ENABLE();
-
- __HAL_RCC_GPIOC_CLK_ENABLE();
- /**LPUART1 GPIO Configuration
- PC0 ------> LPUART1_RX
- PC1 ------> LPUART1_TX
- */
- GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1;
- GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
- GPIO_InitStruct.Pull = GPIO_NOPULL;
- GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
- GPIO_InitStruct.Alternate = GPIO_AF8_LPUART1;
- HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
-
- /* LPUART1 interrupt Init */
- HAL_NVIC_SetPriority(LPUART1_IRQn, 0, 0);
- HAL_NVIC_EnableIRQ(LPUART1_IRQn);
- /* USER CODE BEGIN LPUART1_MspInit 1 */
-
- /* USER CODE END LPUART1_MspInit 1 */
- }
- else if(uartHandle->Instance==USART1)
- {
- /* USER CODE BEGIN USART1_MspInit 0 */
-
- /* USER CODE END USART1_MspInit 0 */
- /* USART1 clock enable */
- __HAL_RCC_USART1_CLK_ENABLE();
-
- __HAL_RCC_GPIOA_CLK_ENABLE();
- /**USART1 GPIO Configuration
- PA9 ------> USART1_TX
- PA10 ------> USART1_RX
- */
- GPIO_InitStruct.Pin = GPIO_PIN_9|GPIO_PIN_10;
- GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
- GPIO_InitStruct.Pull = GPIO_NOPULL;
- GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
- GPIO_InitStruct.Alternate = GPIO_AF7_USART1;
- HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
-
- /* USER CODE BEGIN USART1_MspInit 1 */
-
- /* USER CODE END USART1_MspInit 1 */
- }
- else if(uartHandle->Instance==USART2)
- {
- /* USER CODE BEGIN USART2_MspInit 0 */
-
- /* USER CODE END USART2_MspInit 0 */
- /* USART2 clock enable */
- __HAL_RCC_USART2_CLK_ENABLE();
-
- __HAL_RCC_GPIOA_CLK_ENABLE();
- /**USART2 GPIO Configuration
- PA2 ------> USART2_TX
- PA3 ------> USART2_RX
- */
- GPIO_InitStruct.Pin = GPIO_PIN_2|GPIO_PIN_3;
- GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
- GPIO_InitStruct.Pull = GPIO_NOPULL;
- GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
- GPIO_InitStruct.Alternate = GPIO_AF7_USART2;
- HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
-
- /* USART2 interrupt Init */
- HAL_NVIC_SetPriority(USART2_IRQn, 0, 0);
- HAL_NVIC_EnableIRQ(USART2_IRQn);
- /* USER CODE BEGIN USART2_MspInit 1 */
-
- /* USER CODE END USART2_MspInit 1 */
- }
- else if(uartHandle->Instance==USART3)
- {
- /* USER CODE BEGIN USART3_MspInit 0 */
-
- /* USER CODE END USART3_MspInit 0 */
- /* USART3 clock enable */
- __HAL_RCC_USART3_CLK_ENABLE();
-
- __HAL_RCC_GPIOC_CLK_ENABLE();
- /**USART3 GPIO Configuration
- PC4 ------> USART3_TX
- PC5 ------> USART3_RX
- */
- GPIO_InitStruct.Pin = GPIO_PIN_4|GPIO_PIN_5;
- GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
- GPIO_InitStruct.Pull = GPIO_NOPULL;
- GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
- GPIO_InitStruct.Alternate = GPIO_AF7_USART3;
- HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
-
- /* USART3 interrupt Init */
- HAL_NVIC_SetPriority(USART3_IRQn, 0, 0);
- HAL_NVIC_EnableIRQ(USART3_IRQn);
- /* USER CODE BEGIN USART3_MspInit 1 */
-
- /* USER CODE END USART3_MspInit 1 */
- }
-}
-
-void HAL_UART_MspDeInit(UART_HandleTypeDef* uartHandle)
-{
-
- if(uartHandle->Instance==LPUART1)
- {
- /* USER CODE BEGIN LPUART1_MspDeInit 0 */
-
- /* USER CODE END LPUART1_MspDeInit 0 */
- /* Peripheral clock disable */
- __HAL_RCC_LPUART1_CLK_DISABLE();
-
- /**LPUART1 GPIO Configuration
- PC0 ------> LPUART1_RX
- PC1 ------> LPUART1_TX
- */
- HAL_GPIO_DeInit(GPIOC, GPIO_PIN_0|GPIO_PIN_1);
-
- /* LPUART1 interrupt Deinit */
- HAL_NVIC_DisableIRQ(LPUART1_IRQn);
- /* USER CODE BEGIN LPUART1_MspDeInit 1 */
-
- /* USER CODE END LPUART1_MspDeInit 1 */
- }
- else if(uartHandle->Instance==USART1)
- {
- /* USER CODE BEGIN USART1_MspDeInit 0 */
-
- /* USER CODE END USART1_MspDeInit 0 */
- /* Peripheral clock disable */
- __HAL_RCC_USART1_CLK_DISABLE();
-
- /**USART1 GPIO Configuration
- PA9 ------> USART1_TX
- PA10 ------> USART1_RX
- */
- HAL_GPIO_DeInit(GPIOA, GPIO_PIN_9|GPIO_PIN_10);
-
- /* USER CODE BEGIN USART1_MspDeInit 1 */
-
- /* USER CODE END USART1_MspDeInit 1 */
- }
- else if(uartHandle->Instance==USART2)
- {
- /* USER CODE BEGIN USART2_MspDeInit 0 */
-
- /* USER CODE END USART2_MspDeInit 0 */
- /* Peripheral clock disable */
- __HAL_RCC_USART2_CLK_DISABLE();
-
- /**USART2 GPIO Configuration
- PA2 ------> USART2_TX
- PA3 ------> USART2_RX
- */
- HAL_GPIO_DeInit(GPIOA, GPIO_PIN_2|GPIO_PIN_3);
-
- /* USART2 interrupt Deinit */
- HAL_NVIC_DisableIRQ(USART2_IRQn);
- /* USER CODE BEGIN USART2_MspDeInit 1 */
-
- /* USER CODE END USART2_MspDeInit 1 */
- }
- else if(uartHandle->Instance==USART3)
- {
- /* USER CODE BEGIN USART3_MspDeInit 0 */
-
- /* USER CODE END USART3_MspDeInit 0 */
- /* Peripheral clock disable */
- __HAL_RCC_USART3_CLK_DISABLE();
-
- /**USART3 GPIO Configuration
- PC4 ------> USART3_TX
- PC5 ------> USART3_RX
- */
- HAL_GPIO_DeInit(GPIOC, GPIO_PIN_4|GPIO_PIN_5);
-
- /* USART3 interrupt Deinit */
- HAL_NVIC_DisableIRQ(USART3_IRQn);
- /* USER CODE BEGIN USART3_MspDeInit 1 */
-
- /* USER CODE END USART3_MspDeInit 1 */
- }
-}
-
-/* USER CODE BEGIN 1 */
-/* USER CODE END 1 */
-
-/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
+/**
+ ******************************************************************************
+ * File Name : USART.c
+ * Description : This file provides code for the configuration
+ * of the USART instances.
+ ******************************************************************************
+ * @attention
+ *
+ * © Copyright (c) 2019 STMicroelectronics.
+ * All rights reserved.
+ *
+ * This software component is licensed by ST under BSD 3-Clause license,
+ * the "License"; You may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ * opensource.org/licenses/BSD-3-Clause
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "usart.h"
+#include "tos_at.h"
+
+/* USER CODE BEGIN 0 */
+uint8_t data;
+/* USER CODE END 0 */
+
+UART_HandleTypeDef hlpuart1;
+UART_HandleTypeDef huart1;
+UART_HandleTypeDef huart2;
+UART_HandleTypeDef huart3;
+
+/* LPUART1 init function */
+
+void MX_LPUART1_UART_Init(void)
+{
+
+ hlpuart1.Instance = LPUART1;
+ hlpuart1.Init.BaudRate = 115200;
+ hlpuart1.Init.WordLength = UART_WORDLENGTH_8B;
+ hlpuart1.Init.StopBits = UART_STOPBITS_1;
+ hlpuart1.Init.Parity = UART_PARITY_NONE;
+ hlpuart1.Init.Mode = UART_MODE_TX_RX;
+ hlpuart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
+ hlpuart1.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
+ hlpuart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
+ if (HAL_UART_Init(&hlpuart1) != HAL_OK)
+ {
+ Error_Handler();
+ }
+ HAL_UART_Receive_IT(&hlpuart1, &data, 1);
+#if AT_INPUT_TYPE_FRAME_EN
+ __HAL_UART_ENABLE_IT(&hlpuart1, UART_IT_IDLE);
+#endif
+}
+/* USART1 init function */
+
+void MX_USART1_UART_Init(void)
+{
+
+ huart1.Instance = USART1;
+ huart1.Init.BaudRate = 115200;
+ huart1.Init.WordLength = UART_WORDLENGTH_8B;
+ huart1.Init.StopBits = UART_STOPBITS_1;
+ huart1.Init.Parity = UART_PARITY_NONE;
+ huart1.Init.Mode = UART_MODE_TX_RX;
+ huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
+ huart1.Init.OverSampling = UART_OVERSAMPLING_16;
+ huart1.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
+ huart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
+ if (HAL_UART_Init(&huart1) != HAL_OK)
+ {
+ Error_Handler();
+ }
+
+}
+/* USART2 init function */
+
+void MX_USART2_UART_Init(void)
+{
+
+ huart2.Instance = USART2;
+ huart2.Init.BaudRate = 115200;
+ huart2.Init.WordLength = UART_WORDLENGTH_8B;
+ huart2.Init.StopBits = UART_STOPBITS_1;
+ huart2.Init.Parity = UART_PARITY_NONE;
+ huart2.Init.Mode = UART_MODE_TX_RX;
+ huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE;
+ huart2.Init.OverSampling = UART_OVERSAMPLING_16;
+ huart2.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
+ huart2.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
+ if (HAL_UART_Init(&huart2) != HAL_OK)
+ {
+ Error_Handler();
+ }
+
+}
+/* USART3 init function */
+
+void MX_USART3_UART_Init(void)
+{
+
+ huart3.Instance = USART3;
+ huart3.Init.BaudRate = 115200;
+ huart3.Init.WordLength = UART_WORDLENGTH_8B;
+ huart3.Init.StopBits = UART_STOPBITS_1;
+ huart3.Init.Parity = UART_PARITY_NONE;
+ huart3.Init.Mode = UART_MODE_TX_RX;
+ huart3.Init.HwFlowCtl = UART_HWCONTROL_NONE;
+ huart3.Init.OverSampling = UART_OVERSAMPLING_16;
+ huart3.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
+ huart3.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
+ if (HAL_UART_Init(&huart3) != HAL_OK)
+ {
+ Error_Handler();
+ }
+
+}
+
+void HAL_UART_MspInit(UART_HandleTypeDef* uartHandle)
+{
+
+ GPIO_InitTypeDef GPIO_InitStruct = {0};
+ if(uartHandle->Instance==LPUART1)
+ {
+ /* USER CODE BEGIN LPUART1_MspInit 0 */
+
+ /* USER CODE END LPUART1_MspInit 0 */
+ /* LPUART1 clock enable */
+ __HAL_RCC_LPUART1_CLK_ENABLE();
+
+ __HAL_RCC_GPIOC_CLK_ENABLE();
+ /**LPUART1 GPIO Configuration
+ PC0 ------> LPUART1_RX
+ PC1 ------> LPUART1_TX
+ */
+ GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1;
+ GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
+ GPIO_InitStruct.Pull = GPIO_NOPULL;
+ GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
+ GPIO_InitStruct.Alternate = GPIO_AF8_LPUART1;
+ HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
+
+ /* LPUART1 interrupt Init */
+ HAL_NVIC_SetPriority(LPUART1_IRQn, 0, 0);
+ HAL_NVIC_EnableIRQ(LPUART1_IRQn);
+ /* USER CODE BEGIN LPUART1_MspInit 1 */
+
+ /* USER CODE END LPUART1_MspInit 1 */
+ }
+ else if(uartHandle->Instance==USART1)
+ {
+ /* USER CODE BEGIN USART1_MspInit 0 */
+
+ /* USER CODE END USART1_MspInit 0 */
+ /* USART1 clock enable */
+ __HAL_RCC_USART1_CLK_ENABLE();
+
+ __HAL_RCC_GPIOA_CLK_ENABLE();
+ /**USART1 GPIO Configuration
+ PA9 ------> USART1_TX
+ PA10 ------> USART1_RX
+ */
+ GPIO_InitStruct.Pin = GPIO_PIN_9|GPIO_PIN_10;
+ GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
+ GPIO_InitStruct.Pull = GPIO_NOPULL;
+ GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
+ GPIO_InitStruct.Alternate = GPIO_AF7_USART1;
+ HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
+
+ /* USER CODE BEGIN USART1_MspInit 1 */
+
+ /* USER CODE END USART1_MspInit 1 */
+ }
+ else if(uartHandle->Instance==USART2)
+ {
+ /* USER CODE BEGIN USART2_MspInit 0 */
+
+ /* USER CODE END USART2_MspInit 0 */
+ /* USART2 clock enable */
+ __HAL_RCC_USART2_CLK_ENABLE();
+
+ __HAL_RCC_GPIOA_CLK_ENABLE();
+ /**USART2 GPIO Configuration
+ PA2 ------> USART2_TX
+ PA3 ------> USART2_RX
+ */
+ GPIO_InitStruct.Pin = GPIO_PIN_2|GPIO_PIN_3;
+ GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
+ GPIO_InitStruct.Pull = GPIO_NOPULL;
+ GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
+ GPIO_InitStruct.Alternate = GPIO_AF7_USART2;
+ HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
+
+ /* USART2 interrupt Init */
+ HAL_NVIC_SetPriority(USART2_IRQn, 0, 0);
+ HAL_NVIC_EnableIRQ(USART2_IRQn);
+ /* USER CODE BEGIN USART2_MspInit 1 */
+
+ /* USER CODE END USART2_MspInit 1 */
+ }
+ else if(uartHandle->Instance==USART3)
+ {
+ /* USER CODE BEGIN USART3_MspInit 0 */
+
+ /* USER CODE END USART3_MspInit 0 */
+ /* USART3 clock enable */
+ __HAL_RCC_USART3_CLK_ENABLE();
+
+ __HAL_RCC_GPIOC_CLK_ENABLE();
+ /**USART3 GPIO Configuration
+ PC4 ------> USART3_TX
+ PC5 ------> USART3_RX
+ */
+ GPIO_InitStruct.Pin = GPIO_PIN_4|GPIO_PIN_5;
+ GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
+ GPIO_InitStruct.Pull = GPIO_NOPULL;
+ GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
+ GPIO_InitStruct.Alternate = GPIO_AF7_USART3;
+ HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
+
+ /* USART3 interrupt Init */
+ HAL_NVIC_SetPriority(USART3_IRQn, 0, 0);
+ HAL_NVIC_EnableIRQ(USART3_IRQn);
+ /* USER CODE BEGIN USART3_MspInit 1 */
+
+ /* USER CODE END USART3_MspInit 1 */
+ }
+}
+
+void HAL_UART_MspDeInit(UART_HandleTypeDef* uartHandle)
+{
+
+ if(uartHandle->Instance==LPUART1)
+ {
+ /* USER CODE BEGIN LPUART1_MspDeInit 0 */
+
+ /* USER CODE END LPUART1_MspDeInit 0 */
+ /* Peripheral clock disable */
+ __HAL_RCC_LPUART1_CLK_DISABLE();
+
+ /**LPUART1 GPIO Configuration
+ PC0 ------> LPUART1_RX
+ PC1 ------> LPUART1_TX
+ */
+ HAL_GPIO_DeInit(GPIOC, GPIO_PIN_0|GPIO_PIN_1);
+
+ /* LPUART1 interrupt Deinit */
+ HAL_NVIC_DisableIRQ(LPUART1_IRQn);
+ /* USER CODE BEGIN LPUART1_MspDeInit 1 */
+
+ /* USER CODE END LPUART1_MspDeInit 1 */
+ }
+ else if(uartHandle->Instance==USART1)
+ {
+ /* USER CODE BEGIN USART1_MspDeInit 0 */
+
+ /* USER CODE END USART1_MspDeInit 0 */
+ /* Peripheral clock disable */
+ __HAL_RCC_USART1_CLK_DISABLE();
+
+ /**USART1 GPIO Configuration
+ PA9 ------> USART1_TX
+ PA10 ------> USART1_RX
+ */
+ HAL_GPIO_DeInit(GPIOA, GPIO_PIN_9|GPIO_PIN_10);
+
+ /* USER CODE BEGIN USART1_MspDeInit 1 */
+
+ /* USER CODE END USART1_MspDeInit 1 */
+ }
+ else if(uartHandle->Instance==USART2)
+ {
+ /* USER CODE BEGIN USART2_MspDeInit 0 */
+
+ /* USER CODE END USART2_MspDeInit 0 */
+ /* Peripheral clock disable */
+ __HAL_RCC_USART2_CLK_DISABLE();
+
+ /**USART2 GPIO Configuration
+ PA2 ------> USART2_TX
+ PA3 ------> USART2_RX
+ */
+ HAL_GPIO_DeInit(GPIOA, GPIO_PIN_2|GPIO_PIN_3);
+
+ /* USART2 interrupt Deinit */
+ HAL_NVIC_DisableIRQ(USART2_IRQn);
+ /* USER CODE BEGIN USART2_MspDeInit 1 */
+
+ /* USER CODE END USART2_MspDeInit 1 */
+ }
+ else if(uartHandle->Instance==USART3)
+ {
+ /* USER CODE BEGIN USART3_MspDeInit 0 */
+
+ /* USER CODE END USART3_MspDeInit 0 */
+ /* Peripheral clock disable */
+ __HAL_RCC_USART3_CLK_DISABLE();
+
+ /**USART3 GPIO Configuration
+ PC4 ------> USART3_TX
+ PC5 ------> USART3_RX
+ */
+ HAL_GPIO_DeInit(GPIOC, GPIO_PIN_4|GPIO_PIN_5);
+
+ /* USART3 interrupt Deinit */
+ HAL_NVIC_DisableIRQ(USART3_IRQn);
+ /* USER CODE BEGIN USART3_MspDeInit 1 */
+
+ /* USER CODE END USART3_MspDeInit 1 */
+ }
+}
+
+/* USER CODE BEGIN 1 */
+/* USER CODE END 1 */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/board/BearPi_STM32L431RC/TOS-CONFIG/tos_config.h b/board/BearPi_STM32L431RC/TOS-CONFIG/tos_config.h
index 0178e7fc579376919d0cca523e95cfc35379ec15..7d9223e89a186940fd1e5cad033d2aea49617420 100644
--- a/board/BearPi_STM32L431RC/TOS-CONFIG/tos_config.h
+++ b/board/BearPi_STM32L431RC/TOS-CONFIG/tos_config.h
@@ -1,45 +1,47 @@
-#ifndef _TOS_CONFIG_H_
-#define _TOS_CONFIG_H_
-
-#include "stm32l4xx.h"
-
-#define TOS_CFG_TASK_PRIO_MAX 10u
-
-#define TOS_CFG_ROUND_ROBIN_EN 1u
-
-#define TOS_CFG_OBJECT_VERIFY_EN 1u
-
-#define TOS_CFG_TASK_DYNAMIC_CREATE_EN 0u
-
-#define TOS_CFG_EVENT_EN 1u
-
-#define TOS_CFG_MMBLK_EN 1u
-
-#define TOS_CFG_MMHEAP_EN 1u
-
-#define TOS_CFG_MMHEAP_DEFAULT_POOL_SIZE 0x8000
-
-#define TOS_CFG_MUTEX_EN 1u
-
-#define TOS_CFG_TIMER_EN 1u
-
-#define TOS_CFG_PWR_MGR_EN 0u
-
-#define TOS_CFG_TICKLESS_EN 0u
-
-#define TOS_CFG_SEM_EN 1u
-
-#define TOS_CFG_TASK_STACK_DRAUGHT_DEPTH_DETACT_EN 1u
-
-#define TOS_CFG_FAULT_BACKTRACE_EN 0u
-
-#define TOS_CFG_IDLE_TASK_STK_SIZE 512u
-
-#define TOS_CFG_CPU_TICK_PER_SECOND 1000u
-
-#define TOS_CFG_CPU_CLOCK (SystemCoreClock)
-
-#define TOS_CFG_TIMER_AS_PROC 1u
-
-#endif
-
+#ifndef _TOS_CONFIG_H_
+#define _TOS_CONFIG_H_
+
+#include "stm32l4xx.h"
+
+#define TOS_CFG_TASK_PRIO_MAX 10u
+
+#define TOS_CFG_ROUND_ROBIN_EN 1u
+
+#define TOS_CFG_OBJECT_VERIFY_EN 1u
+
+#define TOS_CFG_TASK_DYNAMIC_CREATE_EN 0u
+
+#define TOS_CFG_EVENT_EN 1u
+
+#define TOS_CFG_MMBLK_EN 1u
+
+#define TOS_CFG_MMHEAP_EN 1u
+
+#define TOS_CFG_MMHEAP_DEFAULT_POOL_SIZE 0x8000
+
+#define TOS_CFG_MUTEX_EN 1u
+
+#define TOS_CFG_TIMER_EN 1u
+
+#define TOS_CFG_PWR_MGR_EN 0u
+
+#define TOS_CFG_TICKLESS_EN 0u
+
+#define TOS_CFG_SEM_EN 1u
+
+#define TOS_CFG_TASK_STACK_DRAUGHT_DEPTH_DETACT_EN 1u
+
+#define TOS_CFG_FAULT_BACKTRACE_EN 0u
+
+#define TOS_CFG_IDLE_TASK_STK_SIZE 512u
+
+#define TOS_CFG_CPU_TICK_PER_SECOND 1000u
+
+#define TOS_CFG_CPU_CLOCK (SystemCoreClock)
+
+#define TOS_CFG_TIMER_AS_PROC 1u
+
+#define TOS_CFG_MAIL_QUEUE_EN 1u
+
+#endif
+
diff --git a/kernel/core/include/tos_version.h b/kernel/core/include/tos_version.h
index 4abd006312b1bc699b35c59c6e16b1a09e75d2e3..84bb76c7bcfaca1ec980d6b070b4a99e5400002c 100644
--- a/kernel/core/include/tos_version.h
+++ b/kernel/core/include/tos_version.h
@@ -24,9 +24,9 @@
// patch is updated for patch changes/bug fixes that should not need user code changes
#define TOS_VERSION_MAJOR 0x02
-#define TOS_VERSION_MINOR 0x03
-#define TOS_VERSION_PATCH 0x01
-#define TOS_VERSION "2.3.1"
+#define TOS_VERSION_MINOR 0x04
+#define TOS_VERSION_PATCH 0x00
+#define TOS_VERSION "2.4.0"
#endif /* _TOS_VERSION_H_ */
diff --git a/net/at/Makefile b/net/at/Makefile
index a82c0e547b2a12941dfd3d5ea095abc8ebf4da8e..5a598109e6303d4288e4ff0a5646d512f6c2e040 100644
--- a/net/at/Makefile
+++ b/net/at/Makefile
@@ -1,34 +1,34 @@
-###################################################################
-#automatic detection QTOP and LOCALDIR
-CUR_DIR := $(patsubst %/,%,$(dir $(realpath $(firstword $(MAKEFILE_LIST)))))
-TRYQTOP := $(shell if [ -n "$$QTOP" ] ; then\
- echo $$QTOP;\
- else\
- cd $(CUR_DIR); while /usr/bin/test ! -d qmk ; do \
- dir=`cd ../;pwd`; \
- if [ "$$dir" = "/" ] ; then \
- echo Cannot find QTOP in $(firstword $(MAKEFILE_LIST)) 1>&2; \
- exit 1; \
- fi ; \
- cd $$dir; \
- done ; \
- pwd; \
- fi)
-QTOP ?= $(realpath ${TRYQTOP})
-
-ifeq ($(QTOP),)
-$(error Please run this in a tree)
-endif
-LOCALDIR = $(patsubst %/,%,$(subst $(realpath $(QTOP))/,,$(CUR_DIR)))
-
-####################################################################
-
-
-TREE_LIB_ENABLE=1
-lib=
-subdirs=
-
-
-include ${QTOP}/qmk/generic/Make.tpl
-
-
+###################################################################
+#automatic detection QTOP and LOCALDIR
+CUR_DIR := $(patsubst %/,%,$(dir $(realpath $(firstword $(MAKEFILE_LIST)))))
+TRYQTOP := $(shell if [ -n "$$QTOP" ] ; then\
+ echo $$QTOP;\
+ else\
+ cd $(CUR_DIR); while /usr/bin/test ! -d qmk ; do \
+ dir=`cd ../;pwd`; \
+ if [ "$$dir" = "/" ] ; then \
+ echo Cannot find QTOP in $(firstword $(MAKEFILE_LIST)) 1>&2; \
+ exit 1; \
+ fi ; \
+ cd $$dir; \
+ done ; \
+ pwd; \
+ fi)
+QTOP ?= $(realpath ${TRYQTOP})
+
+ifeq ($(QTOP),)
+$(error Please run this in a tree)
+endif
+LOCALDIR = $(patsubst %/,%,$(subst $(realpath $(QTOP))/,,$(CUR_DIR)))
+
+####################################################################
+
+
+TREE_LIB_ENABLE=1
+lib=
+subdirs=
+
+
+include ${QTOP}/qmk/generic/Make.tpl
+
+
diff --git a/net/at/include/tos_at.h b/net/at/include/tos_at.h
index fb1326595ac6eee0b08c90a5fe5f257aec1c1e79..329db7a4daa8ca0c6b2106b1317c90077a65e000 100644
--- a/net/at/include/tos_at.h
+++ b/net/at/include/tos_at.h
@@ -1,493 +1,521 @@
-/*----------------------------------------------------------------------------
- * Tencent is pleased to support the open source community by making TencentOS
- * available.
- *
- * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
- * If you have downloaded a copy of the TencentOS binary from Tencent, please
- * note that the TencentOS binary is licensed under the BSD 3-Clause License.
- *
- * If you have downloaded a copy of the TencentOS source code from Tencent,
- * please note that TencentOS source code is licensed under the BSD 3-Clause
- * License, except for the third-party components listed below which are
- * subject to different license terms. Your integration of TencentOS into your
- * own projects may require compliance with the BSD 3-Clause License, as well
- * as the other licenses applicable to the third-party components included
- * within TencentOS.
- *---------------------------------------------------------------------------*/
-
-#ifndef _TOS_AT_H_
-#define _TOS_AT_H_
-
-#include "tos_k.h"
-#include "tos_hal.h"
-
-#define AT_DATA_CHANNEL_NUM 6
-#define AT_DATA_CHANNEL_FIFO_BUFFER_DEFAULT_SIZE (2048 + 1024)
-
-#define AT_UART_RX_FIFO_BUFFER_SIZE (2048 + 1024)
-#define AT_RECV_CACHE_SIZE 2048
-
-#define AT_CMD_BUFFER_SIZE 512
-
-#define AT_PARSER_TASK_STACK_SIZE 2048
-#define AT_PARSER_TASK_PRIO 2
-
-typedef enum at_status_en {
- AT_STATUS_OK,
- AT_STATUS_ERROR,
- AT_STATUS_INVALID_ARGS,
-} at_status_t;
-
-typedef struct at_cache_st {
- uint8_t *buffer;
- size_t buffer_size;
- size_t recv_len;
-} at_cache_t;
-
-typedef enum at_parse_status_en {
- AT_PARSE_STATUS_NONE,
- AT_PARSE_STATUS_NEWLINE,
- AT_PARSE_STATUS_EVENT,
- AT_PARSE_STATUS_EXPECT,
- AT_PARSE_STATUS_OVERFLOW,
- AT_PARSE_STATUS_OK,
- AT_PARSE_STATUS_FAIL,
- AT_PARSE_STATUS_ERROR
-} at_parse_status_t;
-
-typedef enum at_echo_status_en {
- AT_ECHO_STATUS_NONE,
- AT_ECHO_STATUS_OK,
- AT_ECHO_STATUS_FAIL,
- AT_ECHO_STATUS_ERROR,
- AT_ECHO_STATUS_EXPECT,
-} at_echo_status_t;
-
-typedef enum at_channel_status_en {
- AT_CHANNEL_STATUS_NONE, /*< usually means we are try to get a channel status with invalid id */
- AT_CHANNEL_STATUS_HANGING, /*< channel is not used */
- AT_CHANNEL_STATUS_WORKING, /*< channel is being using */
- AT_CHANNEL_STATUS_BROKEN, /*< channel is broken(module link to remote server is broken) */
-} at_channel_status_t;
-
-typedef struct at_data_channel_st {
- uint8_t is_free;
- k_chr_fifo_t rx_fifo;
- uint8_t *rx_fifo_buffer;
- k_mutex_t rx_lock;
-
- at_channel_status_t status;
-
- k_stopwatch_t timer;
-
- const char *remote_ip;
- const char *remote_port;
-} at_data_channel_t;
-
-typedef struct at_echo_st {
- char *buffer;
- size_t buffer_size;
- char *echo_expect;
- int line_num;
- at_echo_status_t status;
- size_t __w_idx;
- int __is_expecting;
- k_sem_t __expect_notify;
- k_sem_t __status_set_notify;
- int __is_fuzzy_match;
-} at_echo_t;
-
-typedef void (*at_event_callback_t)(void);
-
-typedef struct at_event_st {
- const char *event_header;
- at_event_callback_t event_callback;
-} at_event_t;
-
-typedef struct at_agent_st {
- at_data_channel_t data_channel[AT_DATA_CHANNEL_NUM];
-
- at_event_t *event_table;
- size_t event_table_size;
-
- at_echo_t *echo;
-
- k_task_t parser;
- at_cache_t recv_cache;
-
- k_mutex_t global_lock;
-
- char *cmd_buf;
- k_mutex_t cmd_buf_lock;
-
- hal_uart_t uart;
- k_mutex_t uart_tx_lock;
-// k_mutex_t uart_rx_lock;
- k_sem_t uart_rx_sem;
- k_chr_fifo_t uart_rx_fifo;
- uint8_t *uart_rx_fifo_buffer;
-} at_agent_t;
-
-#define AT_AGENT ((at_agent_t *)(&at_agent))
-
-/**
- * @brief Write data to a channel.
- * Write data to a channel with certain id.
- *
- * @attention None
- *
- * @param[in] channel_id id of the channel.
- * @param[in] buffer data buffer to write.
- * @param[in] buffer_len length of the buffer.
- *
- * @return errcode
- * @retval -1 write failed(error).
- * @retval none -1 the number of bytes written.
- */
-__API__ int tos_at_channel_write(int channel_id, uint8_t *buffer, size_t buffer_len);
-
-/**
- * @brief Read data from a channel.
- * Read data from a channel with a timeout.
- *
- * @attention None
- *
- * @param[in] channel_id id of the channel.
- * @param[out] buffer buffer to hold the data read.
- * @param[in] buffer_len length of the buffer.
- * @param[in] timeout timeout.
- *
- * @return errcode
- * @retval -1 read failed(error).
- * @retval none -1 the number of bytes read.
- */
-__API__ int tos_at_channel_read_timed(int channel_id, uint8_t *buffer, size_t buffer_len, uint32_t timeout);
-
-/**
- * @brief Read data from a channel.
- * Read data from a channel.
- *
- * @attention None
- *
- * @param[in] channel_id id of the channel.
- * @param[out] buffer buffer to hold the data read.
- * @param[in] buffer_len length of the buffer.
- *
- * @return errcode
- * @retval -1 read failed(error).
- * @retval none -1 the number of bytes read.
- */
-__API__ int tos_at_channel_read(int channel_id, uint8_t *buffer, size_t buffer_len);
-
-/**
- * @brief Allocate a channel.
- * Allocate a channel with certain id.
- *
- * @attention None
- *
- * @param[in] channel_id id of the channel.
- * @param[in] ip remote ip of the channel.
- * @param[in] port remote port of the channel.
- *
- * @return errcode
- * @retval -1 allocate failed(error).
- * @retval none -1 the id of the channel.
- */
-__API__ int tos_at_channel_alloc_id(int channel_id, const char *ip, const char *port);
-
-/**
- * @brief Allocate a channel.
- * Allocate a channel.
- *
- * @attention None
- *
- * @param[in] ip remote ip of the channel.
- * @param[in] port remote port of the channel.
- *
- * @return errcode
- * @retval -1 allocate failed(error).
- * @retval none -1 the id of the channel.
- */
-__API__ int tos_at_channel_alloc(const char *ip, const char *port);
-
-/**
- * @brief Allocate a channel.
- * Allocate a channel with certain socket buffer size.
- *
- * @attention None
- *
- * @param[in] channel_id id of the channel.
- * @param[in] ip remote ip of the channel.
- * @param[in] port remote port of the channel.
- * @param[in] socket_buffer_size buffer size of the channel.
- *
- * @return errcode
- * @retval -1 allocate failed(error).
- * @retval none -1 the id of the channel.
- */
-__API__ int tos_at_channel_alloc_with_size(const char *ip, const char *port, size_t socket_buffer_size);
-
-/**
- * @brief Free a channel.
- * Free a channel with certain id.
- *
- * @attention None
- *
- * @param[in] channel_id id of the channel.
- *
- * @return errcode
- * @retval -1 free failed(error).
- * @retval 0 free successfully.
- */
-__API__ int tos_at_channel_free(int channel_id);
-
-/**
- * @brief Set channel broken.
- *
- * @attention None
- *
- * @param[in] channel_id id of the channel.
- *
- * @return errcode
- * @retval -1 set failed(error).
- * @retval 0 set successfully.
- */
-__API__ int tos_at_channel_set_broken(int channel_id);
-
-/**
- * @brief Judge whether channel is working.
- *
- * @attention None
- *
- * @param[in] channel_id id of the channel.
- *
- * @return at channel status(type of at_channel_status_t)
- */
-__API__ int tos_at_channel_is_working(int channel_id);
-
-/**
- * @brief Initialize the at framework.
- *
- * @attention None
- *
- * @param[in] uart_port port number of the uart thougth which the module connect to the MCU.
- * @param[in] event_table the listened event table.
- * @param[in] event_table_size the size of the listened event table.
- *
- * @return errcode
- * @retval -1 initialize failed(error).
- * @retval 0 initialize successfully.
- */
-__API__ int tos_at_init(hal_uart_port_t uart_port, at_event_t *event_table, size_t event_table_size);
-
-/**
- * @brief De-initialize the at framework.
- *
- * @attention None
- *
- * @return
-None
- */
-__API__ void tos_at_deinit(void);
-
-/**
- * @brief Create a echo struct.
- *
- * @attention None
- *
- * @param[in] echo pointer to the echo struct.
- * @param[out] buffer buffer to hold the received message from the module.
- * @param[in] buffer_size size of the buffer.
- * @param[in] echo_expect the expected echo message.
- *
- * @return errcode
- * @retval -1 create failed(error).
- * @retval 0 create successfully.
- */
-__API__ int tos_at_echo_create(at_echo_t *echo, char *buffer, size_t buffer_size, char *echo_expect);
-
-/**
- * @brief Create a echo struct with fuzzy matching for expected echo.
- *
- * @attention None
- *
- * @param[in] echo pointer to the echo struct.
- * @param[out] buffer buffer to hold the received message from the module.
- * @param[in] buffer_size size of the buffer.
- * @param[in] echo_expect_contains if the echo message contains echo_expect_contains, it is a matching.
- *
- * @return errcode
- * @retval -1 create failed(error).
- * @retval 0 create successfully.
- */
-__API__ int tos_at_echo_fuzzy_matching_create(at_echo_t *echo, char *buffer, size_t buffer_size, char *echo_expect_contains);
-
-/**
- * @brief Execute an at command.
- *
- * @attention None
- *
- * @param[in] echo pointer to the echo struct.
- * @param[in] timeout command wait timeout .
- * @param[in] cmd at command.
- *
- * @return errcode
- * @retval -1 execute failed(error).
- * @retval 0 execute successfully.
- */
-__API__ int tos_at_cmd_exec(at_echo_t *echo, uint32_t timeout, const char *cmd, ...);
-
-/**
- * @brief Execute an at command.
- * Execute an at command and wait until the expected echo message received or timeout.
- *
- * @attention None
- *
- * @param[in] echo pointer to the echo struct.
- * @param[in] timeout command wait timeout .
- * @param[in] cmd at command.
- *
- * @return errcode
- * @retval -1 execute failed(error).
- * @retval 0 execute successfully.
- */
-__API__ int tos_at_cmd_exec_until(at_echo_t *echo, uint32_t timeout, const char *cmd, ...);
-
-/**
- * @brief Send raw data througth uart.
- *
- * @attention None
- *
- * @param[in] echo pointer to the echo struct.
- * @param[in] timeout command wait timeout .
- * @param[in] buf data to send.
- * @param[in] size size of the buf.
- *
- * @return errcode
- * @retval -1 execute failed(error).
- * @retval 0 execute successfully.
- */
-__API__ int tos_at_raw_data_send(at_echo_t *echo, uint32_t timeout, const uint8_t *buf, size_t size);
-
-/**
- * @brief Send raw data througth uart.
- * Send raw data througth uart and wait until the expected echo message received or timeout.
- *
- * @attention None
- *
- * @param[in] echo pointer to the echo struct.
- * @param[in] timeout command wait timeout .
- * @param[in] buf data to send.
- * @param[in] size size of the buf.
- *
- * @return errcode
- * @retval -1 execute failed(error).
- * @retval 0 execute successfully.
- */
-__API__ int tos_at_raw_data_send_until(at_echo_t *echo, uint32_t timeout, const uint8_t *buf, size_t size);
-
-/**
- * @brief Write byte to the at uart.
- * The function called by the uart interrupt, to put the data from the uart to the at framework.
- *
- * @attention None
- *
- * @param[in] data uart received data.
- *
- * @return None
- */
-__API__ void tos_at_uart_input_byte(uint8_t data);
-
-/**
- * @brief A global lock provided by at framework.
- * The lock usually used to make a atomic function.
- *
- * @attention None
- *
- * @param None.
- *
- * @return errcode
- * @retval -1 pend failed(error).
- * @retval 0 pend successfully.
- */
-__API__ int tos_at_global_lock_pend(void);
-
-/**
- * @brief A global lock provided by at framework.
- * The lock usually used to make a atomic function.
- *
- * @attention None
- *
- * @param None.
- *
- * @return errcode
- * @retval -1 post failed(error).
- * @retval 0 post successfully.
- */
-__API__ int tos_at_global_lock_post(void);
-
-/**
- * @brief Read data from the uart.
- * Read data from the uart, usually called in listened event callback.
- *
- * @attention None
- *
- * @param[out] buffer buffer to hold the data read from the uart.
- * @param[in] buffer_len length of the buffer.
- *
- * @return length of the data read from the uart.
- */
-__API__ int tos_at_uart_read(uint8_t *buffer, size_t buffer_len);
-
-/**
- * @brief Read data from the uart.
- * Read data from the uart until meet a '\n', usually called in listened event callback.
- *
- * @attention None
- *
- * @param[out] buffer buffer to hold the data read from the uart.
- * @param[in] buffer_len length of the buffer.
- *
- * @return length of the data read from the uart.
- */
-__API__ int tos_at_uart_readline(uint8_t *buffer, size_t buffer_len);
-
-/**
- * @brief Read data from the uart.
- * Read data from the uart until no more incoming data, usually called in listened event callback.
- *
- * @attention None
- *
- * @param[out] buffer buffer to hold the data read from the uart.
- * @param[in] buffer_len length of the buffer.
- *
- * @return length of the data read from the uart.
- */
-__API__ int tos_at_uart_drain(uint8_t *buffer, size_t buffer_len);
-
-/**
- * @brief Get the remote ip of a channel.
- * Get the remote ip of a channel with certain id.
- *
- * @attention None
- *
- * @param[in] channel_id id of the channel.
- *
- * @return remote ip of the channel.
- */
-__API__ const char *tos_at_channel_ip_get(int channel_id);
-
-/**
- * @brief Get the remote port of a channel.
- * Get the remote port of a channel with certain id.
- *
- * @attention None
- *
- * @param[in] channel_id id of the channel.
- *
- * @return remote port of the channel.
- */
-__API__ const char *tos_at_channel_port_get(int channel_id);
-
-#endif /* _TOS_AT_H_ */
-
+/*----------------------------------------------------------------------------
+ * Tencent is pleased to support the open source community by making TencentOS
+ * available.
+ *
+ * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
+ * If you have downloaded a copy of the TencentOS binary from Tencent, please
+ * note that the TencentOS binary is licensed under the BSD 3-Clause License.
+ *
+ * If you have downloaded a copy of the TencentOS source code from Tencent,
+ * please note that TencentOS source code is licensed under the BSD 3-Clause
+ * License, except for the third-party components listed below which are
+ * subject to different license terms. Your integration of TencentOS into your
+ * own projects may require compliance with the BSD 3-Clause License, as well
+ * as the other licenses applicable to the third-party components included
+ * within TencentOS.
+ *---------------------------------------------------------------------------*/
+
+#ifndef _TOS_AT_H_
+#define _TOS_AT_H_
+
+#include "tos_k.h"
+#include "tos_hal.h"
+
+#define AT_DATA_CHANNEL_NUM 6
+#define AT_DATA_CHANNEL_FIFO_BUFFER_DEFAULT_SIZE (2048 + 1024)
+
+#define AT_UART_RX_FIFO_BUFFER_SIZE (2048 + 1024)
+#define AT_RECV_CACHE_SIZE 2048
+
+#define AT_CMD_BUFFER_SIZE 512
+
+#define AT_PARSER_TASK_STACK_SIZE 2048
+#define AT_PARSER_TASK_PRIO 2
+
+#define AT_INPUT_TYPE_FRAME_EN 0
+#define AT_FRAME_LEN_MAIL_MAX 5
+
+typedef enum at_status_en {
+ AT_STATUS_OK,
+ AT_STATUS_ERROR,
+ AT_STATUS_INVALID_ARGS,
+} at_status_t;
+
+typedef struct at_cache_st {
+ uint8_t *buffer;
+ size_t buffer_size;
+ size_t recv_len;
+} at_cache_t;
+
+typedef enum at_parse_status_en {
+ AT_PARSE_STATUS_NONE,
+ AT_PARSE_STATUS_NEWLINE,
+ AT_PARSE_STATUS_EVENT,
+ AT_PARSE_STATUS_EXPECT,
+ AT_PARSE_STATUS_OVERFLOW,
+ AT_PARSE_STATUS_OK,
+ AT_PARSE_STATUS_FAIL,
+ AT_PARSE_STATUS_ERROR
+} at_parse_status_t;
+
+typedef enum at_echo_status_en {
+ AT_ECHO_STATUS_NONE,
+ AT_ECHO_STATUS_OK,
+ AT_ECHO_STATUS_FAIL,
+ AT_ECHO_STATUS_ERROR,
+ AT_ECHO_STATUS_EXPECT,
+} at_echo_status_t;
+
+typedef enum at_channel_status_en {
+ AT_CHANNEL_STATUS_NONE, /*< usually means we are try to get a channel status with invalid id */
+ AT_CHANNEL_STATUS_HANGING, /*< channel is not used */
+ AT_CHANNEL_STATUS_WORKING, /*< channel is being using */
+ AT_CHANNEL_STATUS_BROKEN, /*< channel is broken(module link to remote server is broken) */
+} at_channel_status_t;
+
+typedef struct at_data_channel_st {
+ uint8_t is_free;
+ k_chr_fifo_t rx_fifo;
+ uint8_t *rx_fifo_buffer;
+ k_mutex_t rx_lock;
+
+ at_channel_status_t status;
+
+ k_stopwatch_t timer;
+
+ const char *remote_ip;
+ const char *remote_port;
+} at_data_channel_t;
+
+typedef struct at_echo_st {
+ char *buffer;
+ size_t buffer_size;
+ char *echo_expect;
+ int line_num;
+ at_echo_status_t status;
+ size_t __w_idx;
+ int __is_expecting;
+ k_sem_t __expect_notify;
+ k_sem_t __status_set_notify;
+ int __is_fuzzy_match;
+} at_echo_t;
+
+typedef struct at_frame_len_mail_st {
+ uint16_t frame_len;
+} at_frame_len_mail_t;
+
+typedef void (*at_event_callback_t)(void);
+
+typedef struct at_event_st {
+ const char *event_header;
+ at_event_callback_t event_callback;
+} at_event_t;
+
+typedef struct at_agent_st {
+ at_data_channel_t data_channel[AT_DATA_CHANNEL_NUM];
+
+ at_event_t *event_table;
+ size_t event_table_size;
+
+ at_echo_t *echo;
+
+ k_task_t parser;
+ at_cache_t recv_cache;
+
+ k_mutex_t global_lock;
+
+ char *cmd_buf;
+ k_mutex_t cmd_buf_lock;
+
+ hal_uart_t uart;
+ k_mutex_t uart_tx_lock;
+// k_mutex_t uart_rx_lock;
+
+#if AT_INPUT_TYPE_FRAME_EN
+ k_mail_q_t uart_rx_frame_mail;
+ uint8_t *uart_rx_frame_mail_buffer;
+ uint16_t fifo_available_len;
+#else
+ k_sem_t uart_rx_sem;
+#endif /* AT_INPUT_TYPE_FRAME_EN */
+ k_chr_fifo_t uart_rx_fifo;
+ uint8_t *uart_rx_fifo_buffer;
+} at_agent_t;
+
+#define AT_AGENT ((at_agent_t *)(&at_agent))
+
+/**
+ * @brief Write data to a channel.
+ * Write data to a channel with certain id.
+ *
+ * @attention None
+ *
+ * @param[in] channel_id id of the channel.
+ * @param[in] buffer data buffer to write.
+ * @param[in] buffer_len length of the buffer.
+ *
+ * @return errcode
+ * @retval -1 write failed(error).
+ * @retval none -1 the number of bytes written.
+ */
+__API__ int tos_at_channel_write(int channel_id, uint8_t *buffer, size_t buffer_len);
+
+/**
+ * @brief Read data from a channel.
+ * Read data from a channel with a timeout.
+ *
+ * @attention None
+ *
+ * @param[in] channel_id id of the channel.
+ * @param[out] buffer buffer to hold the data read.
+ * @param[in] buffer_len length of the buffer.
+ * @param[in] timeout timeout.
+ *
+ * @return errcode
+ * @retval -1 read failed(error).
+ * @retval none -1 the number of bytes read.
+ */
+__API__ int tos_at_channel_read_timed(int channel_id, uint8_t *buffer, size_t buffer_len, uint32_t timeout);
+
+/**
+ * @brief Read data from a channel.
+ * Read data from a channel.
+ *
+ * @attention None
+ *
+ * @param[in] channel_id id of the channel.
+ * @param[out] buffer buffer to hold the data read.
+ * @param[in] buffer_len length of the buffer.
+ *
+ * @return errcode
+ * @retval -1 read failed(error).
+ * @retval none -1 the number of bytes read.
+ */
+__API__ int tos_at_channel_read(int channel_id, uint8_t *buffer, size_t buffer_len);
+
+/**
+ * @brief Allocate a channel.
+ * Allocate a channel with certain id.
+ *
+ * @attention None
+ *
+ * @param[in] channel_id id of the channel.
+ * @param[in] ip remote ip of the channel.
+ * @param[in] port remote port of the channel.
+ *
+ * @return errcode
+ * @retval -1 allocate failed(error).
+ * @retval none -1 the id of the channel.
+ */
+__API__ int tos_at_channel_alloc_id(int channel_id, const char *ip, const char *port);
+
+/**
+ * @brief Allocate a channel.
+ * Allocate a channel.
+ *
+ * @attention None
+ *
+ * @param[in] ip remote ip of the channel.
+ * @param[in] port remote port of the channel.
+ *
+ * @return errcode
+ * @retval -1 allocate failed(error).
+ * @retval none -1 the id of the channel.
+ */
+__API__ int tos_at_channel_alloc(const char *ip, const char *port);
+
+/**
+ * @brief Allocate a channel.
+ * Allocate a channel with certain socket buffer size.
+ *
+ * @attention None
+ *
+ * @param[in] channel_id id of the channel.
+ * @param[in] ip remote ip of the channel.
+ * @param[in] port remote port of the channel.
+ * @param[in] socket_buffer_size buffer size of the channel.
+ *
+ * @return errcode
+ * @retval -1 allocate failed(error).
+ * @retval none -1 the id of the channel.
+ */
+__API__ int tos_at_channel_alloc_with_size(const char *ip, const char *port, size_t socket_buffer_size);
+
+/**
+ * @brief Free a channel.
+ * Free a channel with certain id.
+ *
+ * @attention None
+ *
+ * @param[in] channel_id id of the channel.
+ *
+ * @return errcode
+ * @retval -1 free failed(error).
+ * @retval 0 free successfully.
+ */
+__API__ int tos_at_channel_free(int channel_id);
+
+/**
+ * @brief Set channel broken.
+ *
+ * @attention None
+ *
+ * @param[in] channel_id id of the channel.
+ *
+ * @return errcode
+ * @retval -1 set failed(error).
+ * @retval 0 set successfully.
+ */
+__API__ int tos_at_channel_set_broken(int channel_id);
+
+/**
+ * @brief Judge whether channel is working.
+ *
+ * @attention None
+ *
+ * @param[in] channel_id id of the channel.
+ *
+ * @return at channel status(type of at_channel_status_t)
+ */
+__API__ int tos_at_channel_is_working(int channel_id);
+
+/**
+ * @brief Initialize the at framework.
+ *
+ * @attention None
+ *
+ * @param[in] uart_port port number of the uart thougth which the module connect to the MCU.
+ * @param[in] event_table the listened event table.
+ * @param[in] event_table_size the size of the listened event table.
+ *
+ * @return errcode
+ * @retval -1 initialize failed(error).
+ * @retval 0 initialize successfully.
+ */
+__API__ int tos_at_init(hal_uart_port_t uart_port, at_event_t *event_table, size_t event_table_size);
+
+/**
+ * @brief De-initialize the at framework.
+ *
+ * @attention None
+ *
+ * @return
+None
+ */
+__API__ void tos_at_deinit(void);
+
+/**
+ * @brief Create a echo struct.
+ *
+ * @attention None
+ *
+ * @param[in] echo pointer to the echo struct.
+ * @param[out] buffer buffer to hold the received message from the module.
+ * @param[in] buffer_size size of the buffer.
+ * @param[in] echo_expect the expected echo message.
+ *
+ * @return errcode
+ * @retval -1 create failed(error).
+ * @retval 0 create successfully.
+ */
+__API__ int tos_at_echo_create(at_echo_t *echo, char *buffer, size_t buffer_size, char *echo_expect);
+
+/**
+ * @brief Create a echo struct with fuzzy matching for expected echo.
+ *
+ * @attention None
+ *
+ * @param[in] echo pointer to the echo struct.
+ * @param[out] buffer buffer to hold the received message from the module.
+ * @param[in] buffer_size size of the buffer.
+ * @param[in] echo_expect_contains if the echo message contains echo_expect_contains, it is a matching.
+ *
+ * @return errcode
+ * @retval -1 create failed(error).
+ * @retval 0 create successfully.
+ */
+__API__ int tos_at_echo_fuzzy_matching_create(at_echo_t *echo, char *buffer, size_t buffer_size, char *echo_expect_contains);
+
+/**
+ * @brief Execute an at command.
+ *
+ * @attention None
+ *
+ * @param[in] echo pointer to the echo struct.
+ * @param[in] timeout command wait timeout .
+ * @param[in] cmd at command.
+ *
+ * @return errcode
+ * @retval -1 execute failed(error).
+ * @retval 0 execute successfully.
+ */
+__API__ int tos_at_cmd_exec(at_echo_t *echo, uint32_t timeout, const char *cmd, ...);
+
+/**
+ * @brief Execute an at command.
+ * Execute an at command and wait until the expected echo message received or timeout.
+ *
+ * @attention None
+ *
+ * @param[in] echo pointer to the echo struct.
+ * @param[in] timeout command wait timeout .
+ * @param[in] cmd at command.
+ *
+ * @return errcode
+ * @retval -1 execute failed(error).
+ * @retval 0 execute successfully.
+ */
+__API__ int tos_at_cmd_exec_until(at_echo_t *echo, uint32_t timeout, const char *cmd, ...);
+
+/**
+ * @brief Send raw data througth uart.
+ *
+ * @attention None
+ *
+ * @param[in] echo pointer to the echo struct.
+ * @param[in] timeout command wait timeout .
+ * @param[in] buf data to send.
+ * @param[in] size size of the buf.
+ *
+ * @return errcode
+ * @retval -1 execute failed(error).
+ * @retval 0 execute successfully.
+ */
+__API__ int tos_at_raw_data_send(at_echo_t *echo, uint32_t timeout, const uint8_t *buf, size_t size);
+
+/**
+ * @brief Send raw data througth uart.
+ * Send raw data througth uart and wait until the expected echo message received or timeout.
+ *
+ * @attention None
+ *
+ * @param[in] echo pointer to the echo struct.
+ * @param[in] timeout command wait timeout .
+ * @param[in] buf data to send.
+ * @param[in] size size of the buf.
+ *
+ * @return errcode
+ * @retval -1 execute failed(error).
+ * @retval 0 execute successfully.
+ */
+__API__ int tos_at_raw_data_send_until(at_echo_t *echo, uint32_t timeout, const uint8_t *buf, size_t size);
+
+#if AT_INPUT_TYPE_FRAME_EN
+/**
+ * @brief Write amount bytes to the at uart.
+ * The function called by the uart interrupt, to put the data from the uart to the at framework.
+ *
+ * @attention None
+ *
+ * @param[in] pdata pointer of the uart received data.
+ * @param[in] len length of the uart received data.
+ *
+ * @return None
+ */
+__API__ void tos_at_uart_input_frame(uint8_t *pdata, uint16_t len);
+#else
+/**
+ * @brief Write byte to the at uart.
+ * The function called by the uart interrupt, to put the data from the uart to the at framework.
+ *
+ * @attention None
+ *
+ * @param[in] data uart received data.
+ *
+ * @return None
+ */
+__API__ void tos_at_uart_input_byte(uint8_t data);
+#endif
+/**
+ * @brief A global lock provided by at framework.
+ * The lock usually used to make a atomic function.
+ *
+ * @attention None
+ *
+ * @param None.
+ *
+ * @return errcode
+ * @retval -1 pend failed(error).
+ * @retval 0 pend successfully.
+ */
+__API__ int tos_at_global_lock_pend(void);
+
+/**
+ * @brief A global lock provided by at framework.
+ * The lock usually used to make a atomic function.
+ *
+ * @attention None
+ *
+ * @param None.
+ *
+ * @return errcode
+ * @retval -1 post failed(error).
+ * @retval 0 post successfully.
+ */
+__API__ int tos_at_global_lock_post(void);
+
+/**
+ * @brief Read data from the uart.
+ * Read data from the uart, usually called in listened event callback.
+ *
+ * @attention None
+ *
+ * @param[out] buffer buffer to hold the data read from the uart.
+ * @param[in] buffer_len length of the buffer.
+ *
+ * @return length of the data read from the uart.
+ */
+__API__ int tos_at_uart_read(uint8_t *buffer, size_t buffer_len);
+
+/**
+ * @brief Read data from the uart.
+ * Read data from the uart until meet a '\n', usually called in listened event callback.
+ *
+ * @attention None
+ *
+ * @param[out] buffer buffer to hold the data read from the uart.
+ * @param[in] buffer_len length of the buffer.
+ *
+ * @return length of the data read from the uart.
+ */
+__API__ int tos_at_uart_readline(uint8_t *buffer, size_t buffer_len);
+
+/**
+ * @brief Read data from the uart.
+ * Read data from the uart until no more incoming data, usually called in listened event callback.
+ *
+ * @attention None
+ *
+ * @param[out] buffer buffer to hold the data read from the uart.
+ * @param[in] buffer_len length of the buffer.
+ *
+ * @return length of the data read from the uart.
+ */
+__API__ int tos_at_uart_drain(uint8_t *buffer, size_t buffer_len);
+
+/**
+ * @brief Get the remote ip of a channel.
+ * Get the remote ip of a channel with certain id.
+ *
+ * @attention None
+ *
+ * @param[in] channel_id id of the channel.
+ *
+ * @return remote ip of the channel.
+ */
+__API__ const char *tos_at_channel_ip_get(int channel_id);
+
+/**
+ * @brief Get the remote port of a channel.
+ * Get the remote port of a channel with certain id.
+ *
+ * @attention None
+ *
+ * @param[in] channel_id id of the channel.
+ *
+ * @return remote port of the channel.
+ */
+__API__ const char *tos_at_channel_port_get(int channel_id);
+
+#endif /* _TOS_AT_H_ */
+
diff --git a/net/at/src/tos_at.c b/net/at/src/tos_at.c
index 93c4b858ba33cfb57efe8b50eda5e1a4182bd027..95931275b580075577cda3d42cd40e82415ba751 100644
--- a/net/at/src/tos_at.c
+++ b/net/at/src/tos_at.c
@@ -1,1026 +1,1097 @@
-/*----------------------------------------------------------------------------
- * Tencent is pleased to support the open source community by making TencentOS
- * available.
- *
- * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
- * If you have downloaded a copy of the TencentOS binary from Tencent, please
- * note that the TencentOS binary is licensed under the BSD 3-Clause License.
- *
- * If you have downloaded a copy of the TencentOS source code from Tencent,
- * please note that TencentOS source code is licensed under the BSD 3-Clause
- * License, except for the third-party components listed below which are
- * subject to different license terms. Your integration of TencentOS into your
- * own projects may require compliance with the BSD 3-Clause License, as well
- * as the other licenses applicable to the third-party components included
- * within TencentOS.
- *---------------------------------------------------------------------------*/
-
-/*
-Note:
- If you find that the AT framework occasionally loses characters,
- this may be caused by the unnecessary critical section of at_channel,
- so you can remove the critical section of ring_queue in tos_ring_queue.c.
- Once you remove, ring queue becomes only a data structure,
- you must use critical section or mutex to protect the data in ring_queue.
-*/
-
-#include "tos_at.h"
-
-__STATIC__ at_agent_t at_agent;
-
-__STATIC__ k_stack_t at_parser_task_stack[AT_PARSER_TASK_STACK_SIZE];
-
-__API__ int tos_at_global_lock_pend(void)
-{
- if (tos_mutex_pend(&AT_AGENT->global_lock) != K_ERR_NONE) {
- return -1;
- }
- return 0;
-}
-
-__API__ int tos_at_global_lock_post(void)
-{
- if (tos_mutex_post(&AT_AGENT->global_lock) != K_ERR_NONE) {
- return -1;
- }
- return 0;
-}
-
-__STATIC__ int at_uart_getchar(uint8_t *data, k_tick_t timeout)
-{
- TOS_CPU_CPSR_ALLOC();
- k_err_t err;
-
- tos_stopwatch_delay(1);
-
- if (tos_sem_pend(&AT_AGENT->uart_rx_sem, timeout) != K_ERR_NONE) {
- return -1;
- }
-
- /*
- the uart_rx_fifo is only read by at_parser task,
- and it will be written in usart interrupt handler,
- so it is more effective to use critical sections.
- */
-
-// if (tos_mutex_pend(&AT_AGENT->uart_rx_lock) != K_ERR_NONE) {
-// return -1;
-// }
-
- TOS_CPU_INT_DISABLE();
-
- err = tos_chr_fifo_pop(&AT_AGENT->uart_rx_fifo, data);
-
- TOS_CPU_INT_ENABLE();
-
-// tos_mutex_post(&AT_AGENT->uart_rx_lock);
-
- return err == K_ERR_NONE ? 0 : -1;
-}
-
-__STATIC__ at_event_t *at_event_do_get(char *buffer, size_t buffer_len)
-{
- int i = 0;
- at_event_t *event_table = K_NULL, *event = K_NULL;
- size_t event_table_size = 0, event_len;
-
- event_table = AT_AGENT->event_table;
- event_table_size = AT_AGENT->event_table_size;
-
- for (i = 0; i < event_table_size; ++i) {
- event = &event_table[i];
- event_len = strlen(event->event_header);
-
- if (buffer_len < event_len) {
- continue;
- }
-
- if (strncmp(event->event_header, buffer, event_len) == 0) {
- return event;
- }
- }
-
- return K_NULL;
-}
-
-__STATIC__ at_event_t *at_get_event(void)
-{
- char *buffer;
- size_t buffer_len;
- at_cache_t *at_cache = K_NULL;
-
- at_cache = &AT_AGENT->recv_cache;
-
- buffer = (char *)at_cache->buffer;
- buffer_len = at_cache->recv_len;
-
- return at_event_do_get(buffer, buffer_len);
-}
-
-__API__ int tos_at_uart_read(uint8_t *buffer, size_t buffer_len)
-{
- uint8_t data;
- size_t read_len = 0;
-
- while (K_TRUE) {
- if (at_uart_getchar(&data, TOS_TIME_FOREVER) != 0) {
- return read_len;
- }
-
- buffer[read_len++] = data;
-
- if (read_len == buffer_len) {
- return buffer_len;
- }
- }
-}
-
-__API__ int tos_at_uart_readline(uint8_t *buffer, size_t buffer_len)
-{
- uint8_t data;
- size_t read_len = 0;
-
- while (K_TRUE) {
- if (at_uart_getchar(&data, TOS_TIME_FOREVER) != 0) {
- return read_len;
- }
-
- buffer[read_len++] = data;
-
- if (data == '\n') {
- return read_len;
- } else if (read_len == buffer_len) {
- return buffer_len;
- }
- }
-}
-
-__API__ int tos_at_uart_drain(uint8_t *buffer, size_t buffer_len)
-{
- uint8_t data;
- size_t read_len = 0;
-
- while (K_TRUE) {
- if (at_uart_getchar(&data, TOS_TIME_NOWAIT) != 0) {
- return read_len;
- }
-
- buffer[read_len++] = data;
-
- if (read_len == buffer_len) {
- return buffer_len;
- }
- }
-}
-
-__STATIC__ int at_is_echo_expect(void)
-{
- char *recv_buffer, *expect;
- size_t recv_buffer_len, expect_len;
- at_echo_t *at_echo = K_NULL;
- at_cache_t *at_cache = K_NULL;
-
- at_echo = AT_AGENT->echo;
-
- if (!at_echo || !at_echo->echo_expect) {
- return 0;
- }
-
- at_cache = &AT_AGENT->recv_cache;
-
- recv_buffer = (char *)at_cache->buffer;
- recv_buffer_len = at_cache->recv_len;
-
- expect = at_echo->echo_expect;
- expect_len = strlen(expect);
-
- if (recv_buffer_len < expect_len) {
- return 0;
- }
-
- if (at_echo->__is_fuzzy_match) {
- if (strstr(recv_buffer, expect) != NULL) {
- return 0;
- }
- return -1;
- }
-
- if (strncmp(expect, recv_buffer, expect_len) == 0) {
- return 1;
- }
-
- return 0;
-}
-
-__STATIC__ at_parse_status_t at_uart_line_parse(void)
-{
- size_t curr_len = 0;
- uint8_t data, last_data = 0;
- at_cache_t *recv_cache = K_NULL;
-
- recv_cache = &AT_AGENT->recv_cache;
-
- recv_cache->recv_len = 0;
- memset(recv_cache->buffer, 0, recv_cache->buffer_size);
-
- while (K_TRUE) {
- if (at_uart_getchar(&data, TOS_TIME_FOREVER) != 0) {
- continue;
- }
-
- if (data == '\0') {
- continue;
- }
-
- if (curr_len < recv_cache->buffer_size) {
- recv_cache->buffer[curr_len++] = data;
- recv_cache->recv_len = curr_len;
- } else {
- recv_cache->buffer[recv_cache->buffer_size - 1] = '\0';
- return AT_PARSE_STATUS_OVERFLOW;
- }
-
- if (at_get_event() != K_NULL) {
- return AT_PARSE_STATUS_EVENT;
- }
-
- if (at_is_echo_expect()) {
- return AT_PARSE_STATUS_EXPECT;
- }
-
- if (strstr((char*)recv_cache->buffer, "OK")) {
- return AT_PARSE_STATUS_OK;
- } else if (strstr((char*)recv_cache->buffer, "FAIL")) {
- return AT_PARSE_STATUS_FAIL;
- } else if (strstr((char*)recv_cache->buffer, "ERROR")) {
- return AT_PARSE_STATUS_ERROR;
- }
-
- if (data == '\n' && last_data == '\r') { // 0xd 0xa
- curr_len -= 1;
- recv_cache->buffer[curr_len - 1] = '\n';
- recv_cache->recv_len = curr_len;
-
- if (curr_len == 1) { // only a blank newline, ignore
- last_data = 0;
- curr_len = 0;
- recv_cache->recv_len = 0;
- continue;
- }
-
- return AT_PARSE_STATUS_NEWLINE;
- }
-
- last_data = data;
- }
-}
-
-__STATIC__ void at_echo_buffer_copy(at_cache_t *at_cache, at_echo_t *echo)
-{
- uint8_t *recv_buffer = K_NULL;
- size_t recv_buffer_len, copy_len, remain_len;
-
- recv_buffer = at_cache->buffer;
- recv_buffer_len = at_cache->recv_len;
-
- remain_len = echo->buffer_size - echo->__w_idx;
- if (remain_len == 0) {
- return;
- }
-
- copy_len = remain_len < recv_buffer_len ? remain_len : recv_buffer_len;
- memcpy(echo->buffer + echo->__w_idx, recv_buffer, copy_len);
- echo->__w_idx += copy_len;
-
- ++echo->line_num;
-}
-
-__STATIC__ void at_parser(void *arg)
-{
- at_echo_t *at_echo = K_NULL;
- at_event_t *at_event = K_NULL;
- at_cache_t *recv_cache = K_NULL;
- at_parse_status_t at_parse_status;
-
- recv_cache = &AT_AGENT->recv_cache;
-
- while (K_TRUE) {
- at_parse_status = at_uart_line_parse();
-
- tos_kprintln("--->%s", recv_cache->buffer);
-
- if (at_parse_status == AT_PARSE_STATUS_OVERFLOW) {
- tos_kprintln("AT parse overflow!");
- continue;
- }
-
- if (at_parse_status == AT_PARSE_STATUS_EVENT) {
- at_event = at_get_event();
- if (at_event && at_event->event_callback) {
- at_event->event_callback();
- }
- continue;
- }
-
- at_echo = AT_AGENT->echo;
- if (!at_echo) {
- continue;
- }
-
- if (at_echo->buffer) {
- at_echo_buffer_copy(recv_cache, at_echo);
- }
-
- if (at_parse_status == AT_PARSE_STATUS_EXPECT) {
- at_echo->status = AT_ECHO_STATUS_EXPECT;
- if (at_echo->__is_expecting) {
- tos_sem_post(&at_echo->__expect_notify);
- }
- } else if (at_parse_status == AT_PARSE_STATUS_OK) {
- at_echo->status = AT_ECHO_STATUS_OK;
- if (!at_echo->__is_expecting) {
- tos_sem_post(&at_echo->__status_set_notify);
- }
- } else if (at_parse_status == AT_PARSE_STATUS_FAIL) {
- at_echo->status = AT_ECHO_STATUS_FAIL;
- if (!at_echo->__is_expecting) {
- tos_sem_post(&at_echo->__status_set_notify);
- }
- } else if (at_parse_status == AT_PARSE_STATUS_ERROR) {
- at_echo->status = AT_ECHO_STATUS_ERROR;
- if (!at_echo->__is_expecting) {
- tos_sem_post(&at_echo->__status_set_notify);
- }
- }
- }
-}
-
-__STATIC__ int at_uart_send(const uint8_t *buf, size_t size, uint32_t timeout)
-{
- int ret;
-
- tos_mutex_pend(&AT_AGENT->uart_tx_lock);
- ret = tos_hal_uart_write(&AT_AGENT->uart, buf, size, timeout);
- tos_mutex_post(&AT_AGENT->uart_tx_lock);
-
- return ret;
-}
-
-__API__ int tos_at_echo_create(at_echo_t *echo, char *buffer, size_t buffer_size, char *echo_expect)
-{
- if (!echo) {
- return -1;
- }
-
- if (buffer) {
- memset(buffer, 0, buffer_size);
- }
-
- echo->buffer = buffer;
- echo->buffer_size = buffer_size;
- echo->echo_expect = echo_expect;
- echo->line_num = 0;
- echo->status = AT_ECHO_STATUS_NONE;
- echo->__w_idx = 0;
- echo->__is_expecting = K_FALSE;
- echo->__is_fuzzy_match = K_FALSE;
- return 0;
-}
-
-__API__ int tos_at_echo_fuzzy_matching_create(at_echo_t *echo, char *buffer, size_t buffer_size, char *echo_expect_contains)
-{
- if (!echo) {
- return -1;
- }
-
- if (buffer) {
- memset(buffer, 0, buffer_size);
- }
-
- echo->buffer = buffer;
- echo->buffer_size = buffer_size;
- echo->echo_expect = echo_expect_contains;
- echo->line_num = 0;
- echo->status = AT_ECHO_STATUS_NONE;
- echo->__w_idx = 0;
- echo->__is_expecting = K_FALSE;
- echo->__is_fuzzy_match = K_TRUE;
- return 0;
-}
-
-__STATIC_INLINE__ void at_echo_flush(at_echo_t *echo)
-{
- echo->line_num = 0;
- echo->status = AT_ECHO_STATUS_NONE;
- echo->__w_idx = 0;
-}
-
-__STATIC_INLINE__ void at_echo_attach(at_echo_t *echo)
-{
- at_echo_flush(echo);
- AT_AGENT->echo = echo;
-}
-
-__API__ int tos_at_raw_data_send(at_echo_t *echo, uint32_t timeout, const uint8_t *buf, size_t size)
-{
- int ret = 0;
-
- if (echo) {
- at_echo_attach(echo);
- }
-
- ret = at_uart_send(buf, size, 0xFFFF);
-
- tos_task_delay(tos_millisec2tick(timeout));
-
- AT_AGENT->echo = K_NULL;
-
- return ret;
-}
-
-__API__ int tos_at_raw_data_send_until(at_echo_t *echo, uint32_t timeout, const uint8_t *buf, size_t size)
-{
- int ret = 0;
-
- if (!echo || !echo->echo_expect) {
- return -1;
- }
-
- if (tos_sem_create(&echo->__expect_notify, 0) != K_ERR_NONE) {
- return -1;
- }
- echo->__is_expecting = K_TRUE;
- at_echo_attach(echo);
-
- ret = at_uart_send(buf, size, 0xFFFF);
-
- if (tos_sem_pend(&echo->__expect_notify, tos_millisec2tick(timeout)) != K_ERR_NONE) {
- ret = -1;
- }
-
- tos_sem_destroy(&echo->__expect_notify);
-
- AT_AGENT->echo = K_NULL;
-
- return ret;
-}
-
-__STATIC__ int at_cmd_do_exec(const char *format, va_list args)
-{
- size_t cmd_len = 0;
-
- if (tos_mutex_pend(&AT_AGENT->cmd_buf_lock) != K_ERR_NONE) {
- return -1;
- }
-
- cmd_len = vsnprintf(AT_AGENT->cmd_buf, AT_CMD_BUFFER_SIZE, format, args);
-
- printf("AT CMD:\n%s\n", AT_AGENT->cmd_buf);
-
- at_uart_send((uint8_t *)AT_AGENT->cmd_buf, cmd_len, 0xFFFF);
-
- tos_mutex_post(&AT_AGENT->cmd_buf_lock);
-
- return 0;
-}
-
-__API__ int tos_at_cmd_exec(at_echo_t *echo, uint32_t timeout, const char *cmd, ...)
-{
- int ret = 0;
- va_list args;
-
- if (!echo) {
- return -1;
- }
-
- if (tos_sem_create(&echo->__status_set_notify, 0) != K_ERR_NONE) {
- return -1;
- }
-
- at_echo_attach(echo);
-
- va_start(args, cmd);
- ret = at_cmd_do_exec(cmd, args);
- va_end(args);
-
- if (ret != 0) {
- AT_AGENT->echo = K_NULL;
- return -1;
- }
-
- if (tos_sem_pend(&echo->__status_set_notify, tos_millisec2tick(timeout)) != K_ERR_NONE) {
- ret = -1;
- }
-
- tos_sem_destroy(&echo->__status_set_notify);
-
- AT_AGENT->echo = K_NULL;
-
- return ret;
-}
-
-__API__ int tos_at_cmd_exec_until(at_echo_t *echo, uint32_t timeout, const char *cmd, ...)
-{
- int ret = 0;
- va_list args;
-
- if (!echo || !echo->echo_expect) {
- return -1;
- }
-
- if (tos_sem_create(&echo->__expect_notify, 0) != K_ERR_NONE) {
- return -1;
- }
- echo->__is_expecting = K_TRUE;
- at_echo_attach(echo);
-
- va_start(args, cmd);
- ret = at_cmd_do_exec(cmd, args);
- va_end(args);
-
- if (ret != 0) {
- AT_AGENT->echo = K_NULL;
- return -1;
- }
-
- if (tos_sem_pend(&echo->__expect_notify, tos_millisec2tick(timeout)) != K_ERR_NONE) {
- ret = -1;
- }
-
- tos_sem_destroy(&echo->__expect_notify);
-
- AT_AGENT->echo = K_NULL;
-
- return ret;
-}
-
-__STATIC__ int at_recv_cache_init(void)
-{
- uint8_t *buffer = K_NULL;
-
- buffer = tos_mmheap_alloc(AT_RECV_CACHE_SIZE);
- if (!buffer) {
- AT_AGENT->recv_cache.buffer = K_NULL;
- return - 1;
- }
-
- AT_AGENT->recv_cache.buffer = buffer;
- AT_AGENT->recv_cache.buffer_size = AT_RECV_CACHE_SIZE;
- AT_AGENT->recv_cache.recv_len = 0;
- return 0;
-}
-
-__STATIC__ void at_recv_cache_deinit(void)
-{
- uint8_t *buffer = K_NULL;
-
- buffer = AT_AGENT->recv_cache.buffer;
- if (buffer) {
- tos_mmheap_free(buffer);
- }
-
- AT_AGENT->recv_cache.buffer = K_NULL;
- AT_AGENT->recv_cache.buffer_size = 0;
- AT_AGENT->recv_cache.recv_len = 0;
-}
-
-__STATIC__ at_data_channel_t *at_channel_get(int channel_id, int is_alloc)
-{
- /*
- if is_alloc is K_TRUE, means we are allocating a channel with certain id,
- data_channel[channel_id] must be free if return none K_NULL.
- otherwise if is_alloc is K_FALSE, means we are trying to get a channel with
- certain id, data_channel[channel_id] must be not free if return none K_NULL.
- */
- at_data_channel_t *data_channel = K_NULL;
-
- if (channel_id < 0 || channel_id >= AT_DATA_CHANNEL_NUM) {
- return K_NULL;
- }
-
- data_channel = &AT_AGENT->data_channel[channel_id];
-
- if (is_alloc && data_channel->is_free) {
- return data_channel;
- }
-
- if (!is_alloc && !data_channel->is_free) {
- return data_channel;
- }
-
- return K_NULL;
-}
-
-__API__ int tos_at_channel_read(int channel_id, uint8_t *buffer, size_t buffer_len)
-{
- int read_len;
- size_t total_read_len = 0;
- at_data_channel_t *data_channel = K_NULL;
-
- data_channel = at_channel_get(channel_id, K_FALSE);
- if (!data_channel || data_channel->status == AT_CHANNEL_STATUS_BROKEN) {
- return -1;
- }
-
- while (K_TRUE) {
- if (tos_mutex_pend(&data_channel->rx_lock) != K_ERR_NONE) {
- return total_read_len;
- }
-
- read_len = tos_chr_fifo_pop_stream(&data_channel->rx_fifo, buffer, buffer_len);
-
- tos_mutex_post(&data_channel->rx_lock);
-
- total_read_len += read_len;
- if (total_read_len < buffer_len) {
- continue;
- } else {
- return buffer_len;
- }
- }
-}
-
-__API__ int tos_at_channel_read_timed(int channel_id, uint8_t *buffer, size_t buffer_len, uint32_t timeout)
-{
- int read_len = 0;
- size_t total_read_len = 0;
- k_tick_t tick, remain_tick;
- at_data_channel_t *data_channel = K_NULL;
-
- data_channel = at_channel_get(channel_id, K_FALSE);
- if (!data_channel || data_channel->status == AT_CHANNEL_STATUS_BROKEN) {
- return -1;
- }
-
- tick = tos_millisec2tick(timeout);
-
- tos_stopwatch_countdown(&data_channel->timer, tick);
- while (!tos_stopwatch_is_expired(&data_channel->timer)) {
- remain_tick = tos_stopwatch_remain(&data_channel->timer);
- if (remain_tick == (k_tick_t)0u) {
- return total_read_len;
- }
-
- if (tos_mutex_pend_timed(&data_channel->rx_lock, remain_tick) != K_ERR_NONE) {
- return total_read_len;
- }
-
- read_len = tos_chr_fifo_pop_stream(&data_channel->rx_fifo, buffer + read_len, buffer_len - total_read_len);
-
- tos_mutex_post(&data_channel->rx_lock);
-
- total_read_len += read_len;
- if (total_read_len < buffer_len) {
- continue;
- } else {
- return buffer_len;
- }
- }
-
- return total_read_len;
-}
-
-__API__ int tos_at_channel_write(int channel_id, uint8_t *buffer, size_t buffer_len)
-{
- int ret;
- at_data_channel_t *data_channel = K_NULL;
-
- data_channel = at_channel_get(channel_id, K_FALSE);
- if (!data_channel) {
- return -1;
- }
-
- if (tos_mutex_pend(&data_channel->rx_lock) != K_ERR_NONE) {
- return -1;
- }
-
- ret = tos_chr_fifo_push_stream(&data_channel->rx_fifo, buffer, buffer_len);
-
- tos_mutex_post(&data_channel->rx_lock);
-
- return ret;
-}
-
-__STATIC_INLINE__ int at_channel_construct(at_data_channel_t *data_channel, const char *ip, const char *port, size_t socket_buffer_size)
-{
- uint8_t *fifo_buffer = K_NULL;
-
- fifo_buffer = tos_mmheap_alloc(socket_buffer_size);
-
- if (!fifo_buffer) {
- return -1;
- }
-
- if (tos_mutex_create(&data_channel->rx_lock) != K_ERR_NONE) {
- goto errout;
- }
-
- if (tos_stopwatch_create(&data_channel->timer) != K_ERR_NONE) {
- goto errout;
- }
-
- data_channel->rx_fifo_buffer = fifo_buffer;
- tos_chr_fifo_create(&data_channel->rx_fifo, fifo_buffer, socket_buffer_size);
- data_channel->remote_ip = ip;
- data_channel->remote_port = port;
-
- data_channel->is_free = K_FALSE;
- data_channel->status = AT_CHANNEL_STATUS_WORKING;
-
- return 0;
-
-errout:
- tos_mmheap_free(fifo_buffer);
- return -1;
-}
-
-__API__ int tos_at_channel_alloc_id(int channel_id, const char *ip, const char *port)
-{
- at_data_channel_t *data_channel = K_NULL;
- size_t socket_buffer_size = 0;
-
- data_channel = at_channel_get(channel_id, K_TRUE);
- if (!data_channel) {
- return -1;
- }
-
- socket_buffer_size = AT_DATA_CHANNEL_FIFO_BUFFER_DEFAULT_SIZE;
- if (at_channel_construct(data_channel, ip, port, socket_buffer_size) != 0) {
- return -1;
- }
-
- return channel_id;
-}
-
-__API__ int tos_at_channel_alloc(const char *ip, const char *port)
-{
- int id = 0;
- at_data_channel_t *data_channel = K_NULL;
- size_t socket_buffer_size = 0;
-
- for (id = 0; id < AT_DATA_CHANNEL_NUM; ++id) {
- data_channel = &AT_AGENT->data_channel[id];
- if (data_channel->is_free) {
- break;
- }
- }
-
- if (id == AT_DATA_CHANNEL_NUM || !data_channel) {
- return -1;
- }
-
- socket_buffer_size = AT_DATA_CHANNEL_FIFO_BUFFER_DEFAULT_SIZE;
- if (at_channel_construct(data_channel, ip, port, socket_buffer_size) != 0) {
- return -1;
- }
-
- return id;
-}
-
-__API__ int tos_at_channel_alloc_with_size(const char *ip, const char *port, size_t socket_buffer_size)
-{
- int id = 0;
- at_data_channel_t *data_channel = K_NULL;
-
- for (id = 0; id < AT_DATA_CHANNEL_NUM; ++id) {
- data_channel = &AT_AGENT->data_channel[id];
- if (data_channel->is_free) {
- break;
- }
- }
-
- if (id == AT_DATA_CHANNEL_NUM || !data_channel) {
- return -1;
- }
-
- if (at_channel_construct(data_channel, ip, port, socket_buffer_size) != 0) {
- return -1;
- }
-
- return id;
-}
-
-__API__ int tos_at_channel_free(int channel_id)
-{
- at_data_channel_t *data_channel = K_NULL;
-
- data_channel = at_channel_get(channel_id, K_FALSE);
- if (!data_channel) {
- return -1;
- }
-
- tos_mutex_destroy(&data_channel->rx_lock);
-
- tos_stopwatch_destroy(&data_channel->timer);
-
- tos_mmheap_free(data_channel->rx_fifo_buffer);
- tos_chr_fifo_destroy(&data_channel->rx_fifo);
-
- memset(data_channel, 0, sizeof(at_data_channel_t));
-
- data_channel->is_free = K_TRUE;
- data_channel->status = AT_CHANNEL_STATUS_HANGING;
-
- return 0;
-}
-
-__API__ int tos_at_channel_set_broken(int channel_id)
-{
- at_data_channel_t *data_channel = K_NULL;
-
- data_channel = at_channel_get(channel_id, K_FALSE);
- if (!data_channel) {
- return -1;
- }
-
- data_channel->status = AT_CHANNEL_STATUS_BROKEN;
- return 0;
-}
-
-__API__ int tos_at_channel_is_working(int channel_id)
-{
- at_data_channel_t *data_channel = K_NULL;
-
- data_channel = at_channel_get(channel_id, K_FALSE);
- return data_channel && data_channel->status == AT_CHANNEL_STATUS_WORKING;
-}
-
-__STATIC__ void at_channel_init(void)
-{
- int i = 0;
-
- for (i = 0; i < AT_DATA_CHANNEL_NUM; ++i) {
- memset(&AT_AGENT->data_channel[i], 0, sizeof(at_data_channel_t));
- AT_AGENT->data_channel[i].is_free = K_TRUE;
- AT_AGENT->data_channel[i].status = AT_CHANNEL_STATUS_HANGING;
- }
-}
-
-__STATIC__ void at_channel_deinit(void)
-{
- int i = 0;
-
- for (i = 0; i < AT_DATA_CHANNEL_NUM; ++i) {
- tos_at_channel_free(i);
- }
-}
-
-__API__ const char *tos_at_channel_ip_get(int channel_id)
-{
- at_data_channel_t *data_channel = K_NULL;
-
- data_channel = at_channel_get(channel_id, K_FALSE);
- if (!data_channel) {
- return K_NULL;
- }
-
- return data_channel->remote_ip;
-}
-
-__API__ const char *tos_at_channel_port_get(int channel_id)
-{
- at_data_channel_t *data_channel = K_NULL;
-
- data_channel = at_channel_get(channel_id, K_FALSE);
- if (!data_channel) {
- return K_NULL;
- }
-
- return data_channel->remote_port;
-}
-
-__STATIC__ void at_event_table_set(at_event_t *event_table, size_t event_table_size)
-{
- AT_AGENT->event_table = event_table;
- AT_AGENT->event_table_size = event_table_size;
-}
-
-__API__ int tos_at_init(hal_uart_port_t uart_port, at_event_t *event_table, size_t event_table_size)
-{
- void *buffer = K_NULL;
-
- memset(AT_AGENT, 0, sizeof(at_agent_t));
-
- at_event_table_set(event_table, event_table_size);
-
- at_channel_init();
-
- buffer = tos_mmheap_alloc(AT_UART_RX_FIFO_BUFFER_SIZE);
- if (!buffer) {
- return -1;
- }
-
- AT_AGENT->uart_rx_fifo_buffer = (uint8_t *)buffer;
- tos_chr_fifo_create(&AT_AGENT->uart_rx_fifo, buffer, AT_UART_RX_FIFO_BUFFER_SIZE);
-
- buffer = tos_mmheap_alloc(AT_CMD_BUFFER_SIZE);
- if (!buffer) {
- goto errout0;
- }
- AT_AGENT->cmd_buf = (char *)buffer;
-
- if (tos_mutex_create(&AT_AGENT->cmd_buf_lock) != K_ERR_NONE) {
- goto errout1;
- }
-
- if (at_recv_cache_init() != 0) {
- goto errout2;
- }
-
- if (tos_sem_create(&AT_AGENT->uart_rx_sem, (k_sem_cnt_t)0u) != K_ERR_NONE) {
- goto errout3;
- }
-
-// if (tos_mutex_create(&AT_AGENT->uart_rx_lock) != K_ERR_NONE) {
-// goto errout4;
-// }
-
- if (tos_mutex_create(&AT_AGENT->uart_tx_lock) != K_ERR_NONE) {
- goto errout5;
- }
-
- if (tos_task_create(&AT_AGENT->parser, "at_parser", at_parser,
- K_NULL, AT_PARSER_TASK_PRIO, at_parser_task_stack,
- AT_PARSER_TASK_STACK_SIZE, 0) != K_ERR_NONE) {
- goto errout6;
- }
-
- if (tos_hal_uart_init(&AT_AGENT->uart, uart_port) != 0) {
- goto errout7;
- }
-
- if (tos_mutex_create(&AT_AGENT->global_lock) != K_ERR_NONE) {
- goto errout8;
- }
-
- return 0;
-
-errout8:
- tos_hal_uart_deinit(&AT_AGENT->uart);
-
-errout7:
- tos_task_destroy(&AT_AGENT->parser);
-
-errout6:
- tos_mutex_destroy(&AT_AGENT->uart_tx_lock);
-
-errout5:
-// tos_mutex_destroy(&AT_AGENT->uart_rx_lock);
-
-//errout4:
- tos_sem_destroy(&AT_AGENT->uart_rx_sem);
-
-errout3:
- at_recv_cache_deinit();
-
-errout2:
- tos_mutex_destroy(&AT_AGENT->cmd_buf_lock);
-
-errout1:
- tos_mmheap_free(AT_AGENT->cmd_buf);
- AT_AGENT->cmd_buf = K_NULL;
-
-errout0:
- tos_mmheap_free(AT_AGENT->uart_rx_fifo_buffer);
- AT_AGENT->uart_rx_fifo_buffer = K_NULL;
- tos_chr_fifo_destroy(&AT_AGENT->uart_rx_fifo);
-
- return -1;
-}
-
-__API__ void tos_at_deinit(void)
-{
- tos_mutex_destroy(&AT_AGENT->global_lock);
-
- tos_hal_uart_deinit(&AT_AGENT->uart);
-
- tos_task_destroy(&AT_AGENT->parser);
-
- tos_mutex_destroy(&AT_AGENT->uart_tx_lock);
-
- tos_sem_destroy(&AT_AGENT->uart_rx_sem);
-
- at_recv_cache_deinit();
-
- tos_mutex_destroy(&AT_AGENT->cmd_buf_lock);
-
- tos_mmheap_free(AT_AGENT->cmd_buf);
- AT_AGENT->cmd_buf = K_NULL;
-
- tos_mmheap_free(AT_AGENT->uart_rx_fifo_buffer);
- AT_AGENT->uart_rx_fifo_buffer = K_NULL;
-
- tos_chr_fifo_destroy(&AT_AGENT->uart_rx_fifo);
-
- at_channel_deinit();
-}
-
-/* To completely decouple the uart intterupt and at agent, we need a more powerful
- hal(driver framework), that would be a huge work, we place it in future plans. */
-__API__ void tos_at_uart_input_byte(uint8_t data)
-{
- if (tos_chr_fifo_push(&AT_AGENT->uart_rx_fifo, data) == K_ERR_NONE) {
- tos_sem_post(&AT_AGENT->uart_rx_sem);
- }
-}
-
+/*----------------------------------------------------------------------------
+ * Tencent is pleased to support the open source community by making TencentOS
+ * available.
+ *
+ * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
+ * If you have downloaded a copy of the TencentOS binary from Tencent, please
+ * note that the TencentOS binary is licensed under the BSD 3-Clause License.
+ *
+ * If you have downloaded a copy of the TencentOS source code from Tencent,
+ * please note that TencentOS source code is licensed under the BSD 3-Clause
+ * License, except for the third-party components listed below which are
+ * subject to different license terms. Your integration of TencentOS into your
+ * own projects may require compliance with the BSD 3-Clause License, as well
+ * as the other licenses applicable to the third-party components included
+ * within TencentOS.
+ *---------------------------------------------------------------------------*/
+
+/*
+Note:
+ If you find that the AT framework occasionally loses characters,
+ this may be caused by the unnecessary critical section of at_channel,
+ so you can remove the critical section of ring_queue in tos_ring_queue.c.
+ Once you remove, ring queue becomes only a data structure,
+ you must use critical section or mutex to protect the data in ring_queue.
+*/
+
+#include "tos_at.h"
+
+__STATIC__ at_agent_t at_agent;
+
+__STATIC__ k_stack_t at_parser_task_stack[AT_PARSER_TASK_STACK_SIZE];
+
+__API__ int tos_at_global_lock_pend(void)
+{
+ if (tos_mutex_pend(&AT_AGENT->global_lock) != K_ERR_NONE) {
+ return -1;
+ }
+ return 0;
+}
+
+__API__ int tos_at_global_lock_post(void)
+{
+ if (tos_mutex_post(&AT_AGENT->global_lock) != K_ERR_NONE) {
+ return -1;
+ }
+ return 0;
+}
+
+__STATIC__ int at_uart_getchar_from_fifo(uint8_t *data)
+{
+ TOS_CPU_CPSR_ALLOC();
+ k_err_t err;
+
+ TOS_CPU_INT_DISABLE();
+ err = tos_chr_fifo_pop(&AT_AGENT->uart_rx_fifo, data);
+ TOS_CPU_INT_ENABLE();
+
+ return err;
+}
+
+__STATIC__ int at_uart_getchar(uint8_t *data, k_tick_t timeout)
+{
+#if AT_INPUT_TYPE_FRAME_EN
+ at_frame_len_mail_t frame_len_mail;
+ size_t mail_size;
+
+ if (AT_AGENT->fifo_available_len == 0) {
+ if (tos_mail_q_pend(&AT_AGENT->uart_rx_frame_mail, &frame_len_mail, &mail_size, timeout) != K_ERR_NONE) {
+ return -1;
+ }
+ AT_AGENT->fifo_available_len = frame_len_mail.frame_len;
+ }
+
+ if (at_uart_getchar_from_fifo(data) != K_ERR_NONE) {
+ return -1;
+ }
+
+ AT_AGENT->fifo_available_len -= 1;
+ return 0;
+#else
+ tos_stopwatch_delay(1);
+
+ if (tos_sem_pend(&AT_AGENT->uart_rx_sem, timeout) != K_ERR_NONE) {
+ return -1;
+ }
+
+ /*
+ the uart_rx_fifo is only read by at_parser task,
+ and it will be written in usart interrupt handler,
+ so it is more effective to use critical sections.
+ */
+
+// if (tos_mutex_pend(&AT_AGENT->uart_rx_lock) != K_ERR_NONE) {
+// return -1;
+// }
+
+ if (at_uart_getchar_from_fifo(data) != K_ERR_NONE) {
+ return -1;
+ }
+
+// tos_mutex_post(&AT_AGENT->uart_rx_lock);
+
+ return 0;
+#endif /* AT_INPUT_TYPE_FRAME_EN */
+}
+
+__STATIC__ at_event_t *at_event_do_get(char *buffer, size_t buffer_len)
+{
+ int i = 0;
+ at_event_t *event_table = K_NULL, *event = K_NULL;
+ size_t event_table_size = 0, event_len;
+
+ event_table = AT_AGENT->event_table;
+ event_table_size = AT_AGENT->event_table_size;
+
+ for (i = 0; i < event_table_size; ++i) {
+ event = &event_table[i];
+ event_len = strlen(event->event_header);
+
+ if (buffer_len < event_len) {
+ continue;
+ }
+
+ if (strncmp(event->event_header, buffer, event_len) == 0) {
+ return event;
+ }
+ }
+
+ return K_NULL;
+}
+
+__STATIC__ at_event_t *at_get_event(void)
+{
+ char *buffer;
+ size_t buffer_len;
+ at_cache_t *at_cache = K_NULL;
+
+ at_cache = &AT_AGENT->recv_cache;
+
+ buffer = (char *)at_cache->buffer;
+ buffer_len = at_cache->recv_len;
+
+ return at_event_do_get(buffer, buffer_len);
+}
+
+__API__ int tos_at_uart_read(uint8_t *buffer, size_t buffer_len)
+{
+ uint8_t data;
+ size_t read_len = 0;
+
+ while (K_TRUE) {
+ if (at_uart_getchar(&data, TOS_TIME_FOREVER) != 0) {
+ return read_len;
+ }
+
+ buffer[read_len++] = data;
+
+ if (read_len == buffer_len) {
+ return buffer_len;
+ }
+ }
+}
+
+__API__ int tos_at_uart_readline(uint8_t *buffer, size_t buffer_len)
+{
+ uint8_t data;
+ size_t read_len = 0;
+
+ while (K_TRUE) {
+ if (at_uart_getchar(&data, TOS_TIME_FOREVER) != 0) {
+ return read_len;
+ }
+
+ buffer[read_len++] = data;
+
+ if (data == '\n') {
+ return read_len;
+ } else if (read_len == buffer_len) {
+ return buffer_len;
+ }
+ }
+}
+
+__API__ int tos_at_uart_drain(uint8_t *buffer, size_t buffer_len)
+{
+ uint8_t data;
+ size_t read_len = 0;
+
+ while (K_TRUE) {
+ if (at_uart_getchar(&data, TOS_TIME_NOWAIT) != 0) {
+ return read_len;
+ }
+
+ buffer[read_len++] = data;
+
+ if (read_len == buffer_len) {
+ return buffer_len;
+ }
+ }
+}
+
+__STATIC__ int at_is_echo_expect(void)
+{
+ char *recv_buffer, *expect;
+ size_t recv_buffer_len, expect_len;
+ at_echo_t *at_echo = K_NULL;
+ at_cache_t *at_cache = K_NULL;
+
+ at_echo = AT_AGENT->echo;
+
+ if (!at_echo || !at_echo->echo_expect) {
+ return 0;
+ }
+
+ at_cache = &AT_AGENT->recv_cache;
+
+ recv_buffer = (char *)at_cache->buffer;
+ recv_buffer_len = at_cache->recv_len;
+
+ expect = at_echo->echo_expect;
+ expect_len = strlen(expect);
+
+ if (recv_buffer_len < expect_len) {
+ return 0;
+ }
+
+ if (at_echo->__is_fuzzy_match) {
+ if (strstr(recv_buffer, expect) != NULL) {
+ return 0;
+ }
+ return -1;
+ }
+
+ if (strncmp(expect, recv_buffer, expect_len) == 0) {
+ return 1;
+ }
+
+ return 0;
+}
+
+__STATIC__ at_parse_status_t at_uart_line_parse(void)
+{
+ size_t curr_len = 0;
+ uint8_t data, last_data = 0;
+ at_cache_t *recv_cache = K_NULL;
+
+ recv_cache = &AT_AGENT->recv_cache;
+
+ recv_cache->recv_len = 0;
+ memset(recv_cache->buffer, 0, recv_cache->buffer_size);
+
+ while (K_TRUE) {
+ if (at_uart_getchar(&data, TOS_TIME_FOREVER) != 0) {
+ continue;
+ }
+
+// if (data == '\0') {
+// continue;
+// }
+
+ if (curr_len < recv_cache->buffer_size) {
+ recv_cache->buffer[curr_len++] = data;
+ recv_cache->recv_len = curr_len;
+ } else {
+ recv_cache->buffer[recv_cache->buffer_size - 1] = '\0';
+ return AT_PARSE_STATUS_OVERFLOW;
+ }
+
+ if (at_get_event() != K_NULL) {
+ return AT_PARSE_STATUS_EVENT;
+ }
+
+ if (at_is_echo_expect()) {
+ return AT_PARSE_STATUS_EXPECT;
+ }
+
+ if (strstr((char*)recv_cache->buffer, "OK")) {
+ return AT_PARSE_STATUS_OK;
+ } else if (strstr((char*)recv_cache->buffer, "FAIL")) {
+ return AT_PARSE_STATUS_FAIL;
+ } else if (strstr((char*)recv_cache->buffer, "ERROR")) {
+ return AT_PARSE_STATUS_ERROR;
+ }
+
+ if (data == '\n' && last_data == '\r') { // 0xd 0xa
+// curr_len -= 1;
+// recv_cache->buffer[curr_len - 1] = '\n';
+// recv_cache->recv_len = curr_len;
+
+ if (curr_len == 2) { // only a blank newline, ignore
+ last_data = 0;
+ curr_len = 0;
+ recv_cache->recv_len = 0;
+ continue;
+ }
+
+ return AT_PARSE_STATUS_NEWLINE;
+ }
+
+ last_data = data;
+ }
+}
+
+__STATIC__ void at_echo_buffer_copy(at_cache_t *at_cache, at_echo_t *echo)
+{
+ uint8_t *recv_buffer = K_NULL;
+ size_t recv_buffer_len, copy_len, remain_len;
+
+ recv_buffer = at_cache->buffer;
+ recv_buffer_len = at_cache->recv_len;
+
+ remain_len = echo->buffer_size - echo->__w_idx;
+ if (remain_len == 0) {
+ return;
+ }
+
+ copy_len = remain_len < recv_buffer_len ? remain_len : recv_buffer_len;
+ memcpy(echo->buffer + echo->__w_idx, recv_buffer, copy_len);
+ echo->__w_idx += copy_len;
+
+ ++echo->line_num;
+}
+
+__STATIC__ void at_parser(void *arg)
+{
+ at_echo_t *at_echo = K_NULL;
+ at_event_t *at_event = K_NULL;
+ at_cache_t *recv_cache = K_NULL;
+ at_parse_status_t at_parse_status;
+
+ recv_cache = &AT_AGENT->recv_cache;
+
+ while (K_TRUE) {
+ at_parse_status = at_uart_line_parse();
+
+ tos_kprintln("--->%s", recv_cache->buffer);
+
+ if (at_parse_status == AT_PARSE_STATUS_OVERFLOW) {
+ tos_kprintln("AT parse overflow!");
+ continue;
+ }
+
+ if (at_parse_status == AT_PARSE_STATUS_EVENT) {
+ at_event = at_get_event();
+ if (at_event && at_event->event_callback) {
+ at_event->event_callback();
+ }
+ continue;
+ }
+
+ at_echo = AT_AGENT->echo;
+ if (!at_echo) {
+ continue;
+ }
+
+ if (at_echo->buffer) {
+ at_echo_buffer_copy(recv_cache, at_echo);
+ }
+
+ if (at_parse_status == AT_PARSE_STATUS_EXPECT) {
+ at_echo->status = AT_ECHO_STATUS_EXPECT;
+ if (at_echo->__is_expecting) {
+ tos_sem_post(&at_echo->__expect_notify);
+ }
+ } else if (at_parse_status == AT_PARSE_STATUS_OK) {
+ at_echo->status = AT_ECHO_STATUS_OK;
+ if (!at_echo->__is_expecting) {
+ tos_sem_post(&at_echo->__status_set_notify);
+ }
+ } else if (at_parse_status == AT_PARSE_STATUS_FAIL) {
+ at_echo->status = AT_ECHO_STATUS_FAIL;
+ if (!at_echo->__is_expecting) {
+ tos_sem_post(&at_echo->__status_set_notify);
+ }
+ } else if (at_parse_status == AT_PARSE_STATUS_ERROR) {
+ at_echo->status = AT_ECHO_STATUS_ERROR;
+ if (!at_echo->__is_expecting) {
+ tos_sem_post(&at_echo->__status_set_notify);
+ }
+ }
+ }
+}
+
+__STATIC__ int at_uart_send(const uint8_t *buf, size_t size, uint32_t timeout)
+{
+ int ret;
+
+ tos_mutex_pend(&AT_AGENT->uart_tx_lock);
+ ret = tos_hal_uart_write(&AT_AGENT->uart, buf, size, timeout);
+ tos_mutex_post(&AT_AGENT->uart_tx_lock);
+
+ return ret;
+}
+
+__API__ int tos_at_echo_create(at_echo_t *echo, char *buffer, size_t buffer_size, char *echo_expect)
+{
+ if (!echo) {
+ return -1;
+ }
+
+ if (buffer) {
+ memset(buffer, 0, buffer_size);
+ }
+
+ echo->buffer = buffer;
+ echo->buffer_size = buffer_size;
+ echo->echo_expect = echo_expect;
+ echo->line_num = 0;
+ echo->status = AT_ECHO_STATUS_NONE;
+ echo->__w_idx = 0;
+ echo->__is_expecting = K_FALSE;
+ echo->__is_fuzzy_match = K_FALSE;
+ return 0;
+}
+
+__API__ int tos_at_echo_fuzzy_matching_create(at_echo_t *echo, char *buffer, size_t buffer_size, char *echo_expect_contains)
+{
+ if (!echo) {
+ return -1;
+ }
+
+ if (buffer) {
+ memset(buffer, 0, buffer_size);
+ }
+
+ echo->buffer = buffer;
+ echo->buffer_size = buffer_size;
+ echo->echo_expect = echo_expect_contains;
+ echo->line_num = 0;
+ echo->status = AT_ECHO_STATUS_NONE;
+ echo->__w_idx = 0;
+ echo->__is_expecting = K_FALSE;
+ echo->__is_fuzzy_match = K_TRUE;
+ return 0;
+}
+
+__STATIC_INLINE__ void at_echo_flush(at_echo_t *echo)
+{
+ echo->line_num = 0;
+ echo->status = AT_ECHO_STATUS_NONE;
+ echo->__w_idx = 0;
+}
+
+__STATIC_INLINE__ void at_echo_attach(at_echo_t *echo)
+{
+ at_echo_flush(echo);
+ AT_AGENT->echo = echo;
+}
+
+__API__ int tos_at_raw_data_send(at_echo_t *echo, uint32_t timeout, const uint8_t *buf, size_t size)
+{
+ int ret = 0;
+
+ if (echo) {
+ at_echo_attach(echo);
+ }
+
+ ret = at_uart_send(buf, size, 0xFFFF);
+
+ tos_task_delay(tos_millisec2tick(timeout));
+
+ AT_AGENT->echo = K_NULL;
+
+ return ret;
+}
+
+__API__ int tos_at_raw_data_send_until(at_echo_t *echo, uint32_t timeout, const uint8_t *buf, size_t size)
+{
+ int ret = 0;
+
+ if (!echo || !echo->echo_expect) {
+ return -1;
+ }
+
+ if (tos_sem_create(&echo->__expect_notify, 0) != K_ERR_NONE) {
+ return -1;
+ }
+ echo->__is_expecting = K_TRUE;
+ at_echo_attach(echo);
+
+ ret = at_uart_send(buf, size, 0xFFFF);
+
+ if (tos_sem_pend(&echo->__expect_notify, tos_millisec2tick(timeout)) != K_ERR_NONE) {
+ ret = -1;
+ }
+
+ tos_sem_destroy(&echo->__expect_notify);
+
+ AT_AGENT->echo = K_NULL;
+
+ return ret;
+}
+
+__STATIC__ int at_cmd_do_exec(const char *format, va_list args)
+{
+ size_t cmd_len = 0;
+
+ if (tos_mutex_pend(&AT_AGENT->cmd_buf_lock) != K_ERR_NONE) {
+ return -1;
+ }
+
+ cmd_len = vsnprintf(AT_AGENT->cmd_buf, AT_CMD_BUFFER_SIZE, format, args);
+
+ tos_kprintln("AT CMD:\n%s\n", AT_AGENT->cmd_buf);
+
+ at_uart_send((uint8_t *)AT_AGENT->cmd_buf, cmd_len, 0xFFFF);
+
+ tos_mutex_post(&AT_AGENT->cmd_buf_lock);
+
+ return 0;
+}
+
+__API__ int tos_at_cmd_exec(at_echo_t *echo, uint32_t timeout, const char *cmd, ...)
+{
+ int ret = 0;
+ va_list args;
+
+ if (!echo) {
+ return -1;
+ }
+
+ if (tos_sem_create(&echo->__status_set_notify, 0) != K_ERR_NONE) {
+ return -1;
+ }
+
+ at_echo_attach(echo);
+
+ va_start(args, cmd);
+ ret = at_cmd_do_exec(cmd, args);
+ va_end(args);
+
+ if (ret != 0) {
+ AT_AGENT->echo = K_NULL;
+ return -1;
+ }
+
+ if (tos_sem_pend(&echo->__status_set_notify, tos_millisec2tick(timeout)) != K_ERR_NONE) {
+ ret = -1;
+ }
+
+ tos_sem_destroy(&echo->__status_set_notify);
+
+ AT_AGENT->echo = K_NULL;
+
+ return ret;
+}
+
+__API__ int tos_at_cmd_exec_until(at_echo_t *echo, uint32_t timeout, const char *cmd, ...)
+{
+ int ret = 0;
+ va_list args;
+
+ if (!echo || !echo->echo_expect) {
+ return -1;
+ }
+
+ if (tos_sem_create(&echo->__expect_notify, 0) != K_ERR_NONE) {
+ return -1;
+ }
+ echo->__is_expecting = K_TRUE;
+ at_echo_attach(echo);
+
+ va_start(args, cmd);
+ ret = at_cmd_do_exec(cmd, args);
+ va_end(args);
+
+ if (ret != 0) {
+ AT_AGENT->echo = K_NULL;
+ return -1;
+ }
+
+ if (tos_sem_pend(&echo->__expect_notify, tos_millisec2tick(timeout)) != K_ERR_NONE) {
+ ret = -1;
+ }
+
+ tos_sem_destroy(&echo->__expect_notify);
+
+ AT_AGENT->echo = K_NULL;
+
+ return ret;
+}
+
+__STATIC__ int at_recv_cache_init(void)
+{
+ uint8_t *buffer = K_NULL;
+
+ buffer = tos_mmheap_alloc(AT_RECV_CACHE_SIZE);
+ if (!buffer) {
+ AT_AGENT->recv_cache.buffer = K_NULL;
+ return - 1;
+ }
+
+ AT_AGENT->recv_cache.buffer = buffer;
+ AT_AGENT->recv_cache.buffer_size = AT_RECV_CACHE_SIZE;
+ AT_AGENT->recv_cache.recv_len = 0;
+ return 0;
+}
+
+__STATIC__ void at_recv_cache_deinit(void)
+{
+ uint8_t *buffer = K_NULL;
+
+ buffer = AT_AGENT->recv_cache.buffer;
+ if (buffer) {
+ tos_mmheap_free(buffer);
+ }
+
+ AT_AGENT->recv_cache.buffer = K_NULL;
+ AT_AGENT->recv_cache.buffer_size = 0;
+ AT_AGENT->recv_cache.recv_len = 0;
+}
+
+__STATIC__ at_data_channel_t *at_channel_get(int channel_id, int is_alloc)
+{
+ /*
+ if is_alloc is K_TRUE, means we are allocating a channel with certain id,
+ data_channel[channel_id] must be free if return none K_NULL.
+ otherwise if is_alloc is K_FALSE, means we are trying to get a channel with
+ certain id, data_channel[channel_id] must be not free if return none K_NULL.
+ */
+ at_data_channel_t *data_channel = K_NULL;
+
+ if (channel_id < 0 || channel_id >= AT_DATA_CHANNEL_NUM) {
+ return K_NULL;
+ }
+
+ data_channel = &AT_AGENT->data_channel[channel_id];
+
+ if (is_alloc && data_channel->is_free) {
+ return data_channel;
+ }
+
+ if (!is_alloc && !data_channel->is_free) {
+ return data_channel;
+ }
+
+ return K_NULL;
+}
+
+__API__ int tos_at_channel_read(int channel_id, uint8_t *buffer, size_t buffer_len)
+{
+ int read_len;
+ size_t total_read_len = 0;
+ at_data_channel_t *data_channel = K_NULL;
+
+ data_channel = at_channel_get(channel_id, K_FALSE);
+ if (!data_channel || data_channel->status == AT_CHANNEL_STATUS_BROKEN) {
+ return -1;
+ }
+
+ while (K_TRUE) {
+ if (tos_mutex_pend(&data_channel->rx_lock) != K_ERR_NONE) {
+ return total_read_len;
+ }
+
+ read_len = tos_chr_fifo_pop_stream(&data_channel->rx_fifo, buffer, buffer_len);
+
+ tos_mutex_post(&data_channel->rx_lock);
+
+ total_read_len += read_len;
+ if (total_read_len < buffer_len) {
+ continue;
+ } else {
+ return buffer_len;
+ }
+ }
+}
+
+__API__ int tos_at_channel_read_timed(int channel_id, uint8_t *buffer, size_t buffer_len, uint32_t timeout)
+{
+ int read_len = 0;
+ size_t total_read_len = 0;
+ k_tick_t tick, remain_tick;
+ at_data_channel_t *data_channel = K_NULL;
+
+ data_channel = at_channel_get(channel_id, K_FALSE);
+ if (!data_channel || data_channel->status == AT_CHANNEL_STATUS_BROKEN) {
+ return -1;
+ }
+
+ tick = tos_millisec2tick(timeout);
+
+ tos_stopwatch_countdown(&data_channel->timer, tick);
+ while (!tos_stopwatch_is_expired(&data_channel->timer)) {
+ remain_tick = tos_stopwatch_remain(&data_channel->timer);
+ if (remain_tick == (k_tick_t)0u) {
+ return total_read_len;
+ }
+
+ if (tos_mutex_pend_timed(&data_channel->rx_lock, remain_tick) != K_ERR_NONE) {
+ return total_read_len;
+ }
+
+ read_len = tos_chr_fifo_pop_stream(&data_channel->rx_fifo, buffer + read_len, buffer_len - total_read_len);
+
+ tos_mutex_post(&data_channel->rx_lock);
+
+ total_read_len += read_len;
+ if (total_read_len < buffer_len) {
+ continue;
+ } else {
+ return buffer_len;
+ }
+ }
+
+ return total_read_len;
+}
+
+__API__ int tos_at_channel_write(int channel_id, uint8_t *buffer, size_t buffer_len)
+{
+ int ret;
+ at_data_channel_t *data_channel = K_NULL;
+
+ data_channel = at_channel_get(channel_id, K_FALSE);
+ if (!data_channel) {
+ return -1;
+ }
+
+ if (tos_mutex_pend(&data_channel->rx_lock) != K_ERR_NONE) {
+ return -1;
+ }
+
+ ret = tos_chr_fifo_push_stream(&data_channel->rx_fifo, buffer, buffer_len);
+
+ tos_mutex_post(&data_channel->rx_lock);
+
+ return ret;
+}
+
+__STATIC_INLINE__ int at_channel_construct(at_data_channel_t *data_channel, const char *ip, const char *port, size_t socket_buffer_size)
+{
+ uint8_t *fifo_buffer = K_NULL;
+
+ fifo_buffer = tos_mmheap_alloc(socket_buffer_size);
+
+ if (!fifo_buffer) {
+ return -1;
+ }
+
+ if (tos_mutex_create(&data_channel->rx_lock) != K_ERR_NONE) {
+ goto errout;
+ }
+
+ if (tos_stopwatch_create(&data_channel->timer) != K_ERR_NONE) {
+ goto errout;
+ }
+
+ data_channel->rx_fifo_buffer = fifo_buffer;
+ tos_chr_fifo_create(&data_channel->rx_fifo, fifo_buffer, socket_buffer_size);
+ data_channel->remote_ip = ip;
+ data_channel->remote_port = port;
+
+ data_channel->is_free = K_FALSE;
+ data_channel->status = AT_CHANNEL_STATUS_WORKING;
+
+ return 0;
+
+errout:
+ tos_mmheap_free(fifo_buffer);
+ return -1;
+}
+
+__API__ int tos_at_channel_alloc_id(int channel_id, const char *ip, const char *port)
+{
+ at_data_channel_t *data_channel = K_NULL;
+ size_t socket_buffer_size = 0;
+
+ data_channel = at_channel_get(channel_id, K_TRUE);
+ if (!data_channel) {
+ return -1;
+ }
+
+ socket_buffer_size = AT_DATA_CHANNEL_FIFO_BUFFER_DEFAULT_SIZE;
+ if (at_channel_construct(data_channel, ip, port, socket_buffer_size) != 0) {
+ return -1;
+ }
+
+ return channel_id;
+}
+
+__API__ int tos_at_channel_alloc(const char *ip, const char *port)
+{
+ int id = 0;
+ at_data_channel_t *data_channel = K_NULL;
+ size_t socket_buffer_size = 0;
+
+ for (id = 0; id < AT_DATA_CHANNEL_NUM; ++id) {
+ data_channel = &AT_AGENT->data_channel[id];
+ if (data_channel->is_free) {
+ break;
+ }
+ }
+
+ if (id == AT_DATA_CHANNEL_NUM || !data_channel) {
+ return -1;
+ }
+
+ socket_buffer_size = AT_DATA_CHANNEL_FIFO_BUFFER_DEFAULT_SIZE;
+ if (at_channel_construct(data_channel, ip, port, socket_buffer_size) != 0) {
+ return -1;
+ }
+
+ return id;
+}
+
+__API__ int tos_at_channel_alloc_with_size(const char *ip, const char *port, size_t socket_buffer_size)
+{
+ int id = 0;
+ at_data_channel_t *data_channel = K_NULL;
+
+ for (id = 0; id < AT_DATA_CHANNEL_NUM; ++id) {
+ data_channel = &AT_AGENT->data_channel[id];
+ if (data_channel->is_free) {
+ break;
+ }
+ }
+
+ if (id == AT_DATA_CHANNEL_NUM || !data_channel) {
+ return -1;
+ }
+
+ if (at_channel_construct(data_channel, ip, port, socket_buffer_size) != 0) {
+ return -1;
+ }
+
+ return id;
+}
+
+__API__ int tos_at_channel_free(int channel_id)
+{
+ at_data_channel_t *data_channel = K_NULL;
+
+ data_channel = at_channel_get(channel_id, K_FALSE);
+ if (!data_channel) {
+ return -1;
+ }
+
+ tos_mutex_destroy(&data_channel->rx_lock);
+
+ tos_stopwatch_destroy(&data_channel->timer);
+
+ tos_mmheap_free(data_channel->rx_fifo_buffer);
+ tos_chr_fifo_destroy(&data_channel->rx_fifo);
+
+ memset(data_channel, 0, sizeof(at_data_channel_t));
+
+ data_channel->is_free = K_TRUE;
+ data_channel->status = AT_CHANNEL_STATUS_HANGING;
+
+ return 0;
+}
+
+__API__ int tos_at_channel_set_broken(int channel_id)
+{
+ at_data_channel_t *data_channel = K_NULL;
+
+ data_channel = at_channel_get(channel_id, K_FALSE);
+ if (!data_channel) {
+ return -1;
+ }
+
+ data_channel->status = AT_CHANNEL_STATUS_BROKEN;
+ return 0;
+}
+
+__API__ int tos_at_channel_is_working(int channel_id)
+{
+ at_data_channel_t *data_channel = K_NULL;
+
+ data_channel = at_channel_get(channel_id, K_FALSE);
+ return data_channel && data_channel->status == AT_CHANNEL_STATUS_WORKING;
+}
+
+__STATIC__ void at_channel_init(void)
+{
+ int i = 0;
+
+ for (i = 0; i < AT_DATA_CHANNEL_NUM; ++i) {
+ memset(&AT_AGENT->data_channel[i], 0, sizeof(at_data_channel_t));
+ AT_AGENT->data_channel[i].is_free = K_TRUE;
+ AT_AGENT->data_channel[i].status = AT_CHANNEL_STATUS_HANGING;
+ }
+}
+
+__STATIC__ void at_channel_deinit(void)
+{
+ int i = 0;
+
+ for (i = 0; i < AT_DATA_CHANNEL_NUM; ++i) {
+ tos_at_channel_free(i);
+ }
+}
+
+__API__ const char *tos_at_channel_ip_get(int channel_id)
+{
+ at_data_channel_t *data_channel = K_NULL;
+
+ data_channel = at_channel_get(channel_id, K_FALSE);
+ if (!data_channel) {
+ return K_NULL;
+ }
+
+ return data_channel->remote_ip;
+}
+
+__API__ const char *tos_at_channel_port_get(int channel_id)
+{
+ at_data_channel_t *data_channel = K_NULL;
+
+ data_channel = at_channel_get(channel_id, K_FALSE);
+ if (!data_channel) {
+ return K_NULL;
+ }
+
+ return data_channel->remote_port;
+}
+
+__STATIC__ void at_event_table_set(at_event_t *event_table, size_t event_table_size)
+{
+ AT_AGENT->event_table = event_table;
+ AT_AGENT->event_table_size = event_table_size;
+}
+
+__API__ int tos_at_init(hal_uart_port_t uart_port, at_event_t *event_table, size_t event_table_size)
+{
+ void *buffer = K_NULL;
+
+ memset(AT_AGENT, 0, sizeof(at_agent_t));
+
+ at_event_table_set(event_table, event_table_size);
+
+ at_channel_init();
+
+ buffer = tos_mmheap_alloc(AT_UART_RX_FIFO_BUFFER_SIZE);
+ if (!buffer) {
+ return -1;
+ }
+
+ AT_AGENT->uart_rx_fifo_buffer = (uint8_t *)buffer;
+ tos_chr_fifo_create(&AT_AGENT->uart_rx_fifo, buffer, AT_UART_RX_FIFO_BUFFER_SIZE);
+
+ buffer = tos_mmheap_alloc(AT_CMD_BUFFER_SIZE);
+ if (!buffer) {
+ goto errout0;
+ }
+ AT_AGENT->cmd_buf = (char *)buffer;
+
+ if (tos_mutex_create(&AT_AGENT->cmd_buf_lock) != K_ERR_NONE) {
+ goto errout1;
+ }
+
+ if (at_recv_cache_init() != 0) {
+ goto errout2;
+ }
+
+#if AT_INPUT_TYPE_FRAME_EN
+ buffer = tos_mmheap_alloc(AT_FRAME_LEN_MAIL_MAX * sizeof(at_frame_len_mail_t));
+ if (!buffer) {
+ goto errout3;
+ }
+
+ AT_AGENT->uart_rx_frame_mail_buffer = (uint8_t *)buffer;
+
+ if (tos_mail_q_create(&AT_AGENT->uart_rx_frame_mail, buffer, AT_FRAME_LEN_MAIL_MAX, sizeof(at_frame_len_mail_t)) != K_ERR_NONE) {
+ goto errout4;
+ }
+#else
+ if (tos_sem_create(&AT_AGENT->uart_rx_sem, (k_sem_cnt_t)0u) != K_ERR_NONE) {
+ goto errout3;
+ }
+#endif /* AT_INPUT_TYPE_FRAME_EN */
+
+// if (tos_mutex_create(&AT_AGENT->uart_rx_lock) != K_ERR_NONE) {
+// goto errout5;
+// }
+
+ if (tos_mutex_create(&AT_AGENT->uart_tx_lock) != K_ERR_NONE) {
+ goto errout6;
+ }
+
+ if (tos_mutex_create(&AT_AGENT->global_lock) != K_ERR_NONE) {
+ goto errout7;
+ }
+
+ if (tos_hal_uart_init(&AT_AGENT->uart, uart_port) != 0) {
+ goto errout8;
+ }
+
+ if (tos_task_create(&AT_AGENT->parser, "at_parser", at_parser,
+ K_NULL, AT_PARSER_TASK_PRIO, at_parser_task_stack,
+ AT_PARSER_TASK_STACK_SIZE, 0) != K_ERR_NONE) {
+ goto errout9;
+ }
+
+ return 0;
+errout9:
+ tos_hal_uart_deinit(&AT_AGENT->uart);
+
+errout8:
+ tos_mutex_destroy(&AT_AGENT->global_lock);
+
+errout7:
+ tos_mutex_destroy(&AT_AGENT->uart_tx_lock);
+
+errout6:
+// tos_mutex_destroy(&AT_AGENT->uart_rx_lock);
+
+//errout5:
+#if AT_INPUT_TYPE_FRAME_EN
+ tos_mail_q_destroy(&AT_AGENT->uart_rx_frame_mail);
+#else
+ tos_sem_destroy(&AT_AGENT->uart_rx_sem);
+#endif /* AT_INPUT_TYPE_FRAME_EN */
+
+#if AT_INPUT_TYPE_FRAME_EN
+errout4:
+ tos_mmheap_free(AT_AGENT->uart_rx_frame_mail_buffer);
+ AT_AGENT->uart_rx_frame_mail_buffer = K_NULL;
+#endif /* AT_INPUT_TYPE_FRAME_EN */
+
+errout3:
+ at_recv_cache_deinit();
+
+errout2:
+ tos_mutex_destroy(&AT_AGENT->cmd_buf_lock);
+
+errout1:
+ tos_mmheap_free(AT_AGENT->cmd_buf);
+ AT_AGENT->cmd_buf = K_NULL;
+
+errout0:
+ tos_mmheap_free(AT_AGENT->uart_rx_fifo_buffer);
+ AT_AGENT->uart_rx_fifo_buffer = K_NULL;
+ tos_chr_fifo_destroy(&AT_AGENT->uart_rx_fifo);
+
+ return -1;
+}
+
+__API__ void tos_at_deinit(void)
+{
+ tos_task_destroy(&AT_AGENT->parser);
+
+ tos_hal_uart_deinit(&AT_AGENT->uart);
+
+ tos_mutex_destroy(&AT_AGENT->global_lock);
+
+ tos_mutex_destroy(&AT_AGENT->uart_tx_lock);
+
+ //tos_mutex_destroy(&AT_AGENT->uart_tx_lock);
+
+#if AT_INPUT_TYPE_FRAME_EN
+ tos_mail_q_destroy(&AT_AGENT->uart_rx_frame_mail);
+ tos_mmheap_free(AT_AGENT->uart_rx_frame_mail_buffer);
+ AT_AGENT->uart_rx_frame_mail_buffer = K_NULL;
+#else
+ tos_sem_destroy(&AT_AGENT->uart_rx_sem);
+#endif /* AT_INPUT_TYPE_FRAME_EN */
+
+ at_recv_cache_deinit();
+
+ tos_mutex_destroy(&AT_AGENT->cmd_buf_lock);
+
+ tos_mmheap_free(AT_AGENT->cmd_buf);
+ AT_AGENT->cmd_buf = K_NULL;
+
+ tos_mmheap_free(AT_AGENT->uart_rx_fifo_buffer);
+ AT_AGENT->uart_rx_fifo_buffer = K_NULL;
+
+ tos_chr_fifo_destroy(&AT_AGENT->uart_rx_fifo);
+
+ at_channel_deinit();
+}
+
+/* To completely decouple the uart intterupt and at agent, we need a more powerful
+ hal(driver framework), that would be a huge work, we place it in future plans. */
+#if AT_INPUT_TYPE_FRAME_EN
+__API__ void tos_at_uart_input_frame(uint8_t *pdata, uint16_t len)
+{
+ int ret;
+ at_frame_len_mail_t at_frame_len_mail;
+
+ ret = tos_chr_fifo_push_stream(&AT_AGENT->uart_rx_fifo, pdata, len);
+ if (ret != len) {
+ return;
+ }
+
+ at_frame_len_mail.frame_len = len;
+ tos_mail_q_post(&AT_AGENT->uart_rx_frame_mail, &at_frame_len_mail, sizeof(at_frame_len_mail_t));
+}
+#else
+__API__ void tos_at_uart_input_byte(uint8_t data)
+{
+ if (tos_chr_fifo_push(&AT_AGENT->uart_rx_fifo, data) == K_ERR_NONE) {
+ tos_sem_post(&AT_AGENT->uart_rx_sem);
+ }
+}
+#endif /* AT_INPUT_TYPE_FRAME_EN */