1043 views|4 replies

501

Posts

4

Resources
The OP
 

[Renesas Electronics 200MHz Cortex-M33 RA6E2 Evaluation Board] Implementing streamlined shell command line interaction [Copy link]

Preface

Previously we implemented the serial port driver. Based on this, we further implemented the serial port command line to facilitate subsequent development and debugging.

Implementation ideas

Based on the previous serial port interface, the main loop continuously queries the serial port data, and writes the data into the command line cache.

Check that reading from the serial port is not blocked.

If a line of string is read, the table is passed to see if there is a command corresponding to the string. If so, the corresponding callback function is executed.

data structure

Table of string commands and corresponding functions

typedef struct

{

unsigned char const* name; 

CommandFunc func; 

char const* helpstr; 

}shell_cmd_cfg;

Implementing the interface

Read serial port

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;

}

send

Send can also implement putchar printf or redirect printf to implement

Redirect printf as follows

uart_ep.c

#include <stdio.h>

int fputc(int ch, FILE *f)

{

(void)f;

uart_sendbyte((uint8_t)ch);

return ch;

}

Read a line

static unsigned int shell_read_line(int get(unsigned char* tmp))

{

unsigned char ch = '\r';

unsigned int count;

unsigned char tmp;

/*??????"sh>"*/

if(cmd_buf[0]=='\r')

{

printf("sh>\r\n");

memset(cmd_buf,0x00,sizeof(cmd_buf));

}

/*??????????,????*/

if(get(&tmp)==0)

{

ch = tmp;

}

else

{

return 0;

}

/*????????????????????0????????????"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

{

/*??????????????????????????"*/

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;

}

test

In the main loop

for(;;)

{

shell_exec_shellcmd();

}

Use the host terminal assistant to connect, there is a command help by default

Type help and press Enter to view supported commands.

Code

shell.c

#include <stdio.h>
#include <string.h>
#include "shell.h"

extern uint32_t uart_read(uint8_t* buffer, uint32_t len);
extern uint32_t uart_write(uint8_t* buffer, uint32_t len);

#define SHELL_CMD_LEN 64                   
extern const shell_cmd_cfg shell_cmd_list[ ];   
static unsigned char cmd_buf[SHELL_CMD_LEN]="\r";
static unsigned int cmd_buf_index=0;  

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;
}

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;
}

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);
}

static unsigned int shell_read_line(int get(unsigned char* tmp))
{
    unsigned char ch = '\r';
    unsigned int count;
    unsigned char tmp;
    /*??????"sh>"*/
    if(cmd_buf[0]=='\r')
    {
        printf("sh>\r\n");
        memset(cmd_buf,0x00,sizeof(cmd_buf));
    }
    /*??????????,????*/
    if(get(&tmp)==0)
    {
        ch = tmp; 
    }
    else
    {
        return 0;
    }
    /*????????????????????0????????????"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 
        {
            /*??????????????????????????"*/
            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;
}


int shell_exec_cmdlist(unsigned char* cmd)
{
    int i;
    for (i=0; shell_cmd_list[i].name != 0; i++)
    {
        if (shell_cmd_check(cmd, shell_cmd_list[i].name) == 0) 
        {
            shell_cmd_list[i].func(cmd);
            return 0;
        }            
    } 
    if(shell_cmd_list[i].name == NULL)
    {
        printf("unkown command\r\n");
        return -1;
    }
    return 0;
}

void shell_exec_shellcmd(void)
{
    if(shell_read_line(shell_getchar))
    {
        shell_exec_cmdlist(cmd_buf);
    }
}

shell.h

#ifndef _SHELL_H_
#define _SHELL_H_

#ifdef __cplusplus
extern "C" {
#endif
     
#include <stdint.h>

typedef void ( * CommandFunc )( void *); 


typedef struct
{
    unsigned char const* name;       
    CommandFunc func;          
    char const* helpstr;      
}shell_cmd_cfg;

#define SHELL_CMDBUF_SIZE  64         


void shell_exec_shellcmd(void);

int shell_exec_cmdlist(unsigned char* cmd);


#ifdef __cplusplus
}
#endif

#endif

shell_func.c

#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include "shell_func.h"
#include "shell.h"

const shell_cmd_cfg shell_cmd_list[ ] = 
{
  { (const uint8_t*)"help",         HelpFun,         "help"},             
  { (const uint8_t*)0,		0 , 0},
};

void HelpFun(void* param)
{
	  (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[i].name != 0; i++)
    {
        printf("%02d.",i);
        printf("%-16s",shell_cmd_list[i].name);
        printf("%s\r\n",shell_cmd_list[i].helpstr);
    }
}

shell_func.h

#ifndef __SHELL_FUN_H
#define __SHELL_FUN_H

#include <stdint.h>

#ifdef __cplusplus
 extern "C" {
#endif
 
void HelpFun(void* param);


#ifdef __cplusplus
}
#endif

#endif

Summarize

The above implements a simple command line, which facilitates subsequent development and testing.

This post is from Renesas Electronics MCUs

Latest reply

Very good, I will implement it when I have time, thank you for sharing  Details Published on 2023-12-4 16:47

6827

Posts

11

Resources
2
 
Implement your own shell. If you want to be excellent, you can try rtt. In this way, you can install it on the system and have a shell, which is even better!
This post is from Renesas Electronics MCUs
 
 

6748

Posts

2

Resources
3
 

How to implement it yourself? What if you want to turn a function into a command?

This post is from Renesas Electronics MCUs

Comments

You can refer to the next article, statically add a line (string, function name) to the array [Renesas Electronics 200MHz Cortex-M33 RA6E2 Evaluation Board] PWM Test - Implementing Command Line Control of PWM Signal Source - Renesas Electronics MCU - Electronic Engineering World - Forum (eeworld.com.cn)  Details Published on 2023-10-19 20:05
 
 
 

501

Posts

4

Resources
4
 
wangerxian posted on 2023-10-19 18:15 Do you implement it yourself? What if you want to turn a function into a command?

Please refer to the next article.

Just add a line (string, function name) to the array statically

[Renesas 200MHz Cortex-M33 RA6E2 Evaluation Board] PWM Test - Implementing Command Line Controlled PWM Signal Source - Renesas MCU - Electronic Engineering World - Forum (eeworld.com.cn)

This post is from Renesas Electronics MCUs
 
 
 

224

Posts

0

Resources
5
 

Very good, I will implement it when I have time, thank you for sharing


This post is from Renesas Electronics MCUs
 
 
 

Just looking around
Find a datasheet?

EEWorld Datasheet Technical Support

EEWorld
subscription
account

EEWorld
service
account

Automotive
development
circle

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号
快速回复 返回顶部 Return list