EE445M RTOS
Taken at the University of Texas Spring 2015
shellpp.cpp
Go to the documentation of this file.
1 #include "shellpp.hpp"
2 #include "blinker.hpp"
3 
4 #include "inc/hw_memmap.h"
5 
6 #include "libio/kbd.h"
7 
8 #define EXIT_SUCCESS 0
9 
10 #define SHELL_VERBOSE
11 
12 #define shell_command_is(a) \
13  0 == ustrncmp(a, (const char*) buf.buf, buf.length())
14 
17 
20 
21 exit_status_t shell::doctor(const char* args) {
22 
23  blinker blink = blinker(GPIO_PORTF_BASE);
24  blink.toggle(PIN_RED);
25  return EXIT_SUCCESS;
26 }
27 
28 exit_status_t shell::witch(const char* args) {
29 
30  blinker blink = blinker(GPIO_PORTF_BASE);
31  blink.toggle(PIN_GREEN);
32  return EXIT_SUCCESS;
33 }
34 
35 exit_status_t shell::jester(const char* args) {
36 
37  blinker blink = blinker(GPIO_PORTF_BASE);
38  blink.toggle(PIN_BLUE);
39  return EXIT_SUCCESS;
40 }
41 
44 int32_t shell::ustrncmp(const char *s1, const char *s2, uint32_t n) {
45 
46  /* Loop while there are more characters. */
47  while(n) {
48  /* If we reached a NULL in both strings, they must be equal so
49  * we end the comparison and return 0 */
50  if((!*s1 || (*s1 == ' ')) && (!*s2 || (*s2 == ' '))) {
51  return(0);
52  }
53 
54  if(*s2 < *s1) { return(1); }
55  if(*s1 < *s2) { return(-1); }
56 
57  s1++;
58  s2++;
59  n--;
60  }
61  /* If we fall out, the strings must be equal for at least the
62  * first n characters so return 0 to indicate this. */
63  return 0;
64 }
65 
66 void shell::ustrcpy(char* dest, const char* source) {
67 
68  uint32_t i = 0;
69  while (1) {
70  dest[i] = source[i];
71  if (source[i++] == '\0') { break; }
72  }
73 }
74 
75 void shell::init() {
76 
78  init_ps1();
79 }
80 
82 
83  init();
84 }
85 
87 
88  uart0 = u;
89  init();
90 }
91 
92 shell::shell(uart* u, semaphore* m_start, semaphore* m_stop) {
93 
94  uart0 = u;
95 
96  m_start = m_start;
97  m_stop = m_stop;
98 
99  init();
100 }
101 
103 
104  /* KLUDGE: shitty way to set PS1 */
105  ps1[0] = '>';
106  ps1[1] = ' ';
107  ps1[2] = ' ';
108  ps1[3] = 0;
109 
110  print_ps1();
111 }
112 
113 void* shell::memset(void* b, int c, int len) {
114 
115  int i;
116  unsigned char *p = (unsigned char *) b;
117  i = 0;
118  while(len > 0) {
119  *p = c;
120  ++p;
121  --len;
122  }
123  return b;
124 }
125 
126 uint32_t shell::strlen(const char* s) {
127  uint32_t len = 0;
128  while(s[len]) { ++len; }
129  return(len);
130 }
131 
132 void* umemcpy(void *str1, const void *str2, long n) {
133 
134  long i = 0;
135  uint8_t *dest8 = (uint8_t*)str1;
136  uint8_t *source8 = (uint8_t*)str2;
137  for (i=0; i<n; ++i) {
138  dest8[i] = source8[i];
139  }
140 }
141 
143 
144  buf.clear();
145 }
146 
147 void shell::set_ps1(char* new_ps1) {
148 
149  umemcpy(ps1, new_ps1, strlen(new_ps1));
150 }
151 
154 
155  buf.clear();
156  uart0->atomic_printf("\n\n\r%s", ps1);
157 }
158 
159 bool shell::type(char ch) {
160 
161  bool ret;
162  if (buf.full()) {
163  ret = false;
164  } else {
165  ret = true;
166  buf.add((const char) ch);
167  }
168  if(ret) {
169  uart0->atomic_printf("%c", ch);
170  }
171  return ret;
172 }
173 
174 void shell::accept(char ch) {
175 
176  switch(ch) {
177  case SC_CR:
178  execute_command();
179  break;
180 
181  case 127:
182  case SC_BACKSPACE:
183  backspace();
184  break;
185 
186  default:
187  type(ch);
188  break;
189  }
190 }
191 
193 
194  bool ok;
195  buf.get(ok);
196  if (ok) {
197  uart0->atomic_printf("\b \b");
198  }
199 }
200 
202 
203  shell::m_start->post();
204  return EXIT_SUCCESS;
205 }
206 
207 exit_status_t shell::motor_stop(const char* args) {
208 
209  shell::m_stop->post();
210  return EXIT_SUCCESS;
211 }
212 
216 /* exit_status_t shell::help_info(const char* args) { */
217 
218 /* uart0->atomic_printf("Recognized commands:\n"); */
219 /* uart0->atomic_printf("help\n"); */
220 /* uart0->atomic_printf("doctor\n"); */
221 /* uart0->atomic_printf("witch\n"); */
222 /* uart0->atomic_printf("jester\n"); */
223 /* uart0->atomic_printf("start\n"); */
224 /* uart0->atomic_printf("stop\n"); */
225 /* return EXIT_SUCCESS; */
226 /* } */
227 
229 
230  /* Null terminate to separate the cmd from the args */
231  uint8_t len = buf.length();
232  uint8_t idx = 0;
233  while((idx < len) && (buf.buf[idx] != ' ')) {
234  ++idx;
235  }
236  buf.buf[idx] = 0;
237 
238  /* Clear some space between the user input and this cmd output */
239  uart0->atomic_printf("\r\n");
240 
241  exit_status_t exit_code = (exit_status_t) 0xDEADBEEF;
242  const char* args = &buf.buf[idx+1];
243  /* Waldo says this line requires the extra char to be a 0 */
244  if(shell_command_is("doctor")) {
245  exit_code = doctor(args);
246  } else if(shell_command_is("witch")) {
247  exit_code = witch(args);
248  } else if(shell_command_is("jester")) {
249  exit_code = jester(args);
250  /* begin motor control commands */
251  } else if(shell_command_is("start")) {
252  exit_code = motor_start(args);
253  } else if(shell_command_is("stop")) {
254  exit_code = motor_stop(args);
255  } else {
256  uart0->atomic_printf("%s is not a recognized command.\n\r", buf.buf);
257  }
258 
259 #ifdef SHELL_VERBOSE
260  if (exit_code != EXIT_SUCCESS) {
261  uart0->atomic_printf("\n\rnonzero exit code: %d", exit_code);
262  }
263 #endif
264 
265  /* Prepare for the next command */
266  print_ps1();
267 
268  return exit_code;
269 }
#define EXIT_SUCCESS
Definition: shellpp.cpp:8
void * umemcpy(void *str1, const void *str2, long n)
Definition: shellpp.cpp:132
void clear()
Definition: bufferpp.hpp:33
uint8_t exit_status_t
Definition: shellpp.hpp:28
int32_t ustrncmp(const char *, const char *, uint32_t)
Definition: shellpp.cpp:44
Definition: uartpp.hpp:28
void atomic_printf(const char *pcString,...)
Definition: uartpp.cpp:348
void init_ps1(void)
Definition: shellpp.cpp:102
static exit_status_t motor_start(const char *args)
Definition: shellpp.cpp:201
exit_status_t(* sys_cmd)(const char *)
Definition: shellpp.hpp:29
void post(void)
Definition: semaphorepp.cpp:45
const pin_t PIN_BLUE
Definition: blinker.hpp:20
bool type(char ch)
Definition: shellpp.cpp:159
#define shell_command_is(a)
Definition: shellpp.cpp:12
exit_status_t execute_command()
Definition: shellpp.cpp:228
T buf[N]
Definition: bufferpp.hpp:115
static void ustrcpy(char *dest, const char *source)
Definition: shellpp.cpp:66
bool full()
Definition: bufferpp.hpp:96
T get(bool &ok)
Definition: bufferpp.hpp:76
char ps1[4+1]
Definition: shellpp.hpp:36
void init(void)
Definition: shellpp.cpp:75
bool add(const T data)
Definition: bufferpp.hpp:56
static sys_cmd system_command_funcs[2]
Definition: shellpp.hpp:54
blinker blink
Definition: move-main.cpp:38
static exit_status_t witch(const char *args)
Definition: shellpp.cpp:28
shell()
Definition: shellpp.cpp:81
const pin_t PIN_RED
Definition: blinker.hpp:18
void print_ps1()
Definition: shellpp.cpp:153
static exit_status_t motor_stop(const char *args)
Definition: shellpp.cpp:207
#define SHELL_COMMANDS
Definition: shellpp.hpp:15
static exit_status_t jester(const char *args)
Definition: shellpp.cpp:35
static exit_status_t doctor(const char *args)
Definition: shellpp.cpp:21
static semaphore * m_stop
Definition: shellpp.hpp:61
void accept(char ch)
Definition: shellpp.cpp:174
#define SYSTEM_MAX_NAME_LENGTH
Definition: shellpp.hpp:17
void set_ps1(char *new_ps1)
Definition: shellpp.cpp:147
virtual void toggle(pin_t pin)
Definition: blinker.cpp:34
const pin_t PIN_GREEN
Definition: blinker.hpp:19
void backspace(void)
Definition: shellpp.cpp:192
buffer< char, 32 > buf
Definition: shellpp.hpp:34
static char system_command_names[2][10]
Definition: shellpp.hpp:53
void clear_buffer()
Definition: shellpp.cpp:142
uart * uart0
Definition: shellpp.hpp:33
void * memset(void *b, int c, int len)
Definition: shellpp.cpp:113
uint32_t length()
Definition: bufferpp.hpp:106
uint32_t strlen(const char *)
Definition: shellpp.cpp:126
static semaphore * m_start
Definition: shellpp.hpp:60