更新: 新增类似linux的重定向符号,支持xcmd_print到文件
This commit is contained in:
parent
840076a741
commit
c23f3288e9
55
README.md
55
README.md
|
@ -1,40 +1,53 @@
|
||||||
# xcmd
|
# xcmd
|
||||||
|
|
||||||
#### 效果展示
|
#### 效果展示
|
||||||
|
|
||||||
![输入图片说明](https://images.gitee.com/uploads/images/2021/0922/220957_66faa768_1680380.gif "演示1.gif")
|
![输入图片说明](https://images.gitee.com/uploads/images/2021/0922/220957_66faa768_1680380.gif "演示1.gif")
|
||||||
|
|
||||||
#### 介绍
|
#### 介绍
|
||||||
|
|
||||||
xcmd是一款单片机命令行工具,移植十分方便,并且对flash与ram占用很小,旨在为单片机提供一个能够快速搭建且占用资源很小的命令行工具,可以大大加快单片机程序调试工作,它有一下几个优点。
|
xcmd是一款单片机命令行工具,移植十分方便,并且对flash与ram占用很小,旨在为单片机提供一个能够快速搭建且占用资源很小的命令行工具,可以大大加快单片机程序调试工作,它有一下几个优点。
|
||||||
|
|
||||||
1. **移植十分简单**
|
1. **移植十分简单**
|
||||||
2. **资源占用约8K rom 1K ram**
|
2. **资源占用很小**
|
||||||
3. **支持历史记录**
|
3. **支持历史记录**
|
||||||
4. **支持命令自动补全**
|
4. **支持命令自动补全**
|
||||||
5. **支持注册快捷键**
|
5. **支持注册快捷键**
|
||||||
5. **支持`xcmd_cmd_register()/xcmd_key_register`方法注册命令或按键**
|
6. **支持 `xcmd_cmd_register()/xcmd_key_register`方法注册命令或按键**
|
||||||
5. **支持`XCMD_EXPORT_CMD()/XCMD_EXPORT_KEY()`方法直接导出命令或按键,不需要额外运行注册函数**
|
7. **支持 `XCMD_EXPORT_CMD()/XCMD_EXPORT_KEY()`方法直接导出命令或按键,不需要额外运行注册函数**
|
||||||
|
|
||||||
#### 支持的平台
|
#### 支持的平台
|
||||||
|
|
||||||
1. linux
|
1. linux
|
||||||
2. arduino
|
2. arduino
|
||||||
3. stm32
|
3. stm32
|
||||||
4. esp32
|
4. esp32
|
||||||
5. qemu-stm32
|
5. qemu-stm32
|
||||||
|
|
||||||
#### 测试过的串口软件
|
#### 测试过的串口软件
|
||||||
|
|
||||||
2. (win/linux推荐)putty
|
2. (win/linux推荐)putty
|
||||||
3. (win推荐)MobaXterm
|
3. (win推荐)MobaXterm
|
||||||
5. (linux端推荐)cu
|
4. (linux端推荐)cu
|
||||||
1. SecureCRT:请设置成Xterm模式
|
5. SecureCRT:请设置成Xterm模式
|
||||||
4. Xshell
|
6. Xshell
|
||||||
6. nc(支持性很差)
|
7. nc(支持性很差)
|
||||||
7. minicom(支持性很差)
|
8. minicom(支持性很差)
|
||||||
|
|
||||||
#### 支持的扩展功能
|
#### 支持的扩展功能
|
||||||
|
|
||||||
1. 类linux风格的快捷键:ctr+left、ctr+right、ctr+a、ctr+e、ctr+u、ctr+k、ctr+l快捷键
|
1. 类linux风格的快捷键:ctr+left、ctr+right、ctr+a、ctr+e、ctr+u、ctr+k、ctr+l快捷键
|
||||||
2. 支持字体、背景颜色显示
|
2. 支持字体、背景颜色显示
|
||||||
3. 支持类linux的文件操作(Fatfs文件系统):ls、cd、rm、df、mv、mkdir、touch、read、write
|
3. 支持类linux的文件操作(Fatfs文件系统):ls、cd、rm、df、mv、mkdir、touch、rd、wr、cat
|
||||||
4. 支持基于socket的udp server、udp client测试程序
|
4. 支持基于socket的udp server、udp client测试程序
|
||||||
|
|
||||||
#### 移植
|
#### 移植
|
||||||
|
|
||||||
- 移植十分简单,可在example中查看各平台移植结果
|
- 移植十分简单,可在example中查看各平台移植结果
|
||||||
|
|
||||||
1. 在初始化的时候提供字符输入输出函数即可
|
1. 在初始化的时候提供字符输入输出函数即可
|
||||||
2. 从example中拷贝一个xcmd_confg.h到自己的项目
|
2. 从example中拷贝一个xcmd_confg.h到自己的项目
|
||||||
|
|
||||||
```C
|
```C
|
||||||
/* 例如移植到Arduino平台 */
|
/* 例如移植到Arduino平台 */
|
||||||
int cmd_get_char(uint8_t *ch)
|
int cmd_get_char(uint8_t *ch)
|
||||||
|
@ -62,14 +75,17 @@ void setup() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void loop() {
|
void loop() {
|
||||||
|
|
||||||
xcmd_task();
|
xcmd_task();
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
#### 配置
|
#### 配置
|
||||||
|
|
||||||
配置xcmd_config.h
|
配置xcmd_config.h
|
||||||
|
|
||||||
**注意**: 如果不知道如何修改连接脚本,建议不要使能ENABLE_XCMD_EXPORT。不使能ENABLE_XCMD_EXPORT的情况下有更好的兼容性移植更加简单
|
**注意**: 如果不知道如何修改连接脚本,建议不要使能ENABLE_XCMD_EXPORT。不使能ENABLE_XCMD_EXPORT的情况下有更好的兼容性移植更加简单
|
||||||
|
|
||||||
```C
|
```C
|
||||||
#define XCMD_LINE_MAX_LENGTH (128) /* 命令行支持的最大字符数 */
|
#define XCMD_LINE_MAX_LENGTH (128) /* 命令行支持的最大字符数 */
|
||||||
#define XCMD_HISTORY_MAX_NUM (16) /* 支持的历史记录个数, 这个参数对内存的影响很大,建议arduino设置为0,0为不支持 */
|
#define XCMD_HISTORY_MAX_NUM (16) /* 支持的历史记录个数, 这个参数对内存的影响很大,建议arduino设置为0,0为不支持 */
|
||||||
|
@ -78,8 +94,11 @@ void loop() {
|
||||||
// #define XCMD_DEFAULT_PROMPT_CLOLR TX_GREEN /* 提示符颜色 */
|
// #define XCMD_DEFAULT_PROMPT_CLOLR TX_GREEN /* 提示符颜色 */
|
||||||
// #define ENABLE_XCMD_EXPORT /* 需要修改lds,启用后支持XCMD_EXPORT_CMD和XCMD_EXPORT_KEY方法导出命令 */
|
// #define ENABLE_XCMD_EXPORT /* 需要修改lds,启用后支持XCMD_EXPORT_CMD和XCMD_EXPORT_KEY方法导出命令 */
|
||||||
```
|
```
|
||||||
|
|
||||||
#### 使用说明
|
#### 使用说明
|
||||||
|
|
||||||
##### xcmd_register()方法注册自定义命令
|
##### xcmd_register()方法注册自定义命令
|
||||||
|
|
||||||
```C
|
```C
|
||||||
static int cmd_echo(int argc, char* argv[])
|
static int cmd_echo(int argc, char* argv[])
|
||||||
{
|
{
|
||||||
|
@ -100,7 +119,9 @@ void test_cmd_init(void)
|
||||||
xcmd_cmd_register(cmds, sizeof(cmds)/sizeof(xcmd_t));
|
xcmd_cmd_register(cmds, sizeof(cmds)/sizeof(xcmd_t));
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
##### xcmd_key_register() 方法注册自定义快捷键
|
##### xcmd_key_register() 方法注册自定义快捷键
|
||||||
|
|
||||||
```C
|
```C
|
||||||
int cmd_ctr_a(void* pv)
|
int cmd_ctr_a(void* pv)
|
||||||
{
|
{
|
||||||
|
@ -117,7 +138,9 @@ void test_keys_init(void)
|
||||||
xcmd_key_register(user_keys, sizeof(user_keys)/sizeof(xcmd_key_t));
|
xcmd_key_register(user_keys, sizeof(user_keys)/sizeof(xcmd_key_t));
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
##### XCMD_EXPORT_CMD()方法注册自定义命令,需要使能宏ENABLE_XCMD_EXPORT并修改lds,见`example/stm32/qemu/demos/main.ld`
|
|
||||||
|
##### XCMD_EXPORT_CMD()方法注册自定义命令,需要使能宏ENABLE_XCMD_EXPORT并修改lds,见 `example/stm32/qemu/demos/main.ld`
|
||||||
|
|
||||||
```C
|
```C
|
||||||
static int cmd_echo(int argc, char* argv[])
|
static int cmd_echo(int argc, char* argv[])
|
||||||
{
|
{
|
||||||
|
@ -129,7 +152,9 @@ static int cmd_echo(int argc, char* argv[])
|
||||||
}
|
}
|
||||||
XCMD_EXPORT_CMD(echo, cmd_echo, "print anything")
|
XCMD_EXPORT_CMD(echo, cmd_echo, "print anything")
|
||||||
```
|
```
|
||||||
##### XCMD_EXPORT_KEY() 方法注册自定义快捷键, 需要使能宏ENABLE_XCMD_EXPORT并修改lds,见`example/stm32/qemu/demos/main.ld`
|
|
||||||
|
##### XCMD_EXPORT_KEY() 方法注册自定义快捷键, 需要使能宏ENABLE_XCMD_EXPORT并修改lds,见 `example/stm32/qemu/demos/main.ld`
|
||||||
|
|
||||||
```C
|
```C
|
||||||
int cmd_ctr_a(void* pv)
|
int cmd_ctr_a(void* pv)
|
||||||
{
|
{
|
||||||
|
@ -137,5 +162,7 @@ int cmd_ctr_a(void* pv)
|
||||||
}
|
}
|
||||||
XCMD_EXPORT_KEY(KEY_CTR_A, cmd_ctr_a, "ctr+a")
|
XCMD_EXPORT_KEY(KEY_CTR_A, cmd_ctr_a, "ctr+a")
|
||||||
```
|
```
|
||||||
|
|
||||||
#### 其他
|
#### 其他
|
||||||
|
|
||||||
流程图需要使用drawio来打开,可以使用vscode drawio的插件来打开
|
流程图需要使用drawio来打开,可以使用vscode drawio的插件来打开
|
||||||
|
|
|
@ -170,8 +170,8 @@
|
||||||
/* Number of volumes (logical drives) to be used. (1-10) */
|
/* Number of volumes (logical drives) to be used. (1-10) */
|
||||||
|
|
||||||
|
|
||||||
#define FF_STR_VOLUME_ID 0
|
#define FF_STR_VOLUME_ID 1
|
||||||
#define FF_VOLUME_STRS "RAM","NAND","CF","SD","SD2","USB","USB2","USB3"
|
// #define FF_VOLUME_STRS "RAM","NAND" //,"CF","SD","SD2","USB","USB2","USB3"
|
||||||
/* FF_STR_VOLUME_ID switches support for volume ID in arbitrary strings.
|
/* FF_STR_VOLUME_ID switches support for volume ID in arbitrary strings.
|
||||||
/ When FF_STR_VOLUME_ID is set to 1 or 2, arbitrary strings can be used as drive
|
/ When FF_STR_VOLUME_ID is set to 1 or 2, arbitrary strings can be used as drive
|
||||||
/ number in the path name. FF_VOLUME_STRS defines the volume ID strings for each
|
/ number in the path name. FF_VOLUME_STRS defines the volume ID strings for each
|
||||||
|
@ -194,7 +194,7 @@
|
||||||
|
|
||||||
|
|
||||||
#define FF_MIN_SS 512
|
#define FF_MIN_SS 512
|
||||||
#define FF_MAX_SS 512
|
#define FF_MAX_SS 4096
|
||||||
/* This set of options configures the range of sector size to be supported. (512,
|
/* This set of options configures the range of sector size to be supported. (512,
|
||||||
/ 1024, 2048 or 4096) Always set both 512 for most systems, generic memory card and
|
/ 1024, 2048 or 4096) Always set both 512 for most systems, generic memory card and
|
||||||
/ harddisk, but a larger value may be required for on-board flash memory and some
|
/ harddisk, but a larger value may be required for on-board flash memory and some
|
||||||
|
|
|
@ -11,21 +11,29 @@
|
||||||
|
|
||||||
static DiskIo_t * g_Disks[FF_VOLUMES] = {0};
|
static DiskIo_t * g_Disks[FF_VOLUMES] = {0};
|
||||||
|
|
||||||
int f_disk_regist(DiskIo_t * disk, int id)
|
#if FF_STR_VOLUME_ID >= 1
|
||||||
|
#ifndef FF_VOLUME_STRS
|
||||||
|
const char* VolumeStr[FF_VOLUMES] = {0};
|
||||||
|
#else
|
||||||
|
static char * VolumeStr[FF_VOLUMES] = {FF_VOLUME_STRS};
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int f_disk_regist(DiskIo_t * disk, const char* volume_name, int id)
|
||||||
{
|
{
|
||||||
if(!disk)
|
if(!disk || !volume_name)
|
||||||
{
|
{
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(id<0)
|
if(id<0)
|
||||||
{
|
{
|
||||||
for(int i=0; i<FF_VOLUMES; i++)
|
for(int i=0; i<FF_VOLUMES; i++)
|
||||||
{
|
{
|
||||||
if(!g_Disks[id])
|
if(!g_Disks[i])
|
||||||
{
|
{
|
||||||
g_Disks[i] = disk;
|
g_Disks[i] = disk;
|
||||||
return i;
|
id = i;
|
||||||
|
goto ok;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -34,10 +42,39 @@ int f_disk_regist(DiskIo_t * disk, int id)
|
||||||
if((id < FF_VOLUMES) && !g_Disks[id])
|
if((id < FF_VOLUMES) && !g_Disks[id])
|
||||||
{
|
{
|
||||||
g_Disks[id] = disk;
|
g_Disks[id] = disk;
|
||||||
return id;
|
goto ok;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
ok:
|
||||||
|
#if FF_STR_VOLUME_ID >= 1
|
||||||
|
|
||||||
|
#ifndef FF_VOLUME_STRS
|
||||||
|
|
||||||
|
#if FF_STR_VOLUME_ID == 1
|
||||||
|
snprintf(disk->disk_path, MAX_VOL_NAME_LEN, "%s:", volume_name);
|
||||||
|
#endif
|
||||||
|
#if FF_STR_VOLUME_ID == 2
|
||||||
|
snprintf(disk->disk_path, MAX_VOL_NAME_LEN, "/%s/", volume_name);
|
||||||
|
#endif
|
||||||
|
VolumeStr[id] = volume_name;
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#if FF_STR_VOLUME_ID == 1
|
||||||
|
snprintf(disk->disk_path, MAX_VOL_NAME_LEN, "%s:", VolumeStr[id]);
|
||||||
|
#endif
|
||||||
|
#if FF_STR_VOLUME_ID == 2
|
||||||
|
snprintf(disk->disk_path, MAX_VOL_NAME_LEN, "/%s/", VolumeStr[id]);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#else
|
||||||
|
snprintf(disk->disk_path, MAX_VOL_NAME_LEN, "%d:", id);
|
||||||
|
#endif
|
||||||
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
DiskIo_t * f_disk_get(int id)
|
DiskIo_t * f_disk_get(int id)
|
||||||
|
@ -48,3 +85,12 @@ DiskIo_t * f_disk_get(int id)
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char * f_disk_path(int id)
|
||||||
|
{
|
||||||
|
if(id < FF_VOLUMES)
|
||||||
|
{
|
||||||
|
return g_Disks[id]->disk_path;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
|
@ -14,9 +14,11 @@
|
||||||
#include "diskio.h"
|
#include "diskio.h"
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#define MAX_VOL_NAME_LEN (16)
|
||||||
|
|
||||||
typedef struct __DiskIo
|
typedef struct __DiskIo
|
||||||
{
|
{
|
||||||
char * disk_name;
|
char disk_path[MAX_VOL_NAME_LEN];
|
||||||
DSTATUS (*disk_status)(void);
|
DSTATUS (*disk_status)(void);
|
||||||
DSTATUS (*disk_initialize)(void);
|
DSTATUS (*disk_initialize)(void);
|
||||||
DRESULT (*disk_read)(BYTE *buff, LBA_t sector, UINT count);
|
DRESULT (*disk_read)(BYTE *buff, LBA_t sector, UINT count);
|
||||||
|
@ -24,7 +26,7 @@ typedef struct __DiskIo
|
||||||
DRESULT (*disk_ioctl) (BYTE cmd, void *buff);
|
DRESULT (*disk_ioctl) (BYTE cmd, void *buff);
|
||||||
}DiskIo_t;
|
}DiskIo_t;
|
||||||
|
|
||||||
int f_disk_regist(DiskIo_t * disk, int id);
|
int f_disk_regist(DiskIo_t * disk, const char* volume_name, int id);
|
||||||
DiskIo_t * f_disk_get(int id);
|
DiskIo_t * f_disk_get(int id);
|
||||||
|
char * f_disk_path(int id);
|
||||||
#endif
|
#endif
|
|
@ -9,6 +9,7 @@
|
||||||
#include "fs_cmds.h"
|
#include "fs_cmds.h"
|
||||||
#include "xcmd.h"
|
#include "xcmd.h"
|
||||||
#include "ff.h"
|
#include "ff.h"
|
||||||
|
#include "fatfs_port.h"
|
||||||
|
|
||||||
#define RESAULT_TO_STR(r) resault_to_str_map[r]
|
#define RESAULT_TO_STR(r) resault_to_str_map[r]
|
||||||
static char *resault_to_str_map[] =
|
static char *resault_to_str_map[] =
|
||||||
|
@ -41,13 +42,13 @@ static FILINFO fno;
|
||||||
#define HELP_DF ("Show Disk Info. Usage: df")
|
#define HELP_DF ("Show Disk Info. Usage: df")
|
||||||
#define HELP_LS ("List information about the FILEs. Usage: ls")
|
#define HELP_LS ("List information about the FILEs. Usage: ls")
|
||||||
#define HELP_CD ("Change the shell working directory. Usage: cd path")
|
#define HELP_CD ("Change the shell working directory. Usage: cd path")
|
||||||
#define HELP_READ ("Read FILE. Usage: read path")
|
#define HELP_CAT ("Read FILE. Usage: cat path")
|
||||||
#define HELP_RM ("Delete FILE. Usage: rm [-r:dir] path")
|
#define HELP_RM ("Delete FILE. Usage: rm [-r:dir] path")
|
||||||
#define HELP_MV ("Move FILE. Usage: mv path")
|
#define HELP_MV ("Move FILE. Usage: mv path")
|
||||||
#define HELP_SYNC ("Sync Usage: sync")
|
#define HELP_SYNC ("Sync Usage: sync")
|
||||||
#define HELP_MKDIR ("Make DIR. Usage: mkdir path")
|
#define HELP_MKDIR ("Make DIR. Usage: mkdir path")
|
||||||
#define HELP_TOUCH ("Create empty FILE. Usage: touch path")
|
#define HELP_TOUCH ("Create empty FILE. Usage: touch path")
|
||||||
#define HELP_WRITE ("Write str to FILE. Usage: Write [-a:append] path str")
|
#define HELP_WRITE ("Write str to FILE. Usage: wr string (>|>>) filename")
|
||||||
|
|
||||||
static FRESULT scan_files(
|
static FRESULT scan_files(
|
||||||
char *path /* Start node to be scanned (***also used as work area***) */
|
char *path /* Start node to be scanned (***also used as work area***) */
|
||||||
|
@ -152,9 +153,10 @@ static FRESULT df(char* path, DWORD* totle_byte, DWORD* free_byte)
|
||||||
#if FF_MAX_SS != FF_MIN_SS
|
#if FF_MAX_SS != FF_MIN_SS
|
||||||
*totle_byte = tot_sect * fs->ssize;
|
*totle_byte = tot_sect * fs->ssize;
|
||||||
*free_byte = fre_sect * fs->ssize;
|
*free_byte = fre_sect * fs->ssize;
|
||||||
#endif
|
#else
|
||||||
*totle_byte = tot_sect * FF_MAX_SS;
|
*totle_byte = tot_sect * FF_MAX_SS;
|
||||||
*free_byte = fre_sect * FF_MAX_SS;
|
*free_byte = fre_sect * FF_MAX_SS;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
@ -163,21 +165,23 @@ static int cmd_df(int argc, char* argv[])
|
||||||
{
|
{
|
||||||
FRESULT res;
|
FRESULT res;
|
||||||
DWORD fre_bytes, tot_bytes;
|
DWORD fre_bytes, tot_bytes;
|
||||||
res = df("0:", &tot_bytes, &fre_bytes);
|
char * disk_path;
|
||||||
if (res != FR_OK)
|
for(int i=0; i<FF_VOLUMES; i++)
|
||||||
{
|
{
|
||||||
xcmd_print("0: Failure:%s\r\n", RESAULT_TO_STR(res));
|
disk_path = f_disk_path(i);
|
||||||
return -1;
|
if(disk_path)
|
||||||
|
{
|
||||||
|
res = df(disk_path, &tot_bytes, &fre_bytes);
|
||||||
|
if (res != FR_OK)
|
||||||
|
{
|
||||||
|
xcmd_print("%s Failure:%s\r\n", disk_path, RESAULT_TO_STR(res));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
xcmd_print("%s %lu/%lu KiB.\r\n", disk_path, fre_bytes/1024, tot_bytes / 1024);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
xcmd_print("0:/ %lu/%lu KiB.\r\n", fre_bytes/1024, tot_bytes / 1024);
|
|
||||||
|
|
||||||
res = df("1:", &tot_bytes, &fre_bytes);
|
|
||||||
if (res != FR_OK)
|
|
||||||
{
|
|
||||||
xcmd_print("1: Failure:%s\r\n", RESAULT_TO_STR(res));
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
xcmd_print("1:/ %lu/%lu KiB.\r\n", fre_bytes/1024, tot_bytes / 1024);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -220,50 +224,6 @@ static int cmd_cd(int argc, char *argv[])
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int cmd_read(int argc, char *argv[])
|
|
||||||
{
|
|
||||||
if (argc >= 2)
|
|
||||||
{
|
|
||||||
FRESULT res;
|
|
||||||
res = f_open(&fp, argv[1], FA_READ);
|
|
||||||
if (res != FR_OK)
|
|
||||||
{
|
|
||||||
xcmd_print("Failure:%s\r\n", RESAULT_TO_STR(res));
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
char buf[128];
|
|
||||||
UINT br;
|
|
||||||
while (1)
|
|
||||||
{
|
|
||||||
res = f_read(&fp, buf, 128, &br);
|
|
||||||
if (res != FR_OK)
|
|
||||||
{
|
|
||||||
xcmd_print("Failure:%s\r\n", RESAULT_TO_STR(res));
|
|
||||||
f_close(&fp);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (br == 0)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
for(UINT i=0; i<br; i++)
|
|
||||||
{
|
|
||||||
xcmd_print("%c", buf[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
xcmd_print("%s\r\n", HELP_READ);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
f_close(&fp);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int cmd_rm(int argc, char *argv[])
|
static int cmd_rm(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
FRESULT res;
|
FRESULT res;
|
||||||
|
@ -385,70 +345,125 @@ static int cmd_touch(int argc, char *argv[])
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int cmd_write(int argc, char *argv[])
|
static int cmd_cat(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
uint8_t append_flag = 0;
|
if (argc >= 2)
|
||||||
uint8_t param_num = 3;
|
|
||||||
/* 查找可选参数 */
|
|
||||||
if (strcmp(argv[1], "-a") == 0)
|
|
||||||
{
|
{
|
||||||
append_flag = 1;
|
FRESULT res;
|
||||||
param_num = 4;
|
res = f_open(&fp, argv[1], FA_READ);
|
||||||
}
|
|
||||||
|
|
||||||
FRESULT res = FR_INVALID_PARAMETER;
|
|
||||||
char *str = NULL;
|
|
||||||
if (argc >= param_num)
|
|
||||||
{
|
|
||||||
if (append_flag)
|
|
||||||
{
|
|
||||||
res = f_open(&fp, argv[2], FA_WRITE | FA_OPEN_APPEND);
|
|
||||||
str = argv[3];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
res = f_open(&fp, argv[1], FA_WRITE | FA_CREATE_ALWAYS);
|
|
||||||
str = argv[2];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (res != FR_OK)
|
if (res != FR_OK)
|
||||||
{
|
{
|
||||||
xcmd_print("Failure:%s", RESAULT_TO_STR(res));
|
xcmd_print("Failure:%s\r\n", RESAULT_TO_STR(res));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
char buf[128];
|
||||||
UINT br;
|
UINT br;
|
||||||
res = f_write(&fp, str, strlen(str), &br);
|
while (1)
|
||||||
res = f_write(&fp, "\n", 1, &br);
|
|
||||||
f_close(&fp);
|
|
||||||
if (res != FR_OK)
|
|
||||||
{
|
{
|
||||||
xcmd_print("Failure:%s", RESAULT_TO_STR(res));
|
res = f_read(&fp, buf, 128, &br);
|
||||||
return -1;
|
if (res != FR_OK)
|
||||||
|
{
|
||||||
|
xcmd_print("Failure:%s\r\n", RESAULT_TO_STR(res));
|
||||||
|
f_close(&fp);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (br == 0)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
for(UINT i=0; i<br; i++)
|
||||||
|
{
|
||||||
|
xcmd_print("%c", buf[i]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
xcmd_print("%s\r\n", HELP_WRITE);
|
xcmd_print("%s\r\n", HELP_CAT);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
f_close(&fp);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ssize_t file_open(char *name, int is_write, int is_append)
|
||||||
|
{
|
||||||
|
FRESULT res;
|
||||||
|
BYTE mode = 0;
|
||||||
|
if(is_write)
|
||||||
|
{
|
||||||
|
if (is_append)
|
||||||
|
{
|
||||||
|
mode = FA_WRITE | FA_OPEN_APPEND;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mode = FA_WRITE | FA_CREATE_ALWAYS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mode = FA_READ;
|
||||||
|
}
|
||||||
|
res = f_open(&fp, name, mode);
|
||||||
|
if (res != FR_OK)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return (ssize_t)&fp;
|
||||||
|
}
|
||||||
|
|
||||||
|
void file_close(ssize_t fd)
|
||||||
|
{
|
||||||
|
if(fd != -1)
|
||||||
|
f_close((FIL*)fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
int file_read(ssize_t fd, char *buf, int buflen)
|
||||||
|
{
|
||||||
|
FRESULT res;
|
||||||
|
UINT br;
|
||||||
|
if(fd != -1)
|
||||||
|
{
|
||||||
|
res = f_read((FIL*)fd, buf, buflen, &br);
|
||||||
|
if (res != FR_OK)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int file_write(ssize_t fd, const char *str)
|
||||||
|
{
|
||||||
|
|
||||||
|
FRESULT res = FR_INVALID_PARAMETER;
|
||||||
|
if(fd != -1)
|
||||||
|
{
|
||||||
|
UINT br;
|
||||||
|
res = f_write((FIL*)fd, str, strlen(str), &br);
|
||||||
|
if (res != FR_OK)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
XCMD_EXPORT_CMD(ls, cmd_ls, HELP_LS)
|
XCMD_EXPORT_CMD(ls, cmd_ls, HELP_LS)
|
||||||
XCMD_EXPORT_CMD(df, cmd_df, HELP_DF)
|
XCMD_EXPORT_CMD(df, cmd_df, HELP_DF)
|
||||||
XCMD_EXPORT_CMD(cd, cmd_cd, HELP_CD)
|
XCMD_EXPORT_CMD(cd, cmd_cd, HELP_CD)
|
||||||
XCMD_EXPORT_CMD(read, cmd_read, HELP_READ)
|
XCMD_EXPORT_CMD(cat, cmd_cat, HELP_CAT)
|
||||||
XCMD_EXPORT_CMD(rm, cmd_rm, HELP_RM)
|
XCMD_EXPORT_CMD(rm, cmd_rm, HELP_RM)
|
||||||
XCMD_EXPORT_CMD(mv, cmd_mv, HELP_MV)
|
XCMD_EXPORT_CMD(mv, cmd_mv, HELP_MV)
|
||||||
XCMD_EXPORT_CMD(sync, cmd_sync, HELP_SYNC)
|
XCMD_EXPORT_CMD(sync, cmd_sync, HELP_SYNC)
|
||||||
XCMD_EXPORT_CMD(mkdir, cmd_mkdir, HELP_MKDIR)
|
XCMD_EXPORT_CMD(mkdir, cmd_mkdir, HELP_MKDIR)
|
||||||
XCMD_EXPORT_CMD(touch, cmd_touch, HELP_TOUCH)
|
XCMD_EXPORT_CMD(touch, cmd_touch, HELP_TOUCH)
|
||||||
XCMD_EXPORT_CMD(write, cmd_write, HELP_WRITE)
|
|
||||||
|
|
||||||
static xcmd_t cmds[] =
|
static xcmd_t cmds[] =
|
||||||
{
|
{
|
||||||
|
@ -456,13 +471,12 @@ static xcmd_t cmds[] =
|
||||||
{"ls", cmd_ls, HELP_LS, NULL},
|
{"ls", cmd_ls, HELP_LS, NULL},
|
||||||
{"df", cmd_df, HELP_DF, NULL},
|
{"df", cmd_df, HELP_DF, NULL},
|
||||||
{"cd", cmd_cd, HELP_CD, NULL},
|
{"cd", cmd_cd, HELP_CD, NULL},
|
||||||
{"read", cmd_read, HELP_READ, NULL},
|
{"cat", cmd_cat, HELP_CAT, NULL},
|
||||||
{"rm", cmd_rm, HELP_RM, NULL},
|
{"rm", cmd_rm, HELP_RM, NULL},
|
||||||
{"mv", cmd_mv, HELP_MV, NULL},
|
{"mv", cmd_mv, HELP_MV, NULL},
|
||||||
{"sync", cmd_sync, HELP_SYNC, NULL},
|
{"sync", cmd_sync, HELP_SYNC, NULL},
|
||||||
{"mkdir", cmd_mkdir, HELP_MKDIR, NULL},
|
{"mkdir", cmd_mkdir, HELP_MKDIR, NULL},
|
||||||
{"touch", cmd_touch, HELP_TOUCH, NULL},
|
{"touch", cmd_touch, HELP_TOUCH, NULL}
|
||||||
{"write", cmd_write, HELP_WRITE, NULL},
|
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
62
src/xcmd.c
62
src/xcmd.c
|
@ -20,7 +20,9 @@ typedef struct __history
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
|
ssize_t write_fd;
|
||||||
|
ssize_t read_fd;
|
||||||
int (*get_c)(uint8_t*);
|
int (*get_c)(uint8_t*);
|
||||||
int (*put_c)(uint8_t);
|
int (*put_c)(uint8_t);
|
||||||
}io;
|
}io;
|
||||||
|
@ -65,6 +67,31 @@ struct
|
||||||
uint8_t _initOK;
|
uint8_t _initOK;
|
||||||
} g_xcmder = {0};
|
} g_xcmder = {0};
|
||||||
|
|
||||||
|
ssize_t file_open(char *name, int is_write, int is_append) __attribute__((weak));
|
||||||
|
void file_close(ssize_t fd) __attribute__((weak));
|
||||||
|
int file_write(ssize_t fd, const char *str) __attribute__((weak));
|
||||||
|
int file_read(ssize_t fd, char *buf, int buflen) __attribute__((weak));
|
||||||
|
|
||||||
|
void file_close(ssize_t fd)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t file_open(char *name, int is_write, int is_append)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int file_write(ssize_t fd, const char *str)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int file_read(ssize_t fd, char *buf, int buflen)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
static char *xcmd_strpbrk(char*s, const char *delim) //返回s1中第一个满足条件的字符的指针, 并且保留""号内的源格式
|
static char *xcmd_strpbrk(char*s, const char *delim) //返回s1中第一个满足条件的字符的指针, 并且保留""号内的源格式
|
||||||
{
|
{
|
||||||
uint8_t flag = 0;
|
uint8_t flag = 0;
|
||||||
|
@ -159,6 +186,27 @@ static int xcmd_get_param(char* msg, char*delim, char* get[], int max_num)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int xcmd_redirected(int argc, char*argv[])
|
||||||
|
{
|
||||||
|
for(int i=1; i<(argc-1); i++)
|
||||||
|
{
|
||||||
|
if(argv[i][0] == '>')
|
||||||
|
{
|
||||||
|
argc = i;
|
||||||
|
if(argv[i][1] == '>')
|
||||||
|
{
|
||||||
|
g_xcmder.io.write_fd = file_open(argv[i+1], 1, 1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
g_xcmder.io.write_fd = file_open(argv[i+1], 1, 0);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return argc;
|
||||||
|
}
|
||||||
|
|
||||||
static int xcmd_cmd_match(int argc, char*argv[])
|
static int xcmd_cmd_match(int argc, char*argv[])
|
||||||
{
|
{
|
||||||
uint8_t flag = 0;
|
uint8_t flag = 0;
|
||||||
|
@ -178,7 +226,10 @@ static int xcmd_cmd_match(int argc, char*argv[])
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
argc = xcmd_redirected(argc, argv);
|
||||||
ret = p->func(argc, argv);
|
ret = p->func(argc, argv);
|
||||||
|
file_close(g_xcmder.io.write_fd);
|
||||||
|
g_xcmder.io.write_fd = -1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -310,6 +361,13 @@ static void xcmd_parser(uint8_t byte)
|
||||||
|
|
||||||
void xcmd_put_str(const char *str)
|
void xcmd_put_str(const char *str)
|
||||||
{
|
{
|
||||||
|
if(g_xcmder.io.write_fd != -1)
|
||||||
|
{
|
||||||
|
if(file_write(g_xcmder.io.write_fd, str) != -1)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
for(uint16_t i=0; str[i]; i++)
|
for(uint16_t i=0; str[i]; i++)
|
||||||
{
|
{
|
||||||
g_xcmder.io.put_c(str[i]);
|
g_xcmder.io.put_c(str[i]);
|
||||||
|
@ -648,6 +706,8 @@ void xcmd_init( int (*get_c)(uint8_t*), int (*put_c)(uint8_t))
|
||||||
{
|
{
|
||||||
g_xcmder.io.get_c = get_c;
|
g_xcmder.io.get_c = get_c;
|
||||||
g_xcmder.io.put_c = put_c;
|
g_xcmder.io.put_c = put_c;
|
||||||
|
g_xcmder.io.read_fd = -1;
|
||||||
|
g_xcmder.io.write_fd = -1;
|
||||||
|
|
||||||
g_xcmder.parser.prompt = XCMD_DEFAULT_PROMPT;
|
g_xcmder.parser.prompt = XCMD_DEFAULT_PROMPT;
|
||||||
g_xcmder.parser.byte_num = 0;
|
g_xcmder.parser.byte_num = 0;
|
||||||
|
|
Loading…
Reference in New Issue