實作一個 shell,支援以下指令:
main.c
1
2
3
4
5
6
7
8
9
10
11
12
13
| #include "shell.h"
#define CMD_LEN 128
int main() {
shell_init();
while (1) {
char cmd[CMD_LEN];
shell_input(cmd);
shell_controller(cmd);
}
}
|
shell_input 基本上就是在 read_newline,然後處理一下 ANSI Escape。
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
| void shell_input(char* cmd) {
uart_printf("\r# ");
int idx = 0, end = 0, i;
cmd[0] = '\0';
char c;
while ((c = uart_read()) != '\n') {
// Decode CSI key sequences
if (c == 27) {
enum ANSI_ESC key = decode_ansi_escape();
switch (key) {
case CursorForward:
if (idx < end) idx++;
break;
case CursorBackward:
if (idx > 0) idx--;
break;
case Delete:
// left shift command
for (i = idx; i < end; i++) {
cmd[i] = cmd[i + 1];
}
cmd[--end] = '\0';
break;
case Unknown:
uart_flush();
break;
}
}
// CTRL-C
else if (c == 3) {
cmd[0] = '\0';
break;
}
// Backspace
else if (c == 8 || c == 127) {
if (idx > 0) {
idx--;
// left shift command
for (i = idx; i < end; i++) {
cmd[i] = cmd[i + 1];
}
cmd[--end] = '\0';
}
}
else {
// right shift command
if (idx < end) {
for (i = end; i > idx; i--) {
cmd[i] = cmd[i - 1];
}
}
cmd[idx++] = c;
cmd[++end] = '\0';
}
uart_printf("\r# %s \r\e[%dC", cmd, idx + 2);
}
uart_printf("\n");
}
|
shell_controller 根據 input 決定要執行什麼 function。
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
| void shell_controller(char* cmd) {
if (!strcmp(cmd, "")) {
return;
}
else if (!strcmp(cmd, "help")) {
uart_printf("help: print all available commands\n");
uart_printf("hello: print Hello World!\n");
uart_printf("timestamp: get current timestamp\n");
uart_printf("reboot: reboot pi\n");
}
else if (!strcmp(cmd, "hello")) {
uart_printf("Hello World!\n");
}
else if (!strcmp(cmd, "timestamp")) {
uart_printf("%f\n", get_timestamp());
}
else if (!strcmp(cmd, "reboot")) {
uart_printf("Rebooting...");
reset();
while (1); // hang until reboot
}
else {
uart_printf("shell: command not found: %s\n", cmd);
}
}
|
This register is provided so that software can discover the frequency of the system counter. It must be programmed with this value as part of system initialization. The value of the register is not interpreted by hardware.
https://developer.arm.com/docs/ddi0595/c/aarch64-system-registers/cntfrq_el0
Holds the 64-bit physical count value.
https://developer.arm.com/docs/ddi0595/b/aarch64-system-registers/cntpct_el0
https://elinux.org/BCM2835_registers#PM