/**
 * \file    cli_cmd_base.c
 * \brief   CLI command definistions
 *
 * \par     Copyright (c) 2018 UWE Technologies Corp., Ltd. All Rights Reserved.
 * \author  James
 * \date    2018-02-24
 * \version 
 * 
 * \history 
 *  Date        Note
 *  2018-02-24  Original Creation
 * 
 */


#include <stdarg.h>
#include "cli_engine.h"

#if CLI_ENABLED

#include "libc.h"
#include "drivers.h"
#include "cli_cmd_base.h"
#include "sys_low_power.h"

#if CLI_INCLUDE_UART
#include "sys_uart1.h"
#endif

#if SYS_FREERTOS_ENABLED
/* Kernel includes. */
#include "FreeRTOS.h"
#include "task.h"
#endif

/* Command definitions */


/** Debug level */
const char * const g_cli_dbg_lvl_str[SYS_DEBUG_LEVEL_END] = {
    "Off",
    "L1",
    "L2",
    "L3",
    "L4"
    };

/** VDM mode */
const char * const g_cli_onoff_str[2] = {
    "Off",
    "On"
    };

/** True/False */
const char * const g_cli_true_str[2] = {
    "False",
    "True"
    };


#if CLI_INCLUDE_RESET
const char * const g_cli_cmd_rst_help[] = {
#if CLI_INCLUDE_HELP
    "Reset system",
#if CLI_ENABLED_VERBOSE_HELP
    "",
#endif /* CLI_ENABLED_VERBOSE_HELP */
#endif /* CLI_INCLUDE_HELP */
    0,
};

int cli_cmd_rst(int argc, char *argv[])
{
    DRV_INTR_GLOBAL_DISABLE();
    drv_chip_reset();
    return(CLI_CMD_SUCCESS);
}
#endif



#if CLI_INCLUDE_VER
/** Version help */
const char * const g_cli_cmd_ver_help[] = {
#if CLI_INCLUDE_HELP
    "Version",
#if CLI_ENABLED_VERBOSE_HELP
    "",
#endif /* CLI_ENABLED_VERBOSE_HELP */
#endif /* CLI_INCLUDE_HELP */
    0,
};

/**
 * Display version
 *
 * \detail 
 *  No need argument input
 * \param argc argument count
 * \param argv argument vector
 * \return 0: success, nonzero: failure
 *
 * \see CLI_CMD_RESULT_e
 */
int cli_cmd_ver(int argc, char *argv[])
{
    cli_print_brand(TRUE);
    return(CLI_CMD_SUCCESS);
}
#endif

#if CLI_INCLUDE_REG
const char * const g_cli_cmd_reg_read_help[] = {
#if CLI_INCLUDE_HELP
    "Reg read",
#if CLI_ENABLED_VERBOSE_HELP
    "<addr> [count]",
#endif /* CLI_ENABLED_VERBOSE_HELP */
#endif /* CLI_INCLUDE_HELP */
    0,
};

int cli_cmd_reg_read(int argc, char *argv[])
{
    u32_t    addr;
    u32_t    count;

    if (argc < 2)
        return(CLI_CMD_PARAM_ERROR);

    addr = (0xFFFF & strtoul(argv[1],(char **)0,0)) + 0x40000000;

    if (0 != (addr % 4))
        return(CLI_CMD_PARAM_ERROR);

    if (argc == 3) {
        count = strtol(argv[2],(char **)0,0);
    }
    else
        count = 1;

    while(count>0) {
        printf(" Reg[%08X]=%08X\n", addr, DRV_REG_GET(addr));
        count--;
        addr += 4;
    }
    
    return(CLI_CMD_SUCCESS);
}

const char * const g_cli_cmd_reg_write_help[] = {
#if CLI_INCLUDE_HELP
    "Reg write",
#if CLI_ENABLED_VERBOSE_HELP
    "<addr> <v>",
#endif /* CLI_ENABLED_VERBOSE_HELP */
#endif /* CLI_INCLUDE_HELP */
    0,
};

int cli_cmd_reg_write(int argc, char *argv[])
{
    u32_t addr;
    u32_t val;

    if (argc < 3)
        return(CLI_CMD_PARAM_ERROR);

    addr = (0xFFFF & strtoul(argv[1],(char **)0,0)) + 0x40000000;

    if (0 != (addr % 4))
        return(CLI_CMD_PARAM_ERROR);

    val = strtoul(argv[2], (char **)0, 0);

    printf(" Reg[%08X]=%08X\n", addr, DRV_REG_GET(addr));

    DRV_REG_SET(addr, val);

    printf(" Wrote %08X\n", val);
    
    return(CLI_CMD_SUCCESS);
}
#endif /* CLI_INCLUDE_REG */

#if CLI_INCLUDE_DM
/** Display memory help */
const char * const g_cli_cmd_dm_help[] = {
#if CLI_INCLUDE_HELP
    "Display Memory",
#if CLI_ENABLED_VERBOSE_HELP
    "<addr> [count]",
#endif /* CLI_ENABLED_VERBOSE_HELP */
#endif /* CLI_INCLUDE_HELP */
    0,
};

/**
 * Display memory
 *
 * \detail 
 *  Arguments...
 *    arg1: address to start display
 *    arg2: if present, specifies the number of units to be displayed.
 * \param argc argument count
 * \param argv argument vector
 * \return 0: success, nonzero: failure
 *
 * \see CLI_CMD_RESULT_e
 */
int cli_cmd_dm(int argc, char *argv[])
{
    u32_t   addr;
    u32_t   count;

    if (argc < 2)
        return(CLI_CMD_PARAM_ERROR);

    addr = strtoul(argv[1],(char **)0,0);

    if (argc == 3) {
        count = strtoul(argv[2], (char **)0,0);
    }
    else
        count = 100;

    drv_uart_puthex((u8_t *)addr, count, TRUE);
    
    return(CLI_CMD_SUCCESS);
}
#endif

const char * const g_cli_cmd_mm_help[] = {
#if CLI_INCLUDE_HELP
    "Modify Memory",
#if CLI_ENABLED_VERBOSE_HELP
    "<addr> <v> [count]",
#endif /* CLI_ENABLED_VERBOSE_HELP */
#endif /* CLI_INCLUDE_HELP */
    0,
};

#if CLI_INCLUDE_MM
int cli_cmd_mm(int argc, char *argv[])
{
    u32_t addr, addr2;
    u32_t val;
    u32_t count, count2;

    if (argc < 3)
        return(CLI_CMD_PARAM_ERROR);

    addr = strtoul(argv[1],(char **)0,0);

    if (0 != (addr % 4))
        return(CLI_CMD_PARAM_ERROR);

    val = strtoul(argv[2], (char **)0, 0);

    if (argc > 3) {
        count = strtoul(argv[3], (char **)0,0);
    }
    else
        count = 1;

    addr2 = addr;
    count2 = count;
    while(count>0) {
        if (addr < DRV_FLASH_SIZE+APP_ADDR_OFFSET)
        {
            drv_flash_write(addr, (u8_t *)&val, 4);
        }
        else {
            DRV_REG_SET(addr, val);
        }
        count--;
        addr += 4;
    }
    drv_uart_puthex((u8_t *)addr2, count2, TRUE);

    return(CLI_CMD_SUCCESS);
}
#endif /* CLI_INCLUDE_MM */

#if CLI_INCLUDE_GPIO
const char * const g_cli_cmd_gpio_help[] = {
#if CLI_INCLUDE_HELP
    "GPIO commands",
#if CLI_ENABLED_VERBOSE_HELP
	"",
    "<id> {off|on}",
    "<id> {in|out}",
    "<id> {pd} {off|on}",
    "<id> {pu} {off|on}",
    "<id> {od} {nor|nopu|10kpu|1kpu}",
    "<id> {drv} {4mA|6mA|8mA|10mA}",
    "<id> {int} {off|on}",
    "<id> {int-mask} {off|on}",
    "<id> {int-type} {level|edge}",
    "<id> {int-polar} {0|1}",
    "\t 0: Low or falling",
    "\t 1: High or rising",
    "<id> {bit-mask} {off|on}",
    "<id> {get}",
    "<id> {set} {0|1}",
#endif /* CLI_ENABLED_VERBOSE_HELP */
#endif /* CLI_INCLUDE_HELP */
    0,
};

int cli_cmd_gpio(int argc, char *argv[])
{
const char * const header = "  # EN  OE  VAL PD  PU  OD    DRV  INT INTM TYPE  POLAR   BITM INTS INTMS\n -- --- --- --- --- --- ----- ---- --- ---- ----- ------- ---- ---- -----";
const char * const od_type[DRV_GPIO_OD_TYPE_MAX] = {"Nor", "NoPU", "10KPU", "1KPU"};
const char * const drv_type[DRV_GPIO_OUTPUT_DRIVER_MAX] = {"4mA", "6mA", "8mA", "10mA"};
    int id;
    int val;

    if (argc < 2)
    {
        drv_uart_puts(header);
        for (id = 0; id < DRV_GPIO_MAX; id++)
        {
            printf(" %02d %-3s %-3s %3d %-3s %-3s %-5s %-4s %-3s %-4s %-5s %-7s %-4s %4d %5d\n",
                id, 
                g_cli_onoff_str[drv_gpio_en_get(id) ? 1 : 0],
                g_cli_onoff_str[drv_gpio_oe_get(id) ? 1 : 0],
                drv_gpio_val_get(id),
                g_cli_onoff_str[drv_gpio_pd_get(id) ? 1 : 0],
                g_cli_onoff_str[drv_gpio_pu_get(id) ? 1 : 0],
                od_type[drv_gpio_od_get(id)],
                drv_type[drv_gpio_output_driver_get(id)],
                g_cli_onoff_str[drv_gpio_intr_en_get(id) ? 1 : 0],
                g_cli_onoff_str[drv_gpio_intr_mask_get(id) ? 1 : 0],
                drv_gpio_intr_type_get(id) ? "Edge" : "Level",
                drv_gpio_intr_polar_get(id) ? (drv_gpio_intr_type_get(id) ? "Rising" : "High") : (drv_gpio_intr_type_get(id) ? "Falling" : "Low"),
                g_cli_onoff_str[drv_gpio_bit_mask_get(id) ? 1 : 0],
                drv_gpio_intr_sta_get(id) ? 1 : 0,
                drv_gpio_intr_sta_masked_get(id) ? 1 : 0
                );
        }
    }
    else {
        id = (u8_t)strtoul(argv[1],(char **)0,0);

        if ((argc < 3) || (id >= DRV_GPIO_MAX))
            return(CLI_CMD_PARAM_ERROR);

        if (0 == strcmp(argv[2],"in"))
        {
            drv_gpio_oe_set(id, FALSE);
        }
        else if (0 == strcmp(argv[2],"out"))
        {
        	drv_gpio_oe_set(id, TRUE);
        }
        else if (0 == strcmp(argv[2],"off"))
        {
        	drv_gpio_en_set(id, FALSE);
        }
        else if (0 == strcmp(argv[2],"on"))
        {
        	drv_gpio_en_set(id, TRUE);
        }
        else if (0 == strcmp(argv[2],"pd"))
        {
            if (argc < 4)
                return(CLI_CMD_PARAM_ERROR);
            if (0 == strcmp(argv[3],"on"))
            {
            	drv_gpio_pd_set(id, TRUE);
            }
            else if (0 == strcmp(argv[3],"off"))
            {
            	drv_gpio_pd_set(id, FALSE);
            }
            else {
                return(CLI_CMD_NOT_FOUND);
            }
        }
        else if (0 == strcmp(argv[2],"pu"))
        {
            if (argc < 4)
                return(CLI_CMD_PARAM_ERROR);
            if (0 == strcmp(argv[3],"on"))
            {
            	drv_gpio_pu_set(id, TRUE);
            }
            else if (0 == strcmp(argv[3],"off"))
            {
            	drv_gpio_pu_set(id, FALSE);
            }
            else {
                return(CLI_CMD_NOT_FOUND);
            }
        }
        else if (0 == strcmp(argv[2],"od"))
        {
            if (argc < 4)
                return(CLI_CMD_PARAM_ERROR);
            if (0 == strcmp(argv[3],"nor"))
            {
            	drv_gpio_od_set(id, DRV_GPIO_OD_TYPE_NORMAL);
            }
            else if (0 == strcmp(argv[3],"nopu"))
            {
            	drv_gpio_od_set(id, DRV_GPIO_OD_TYPE_NMOS_NO_PU);
            }
            else if (0 == strcmp(argv[3],"10kpu"))
            {
            	drv_gpio_od_set(id, DRV_GPIO_OD_TYPE_NMOS_10KOHM_PU);
            }
            else if (0 == strcmp(argv[3],"1kpu"))
            {
            	drv_gpio_od_set(id, DRV_GPIO_OD_TYPE_NMOS_1KOHM_PU);
            }
            else {
                return(CLI_CMD_NOT_FOUND);
            }
        }
        else if (0 == strcmp(argv[2],"drv"))
        {
            if (argc < 4)
                return(CLI_CMD_PARAM_ERROR);
            if (0 == strcasecmp(argv[3],"4ma"))
            {
            	drv_gpio_output_driver_set(id, DRV_GPIO_OUTPUT_DRIVER_4mA);
            }
            else if (0 == strcasecmp(argv[3],"6ma"))
            {
            	drv_gpio_output_driver_set(id, DRV_GPIO_OUTPUT_DRIVER_6mA);
            }
            else if (0 == strcasecmp(argv[3],"8ma"))
            {
            	drv_gpio_output_driver_set(id, DRV_GPIO_OUTPUT_DRIVER_8mA);
            }
            else if (0 == strcasecmp(argv[3],"10ma"))
            {
            	drv_gpio_output_driver_set(id, DRV_GPIO_OUTPUT_DRIVER_10mA);
            }
            else {
                return(CLI_CMD_NOT_FOUND);
            }
        }
        else if (0 == strcmp(argv[2],"int"))
        {
            if (argc < 4)
                return(CLI_CMD_PARAM_ERROR);
            if (0 == strcmp(argv[3],"on"))
            {
            	drv_gpio_intr_en_set(id, TRUE);
            }
            else if (0 == strcmp(argv[3],"off"))
            {
            	drv_gpio_intr_en_set(id, FALSE);
            }
            else {
                return(CLI_CMD_NOT_FOUND);
            }
        }
        else if (0 == strcmp(argv[2],"int-mask"))
        {
            if (argc < 4)
                return(CLI_CMD_PARAM_ERROR);
            if (0 == strcmp(argv[3],"on"))
            {
            	drv_gpio_intr_mask_set(id, TRUE);
            }
            else if (0 == strcmp(argv[3],"off"))
            {
            	drv_gpio_intr_mask_set(id, FALSE);
            }
            else {
                return(CLI_CMD_NOT_FOUND);
            }
        }
        else if (0 == strcmp(argv[2],"int-type"))
        {
            if (argc < 4)
                return(CLI_CMD_PARAM_ERROR);
            if (0 == strcmp(argv[3],"edge"))
            {
            	drv_gpio_intr_type_set(id, 1);
            }
            else if (0 == strcmp(argv[3],"level"))
            {
            	drv_gpio_intr_type_set(id, 0);
            }
            else {
                return(CLI_CMD_NOT_FOUND);
            }
        }
        else if (0 == strcmp(argv[2],"int-polar"))
        {
            if (argc < 4)
                return(CLI_CMD_PARAM_ERROR);
            if (0 == strcmp(argv[3],"1"))
            {
            	drv_gpio_intr_polar_set(id, 1);
            }
            else if (0 == strcmp(argv[3],"0"))
            {
            	drv_gpio_intr_polar_set(id, 0);
            }
            else {
                return(CLI_CMD_NOT_FOUND);
            }
        }
        else if (0 == strcmp(argv[2],"bit-mask"))
        {
            if (argc < 4)
                return(CLI_CMD_PARAM_ERROR);
            if (0 == strcmp(argv[3],"1"))
            {
            	drv_gpio_bit_mask_set(id, 1);
            }
            else if (0 == strcmp(argv[3],"0"))
            {
            	drv_gpio_bit_mask_set(id, 0);
            }
            else {
                return(CLI_CMD_NOT_FOUND);
            }
        }
        else if (0 == strcmp(argv[2],"get"))
        {
             val = drv_gpio_val_get(id);
             printf("Get GPIO %d: %d\n", id, val);
        }
        else if (0 == strcmp(argv[2],"set"))
        {
            if (argc < 4)
                return(CLI_CMD_PARAM_ERROR);
            val = (u8_t)strtoul(argv[3],(char **)0,0);
            drv_gpio_val_set(id,val);
            printf("Set GPIO %d: %d\n", id, val);
        }
        else {
            return(CLI_CMD_NOT_FOUND);
        }
    }
    
    return(CLI_CMD_SUCCESS);
}
#endif


#if CLI_INCLUDE_GPIO_CAP
const char * const g_cli_cmd_gpio_cap_help[] = {
#if CLI_INCLUDE_HELP
    "GPIO in capture commands",
#if CLI_ENABLED_VERBOSE_HELP
	"",
    "<id> {off|on <gpio>}",
    "<id> {mode} <value>",
    "\t Mode:",
    "\t  0: Capture the width between rising edges of input signal",
    "\t  1: Capture the width between falling edges of input signal",
    "\t  2: Capture the width from rising edge to falling edge of input signal",
    "\t  3: Capture the width from falling edge to rising edge of input signal",
#endif /* CLI_ENABLED_VERBOSE_HELP */
#endif /* CLI_INCLUDE_HELP */
    0,
};

int cli_cmd_gpio_cap(int argc, char *argv[])
{
const char * const header = "  # EN  GPIO MODE   CAP COUNT\n -- --- ---- ---- -----------";
    int id;
    int val;

    if (argc < 2)
    {
        drv_uart_puts(header);
        for (id = 0; id < DRV_CAPTURE_ID_MAX; id++)
        {
            printf(" %02d %-3s %4d %4d %11u\n",
                id, 
                g_cli_onoff_str[drv_gpio_cap_en_get(id) ? 1 : 0],
                (drv_cap_en_gpio_get(id) == DRV_GPIO_MAX) ? -1 : drv_cap_en_gpio_get(id),
                drv_gpio_cap_mode_get(id),
                drv_gpio_cap_count_get(id)
                );
        }
    }
    else {
        id = (u8_t)strtoul(argv[1],(char **)0,0);

        if ((argc < 3) || (id >= DRV_CAPTURE_ID_MAX))
            return(CLI_CMD_PARAM_ERROR);

        if (0 == strcmp(argv[2],"off"))
        {
        	drv_gpio_cap_en_set(id, 0, FALSE);
        }
        else if (0 == strcmp(argv[2],"on"))
        {
            if (argc < 4)
                return(CLI_CMD_PARAM_ERROR);

            val = (u8_t)strtoul(argv[3],(char **)0,0);
        	drv_gpio_cap_en_set(id, val, TRUE);
        }
        else if (0 == strcmp(argv[2],"mode"))
        {
            if (argc < 4)
                return(CLI_CMD_PARAM_ERROR);

            val = (u8_t)strtoul(argv[3],(char **)0,0);
        	drv_gpio_cap_mode_set(id, val);
        }
        else {
            return(CLI_CMD_NOT_FOUND);
        }
    }
    
    return(CLI_CMD_SUCCESS);
}
#endif



#if CLI_INCLUDE_ADC
const char * const g_cli_cmd_adc_help[] = {
#if CLI_INCLUDE_HELP
    "ADC read",
#if CLI_ENABLED_VERBOSE_HELP
    "<chn> [cnt] [stc]",
    "\t stc - Sample time control, in unit of clock cycle[0~7]",
#endif /* CLI_ENABLED_VERBOSE_HELP */
#endif /* CLI_INCLUDE_HELP */
    0,
};

int cli_cmd_adc(int argc, char *argv[])
{
    u32_t    channel;
    u32_t    count;
    u32_t    stc = 0x3;

    if (argc < 2)
        return(CLI_CMD_PARAM_ERROR);

    channel = strtoul(argv[1],(char **)0,0);

    if (argc >= 3)
    {
        count = strtoul(argv[2],(char **)0,0);
    }
    else
    {
        count = 10;
    }

    // configure sample time control
    if (argc == 4)
    {
        stc = drv_adc_stc_get();
        drv_adc_stc_set(strtoul(argv[3],(char **)0,0));
        printf(" ADC STC changed to %02X\n", drv_adc_stc_get());
    }

#if SYS_FREERTOS_ENABLED
    sync_enter_critical();
#endif /* SYS_FREERTOS_ENABLED */

    while(count>0) {
        printf(" ADC[%u]=%04X\n", channel, drv_adc_read(channel));
        count--;
    }

#if SYS_FREERTOS_ENABLED
    sync_exit_critical();
#endif /* SYS_FREERTOS_ENABLED */

    // restore sample time control
    if (argc == 4)
    {
        drv_adc_stc_set(stc);
    }

    return(CLI_CMD_SUCCESS);
}
#endif


#if ((CLI_INCLUDE_SPI) || (CLI_INCLUDE_I2C) || (CLI_INCLUDE_UART))

volatile u8_t cli_tmp_txbuf[17];
volatile u8_t cli_tmp_rxbuf[17];

#endif

#if CLI_INCLUDE_SPI

const char * const g_cli_cmd_spi_help[] = {
#if CLI_INCLUDE_HELP
    "spi commands",
#if CLI_ENABLED_VERBOSE_HELP
    "",
    "{close}",
    "{dbg} {off|on}",
    "{slave} <cpol> <cpha>",
    "{ssdis} {off|on}",
#if ((SPI_MODULE_ENABLED)&&(SPI_MODULE_SLAVE_ENABLED)&&(SPI_MODULE_SLAVE_DMA_ENABLED))
    "{dma} {off|on}",
#endif /* ((SPI_MODULE_ENABLED)&&(SPI_MODULE_SLAVE_ENABLED)&&(SPI_MODULE_SLAVE_DMA_ENABLED)) */
    "{ssmode} {byte|session|always}",
    "{open} <ss> <clk> <cpol> <cpha>",
    "\t ss: Slave Select PIN",
    "\t clk: Frequency = CPUCLK/(2^(clk+1))",
    "\t  0: 16.5888MHz",
    "\t  1: 8.2944MHz",
    "\t  2: 4.1472MHz",
    "\t  3: 2.0736MHz",
    "\t  4: 1.0368MHz",
    "\t  5: 518.4KHz",
    "\t  6: 259.2KHz",
    "\t  7: Not generated",
    "{rx} <cnt>",
    "{tx} <hex>",
    "\t hex format:",
    "\t  F48E22C6, 4 bytes",
    "{test} [cnt]",
    "\t tx and rx 16 bytes data",
#endif /* CLI_ENABLED_VERBOSE_HELP */
#endif /* CLI_INCLUDE_HELP */
    0,
};

struct CLI_SPI_INFO_s
{
    u32_t master:1;
    u32_t slave:1;
    u32_t ssmode:3;
    u32_t ss:3;
    u32_t clk:3;
    u32_t cpp:2;
    u32_t reserved:19;
} cli_spi_info = {0,0,0,0,0,0,0};

int cli_cmd_spi(int argc, char *argv[])
{
    u32_t tmp1 = 0, tmp2 = 0, tmp3 = 0;

    if (argc < 2)
    {
        printf(" SPI Information\n");
        printf("  %-25s: %s\n", "Enabled", g_cli_onoff_str[drv_spi_en_get()]);
        printf("  %-25s: %s\n", "Mode", cli_spi_info.master ? "Master" : "Slave");
        printf("  %-25s: %u\n", "Slave Select PIN", cli_spi_info.ss);
        printf("  %-25s: %u\n", "CPOL", (cli_spi_info.cpp >> 1) & 0x1);
        printf("  %-25s: %u\n", "CPHA", cli_spi_info.cpp & 0x1);
        if (cli_spi_info.master)
        {
            printf("  %-25s: %s\n", "Slave Select Mode", cli_spi_info.ssmode ? ((2 > cli_spi_info.ssmode) ? "Session" : "Always") : "Byte");
            printf("  %-25s: %u Hz\n", "Clock", (cli_spi_info.clk >= 7) ? 0 : (drv_chip_freq_get() / (2 << cli_spi_info.clk)));
        }
        else {
            printf("  %-25s: %s\n", "Slave Select Disable", g_cli_onoff_str[drv_spi_ssdis_get()]);
        }
        printf("  %-25s: %s\n", "Debugging", g_cli_onoff_str[drv_spi_isr_dbg_get()]);
    }
    else {
        if (0 == strcmp("close", argv[1]))
        {
            cli_spi_info.master = FALSE;
            cli_spi_info.slave = FALSE;
            drv_spi_close();
        }
        else if (0 == strcmp("slave", argv[1]))
        {
            if (argc < 4)
                return(CLI_CMD_PARAM_ERROR);

            cli_spi_info.master = FALSE;
            cli_spi_info.slave = TRUE;
            tmp2 = strtoul(argv[2], (char **)0, 0);
            tmp3 = strtoul(argv[3], (char **)0, 0);
            if ((tmp2 > 1)||(tmp3 > 1))
            {
                return(CLI_CMD_PARAM_ERROR);
            }
            cli_spi_info.cpp = (tmp2 << 1) | tmp3;
            cli_spi_info.ss = SPI_SSN_3;
            drv_spi_open(cli_spi_info.master, cli_spi_info.ss, SPI_SPEED_FCLK_DIVIDE_BY_8, cli_spi_info.cpp);
#if ((SPI_MODULE_ENABLED)&&(SPI_MODULE_SLAVE_ENABLED)&&(SPI_MODULE_SLAVE_DMA_ENABLED))
            if ((argc == 5) && (0 == strcmp("dma", argv[4])))
            {
                drv_spi_sla_dma_start();
            }
#endif /* ((SPI_MODULE_ENABLED)&&(SPI_MODULE_SLAVE_ENABLED)&&(SPI_MODULE_SLAVE_DMA_ENABLED)) */
        }
        else if (0 == strcmp("dbg", argv[1]))
        {
            if (argc < 3)
                return(CLI_CMD_PARAM_ERROR);

            if (0 == strcmp("on", argv[2]))
            {
                drv_spi_isr_dbg_set(TRUE);
            }
            else if (0 == strcmp("off", argv[2]))
            {
                drv_spi_isr_dbg_set(FALSE);
            }
            else {
                return(CLI_CMD_NOT_FOUND);
            }
        }
        else if (0 == strcmp("ssdis", argv[1]))
        {
            if (argc < 3)
                return(CLI_CMD_PARAM_ERROR);

            if (cli_spi_info.master)
                return(CLI_CMD_DENIED);

            if (0 == strcmp("on", argv[2]))
            {
                drv_spi_ssdis_set(TRUE);
            }
            else if (0 == strcmp("off", argv[2]))
            {
                drv_spi_ssdis_set(FALSE);
            }
            else {
                return(CLI_CMD_NOT_FOUND);
            }
        }
#if ((SPI_MODULE_ENABLED)&&(SPI_MODULE_SLAVE_ENABLED)&&(SPI_MODULE_SLAVE_DMA_ENABLED))
        else if (0 == strcmp("dma", argv[1]))
        {
            if (argc < 3)
                return(CLI_CMD_PARAM_ERROR);

            if (cli_spi_info.master)
                return(CLI_CMD_DENIED);

            if (!cli_spi_info.slave)
                return(CLI_CMD_DENIED);

            if (0 == strcmp("on", argv[2]))
            {
                for (tmp1 = 0; tmp1 < SPI_SLA_RX_BUF_SIZE; tmp1++)
                {
                    g_spi_info.sla_rx_buf[tmp1] = 0;
                }
                for (tmp1 = 0; tmp1 < SPI_SLA_TX_BUF_SIZE; tmp1++)
                {
                    g_spi_info.sla_tx_buf[tmp1] = 0x80 - tmp1;
                }
                drv_spi_sla_dma_start();
            }
            else if (0 == strcmp("off", argv[2]))
            {
                drv_spi_close();
                drv_spi_open(cli_spi_info.master, cli_spi_info.ss, SPI_SPEED_FCLK_DIVIDE_BY_8, cli_spi_info.cpp);
            }
            else {
                return(CLI_CMD_NOT_FOUND);
            }
        }
#endif /* ((SPI_MODULE_ENABLED)&&(SPI_MODULE_SLAVE_ENABLED)&&(SPI_MODULE_SLAVE_DMA_ENABLED)) */
        else if (0 == strcmp("ssmode", argv[1]))
        {
            if (argc < 3)
                return(CLI_CMD_PARAM_ERROR);

            if (!(cli_spi_info.master))
                return(CLI_CMD_DENIED);

            if (0 == strcmp("byte", argv[2]))
            {
                cli_spi_info.ssmode = 0;
                drv_spi_sla_sel_off();
            }
            else if (0 == strcmp("session", argv[2]))
            {
                cli_spi_info.ssmode = 1;
                drv_spi_sla_sel_off();
            }
            else if (0 == strcmp("always", argv[2]))
            {
                cli_spi_info.ssmode = 2;
                drv_spi_sla_sel_on(cli_spi_info.ss);
            }
            else {
                return(CLI_CMD_NOT_FOUND);
            }
        }
        else if (0 == strcmp("test", argv[1]))
        {
            if (cli_spi_info.master)
            {
                u8_t cnt = 16;
                if (argc == 3)
                    cnt = (u8_t)strtoul(argv[2], (char **)0, 0);

                if ( 0 == cnt)
                    cnt = 1;

                drv_spi_open(cli_spi_info.master, cli_spi_info.ss, cli_spi_info.clk, cli_spi_info.cpp);
                if (0 == cli_spi_info.ssmode)
                {
                    for (tmp1 = 0; tmp1 < cnt; tmp1++)
                    {
                        cli_tmp_txbuf[tmp1] = tmp1+100;
                        drv_spi_sla_sel_on(cli_spi_info.ss);
                        tmp2 = drv_spi_transmit((u8_t *)(&cli_tmp_txbuf[tmp1]), 0, 1);
                        drv_spi_sla_sel_off();
                        rtc_delay_us(400U);
                    }
                    rtc_delay_us(3000U);
                    for (tmp1 = 0; tmp1 < cnt; tmp1++)
                    {
                        cli_tmp_rxbuf[tmp1] = 0;
                        drv_spi_sla_sel_on(cli_spi_info.ss);
                        tmp3 = drv_spi_transmit(0, (u8_t *)(&cli_tmp_rxbuf[tmp1]), 1);
                        drv_spi_sla_sel_off();
                        rtc_delay_us(400U);
                    }
                }
                else if (1 == cli_spi_info.ssmode) 
                {
                    for (tmp1 = 0; tmp1 < cnt; tmp1++)
                    {
                        cli_tmp_rxbuf[tmp1] = 0;
                        cli_tmp_txbuf[tmp1] = tmp1+100;
                    }
                    drv_spi_sla_sel_on(cli_spi_info.ss);
                    tmp2 = drv_spi_transmit((u8_t *)cli_tmp_txbuf, 0, tmp1);
                    drv_spi_sla_sel_off();
                    rtc_delay_us(3000U);
                    drv_spi_sla_sel_on(cli_spi_info.ss);
                    tmp3 = drv_spi_transmit(0, (u8_t *)cli_tmp_rxbuf, tmp1);
                    drv_spi_sla_sel_off();
                }
                else if (2 == cli_spi_info.ssmode) 
                {
                    for (tmp1 = 0; tmp1 < cnt; tmp1++)
                    {
                        cli_tmp_rxbuf[tmp1] = 0;
                        cli_tmp_txbuf[tmp1] = tmp1+100;
                    }
                    tmp2 = drv_spi_transmit((u8_t *)cli_tmp_txbuf, 0, tmp1);
                    rtc_delay_us(3000U);
                    tmp3 = drv_spi_transmit(0, (u8_t *)cli_tmp_rxbuf, tmp1);
                }

                drv_uart_putstr("SPI TX(");
                drv_uart_putdec(tmp2);
                drv_uart_putstr(")\n");
                drv_uart_puthex((u8_t *)cli_tmp_txbuf,tmp1,FALSE);
                drv_uart_putchar(UART_LF);

                drv_uart_putstr("SPI RX(");
                drv_uart_putdec(tmp3);
                drv_uart_putstr(")\n");
                drv_uart_puthex((u8_t *)cli_tmp_rxbuf,tmp1,FALSE);
                drv_uart_putchar(UART_LF);
            }
            else {
                return(CLI_CMD_DENIED);
            }
        }
        else {
            if (argc < 3)
                return(CLI_CMD_PARAM_ERROR);

            if (0 == strcmp("rx", argv[1]))
            {
                tmp1 = (u8_t)strtoul(argv[2], (char **)0, 0);
                if (tmp1)
                {
                    if (tmp1 > 16)
                        return(CLI_CMD_PARAM_ERROR);

                    if (cli_spi_info.master)
                    {
                        drv_spi_open(cli_spi_info.master, cli_spi_info.ss, cli_spi_info.clk, cli_spi_info.cpp);
                        drv_spi_sla_sel_on(cli_spi_info.ss);
                        tmp2 = drv_spi_transmit(0, (u8_t *)cli_tmp_rxbuf, tmp1);
                        drv_spi_sla_sel_off();
                        drv_uart_putstr("SPI RX(");
                        drv_uart_putdec(tmp2);
                        drv_uart_putstr(")\n");
                        drv_uart_puthex((u8_t *)cli_tmp_rxbuf,tmp1,FALSE);
                        drv_uart_putchar(UART_LF);
                    }
                    else {
#if SPI_MODULE_SLAVE_ENABLED  /* modified by James Gan - 2018-08-23 */
                        drv_spi_sla_rx_bytes_set(tmp1);
#if SPI_MODULE_SLAVE_DMA_ENABLED
                        drv_spi_sla_tx_bytes_set(tmp1);
#endif /* SPI_MODULE_SLAVE_DMA_ENABLED */
#else
                        return(CLI_CMD_DENIED);
#endif /* #if SPI_MODULE_SLAVE_ENABLED */
                    }
                }
            }
            else if (0 == strcmp("tx", argv[1]))
            {
                tmp1 = strtohex((u8_t *)cli_tmp_txbuf, argv[2], 16);
                    
                if (cli_spi_info.master)
                {
                    drv_spi_open(cli_spi_info.master, cli_spi_info.ss, cli_spi_info.clk, cli_spi_info.cpp);
                    drv_spi_sla_sel_on(cli_spi_info.ss);
                    tmp2 = drv_spi_transmit((u8_t *)cli_tmp_txbuf, 0, tmp1);
                    drv_spi_sla_sel_off();
                    drv_uart_putstr("SPI TX(");
                    drv_uart_putdec(tmp2);
                    drv_uart_putstr(")\n");
                    drv_uart_puthex((u8_t *)cli_tmp_txbuf,tmp1,FALSE);
                    drv_uart_putchar(UART_LF);
                }
                else {
                    return(CLI_CMD_DENIED);
                }
            }
            else {
                if (argc < 4)
                    return(CLI_CMD_PARAM_ERROR);

                if (0 == strcmp("open", argv[1]))
                {
                    if (argc < 6)
                        return(CLI_CMD_PARAM_ERROR);
                    cli_spi_info.ss = strtoul(argv[2], (char **)0, 0);
                    cli_spi_info.clk = strtoul(argv[3], (char **)0, 0);
                    if (cli_spi_info.clk > SPI_CLOCK_NOT_GENERATED)
                        return(CLI_CMD_PARAM_ERROR);

                    tmp2 = strtoul(argv[4], (char **)0, 0);
                    tmp3 = strtoul(argv[5], (char **)0, 0);
                    if ((tmp2 > 1)||(tmp3 > 1))
                    {
                        return(CLI_CMD_PARAM_ERROR);
                    }
                    cli_spi_info.master = TRUE;
                    cli_spi_info.slave = FALSE;
                    cli_spi_info.cpp = (tmp2 << 1) | tmp3;
                    drv_spi_open(cli_spi_info.master, cli_spi_info.ss, cli_spi_info.clk, cli_spi_info.cpp);
                }
                else {
                    return(CLI_CMD_NOT_FOUND);
                }
            }
        }
    }
    return(CLI_CMD_SUCCESS);
}
#endif

#if CLI_INCLUDE_I2C
const char * const g_cli_cmd_i2c_help[] = {
#if CLI_INCLUDE_HELP
    "i2c commands",
#if CLI_ENABLED_VERBOSE_HELP
    "<id> {freq} {100|200|300|400|800|1000|2000|{custom <div>}}",
    "\t  custom: SCL=Fclk/(4*(div[3:0]+1)*(div[7:4]+1))",
    "<id> {open} <slvaddr>",
    "<id> {close}",
    "<id> {test}",
    "\t tx and rx 16 bytes data",
    "<id> {ro} <cnt>",
    "<id> {rr} <reg> <cnt>",
    "<id> {rw} <reg> <hex>",
    "<id> {sta}",
#endif /* CLI_ENABLED_VERBOSE_HELP */
#endif /* CLI_INCLUDE_HELP */
    0,
};

u8_t cli_i2c_slv_addr[DRV_I2C_ID_MAX] = {0, 0};

int cli_cmd_i2c(int argc, char *argv[])
{
    u32_t id, tmp1, tmp2;
    char *p;

    id = strtoul(argv[1], &p, 0);
    if ((argc < 3) || (id>= DRV_I2C_ID_MAX) || ((p != NULL) && (*p != '\0')))
        return(CLI_CMD_PARAM_ERROR);

    if (0 == strcmp("close", argv[2]))
    {
        cli_i2c_slv_addr[id] = 0;
        drv_i2c_close(id);
    }
    else if (0 == strcmp("test", argv[2]))
    {
        if (cli_i2c_slv_addr[id])
        {
            for (tmp1 = 0; tmp1 < 16; tmp1++)
            {
                cli_tmp_rxbuf[tmp1] = 0;
                cli_tmp_txbuf[tmp1] = tmp1+100;
            }
            tmp2 = drv_i2c_master_transmit(id, cli_i2c_slv_addr[id], (u8_t *)cli_tmp_txbuf, tmp1, (u8_t *)cli_tmp_rxbuf, tmp1);
            printf("I2C TX (%u)\n",tmp2);
            drv_uart_puthex((u8_t *)&cli_tmp_txbuf[0],tmp1,FALSE);

            drv_uart_putstr("\nI2C RX:\n");
            drv_uart_puthex((u8_t *)&cli_tmp_rxbuf[0],tmp1,FALSE);
            drv_uart_putchar(UART_LF);
        }
        else {
            return(CLI_CMD_DENIED);
        }
    }
    else if (0 == strcmp("sta", argv[2]))
    {
        printf(" I2C                : %u\n", id);
        printf("  Interrupt Enable  : %s\n", g_cli_onoff_str[g_i2c_info[id].intr_en_flag]);
        printf("  Last status       : %u\n", g_i2c_info[id].last_status);
#if I2C_ISR_DBG_ENABLED
        printf("  Interrupt Count   : %u\n", g_i2c_info[id].intr_occurence_cnt);
        printf("  STA Reg Buffer    : %u\n", g_i2c_info[id].sta_buf_idx);
        drv_uart_puthex((u8_t *)&(g_i2c_info[id].sta_buf),g_i2c_info[id].sta_buf_idx,FALSE);
        printf("  RX Buffer    : %u, %u\n", g_i2c_info[id].rx_data_index, g_i2c_info[id].rx_data_len);
        drv_uart_puthex((u8_t *)&(g_i2c_info[id].rx_data[0]),I2C_BUFFER_SIZE,FALSE);
        printf("  TX Buffer    : %u, %u\n", g_i2c_info[id].tx_data_index, g_i2c_info[id].tx_data_len);
        drv_uart_puthex((u8_t *)&(g_i2c_info[id].tx_data[0]),I2C_BUFFER_SIZE,FALSE);
        g_i2c_info[id].intr_occurence_cnt = 0;
        g_i2c_info[id].sta_buf_idx = 0;
#endif /* I2C_ISR_DBG_ENABLED */
        drv_uart_putchar(UART_LF);
    }
    else {
        if (argc < 4)
            return(CLI_CMD_PARAM_ERROR);

        if (0 == strcmp("open", argv[2]))
        {
            cli_i2c_slv_addr[id] = (u8_t)strtoul(argv[3], (char **)0, 0);
            drv_i2c_open(id, cli_i2c_slv_addr[id]);
        }
        else {
            if (argc < 4)
                return(CLI_CMD_PARAM_ERROR);

            if (0 == strcmp("freq", argv[2]))
            {
                tmp1 = strtoul(argv[3], (char **)0, 0);
                if (0 == strcmp("custom", argv[3]))
                {
                    tmp2 = strtoul(argv[4], (char **)0, 0);
                    drv_i2c_master_freq_set(id, tmp2);
                }
                else if ((100 == tmp1) || (200 == tmp1) ||
                    (300 == tmp1) || (400 == tmp1) ||
                    (800 == tmp1) || (1000 == tmp1) ||
                    (2000 == tmp1))
                {
                    switch (tmp1)
                    {
                        case 2000:
                            drv_i2c_master_freq_set(id, I2C_FREQ_2073K);
                            break;
                        case 1000:
                            drv_i2c_master_freq_set(id, I2C_FREQ_1036K);
                            break;
                        case 800:
                            drv_i2c_master_freq_set(id, I2C_FREQ_829K);
                            break;
                        case 400:
                            drv_i2c_master_freq_set(id, I2C_FREQ_400K);
                            break;
                        case 300:
                            drv_i2c_master_freq_set(id, I2C_FREQ_300K);
                            break;
                        case 200:
                            drv_i2c_master_freq_set(id, I2C_FREQ_200K);
                            break;
                        case 100:
                            drv_i2c_master_freq_set(id, I2C_FREQ_100K);
                            break;
                        default:
                            break;
                    }
                    
                }
                else {
                    return(CLI_CMD_PARAM_ERROR);
                }
            }
            else if (0 == strcmp("rr", argv[2]))
            {
                if (cli_i2c_slv_addr[id])
                {
                    cli_tmp_txbuf[0] = (u8_t)strtoul(argv[3], (char **)0, 0);
                    tmp2 = strtoul(argv[4], (char **)0, 0);
                    if (0 == tmp2)
                        tmp2 = 1;

                    tmp1 = drv_i2c_master_transmit(id, cli_i2c_slv_addr[id], (u8_t *)&cli_tmp_txbuf[0], 1, (u8_t *)&cli_tmp_rxbuf[0], tmp2);
                    printf("I2C RR (%u)\n",tmp1);
                    drv_uart_puthex((u8_t *)&cli_tmp_rxbuf[0],tmp2,FALSE);
                }
                else {
                    return(CLI_CMD_DENIED);
                }
            }
            else if (0 == strcmp("ro", argv[2]))
            {
                if (cli_i2c_slv_addr[id])
                {
                    tmp2 = strtoul(argv[3], (char **)0, 0);
                    if (0 == tmp2)
                        tmp2 = 1;

                    tmp1 = drv_i2c_master_transmit(id, cli_i2c_slv_addr[id], (u8_t *)cli_tmp_txbuf, 0, (u8_t *)cli_tmp_rxbuf, tmp2);
                    printf("I2C RO (%u)\n",tmp1);
                    drv_uart_puthex((u8_t *)&cli_tmp_rxbuf[0],tmp2,FALSE);
                }
                else {
                    return(CLI_CMD_DENIED);
                }
            }
            else if (0 == strcmp("rw", argv[2]))
            {
                if (cli_i2c_slv_addr[id])
                {
                    cli_tmp_txbuf[0] = (u8_t)strtoul(argv[3], (char **)0, 0);
                    tmp2 = strtohex((u8_t *)&cli_tmp_txbuf[1], argv[4], 16);
                    tmp1 = drv_i2c_master_transmit(id, cli_i2c_slv_addr[id], (u8_t *)cli_tmp_txbuf, tmp2+1, NULL, 0);
                    printf("I2C RW (%u)\n",tmp1);
                    drv_uart_puthex((u8_t *)&cli_tmp_txbuf[0],tmp2,FALSE);
                }
                else {
                    return(CLI_CMD_DENIED);
                }
            }
            else {
                return(CLI_CMD_NOT_FOUND);
            }
        }
    }
    return(CLI_CMD_SUCCESS);
}
#endif

#if CLI_INCLUDE_PWM
const char * const g_cli_cmd_pwm_help[] = {
#if CLI_INCLUDE_HELP
    "PWM command",
#if CLI_ENABLED_VERBOSE_HELP
    "",
    "<id> {off|on}",
    "<id> {init} {low|high} <per>",
    "<id> {duty} <cmp1> <cmp2>",
    "<id> {freq} <init:0-1> <freq> <duty:0-100>",
#endif /* CLI_ENABLED_VERBOSE_HELP */
#endif /* CLI_INCLUDE_HELP */
    0,
};

int cli_cmd_pwm(int argc, char *argv[])
{
const char * const header = "  # EN  INIT PER   CMP1  CMP2\n -- --- ---- ----- ----- -----";
    u32_t id, tmp1, tmp2;
    char *p;

    if (argc < 2)
    {
        drv_uart_puts(header);
        for (id = 0; id < DRV_PWM_CHN_MAX; id++)
        {
            printf(" %02d %-3s %-4s %5X %5X %5X\n",
                id, 
                g_cli_onoff_str[drv_pwm_en_get(id) ? 1 : 0],
                drv_pwm_init_get(id) ? "High" : "Low",
                drv_pwm_per_get(id),
                drv_pwm_duty_cmp1_get(id),
                drv_pwm_duty_cmp2_get(id)
                );
        }        
    }
    else {
        id = strtoul(argv[1], &p, 0);
        if ((argc < 3) || (id >= DRV_PWM_CHN_MAX) || ((p != NULL) && (*p != '\0')))
            return(CLI_CMD_PARAM_ERROR);

        if (0 == strcmp("off", argv[2]))
        {
            drv_pwm_en_set(id,FALSE);
        }
        else if (0 == strcmp("on", argv[2]))
        {
            drv_pwm_en_set(id,TRUE);
        }
        else if (0 == strcmp("init", argv[2]))
        {
            if (argc < 5)
            {
                return(CLI_CMD_PARAM_ERROR);
            }
            tmp1 = strtoul(argv[4], &p, 0);
            if (0 == strcmp("low", argv[3]))
            {
                drv_pwm_init_set(id,0,tmp1);
            }
            else if (0 == strcmp("high", argv[3]))
            {
                drv_pwm_init_set(id,1,tmp1);
            }
            else {
                return(CLI_CMD_NOT_FOUND);
            }
        }
        else if (0 == strcmp("duty", argv[2]))
        {
            if (argc < 5)
            {
                return(CLI_CMD_PARAM_ERROR);
            }
            tmp1 = strtoul(argv[3], &p, 0);
            tmp2 = strtoul(argv[4], &p, 0);
            drv_pwm_duty_set(id,tmp1,tmp2);
            drv_pwm_en_set(id,TRUE);
        }
        else if (0 == strcmp("freq", argv[2]))
        {
            if (argc < 6)
            {
                return(CLI_CMD_PARAM_ERROR);
            }
            tmp1 = strtoul(argv[3], &p, 0);
            if ((tmp1 > 1) || ((p != NULL) && (*p != '\0')))
                return(CLI_CMD_PARAM_ERROR);
            tmp2 = strtoul(argv[4], &p, 0);
            if ((tmp2 > drv_chip_freq_get()) || ((p != NULL) && (*p != '\0')))
                return(CLI_CMD_PARAM_ERROR);
            u32_t tmp3 = strtoul(argv[5], &p, 0);
            if ((tmp3 > 100) || ((p != NULL) && (*p != '\0')))
                return(CLI_CMD_PARAM_ERROR);
            drv_pwm_freq_set(id,tmp1,tmp2,tmp3);
            drv_pwm_en_set(id,TRUE);
        }
        else {
            return(CLI_CMD_NOT_FOUND);
        }
    }

    return(CLI_CMD_SUCCESS);
}
#endif


#if CLI_INCLUDE_WDT
const char * const g_cli_cmd_wdt_help[] = {
#if CLI_INCLUDE_HELP
    "WDT commands",
#if CLI_ENABLED_VERBOSE_HELP
    "",
    "{on <timeout:ms>|off}",
    "\t The maximal timeout is 129,453 ms",
    "{feed}",
#endif /* CLI_ENABLED_VERBOSE_HELP */
#endif /* CLI_INCLUDE_HELP */
    0,
};

int cli_cmd_wdt(int argc, char *argv[])
{
    u32_t tmp;
    char *p;

    if (argc < 2)
    {
        printf(" WDT is %s", g_cli_onoff_str[drv_wdt_enable_get()]);
        if (drv_wdt_enable_get())
        {
            printf(", timeout on %d ms\n", drv_wdt_timeout_get());
        }
        else {
            drv_uart_putchar(UART_LF);
        }
    }
    else {
        if (0 == strcmp("off", argv[1]))
        {
            drv_wdt_init(0, FALSE);
        }
        else if (0 == strcmp("feed", argv[1]))
        {
            drv_wdt_feed();
        }
        else if (0 == strcmp("on", argv[1]))
        {
            if (argc < 3)
                return(CLI_CMD_PARAM_ERROR);

            tmp = strtoul(argv[2], &p, 0);
            drv_wdt_init(tmp, TRUE);
        }
        else {
            return(CLI_CMD_NOT_FOUND);
        }
    }

    return(CLI_CMD_SUCCESS);

}
#endif

#if CLI_INCLUDE_UART
const char * const g_cli_cmd_uart_help[] = {
#if CLI_INCLUDE_HELP
    "UART commands",
#if CLI_ENABLED_VERBOSE_HELP
    "",
    "<id> {on|off}",
    "<id> {baudrate} <value>",
    "<id> {databits} {5|6|7|8}",
    "<id> {parity} {on {odd|even}|off}",
    "<id> {stopbits} {1|2}",
    "<id> {loop} {on|off}",
    "<id> {dma} {on|off}",
    "<id> {flowctrl} {on|off}",
    "<id> {tx} <string>",
    "\t The maximal length of string is 16",
#endif /* CLI_ENABLED_VERBOSE_HELP */
#endif /* CLI_INCLUDE_HELP */
    0,
};

int cli_cmd_uart(int argc, char *argv[])
{
    u32_t id, tmp;
    char *p;

    if (argc < 2)
    {
        for (int i = 0; i < DRV_UART_ID_MAX; i++)
        {
            printf("\n UART         : %d\n", i);
            printf("  Interrupt   : %s\n", g_cli_onoff_str[drv_uart_common_intr_get(i)]);
            printf("  Baud rate   : %u\n", drv_uart_common_baud_rate_get(i));
            printf("  Data bits   : %u\n", drv_uart_common_data_length_get(i) + 5);
            printf("  Parity      : %s\n", drv_uart_common_parity_check_get(i) ? (drv_uart_common_parity_selection_get(i) ? "Even" : "Odd") : "None");
            printf("  Stop bits   : %u\n", drv_uart_common_stop_bit_get(i) + 1);
            if (DRV_UART_ID_1 == i)
            {
                printf("  Loopback    : %s\n", g_cli_onoff_str[sys_uart1_loopback_get()]);
            }
            else {
                printf("  Flow Control: %s\n", g_cli_onoff_str[drv_uart_common_flowctrl_get(0)]);
            }
        }
    }
    else {

        id = strtoul(argv[1], &p, 0);
        if ((argc < 3) || (id>= DRV_UART_ID_MAX) || ((p != NULL) && (*p != '\0')))
            return(CLI_CMD_PARAM_ERROR);


        if (0 == strcmp("off", argv[2]))
        {
            drv_uart_common_intr_set(id, FALSE);
        }
        else if (0 == strcmp("on", argv[2]))
        {
            drv_uart_common_init(id);
            drv_uart_common_intr_set(id, TRUE);
        }
        else if (0 == strcmp("baudrate", argv[2]))
        {
            if (argc < 4)
                return(CLI_CMD_PARAM_ERROR);

            tmp = strtoul(argv[3], &p, 0);
            drv_uart_common_baud_rate_set(id, tmp);
        }
        else if (0 == strcmp("databits", argv[2]))
        {
            if (argc < 4)
                return(CLI_CMD_PARAM_ERROR);

            if (0 == strcmp("5", argv[3]))
            {
                drv_uart_common_data_length_set(id,DRV_UART_DATA_BITS_5);
            }
            else if (0 == strcmp("6", argv[3]))
            {
                drv_uart_common_data_length_set(id,DRV_UART_DATA_BITS_6);
            }
            else if (0 == strcmp("7", argv[3]))
            {
                drv_uart_common_data_length_set(id,DRV_UART_DATA_BITS_7);
            }
            else if (0 == strcmp("8", argv[3]))
            {
                drv_uart_common_data_length_set(id,DRV_UART_DATA_BITS_8);
            }
            else {
                return(CLI_CMD_NOT_FOUND);
            }
        }
        else if (0 == strcmp("parity", argv[2]))
        {
            if (argc < 4)
                return(CLI_CMD_PARAM_ERROR);

            if (0 == strcmp("on", argv[3]))
            {
                if (argc < 5)
                    return(CLI_CMD_PARAM_ERROR);

                if (0 == strcmp("odd", argv[4]))
                {
                    drv_uart_common_parity_check_set(id,TRUE,0);
                }
                else if (0 == strcmp("even", argv[4]))
                {
                    drv_uart_common_parity_check_set(id,TRUE,1);
                }
                else {
                    return(CLI_CMD_NOT_FOUND);
                }
            }
            else if (0 == strcmp("off", argv[3]))
            {
                drv_uart_common_parity_check_set(id,FALSE,0);
            }
            else {
                return(CLI_CMD_NOT_FOUND);
            }
        }
        else if (0 == strcmp("stopbits", argv[2]))
        {
            if (argc < 4)
                return(CLI_CMD_PARAM_ERROR);

            if (0 == strcmp("1", argv[3]))
            {
                drv_uart_common_stop_bit_set(id,FALSE);
            }
            else if (0 == strcmp("2", argv[3]))
            {
                drv_uart_common_stop_bit_set(id,TRUE);
            }
            else {
                return(CLI_CMD_NOT_FOUND);
            }
        }
        else if (0 == strcmp("loop", argv[2]))
        {
            if (argc < 4)
                return(CLI_CMD_PARAM_ERROR);

            if (0 == strcmp("on", argv[3]))
            {
                sys_uart1_loopback_set(TRUE);
            }
            else if (0 == strcmp("off", argv[3]))
            {
                sys_uart1_loopback_set(FALSE);
            }
            else {
                return(CLI_CMD_NOT_FOUND);
            }
        }
        else if (0 == strcmp("dma", argv[2]))
        {
            if (DRV_UART_ID_0 == id)
                return(CLI_CMD_DENIED);

            if (argc < 4)
                return(CLI_CMD_PARAM_ERROR);

            if (0 == strcmp("on", argv[3]))
            {
                drv_uart1_dma_en_set(TRUE);
            }
            else if (0 == strcmp("off", argv[3]))
            {
                drv_uart1_dma_en_set(FALSE);
            }
            else {
                return(CLI_CMD_NOT_FOUND);
            }
        }
        else if (0 == strcmp("flowctrl", argv[2]))
        {
            if (DRV_UART_ID_1 == id)
                return(CLI_CMD_DENIED);

            if (argc < 4)
                return(CLI_CMD_PARAM_ERROR);

            if (0 == strcmp("on", argv[3]))
            {
                drv_uart_common_flowctrl_set(id,TRUE);
            }
            else if (0 == strcmp("off", argv[3]))
            {
                drv_uart_common_flowctrl_set(id,FALSE);
            }
            else {
                return(CLI_CMD_NOT_FOUND);
            }
        }
        else if (0 == strcmp("tx", argv[2]))
        {
            if (argc < 4)
                return(CLI_CMD_PARAM_ERROR);

            strncpy((char *)cli_tmp_txbuf, argv[3], 16);
            cli_tmp_txbuf[16] = 0;
            drv_uart_common_putstr(id, (char *)cli_tmp_txbuf);
        }
        else if (0 == strcmp("default", argv[2]))
        {
            if (argc < 4)
                return(CLI_CMD_PARAM_ERROR);

            if (0 == strcmp("on", argv[3]))
            {
                drv_uart_default_set(id);
            }
            else if (0 == strcmp("off", argv[3]))
            {
                drv_uart_default_set(DRV_UART_ID_1);
            }
            else {
                return(CLI_CMD_NOT_FOUND);
            }
        }
        else {
            return(CLI_CMD_NOT_FOUND);
        }
    }

    return(CLI_CMD_SUCCESS);

}
#endif


#if CLI_INCLUDE_SYS
/** System information help */
const char * const g_cli_cmd_sys_help[] = {
#if CLI_INCLUDE_HELP
    "System command",
#if CLI_ENABLED_VERBOSE_HELP
    "{timer}",
    "{trim}",
#endif /* CLI_ENABLED_VERBOSE_HELP */
#endif /* CLI_INCLUDE_HELP */
    0,
};

#if SYS_FREERTOS_ENABLED
void vTaskListPrint(void)
{
#define LINE_LEN_OF_TASK_LIST   (26)
const char * const pcHeader = "\n Task STA PRI Stack #\n ---- --- --- ----- --";
char *pcListBuffer;

    pcListBuffer = pvPortMalloc(uxTaskGetNumberOfTasks() * LINE_LEN_OF_TASK_LIST);
    if( pcListBuffer != NULL )
	{
    	/* Create the list of task states. */
    	vTaskList( pcListBuffer );

    	drv_uart_puts(pcHeader);
    	drv_uart_puts(pcListBuffer);
        vPortFree( pcListBuffer );
    }
}

extern size_t xPortGetFreeHeapSize( void );

#endif

extern char total_mem [];
extern char global_stack_size [];
extern char global_data_size [];
extern volatile u32_t g_ext_interrupt_idx_pri_map;
extern volatile u32_t g_ext_interrupt_pri_idx_map;

const char * const g_cli_intr_str[IPIC_CFG_INTR_VEC_NUM] = {
    "PD",
    "DMA",
    "I2C0",
    "I2C1",
    "UART0",
    "UART1",
    "SPI",
    "GPIO"
    };

int cli_cmd_sys(int argc, char *argv[])
{
    u32_t current_time = (u32_t)(now()/SAL_SECOND_US);

    if (argc < 2)
    {
        cli_print_brand(TRUE);
        printf("\n %-26s: %u Hz\n", "System Clock", drv_chip_freq_get());
        printf(" %-26s: %02u:%02u:%02u\n", "Up Time", current_time / 3600, (current_time / 60) % 60, current_time % 60);
        //printf(" %-26s: %f\n", "Pi", 3.1415926);

        printf("\n %-26s: %s\n", "Debug Level", g_cli_dbg_lvl_str[sys_cfg_dbg_get()]);
        printf(" %-26s: %s [%u s]\n", "Sleep Mode", g_cli_onoff_str[sys_cfg_sleep_mode_get()], sys_cfg_idle_hold_time_get());
        printf(" %-26s: %s [%u ms]\n", "Auto wakeup", g_cli_onoff_str[sys_cfg_auto_wakeup_get() ? TRUE : FALSE], sys_cfg_auto_wakeup_get());

        printf("\n %-26s: %s\n", "WDT Enabled", g_cli_true_str[drv_wdt_enable_get() ? TRUE : FALSE]);
        printf(" %-26s: %s\n", "WDT Reset Flag", g_cli_true_str[drv_wdt_reset_flag_get() ? TRUE : FALSE]);

    	drv_uart_puts("\n Memory :");
        printf("  %-25s: %u\n", "Total", (unsigned int)total_mem);
        printf("  %-25s: %u\n", "Free", (unsigned int)total_mem - (unsigned int)global_stack_size - (unsigned int)global_data_size);
        printf("  %-25s: %u\n", "Global Stack", (unsigned int)global_stack_size);
#if SYS_FREERTOS_ENABLED
        printf("  %-25s: %u\n", "Global Data", (unsigned int)global_data_size - (unsigned int)configTOTAL_HEAP_SIZE);
        printf("  %-25s: %u\n", "Heap Total", (unsigned int)configTOTAL_HEAP_SIZE);
        printf("  %-25s: %u\n", "Heap Free", xPortGetFreeHeapSize());
    	vTaskListPrint();
#else
        printf("  %-25s: %u\n\n", "Global Data", (unsigned int)global_data_size);
#endif
    }
    else {
        if (0 == strcmp("timer", argv[1]))
        {
            drv_timer_dump();
        }
        else if (0 == strcmp("trim", argv[1]))
        {
        	drv_uart_putstr(" Trim-Code :");
            drv_uart_puthex((u8_t *)&trim_code_buffer[0],DRV_FLASH_TRIM_CODE_NUM,FALSE);
            printf("  %-25s: 0x%X\n", "Current Sense Offset", drv_flash_trim_current_sense_offset_get());
            printf("  %-25s: %u\n", "ADC Reference Voltage", drv_flash_trim_ref_volt_get());
        }
        else if (0 == strcmp("intr", argv[1]))
        {
            drv_uart_puts(" Interrupts : ");
            for (int i = 0; i < IPIC_CFG_INTR_VEC_NUM; i++)
            {
                printf("  %-25s: %-3s, PRI: %u\n", g_cli_intr_str[i], g_cli_onoff_str[drv_intr_ext_en_get(i)],SAL_FIELD_GET2(g_ext_interrupt_idx_pri_map,i<<2,3));
            }
            if (sys_cfg_dbg_get() >= SYS_DEBUG_LEVEL_3)
            {
                printf("  %-25s: 0x%08X\n", "Index to Priority Map", g_ext_interrupt_idx_pri_map);
                printf("  %-25s: 0x%08X(0x%08X)\n", "Priority to Index Map", g_ext_interrupt_pri_idx_map,DRV_REG_GET(MCU_INT_INDEX_REG));
            }
        }
        else {
            return(CLI_CMD_NOT_FOUND);
        }
    }

    return(CLI_CMD_SUCCESS);
}
#endif

#if CLI_INCLUDE_CFG
const char * const g_cli_cmd_cfg_help[] = {
#if CLI_INCLUDE_HELP
    "System config",
#if CLI_ENABLED_VERBOSE_HELP
    "{erase}",
    "{save}",
    "{dbg} {off|l1|l2|l3}",
    "{sleep} {on|off} [second]",
    "{wakeup} <ms>",
    "{clock} {33m|29m|22m|11m|7.375m|5.5m|3.625m}",
    "{trim} {ref} <voltage>",
    "{trim} {isense} <offset>",
#endif /* CLI_ENABLED_VERBOSE_HELP */
#endif /* CLI_INCLUDE_HELP */
    0,
};

int cli_cmd_cfg(int argc, char *argv[])
{
    u32_t tmp;
    if (argc < 2)
        return(CLI_CMD_PARAM_ERROR);

    if (0 == strcmp("erase", argv[1]))
    {
        printf("\n Erasing config... ");
        sys_cfg_erase();
        printf("done\n");
    }
    else if (0 == strcmp("save", argv[1]))
    {
        printf("\n Saving config... ");
        sys_cfg_save();
        printf("done\n");
    }
    else if (0 == strcmp("dbg", argv[1])) 
    {
        if (argc < 3)
            return(CLI_CMD_PARAM_ERROR);

        if (0 == strcmp("l1", argv[2]))
        {
            sys_cfg_dbg_set(SYS_DEBUG_LEVEL_1);
        }
        else if (0 == strcmp("off", argv[2]))
        {
            sys_cfg_dbg_set(SYS_DEBUG_LEVEL_OFF);
        }
        else if (0 == strcmp("l2", argv[2]))
        {
            sys_cfg_dbg_set(SYS_DEBUG_LEVEL_2);
        }
        else if (0 == strcmp("l3", argv[2]))
        {
            sys_cfg_dbg_set(SYS_DEBUG_LEVEL_3);
        }
        else if (0 == strcmp("l4", argv[2]))
        {
            sys_cfg_dbg_set(SYS_DEBUG_LEVEL_4);
        }
        else {
            return(CLI_CMD_NOT_FOUND);
        }
    }
    else if (0 == strcmp("sleep", argv[1])) 
    {
        if (argc < 3)
            return(CLI_CMD_PARAM_ERROR);

        if (0 == strcmp("on", argv[2]))
        {
            sys_lpm_activate();
            sys_cfg_sleep_mode_set(TRUE);
            // configure idle hold time
            if (argc >= 4)
            {
                tmp = strtoul(argv[3],(char **)0, 0) & 0xFF;
                if (0 == tmp)
                    tmp = SYS_CONFIG_IDLE_HOLD_TIME;
                sys_cfg_idle_hold_time_set(tmp);
            }
            else if (0 == sys_cfg_idle_hold_time_get()) 
            {
                sys_cfg_idle_hold_time_set(SYS_CONFIG_IDLE_HOLD_TIME);
            }
            sys_lpm_idle_hold_time_set(sys_cfg_idle_hold_time_get());
            sys_lpm_activate();
        }
        else if (0 == strcmp("off", argv[2]))
        {
            sys_cfg_sleep_mode_set(FALSE);
        }
        else 
        {
            return(CLI_CMD_NOT_FOUND);
        }
    }
    else if (0 == strcmp("wakeup", argv[1])) 
    {
        if (argc < 3)
            return(CLI_CMD_PARAM_ERROR);

        tmp = strtoul(argv[2],(char **)0, 0);
        if (tmp > 15000)
            tmp = 15000;

        if (0 != (tmp % 500))
        {
            drv_uart_puts("Please input wakeup time in multiple of 500 milliseconds\n");
            return(CLI_CMD_SUCCESS);
        }
        // save configuration
        sys_cfg_auto_wakeup_set(tmp);
    }
    else if (0 == strcmp("clock", argv[1])) 
    {
        if (argc < 3)
            return(CLI_CMD_PARAM_ERROR);

        if (0 == strcmp("33m", argv[2]))
        {
            drv_uart_common_intr_set(drv_uart_default_get(), FALSE);
            drv_uart_common_intr_set(drv_uart_second_get(), FALSE);
            drv_chip_freq_set(DRV_CHIP_FREQ_33M);
            // update baudrate configuration
            drv_uart_common_baud_rate_set(drv_uart_default_get(), DRV_UART_DEF_BAUDRATE);
            drv_uart_common_baud_rate_set(drv_uart_second_get(), DRV_UART_DEF_BAUDRATE);
            drv_uart_common_intr_set(drv_uart_default_get(), TRUE);
            drv_uart_common_intr_set(drv_uart_second_get(), TRUE);
        }
        else if (0 == strcmp("29m", argv[2]))
        {
            drv_uart_common_intr_set(drv_uart_default_get(), FALSE);
            drv_uart_common_intr_set(drv_uart_second_get(), FALSE);
            drv_chip_freq_set(DRV_CHIP_FREQ_29M);
            // update baudrate configuration
            drv_uart_common_baud_rate_set(drv_uart_default_get(), DRV_UART_DEF_BAUDRATE);
            drv_uart_common_baud_rate_set(drv_uart_second_get(), DRV_UART_DEF_BAUDRATE);
            drv_uart_common_intr_set(drv_uart_default_get(), TRUE);
            drv_uart_common_intr_set(drv_uart_second_get(), TRUE);
        }
        else if (0 == strcmp("22m", argv[2]))
        {
            drv_uart_common_intr_set(drv_uart_default_get(), FALSE);
            drv_uart_common_intr_set(drv_uart_second_get(), FALSE);
            drv_chip_freq_set(DRV_CHIP_FREQ_22M);
            // update baudrate configuration
            drv_uart_common_baud_rate_set(drv_uart_default_get(), DRV_UART_DEF_BAUDRATE);
            drv_uart_common_baud_rate_set(drv_uart_second_get(), DRV_UART_DEF_BAUDRATE);
            drv_uart_common_intr_set(drv_uart_default_get(), TRUE);
            drv_uart_common_intr_set(drv_uart_second_get(), TRUE);
        }
        else if (0 == strcmp("11m", argv[2]))
        {
            drv_uart_common_intr_set(drv_uart_default_get(), FALSE);
            drv_uart_common_intr_set(drv_uart_second_get(), FALSE);
            drv_chip_freq_set(DRV_CHIP_FREQ_11M);
            // update baudrate configuration
            drv_uart_common_baud_rate_set(drv_uart_default_get(), DRV_UART_DEF_BAUDRATE);
            drv_uart_common_baud_rate_set(drv_uart_second_get(), DRV_UART_DEF_BAUDRATE);
            drv_uart_common_intr_set(drv_uart_default_get(), TRUE);
            drv_uart_common_intr_set(drv_uart_second_get(), TRUE);
        }
        else if (0 == strcmp("7.375m", argv[2]))
        {
            drv_uart_common_intr_set(drv_uart_default_get(), FALSE);
            drv_uart_common_intr_set(drv_uart_second_get(), FALSE);
            drv_chip_freq_set(DRV_CHIP_FREQ_7P375M);
            // update baudrate configuration
            drv_uart_common_baud_rate_set(drv_uart_default_get(), DRV_UART_DEF_BAUDRATE);
            drv_uart_common_baud_rate_set(drv_uart_second_get(), DRV_UART_DEF_BAUDRATE);
            drv_uart_common_intr_set(drv_uart_default_get(), TRUE);
            drv_uart_common_intr_set(drv_uart_second_get(), TRUE);
        }
        else if (0 == strcmp("5.5m", argv[2]))
        {
            drv_uart_common_intr_set(drv_uart_default_get(), FALSE);
            drv_uart_common_intr_set(drv_uart_second_get(), FALSE);
            drv_chip_freq_set(DRV_CHIP_FREQ_5P5M);
            // update baudrate configuration
            drv_uart_common_baud_rate_set(drv_uart_default_get(), DRV_UART_DEF_BAUDRATE);
            drv_uart_common_baud_rate_set(drv_uart_second_get(), DRV_UART_DEF_BAUDRATE);
            drv_uart_common_intr_set(drv_uart_default_get(), TRUE);
            drv_uart_common_intr_set(drv_uart_second_get(), TRUE);
        }
        else if (0 == strcmp("3.625m", argv[2]))
        {
            drv_uart_common_intr_set(drv_uart_default_get(), FALSE);
            drv_uart_common_intr_set(drv_uart_second_get(), FALSE);
            drv_chip_freq_set(DRV_CHIP_FREQ_3P625M);
            // update baudrate configuration
            drv_uart_common_baud_rate_set(drv_uart_default_get(), DRV_UART_DEF_BAUDRATE);
            drv_uart_common_baud_rate_set(drv_uart_second_get(), DRV_UART_DEF_BAUDRATE);
            drv_uart_common_intr_set(drv_uart_default_get(), TRUE);
            drv_uart_common_intr_set(drv_uart_second_get(), TRUE);
        }
        else {
            return(CLI_CMD_NOT_FOUND);
        }
        printf("PLL CFG: 0x%X\n", DRV_REG_GET(PLL_CFG_REG));
    }
    else if (0 == strcmp("trim", argv[1])) 
    {
        if (argc < 3)
            return(CLI_CMD_PARAM_ERROR);

        // configure reference voltage
        if (0 == strcmp("ref", argv[2]))
        {
            tmp = strtoul(argv[3],(char **)0, 0) & 0xFFF;
            if (0 == tmp)
                tmp = 3300;
            drv_flash_trim_ref_volt_set(tmp);
        }
        else if (0 == strcmp("isense", argv[2]))
        {
            tmp = strtoul(argv[3],(char **)0, 0) & 0xFFF;
            if ((0 == tmp) || (0xFFF == tmp))
                tmp = 0x800;
            printf("isense: %u\n", tmp);
            drv_flash_trim_current_sense_offset_set(tmp);
        }
        else 
        {
            return(CLI_CMD_NOT_FOUND);
        }
    }
    else 
    {
        return(CLI_CMD_NOT_FOUND);
    }

    return(CLI_CMD_SUCCESS);
}
#endif


#if CLI_INCLUDE_BIST
const char * const g_cli_cmd_bist_help[] = {
#if CLI_INCLUDE_HELP
    "System BIST",
#if CLI_ENABLED_VERBOSE_HELP
    "{init}",
    "{clkgen} <count>",
    "{rd} <addr>",
    "{wr} <addr> <data>",
#endif /* CLI_ENABLED_VERBOSE_HELP */
#endif /* CLI_INCLUDE_HELP */
    0,
};

int cli_cmd_bist(int argc, char *argv[])
{
    u32_t addr = 0;
    u8_t resp = 0;
    u32_t val = 0;
    if (argc < 2)
        return(CLI_CMD_PARAM_ERROR);

    if (0 == strcmp("init", argv[1]))
    {
        drv_bist_init();
    }
    else if (0 == strcmp("clkgen", argv[1]))
    {
        if (argc < 3)
            return(CLI_CMD_PARAM_ERROR);

        val = strtoul(argv[2],(char **)0, 0);

#if SYS_FREERTOS_ENABLED
    sync_enter_critical();
#endif /* SYS_FREERTOS_ENABLED */
        drv_bist_clk_gen(val);
#if SYS_FREERTOS_ENABLED
    sync_exit_critical();
#endif /* SYS_FREERTOS_ENABLED */

        printf("BIST clk gen %u\n", val);
        
    }
    else if (0 == strcmp("rd", argv[1])) 
    {
        if (argc < 3)
            return(CLI_CMD_PARAM_ERROR);

        addr = strtoul(argv[2],(char **)0, 0);

#if SYS_FREERTOS_ENABLED
    sync_enter_critical();
#endif /* SYS_FREERTOS_ENABLED */
        resp = drv_bist_read(addr, &val);
#if SYS_FREERTOS_ENABLED
    sync_exit_critical();
#endif /* SYS_FREERTOS_ENABLED */

        printf("BIST read 0x%08X, response = 0x%02X, value = 0x%08X\n", addr, resp, val);
    }
    else if (0 == strcmp("wr", argv[1])) 
    {
        if (argc < 4)
            return(CLI_CMD_PARAM_ERROR);

        addr = strtoul(argv[2],(char **)0, 0);
        val = strtoul(argv[3],(char **)0, 0);

#if SYS_FREERTOS_ENABLED
    sync_enter_critical();
#endif /* SYS_FREERTOS_ENABLED */
        resp = drv_bist_write(addr, val);
#if SYS_FREERTOS_ENABLED
    sync_exit_critical();
#endif /* SYS_FREERTOS_ENABLED */

        printf("BIST write 0x%08X, value = 0x%08X, response = 0x%02X\n", addr, val, resp);
    }
    else 
    {
        return(CLI_CMD_NOT_FOUND);
    }

    return(CLI_CMD_SUCCESS);
}
#endif


extern const char * const g_cli_cmd_help_help[];
int cli_cmd_help(int argc,char *argv[]);
extern const char * const g_cli_cmd_logout_help[];
int cli_cmd_logout(int argc,char *argv[]);

void cli_cmd_base_init()
{
#if CLI_INCLUDE_HELP
    cli_cmd_list_add( "?",              g_cli_cmd_help_help,         cli_cmd_help );
#endif
#if CLI_INCLUDE_LOGOUT
    cli_cmd_list_add( "exit",           g_cli_cmd_logout_help,       cli_cmd_logout );
#endif
#if CLI_INCLUDE_RESET
    cli_cmd_list_add( "reset",          g_cli_cmd_rst_help,          cli_cmd_rst );
#endif
#if CLI_INCLUDE_VER
    cli_cmd_list_add( "ver",            g_cli_cmd_ver_help,          cli_cmd_ver );
#endif
#if CLI_INCLUDE_REG
    cli_cmd_list_add( "rr",             g_cli_cmd_reg_read_help,     cli_cmd_reg_read );
    cli_cmd_list_add( "rw",             g_cli_cmd_reg_write_help,    cli_cmd_reg_write );
#endif /* CLI_INCLUDE_REG */
#if CLI_INCLUDE_DM
    cli_cmd_list_add( "dm",             g_cli_cmd_dm_help,           cli_cmd_dm );
#endif
#if CLI_INCLUDE_MM
    cli_cmd_list_add( "mm",             g_cli_cmd_mm_help,           cli_cmd_mm );
#endif
#if CLI_INCLUDE_GPIO
    cli_cmd_list_add( "gpio",           g_cli_cmd_gpio_help,         cli_cmd_gpio );
#endif
#if CLI_INCLUDE_GPIO_CAP
    cli_cmd_list_add( "incap",          g_cli_cmd_gpio_cap_help,     cli_cmd_gpio_cap );
#endif
#if CLI_INCLUDE_ADC
    cli_cmd_list_add( "adc",            g_cli_cmd_adc_help,          cli_cmd_adc );
#endif
#if CLI_INCLUDE_SPI
    cli_cmd_list_add( "spi",            g_cli_cmd_spi_help,          cli_cmd_spi );
#endif
#if CLI_INCLUDE_I2C
    cli_cmd_list_add( "i2c",            g_cli_cmd_i2c_help,          cli_cmd_i2c );
#endif
#if CLI_INCLUDE_PWM
    cli_cmd_list_add( "pwm",            g_cli_cmd_pwm_help,          cli_cmd_pwm );
#endif
#if CLI_INCLUDE_WDT
    cli_cmd_list_add( "wdt",            g_cli_cmd_wdt_help,          cli_cmd_wdt );
#endif
#if CLI_INCLUDE_UART
    cli_cmd_list_add( "uart",           g_cli_cmd_uart_help,         cli_cmd_uart );
#endif
#if CLI_INCLUDE_SYS
    cli_cmd_list_add( "sys",            g_cli_cmd_sys_help,          cli_cmd_sys );
#endif
#if CLI_INCLUDE_CFG
    cli_cmd_list_add( "cfg",            g_cli_cmd_cfg_help,          cli_cmd_cfg );
#endif
#if CLI_INCLUDE_UPGRADE
    cli_cmd_list_add( "fwup",           g_cli_cmd_upgrade_help,      cli_cmd_upgrade );
#endif
#if CLI_INCLUDE_BIST
    cli_cmd_list_add( "bist",           g_cli_cmd_bist_help,         cli_cmd_bist );
#endif
}


#endif

