Repository navigation
Expand file tree
/
Copy pathshell.hpp
More file actions
248 lines (210 loc) · 5.23 KB
/
Copy pathshell.hpp
File metadata and controls
248 lines (210 loc) · 5.23 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
//////////////////////////////////////////////////////////////////////////
// The MOS Shell //
// https://github.com/Eplankton/mos-core //
// Old Salt Harbour Electric Industry Group //
// The Apache License, Version 2.0 //
//////////////////////////////////////////////////////////////////////////
#ifndef _MOS_SHELL_
#define _MOS_SHELL_
#include "kernel/task.hpp"
#include "kernel/data_type/buffer.hpp"
namespace MOS::Shell
{
using namespace Kernel;
using namespace Utils;
using namespace DataType;
using Cmd_t = struct Command_t
{
using Ret_t = void;
using Text_t = const char*;
using Argv_t = const char*;
using Fn_t = Ret_t (*)(Argv_t);
Text_t text;
Fn_t callback;
MOS_INLINE inline uint32_t
len() const volatile { return strlen(text); }
MOS_INLINE inline void
run(Argv_t argv) const volatile { callback(argv); }
MOS_INLINE inline void
operator=(const Command_t& cmd) volatile
{
text = cmd.text;
callback = cmd.callback;
}
Argv_t match(Text_t str) const volatile
{
const auto xlen = len(); // The length of a command
// Skip all blank
auto skip = [](Text_t str) {
while (*str == ' ') ++str;
return str;
};
// Check whether match or not
auto check = [&](Text_t str) {
return (str[xlen] == ' ' || str[xlen] == '\0') &&
(strncmp(str, text, xlen) == 0);
};
str = skip(str);
return check(str) ? skip(str + xlen) : nullptr;
}
};
namespace CallBack
{
using Argv_t = Cmd_t::Argv_t;
MOS_INLINE static inline void
bad_argv_err()
{
LOG("Invalid Arguments");
}
static inline void
task_ctrl_cmd(Argv_t argv, auto&& ok, auto&& err)
{
auto name = argv;
if (*name != '\0') {
if (auto tcb = Task::find(name)) {
ok(tcb);
}
else {
LOG("Unknown task '%s'", name);
}
}
else { // No arguments provided
err();
}
}
static inline void
ls_cmd(Argv_t _) { Task::print_all(); }
static inline void
kill_cmd(Argv_t argv)
{
task_ctrl_cmd(
argv, [](auto tcb) {
LOG("Task '%s' terminated", tcb->get_name());
Task::terminate(tcb);
},
bad_argv_err
);
}
static inline void
time_cmd(Argv_t _)
{
const uint32_t up_tks = (uint32_t) (Global::os_ticks / Macro::SYSTICK);
kprintf(
"========= Uptime: %02u:%02u:%02u =========\n",
(up_tks / 3600),
(up_tks % 3600 / 60),
(up_tks % 60)
);
}
static inline void
block_cmd(Argv_t argv)
{
task_ctrl_cmd(
argv,
[](auto tcb) {
LOG("Task '%s' blocked", tcb->get_name());
Task::block(tcb);
},
bad_argv_err
);
}
static inline void
resume_cmd(Argv_t argv)
{
task_ctrl_cmd(
argv, [](auto tcb) {
LOG("Task '%s' resumed", tcb->get_name());
Task::resume(tcb);
},
bad_argv_err
);
}
static inline void
uname_cmd(Argv_t argv)
{
IrqGuard_t guard;
if (argv && *argv) {
LOG("User Name => %s", argv);
memcpy((void*) Global::user_name, argv, Macro::USER_NAME_SIZE);
}
kprintf(
" A_A _ [%s] @ %s\n"
"o'' )_____// Build @ %s, %s\n"
" `_/ MOS ) Chip @ %s, %s\n"
" (_(_/--(_/ 2023-2026 Copyright by Eplankton\n",
Global::user_name,
MOS_VERSION,
__TIME__, __DATE__,
MOS_MCU, MOS_ARCH
);
}
static inline void
reboot_cmd(Argv_t argv)
{
LOG("Reboot!\n\n");
MOS_REBOOT();
}
static inline void
help_cmd(Argv_t argv);
static constexpr Cmd_t sys_cmd_map[] = {
{ "ls", ls_cmd}, // List all tasks
{ "kill", kill_cmd}, // Kill a task
{ "block", block_cmd}, // Block a task
{"resume", resume_cmd}, // Resume a task
{ "help", help_cmd}, // Show help info
{ "time", time_cmd}, // Show system uptime
{ "uname", uname_cmd}, // Show system info / Set user name
{"reboot", reboot_cmd}, // Reboot system
// Add more commands to here by {"text", callback}
};
// Register services
static Buffer_t<Cmd_t, Macro::SHELL_USR_CMD_SIZE> usr_cmd_map;
static inline void
help_cmd(Argv_t argv)
{
static auto show = [](const auto& cmds) {
for (auto [text, _]: cmds) {
kprintf("%s, ", text);
}
};
kprintf("{");
show(sys_cmd_map);
show(usr_cmd_map);
kprintf("}\n");
}
}
MOS_INLINE inline void
add_usr_cmd(Cmd_t&& cmd)
{
CallBack::usr_cmd_map.push(cmd);
}
template <size_t N>
void launch(SyncRxBuf_t<N>& input)
{
static auto parser = [](auto str) {
using CallBack::sys_cmd_map;
using CallBack::usr_cmd_map;
kprintf("> %s\n", str); // Echo the input str
if (str[0] != '\0') {
for (auto& cmd: sys_cmd_map) { // Search in System Commands
if (auto argv = cmd.match(str)) {
return cmd.run(argv);
}
}
for (auto& cmd: usr_cmd_map) { // Search in User Commands
if (auto argv = cmd.match(str)) {
return cmd.run(argv);
}
}
LOG("Unknown command '%s'", str);
}
};
CallBack::uname_cmd(nullptr);
Task::print_all();
// Wait -> Recv -> Parse -> Run -> Clear -> Wait
while (true) {
parser(input.recv().as_str());
}
}
}
#endif