930 lines
20 KiB
C
930 lines
20 KiB
C
|
|
||
|
#include <stdio.h>
|
||
|
#include <stdarg.h>
|
||
|
#include <string.h>
|
||
|
|
||
|
#include "cli.h"
|
||
|
#include <os/os.h>
|
||
|
#include <common/bk_compiler.h>
|
||
|
#include "shell_drv.h"
|
||
|
#include <components/ate.h>
|
||
|
#include <modules/pm.h>
|
||
|
#include <driver/gpio.h>
|
||
|
|
||
|
#if CONFIG_AT
|
||
|
#include "atsvr_unite.h"
|
||
|
#if CONFIG_AT_DATA_MODE
|
||
|
#include "../../../components/at/inc/at_sal_ex.h"
|
||
|
#endif
|
||
|
#endif
|
||
|
|
||
|
#if 0//def CONFIG_SYS_CPU0
|
||
|
|
||
|
const uart_config_t at_config =
|
||
|
{
|
||
|
.baud_rate = UART_BAUD_RATE,
|
||
|
.data_bits = UART_DATA_8_BITS,
|
||
|
.parity = UART_PARITY_NONE,
|
||
|
.stop_bits = UART_STOP_BITS_1,
|
||
|
.flow_ctrl = UART_FLOWCTRL_DISABLE,
|
||
|
.src_clk = UART_SCLK_XTAL_26M,
|
||
|
|
||
|
};
|
||
|
#endif
|
||
|
//#define ATSVR_TAG "atsvr"
|
||
|
|
||
|
#define DEV_UART 1
|
||
|
#define DEV_MAILBOX 2
|
||
|
|
||
|
#if CONFIG_SYS_PRINT_DEV_UART
|
||
|
#define CMD_DEV DEV_UART
|
||
|
#elif CONFIG_SYS_PRINT_DEV_MAILBOX
|
||
|
#define CMD_DEV DEV_MAILBOX
|
||
|
#endif
|
||
|
|
||
|
#if (CONFIG_SYS_CPU0)
|
||
|
#if CONFIG_MAILBOX
|
||
|
#define FWD_CMD_TO_SLAVE
|
||
|
#define RECV_CMD_LOG_FROM_SLAVE
|
||
|
#endif
|
||
|
#endif
|
||
|
|
||
|
#if defined(FWD_CMD_TO_SLAVE)
|
||
|
#define SLAVE_RSP_BLK_ID 0
|
||
|
#define SLAVE_IND_BLK_ID 1
|
||
|
#endif
|
||
|
|
||
|
#define ATSVR_WAIT_OUT_TIME (2000) // 2s.
|
||
|
|
||
|
#define ATSVR_TASK_WAIT_TIME (100) // 100ms
|
||
|
#define ATSVR_TASK_WAKE_CYCLE (20) // 2s
|
||
|
|
||
|
#define ATSVR_EVENT_RX_IND 0x02
|
||
|
|
||
|
#if (CMD_DEV == DEV_MAILBOX)
|
||
|
#define ATSVR_RX_BUF_LEN 140
|
||
|
#endif
|
||
|
#if (CMD_DEV == DEV_UART)
|
||
|
#define ATSVR_RX_BUF_LEN 4
|
||
|
#endif
|
||
|
|
||
|
#if CONFIG_AT_DATA_MODE
|
||
|
#define ATSVR_CMD_BUF_LEN 4096
|
||
|
#else
|
||
|
#define ATSVR_CMD_BUF_LEN 200
|
||
|
#endif
|
||
|
#define ATSVR_RSP_BUF_LEN 140
|
||
|
#define ATSVR_IND_BUF_LEN 132
|
||
|
|
||
|
#define ATSVR_RSP_QUEUE_ID (7)
|
||
|
#define ATSVR_FWD_QUEUE_ID (8)
|
||
|
#define ATSVR_IND_QUEUE_ID (10)
|
||
|
|
||
|
enum
|
||
|
{
|
||
|
CMD_TYPE_TEXT = 0,
|
||
|
CMD_TYPE_INVALID,
|
||
|
};
|
||
|
|
||
|
typedef struct
|
||
|
{
|
||
|
u8 rsp_buff[ATSVR_RSP_BUF_LEN];
|
||
|
beken_semaphore_t rsp_buf_semaphore;
|
||
|
|
||
|
u8 rx_buff[ATSVR_RX_BUF_LEN];
|
||
|
|
||
|
u8 cur_cmd_type;
|
||
|
u8 cmd_buff[ATSVR_CMD_BUF_LEN];
|
||
|
u16 cmd_data_len;
|
||
|
|
||
|
|
||
|
u8 echo_enable;
|
||
|
|
||
|
/* patch for AT cmd handling. */
|
||
|
u8 cmd_ind_buff[ATSVR_IND_BUF_LEN];
|
||
|
beken_semaphore_t ind_buf_semaphore;
|
||
|
} cmd_line_t;
|
||
|
|
||
|
#define GET_BLOCK_ID(blocktag) ((blocktag) & 0xFF)
|
||
|
#define GET_QUEUE_ID(blocktag) (((blocktag) & 0x0F00) >> 8)
|
||
|
#define MAKE_BLOCK_TAG(blk_id, q_id) (((blk_id) & 0xFF) | (((q_id) & 0x0F) << 8) )
|
||
|
|
||
|
static cmd_line_t cmd_line_buf;
|
||
|
|
||
|
|
||
|
#if (CMD_DEV == DEV_UART)
|
||
|
#if (CONFIG_UART_PRINT_PORT == AT_UART_PORT_CFG)
|
||
|
extern shell_dev_t shell_uart;
|
||
|
static shell_dev_t * cmd_dev = &shell_uart;
|
||
|
#else
|
||
|
extern shell_dev_t atsvr_shell_uart;
|
||
|
static shell_dev_t * cmd_dev = &atsvr_shell_uart;
|
||
|
|
||
|
#endif
|
||
|
#endif
|
||
|
#if (CMD_DEV == DEV_MAILBOX)
|
||
|
//#if (0 == CONFIG_DEFAULT_AT_PORT)
|
||
|
//extern shell_dev_t shell_dev_mb;
|
||
|
//static shell_dev_t * cmd_dev = &shell_dev_mb;
|
||
|
//#else
|
||
|
extern shell_dev_t atsvr_shell_dev_mb;
|
||
|
static shell_dev_t * cmd_dev = &atsvr_shell_dev_mb;
|
||
|
//#endif
|
||
|
#endif
|
||
|
|
||
|
|
||
|
#if defined(FWD_CMD_TO_SLAVE) || defined(RECV_CMD_LOG_FROM_SLAVE)
|
||
|
|
||
|
typedef struct
|
||
|
{
|
||
|
log_cmd_t rsp_buf;
|
||
|
log_cmd_t ind_buf;
|
||
|
} fwd_slave_data_t;
|
||
|
|
||
|
static fwd_slave_data_t ipc_fwd_data;
|
||
|
extern shell_dev_ipc_t atsvr_shell_dev_ipc;
|
||
|
static shell_dev_ipc_t * ipc_dev = &atsvr_shell_dev_ipc;
|
||
|
|
||
|
static int result_fwd(int blk_id);
|
||
|
static u32 atsvr_ipc_rx_indication(u16 cmd, log_cmd_t *data, u16 cpu_id);
|
||
|
|
||
|
#endif
|
||
|
|
||
|
static inline uint32_t atsvr_task_enter_critical()
|
||
|
{
|
||
|
return rtos_enter_critical();
|
||
|
}
|
||
|
|
||
|
static inline void atsvr_task_exit_critical(uint32_t flags)
|
||
|
{
|
||
|
rtos_exit_critical(flags);
|
||
|
}
|
||
|
|
||
|
static const char atsvr_prompt_str[] = "\r\n>";
|
||
|
|
||
|
static u8 atsvr_init_ok = bFALSE;
|
||
|
|
||
|
static u32 atsvr_pm_wake_time = ATSVR_TASK_WAKE_CYCLE; // wait cycles before enter sleep.
|
||
|
static u8 atsvr_pm_wake_flag = 1;
|
||
|
|
||
|
#if 0
|
||
|
|
||
|
typedef struct
|
||
|
{
|
||
|
beken_semaphore_t event_semaphore; // will release from ISR.
|
||
|
u32 event_flag;
|
||
|
} os_ext_event_t;
|
||
|
|
||
|
static os_ext_event_t atsvr_task_event;
|
||
|
|
||
|
static bool_t atsvr_create_event(void)
|
||
|
{
|
||
|
atsvr_task_event.event_flag = 0;
|
||
|
rtos_init_semaphore(&atsvr_task_event.event_semaphore, 1);
|
||
|
|
||
|
return bTRUE;
|
||
|
}
|
||
|
|
||
|
/* this API may be called from ISR. */
|
||
|
bool_t atsvr_set_event(u32 event_flag)
|
||
|
{
|
||
|
u32 int_mask;
|
||
|
|
||
|
int_mask = atsvr_task_enter_critical();
|
||
|
|
||
|
atsvr_task_event.event_flag |= event_flag;
|
||
|
|
||
|
atsvr_task_exit_critical(int_mask);
|
||
|
|
||
|
rtos_set_semaphore(&atsvr_task_event.event_semaphore);
|
||
|
|
||
|
return bTRUE;
|
||
|
}
|
||
|
|
||
|
u32 atsvr_wait_any_event(u32 timeout)
|
||
|
{
|
||
|
u32 int_mask;
|
||
|
u32 event_flag;
|
||
|
|
||
|
int result;
|
||
|
|
||
|
while(bTRUE)
|
||
|
{
|
||
|
int_mask = atsvr_task_enter_critical();
|
||
|
|
||
|
event_flag = atsvr_task_event.event_flag;
|
||
|
atsvr_task_event.event_flag = 0;
|
||
|
|
||
|
atsvr_task_exit_critical(int_mask);
|
||
|
|
||
|
if((event_flag != 0) || (timeout == 0))
|
||
|
{
|
||
|
return event_flag;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
result = rtos_get_semaphore(&atsvr_task_event.event_semaphore, timeout);
|
||
|
|
||
|
if(result == kTimeoutErr)
|
||
|
return 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
#else
|
||
|
|
||
|
static beken_semaphore_t atsvr_semaphore; // will release from ISR.
|
||
|
|
||
|
static bool_t atsvr_create_event(void)
|
||
|
{
|
||
|
rtos_init_semaphore(&atsvr_semaphore, 1);
|
||
|
|
||
|
return bTRUE;
|
||
|
}
|
||
|
|
||
|
static bool_t atsvr_set_event(u32 event_flag)
|
||
|
{
|
||
|
(void)event_flag;
|
||
|
|
||
|
rtos_set_semaphore(&atsvr_semaphore);
|
||
|
|
||
|
return bTRUE;
|
||
|
}
|
||
|
|
||
|
static u32 atsvr_wait_any_event(u32 timeout)
|
||
|
{
|
||
|
int result;
|
||
|
|
||
|
result = rtos_get_semaphore(&atsvr_semaphore, timeout);
|
||
|
|
||
|
if(result == kTimeoutErr)
|
||
|
return 0;
|
||
|
|
||
|
return ATSVR_EVENT_RX_IND;
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
|
||
|
/* call from cmd TX ISR. */
|
||
|
static int cmd_tx_complete(u8 *pbuf, u16 buf_tag)
|
||
|
{
|
||
|
u8 queue_id = GET_QUEUE_ID(buf_tag);
|
||
|
u16 blk_id = GET_BLOCK_ID(buf_tag);
|
||
|
|
||
|
/* rsp ok ?? */
|
||
|
if( queue_id == ATSVR_RSP_QUEUE_ID ) /* rsp. */
|
||
|
{
|
||
|
/* it is called from cmd_dev tx ISR. */
|
||
|
|
||
|
if ( (pbuf != cmd_line_buf.rsp_buff) || (blk_id != 0) )
|
||
|
{
|
||
|
/* something wrong!!! */
|
||
|
ATSVRLOGE("FAULT: in rsp.\r\n");
|
||
|
}
|
||
|
|
||
|
/* rsp compelete, rsp_buff can be used for next cmd/response. */
|
||
|
rtos_set_semaphore(&cmd_line_buf.rsp_buf_semaphore);
|
||
|
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
if( queue_id == ATSVR_IND_QUEUE_ID ) /* cmd_ind. */
|
||
|
{
|
||
|
/* it is called from cmd_dev tx ISR. */
|
||
|
|
||
|
if ( (pbuf != cmd_line_buf.cmd_ind_buff) || (blk_id != 0) )
|
||
|
{
|
||
|
/* something wrong!!! */
|
||
|
ATSVRLOGE("FAULT: indication.\r\n");
|
||
|
}
|
||
|
|
||
|
/* indication tx compelete, cmd_ind_buff can be used for next cmd_indication. */
|
||
|
rtos_set_semaphore(&cmd_line_buf.ind_buf_semaphore);
|
||
|
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
if( queue_id == ATSVR_FWD_QUEUE_ID ) /* slave buffer. */
|
||
|
{
|
||
|
#if defined(FWD_CMD_TO_SLAVE)
|
||
|
result_fwd(blk_id);
|
||
|
return 1;
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
/* call from TX ISR. */
|
||
|
static void atsvr_cmd_tx_complete(u8 *pbuf, u16 buf_tag)
|
||
|
{
|
||
|
u32 int_mask = atsvr_task_enter_critical();
|
||
|
int tx_handled = cmd_tx_complete(pbuf, buf_tag);
|
||
|
|
||
|
if(tx_handled == 0) /* not handled. */
|
||
|
{
|
||
|
/* FAULT !!!! */
|
||
|
ATSVRLOGE("FATAL:%x,\r\n", buf_tag);
|
||
|
}
|
||
|
|
||
|
atsvr_task_exit_critical(int_mask);
|
||
|
}
|
||
|
|
||
|
/* call from RX ISR. */
|
||
|
static void atsvr_rx_indicate(void)
|
||
|
{
|
||
|
atsvr_set_event(ATSVR_EVENT_RX_IND);
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
static bool_t echo_out(u8 * echo_str, u16 len)
|
||
|
{
|
||
|
u16 wr_cnt;
|
||
|
|
||
|
if(len == 0)
|
||
|
return bTRUE;
|
||
|
|
||
|
wr_cnt = cmd_dev->dev_drv->write_echo(cmd_dev, echo_str, len);
|
||
|
|
||
|
return (wr_cnt == len);
|
||
|
}
|
||
|
|
||
|
static void cmd_info_out(u8 * msg_buf, u16 msg_len, u16 blk_tag)
|
||
|
{
|
||
|
u32 int_mask = atsvr_task_enter_critical();
|
||
|
|
||
|
/* should have a count semaphore for write_asyn calls for rsp/ind/cmd_hint & slave rsp/ind. *
|
||
|
* otherwise there will be coupled with driver, drv tx_queue_len MUST be >= 5. */
|
||
|
cmd_dev->dev_drv->write_async(cmd_dev, msg_buf, msg_len, blk_tag);
|
||
|
|
||
|
atsvr_task_exit_critical(int_mask);
|
||
|
}
|
||
|
|
||
|
/* NOTICE: this can only be called by shell task internally (cmd handler). */
|
||
|
/* it is not a re-enterance function becaue of using rsp_buff. */
|
||
|
static bool_t cmd_rsp_out(u8 * rsp_msg, u16 msg_len)
|
||
|
{
|
||
|
u16 rsp_blk_tag = MAKE_BLOCK_TAG(0, ATSVR_RSP_QUEUE_ID);
|
||
|
|
||
|
if(rsp_msg != cmd_line_buf.rsp_buff)
|
||
|
{
|
||
|
if(msg_len > sizeof(cmd_line_buf.rsp_buff))
|
||
|
{
|
||
|
msg_len = sizeof(cmd_line_buf.rsp_buff);;
|
||
|
}
|
||
|
|
||
|
memcpy(cmd_line_buf.rsp_buff, rsp_msg, msg_len);
|
||
|
}
|
||
|
|
||
|
cmd_info_out(cmd_line_buf.rsp_buff, msg_len, rsp_blk_tag);
|
||
|
|
||
|
return bTRUE;
|
||
|
}
|
||
|
|
||
|
/* it is not a re-enterance function, should sync using ind_buf_semaphore. */
|
||
|
static bool_t cmd_ind_out(u8 * ind_msg, u16 msg_len)
|
||
|
{
|
||
|
u16 ind_blk_tag = MAKE_BLOCK_TAG(0, ATSVR_IND_QUEUE_ID);
|
||
|
|
||
|
if(ind_msg != cmd_line_buf.cmd_ind_buff)
|
||
|
{
|
||
|
if(msg_len > sizeof(cmd_line_buf.cmd_ind_buff))
|
||
|
{
|
||
|
msg_len = sizeof(cmd_line_buf.cmd_ind_buff);;
|
||
|
}
|
||
|
|
||
|
memcpy(cmd_line_buf.cmd_ind_buff, ind_msg, msg_len);
|
||
|
}
|
||
|
|
||
|
cmd_info_out(cmd_line_buf.cmd_ind_buff, msg_len, ind_blk_tag);
|
||
|
|
||
|
return bTRUE;
|
||
|
}
|
||
|
extern int get_data_len(void);
|
||
|
static void rx_ind_process(void)
|
||
|
{
|
||
|
u16 read_cnt, buf_len;
|
||
|
u8 cmd_rx_done = bFALSE;
|
||
|
#if CONFIG_SYS_CPU0
|
||
|
u16 echo_len;
|
||
|
u16 i = 0;
|
||
|
u8 need_backspace = bFALSE;
|
||
|
#if CONFIG_AT_DATA_MODE
|
||
|
int at_data_len = 0;
|
||
|
#endif
|
||
|
#endif
|
||
|
|
||
|
if(cmd_dev->dev_type == SHELL_DEV_MAILBOX)
|
||
|
{
|
||
|
buf_len = ATSVR_RX_BUF_LEN;
|
||
|
}
|
||
|
else /* if(cmd_dev->dev_type == SHELL_DEV_UART) */
|
||
|
{
|
||
|
buf_len = 1; /* for UART device, read one by one. */
|
||
|
}
|
||
|
|
||
|
#if CONFIG_AT_DATA_MODE
|
||
|
if(ATSVR_WK_DATA_HANDLE== get_atsvr_work_state())
|
||
|
{
|
||
|
at_data_len = get_data_len();
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
|
||
|
while(bTRUE)
|
||
|
{
|
||
|
u8 * rx_temp_buff = &cmd_line_buf.rx_buff[0];
|
||
|
|
||
|
read_cnt = cmd_dev->dev_drv->read(cmd_dev, rx_temp_buff, buf_len);
|
||
|
#if CONFIG_SYS_CPU1
|
||
|
memcpy(cmd_line_buf.cmd_buff,cmd_line_buf.rx_buff,read_cnt);
|
||
|
cmd_line_buf.cmd_data_len = read_cnt;
|
||
|
cmd_line_buf.cur_cmd_type = CMD_TYPE_TEXT;
|
||
|
cmd_rx_done = 1;
|
||
|
goto cpu1_handle;
|
||
|
#endif
|
||
|
#if CONFIG_SYS_CPU0
|
||
|
echo_len = 0;
|
||
|
|
||
|
for(i = 0; i < read_cnt; i++)
|
||
|
{
|
||
|
if(cmd_line_buf.cur_cmd_type == CMD_TYPE_INVALID)
|
||
|
{
|
||
|
echo_len++;
|
||
|
|
||
|
if((rx_temp_buff[i] >= 0x20) && (rx_temp_buff[i] < 0x7f))
|
||
|
{
|
||
|
cmd_line_buf.cur_cmd_type = CMD_TYPE_TEXT;
|
||
|
|
||
|
cmd_line_buf.cmd_data_len = 0;
|
||
|
cmd_line_buf.cmd_buff[cmd_line_buf.cmd_data_len] = rx_temp_buff[i];
|
||
|
cmd_line_buf.cmd_data_len++;
|
||
|
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
|
||
|
}
|
||
|
|
||
|
if(cmd_line_buf.cur_cmd_type == CMD_TYPE_TEXT)
|
||
|
{
|
||
|
echo_len++;
|
||
|
if(rx_temp_buff[i] == '\b')
|
||
|
{
|
||
|
if(cmd_line_buf.cmd_data_len > 0)
|
||
|
{
|
||
|
cmd_line_buf.cmd_data_len--;
|
||
|
|
||
|
if(cmd_line_buf.cmd_data_len == 0)
|
||
|
need_backspace = bTRUE;
|
||
|
}
|
||
|
}
|
||
|
else if((rx_temp_buff[i] == '\n') || (rx_temp_buff[i] == '\r'))
|
||
|
{
|
||
|
#if CONFIG_AT_DATA_MODE
|
||
|
if(ATSVR_WK_DATA_HANDLE== get_atsvr_work_state())
|
||
|
{
|
||
|
if(cmd_line_buf.cmd_data_len < at_data_len)
|
||
|
{
|
||
|
cmd_line_buf.cmd_buff[cmd_line_buf.cmd_data_len] = rx_temp_buff[i];
|
||
|
cmd_line_buf.cmd_data_len++;
|
||
|
continue;
|
||
|
}
|
||
|
//else
|
||
|
// cmd_line_buf.cmd_buff[cmd_line_buf.cmd_data_len] = 0; // in case cmd_data_len overflow.
|
||
|
|
||
|
cmd_rx_done = bTRUE;
|
||
|
break;
|
||
|
}
|
||
|
#endif
|
||
|
if(cmd_line_buf.cmd_data_len < sizeof(cmd_line_buf.cmd_buff))
|
||
|
{
|
||
|
cmd_line_buf.cmd_buff[cmd_line_buf.cmd_data_len] = 0;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
cmd_line_buf.cmd_buff[cmd_line_buf.cmd_data_len - 1] = 0; // in case cmd_data_len overflow.
|
||
|
}
|
||
|
|
||
|
cmd_rx_done = bTRUE;
|
||
|
break;
|
||
|
}
|
||
|
else if((rx_temp_buff[i] >= 0x20))
|
||
|
{
|
||
|
if(cmd_line_buf.cmd_data_len < sizeof(cmd_line_buf.cmd_buff))
|
||
|
{
|
||
|
cmd_line_buf.cmd_buff[cmd_line_buf.cmd_data_len] = rx_temp_buff[i];
|
||
|
cmd_line_buf.cmd_data_len++;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
if( cmd_rx_done )
|
||
|
{
|
||
|
if(cmd_line_buf.echo_enable)
|
||
|
{
|
||
|
echo_out(&rx_temp_buff[0], echo_len);
|
||
|
echo_out((u8 *)"\r\n", 2);
|
||
|
}
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if(cmd_line_buf.echo_enable)
|
||
|
{
|
||
|
if(echo_len > 0)
|
||
|
{
|
||
|
if( (rx_temp_buff[echo_len - 1] == '\b') ||
|
||
|
(rx_temp_buff[echo_len - 1] == 0x7f) ) /* DEL */
|
||
|
{
|
||
|
echo_len--;
|
||
|
if((cmd_line_buf.cmd_data_len > 0) || need_backspace)
|
||
|
echo_out((u8 *)"\b \b", 3);
|
||
|
}
|
||
|
|
||
|
u8 cr_lf = 0;
|
||
|
|
||
|
if(echo_len == 1)
|
||
|
{
|
||
|
if( (rx_temp_buff[echo_len - 1] == '\r') ||
|
||
|
(rx_temp_buff[echo_len - 1] == '\n') )
|
||
|
{
|
||
|
cr_lf = 1;
|
||
|
}
|
||
|
}
|
||
|
else if(echo_len == 2)
|
||
|
{
|
||
|
if( (memcmp(rx_temp_buff, "\r\n", 2) == 0) ||
|
||
|
(memcmp(rx_temp_buff, "\n\r", 2) == 0) )
|
||
|
{
|
||
|
cr_lf = 1;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if(cr_lf != 0)
|
||
|
{
|
||
|
echo_out((u8 *)&atsvr_prompt_str[0], 3);
|
||
|
echo_len = 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
echo_out(rx_temp_buff, echo_len);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if(read_cnt < buf_len) /* all data are read out. */
|
||
|
break;
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
if(read_cnt < buf_len) /* all data are read out. */
|
||
|
{
|
||
|
}
|
||
|
else /* cmd pends in buffer, handle it in new loop cycle. */
|
||
|
{
|
||
|
atsvr_set_event(ATSVR_EVENT_RX_IND);
|
||
|
}
|
||
|
#if CONFIG_SYS_CPU1
|
||
|
cpu1_handle:
|
||
|
#endif
|
||
|
/* can re-use *buf_len*. */
|
||
|
if( cmd_rx_done )
|
||
|
{
|
||
|
#if CONFIG_SYS_CPU0
|
||
|
if(cmd_line_buf.cur_cmd_type == CMD_TYPE_TEXT)
|
||
|
{
|
||
|
#endif
|
||
|
u16 rx_ovf = 0;
|
||
|
cmd_dev->dev_drv->io_ctrl(cmd_dev, SHELL_IO_CTRL_GET_RX_STATUS, &rx_ovf);
|
||
|
|
||
|
if(rx_ovf != 0)
|
||
|
{
|
||
|
ATSVRLOGE("AT Commands lost!\r\n");
|
||
|
}
|
||
|
|
||
|
rtos_get_semaphore(&cmd_line_buf.rsp_buf_semaphore, ATSVR_WAIT_OUT_TIME);
|
||
|
|
||
|
cmd_line_buf.rsp_buff[0] = 0;
|
||
|
|
||
|
/* handle command. */
|
||
|
if( cmd_line_buf.cmd_data_len > 0 )
|
||
|
//atsvr_handle_shell_input( (char *)cmd_line_buf.cmd_buff, cmd_line_buf.cmd_data_len, (char *)cmd_line_buf.rsp_buff, ATSVR_RSP_BUF_LEN - 4 );
|
||
|
atsvr_msg_get_input((char *)cmd_line_buf.cmd_buff, cmd_line_buf.cmd_data_len, (char *)cmd_line_buf.rsp_buff, ATSVR_RSP_BUF_LEN - 4);
|
||
|
|
||
|
cmd_line_buf.rsp_buff[ATSVR_RSP_BUF_LEN - 4] = 0;
|
||
|
|
||
|
buf_len = strlen((char *)cmd_line_buf.rsp_buff);
|
||
|
if(buf_len > (ATSVR_RSP_BUF_LEN - 4))
|
||
|
buf_len = (ATSVR_RSP_BUF_LEN - 4);
|
||
|
buf_len += sprintf((char *)&cmd_line_buf.rsp_buff[buf_len], &atsvr_prompt_str[0]);
|
||
|
|
||
|
cmd_rsp_out(cmd_line_buf.rsp_buff, buf_len);
|
||
|
#if CONFIG_SYS_CPU0
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
cmd_line_buf.cur_cmd_type = CMD_TYPE_INVALID; /* reset cmd line to interpret new cmd. */
|
||
|
cmd_line_buf.cmd_data_len = 0;
|
||
|
}
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
extern gpio_id_t bk_uart_get_rx_gpio(uart_id_t id);
|
||
|
|
||
|
static void atsvr_rx_wakeup(int gpio_id);
|
||
|
|
||
|
static void atsvr_power_save_enter(void)
|
||
|
{
|
||
|
//u32 flush_log = cmd_line_buf.log_flush;
|
||
|
|
||
|
cmd_dev->dev_drv->io_ctrl(cmd_dev, SHELL_IO_CTRL_RX_SUSPEND, NULL);
|
||
|
|
||
|
if(cmd_dev->dev_type == SHELL_DEV_UART)
|
||
|
{
|
||
|
u8 uart_port = UART_ID_MAX;
|
||
|
|
||
|
cmd_dev->dev_drv->io_ctrl(cmd_dev, SHELL_IO_CTRL_GET_UART_PORT, &uart_port);
|
||
|
u32 gpio_id = bk_uart_get_rx_gpio(uart_port);
|
||
|
|
||
|
bk_gpio_register_isr(gpio_id, (gpio_isr_t)atsvr_rx_wakeup);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void atsvr_power_save_exit(void)
|
||
|
{
|
||
|
cmd_dev->dev_drv->io_ctrl(cmd_dev, SHELL_IO_CTRL_RX_RESUME, NULL);
|
||
|
}
|
||
|
|
||
|
static void wakeup_process(void)
|
||
|
{
|
||
|
bk_pm_module_vote_sleep_ctrl(PM_SLEEP_MODULE_NAME_AT, 0, 0);
|
||
|
atsvr_pm_wake_flag = 1;
|
||
|
atsvr_pm_wake_time = ATSVR_TASK_WAKE_CYCLE;
|
||
|
}
|
||
|
|
||
|
static void atsvr_rx_wakeup(int gpio_id)
|
||
|
{
|
||
|
wakeup_process();
|
||
|
|
||
|
ATSVRLOG("ATSVR_wakeup\r\n");
|
||
|
|
||
|
if(cmd_dev->dev_type == SHELL_DEV_UART)
|
||
|
{
|
||
|
bk_gpio_register_isr(gpio_id, NULL);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void atsvr_task_init(void)
|
||
|
{
|
||
|
//u16 i;
|
||
|
|
||
|
cmd_line_buf.cur_cmd_type = CMD_TYPE_INVALID;
|
||
|
cmd_line_buf.cmd_data_len = 0;
|
||
|
cmd_line_buf.echo_enable = bTRUE;
|
||
|
|
||
|
rtos_init_semaphore_ex(&cmd_line_buf.rsp_buf_semaphore, 1, 1); // one buffer for cmd_rsp.
|
||
|
rtos_init_semaphore_ex(&cmd_line_buf.ind_buf_semaphore, 1, 1); // one buffer for cmd_ind.
|
||
|
|
||
|
atsvr_create_event();
|
||
|
|
||
|
cmd_dev->dev_drv->init(cmd_dev);
|
||
|
|
||
|
cmd_dev->dev_drv->open(cmd_dev, atsvr_cmd_tx_complete, atsvr_rx_indicate); // rx cmd, tx rsp.
|
||
|
|
||
|
#if defined(FWD_CMD_TO_SLAVE) || defined(RECV_CMD_LOG_FROM_SLAVE)
|
||
|
ipc_dev->dev_drv->init(ipc_dev);
|
||
|
ipc_dev->dev_drv->open(ipc_dev, (shell_ipc_rx_t)atsvr_ipc_rx_indication, NULL); /* register rx-callback to copy log data to buffer. */
|
||
|
#endif
|
||
|
|
||
|
atsvr_init_ok = bTRUE;
|
||
|
|
||
|
pm_cb_conf_t enter_config;
|
||
|
enter_config.cb = (pm_cb)atsvr_power_save_enter;
|
||
|
enter_config.args = NULL;
|
||
|
|
||
|
pm_cb_conf_t exit_config;
|
||
|
exit_config.cb = (pm_cb)atsvr_power_save_exit;
|
||
|
exit_config.args = NULL;
|
||
|
|
||
|
#if 1
|
||
|
bk_pm_sleep_register_cb(PM_MODE_LOW_VOLTAGE, PM_DEV_ID_UART2, &enter_config, &exit_config);
|
||
|
|
||
|
u8 uart_port = UART_ID_MAX;
|
||
|
|
||
|
cmd_dev->dev_drv->io_ctrl(cmd_dev, SHELL_IO_CTRL_GET_UART_PORT, &uart_port);
|
||
|
|
||
|
atsvr_rx_wakeup(bk_uart_get_rx_gpio(uart_port));
|
||
|
#else
|
||
|
|
||
|
u8 uart_port = UART_ID_MAX;
|
||
|
cmd_dev->dev_drv->io_ctrl(cmd_dev, SHELL_IO_CTRL_GET_UART_PORT, &uart_port);
|
||
|
|
||
|
u8 pm_uart_port = uart_id_to_pm_uart_id(uart_port);
|
||
|
bk_pm_sleep_register_cb(PM_MODE_LOW_VOLTAGE, pm_uart_port, &enter_config, &exit_config);
|
||
|
|
||
|
atsvr_rx_wakeup(bk_uart_get_rx_gpio(uart_port));
|
||
|
#endif
|
||
|
|
||
|
|
||
|
}
|
||
|
|
||
|
void atsvr_task( void *para )
|
||
|
{
|
||
|
u32 Events;
|
||
|
u32 timeout = ATSVR_TASK_WAIT_TIME;
|
||
|
|
||
|
atsvr_task_init();
|
||
|
|
||
|
echo_out((u8 *)&atsvr_prompt_str[0], 3);
|
||
|
|
||
|
atsvr_notice_ready();
|
||
|
|
||
|
while(bTRUE)
|
||
|
{
|
||
|
Events = atsvr_wait_any_event(timeout); // WAIT_EVENT;
|
||
|
|
||
|
|
||
|
if(Events & ATSVR_EVENT_RX_IND)
|
||
|
{
|
||
|
wakeup_process();
|
||
|
rx_ind_process();
|
||
|
}
|
||
|
|
||
|
if(Events == 0)
|
||
|
{
|
||
|
if(atsvr_pm_wake_time > 0)
|
||
|
atsvr_pm_wake_time--;
|
||
|
|
||
|
if(atsvr_pm_wake_time == 0)
|
||
|
{
|
||
|
if(atsvr_pm_wake_flag != 0)
|
||
|
{
|
||
|
atsvr_pm_wake_flag = 0;
|
||
|
bk_pm_module_vote_sleep_ctrl(PM_SLEEP_MODULE_NAME_AT, 1, 0);
|
||
|
ATSVRLOG("ATSVR sleep\r\n");
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if(atsvr_pm_wake_flag)
|
||
|
{
|
||
|
timeout = ATSVR_TASK_WAIT_TIME;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
timeout = BEKEN_WAIT_FOREVER;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#if defined(FWD_CMD_TO_SLAVE) || defined(RECV_CMD_LOG_FROM_SLAVE)
|
||
|
static int cmd_rsp_fwd(u8 * rsp_msg, u16 msg_len)
|
||
|
{
|
||
|
u16 rsp_blk_tag = MAKE_BLOCK_TAG(SLAVE_RSP_BLK_ID, ATSVR_FWD_QUEUE_ID);
|
||
|
|
||
|
cmd_info_out(rsp_msg, msg_len, rsp_blk_tag);
|
||
|
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
static int cmd_ind_fwd(u8 * ind_msg, u16 msg_len)
|
||
|
{
|
||
|
u16 ind_blk_tag = MAKE_BLOCK_TAG(SLAVE_IND_BLK_ID, ATSVR_FWD_QUEUE_ID);
|
||
|
|
||
|
if(0 == strcmp(ATSVR_READY_MSG,(char*)(ind_msg)))
|
||
|
{
|
||
|
extern _at_svr_ctrl_env_t _at_svr_env;
|
||
|
_at_svr_env.cpu1_ready = true;
|
||
|
ATSVRLOGE("ATSVR:CPU0 Notice CPU1 is ready\r\n");
|
||
|
}
|
||
|
cmd_info_out(ind_msg, msg_len, ind_blk_tag);
|
||
|
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
static int result_fwd(int blk_id)
|
||
|
{
|
||
|
log_cmd_t * log_cmd;
|
||
|
|
||
|
if(blk_id == SLAVE_RSP_BLK_ID)
|
||
|
{
|
||
|
log_cmd = &ipc_fwd_data.rsp_buf;
|
||
|
}
|
||
|
else if(blk_id == SLAVE_IND_BLK_ID)
|
||
|
{
|
||
|
log_cmd = &ipc_fwd_data.ind_buf;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
log_cmd->hdr.data = 0;
|
||
|
log_cmd->hdr.cmd = MB_CMD_LOG_OUT_OK;
|
||
|
|
||
|
return ipc_dev->dev_drv->write_cmd(ipc_dev, (mb_chnl_cmd_t *)log_cmd);
|
||
|
}
|
||
|
|
||
|
static u32 atsvr_ipc_rx_indication(u16 cmd, log_cmd_t *log_cmd, u16 cpu_id)
|
||
|
{
|
||
|
u32 result = ACK_STATE_FAIL;
|
||
|
u8 * data = log_cmd->buf;
|
||
|
u16 data_len = log_cmd->len;
|
||
|
if(cmd == MB_CMD_LOG_OUT)
|
||
|
{
|
||
|
u8 queue_id = GET_QUEUE_ID(log_cmd->tag);
|
||
|
|
||
|
if(queue_id == ATSVR_RSP_QUEUE_ID)
|
||
|
{
|
||
|
memcpy(&ipc_fwd_data.rsp_buf, log_cmd, sizeof(ipc_fwd_data.rsp_buf));
|
||
|
cmd_rsp_fwd(data, data_len);
|
||
|
|
||
|
return ACK_STATE_PENDING;
|
||
|
}
|
||
|
else if(queue_id == ATSVR_IND_QUEUE_ID)
|
||
|
{
|
||
|
memcpy(&ipc_fwd_data.ind_buf, log_cmd, sizeof(ipc_fwd_data.ind_buf));
|
||
|
cmd_ind_fwd(data, data_len);
|
||
|
|
||
|
return ACK_STATE_PENDING;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* no cmd handler. */
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
int atsvr_cmd_forward(char *cmd, u16 cmd_len)
|
||
|
{
|
||
|
mb_chnl_cmd_t mb_cmd_buf;
|
||
|
user_cmd_t * user_cmd = (user_cmd_t *)&mb_cmd_buf;
|
||
|
|
||
|
user_cmd->hdr.data = 0;
|
||
|
user_cmd->hdr.cmd = MB_CMD_USER_INPUT;
|
||
|
user_cmd->buf = (u8 *)cmd;
|
||
|
user_cmd->len = cmd_len;
|
||
|
|
||
|
u32 int_mask = atsvr_task_enter_critical();
|
||
|
|
||
|
int ret_code = ipc_dev->dev_drv->write_cmd(ipc_dev, &mb_cmd_buf);
|
||
|
|
||
|
atsvr_task_exit_critical(int_mask);
|
||
|
|
||
|
return ret_code;
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
void atsvr_echo_set(int en_flag)
|
||
|
{
|
||
|
if(en_flag != 0)
|
||
|
cmd_line_buf.echo_enable = bTRUE;
|
||
|
else
|
||
|
cmd_line_buf.echo_enable = bFALSE;
|
||
|
}
|
||
|
|
||
|
int atsvr_echo_get(void)
|
||
|
{
|
||
|
if(cmd_line_buf.echo_enable)
|
||
|
return 1;
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
void atsvr_cmd_ind_out(const char *format, ...)
|
||
|
{
|
||
|
u16 data_len, buf_len = ATSVR_IND_BUF_LEN;
|
||
|
va_list arg_list;
|
||
|
rtos_get_semaphore(&cmd_line_buf.ind_buf_semaphore, ATSVR_WAIT_OUT_TIME);
|
||
|
va_start(arg_list, format);
|
||
|
data_len = vsnprintf( (char *)&cmd_line_buf.cmd_ind_buff[0], buf_len - 1, format, arg_list );
|
||
|
va_end(arg_list);
|
||
|
|
||
|
if(data_len >= buf_len)
|
||
|
data_len = buf_len - 1;
|
||
|
|
||
|
cmd_ind_out(cmd_line_buf.cmd_ind_buff, data_len);
|
||
|
}
|
||
|
|
||
|
int atsvr_get_cpu_id(void)
|
||
|
{
|
||
|
#ifdef CONFIG_FREERTOS_SMP
|
||
|
return rtos_get_core_id();
|
||
|
#elif (CONFIG_CPU_CNT > 1)
|
||
|
|
||
|
if(cmd_dev->dev_type == SHELL_DEV_MAILBOX)
|
||
|
return SELF_CPU;
|
||
|
|
||
|
#endif
|
||
|
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
|