Preface
We have tested the serial port before, refer to
https://en.eeworld.com/bbs/thread-1247060-1-1.html
https://en.eeworld.com/bbs/thread-1247447-1-1.html
To facilitate subsequent debugging, we will now implement a simple SHELL command line.
process
First, you need to implement the serial port transceiver interface
intuart_read(uint8_t* buffer, uint32_tlen)
{
if(cyhal_uart_getc(&cy_retarget_io_uart_obj, buffer, len)
== CY_RSLT_SUCCESS)
{
returnlen;
}
else
{
return0;
}
}
intuart_write(uint8_t* buffer, uint32_tlen)
{
while(len--)
{
cyhal_uart_putc(&cy_retarget_io_uart_obj, *buffer++);
}
}
Implemented in Shell.c and putchar, putchar has been redirected so it does not need to be implemented, otherwise it can be changed to uart_write
/**
*****************************************************************************
* \fnstatic intshell_getchar(unsigned char *data)
* \brief reads a character.
* \note .
* \ param [out] data stores the read data.
* retval 0 Success.
* retval -1 failed.
*****************************************************************************
*/
staticintshell_getchar(unsignedchar*data)
{
int error=0;
//driver_uart_recv(getstdiouart(), data, 1,10,&erro);
if(0 == uart_read(data, 1))
{
error = 1;
}
else
{
uart_write(data,1);
}
if (error!=0)
{
return-1;
}
return0;
}
Core data structures
typedef void ( * CommandFunc )( void *); /**< shell command callback function*/
/**
* \structshell_cmd_cfg
* SHELL command structure.
*/
typedefstruct
{
unsigned char const * name; /**< shell command name*/
CommandFunc func; /**< shell command callback function*/
char const * helpstr; /**< Help string*/
}shell_cmd_cfg;
Defining a table
constshell_cmd_cfgshell_cmd_list[ ] =
{
/*1. Help related*/
{ ( const uint8_t*)"help", HelpFun, "help"}, /*Print help information*/
{ 0, 0 },
};
When receiving a command line, shell_cmd_list is searched for the command name. If a match is found, the function func is called to execute.
Read a line of command key code
staticunsignedintshell_read_line(intget(unsignedchar* tmp))
{
unsignedcharch = '\r';
unsignedintcount;
unsignedchartmp;
/*Start printing once " sh >"*/
if(cmd_buf[0]=='\r')
{
printf("sh>\r\n");
memset(cmd_buf,0x00,sizeof(cmd_buf));
}
/*If a character is received, go down, otherwise return*/
if(get(&tmp)==0)
{
ch = tmp;
}
else
{
return0;
}
/*If a non-printing character is received and the current receive buffer is not 0, it is considered that a frame is received, otherwise "SH>" is printed*/
if((ch == '\r'|| ch == '\n'|| ch < ' '|| ch > '~') && (ch != '\b'))
{
if(cmd_buf_index==0)
{
printf("sh>\r\n");
}
else
{
count = cmd_buf_index;
cmd_buf[cmd_buf_index]=0;
cmd_buf_index =0;
printf("\r\n");
returncount;
}
}
else
{
if(ch == '\b')
{
if(cmd_buf_index != 0)
{
cmd_buf_index--;
putchar('\b');
putchar(' ');
putchar('\b');
cmd_buf[cmd_buf_index]= '\0';
}
}
else
{
/*If a print character is received and the current receive buffer is full, it is considered that one frame has been received"*/
putchar(ch);
cmd_buf[cmd_buf_index++] = ch;
if(cmd_buf_index>=(sizeof(cmd_buf)-1))
{
count = cmd_buf_index;
cmd_buf[cmd_buf_index]=0;
cmd_buf_index =0;
printf("\r\n");
returncount;
}
}
}
return0;
}
test
Compile and run, you can enter help to view the command list
Code
shell.c
/**
*****************************************************************************
* \brief Platform related (PLATFORM) SHELL module (SHELL) related interface implementation.
* \details
* All rights reserved.
* \file shell.c
* \author
* \version 1.0
* \date
* \note Please refer to the notes before use.\n
* \since Newly created
* \par Revision record
* - Initial version
* \par Resource description
* - RAM:
* - ROM:
**************************************************************************
*/
#include <stdio.h>
#include <string.h>
#include "shell.h"
#include "cy_retarget_io.h"
extern int uart_read(uint8_t* buffer, uint32_t len);
extern int uart_write(uint8_t* buffer, uint32_t len);
/********************************************************************************
*
* Internal data
*
****************************************************************************/
#define SHELL_CMD_LEN 64 /**< Shell command buffer length */
extern const shell_cmd_cfg shell_cmd_list[ ]; /**< Defined in shell_fun */
extern const shell_cmd_cfg shell_cmd_list_app[ ]; /**< Defined in app_shellfun */
static int shellpassed = 1; /**< Whether the shell password is verified: 0: verified, 1: not verified */
static unsigned char cmd_buf[SHELL_CMD_LEN]="\r";
static int cmd_buf_index=0; /**< Number of characters of the command currently received */
/********************************************************************************
*
* Internal interface function implementation
*
****************************************************************************/
/**
**************************************************************************
* \fn static int shell_getchar(unsigned char *data)
* \brief Read a character.
* \note .
* \param[out] data stores the read data.
* retval 0 success.
* retval -1 failure.
*****************************************************************************
*/
static int shell_getchar(unsigned char *data)
{
int erro=0;
//driver_uart_recv(getstdiouart(), data, 1,10,&erro);
if(0 == uart_read(data, 1))
{
erro = 1;
}
else
{
uart_write(data,1);
}
if(erro!=0)
{
return -1;
}
return 0;
}
/**
**************************************************************************
* \fn static unsigned int shell_cmd_len(char const *cmd)
* \brief Get the command character length.
* \note End with space or \0.
* \param[in] cmd string
* return unsigned int command character length
************************************************************************
*/
static unsigned int shell_cmd_len(unsigned char const *cmd)
{
unsigned char const *p = cmd;
unsigned int len = 0;
while((*p != ' ') && (*p != 0))
{
p++;
len++;
}
return len;
}
/**
**************************************************************************
* \fn static void shell_check_passwd(void)
* \brief Shell password confirmation.
* \note End with space or \0.
*****************************************************************************
*/
static void shell_check_passwd(void)
{
unsigned int i;
unsigned char ch[6] = {0};
unsigned char pw[7] = SHELL_PASSWORD_STR;
while(1)
{
printf("\r\nPassword:");
memset(ch, 0, sizeof(ch));
for (i = 0; i < sizeof(ch); i++)
{
ch = getchar();
putchar('\b');
putchar('*');
}
if (memcmp(pw, ch, sizeof(ch)) == 0)
{
printf("\r\n");
break;
}
printf("\r\nAccess denied\r\n");
}
}
/**
**************************************************************************
* \fn static int shell_cmd_check(unsigned char *cmd, char const *str)
* \brief Match command characters.
* \note .
* \param[in] cmd string
* \param[in] str Matching character
* retval 0 Match successful
* retval 1 Match failed
********************************************************************************
*/
static int shell_cmd_check(unsigned char *cmd, unsigned char const *str)
{
unsigned int len1 = shell_cmd_len((unsigned char const *)cmd);
unsigned int len2 = shell_cmd_len(str);
if(len1 != len2)
{
return 1;
}
return memcmp(cmd, str, len1);
}
/**
*****************************************************************************
* \fn static unsigned int shell_read_line(int get(void), unsigned int len)
* \brief Shell reads command line.
* \note Enter ends, you can use the Backspace key to clear the input.
* \param[in] get Input interface function
* \param[in] p Receive buffer
* \param[in] len Length to be received
* return unsigned int Actual length received
****************************************************************************
*/
static unsigned int shell_read_line(int get(unsigned char* tmp))
{
unsigned char ch = '\r';
unsigned int count;
unsigned char tmp;
/*Start printing "sh>" once*/
if(cmd_buf[0]=='\r')
{
printf("sh>\r\n");
memset(cmd_buf,0x00,sizeof(cmd_buf));
}
/*If a character is received, go down, otherwise return*/
if(get(&tmp)==0)
{
ch = tmp;
}
else
{
return 0;
}
/*If a non-printing character is received and the current receive buffer is not 0, it is considered that a frame is received, otherwise print "SH>"*/
if((ch == '\r' || ch == '\n' || ch < ' ' || ch > '~') && (ch != '\b'))
{
if(cmd_buf_index==0)
{
printf("sh>\r\n");
}
else
{
count = cmd_buf_index;
cmd_buf[cmd_buf_index]=0;
cmd_buf_index =0;
printf("\r\n");
return count;
}
}
else
{
if(ch == '\b')
{
if(cmd_buf_index != 0)
{
cmd_buf_index--;
putchar('\b');
putchar(' ');
putchar('\b');
cmd_buf[cmd_buf_index]= '\0';
}
}
else
{
/*If a print character is received and the current receive buffer is full, it is considered that a frame has been received"*/
putchar(ch);
cmd_buf[cmd_buf_index++] = ch;
if(cmd_buf_index>=(sizeof(cmd_buf)-1))
{
count = cmd_buf_index;
cmd_buf[cmd_buf_index]=0;
cmd_buf_index =0;
printf("\r\n");
return count;
}
}
}
return 0;
}
/**
**************************************************************************
* \fn int shell_exec_cmdlist(unsigned char* cmd)
* \brief Search for command list and execute.
* retval 0 success
* retval -1 failure
* \note .
*****************************************************************************
*/
int shell_exec_cmdlist(unsigned char* cmd)
{
int i;
/*Platform related commands*/
for (i=0; shell_cmd_list.name != 0; i++)
{
if (shell_cmd_check(cmd, shell_cmd_list.name) == 0)
{
shell_cmd_list.func(cmd);
return 0;
}
}
// /*Application related commands*/
// for (i=0; shell_cmd_list_app.name != 0; i++)
// {
// if (shell_cmd_check(cmd, shell_cmd_list_app.name) == 0)
// {
// shell_cmd_list_app.func(cmd);
// return 0;
// }
// }
if(shell_cmd_list.name == NULL)
{
printf("unkown command\r\n");
return -1;
}
return 0;
}
/********************************************************************************
*
* External interface function implementation
*
****************************************************************************/
/**
*************************************************************************
* \fn void shell_exec_shellcmd(void)
* \brief Execute shell command.
* \note The task cycle calls this function.
*****************************************************************************
*/
void shell_exec_shellcmd(void)
{
if (!shellpassed)
{
shell_check_passwd();
shellpassed = 1;
}
if(shell_read_line(shell_getchar))
{
shell_exec_cmdlist(cmd_buf);
}
}
shell.h
/**
*****************************************************************************
* \brief Platform related (PLATFORM) SHELL module (SHELL) related data structure and interface description.
* \details
* All rights reserved.
* \file shell.h
* \author
* \version 1.0
* \date
* \note Please refer to the notes before use.\n
* \since Newly created
* \par Revision record
* - Initial version
* \par Resource description
* - RAM:
* - ROM:
**************************************************************************
*/
#ifndef _SHELL_H_
#define _SHELL_H_
#ifdef __cplusplus
extern "C" {
#endif
/** \addtogroup PLATFORM PLATFORM
* \{
*/
/** \addtogroup PLATFORM_SHELL PLATFORM_SHELL
* \{
*/
/*****************************************************************************
* *
* Data structure description *
* *
****************************************************************************/
/** \defgroup PLATFORM_SHELL_data PLATFORM_SHELL_data
* \{
*/
typedef void ( * CommandFunc )( void *); /**< shell command callback function*/
/**
* \struct shell_cmd_cfg
* SHELL command structure.
*/
typedef struct
{
unsigned char const* name; /**< shell command name*/
CommandFunc func; /**< shell command callback function*/
char const* helpstr; /**< help string*/
}shell_cmd_cfg;
#define SHELL_PASSWORD_STR "DSWYBS" /**< The shell password is fixed to 6 characters */
#define SHELL_CMDBUF_SIZE 64 /**< The shell command buffer size */
/**
* \}
*/
/*********************************************************************************
*
* Interface function description
*
*************************************************************************/
/** \defgroup PLATFORM_SHELL_if PLATFORM_SHELL_if
* \{
*/
/**
*************************************************************************
* \fn void shell_exec_shellcmd(void)
* \brief Execute shell command.
* \note The task cycle calls this function.
*****************************************************************************
*/
void shell_exec_shellcmd(void);
/**
*****************************************************************************
* \fn int shell_exec_cmdlist(unsigned char* cmd)
* \brief Search for command list and execute.
* retval 0 success
* retval -11 failure
* \note .
*****************************************************************************
*/
int shell_exec_cmdlist(unsigned char* cmd);
/**
* \}
*/
/**
* \}
*/
/**
* \}
*/
#ifdef __cplusplus
}
#endif
#endif
shell_func.c
/**
*****************************************************************************
* \brief Platform layer (PLATFORM) SHELL command module (SHELL_FUN) related interface implementation.
* \details
* All rights reserved.
* \file shell_fun.c
* \author
* \version 1.0
* \date
* \note Platform related commands.\n
* \since Newly created
* \par Revision record
* - Initial version
* \par Resource description
* - RAM:
* - ROM:
**************************************************************************
*/
#include <stdio.h>
#include <time.h>
#include <stdint.h>
#include <string.h>
#include <ctype.h>
#include "shell_fun.h"
#include "shell.h"
/********************************************************************************
*
* Internal data
*
****************************************************************************/
const shell_cmd_cfg shell_cmd_list[ ] =
{
/*1. Help related*/
{ (const uint8_t*)"help", HelpFun, "help"}, /*Print help information*/
{ 0, 0 },
};
/********************************************************************************
*
* Internal interface function implementation
*
****************************************************************************/
/********************************************************************************
*
* External interface function implementation
*
****************************************************************************/
/********************************************************************************
*
* Help related
*
****************************************************************************/
void HelpFun(void* param)
{
unsigned int i;
printf("\r\n");
printf("**************\r\n");
printf("* SHELL *\r\n");
printf("* V1.0 *\r\n");
printf("**************\r\n");
printf("\r\n");
for (i=0; shell_cmd_list.name != 0; i++)
{
printf("%02d.",i);
printf("%-16s",shell_cmd_list.name);
printf("%s\r\n",shell_cmd_list.helpstr);
}
}
shell_func.h
/**
*****************************************************************************
* \brief Platform layer (PLATFORM) SHELL command module (SHELL_FUN) related data structure and interface description.
* \details
* All rights reserved.
* \file shell_fun.h
* \author
* \version 1.0
* \date
* \note Platform related commands.\n
* \since Newly created
* \par Revision record
* -
* \par Resource description
* - RAM:
* - ROM:
**************************************************************************
*/
#ifndef __SHELL_FUN_H
#define __SHELL_FUN_H
#ifdef __cplusplus
extern "C" {
#endif
/*****************************************************************************
*
* 帮助相关
*
****************************************************************************/
void HelpFun(void* param);
void DeadTimeFun(void* param);
void DirFun(void* param);
void SpeedFun(void* param);
#ifdef __cplusplus
}
#endif
#endif
Summarize
The above implements a simple eSHELL command line, which can be used for interaction later.