Skip to content

Introduction

Charmed Labs edited this page Sep 26, 2013 · 2 revisions

Building

Currently, embedded development is done using the ARM uVision V4.20 IDE with RealView compiler. PC-side development is done in the Qt application framework.

Debug Serial

Connector J7 on the PCB is debug serial out. It is recommended with the Rev. 1.0 PCB to solder the connector on the opposite side of the soldermask (Camera side of PCB) to avoid the power and RC-servo connectors getting in the way of the USB to serial board. This USB to serial board is cheap and works well:

https://www.sparkfun.com/products/718

Currently the software sets the debug baud at 115K (8-bit data, 1 stop bit, no parity, no flow control). I discovered this recently-- it's a no nonsense terminal program:

Windows http://freeware.the-meiers.org/CoolTermWin.zip Mac http://freeware.the-meiers.org/CoolTermMac.zip

Remote procedure call interface

We're using a custom RPC framework called Chirp (Call Hopefully Informative Remote Procedure) for communication between processors. Chirp is used in 2 places:

  • Communication between PC and Pixy (M4 core) over USB in "hi-speed" mode (10M bytes/sec on average)
  • Communication between M4 and M0 ARM cores over shared memory

The biggest advantage of Chirp is that it's simple and easy to add procedures. It doesn't require you to write stub code. It's a binary interface, so it's quick. It supports enumerating the available procedures (service discovery), does type checking of arguments, and supports custom datatypes. The data interface is abstracted, a simple read/write interface so you can chirp across various physical interfaces. Currently, Chirp over USB and shared memory is tested and working. Support for serial, I2C and SPI will be added and will include error detection/correction.

Here's a simple example--- from the caller end there are 2 steps:

  1. Query the procedure by name. This takes place only once, upon initialization: getFrame = getProc("getFrame", NULL);

this gets the index for the procedure called getFrame and puts it in a variable. The NULL variable is a callback procedure, if you want asynchronous operation, you can have the result returned in the callback procedure without having to block/wait.

  1. Call the procedure as desired:
helloresult = call(SYNC, getFrame,
              UINT16(x_offset), UINT16(y_offset), UINT16(width), UINT16(height), END_OUT_ARGS,
              &frameLen, &frameData, END_IN_ARGS);

here we call getframe with 4 arguments and get the result in 2 variables, one for the size of the frame result and one for the frame data. We specified SYNC which means that we wish to block/wait for the result. If we had specified ASYNC, we would get the result in the callback procedure we passed into getProc(). The result will tell us if chirp call succeeded or not (error, timeout, etc.)

From the callee end, there are 3 steps:

  1. Register the procedure. This is done once upon initialization: setProc("getFrame", (ProcPtr)getFrame);

  2. Define the procedure:

void getFrame(Chirp *chirp, UINT16_IN(x_offset), UINT16_IN(y_offset), UINT16_IN(width), UINT16_IN(height))
{
  // code to get frame 

  // set result to send back
  CRP_RETURN(chirp, frameLen, frameData);
}
  1. Call the service method periodically: chirp->service();
Clone this wiki locally