Implementation of the shell can be found in shell/shell.c
. Elements in hexagons
are to be provided by the user (check the examples/
for sample implementation) and those in rectangle
are functions that the shell.c
implements and uses.
Shell is implemented around the idea of registering commands in a command table
during development/compile time, scanning the uart in runtime and if a string matches that stored in the command table, then execute the associated function.
The state machine can be understood based on the flow chart below.
flowchart TD
start((Power On))--1-->reset_hldr{{Reset Handler}}
reset_hldr--2-->sp{{Set stack Pointer}}
reset_hldr--3-->prompt["prompt()"]
prompt--4-->init_setup["initial_setup()"]
init_setup--5-->platform_init{{"platform_init()"}}
platform_init--6-->uart_init{{"uart_init()"}}
platform_init--7-->set_read_char{{"set_read_char()"}}
platform_init--8-->set_write_char{{"set_write_char()"}}
prompt--9-->exec_auto_cmds["exec_auto_cmds()"]
prompt--10-->setup{{"setup()"}}
prompt--11-->shell["shell()"]
shell--12-->uart{Char on \nUART?}
uart--No-->loop{{"loop()"}}
loop-->uart
uart--Yes-->strmatch{"String matched in\n command table?"}
strmatch--Yes-->execute["execute()"]
strmatch--No-->uart
execute-->shell
Reset Handler
is the entry point after power on.- The
stack pointer
register (sp) is loaded with memory address that will be used as stack.- This is required for the function calls to work correctly.
- The reset handler then jumps to
prompt()
which never returns. prompt()
jumps toinitial_setup()
.initial_setup()
executes a platform initialization routine (platform_init()
).platform_init()
is a user implemented function that configures the uart and provides shell with two functions that can help it read and write a character on the uart.- This is achieved by calling
uart_init()
,set_read_char()
andset_write_char()
.
uart_init()
implements the configuration and setup of the uart. Because each board/target may have different uart and thus need a different configuration, this function is to be provided by the user.uart_getc()
anduart_putc()
are other two functions that the user would need to implement (not shown in diagram).- These implement a polling based uart read and write respectively.
set_read_char()
is used to registeruart_getc()
as a function pointer in shell. Shell then uses this function to read a character from the uart.set_write_char()
is used to registeruart_putc()
as a function pointer, when then enables the shell to put a character on the uart.- After the
initial_setup()
the state-machine executesexec_auto_cmds()
. This then essentially goes on to executing functions that were registered in the shell to be executed automatically once. An example of this isbuild_info()
. - [Optional]
setup()
allows one time execution, the user may call other functions from this that are to be executed only once. This is optional and the user may skip the implementation. shell()
is the infinite loop!
shell()
implement a scan loop that continuously checks the uart for any bytes and if available stores them in a buffer until \n
or \r
is not seen. shell()
works as follows:
- Scans a character from the uart.
- If there was no valid character, then it executes
loop()
once and returns to (i). - Else, if there was a character found then it -
- Records it in a buffer and checks if it was
\n
or\r
. - If the character was line terminator (i.e
\r
or\n
), then it callsexecute()
which then processes the buffer and checks in the command table if any functions pointer is available against the strings in buffer. Ifyes
then, it executes the command. If not, then it returns andshell()
is called again.
- Records it in a buffer and checks if it was
setup()
and loop()
are both optional functions that the user can implement. The idea is that -
setup()
implements a one time setup, andloop()
is called over and over again.
User can choose to leave these functions unimplemented. One can expect (if implemented) the setup()
to be called just once and loop()
to be called over and over as depicted in the flow chart. This together then gives a linux like environment where the prompt is available for the user to use and there can be functions getting called in the back ground.
The only limitation is that the loop()
should not have an infinite loop within it!