提交 3aaafde7 编写于 作者: M mculover666

add frame input type of at,update version to 2.4.0

上级 a1cdea57
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file stm32l4xx_it.c
* @brief Interrupt Service Routines.
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2019 STMicroelectronics.
* All rights reserved.</center></h2>
*
* 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
*
* <h2><center>&copy; Copyright (c) 2019 STMicroelectronics.
* All rights reserved.</center></h2>
*
* 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****/
/**
******************************************************************************
* File Name : USART.c
* Description : This file provides code for the configuration
* of the USART instances.
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2019 STMicroelectronics.
* All rights reserved.</center></h2>
*
* 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
*
* <h2><center>&copy; Copyright (c) 2019 STMicroelectronics.
* All rights reserved.</center></h2>
*
* 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****/
#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
......@@ -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_ */
###################################################################
#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
/*----------------------------------------------------------------------------
* 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_ */
/*----------------------------------------------------------------------------
* 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 */
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册