-
Notifications
You must be signed in to change notification settings - Fork 1
Core
The primary system structure is the system context, defined in include/upc2/up.h:
typedef struct up_context_struct {
up_bio_t *bio;
int cur_arg;
int ttyfd;
int ttyflags;
struct termios tc;
int logfd;
int control_mode;
int console_mode;
} up_context_t;
The bio field is a pointer to the back-end structure. All communications with the target device should go through this structure.
cur_arg is used by the core logic as an index into the array of parsed arguments it is given. Nothing outside the core should fiddle with it.
The fields ttyfd, ttyflags and tc are all associated with the console. ttyfd is the file descriptor that should be used for console communications; it has been appropriately doctored to avoid translational problems. The other fields should be left alone; they contain the original state of the console which is restored when upc2 exits.
logfd is the file descriptor of the log file for output, or -1 if there is no log file. Logging is for serial output, and generally only needs to be done by the core code.
control_mode is a flag used to catch console escape sequences. The flag is set if the last character read from the console was C-a.
Finally, console_mode is a flag controlling the behaviour of the core logic. If set, the core logic will not call the protocol transfer function for the current boot stage, but simply pipes console input through to the back-end output. If clear (i.e. in upload mode), the transfer function is called.
The core logic is implemented by the function up_become_console() in src/up.c. It makes certain assumptions about the state of the system when it is called:
- All of the files to be uploaded have been opened, and their file descriptors stored in the
fdfield of the relevantup_load_art_tentry. - All of the protocols (that will be used) have been initialised.
Processing then proceeds in three stages.
The function up_start_console() is called to alter the terminal attributes of stdin to be suitable for a remote console, for example not interpreting C-c as a SIGINT. The original attributes are stashed in the system context as described above. If an input socket other than stdin is to be used, this function will need some changes.
The core logic also calls the prepare entry point (if any) of the protocol descriptor of the first boot stage in preparation for the main loop, and checks to see if the first boot stage should start in console mode (see below).
The function up_operate_console() is called repeatedly to operate the core logic. It takes the following steps:
-
The serial input and console input are polled, timing out after a second. The results of the polling are subsequently ignored, so all this really does is introduce slightly random delays and catch comms errors.
-
The serial input is read in a non-blocking manner. If this results in any bytes of input, these are copied to the console output and logged.
-
If the core logic is not in console mode, the
transferfunction for the current protocol is called. If this reports that the upload is finished, it will call thecompleteentry point of this boot stage and advance to the next boot stage, calling theprepareentry point of the new protocol and re-evaluating whether the system should be in console mode or not. If there is no file to upload or the boot stage is explicitly flagged as deferred, the system will go into console mode.Note that the transfer function may last for an arbitrarily long time. It is perfectly permissible (and usual) for the entire upload to be done in a single call to the function.
-
The console input is read in a non-blocking manner. If this results in any bytes of input, they are checked for escape sequences (which are removed and interpreted) and then copied to the serial output. (RMJ: arguably the latter should only happen in console mode -- see below.)
The main loop is exited when the function returns a negative value. In practise this is almost always because the user pressed C-a x.
The core logic finishes up by calling the the complete entry point of the current (final) boot stage protocol, then calls up_finish_console() to restore the terminal attributes of the console.
It is presumed that the front-end will call the shutdown entry of all protocols that it initialised, and close all the files it opened.
The system recognises a number of escape sequences, all beginning with C-a. Most of these sequences should only be used in console mode, and may or may not be noted in upload mode. The sequences currently recognised are:
-
C-a xquits the application. This works in all modes. -
C-a C-apasses a literalC-athrough to the serial back-end. -
C-a llists the boot stages parsed by the command-line logic. The current boot stage is indicated with an asterisk. -
C-a 0selects boot stage 0 as the current boot stage. It remains in console mode; to execute the boot stage, typeC-a c. Similarly,C-a 1selects boot stage 1,C-a 2selects boot stage 2, and so on up toC-a 9selecting boot stage 9. -
C-a nselects the next boot stage. Again, it remains in console mode. -
C-a psimilarly selects the previous boot stage. -
C-a ccontinues the boot at the current boot stage, switching from console mode into upload mode.
(RMJ: sort out console input reading. Arguably we should not read the console input if we are not in console mode, except by calling utils_check_critical_control() to catch C-a x interrupts.)