nr_micro_shell是一个开源的shell工具。使用简单,移植也容易。和它类似的有letter-shell和RTTHREAD的finsh shell。
下面简单介绍下如何移植nr_micro_shell吧。
移植之前首先要搞定串口通信。
串口初始化如下,本次使用中断加fifo缓存接收方式。
void drv_usart_gpio_init(void)
{
usart_config_t USART_InitStructure;
/* Enables clock for switch matrix.: enable */
CLOCK_EnableClock(kCLOCK_Swm);
const uint32_t DEBUG_UART_RX = (/* Selects pull-up function */
IOCON_PIO_MODE_PULLUP |
/* Enable hysteresis */
IOCON_PIO_HYS_EN |
/* Input not invert */
IOCON_PIO_INV_DI |
/* Disables Open-drain function */
IOCON_PIO_OD_DI |
/* Bypass input filter */
IOCON_PIO_SMODE_BYPASS |
/* IOCONCLKDIV0 */
IOCON_PIO_CLKDIV0);
/* PIO1 PIN16 (coords: 36) is configured as USART0, RXD. */
IOCON_PinMuxSet(IOCON, IOCON_INDEX_PIO0_24, DEBUG_UART_RX);
const uint32_t DEBUG_UART_TX = (/* Selects pull-up function */
IOCON_PIO_MODE_PULLUP |
/* Enable hysteresis */
IOCON_PIO_HYS_EN |
/* Input not invert */
IOCON_PIO_INV_DI |
/* Disables Open-drain function */
IOCON_PIO_OD_DI |
/* Bypass input filter */
IOCON_PIO_SMODE_BYPASS |
/* IOCONCLKDIV0 */
IOCON_PIO_CLKDIV0);
/* PIO1 PIN17 (coords: 37) is configured as USART0, TXD. */
IOCON_PinMuxSet(IOCON, IOCON_INDEX_PIO0_25, DEBUG_UART_TX);
/* USART0_TXD connect to P0_25 */
SWM_SetMovablePinSelect(SWM0, kSWM_USART0_TXD, kSWM_PortPin_P0_25);
/* USART0_RXD connect to P0_24 */
SWM_SetMovablePinSelect(SWM0, kSWM_USART0_RXD, kSWM_PortPin_P0_24);
/* Disable clock for switch matrix. */
CLOCK_DisableClock(kCLOCK_Swm);CLOCK_Select(kUART0_Clk_From_MainClk);
RESET_PeripheralReset(kUART0_RST_N_SHIFT_RSTn);
USART_GetDefaultConfig(&USART_InitStructure);
USART_InitStructure.baudRate_Bps = 115200;
USART_InitStructure.enableRx = 1U;
USART_InitStructure.enableTx = 1U;
USART_Init(USART0, &USART_InitStructure, CLOCK_GetMainClkFreq());
//使能UARTx RC中断
USART_EnableInterrupts(USART0, kUSART_RxReadyInterruptEnable);
//优先级,无优先级分组
NVIC_SetPriority(USART0_IRQn, 0);
//UARTx中断使能
NVIC_EnableIRQ(USART0_IRQn);
}
串口发送:
int stdout_putchar (int ch)
{
while (0 == (USART_GetStatusFlags(USART0) & USART_STAT_TXRDY_MASK));
USART_WriteByte(USART0, (uint8_t)ch);
return ch;
}
int fputc(int ch,FILE *f)
{
return stdout_putchar(ch);
}
中断fifo接收:
typedef struct fifo_buffer
{
volatile uint32_t read_i;
volatile uint32_t write_i;
uint8_t buff[128];
}fifo_buffer;
fifo_buffer shell_uart_rx=
{
.read_i = 0,
.write_i = 0,
};
void USART0_IRQHandler(void)
{
uint32_t statusFlag;
uint32_t ch;
statusFlag = USART0->STAT;
// if((statusFlag & USART_STAT_OVERRUNINT_MASK) != 0)
// {
// ch =ch;
// }
if((statusFlag & USART_STAT_RXRDY_MASK) != 0)
{
ch = USART_ReadByte(USART0);
if(((shell_uart_rx.write_i+1)&0x7f) != shell_uart_rx.read_i)
{
shell_uart_rx.buff[shell_uart_rx.write_i++] = ch & 0xff;
shell_uart_rx.write_i &= 0x7f;
}
}
USART0->STAT |= statusFlag;
}
下面就是移植nr_micro_shell代码了。首先去nr_micro_shell仓库下载代码:https://gitee.com/nrush/nr_micro_shell 。
将代码文件加入到工程中。
移植主要是在nr_micro_shell_config.h配置。配置串口字节输出和printf格式化输出。
/* ANSI command line buffer size. */
#define NR_ANSI_LINE_SIZE 256
/* Maximum user name length. */
#define NR_SHELL_USER_NAME_MAX_LENGTH 16
/* Maximum command name length. */
#define NR_SHELL_CMD_NAME_MAX_LENGTH 16
/* Command line buffer size. */
#define NR_SHELL_CMD_LINE_MAX_LENGTH NR_ANSI_LINE_SIZE
/* The maximum number of parameters in the command. */
#define NR_SHELL_CMD_PARAS_MAX_NUM 10
/* Command stores the most history commands (the maximum number here refers to the maximum number of commands that can be stored. When the history command line cache is full, it will automatically release the earliest command record) */
#define NR_SHELL_MAX_CMD_HISTORY_NUM 8
/* History command cache length */
#define NR_SHELL_CMD_HISTORY_BUF_LENGTH 253
/* The user's name. */
#define NR_SHELL_USER_NAME "root:"
/*
0: n
1: r
2: rn
*/
#define NR_SHELL_END_OF_LINE 1
/* Weather the terminal support all ANSI codes. */
#define NR_SHLL_FULL_ANSI 1
/* Show logo or not. */
#define NR_SHELL_SHOW_LOG
// /* Use NR_SHELL_CMD_EXPORT() or not */
#define NR_SHELL_USING_EXPORT_CMD
/* If you use RTOS, you may need to do some special processing for printf(). */
extern int stdout_putchar (int ch) ;
#define shell_printf(fmt, args...) printf(fmt, ##args);
#define ansi_show_char(x) stdout_putchar(x)
然后在main中调用初始化shell以及从串口中读取输入数据进行解析。
void shell_usart_loop(void)
{
if(shell_uart_rx.read_i != shell_uart_rx.write_i)
{
shell(shell_uart_rx.buff[shell_uart_rx.read_i++]);
shell_uart_rx.read_i &= 0x7f;
}
}
编译下载后就可以通过串口来控制了。nr_micro_shell默认有ls和test命令例子。