Loading...
Searching...
No Matches
shell.c
1/***********************************************************************************
2 * @file shell.c *
3 * @author Matt Ricci *
4 * @addtogroup Shell *
5 * *
6 * @todo Add commands to buffer to allow managing shell history for frontend *
7 ***********************************************************************************/
8
9#include "shell.h"
10
11#include "devicelist.h"
12
13extern uint32_t __shell_vector_start;
14extern uint32_t __shell_vector_end;
15
16/* =============================================================================== */
27void vShellExec(void *argument) {
28 ShellTaskParams params = *(ShellTaskParams *)argument;
29
30 for (;;) {
31 params.shell->run(params.shell, params.str);
32
33 // Remove handle from shell first to prevent
34 // nullptr dereference in Shell_clear
35 params.shell->taskHandle = NULL;
36
37 // Delete task and end thread
38 vTaskDelete(NULL);
39 }
40}
41
42/* =============================================================================== */
53int Shell_init(Shell *shell) {
54 shell->usb = *(UART_t *)DeviceList_getDeviceHandle(DEVICE_UART_USB).device;
55 shell->help = Shell_help;
56 shell->run = Shell_run;
57 shell->runTask = Shell_runTask;
58 shell->clear = Shell_clear;
59
60 // TODO:
61 // Error checking to determine if any shell programs exist or vector overflow
62 // occurred.
63
64 return 0;
65}
66
67/* =============================================================================== */
77void Shell_help(Shell *shell) {
78 shell->usb.print(&shell->usb, "Use `help [name]` for more information on a specific command\n\r");
79 shell->usb.print(&shell->usb, "The following commands are currently available:\n\r");
80 for (uint32_t *i = (uint32_t *)&__shell_vector_start; i < (uint32_t *)&__shell_vector_end; i++) {
82 if (strcmp(handle->name, "")) {
83 shell->usb.print(&shell->usb, ":");
84 shell->usb.print(&shell->usb, handle->name);
85 shell->usb.print(&shell->usb, "\n\r");
86 }
87 }
88}
89
90/* =============================================================================== */
102void Shell_run(Shell *shell, uint8_t *programName) {
103 char *token = strtok((char *)programName, " ");
104 char *flags = strchr(token, '\0') + 1;
105
106 // Register programs in vector to shell
107 for (uint32_t *i = (uint32_t *)&__shell_vector_start; i < (uint32_t *)&__shell_vector_end; i++) {
108 // Dereference memory location and cast to program handle pointer
110 // Iterate shell vector and execute function from handle with matching name (if any)
111 if (!strcmp(handle->name, programName)) {
112 handle->exec(shell, flags);
113 return; // Early exit if program is found
114 }
115 }
116
117 // Print help string if no matching command is found
118 shell->usb.print(&shell->usb, (char *)programName);
119 shell->usb.print(&shell->usb, ": command not recognized. Run `help` for a list of available commands\n\r");
120}
121
122/* =============================================================================== */
134void Shell_runTask(Shell *shell, uint8_t *str) {
135
136 static ShellTaskParams params;
137 params.shell = shell;
138 params.str = str;
139
140 // Create new task to parse and execute shell program
141 xTaskCreate(
142 vShellExec,
143 "ShellProgram",
144 256,
145 (void *)&params,
146 configMAX_PRIORITIES - 6,
147 &shell->taskHandle
148 );
149}
150
151/* =============================================================================== */
159bool Shell_clear(Shell *shell) {
160 shell->usb.print(&shell->usb, CMD_CLEAR);
161 // Delete any running task
162 if (shell->taskHandle != NULL)
163 vTaskDelete(shell->taskHandle);
164 return true;
165}
DeviceHandle_t DeviceList_getDeviceHandle(DeviceKey)
Retrieve device handle from list by key.
Definition devicelist.c:36
bool(* clear)(struct Shell *)
Definition shell.h:53
void(* run)(struct Shell *, uint8_t *)
Definition shell.h:51
TaskHandle_t taskHandle
Handle of currently active program in shell thread.
Definition shell.h:54
char name[SHELL_PROGRAM_NAME_LENGTH]
Program name as referenced by the shell.
Definition shell.h:66
void(* help)(struct Shell *)
Definition shell.h:50
void(* runTask)(struct Shell *, uint8_t *)
Definition shell.h:52
UART_t usb
UART interface to connect shell I/O.
Definition shell.h:49
void(* exec)(struct Shell *, uint8_t *)
Program entry point function pointer.
Definition shell.h:67
int Shell_init(Shell *shell)
Initializes the shell, registering programs from shell vector.
Definition shell.c:53
void Shell_help(Shell *)
Displays available shell commands.
Definition shell.c:77
bool Shell_clear(Shell *)
Send clear sequence to host terminal.
Definition shell.c:159
void Shell_runTask(Shell *, uint8_t *)
Creates a task to run a shell program.
Definition shell.c:134
void Shell_run(Shell *, uint8_t *)
Executes a shell program by name.
Definition shell.c:102
Struct definition for shell interface.
Definition shell.h:48
Struct definition for shell program handle.
Definition shell.h:65
Struct definition for parameters passed to shell task.
Definition shell.h:74
void(* print)(struct UART *, char *)
UART print string method.
Definition uart.h:61
Struct definition for UART interface.
Definition uart.h:52