Advanced Computer Systems - prof. Sivan Toledo

Students: Or Ostrovsky, Ofek Kirzner

Porting picol to CC2650 Launchpad

Abstract

As our final project in the course, we aimed to simplify the task of programming useful software, and to ease the process of interfacing with the CC2650 Launchpad board, made by Texas Instruments. Throughout the course, we have put a lot of efforts to accomplish simple tasks, such as manipulating the input and output pins, responding to interrupts, and utilizing various modules embedded in the processor. This is due to the need to understand the internals of the board, and the need to compile, load and debug one's code. We have come to realize that like scripting languages simplify PC programming, it can simplify embedded programming. And so, we have decided to port the TCL language to the CC2650 Launchpad MCU.

Capabilities and main functions

Choosing an interpreter

The platform at hand required the interpreter to meet the following requirements:

Apparently, most scripting engines have taken into account the last requirement, and may be easily embedded inside existing code bases. The other requirements are not so simple, since the more complex and usable the language, so it requires more memory. This rules out most common languages, like python or ruby. Even Lua, which is considered memory efficient, requires at least 32KB of RAM to operate. We briefly examined FORTH, which is a very small language that requires few KB's of RAM to function, but we have decided that any meaningful program written in it, will be more complex than the equivalent C code.

The perfect interpreter (and language) was Picol. Picol is a micro-implementation of the TCL language, which supports the core features of the language. It is also a single file implementation, and easily allows to add new commands if the need arises.

The homepage of the picol project is here.

Interpreter modifications

The biggest challenge we faced, was the fact that the board has a very small amount of RAM, only 28KB. To address this challenge we did several adjustments to the engine:

Responding to multiple IO sources

We wanted the interpreter to execute commands upon input from one of many sources. The interpreter should wait until input arrives from any source, and execute the relevant code. That code might send textual output via UART, or change the state of the board hardware in another way. Currently, we support three sources: * The UART input * GPIO interrupts * Clock generated interrupts

Implementation

Since the interpreter doesn't support multithreading, only one task may use it at once. Also, since it requires a large stack, only one task may use it at all. This results in the following architecture:

Using tirtos's Events allow to add a large number of input sources in the future, since it supports up to 32 distinct events. Also, since all event sources are handled equally without any busy-waiting, the interpreter is responsive for all of them.

New Commands

After Connecting using a UART (using putty for example), with 9600 baud rate, one can try the following commands:

  1. setgpio <pin id> <value> - Sets pin id to the given value.
  2. getgpio <pin id> - Returns the value of the pin id.
  3. gpio_set_inter <pin id> <tcl function> - Sets an interrupt handler on the given pin id.
  4. gpio_clear_inter <pin id> - Deletes the interrupt handler previously set on the given pin id.
  5. sha256 <value> - Computes the SHA256 of the given value.
  6. aes_set_iv <iv> - Sets the iv of a following AES encryption.
  7. aes_set_key <key> - sets the key of a following AES encryption.
  8. aes_cbc_enc <value> - Returns the AES encryption of a given string.
  9. aes_cbc_dec <value> - Returns the decryption of a given string.
  10. true_rand <n> - Returns a truly random number in the range 0-n.
  11. true_randstr <n> - Returns a true random string of length n.
  12. clock_set <command> <timeout> <period?> - Creates a clock that executes the command after the timeout. If a period is specified, the command will be executed again after that period. The command returns the number of the clock used. Both times are specified in milliseconds.
  13. clock_clear <clock_id> - Clears the clock with the given id, which is returned by the previous commend.

All gpio commands currently support only LED0, LED1, BUTTON0 and BUTTON1, but may be expanded in the future.

Demonstration

All demonstrations are also available in the DEMO.tcl file.

General tcl commands

+ 1 1

set x 0
incr x
puts $x

if {!= $x 0} {puts "hello"} else {puts "world"}

for {set i 0} {< $i 5} {incr i} {puts [* 2 $i]}

proc foo {arg1} {puts $arg1}
foo "me"

TRGN/ENC/DEC usage

set key [true_randstr 16]
set iv [true_randstr 16]

aes_set_key $key
aes_set_iv $iv

set crypt [aes_cbc_enc "Hello world"]
aes_cbc_dec $crypt

sha256 "hello world"

GPIO

setgpio 6 1
getgpio 6
setgpio 6 0

proc flip_gpio {pin} {set x [getgpio $pin]; setgpio $pin [! $x]}

gpio_set_inter 13 {flip_gpio 6}
gpio_set_inter 14 {flip_gpio 7}

set pushes 0

gpio_clear_inter 13
gpio_set_inter 13 {uplevel 1 {incr pushes}}

Clock

clock_set {flip_gpio 6} 1000  1000
clock_clear 0