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 */