Scriptable Embedded Systems

From EdWiki


A typical embedded system by default can have limited features. By exposing internal parameter and functions with scripting capability can give more features to user as he wants. User level automation can be made.

With same hardware but extension in software => more features and configurable customization at user level. So flow of the code can be changed by scripting without changing source code.

Example TCL Shell


  • To Port existing TCL source code (7.4) written for UNIX platform to bare metal embedded platform.
  • To Provide syscalls for streams (stdin, stdout...) redirection to UART
  • Implement small file system to store scripts in EEPROM
  • Due to unavailability of Tiva LaunchPad, the Keil 5 Simulator is used.


Block Diagram

The base layer is formed by Tiva device peripheral libraries, which configure and interact with hardware. On top of it, EFS (EEPROM File System), Syscalls and User defined Functions layer are present.

EFS provides the filesystem capability to TCL. Syscall layer emulates the OS type syscall which are used by TCL API, C Library Functions, File Operations and std streams. User defined functions contains core functionality of embedded system (e.g. control logic of any system) and C mapping functions for custom TCL commands (which will be available to user).

On top of that, TCL API layer is present. TCL API handles the standard TCL commands like for, while, if, proc, puts, lindex etc. The TCL Async Event Handler is used for executing TCL commands on asynchronous events like interrupt, timed events. The topmost layer of TCL shell is provided to user to execute TCL commands.

Syscall Redirection

The typical OS system has system calls for doing low level kernel tasks. But in bare metal embedded system, std C library newlib syscalls are not present at default. So custom functions needs to be implemented in such systems so that library calls can be directly used.

  • write, read redirected to UART or EEPROM File system (EFS) based on file number.
  • open, close, fstat, stat, link, lseek syscall redirected to EFS API
  • Syscall implementation to support dynamic allocation (malloc, free, calloc etc)

POSIX Syscall Redirection

As TCL source code is meant for UNIX like OS environments while porting it to bare metal embedded systems, unsupported POSIX syscalls need to be redirected or blocked. Also Environment variables as required by TCL API are emulated.

  • Redirection of opendir, readdir syscall to EFS API
  • Blocking of unsupported syscall with proper errno
e.g. chdir, fork, execvp, pipe, wait, kill, fnctl

EFS File System

A small footprint file system especially for EEPROM was designed as part of this project.


  • Designed for EEPROM (1KiB – 64KiB)
  • Fixed File Count File System
  • Flat hierarchy File System
  • Supports R/W File attributes
  • Supports all Read, Write, Append mode.
  • Page aligned storage.

Supports Syscall like API. Possible future support for folders and symlinks. Possible future support for wear leveling.

Detailed specification of EEPROM File System can be found here.

TCL 7.4 specific changes

TCL 7.4 uses varargs.h which is not supported in stdc. So all varargs implementations ported to stdarg format. Modifying source code for reduced resource utilization like modifying Buffer Sizes, Disabling unsupported functions.

Custom TCL commands are used to configure/control the embedded system. Internally each custom command is mapped to a C function. When that custom command is entered in TCL shell, mapped C function is executed with passed arguments

TCL command <===> C function
delay       <===> delayCmd(int argc, char *argv[]);


The implemented custom commands are

led <color> <on|off|toggle|blink>

delay <time_ms>

system trigger <trigger_event> <TCL command>

system every <period_ms> <TCL command>

system set <parameter> <value>

system get <parameter>

The <parameter> is the name of system parameters exposed to user. For demonstration on Keil simulator, adc0, ticks, sp, ... system parameters are available.

Basic shell commands

This shows how commands can be directly executed from TCL shell. Also Indirect execution of commands by sourcing file

for {set i 0} {$i < 5} {incr i} {
    puts $i
    led blue on
    delay 500
    led blue off
    delay 500

Getting System Parameters

This demostration shows, how system parameter can be imported into TCL script and system behaviour can be dynamically changes.

The delay is dependent on analog value at the adc0 pin.

source demo2.tcl

#demo2.tcl :
for {set i 0} {$i < 10} {inc i} {
    puts $i
    led blue on
    delay [system get adc0]
    led blue off
    delay [system get adc0]

Event trigger

Event triggers are used to execute some TCL command when some asynchronous event is triggered like pressing a switch causing interrupt, timer interrupt, software triggered events.

system trigger <trigger_event> <TCL command>

TCL command can also be TCL command, custom TCL procedure or sourcing a file.

system trigger sw2 "led red toggle"
#                 OR
proc custom_proc {color} {
    led $color toggle
system trigger sw2 "custom_proc blue"

Periodic Execution

Periodic Execution is used to schedule periodic asynchronous execution of TCL command/s. This could be useful in custom logging or data display.

system every <period_ms> <TCL command>

TCL command can also be TCL command, custom TCL procedure or sourcing a file.

# update.tcl :
set sp [system get sp]
set ticks [system get ticks]
lcd clear
lcd write "sp:$sp"
lcd cursor 3 0
lcd write "ticks:$ticks"
system set custom_lcd 1
system every 1000 "source update.tcl"


Resource Utilization

Source O0 O1 Osize Ospeed RAM (.data + .bss) (Bytes)
TCL 108.5 80.9 69.8 80.6 1980
Peripherals 5.0 3.6 3.2 3.6 504
EFS 5.1 3.4 2.8 3.3 101
Custom 4.8 3.4 2.9 3.3 328
Demo (main.c) 1.3 1.2 1.1 1.2 12
Total 124.8 92.6 79.9 91.9 2.85 KiB

The resources required by TCL shell are quite high. Including stack and heap usage, RAM requirement goes to 10 KiB. So micro-controller with minimum flash of 128KiB and RAM of 16 KiB can be used.

Future Scope

Due to resourses issues, other lightweight scripting language like Lua, MicroPython can be ported/implemented.

As full access to the system is given through shell, security concerns needs to be taken care.

If the creation & implementation of custom UART or I2C streams are given to user. User can implement a custom protocol stack in TCL scripting itself. In this way Virtual Protocol Environment can be emulated.


The source code is available for future upgrades / pull requests on github.