2729 lines
63 KiB
C
Executable File
2729 lines
63 KiB
C
Executable File
|
|
#include <stdio.h>
|
|
#include <stdarg.h>
|
|
#include <string.h>
|
|
|
|
#include "cli.h"
|
|
#include <os/os.h>
|
|
#include <common/bk_compiler.h>
|
|
#include <components/shell_task.h>
|
|
#include "shell_drv.h"
|
|
#include <components/ate.h>
|
|
#include <modules/pm.h>
|
|
#include <driver/gpio.h>
|
|
#include "bk_wdt.h"
|
|
#if CONFIG_AT
|
|
#include "atsvr_unite.h"
|
|
#if CONFIG_AT_DATA_MODE
|
|
#include "at_sal_ex.h"
|
|
#endif
|
|
#endif
|
|
|
|
#define DEV_UART 1
|
|
#define DEV_MAILBOX 2
|
|
|
|
#if CONFIG_SYS_PRINT_DEV_UART
|
|
#define LOG_DEV DEV_UART
|
|
#define CMD_DEV DEV_UART
|
|
#elif CONFIG_SYS_PRINT_DEV_MAILBOX
|
|
#define LOG_DEV DEV_MAILBOX
|
|
#define CMD_DEV DEV_MAILBOX
|
|
#endif
|
|
|
|
// #if (CMD_DEV != DEV_MAILBOX)
|
|
#if (CONFIG_SYS_CPU0)
|
|
#if CONFIG_MAILBOX
|
|
#ifndef CONFIG_FREERTOS_SMP
|
|
#define FWD_CMD_TO_MBOX
|
|
#define RECV_CMD_LOG_FROM_MBOX
|
|
#endif
|
|
#endif
|
|
#endif
|
|
|
|
#if defined(FWD_CMD_TO_MBOX)
|
|
#define MBOX_RSP_BLK_ID 0
|
|
#define MBOX_IND_BLK_ID 1
|
|
#define MBOX_COMMON_BLK_ID 2
|
|
|
|
#define MBOX_FWD_PEND_NUM 2 /* (1 Rsp + 1 Ind) */
|
|
#else
|
|
#define MBOX_FWD_PEND_NUM 0
|
|
#endif
|
|
|
|
#define SHELL_LOG_BLOCK_TIME (10)
|
|
#define SHELL_LOG_FWD_WAIT_TIME (1)
|
|
|
|
#define SHELL_WAIT_OUT_TIME (2000) // 2s.
|
|
|
|
#define SHELL_TASK_WAIT_TIME (100) // 100ms
|
|
#define SHELL_TASK_WAKE_CYCLE (20) // 2s
|
|
|
|
#define SHELL_EVENT_TX_REQ 0x01
|
|
#define SHELL_EVENT_RX_IND 0x02
|
|
#define SHELL_EVENT_WAKEUP 0x04
|
|
#define SHELL_EVENT_DYM_FREE 0x08
|
|
#define SHELL_EVENT_MB_LOG 0x10
|
|
#define SHELL_EVENT_MB_FWD 0x20
|
|
|
|
#define SHELL_LOG_BUF1_LEN 136
|
|
#define SHELL_LOG_BUF2_LEN 80
|
|
#define SHELL_LOG_BUF3_LEN 40
|
|
|
|
#if (LOG_DEV == DEV_MAILBOX)
|
|
#define SHELL_LOG_BUF1_NUM 2
|
|
#define SHELL_LOG_BUF2_NUM 4
|
|
#define SHELL_LOG_BUF3_NUM 8
|
|
#define SHELL_DYM_LOG_NUM_MAX 50
|
|
#endif // (LOG_DEV == DEV_MAILBOX)
|
|
|
|
#if (LOG_DEV == DEV_UART)
|
|
#if CONFIG_RELEASE_VERSION
|
|
#define SHELL_LOG_BUF1_NUM 4
|
|
#define SHELL_LOG_BUF2_NUM 16
|
|
#define SHELL_LOG_BUF3_NUM 32
|
|
#define SHELL_DYM_LOG_NUM_MAX 50
|
|
#else
|
|
#if !CONFIG_UART_RING_BUFF
|
|
#define SHELL_LOG_BUF1_NUM 8
|
|
#define SHELL_LOG_BUF2_NUM 40
|
|
#define SHELL_LOG_BUF3_NUM 60
|
|
#define SHELL_DYM_LOG_NUM_MAX 100
|
|
#else
|
|
#define SHELL_LOG_BUF1_NUM 8
|
|
#define SHELL_LOG_BUF2_NUM 30
|
|
#define SHELL_LOG_BUF3_NUM 50
|
|
#define SHELL_DYM_LOG_NUM_MAX 100
|
|
#endif
|
|
#endif
|
|
#endif // (LOG_DEV == DEV_UART)
|
|
|
|
#define SHELL_LOG_BUF_NUM (SHELL_LOG_BUF1_NUM + SHELL_LOG_BUF2_NUM + SHELL_LOG_BUF3_NUM)
|
|
#define SHELL_LOG_PEND_NUM (SHELL_LOG_BUF_NUM * 2 + 4 + MBOX_FWD_PEND_NUM + SHELL_DYM_LOG_NUM_MAX)
|
|
/* the worst case may be (one log + one hint) in pending queue, so twice the log_num for pending queue.*/
|
|
/* 1: RSP, 1: reserved(queue empty), 1: cmd ovf, 1: ind). */
|
|
/* MBOX_FWD_PEND_NUM (1 Rsp + 1 Ind) every slave core. */
|
|
#define SHELL_LOG_BUSY_NUM (8)
|
|
#define SHELL_ASSERT_BUF_LEN 140
|
|
|
|
#if (CMD_DEV == DEV_MAILBOX)
|
|
#define SHELL_RX_BUF_LEN 140
|
|
#endif
|
|
#if (CMD_DEV == DEV_UART)
|
|
#define SHELL_RX_BUF_LEN 4
|
|
#endif
|
|
|
|
#if CONFIG_AT_DATA_MODE
|
|
#define SHELL_CMD_BUF_LEN 4096
|
|
#else
|
|
#define SHELL_CMD_BUF_LEN 200
|
|
#endif
|
|
#define SHELL_RSP_BUF_LEN 140
|
|
#define SHELL_IND_BUF_LEN 132
|
|
|
|
#define SHELL_RSP_QUEUE_ID (7)
|
|
#define SHELL_FWD_QUEUE_ID (8)
|
|
#define SHELL_ROM_QUEUE_ID (9)
|
|
#define SHELL_IND_QUEUE_ID (10)
|
|
#define SHELL_DYM_QUEUE_ID (11)
|
|
|
|
#define TBL_SIZE(tbl) (sizeof(tbl) / sizeof(tbl[0]))
|
|
|
|
#define LOG_BLOCK_MASK LOG_STATIC_BLOCK_MODE
|
|
#define LOG_MALLOC_MASK LOG_NONBLOCK_MODE
|
|
|
|
typedef struct
|
|
{
|
|
beken_semaphore_t event_semaphore; // will release from ISR.
|
|
u32 event_flag;
|
|
} os_ext_event_t;
|
|
|
|
enum
|
|
{
|
|
CMD_TYPE_TEXT = 0,
|
|
CMD_TYPE_HEX,
|
|
CMD_TYPE_BKREG, /* patch for BK_REG tool cmd. */
|
|
CMD_TYPE_INVALID,
|
|
};
|
|
|
|
/* patch for BK_REG tool. */
|
|
enum
|
|
{
|
|
BKREG_WAIT_01 = 0,
|
|
BKREG_WAIT_E0,
|
|
BKREG_WAIT_FC,
|
|
};
|
|
|
|
typedef struct
|
|
{
|
|
u8 rsp_buff[SHELL_RSP_BUF_LEN];
|
|
beken_semaphore_t rsp_buf_semaphore;
|
|
|
|
u8 rx_buff[SHELL_RX_BUF_LEN];
|
|
|
|
u8 cur_cmd_type;
|
|
u8 cmd_buff[SHELL_CMD_BUF_LEN];
|
|
u16 cmd_data_len;
|
|
u8 cmd_ovf_hint;
|
|
|
|
/* patch for BK_REG tool. */
|
|
/* added one state machine for BK_REG tool cmd. */
|
|
u8 bkreg_state;
|
|
u8 bkreg_left_byte;
|
|
/* patch end. */
|
|
|
|
u8 echo_enable;
|
|
|
|
/* patch for AT cmd handling. */
|
|
u8 cmd_ind_buff[SHELL_IND_BUF_LEN];
|
|
beken_semaphore_t ind_buf_semaphore;
|
|
|
|
/* cmd FWD */
|
|
#if defined(FWD_CMD_TO_MBOX)
|
|
beken_semaphore_t cmd_fwd_semaphore;
|
|
#endif
|
|
} cmd_line_t;
|
|
|
|
#define GET_BLOCK_ID(blocktag) ((blocktag) & 0x7FF)
|
|
#define GET_QUEUE_ID(blocktag) (((blocktag) & 0xF800) >> 11)
|
|
#define MAKE_BLOCK_TAG(blk_id, q_id) (((blk_id) & 0x7FF) | (((q_id) & 0x1F) << 11) )
|
|
|
|
typedef struct
|
|
{
|
|
u16 blk_tag; /* bit0~bit7: blk_id, bit8~bit11: queue_id; */
|
|
u16 packet_len;
|
|
} tx_packet_t;
|
|
|
|
typedef struct
|
|
{
|
|
tx_packet_t packet_list[SHELL_LOG_PEND_NUM];
|
|
u16 list_out_idx;
|
|
u16 list_in_idx;
|
|
} pending_queue_t;
|
|
|
|
typedef struct
|
|
{
|
|
u16 blk_list[SHELL_LOG_BUSY_NUM];
|
|
u16 list_out_idx;
|
|
u16 list_in_idx;
|
|
u16 free_cnt;
|
|
} busy_queue_t;
|
|
|
|
typedef struct
|
|
{
|
|
u8 * const log_buf;
|
|
u16 * const blk_list;
|
|
const u16 blk_num;
|
|
const u16 blk_len;
|
|
u16 list_out_idx;
|
|
u16 list_in_idx;
|
|
u16 free_blk_num;
|
|
u32 ovf_cnt;
|
|
} free_queue_t;
|
|
|
|
typedef struct dynamic_log_node_t dynamic_log_node;
|
|
struct dynamic_log_node_t
|
|
{
|
|
dynamic_log_node *next;
|
|
u32 len;
|
|
u8 ptr[0];
|
|
};
|
|
|
|
#define LOG_MALLOC os_malloc
|
|
#define LOG_FREE os_free
|
|
|
|
static dynamic_log_node s_dynamic_header = {NULL};
|
|
static dynamic_log_node *s_to_free_list = NULL;
|
|
static dynamic_log_node *s_curr_node = NULL;
|
|
static dynamic_log_node *s_dym_tail_node = &s_dynamic_header;
|
|
|
|
static int s_block_mode = LOG_COMMON_MODE;
|
|
|
|
static u16 s_dynamic_log_num = 0; // dynamic log in send queue
|
|
static u16 s_dynamic_log_total_len = 0; // total consumption of dynamic log memory
|
|
static u16 s_dynamic_log_num_in_mem = 0; // number of dynamic log in memory, including no free log.
|
|
static u16 s_dynamic_log_mem_max = 0; // maximum of consumption
|
|
|
|
#define DYM_NODE_SIZE (sizeof(dynamic_log_node))
|
|
|
|
#if (CONFIG_CACHE_ENABLE) && (CONFIG_LV_USE_DEMO_METER)
|
|
#define SHELL_DECLARE_MEMORY_ATTR __attribute__((section(".sram_cache")))
|
|
#elif CONFIG_SOC_BK7258 && CONFIG_SYS_PRINT_DEV_UART
|
|
#define SHELL_DECLARE_MEMORY_ATTR __attribute__((section(".dtcm_section")))
|
|
#else
|
|
#define SHELL_DECLARE_MEMORY_ATTR
|
|
#endif
|
|
|
|
beken_semaphore_t log_buf_semaphore = NULL;
|
|
|
|
static SHELL_DECLARE_MEMORY_ATTR u8 shell_log_buff1[SHELL_LOG_BUF1_NUM * SHELL_LOG_BUF1_LEN];
|
|
static SHELL_DECLARE_MEMORY_ATTR u8 shell_log_buff2[SHELL_LOG_BUF2_NUM * SHELL_LOG_BUF2_LEN];
|
|
static SHELL_DECLARE_MEMORY_ATTR u8 shell_log_buff3[SHELL_LOG_BUF3_NUM * SHELL_LOG_BUF3_LEN];
|
|
static SHELL_DECLARE_MEMORY_ATTR u16 buff1_free_list[SHELL_LOG_BUF1_NUM];
|
|
static SHELL_DECLARE_MEMORY_ATTR u16 buff2_free_list[SHELL_LOG_BUF2_NUM];
|
|
static SHELL_DECLARE_MEMORY_ATTR u16 buff3_free_list[SHELL_LOG_BUF3_NUM];
|
|
|
|
|
|
/* queue sort ascending in blk_len. */
|
|
static free_queue_t free_queue[3] =
|
|
{
|
|
{.log_buf = shell_log_buff3, .blk_list = buff3_free_list, .blk_num = SHELL_LOG_BUF3_NUM, \
|
|
.blk_len = SHELL_LOG_BUF3_LEN, .list_out_idx = 0, .list_in_idx = 0, \
|
|
.free_blk_num = SHELL_LOG_BUF3_NUM, .ovf_cnt = 0},
|
|
|
|
{.log_buf = shell_log_buff2, .blk_list = buff2_free_list, .blk_num = SHELL_LOG_BUF2_NUM, \
|
|
.blk_len = SHELL_LOG_BUF2_LEN, .list_out_idx = 0, .list_in_idx = 0, \
|
|
.free_blk_num = SHELL_LOG_BUF2_NUM, .ovf_cnt = 0},
|
|
|
|
{.log_buf = shell_log_buff1, .blk_list = buff1_free_list, .blk_num = SHELL_LOG_BUF1_NUM, \
|
|
.blk_len = SHELL_LOG_BUF1_LEN, .list_out_idx = 0, .list_in_idx = 0, \
|
|
.free_blk_num = SHELL_LOG_BUF1_NUM, .ovf_cnt = 0},
|
|
};
|
|
|
|
#if (CONFIG_CACHE_ENABLE) && (CONFIG_LV_USE_DEMO_METER)
|
|
static __attribute__((section(".sram_cache"))) busy_queue_t log_busy_queue;
|
|
static __attribute__((section(".sram_cache"))) pending_queue_t pending_queue;
|
|
#else
|
|
static busy_queue_t log_busy_queue;
|
|
static pending_queue_t pending_queue;
|
|
#endif
|
|
|
|
#if (CONFIG_CACHE_ENABLE) && (CONFIG_LV_USE_DEMO_METER)
|
|
static __attribute__((section(".sram_cache"))) cmd_line_t cmd_line_buf;
|
|
#else
|
|
static cmd_line_t cmd_line_buf;
|
|
#endif
|
|
|
|
#if (LOG_DEV == DEV_UART)
|
|
static shell_dev_t * log_dev = &shell_uart;
|
|
#endif
|
|
#if (LOG_DEV == DEV_MAILBOX)
|
|
static shell_dev_t * log_dev = &shell_dev_mb;
|
|
#endif
|
|
|
|
#if (CMD_DEV == DEV_UART)
|
|
static shell_dev_t * cmd_dev = &shell_uart;
|
|
#endif
|
|
#if (CMD_DEV == DEV_MAILBOX)
|
|
static shell_dev_t * cmd_dev = &shell_dev_mb;
|
|
#endif
|
|
|
|
#if (CONFIG_SYS_CPU0)
|
|
static const char shell_fault_str[] = "\r\n!!some LOGs discarded!!\r\n";
|
|
static const u16 shell_fault_str_len = sizeof(shell_fault_str) - 1;
|
|
#endif
|
|
#if (!CONFIG_SYS_CPU0)
|
|
static const char shell_fault_str[] = "\r\n!!CPUx:some LOGs discarded!!\r\n";
|
|
static const u16 shell_fault_str_len = sizeof(shell_fault_str) - 1;
|
|
#endif
|
|
|
|
#if defined(FWD_CMD_TO_MBOX) || defined(RECV_CMD_LOG_FROM_MBOX)
|
|
|
|
typedef struct
|
|
{
|
|
log_cmd_t rsp_buf;
|
|
log_cmd_t ind_buf;
|
|
log_cmd_t common_log_buf;
|
|
} fwd_slave_data_t;
|
|
|
|
static u8 s_fwd_status = 0;
|
|
|
|
static fwd_slave_data_t ipc_fwd_data;
|
|
|
|
mb_chnl_cmd_t s_mb_cmd_buf;
|
|
|
|
static shell_dev_ipc_t * ipc_dev = &shell_dev_ipc;
|
|
|
|
static int result_fwd(int blk_id);
|
|
static u32 shell_ipc_rx_indication(u16 cmd, log_cmd_t *data, u16 cpu_id);
|
|
static void shell_ipc_tx_complete(u16 cmd);
|
|
static void set_fwd_state(int blk_id);
|
|
#endif
|
|
|
|
static const char shell_cmd_ovf_str[] = "\r\n!!some CMDs lost!!\r\n";
|
|
static const u16 shell_cmd_ovf_str_len = sizeof(shell_cmd_ovf_str) - 1;
|
|
static const char * shell_prompt_str[2] = {"\r\n$", "\r\n#"};
|
|
static u8 prompt_str_idx = 0;
|
|
static u8 cmd_rx_init_ok = 0;
|
|
static u8 log_handle_init_ok = 0;
|
|
|
|
static u8 fault_hint_print = 0;
|
|
static u32 shell_log_overflow = 0;
|
|
static u32 shell_log_count = 0;
|
|
static u8 shell_log_level = LOG_LEVEL;
|
|
static u8 log_flush_enabled = 1;
|
|
static u8 shell_assert_buff[SHELL_ASSERT_BUF_LEN];
|
|
static u8 log_tx_init_ok = 0;
|
|
|
|
static u32 shell_pm_wake_time = SHELL_TASK_WAKE_CYCLE; // wait cycles before enter sleep.
|
|
static u8 shell_pm_wake_flag = 1;
|
|
|
|
#if (CONFIG_CPU_CNT > 1) && (LOG_DEV != DEV_MAILBOX)
|
|
/* patch for multi-cpu dump. */
|
|
static u8 shell_log_owner_cpu = 0;
|
|
static u8 shell_log_req_cpu = 0;
|
|
#endif
|
|
|
|
#ifdef CONFIG_FREERTOS_SMP
|
|
#include "spinlock.h"
|
|
static volatile spinlock_t shell_spin_lock = SPIN_LOCK_INIT;
|
|
#endif // CONFIG_FREERTOS_SMP
|
|
|
|
|
|
static dynamic_log_node *dynamic_list_pop_front(void);
|
|
static void free_list_push_front(dynamic_log_node *dym_node);
|
|
static void check_and_free_dynamic_node(void);
|
|
static u8 *alloc_dynamic_log_blk(u16 log_len, u16 *blk_tag);
|
|
static void dynamic_list_push_back(dynamic_log_node *dym_node);
|
|
static u8 * alloc_buffer(int block_mode, u16 *blk_tag, u16 buf_len);
|
|
static inline void dynamic_list_push_back_by_buffer(u8 *packet_buf);
|
|
static int shell_log_raw_data_internel(bool hint, const u8 *data, u16 data_len);
|
|
static void output_insert_log(u16 buf_len, char *prefix, const char *format, va_list ap);
|
|
static void output_insert_data(const u8 *data, u16 data_len);
|
|
static dynamic_log_node *dynamic_list_switch(void);
|
|
static void log_handle_task( void *para );
|
|
|
|
static inline uint32_t shell_task_enter_critical()
|
|
{
|
|
uint32_t flags = rtos_disable_int();
|
|
|
|
#ifdef CONFIG_FREERTOS_SMP
|
|
spin_lock(&shell_spin_lock);
|
|
#endif // CONFIG_FREERTOS_SMP
|
|
|
|
return flags;
|
|
}
|
|
|
|
static inline void shell_task_exit_critical(uint32_t flags)
|
|
{
|
|
#ifdef CONFIG_FREERTOS_SMP
|
|
spin_unlock(&shell_spin_lock);
|
|
#endif // CONFIG_FREERTOS_SMP
|
|
|
|
rtos_enable_int(flags);
|
|
}
|
|
|
|
#if 1
|
|
|
|
static os_ext_event_t shell_task_event;
|
|
static os_ext_event_t shell_log_event;
|
|
|
|
static bool_t create_shell_event(void)
|
|
{
|
|
shell_task_event.event_flag = 0;
|
|
rtos_init_semaphore(&shell_task_event.event_semaphore, 1);
|
|
|
|
return bTRUE;
|
|
}
|
|
|
|
/* this API may be called from ISR. */
|
|
static bool_t set_shell_event(os_ext_event_t *ext_event, u32 event_flag)
|
|
{
|
|
BK_ASSERT(ext_event != NULL);
|
|
u32 int_mask;
|
|
|
|
int_mask = shell_task_enter_critical();
|
|
|
|
ext_event->event_flag |= event_flag;
|
|
|
|
shell_task_exit_critical(int_mask);
|
|
|
|
rtos_set_semaphore(&ext_event->event_semaphore);
|
|
|
|
return bTRUE;
|
|
}
|
|
|
|
static u32 wait_any_event(os_ext_event_t *ext_event, u32 timeout)
|
|
{
|
|
BK_ASSERT(ext_event != NULL);
|
|
u32 int_mask;
|
|
u32 event_flag;
|
|
|
|
int result;
|
|
|
|
while(bTRUE)
|
|
{
|
|
int_mask = shell_task_enter_critical();
|
|
|
|
event_flag = ext_event->event_flag;
|
|
ext_event->event_flag = 0;
|
|
|
|
shell_task_exit_critical(int_mask);
|
|
|
|
if((event_flag != 0) || (timeout == 0))
|
|
{
|
|
return event_flag;
|
|
}
|
|
else
|
|
{
|
|
result = rtos_get_semaphore(&ext_event->event_semaphore, timeout);
|
|
|
|
if(result == kTimeoutErr)
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
static beken_semaphore_t shell_semaphore; // will release from ISR.
|
|
|
|
static bool_t create_shell_event(void)
|
|
{
|
|
rtos_init_semaphore(&shell_semaphore, 1);
|
|
|
|
return bTRUE;
|
|
}
|
|
|
|
static bool_t set_shell_event(u32 event_flag)
|
|
{
|
|
(void)event_flag;
|
|
|
|
rtos_set_semaphore(&shell_semaphore);
|
|
|
|
return bTRUE;
|
|
}
|
|
|
|
static u32 wait_any_event(u32 timeout)
|
|
{
|
|
int result;
|
|
|
|
result = rtos_get_semaphore(&shell_semaphore, timeout);
|
|
|
|
if(result == kTimeoutErr)
|
|
return 0;
|
|
|
|
return SHELL_EVENT_RX_IND;
|
|
}
|
|
#endif
|
|
|
|
static void tx_req_process(void);
|
|
|
|
static u8 * alloc_log_blk(u16 log_len, u16 *blk_tag)
|
|
{
|
|
u16 free_blk_id;
|
|
u8 queue_id;
|
|
u8 ovf_cnt_saved = 0;
|
|
free_queue_t * free_q;
|
|
u8 * blk_buf = NULL;
|
|
|
|
u32 int_mask = shell_task_enter_critical();
|
|
|
|
for(queue_id = 0; queue_id < TBL_SIZE(free_queue); queue_id++)
|
|
{
|
|
free_q = &free_queue[queue_id];
|
|
|
|
/* queue ascending in blk_len. */
|
|
if(free_q->blk_len < log_len)
|
|
continue;
|
|
|
|
if(free_q->free_blk_num > 0)
|
|
{
|
|
free_blk_id = free_q->blk_list[free_q->list_out_idx];
|
|
|
|
// free_q->list_out_idx = (free_q->list_out_idx + 1) % free_q->blk_num;
|
|
if((free_q->list_out_idx + 1) < free_q->blk_num)
|
|
free_q->list_out_idx++;
|
|
else
|
|
free_q->list_out_idx = 0;
|
|
|
|
free_q->free_blk_num--;
|
|
|
|
blk_buf = &free_q->log_buf[free_blk_id * free_q->blk_len];
|
|
*blk_tag = MAKE_BLOCK_TAG(free_blk_id, queue_id);
|
|
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
if(ovf_cnt_saved == 0)
|
|
{
|
|
free_q->ovf_cnt++;
|
|
ovf_cnt_saved = 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
if(blk_buf == NULL)
|
|
{
|
|
shell_log_overflow++;
|
|
}
|
|
else
|
|
{
|
|
fault_hint_print = 0;
|
|
shell_log_count++;
|
|
}
|
|
|
|
shell_task_exit_critical(int_mask);
|
|
|
|
return blk_buf;
|
|
}
|
|
|
|
static bool_t free_log_blk(u16 block_tag)
|
|
{
|
|
u8 queue_id = GET_QUEUE_ID(block_tag);
|
|
u16 blk_id = GET_BLOCK_ID(block_tag);
|
|
free_queue_t *free_q;
|
|
|
|
if(queue_id >= TBL_SIZE(free_queue))
|
|
return bFALSE;
|
|
|
|
free_q = &free_queue[queue_id];
|
|
|
|
if(blk_id >= free_q->blk_num)
|
|
return bFALSE;
|
|
|
|
//disable_interrupt(); // called from tx-complete only, don't lock interrupt.
|
|
|
|
free_q->blk_list[free_q->list_in_idx] = blk_id;
|
|
|
|
//free_q->list_in_idx = (free_q->list_in_idx + 1) % free_q->blk_num;
|
|
if((free_q->list_in_idx + 1) < free_q->blk_num)
|
|
free_q->list_in_idx++;
|
|
else
|
|
free_q->list_in_idx = 0;
|
|
|
|
free_q->free_blk_num++;
|
|
|
|
//enable_interrupt(); // called from tx-complete only, don't lock interrupt.
|
|
|
|
return bTRUE;
|
|
}
|
|
|
|
static int merge_log_data(u16 blk_tag, u16 data_len)
|
|
{
|
|
if(pending_queue.list_out_idx == pending_queue.list_in_idx) /* queue empty! */
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
u8 queue_id = GET_QUEUE_ID(blk_tag);
|
|
u16 blk_id = GET_BLOCK_ID(blk_tag);
|
|
if(queue_id >= TBL_SIZE(free_queue)) /* not log buffer */
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
free_queue_t *free_q;
|
|
free_q = &free_queue[queue_id];
|
|
|
|
u8 * src_buf = NULL;
|
|
|
|
if(blk_id < free_q->blk_num)
|
|
{
|
|
src_buf = &free_q->log_buf[blk_id * free_q->blk_len];
|
|
}
|
|
else
|
|
return 0;
|
|
|
|
u16 pre_in_idx;
|
|
|
|
if(pending_queue.list_in_idx > 0)
|
|
pre_in_idx = pending_queue.list_in_idx - 1;
|
|
else
|
|
pre_in_idx = SHELL_LOG_PEND_NUM - 1;
|
|
|
|
queue_id = GET_QUEUE_ID(pending_queue.packet_list[pre_in_idx].blk_tag);
|
|
blk_id = GET_BLOCK_ID(pending_queue.packet_list[pre_in_idx].blk_tag);
|
|
if(queue_id >= TBL_SIZE(free_queue)) /* not log buffer */
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
u8 * dst_buf = NULL;
|
|
u16 buf_len = 0;
|
|
|
|
free_q = &free_queue[queue_id];
|
|
|
|
if(blk_id < free_q->blk_num)
|
|
{
|
|
dst_buf = &free_q->log_buf[blk_id * free_q->blk_len];
|
|
buf_len = free_q->blk_len;
|
|
}
|
|
else
|
|
return 0;
|
|
|
|
u16 cur_len = pending_queue.packet_list[pre_in_idx].packet_len;
|
|
|
|
if((cur_len + data_len) > buf_len) /* can be merged into one buffer? */
|
|
return 0;
|
|
|
|
memcpy(dst_buf + cur_len, src_buf, data_len);
|
|
|
|
pending_queue.packet_list[pre_in_idx].packet_len += data_len;
|
|
|
|
free_log_blk(blk_tag); /* merged, free the log buffer. */
|
|
|
|
return 1;
|
|
}
|
|
|
|
/* call this in interrupt !* DISABLED *! context. */
|
|
static void push_pending_queue(u16 blk_tag, u16 data_len)
|
|
{
|
|
//get_shell_mutex();
|
|
|
|
if(merge_log_data(blk_tag, data_len)) /* has been merged? if so, doesn't enqueue the log. */
|
|
return;
|
|
|
|
pending_queue.packet_list[pending_queue.list_in_idx].blk_tag = blk_tag;
|
|
pending_queue.packet_list[pending_queue.list_in_idx].packet_len = data_len;
|
|
|
|
//pending_queue.list_in_idx = (pending_queue.list_in_idx + 1) % SHELL_LOG_PEND_NUM;
|
|
if((pending_queue.list_in_idx + 1) < SHELL_LOG_PEND_NUM)
|
|
pending_queue.list_in_idx++;
|
|
else
|
|
pending_queue.list_in_idx = 0;
|
|
|
|
//release_shell_mutex();
|
|
|
|
return;
|
|
}
|
|
|
|
/* call this in interrupt !* DISABLED *! context. */
|
|
static void pull_pending_queue(u16 *blk_tag, u16 *data_len)
|
|
{
|
|
*blk_tag = pending_queue.packet_list[pending_queue.list_out_idx].blk_tag;
|
|
*data_len = pending_queue.packet_list[pending_queue.list_out_idx].packet_len;
|
|
|
|
//pending_queue.list_out_idx = (pending_queue.list_out_idx + 1) % SHELL_LOG_PEND_NUM;
|
|
if((pending_queue.list_out_idx + 1) < SHELL_LOG_PEND_NUM)
|
|
pending_queue.list_out_idx++;
|
|
else
|
|
pending_queue.list_out_idx = 0;
|
|
|
|
return;
|
|
}
|
|
|
|
int shell_assert_out(bool bContinue, char * format, ...);
|
|
|
|
/* 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 == SHELL_RSP_QUEUE_ID ) /* rsp. */
|
|
{
|
|
/* it is called from cmd_dev tx ISR. */
|
|
|
|
if ( (pbuf != cmd_line_buf.rsp_buff) || (blk_id != 0) )
|
|
{
|
|
/* something wrong!!! */
|
|
shell_assert_out(bTRUE, "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 == SHELL_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!!! */
|
|
shell_assert_out(bTRUE, "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 == SHELL_ROM_QUEUE_ID ) /* fault hints buffer, point to flash. */
|
|
{
|
|
/* it is called from cmd_dev tx ISR. */
|
|
|
|
if (blk_id == 1)
|
|
{
|
|
if(pbuf != (u8 *)shell_cmd_ovf_str)
|
|
{
|
|
/* something wrong!!! */
|
|
shell_assert_out(bTRUE, "FATAL:t-%x,p-%x\r\n", buf_tag, pbuf);
|
|
}
|
|
|
|
cmd_line_buf.cmd_ovf_hint = 0;
|
|
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
if( queue_id == SHELL_FWD_QUEUE_ID ) /* slave buffer. */
|
|
{
|
|
#if defined(RECV_CMD_LOG_FROM_MBOX)
|
|
if (log_handle_init_ok) {
|
|
set_fwd_state(blk_id);
|
|
} else {
|
|
result_fwd(blk_id);
|
|
}
|
|
return 1;
|
|
#endif
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
/* call from TX ISR. */
|
|
static void shell_cmd_tx_complete(u8 *pbuf, u16 buf_tag)
|
|
{
|
|
u32 int_mask = shell_task_enter_critical();
|
|
int tx_handled = cmd_tx_complete(pbuf, buf_tag);
|
|
|
|
if(tx_handled == 0) /* not handled. */
|
|
{
|
|
/* FAULT !!!! */
|
|
shell_assert_out(bTRUE, "FATAL:%x,\r\n", buf_tag);
|
|
}
|
|
|
|
shell_task_exit_critical(int_mask);
|
|
}
|
|
|
|
/* call from log TX ISR. */
|
|
static int log_tx_complete(u8 *pbuf, u16 buf_tag)
|
|
{
|
|
u16 block_tag;
|
|
u8 queue_id = GET_QUEUE_ID(buf_tag);
|
|
u16 blk_id = GET_BLOCK_ID(buf_tag);
|
|
free_queue_t *free_q;
|
|
|
|
if( queue_id == SHELL_ROM_QUEUE_ID ) /* fault hints buffer, point to flash. */
|
|
{
|
|
/* it is called from log_dev tx ISR. */
|
|
|
|
if (blk_id == 0)
|
|
{
|
|
if(pbuf != (u8 *)shell_fault_str)
|
|
{
|
|
/* something wrong!!! */
|
|
shell_assert_out(bTRUE, "FATAL:t-%x,p-%x\r\n", buf_tag, pbuf);
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
if (queue_id < TBL_SIZE(free_queue)) /* from log busy queue. */
|
|
{
|
|
/* it is called from log_dev tx ISR. */
|
|
|
|
free_q = &free_queue[queue_id];
|
|
|
|
block_tag = log_busy_queue.blk_list[log_busy_queue.list_out_idx];
|
|
|
|
if( ( buf_tag != block_tag ) || (blk_id >= free_q->blk_num) ||
|
|
( (&free_q->log_buf[blk_id * free_q->blk_len]) != pbuf) )
|
|
{
|
|
/* something wrong!!! */
|
|
/* FAULT !!!! */
|
|
shell_assert_out(bTRUE, "FATAL:%x,%x\r\n", buf_tag, block_tag);
|
|
|
|
return -1;
|
|
}
|
|
|
|
/* de-queue from busy queue. */
|
|
//log_busy_queue.list_out_idx = (log_busy_queue.list_out_idx + 1) % SHELL_LOG_BUSY_NUM;
|
|
if((log_busy_queue.list_out_idx + 1) < SHELL_LOG_BUSY_NUM)
|
|
log_busy_queue.list_out_idx++;
|
|
else
|
|
log_busy_queue.list_out_idx = 0;
|
|
|
|
log_busy_queue.free_cnt++;
|
|
|
|
/* free buffer to queue. */
|
|
free_log_blk(block_tag);
|
|
|
|
if (log_buf_semaphore != NULL) {
|
|
rtos_set_semaphore(&log_buf_semaphore);
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
if (queue_id == SHELL_DYM_QUEUE_ID) {
|
|
dynamic_log_node *node = dynamic_list_pop_front();
|
|
free_list_push_front(node);
|
|
if (log_buf_semaphore != NULL)
|
|
set_shell_event(&shell_log_event, SHELL_EVENT_DYM_FREE);
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/* call from TX ISR. */
|
|
static void shell_log_tx_complete(u8 *pbuf, u16 buf_tag)
|
|
{
|
|
u32 int_mask = shell_task_enter_critical();
|
|
|
|
int log_tx_req = log_tx_complete(pbuf, buf_tag);
|
|
|
|
if(log_tx_req == 1)
|
|
{
|
|
//set_shell_event(SHELL_EVENT_TX_REQ); // notify shell task to process the log tx.
|
|
tx_req_process();
|
|
}
|
|
else if(log_tx_req == 0) /* not handled. */
|
|
{
|
|
/* FAULT !!!! */
|
|
shell_assert_out(bTRUE, "FATAL:%x,\r\n", buf_tag);
|
|
}
|
|
|
|
shell_task_exit_critical(int_mask);
|
|
}
|
|
|
|
/* call from TX ISR. */
|
|
static void shell_tx_complete(u8 *pbuf, u16 buf_tag)
|
|
{
|
|
u32 int_mask = shell_task_enter_critical();
|
|
|
|
int tx_req = 0;
|
|
|
|
tx_req = cmd_tx_complete(pbuf, buf_tag);
|
|
|
|
if(tx_req == 0) /* not a cmd tx event, maybe it is a log tx event. */
|
|
{
|
|
tx_req = log_tx_complete(pbuf, buf_tag);
|
|
}
|
|
|
|
if(tx_req == 1)
|
|
{
|
|
//set_shell_event(SHELL_EVENT_TX_REQ); // notify shell task to process the log tx.
|
|
tx_req_process();
|
|
}
|
|
else if(tx_req == 0) /* not handled. */
|
|
{
|
|
/* FAULT !!!! */
|
|
shell_assert_out(bTRUE, "FATAL:%x,\r\n", buf_tag);
|
|
}
|
|
|
|
shell_task_exit_critical(int_mask);
|
|
}
|
|
|
|
/* call from RX ISR. */
|
|
static void shell_rx_indicate(void)
|
|
{
|
|
set_shell_event(&shell_task_event, SHELL_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)
|
|
{
|
|
if(msg_len == 0)
|
|
return;
|
|
|
|
u32 int_mask = shell_task_enter_critical();
|
|
|
|
if(log_dev != cmd_dev)
|
|
{
|
|
/* dedicated device for cmd, don't enqueue the msg to pending queue. */
|
|
/* send to cmd dev directly. */
|
|
/* 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);
|
|
|
|
}
|
|
else
|
|
{
|
|
/* shared device for cmd & log, push the rsp msg to pending queue. */
|
|
push_pending_queue(blk_tag, msg_len);
|
|
|
|
//set_shell_event(SHELL_EVENT_TX_REQ); // notify shell task to process the log tx. can't be called in int-disabled context.
|
|
tx_req_process();
|
|
}
|
|
|
|
shell_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, SHELL_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, SHELL_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;
|
|
}
|
|
|
|
static bool_t cmd_hint_out(void)
|
|
{
|
|
u16 hint_blk_tag = MAKE_BLOCK_TAG(1, SHELL_ROM_QUEUE_ID);
|
|
|
|
cmd_info_out((u8 *)shell_cmd_ovf_str, shell_cmd_ovf_str_len, hint_blk_tag);
|
|
|
|
return bTRUE;
|
|
}
|
|
|
|
static bool_t log_hint_out(void)
|
|
{
|
|
if(fault_hint_print) /* sent one hint since last allocation fail.*/
|
|
return bTRUE;
|
|
|
|
u16 hint_blk_tag = MAKE_BLOCK_TAG(0, SHELL_ROM_QUEUE_ID);
|
|
|
|
u32 int_mask = shell_task_enter_critical();
|
|
|
|
push_pending_queue(hint_blk_tag, shell_fault_str_len);
|
|
|
|
//set_shell_event(SHELL_EVENT_TX_REQ); // notify shell task to process the log tx.
|
|
tx_req_process();
|
|
|
|
fault_hint_print = 1;
|
|
|
|
shell_task_exit_critical(int_mask);
|
|
|
|
return bTRUE;
|
|
}
|
|
|
|
/* call this in interrupt !* DISABLED *! context. */
|
|
static void tx_req_process(void)
|
|
{
|
|
u8 *packet_buf = NULL;
|
|
u16 block_tag;
|
|
u16 log_len;
|
|
u16 tx_ready;
|
|
u16 blk_id;
|
|
u8 queue_id;
|
|
free_queue_t *free_q;
|
|
|
|
/* maybe tx_req is from tx_complete_callback, check if there any log in queue. */
|
|
if(pending_queue.list_out_idx == pending_queue.list_in_idx) /* queue empty! */
|
|
return;
|
|
|
|
if(log_busy_queue.free_cnt == 0)
|
|
return;
|
|
|
|
tx_ready = 0;
|
|
|
|
log_dev->dev_drv->io_ctrl(log_dev, SHELL_IO_CTRL_GET_STATUS, &tx_ready);
|
|
|
|
if(tx_ready == 0)
|
|
return;
|
|
|
|
/** ==== POP from pending queue ==== **/
|
|
pull_pending_queue(&block_tag, &log_len);
|
|
|
|
queue_id = GET_QUEUE_ID(block_tag);
|
|
blk_id = GET_BLOCK_ID(block_tag);
|
|
|
|
if (queue_id < TBL_SIZE(free_queue))
|
|
{
|
|
free_q = &free_queue[queue_id];
|
|
|
|
if(blk_id < free_q->blk_num)
|
|
{
|
|
packet_buf = &free_q->log_buf[blk_id * free_q->blk_len];
|
|
}
|
|
}
|
|
else if(queue_id == SHELL_RSP_QUEUE_ID)
|
|
{
|
|
packet_buf = cmd_line_buf.rsp_buff;
|
|
|
|
if((log_dev != cmd_dev) || (blk_id != 0))
|
|
{
|
|
shell_assert_out(bTRUE, "xFATAL: in Tx_req\r\n");
|
|
/* FAULT !!!! */
|
|
/* if log_dev is not the same with cmd_dev,
|
|
* rsp will not be pushed into pending queue.
|
|
*/
|
|
}
|
|
}
|
|
else if(queue_id == SHELL_IND_QUEUE_ID)
|
|
{
|
|
packet_buf = cmd_line_buf.cmd_ind_buff;
|
|
|
|
if((log_dev != cmd_dev) || (blk_id != 0))
|
|
{
|
|
shell_assert_out(bTRUE, "xFATAL: in Tx_req\r\n");
|
|
/* FAULT !!!! */
|
|
/* if log_dev is not the same with cmd_dev,
|
|
* indication will not be pushed into pending queue.
|
|
*/
|
|
}
|
|
}
|
|
else if(queue_id == SHELL_ROM_QUEUE_ID)
|
|
{
|
|
if(blk_id == 0)
|
|
{
|
|
packet_buf = (u8 *)shell_fault_str;
|
|
}
|
|
else if(blk_id == 1)
|
|
{
|
|
packet_buf = (u8 *)shell_cmd_ovf_str;
|
|
if(log_dev != cmd_dev)
|
|
{
|
|
shell_assert_out(bTRUE, "xFATAL: in Tx_req id=%x\r\n", blk_id);
|
|
/* FAULT !!!! */
|
|
/* if log_dev is not the same with cmd_dev,
|
|
* cmd_hint will not be pushed into pending queue.
|
|
*/
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* FAULT !!!! */
|
|
shell_assert_out(bTRUE, "xFATAL: in Tx_req id=%x\r\n", blk_id);
|
|
}
|
|
}
|
|
else if (queue_id == SHELL_DYM_QUEUE_ID)
|
|
{
|
|
dynamic_log_node *node = dynamic_list_switch();
|
|
packet_buf = node->ptr;
|
|
}
|
|
#if defined(FWD_CMD_TO_MBOX)
|
|
else if(queue_id == SHELL_FWD_QUEUE_ID)
|
|
{
|
|
if(blk_id == MBOX_RSP_BLK_ID)
|
|
{
|
|
packet_buf = (u8 *)ipc_fwd_data.rsp_buf.buf;
|
|
}
|
|
else if(blk_id == MBOX_IND_BLK_ID)
|
|
{
|
|
packet_buf = (u8 *)ipc_fwd_data.ind_buf.buf;
|
|
if(log_dev != cmd_dev)
|
|
{
|
|
shell_assert_out(bTRUE, "xFATAL: in Tx_req id=%x\r\n", blk_id);
|
|
/* FAULT !!!! */
|
|
/* if log_dev is not the same with cmd_dev,
|
|
* fwd_data will not be pushed into pending queue.
|
|
*/
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* FAULT !!!! */
|
|
shell_assert_out(bTRUE, "xFATAL: in Tx_req id=%x\r\n", blk_id);
|
|
}
|
|
}
|
|
#endif
|
|
else
|
|
{
|
|
/* FAULT !!!! */
|
|
shell_assert_out(bTRUE, "xFATAL: in Tx_req %x.\r\n", block_tag);
|
|
}
|
|
|
|
if(packet_buf == NULL)
|
|
return;
|
|
|
|
/* rom & rsp buff not enter busy-queue. */
|
|
if(queue_id < TBL_SIZE(free_queue))
|
|
{
|
|
log_busy_queue.free_cnt--;
|
|
log_busy_queue.blk_list[log_busy_queue.list_in_idx] = block_tag;
|
|
//log_busy_queue.list_in_idx = (log_busy_queue.list_in_idx + 1) % SHELL_LOG_BUSY_NUM;
|
|
if((log_busy_queue.list_in_idx + 1) < SHELL_LOG_BUSY_NUM)
|
|
log_busy_queue.list_in_idx++;
|
|
else
|
|
log_busy_queue.list_in_idx = 0;
|
|
}
|
|
|
|
log_dev->dev_drv->write_async(log_dev, packet_buf, log_len, block_tag); /* send to log dev driver. */
|
|
/* if driver return 0, should free log-block or not de-queue pending queue and try again. */
|
|
/* if return 1, push log-block into busy queue is OK. */
|
|
|
|
return;
|
|
}
|
|
|
|
static void rx_ind_process(void)
|
|
{
|
|
u16 read_cnt, buf_len, echo_len;
|
|
u16 i = 0;
|
|
u8 cmd_rx_done = bFALSE, need_backspace = bFALSE;
|
|
#if CONFIG_AT_DATA_MODE
|
|
int at_data_len = 0;
|
|
#endif
|
|
if(cmd_dev->dev_type == SHELL_DEV_MAILBOX)
|
|
{
|
|
buf_len = SHELL_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);
|
|
|
|
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;
|
|
}
|
|
|
|
/* patch for BK_REG tool. */
|
|
if(cmd_line_buf.bkreg_state == BKREG_WAIT_01)
|
|
{
|
|
if(rx_temp_buff[i] == 0x01)
|
|
cmd_line_buf.bkreg_state = BKREG_WAIT_E0;
|
|
}
|
|
else if(cmd_line_buf.bkreg_state == BKREG_WAIT_E0)
|
|
{
|
|
if(rx_temp_buff[i] == 0xE0)
|
|
cmd_line_buf.bkreg_state = BKREG_WAIT_FC;
|
|
else if(rx_temp_buff[i] != 0x01)
|
|
cmd_line_buf.bkreg_state = BKREG_WAIT_01;
|
|
}
|
|
else if(cmd_line_buf.bkreg_state == BKREG_WAIT_FC)
|
|
{
|
|
if(rx_temp_buff[i] == 0xFC)
|
|
{
|
|
cmd_line_buf.cur_cmd_type = CMD_TYPE_BKREG;
|
|
|
|
cmd_line_buf.cmd_buff[0] = 0x01;
|
|
cmd_line_buf.cmd_buff[1] = 0xE0;
|
|
cmd_line_buf.cmd_buff[2] = 0xFC;
|
|
|
|
cmd_line_buf.cmd_data_len = 3;
|
|
|
|
echo_len = 0; // cann't echo anything.
|
|
|
|
continue;
|
|
}
|
|
else if(rx_temp_buff[i] != 0x01)
|
|
cmd_line_buf.bkreg_state = BKREG_WAIT_01;
|
|
else
|
|
cmd_line_buf.bkreg_state = BKREG_WAIT_E0;
|
|
}
|
|
|
|
}
|
|
|
|
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++;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
/* patch for BK_REG tool. */
|
|
if(cmd_line_buf.cur_cmd_type == CMD_TYPE_BKREG)
|
|
{
|
|
echo_len = 0; // cann't echo anything.
|
|
|
|
/* p[0] = 0x1, p[1]=0xe0, p[2]=0xfc, p[3]=len. */
|
|
if(cmd_line_buf.cmd_data_len == 3)
|
|
{
|
|
cmd_line_buf.bkreg_left_byte = rx_temp_buff[i] + 1; // +1, because will -1 in next process.
|
|
|
|
if((cmd_line_buf.bkreg_left_byte + 3) >= sizeof(cmd_line_buf.cmd_buff)) // 3 bytes of header + 1 byte of len.
|
|
{
|
|
cmd_line_buf.cmd_data_len = 0;
|
|
|
|
cmd_rx_done = bTRUE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
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++;
|
|
}
|
|
|
|
cmd_line_buf.bkreg_left_byte--;
|
|
|
|
if(cmd_line_buf.bkreg_left_byte == 0)
|
|
{
|
|
cmd_rx_done = bTRUE;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if( cmd_rx_done )
|
|
{
|
|
/* patch for BK_REG tool. */
|
|
if(cmd_line_buf.cur_cmd_type == CMD_TYPE_BKREG)
|
|
{
|
|
break; // cann't echo anything.
|
|
}
|
|
|
|
if(cmd_line_buf.echo_enable)
|
|
{
|
|
echo_out(&rx_temp_buff[0], echo_len);
|
|
echo_out((u8 *)"\r\n", 2);
|
|
}
|
|
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
/* patch for BK_REG tool. */
|
|
if( (cmd_line_buf.cur_cmd_type == CMD_TYPE_BKREG) ||
|
|
((cmd_line_buf.cur_cmd_type == CMD_TYPE_INVALID) && (cmd_line_buf.bkreg_state != BKREG_WAIT_01)) )
|
|
{
|
|
// cann't echo anything.
|
|
}
|
|
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 *)shell_prompt_str[prompt_str_idx], 3);
|
|
echo_len = 0;
|
|
}
|
|
}
|
|
echo_out(rx_temp_buff, echo_len);
|
|
}
|
|
}
|
|
|
|
if(read_cnt < buf_len) /* all data are read out. */
|
|
break;
|
|
}
|
|
|
|
if(read_cnt < buf_len) /* all data are read out. */
|
|
{
|
|
}
|
|
else /* cmd pends in buffer, handle it in new loop cycle. */
|
|
{
|
|
set_shell_event(&shell_task_event, SHELL_EVENT_RX_IND);
|
|
}
|
|
|
|
/* can re-use *buf_len*. */
|
|
if( cmd_rx_done )
|
|
{
|
|
if(cmd_line_buf.cur_cmd_type == CMD_TYPE_TEXT)
|
|
{
|
|
if(cmd_line_buf.cmd_ovf_hint == 0)
|
|
{
|
|
u16 rx_ovf = 0;
|
|
cmd_dev->dev_drv->io_ctrl(cmd_dev, SHELL_IO_CTRL_GET_RX_STATUS, &rx_ovf);
|
|
|
|
if(rx_ovf != 0)
|
|
{
|
|
cmd_hint_out();
|
|
cmd_line_buf.cmd_ovf_hint = 1;
|
|
}
|
|
}
|
|
|
|
rtos_get_semaphore(&cmd_line_buf.rsp_buf_semaphore, SHELL_WAIT_OUT_TIME);
|
|
|
|
cmd_line_buf.rsp_buff[0] = 0;
|
|
/* handle command. */
|
|
if( cmd_line_buf.cmd_data_len > 0 )
|
|
#if defined(CONFIG_AT) && defined(CONFIG_SYS_CPU0)
|
|
#if (CONFIG_UART_PRINT_PORT == AT_UART_PORT_CFG)
|
|
atsvr_msg_get_input((char *)cmd_line_buf.cmd_buff, cmd_line_buf.cmd_data_len, (char *)cmd_line_buf.rsp_buff, SHELL_RSP_BUF_LEN - 4);
|
|
#else
|
|
handle_shell_input( (char *)cmd_line_buf.cmd_buff, cmd_line_buf.cmd_data_len, (char *)cmd_line_buf.rsp_buff, SHELL_RSP_BUF_LEN - 4 );
|
|
#endif
|
|
#else
|
|
handle_shell_input( (char *)cmd_line_buf.cmd_buff, cmd_line_buf.cmd_data_len, (char *)cmd_line_buf.rsp_buff, SHELL_RSP_BUF_LEN - 4 );
|
|
#endif
|
|
cmd_line_buf.rsp_buff[SHELL_RSP_BUF_LEN - 4] = 0;
|
|
|
|
buf_len = strlen((char *)cmd_line_buf.rsp_buff);
|
|
if(buf_len > (SHELL_RSP_BUF_LEN - 4))
|
|
buf_len = (SHELL_RSP_BUF_LEN - 4);
|
|
buf_len += sprintf((char *)&cmd_line_buf.rsp_buff[buf_len], shell_prompt_str[prompt_str_idx]);
|
|
|
|
cmd_rsp_out(cmd_line_buf.rsp_buff, buf_len);
|
|
|
|
rtos_delay_milliseconds(4); // delay 4 ms, so idle task has time to release resources of delete-pendign task.
|
|
}
|
|
|
|
/* patch for BK_REG tool. */
|
|
if(cmd_line_buf.cur_cmd_type == CMD_TYPE_BKREG)
|
|
{
|
|
if(cmd_line_buf.cmd_data_len > 3)
|
|
{
|
|
#if CONFIG_BKREG
|
|
extern int bkreg_run_command(const char *cmd, int flag);
|
|
|
|
bkreg_run_command((const char *)&cmd_line_buf.cmd_buff[0], (int)cmd_line_buf.cmd_data_len);
|
|
#endif // CONFIG_BKREG
|
|
}
|
|
}
|
|
|
|
cmd_line_buf.cur_cmd_type = CMD_TYPE_INVALID; /* reset cmd line to interpret new cmd. */
|
|
cmd_line_buf.cmd_data_len = 0;
|
|
cmd_line_buf.bkreg_state = BKREG_WAIT_01; /* reset state machine. */
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
extern gpio_id_t bk_uart_get_rx_gpio(uart_id_t id);
|
|
|
|
static void shell_rx_wakeup(int gpio_id);
|
|
|
|
static void shell_power_save_enter(void)
|
|
{
|
|
if(log_tx_init_ok)
|
|
{
|
|
log_dev->dev_drv->io_ctrl(log_dev, SHELL_IO_CTRL_TX_SUSPEND, (void *)(u32)log_flush_enabled);
|
|
}
|
|
|
|
if(cmd_rx_init_ok)
|
|
{
|
|
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);
|
|
|
|
bk_uart_pm_backup(uart_port);
|
|
|
|
u32 gpio_id = bk_uart_get_rx_gpio(uart_port);
|
|
|
|
bk_gpio_register_isr(gpio_id, (gpio_isr_t)shell_rx_wakeup);
|
|
}
|
|
}
|
|
}
|
|
|
|
static void shell_power_save_exit(void)
|
|
{
|
|
if(log_tx_init_ok)
|
|
{
|
|
log_dev->dev_drv->io_ctrl(log_dev, SHELL_IO_CTRL_TX_RESUME, NULL);
|
|
}
|
|
|
|
if(cmd_rx_init_ok)
|
|
{
|
|
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_LOG, 0, 0);
|
|
shell_pm_wake_flag = 1;
|
|
shell_pm_wake_time = SHELL_TASK_WAKE_CYCLE;
|
|
}
|
|
|
|
static void shell_rx_wakeup(int gpio_id)
|
|
{
|
|
wakeup_process();
|
|
set_shell_event(&shell_task_event, SHELL_EVENT_WAKEUP);
|
|
|
|
shell_log_raw_data((const u8*)"wakeup\r\n", sizeof("wakeup\r\n") - 1);
|
|
|
|
if(cmd_dev->dev_type == SHELL_DEV_UART)
|
|
{
|
|
bk_gpio_register_isr(gpio_id, NULL);
|
|
}
|
|
}
|
|
|
|
// if use psram as dynamic log memory, first malloc will init psram.
|
|
// in the process of psram-initialization, will output some logs.
|
|
// in the case, logs psram-init can not use dynamic logs.
|
|
// so, initialization psram in advace will prevent logs discard at startup.
|
|
static void dynamic_log_init(void)
|
|
{
|
|
#if CONFIG_PSRAM_AS_SYS_MEMORY
|
|
bool bk_psram_heap_init_flag_get();
|
|
if (bk_psram_heap_init_flag_get() == bFALSE) {
|
|
void *ptr = LOG_MALLOC(0);
|
|
if (ptr != NULL)
|
|
LOG_FREE(ptr);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
static void shell_log_tx_init(void)
|
|
{
|
|
u16 i;
|
|
|
|
if(log_tx_init_ok != 0)
|
|
return;
|
|
|
|
for(i = 0; i < SHELL_LOG_BUF1_NUM; i++)
|
|
{
|
|
buff1_free_list[i] = i;
|
|
}
|
|
for(i = 0; i < SHELL_LOG_BUF2_NUM; i++)
|
|
{
|
|
buff2_free_list[i] = i;
|
|
}
|
|
for(i = 0; i < SHELL_LOG_BUF3_NUM; i++)
|
|
{
|
|
buff3_free_list[i] = i;
|
|
}
|
|
|
|
memset(&log_busy_queue, 0, sizeof(log_busy_queue));
|
|
memset(&pending_queue, 0, sizeof(pending_queue));
|
|
|
|
log_busy_queue.free_cnt = SHELL_LOG_BUSY_NUM;
|
|
|
|
log_dev->dev_drv->init(log_dev);
|
|
log_dev->dev_drv->open(log_dev, shell_log_tx_complete, NULL); // tx log.
|
|
|
|
#if defined(FWD_CMD_TO_MBOX) || defined(RECV_CMD_LOG_FROM_MBOX)
|
|
ipc_dev->dev_drv->init(ipc_dev);
|
|
ipc_dev->dev_drv->open(ipc_dev, (shell_ipc_rx_t)shell_ipc_rx_indication, (shell_ipc_tx_complete_t)shell_ipc_tx_complete); /* register rx-callback to copy log data to buffer. */
|
|
#endif
|
|
|
|
log_tx_init_ok = 1;
|
|
|
|
{
|
|
pm_cb_conf_t enter_config;
|
|
enter_config.cb = (pm_cb)shell_power_save_enter;
|
|
enter_config.args = NULL;
|
|
|
|
pm_cb_conf_t exit_config;
|
|
exit_config.cb = (pm_cb)shell_power_save_exit;
|
|
exit_config.args = NULL;
|
|
|
|
#if 0
|
|
bk_pm_sleep_register_cb(PM_MODE_LOW_VOLTAGE, PM_DEV_ID_UART1, &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);
|
|
|
|
shell_rx_wakeup(bk_uart_get_rx_gpio(uart_port));
|
|
#endif
|
|
|
|
u8 uart_port = UART_ID_MAX;
|
|
log_dev->dev_drv->io_ctrl(log_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);
|
|
}
|
|
|
|
dynamic_log_init();
|
|
}
|
|
|
|
#define LOG_HANDLE_TASK_STACK 0x200
|
|
beken_thread_t log_thread_handle = NULL;
|
|
void create_log_handle_task(void)
|
|
{
|
|
int ret;
|
|
shell_log_event.event_flag = 0;
|
|
|
|
check_and_free_dynamic_node();
|
|
|
|
rtos_init_semaphore(&shell_log_event.event_semaphore, 1);
|
|
|
|
rtos_init_semaphore_ex(&log_buf_semaphore, 1, 1); // semaphore for log block mode.
|
|
|
|
ret = rtos_create_thread(&log_thread_handle,
|
|
4,
|
|
"log_hanlder",
|
|
(beken_thread_function_t)log_handle_task,
|
|
LOG_HANDLE_TASK_STACK,
|
|
0);
|
|
if (ret != 0) {
|
|
os_printf("create log handler task fail!\r\n");
|
|
return;
|
|
}
|
|
log_handle_init_ok = 1;
|
|
}
|
|
|
|
|
|
static void shell_task_init(void)
|
|
{
|
|
if(log_tx_init_ok == 0)
|
|
{
|
|
shell_log_tx_init();
|
|
}
|
|
|
|
/* ================================ cmd channel initialize ==================================== */
|
|
cmd_line_buf.cur_cmd_type = CMD_TYPE_INVALID;
|
|
cmd_line_buf.cmd_data_len = 0;
|
|
cmd_line_buf.bkreg_state = BKREG_WAIT_01;
|
|
cmd_line_buf.echo_enable = bTRUE;
|
|
cmd_line_buf.cmd_ovf_hint = 0;
|
|
|
|
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.
|
|
|
|
/* cmd fwd */
|
|
#if defined(FWD_CMD_TO_MBOX)
|
|
rtos_init_semaphore_ex(&cmd_line_buf.cmd_fwd_semaphore, 1, 0); // fwd to CPUx
|
|
#endif
|
|
|
|
create_shell_event();
|
|
|
|
if(log_dev != cmd_dev)
|
|
{
|
|
cmd_dev->dev_drv->init(cmd_dev);
|
|
cmd_dev->dev_drv->open(cmd_dev, shell_cmd_tx_complete, shell_rx_indicate); // rx cmd, tx rsp.
|
|
|
|
// log_dev->dev_drv->init(log_dev);
|
|
// log_dev->dev_drv->open(log_dev, shell_log_tx_complete, NULL); // tx log.
|
|
}
|
|
else
|
|
{
|
|
u32 int_mask = shell_task_enter_critical();
|
|
cmd_dev->dev_drv->io_ctrl(cmd_dev, SHELL_IO_CTRL_SET_RX_ISR, shell_rx_indicate); // rx cmd, tx (rsp & log).
|
|
cmd_dev->dev_drv->io_ctrl(cmd_dev, SHELL_IO_CTRL_SET_TX_CMPL_ISR, shell_tx_complete); // rx cmd, tx (rsp & log).
|
|
shell_task_exit_critical(int_mask);
|
|
}
|
|
|
|
cmd_rx_init_ok = 1;
|
|
|
|
{
|
|
pm_cb_conf_t enter_config;
|
|
enter_config.cb = (pm_cb)shell_power_save_enter;
|
|
enter_config.args = NULL;
|
|
|
|
pm_cb_conf_t exit_config;
|
|
exit_config.cb = (pm_cb)shell_power_save_exit;
|
|
exit_config.args = NULL;
|
|
|
|
#if 0
|
|
bk_pm_sleep_register_cb(PM_MODE_LOW_VOLTAGE, PM_DEV_ID_UART1, &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);
|
|
|
|
shell_rx_wakeup(bk_uart_get_rx_gpio(uart_port));
|
|
#endif
|
|
|
|
uart_id_t 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);
|
|
|
|
shell_rx_wakeup(bk_uart_get_rx_gpio(uart_port));
|
|
}
|
|
|
|
if(ate_is_enabled())
|
|
prompt_str_idx = 1;
|
|
else
|
|
prompt_str_idx = 0;
|
|
|
|
}
|
|
|
|
#if defined(RECV_CMD_LOG_FROM_MBOX)
|
|
static void set_fwd_state(int blk_id)
|
|
{
|
|
u32 int_mask = shell_task_enter_critical();
|
|
s_fwd_status |= 1 << blk_id;
|
|
shell_task_exit_critical(int_mask);
|
|
set_shell_event(&shell_log_event, SHELL_EVENT_MB_FWD);
|
|
}
|
|
|
|
static int get_fwd_blk_id(void)
|
|
{
|
|
int blk_id = -1;
|
|
u32 int_mask = shell_task_enter_critical();
|
|
for (int i = 0; i < 3; i++) {
|
|
if (s_fwd_status & (1 << i)) {
|
|
int mask = ~(1 << i);
|
|
s_fwd_status &= mask;
|
|
blk_id = i;
|
|
break;
|
|
}
|
|
}
|
|
shell_task_exit_critical(int_mask);
|
|
return blk_id;
|
|
}
|
|
|
|
#define FORWARD_TRY_COUNT 10
|
|
static void fwd_mb_log_state(void)
|
|
{
|
|
int ret = 0;
|
|
int blk_id = get_fwd_blk_id();
|
|
if (blk_id < 0) {
|
|
return;
|
|
}
|
|
int try_cnt = FORWARD_TRY_COUNT;
|
|
do {
|
|
ret = result_fwd(blk_id);
|
|
try_cnt--;
|
|
if (ret) {
|
|
break;
|
|
}
|
|
if (try_cnt == 0) {
|
|
shell_assert_out(1, "Error: forward mb log state fail! blk: %x\r\n", blk_id);
|
|
break;
|
|
}
|
|
rtos_delay_milliseconds(SHELL_LOG_FWD_WAIT_TIME);
|
|
} while (1);
|
|
}
|
|
|
|
static void output_mb_log_ex(void)
|
|
{
|
|
// it will not hint log discarded from cpu1.
|
|
shell_log_raw_data_internel(1, ipc_fwd_data.common_log_buf.buf, ipc_fwd_data.common_log_buf.len);
|
|
set_fwd_state(MBOX_COMMON_BLK_ID);
|
|
}
|
|
|
|
#define INVALID_LOG_TAG 0xFFFF
|
|
void reset_forward_log_status(void)
|
|
{
|
|
u32 int_mask = shell_task_enter_critical();
|
|
|
|
ipc_fwd_data.rsp_buf.tag = INVALID_LOG_TAG;
|
|
ipc_fwd_data.ind_buf.tag = INVALID_LOG_TAG;
|
|
ipc_fwd_data.common_log_buf.tag = INVALID_LOG_TAG;
|
|
|
|
shell_task_exit_critical(int_mask);
|
|
}
|
|
#endif
|
|
|
|
static void log_handle_task( void *para )
|
|
{
|
|
u32 Events;
|
|
while(bTRUE)
|
|
{
|
|
Events = wait_any_event(&shell_log_event, BEKEN_WAIT_FOREVER);
|
|
|
|
if(Events & SHELL_EVENT_DYM_FREE)
|
|
{
|
|
check_and_free_dynamic_node();
|
|
}
|
|
#if defined(RECV_CMD_LOG_FROM_MBOX)
|
|
if(Events & SHELL_EVENT_MB_LOG)
|
|
{
|
|
output_mb_log_ex();
|
|
}
|
|
if(Events & SHELL_EVENT_MB_FWD)
|
|
{
|
|
fwd_mb_log_state();
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
|
|
void shell_task( void *para )
|
|
{
|
|
u32 Events;
|
|
u32 timeout = SHELL_TASK_WAIT_TIME;
|
|
|
|
shell_task_init();
|
|
|
|
echo_out((u8 *)shell_prompt_str[prompt_str_idx], 3);
|
|
|
|
while(bTRUE)
|
|
{
|
|
Events = wait_any_event(&shell_task_event, timeout); // WAIT_EVENT;
|
|
|
|
if(Events & SHELL_EVENT_TX_REQ)
|
|
{
|
|
echo_out((u8 *)"Unsolicited", sizeof("Unsolicited") - 1);
|
|
echo_out((u8 *)shell_prompt_str[prompt_str_idx], 3);
|
|
}
|
|
|
|
if(Events & SHELL_EVENT_RX_IND)
|
|
{
|
|
wakeup_process();
|
|
rx_ind_process();
|
|
}
|
|
|
|
if(Events & SHELL_EVENT_WAKEUP)
|
|
{
|
|
// TODO
|
|
}
|
|
|
|
if(Events == 0)
|
|
{
|
|
if(shell_pm_wake_time > 0)
|
|
shell_pm_wake_time--;
|
|
|
|
if(shell_pm_wake_time == 0)
|
|
{
|
|
if(shell_pm_wake_flag != 0)
|
|
{
|
|
shell_pm_wake_flag = 0;
|
|
bk_pm_module_vote_sleep_ctrl(PM_SLEEP_MODULE_NAME_LOG, 1, 0);
|
|
//shell_log_raw_data((const u8*)"sleep\r\n", sizeof("sleep\r\n") - 1);
|
|
}
|
|
}
|
|
}
|
|
|
|
if(shell_pm_wake_flag)
|
|
{
|
|
timeout = SHELL_TASK_WAIT_TIME;
|
|
}
|
|
else
|
|
{
|
|
timeout = BEKEN_WAIT_FOREVER;
|
|
}
|
|
}
|
|
}
|
|
|
|
int shell_get_cpu_id(void)
|
|
{
|
|
#ifdef CONFIG_FREERTOS_SMP
|
|
return rtos_get_core_id();
|
|
#elif (CONFIG_CPU_CNT > 1)
|
|
|
|
if(log_dev->dev_type == SHELL_DEV_MAILBOX)
|
|
return SELF_CPU;
|
|
|
|
#endif
|
|
|
|
return -1;
|
|
}
|
|
|
|
static int shell_cpu_check_valid(void)
|
|
{
|
|
#if (CONFIG_CPU_CNT > 1) && (LOG_DEV != DEV_MAILBOX)
|
|
|
|
if(shell_log_owner_cpu == 0)
|
|
return 1;
|
|
|
|
u8 req_cpu = 0;
|
|
#ifdef CONFIG_FREERTOS_SMP
|
|
req_cpu = 1 << rtos_get_core_id();
|
|
#else
|
|
req_cpu = shell_log_req_cpu;
|
|
#endif
|
|
|
|
if(shell_log_owner_cpu == req_cpu)
|
|
return 1;
|
|
|
|
return 0;
|
|
|
|
#else
|
|
|
|
return 1;
|
|
|
|
#endif
|
|
}
|
|
|
|
int shell_level_check_valid(int level)
|
|
{
|
|
if( !shell_cpu_check_valid() )
|
|
return 0;
|
|
|
|
if(level > shell_log_level)
|
|
return 0;
|
|
|
|
return 1;
|
|
}
|
|
|
|
#if 0
|
|
int shell_log_out_sync(int level, char *prefix, const char *format, va_list ap)
|
|
{
|
|
u32 int_mask;
|
|
char *pbuf;
|
|
u16 data_len = 0, buf_len;
|
|
|
|
if( !shell_level_check_valid(level) )
|
|
return 0;
|
|
|
|
pbuf = (char *)&shell_assert_buff[0];
|
|
buf_len = sizeof(shell_assert_buff);
|
|
|
|
int_mask = shell_task_enter_critical();
|
|
|
|
if(prefix != NULL)
|
|
{
|
|
strncpy(pbuf, prefix, buf_len);
|
|
pbuf[buf_len - 1] = 0;
|
|
data_len = strlen(pbuf);
|
|
}
|
|
else
|
|
{
|
|
data_len = 0;
|
|
}
|
|
|
|
data_len += vsnprintf( &pbuf[data_len], buf_len - data_len, format, ap );
|
|
|
|
if(data_len >= buf_len)
|
|
data_len = buf_len - 1;
|
|
|
|
if ( (data_len != 0) && (pbuf[data_len - 1] == '\n') )
|
|
{
|
|
if ((data_len == 1) || (pbuf[data_len - 2] != '\r'))
|
|
{
|
|
pbuf[data_len] = '\n'; /* '\n\0' replaced with '\r\n', may not end with '\0'. */
|
|
pbuf[data_len - 1] = '\r';
|
|
data_len++;
|
|
}
|
|
}
|
|
|
|
log_dev->dev_drv->write_sync(log_dev, (u8 *)pbuf, data_len);
|
|
|
|
shell_task_exit_critical(int_mask);
|
|
|
|
return 1;
|
|
}
|
|
#endif
|
|
|
|
static int shell_log_raw_data_internel(bool hint, const u8 *data, u16 data_len)
|
|
{
|
|
u8 *packet_buf;
|
|
u16 blk_tag;
|
|
|
|
if( !log_tx_init_ok )
|
|
{
|
|
shell_log_tx_init();
|
|
}
|
|
|
|
if( !shell_cpu_check_valid() )
|
|
return 0;
|
|
|
|
if (NULL == data || 0 == data_len)
|
|
{
|
|
return 0; // bFALSE;
|
|
}
|
|
|
|
packet_buf = alloc_buffer(s_block_mode, &blk_tag, data_len);
|
|
|
|
if (NULL == packet_buf)
|
|
{
|
|
if (hint == 0)
|
|
return 0;
|
|
|
|
if (s_block_mode & LOG_BLOCK_MASK) {
|
|
output_insert_data(data, data_len);
|
|
return 1;
|
|
}
|
|
else
|
|
log_hint_out();
|
|
return 0; // bFALSE;
|
|
}
|
|
|
|
memcpy(packet_buf, data, data_len);
|
|
|
|
u32 int_mask = shell_task_enter_critical();
|
|
|
|
if ( GET_QUEUE_ID(blk_tag) == SHELL_DYM_QUEUE_ID ) {
|
|
dynamic_list_push_back_by_buffer(packet_buf);
|
|
}
|
|
|
|
// push to pending queue.
|
|
push_pending_queue(blk_tag, data_len);
|
|
|
|
// notify shell task to process the log tx.
|
|
tx_req_process();
|
|
|
|
shell_task_exit_critical(int_mask);
|
|
|
|
return 1; // bTRUE;
|
|
}
|
|
|
|
int shell_log_raw_data(const u8 *data, u16 data_len)
|
|
{
|
|
return shell_log_raw_data_internel(1, data, data_len);
|
|
}
|
|
|
|
static int check_block_mode(int block_mode)
|
|
{
|
|
block_mode &= s_block_mode;
|
|
if (rtos_local_irq_disabled() || rtos_is_in_interrupt_context() ||
|
|
log_buf_semaphore == NULL || rtos_is_scheduler_suspended()) {
|
|
block_mode &= LOG_NONBLOCK_MODE;
|
|
}
|
|
return block_mode & LOG_BLOCK_MASK;
|
|
}
|
|
|
|
static inline int transfer_line_end(int data_len, char * ptr)
|
|
{
|
|
if ( (data_len != 0) && (ptr[data_len - 1] == '\n') )
|
|
{
|
|
if (data_len == 1 || ptr[data_len - 2] != '\r')
|
|
{
|
|
ptr[data_len] = '\n';
|
|
ptr[data_len - 1] = '\r';
|
|
(data_len)++;
|
|
}
|
|
}
|
|
return data_len;
|
|
}
|
|
|
|
static int combine_log_with_prefix(const char *prefix, char *pbuf, int buf_len, const char *format, va_list ap)
|
|
{
|
|
int log_len = 0;
|
|
if (prefix != NULL) {
|
|
strcpy(pbuf, prefix);
|
|
log_len = strlen(prefix);
|
|
}
|
|
log_len += vsnprintf(&pbuf[log_len], buf_len - log_len, format, ap);
|
|
BK_ASSERT(log_len <= buf_len);
|
|
if (log_len == buf_len) {
|
|
log_len = buf_len - 1;
|
|
}
|
|
log_len = transfer_line_end(log_len, pbuf);
|
|
return log_len;
|
|
}
|
|
|
|
// check whether dynamic log available.
|
|
static inline bool get_dynamic_log_status(int block_mode, u16 buf_len)
|
|
{
|
|
block_mode &= s_block_mode;
|
|
return (s_dynamic_log_num < SHELL_DYM_LOG_NUM_MAX) &&
|
|
(block_mode & LOG_MALLOC_MASK) &&
|
|
(buf_len + s_dynamic_log_total_len <= CONFIG_DYM_LOG_MEM_MAX);
|
|
}
|
|
|
|
#define LOG_TRY_ALLOC_COUNT 5
|
|
/* alloc log buffer from static memory or dynamic memory */
|
|
static u8 * alloc_buffer(int block_mode, u16 *blk_tag, u16 buf_len)
|
|
{
|
|
u8 *packet_buf = NULL;
|
|
int try_cnt = LOG_TRY_ALLOC_COUNT;
|
|
do {
|
|
if (buf_len <= SHELL_LOG_BUF1_LEN) {
|
|
packet_buf = alloc_log_blk(buf_len, blk_tag);
|
|
if (packet_buf != NULL) {
|
|
break;
|
|
}
|
|
} else {
|
|
/* while long log is more than static block maximum buffer and cannot use dynamic log, drop it. */
|
|
if ((block_mode & LOG_MALLOC_MASK) == 0) {
|
|
break;
|
|
}
|
|
}
|
|
if (get_dynamic_log_status(block_mode, buf_len)) {
|
|
packet_buf = alloc_dynamic_log_blk(buf_len, blk_tag);
|
|
if (packet_buf != NULL) {
|
|
break;
|
|
}
|
|
}
|
|
if (check_block_mode(block_mode) == 0) {
|
|
break;
|
|
}
|
|
rtos_get_semaphore(&log_buf_semaphore, SHELL_LOG_BLOCK_TIME);
|
|
} while (try_cnt--);
|
|
return packet_buf;
|
|
}
|
|
|
|
void shell_log_out_port(int block_mode, int level, char *prefix, const char *format, va_list ap)
|
|
{
|
|
u8 * packet_buf;
|
|
u16 blk_tag;
|
|
u16 log_len = 0, buf_len;
|
|
|
|
if( !log_tx_init_ok )
|
|
{
|
|
shell_log_tx_init();
|
|
}
|
|
|
|
if( !shell_level_check_valid(level) )
|
|
{
|
|
return ;
|
|
}
|
|
|
|
buf_len = vsnprintf( NULL, 0, format, ap ) + 1; /* for '\0' */
|
|
|
|
if(prefix != NULL)
|
|
buf_len += strlen(prefix);
|
|
|
|
if(buf_len == 0)
|
|
return;
|
|
|
|
packet_buf = alloc_buffer(block_mode, &blk_tag, buf_len);
|
|
|
|
if(packet_buf == NULL)
|
|
{
|
|
if (block_mode & s_block_mode & LOG_BLOCK_MASK)
|
|
output_insert_log(buf_len, prefix, format, ap);
|
|
else
|
|
log_hint_out();
|
|
return;
|
|
}
|
|
|
|
log_len = combine_log_with_prefix(prefix, (char *)&packet_buf[0], buf_len, format, ap);
|
|
|
|
u32 int_mask = shell_task_enter_critical();
|
|
|
|
if ( GET_QUEUE_ID(blk_tag) == SHELL_DYM_QUEUE_ID ) {
|
|
dynamic_list_push_back_by_buffer(packet_buf);
|
|
}
|
|
|
|
// push to pending queue.
|
|
push_pending_queue(blk_tag, log_len);
|
|
|
|
//set_shell_event(SHELL_EVENT_TX_REQ); // notify shell task to process the log tx.
|
|
tx_req_process();
|
|
|
|
shell_task_exit_critical(int_mask);
|
|
|
|
return ;
|
|
}
|
|
|
|
static int shell_assert_out_va(bool bContinue, const char * format, va_list arg_list)
|
|
{
|
|
u32 int_mask;
|
|
char *pbuf;
|
|
u16 data_len, buf_len;
|
|
|
|
if( !shell_cpu_check_valid() )
|
|
return 0;
|
|
|
|
pbuf = (char *)&shell_assert_buff[0];
|
|
buf_len = sizeof(shell_assert_buff);
|
|
|
|
/* just disabled interrupts even when dump out in SMP. */
|
|
/* because other core's dump has been blocked by shell_cpu_check_valid(). */
|
|
/* can't try to get SPINLOCK, because may be it is called from HardFault handler, */
|
|
/* and meanwhile the spinlock is held by other cores. */
|
|
|
|
// int_mask = shell_task_enter_critical();
|
|
int_mask = rtos_disable_int();
|
|
|
|
data_len = vsnprintf( pbuf, buf_len, format, arg_list );
|
|
|
|
if(data_len >= buf_len)
|
|
data_len = buf_len - 1;
|
|
|
|
log_dev->dev_drv->write_sync(log_dev, (u8 *)pbuf, data_len);
|
|
|
|
if( bContinue )
|
|
{
|
|
// shell_task_exit_critical(int_mask);
|
|
rtos_enable_int(int_mask);
|
|
}
|
|
else
|
|
{
|
|
while(bTRUE)
|
|
{
|
|
}
|
|
}
|
|
|
|
return 1;//bTRUE;;
|
|
|
|
}
|
|
|
|
int shell_assert_out(bool bContinue, char * format, ...)
|
|
{
|
|
int ret;
|
|
va_list arg_list;
|
|
va_start( arg_list, format );
|
|
ret = shell_assert_out_va(bContinue, format, arg_list);
|
|
va_end( arg_list );
|
|
return ret;
|
|
}
|
|
|
|
int shell_assert_raw(bool bContinue, char * data_buff, u16 data_len)
|
|
{
|
|
u32 int_mask;
|
|
|
|
if( !shell_cpu_check_valid() )
|
|
return 0;
|
|
|
|
/* just disabled interrupts even when dump out in SMP. */
|
|
/* because other core's dump has been blocked by shell_cpu_check_valid(). */
|
|
/* can't try to get SPINLOCK, because may be it is called from HardFault handler, */
|
|
/* and meanwhile the spinlock is held by other cores. */
|
|
|
|
// int_mask = shell_task_enter_critical();
|
|
int_mask = rtos_disable_int();
|
|
|
|
log_dev->dev_drv->write_sync(log_dev, (u8 *)data_buff, data_len);
|
|
|
|
if( bContinue )
|
|
{
|
|
// shell_task_exit_critical(int_mask);
|
|
rtos_enable_int(int_mask);
|
|
}
|
|
else
|
|
{
|
|
while(1)
|
|
{
|
|
}
|
|
}
|
|
|
|
return 1;//bTRUE;;
|
|
|
|
}
|
|
|
|
#if defined(FWD_CMD_TO_MBOX) || defined(RECV_CMD_LOG_FROM_MBOX)
|
|
static int cmd_rsp_fwd(u8 * rsp_msg, u16 msg_len)
|
|
{
|
|
u16 rsp_blk_tag = MAKE_BLOCK_TAG(MBOX_RSP_BLK_ID, SHELL_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(MBOX_IND_BLK_ID, SHELL_FWD_QUEUE_ID);
|
|
|
|
cmd_info_out(ind_msg, msg_len, ind_blk_tag);
|
|
|
|
return 1;
|
|
}
|
|
|
|
static int result_fwd(int blk_id)
|
|
{
|
|
log_cmd_t * log_cmd;
|
|
u32 cmd = MB_CMD_LOG_OUT_OK;
|
|
if(blk_id == MBOX_RSP_BLK_ID)
|
|
{
|
|
log_cmd = &ipc_fwd_data.rsp_buf;
|
|
}
|
|
else if(blk_id == MBOX_IND_BLK_ID)
|
|
{
|
|
log_cmd = &ipc_fwd_data.ind_buf;
|
|
}
|
|
else if(blk_id == MBOX_COMMON_BLK_ID)
|
|
{
|
|
log_cmd = &ipc_fwd_data.common_log_buf;
|
|
cmd = MB_CMD_LOG_UNBLOCK;
|
|
}
|
|
else
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
log_cmd->hdr.data = 0;
|
|
log_cmd->hdr.cmd = cmd;
|
|
u32 int_mask = shell_task_enter_critical();
|
|
if (log_cmd->tag == INVALID_LOG_TAG) {
|
|
shell_task_exit_critical(int_mask);
|
|
return 0;
|
|
}
|
|
int ret = ipc_dev->dev_drv->write_cmd(ipc_dev, (mb_chnl_cmd_t *)log_cmd);
|
|
shell_task_exit_critical(int_mask);
|
|
return ret;
|
|
}
|
|
|
|
static void shell_ipc_tx_complete(u16 cmd)
|
|
{
|
|
if (cmd == MB_CMD_LOG_OUT_OK || cmd == MB_CMD_LOG_UNBLOCK) {
|
|
set_shell_event(&shell_log_event, SHELL_EVENT_MB_FWD);
|
|
}
|
|
|
|
if(cmd == MB_CMD_USER_INPUT) {
|
|
rtos_set_semaphore(&cmd_line_buf.cmd_fwd_semaphore);
|
|
}
|
|
}
|
|
|
|
static u32 shell_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(shell_log_owner_cpu != 0)
|
|
{
|
|
if(shell_log_owner_cpu == (0x01 << cpu_id))
|
|
shell_log_req_cpu = shell_log_owner_cpu;
|
|
else
|
|
return result;
|
|
}
|
|
|
|
if(cmd == MB_CMD_LOG_OUT)
|
|
{
|
|
u8 queue_id = GET_QUEUE_ID(log_cmd->tag);
|
|
|
|
if(queue_id == SHELL_RSP_QUEUE_ID)
|
|
{
|
|
if(cmd_rx_init_ok)
|
|
{
|
|
memcpy(&ipc_fwd_data.rsp_buf, log_cmd, sizeof(ipc_fwd_data.rsp_buf));
|
|
cmd_rsp_fwd(data, data_len);
|
|
|
|
result = ACK_STATE_PENDING;
|
|
}
|
|
}
|
|
else if(queue_id == SHELL_IND_QUEUE_ID)
|
|
{
|
|
if(cmd_rx_init_ok)
|
|
{
|
|
memcpy(&ipc_fwd_data.ind_buf, log_cmd, sizeof(ipc_fwd_data.ind_buf));
|
|
cmd_ind_fwd(data, data_len);
|
|
|
|
result = ACK_STATE_PENDING;
|
|
}
|
|
}
|
|
else // no cmd_hint from slave, so must be log from slave.
|
|
{
|
|
result = shell_log_raw_data_internel(0, data, data_len);
|
|
|
|
if(result == 0) {
|
|
if (log_handle_init_ok) {
|
|
// tansfer log output to shell task
|
|
memcpy(&ipc_fwd_data.common_log_buf, log_cmd, sizeof(ipc_fwd_data.common_log_buf));
|
|
set_shell_event(&shell_log_event, SHELL_EVENT_MB_LOG);
|
|
result = ACK_STATE_PENDING | ACK_STATE_BLOCK;
|
|
} else {
|
|
result = ACK_STATE_FAIL;
|
|
}
|
|
}
|
|
else
|
|
result = ACK_STATE_COMPLETE;
|
|
}
|
|
}
|
|
else if(cmd == MB_CMD_ASSERT_OUT)
|
|
{
|
|
#if (CONFIG_TASK_WDT)
|
|
bk_task_wdt_feed();
|
|
#endif
|
|
#if (CONFIG_INT_WDT)
|
|
bk_int_wdt_feed();
|
|
#endif
|
|
|
|
shell_assert_raw(true, (char *)data, data_len);
|
|
|
|
result = ACK_STATE_COMPLETE;
|
|
}
|
|
|
|
shell_log_req_cpu = 0;
|
|
|
|
/* no cmd handler. */
|
|
return result;
|
|
}
|
|
|
|
int shell_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;
|
|
int ret_code = 0;
|
|
int try_cnt = 0;
|
|
while(1)
|
|
{
|
|
u32 int_mask = shell_task_enter_critical();
|
|
ret_code = ipc_dev->dev_drv->write_cmd(ipc_dev, &mb_cmd_buf);
|
|
shell_task_exit_critical(int_mask);
|
|
|
|
if(ret_code != 0)
|
|
break;
|
|
|
|
rtos_delay_milliseconds(10);
|
|
try_cnt++;
|
|
if(try_cnt < 4)
|
|
continue;
|
|
else
|
|
return 0;
|
|
}
|
|
|
|
rtos_get_semaphore(&cmd_line_buf.cmd_fwd_semaphore, SHELL_WAIT_OUT_TIME);
|
|
return ret_code;
|
|
}
|
|
#endif
|
|
|
|
void shell_echo_set(int en_flag)
|
|
{
|
|
if(en_flag != 0)
|
|
cmd_line_buf.echo_enable = bTRUE;
|
|
else
|
|
cmd_line_buf.echo_enable = bFALSE;
|
|
}
|
|
|
|
int shell_echo_get(void)
|
|
{
|
|
if(cmd_line_buf.echo_enable)
|
|
return 1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
void shell_set_log_level(int level)
|
|
{
|
|
shell_log_level = level;
|
|
}
|
|
|
|
int shell_get_log_level(void)
|
|
{
|
|
return shell_log_level;
|
|
}
|
|
|
|
void shell_set_log_flush(int flush_flag)
|
|
{
|
|
log_flush_enabled = flush_flag;
|
|
}
|
|
|
|
int shell_get_log_flush(void)
|
|
{
|
|
return log_flush_enabled;
|
|
}
|
|
|
|
int shell_get_log_statist(u32 * info_list, u32 num)
|
|
{
|
|
int cnt = 0;
|
|
if(num > 0)
|
|
{
|
|
info_list[0] = shell_log_overflow;
|
|
cnt++;
|
|
}
|
|
if(num > 1)
|
|
{
|
|
info_list[1] = shell_log_count;
|
|
cnt++;
|
|
}
|
|
if(num > 2)
|
|
{
|
|
info_list[2] = free_queue[0].ovf_cnt;
|
|
cnt++;
|
|
}
|
|
if(num > 3)
|
|
{
|
|
info_list[3] = free_queue[1].ovf_cnt;
|
|
cnt++;
|
|
}
|
|
if(num > 4)
|
|
{
|
|
info_list[4] = free_queue[2].ovf_cnt;
|
|
cnt++;
|
|
}
|
|
|
|
return cnt;
|
|
}
|
|
|
|
void shell_log_flush(void)
|
|
{
|
|
u32 int_mask;
|
|
|
|
/* just disabled interrupts even when dump out in SMP. */
|
|
/* because it is called by power_saving process or by dumping process. */
|
|
/* in any case, only one core is running. */
|
|
/* can't try to get SPINLOCK, because may be it is called from HardFault handler, */
|
|
/* and meanwhile the spinlock is held by other cores. */
|
|
|
|
// int_mask = shell_task_enter_critical();
|
|
int_mask = rtos_disable_int();
|
|
|
|
log_dev->dev_drv->io_ctrl(log_dev, SHELL_IO_CTRL_FLUSH, NULL);
|
|
|
|
// shell_task_exit_critical(int_mask);
|
|
rtos_enable_int(int_mask);
|
|
}
|
|
|
|
void shell_set_uart_port(uint8_t uart_port)
|
|
{
|
|
#if (LOG_DEV == DEV_UART)
|
|
if(log_dev->dev_type != SHELL_DEV_UART)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if ((bk_get_printf_port() != uart_port) && (uart_port < UART_ID_MAX))
|
|
{
|
|
u32 int_mask = shell_task_enter_critical();
|
|
|
|
shell_log_flush();
|
|
log_dev->dev_drv->close(log_dev);
|
|
log_dev->dev_drv->io_ctrl(log_dev, SHELL_IO_CTRL_SET_UART_PORT, &uart_port);
|
|
|
|
bk_set_printf_port(uart_port);
|
|
|
|
log_dev->dev_drv->init(log_dev);
|
|
if(log_dev != cmd_dev)
|
|
{
|
|
log_dev->dev_drv->open(log_dev, shell_log_tx_complete, NULL); // tx log.
|
|
}
|
|
else
|
|
{
|
|
log_dev->dev_drv->open(log_dev, shell_tx_complete, shell_rx_indicate);
|
|
}
|
|
|
|
shell_task_exit_critical(int_mask);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
void shell_cmd_ind_out(const char *format, ...)
|
|
{
|
|
u16 data_len, buf_len = SHELL_IND_BUF_LEN;
|
|
va_list arg_list;
|
|
|
|
if(!cmd_rx_init_ok)
|
|
return;
|
|
|
|
rtos_get_semaphore(&cmd_line_buf.ind_buf_semaphore, SHELL_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);
|
|
}
|
|
|
|
void shell_set_log_cpu(u8 req_cpu)
|
|
{
|
|
#if (CONFIG_CPU_CNT > 1) && (LOG_DEV != DEV_MAILBOX)
|
|
if(req_cpu >= CONFIG_CPU_CNT)
|
|
{
|
|
shell_log_owner_cpu = 0;
|
|
shell_log_req_cpu = 0;
|
|
}
|
|
else if(shell_log_owner_cpu == 0)
|
|
{
|
|
shell_log_owner_cpu = 1 << req_cpu;
|
|
shell_log_req_cpu = 1 << req_cpu;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
static void free_list_push_front(dynamic_log_node *dym_node)
|
|
{
|
|
if (dym_node == NULL) {
|
|
BK_ASSERT(0);
|
|
return;
|
|
}
|
|
dym_node->next = s_to_free_list;
|
|
s_to_free_list = dym_node;
|
|
}
|
|
|
|
static void dynamic_list_push_back(dynamic_log_node *dym_node)
|
|
{
|
|
if (s_curr_node == NULL) {
|
|
s_curr_node = dym_node;
|
|
}
|
|
s_dym_tail_node->next = dym_node;
|
|
s_dym_tail_node = dym_node;
|
|
|
|
s_dynamic_log_total_len += dym_node->len;
|
|
if (s_dynamic_log_total_len > s_dynamic_log_mem_max) {
|
|
s_dynamic_log_mem_max = s_dynamic_log_total_len;
|
|
}
|
|
s_dynamic_log_num++;
|
|
}
|
|
|
|
static dynamic_log_node *dynamic_list_pop_front(void)
|
|
{
|
|
dynamic_log_node *node = s_dynamic_header.next;
|
|
if (node == NULL) {
|
|
BK_ASSERT(0);
|
|
return NULL;
|
|
}
|
|
BK_ASSERT(s_dynamic_header.next != s_curr_node);
|
|
s_dynamic_header.next = node->next;
|
|
s_dynamic_log_num--;
|
|
node->next = NULL;
|
|
if (node == s_dym_tail_node) {
|
|
s_dym_tail_node = &s_dynamic_header;
|
|
BK_ASSERT(s_curr_node == NULL);
|
|
}
|
|
return node;
|
|
}
|
|
|
|
static void dynamic_node_gc(void)
|
|
{
|
|
dynamic_log_node *node;
|
|
dynamic_log_node *temp_node;
|
|
dynamic_log_node *free_list = NULL;
|
|
u32 int_mask = shell_task_enter_critical();
|
|
if (s_to_free_list != NULL) {
|
|
free_list = s_to_free_list;
|
|
s_to_free_list = NULL;
|
|
}
|
|
shell_task_exit_critical(int_mask);
|
|
node = free_list;
|
|
while (node != NULL) {
|
|
temp_node = node;
|
|
s_dynamic_log_total_len -= node->len;
|
|
node = node->next;
|
|
LOG_FREE(temp_node);
|
|
s_dynamic_log_num_in_mem--;
|
|
}
|
|
}
|
|
|
|
static void check_and_free_dynamic_node(void)
|
|
{
|
|
if (s_to_free_list != NULL) {
|
|
dynamic_node_gc();
|
|
}
|
|
}
|
|
|
|
static u8 *alloc_dynamic_log_blk(u16 log_len, u16 *blk_tag)
|
|
{
|
|
if (rtos_is_in_interrupt_context()) {
|
|
return NULL;
|
|
}
|
|
int total_len = log_len + DYM_NODE_SIZE;
|
|
dynamic_log_node *node = (dynamic_log_node *)LOG_MALLOC(total_len);
|
|
if (node == NULL) {
|
|
return NULL;
|
|
}
|
|
node->len = total_len;
|
|
node->next = NULL;
|
|
*blk_tag = MAKE_BLOCK_TAG(0, SHELL_DYM_QUEUE_ID);
|
|
s_dynamic_log_num_in_mem++;
|
|
return &node->ptr[0];
|
|
}
|
|
|
|
static dynamic_log_node *dynamic_list_switch(void)
|
|
{
|
|
dynamic_log_node *node;
|
|
node = s_curr_node;
|
|
s_curr_node = s_curr_node->next;
|
|
return node;
|
|
}
|
|
|
|
static inline void dynamic_list_push_back_by_buffer(u8 *packet_buf)
|
|
{
|
|
dynamic_log_node *node = (dynamic_log_node *)&packet_buf[-DYM_NODE_SIZE];
|
|
dynamic_list_push_back(node);
|
|
}
|
|
|
|
static void shell_insert_data( const u8 *data, u16 data_len )
|
|
{
|
|
u32 int_mask;
|
|
if( !shell_cpu_check_valid() )
|
|
return;
|
|
|
|
int_mask = rtos_disable_int();
|
|
|
|
log_dev->dev_drv->write_sync(log_dev, (u8 *)data, data_len);
|
|
|
|
rtos_enable_int(int_mask);
|
|
}
|
|
|
|
static void output_insert_data(const u8 *data, u16 data_len)
|
|
{
|
|
shell_assert_out(bTRUE, "\r\nINSRT:");
|
|
shell_insert_data(data, data_len);
|
|
}
|
|
|
|
static void output_insert_log(u16 buf_len, char *prefix, const char *format, va_list ap)
|
|
{
|
|
shell_assert_out(bTRUE, "\r\nINSRT:%s", prefix);
|
|
shell_assert_out_va(bTRUE, format, ap);
|
|
}
|
|
|
|
void print_dynamic_log_info(void)
|
|
{
|
|
os_printf("dynamic log info:\n");
|
|
os_printf("mem_queue:%d, mem_comsume:%d\r\n",
|
|
s_dynamic_log_num_in_mem, s_dynamic_log_total_len);
|
|
os_printf("dynamic log mem max: %d\r\n",s_dynamic_log_mem_max);
|
|
}
|