BASIC Stamp clone

one BASIC Stamp can directly program another
(c) 1998, 2000, 2005  EME Systems, Berkeley CA U.S.A.
<stamp index> <home>

Contents: (updated 5/26/2005)

If you are interested in the meaning of the PBASIC tokens, I highly recommend Brian Forbes' book.


Clone.BS2: BS2 programing a BS2

top

Below is a program that allows one BS2 to program another. I wrote this program as an exercise to explore how the BS2 programming algorithm works. It turned out to be very useful. Sometimes I have customers who need an upgrade of the firmware in their OWL2c data logger, but I do not dream of asking them to fire up the programming software on a PC out at the field site. Instead, I can now send them a small "BS Cloner", which they only need to plug into the serial port of the data logger and press one button to accomplish the firmware update. This has evolved from a program for the BASIC Stamp into a small versatile module, the Stache.

The insights did not come without an effort. The protocols are not published in the Parallax literature. Note: with the introduction of the new Windows IDE, and advanced programming tools and tokenizer libraries, Parallax has now documented the protocols described here. Check the developer tools on the Parallax web site.  I used a Tandy M102 as a "sniffer" to capture the codes sent by the STAMP.EXE program to the stamp2 during the programing operation (ALT-R), and also I used the T102 to "sniff" the replies sent back by the stamp2. An oscilloscope was necessary to resolve some timing issues. A very similar protocol is used by the BS2sx, the BS2e the BS2p and the BS2pe  and the BS2px.

The programming mode is invoked by first resetting the target while holding its RS232 receive line in a high break state for 0.1 second. Then the target has to hear the string "BS2" followed by a null byte. Then the data can follow, in a specific block structured format: Each block consists of the starting address of the block, then 16 bytes of data, and then a checksum at the end of each block. The data is simply an image of what is to be programmed into the eeprom, and is the same hex data you see if you choose the (ALT-M) detailed memory map in STAMP2.EXE . There are 128 blocks of 16 characters in the 2k eeprom memory of the BS2. The block address is a number between 128 (for block 0) and 255 (for block 127). The checksum that follows each block is the usual twos complement sum of the data and address bytes. It is only necessary to send blocks that contain program or data. Thus it is possible to leave some blocks untouched in the target Stamp. The programming terminates when the target receives a null in the address position. The target BS2 echoes back all the characters it receives passively back to the master. The target BS2 also actively sends back some responses that are critical to the successful programming process.

What the program listed below does, is that it fools the target BS2 into thinking that it is connected to a PC running STAMP.EXE, when it is really just connected to another BS2. The program takes up 100+ bytes of eeprom, so there must be at least that much free above the main program. In this example, all the main program does is to wink an led attached to P15. It also monitors the status of a switch attached to P14, and branches to the cloning routine when P14 goes to a high level. That is the trigger for cloning. After the cloning is complete, the target will start running the same program. That is, if an led is attached to its pin 15, that led will wink. The target stamp does not have to be prepared in any way to receive the program.

In version 1.1 of the program I added a wire for feedback from the target BS2 back to the master. The master now looks for a handshake pulse to come back from the target after each packet is transmitted, before sending the next. In the previous version, I ran it "open loop" with a 5 millisecond delay at that point, which was fine for the BS2s that I tested. (3 milliseconds was not enough delay for eeprom programming--the eeprom programming spec is 10 milliseconds maximum). But you never know... slow eeprom, low temperature. As a bonus, the feedback allows the primary BS2 to signal whether the cloning was successful or not.

' CLONE.BS2  rev 1.1
' (c) 1998 Tracy Allen, emesys
' allows one BS2 to program another
' by invoking the ALT-R algorithm.
' "MASTER" programs "TARGET" with
' an exact copy of its eeprom.
' Connections:
' --------- ---------
' | td|6----------->2|rd |
' | rd|7<-----------1|td |
' | rst|5----------->3|atn |
' | PRIME | | |
' | BS2 | | CLONE |
' |trigger|19--<0/1 | BS2 |19---------;
' | wow|20-->|-/\/-; | |20-->|-/\/-;
' --------- led 1k | --------- led 1k |
' | |
' ground ground
' The switch on pin 19 (in14) goes high to trigger
' programming of the CLONE. The "wow" led is an
' indicator to show progress, completion or failure.

rd con 2 ' handshake in from clone
td con 1 ' data out to clone
rst con 0 ' reset out to clone
wow con 15 ' led indicator

trigger var in14 ' in14=1 triggers cloning

cksm var word ' checksum
' also block address
' also handshake
bite var byte ' for data from eeprom
ix var byte ' index 128 blocks
jx var nib ' index 16 bytes/block

' Substitute your own program for "spain" below.
' All "spain" does is flash an led, and monitor an
' input to trigger the cloning routine.
'
spain:
freqout wow,1000,1
branch trigger,[spain,clone]
clone:
high td ' create break on rs232 line
pulsout rst,5 ' reset the clone-to-be
pause 100 ' hold the break condx
serout td,$4054,2,["BS2",0] ' send preamble
' "BS2null". sent here open loop;
' no error trapping.
pause 1 ' pacing.
for ix=0 to 127 ' send 128 blocks of 16 bytes
' total 2048 bytes
' can be modified to send only
' occupied blocks (per ALT-M).
cksm=ix+128 ' initialize checksum
' first block is adrs 128.
serout td,$4054,[cksm] ' send block adrs.
for jx=0 to 15 ' 16 bytes per block.
read ix*16+jx,bite ' get byte from adrs.
cksm=cksm+bite ' update checksum.
serout td,$4054,[bite] ' xmit byte to clone.
next ' next byte.
serout td,$4054,[-cksm//256] ' xmit checksum.
' now, target programs this eeprom block
' which usually takes 3-4 milliseconds.
' It returns a 0-1-0 pulse (ascii 0)
' when it is ready for next block.
pulsin rd,1,cksm ' wait for handshake
if cksm=0 then failed ' failed if no handshake..
toggle wow ' flip the indicator.
next ' next block.
serout td,$4054,[0] ' xmit null to clone.
pulsout rst,5 ' reset clone.
'
' now just pass time, wait for trigger to be rearmed.
' the "wow" led on the clone should now be pulsing too.
finish:
freqout wow,1000,2 ' pulses 2/sec for success.
branch trigger,[spain,finish]
failed: high wow ' stays high to signal failed.
branch trigger,[spain,failed]
end

Here are details of the complete exchange between a host PC and the BASIC Stamp II:

  1. host sets td line high
  2. host resets target
  3. host holds td line high for 100 ms (break)
  4. host sends 66 "B"
  5. ---target responds with 190    (=256-66)
  6. host sends 83 "S"
  7. ---target responds with 173    (=256-83)
  8. host sends 50 "2"
  9. ---target responds with 206    (=256-50)
  10. host sends 0 null
  11. ---target responds with 16     (version number)
  12. host sends 18 byte packet address,data0,....data15,checksum
  13. ---target responds with 0 null
  14. host sends up to 128 packets as in step 12
  15. ---target responds with 0 after each packet
  16. host sends 0 in the address position
  17. ---target responds with 0
  18. host resets the stamp-program in stamp starts running

Responses from the target during the "BS2" preamble have to happen pretty fast, within a few milliseconds. I know that if the responses are too slow, or if the responses of the target are different, you usually get the "hardware not found" error. The 16 that follows the null is the version number from the target. For example, if the STAMP2.EXE program gets a 64 instead of a 16, it warns, "found hardware v 4.0, only v1.x supported". 64/16=4. You can trick it to find up to version 8. (in the year 2099?)

The addresses go from 128 up to 255, corresponding the 128 blocks of 16 bytes in the eeprom. The STAMP2.EXE program only sends blocks that are used. For example, in my tests I concocted a program that had a little data in eeprom, and a short program. STAMP2.EXE sent only blocks with addresses 128, 252 and 255. The actual data bytes in each 16 byte packet correspond exactly with what you see line by line when you press ALT-M in STAMP.EXE. The stamp makes a distinction between defined and undefined data. For example,

cats data (32)            ' 32 bytes of undefined data is not uploaded
dogs data 1(32) ' 32 bytes of defined (=1) data is uploaded
rats data 88,73,255,0 ' more defined data is uploaded

If any byte within a block is defined data or program, then the whole block of 16 is uploaded, with the undefined parts set equal to zero. The checksum, the 18th byte in the packet, is calculated in the usual way and includes the address byte, per CLONE.BS2.

The target responds with an ascii null after each packet. This presumably is based on an internal program and verify(?) routine in the target. Programming the eeprom takes about 3 to 4 milliseconds, 10 milliseconds worst case. The handshake serves to pace the flow of data from the host to the BS2.

The checksum for each block is the twos-complement of the sum of all the 17 bytes of address and data,

 

The BS2SX, BS2e and BS2P programming protocol

top

When you are running the DOS version of the Stamp software, STAMP2SX.EXE, STAMP2e.EXE or STAMP2P.EXE, the ALT-R command transfers the active program into the memory of the BASIC Stamp, one program bank at a time. The program banks are selected using the ALT-n command.

In Windows, STAMP2W.EXE, version 1.9 or later, the action is initiated with CTRL-R, or with a menu or task bar action. It is possible to organize the separate programs for each bank into a project, using the $STAMP directive. Also, you can choose to send to the Stamp (with the RUN command) 1) all the programs associated with a project, 2) only those programs that have changed since the previous RUN, or 3) only the program currently in the top editor window.

The software is described in the Parallax documentation and elsewhere

The protocols for the BS2sx,  BS2e, BS2P, BS2pe, and BS2px are almost exactly the same except as noted below. The protocol for the BS2 is actually the most complicated. The new multibank stamps have one element that is not in the original BS2 protocol, that is, the target bank number for each program in a project. As far as the BASIC Stamp itself is concerned, there is no direct link between the programs that comprise a multibank project. Each of those programs comes into the BASIC Stamp as a separate entity that contains the target bank number.

The HEX code that is actually loaded into each bank of the EEPROM can be viewed in the "Detailed EEPROM Memory Map". (CTRL-M windows, ALT-M dos). As with the original BS2, the 2k-bytes in each program bank are grouped into blocks of 16 bytes, and these show up as individual lines in the memory map. The RUN command always sends complete blocks of 16 bytes, but it only sends those blocks that have at least one byte occupied by program code or defined data (remaining bytes in the block filled with zeros). Blocks of 16 bytes that do not contain program code or defined data are not sent when a program is RUN. Those bytes are untouched in the target Stamp. The whole programming algorithm is built around transmitting a header, followed by up to 128 blocks of data that include an address and a checksum for each block.

So, each program bank in a BS2SX, BS2e or BS2p BS2pe, BS2px contains 2048 bytes of EEPROM, organized as 128 blocks of 16 bytes. Data from DATA statements builds up from address zero, while the program builds down from address 2047. The BS2SX/e/P/pe/px contains 8 such banks, each with 2048 bytes of EEPROM. The bank number is sent as part of the programming header.

Here is the programming protocol for the BS2pe.  See below for the differences Stamp to Stamp.  The communication takes  place at 9600 baud, except for the BS2px, which communicates at 19200 baud.  Remember that the Stamp passively echoes all activity of the txd line.  The Stamp also will actively transmit back handshakes to the PC as noted here.

  1. PC sets its transmit data line high, and resets the Stamp by pulsing the ATN line high.
  2. PC continues to hold the transmit line high for 0.05 to 0.1 second (BREAK condition)
  3. PC brings transmit line low, ending the BREAK condition  (The Stamp is is at this point reset in programming mode)
  4. PC transmits ascii character  "I" [a different letter is used for each Stamp] 
  5. BS2pe transmits back the ascii character "j" (24 pin) or "J" (40 pin OEM) (actually transmitted, not just the passive echo) [different for each Stamp and different for firmware version numbers.]
  6. PC transmits ascii character from 0 to 7, the bank # to be programmed
  7. PC transmits the block number as one byte from 128 to 255 (offset from 0 to 127). It only transmits blocks that contain program or defined data. All other blocks are left undisturbed.
  8. PC transmits the 16 bytes of data in the block.
  9. PC transmits a checksum, -(sum of 17 bytes mod 256)
  10. Stamp transmits back an ascii null (handshake)
  11. PC transmits next block address, block data and checksum
  12. Stamp transmits back an ascii null
  13. repeat steps 11 and 12 for all occupied blocks
  14. PC sends ascii null in the block address position to terminate the process.
  15. Stamp transmits back an ascii null.
  16. PC sets its transmit line low, and resets the Stamp by pulsing the ATN line high.

This algorithm is almost identical to the algorithm for the vanilla BS2, except in the preamble:

In the windows version of the software, an entire project, consisting of up to 8 program banks, can be programmed into a BS2sx or BS2e with one RUN command. The sequence consists of one repetition of the above sequence for each bank. As for he Stamp, it is receiving each bank independent of the others.

The new IDE (version 1.33 and above), actually tests the PC ports to see what stamps might be connected there, and recognizes them when it finds them. It does that by sending out all the above pings in sequence, until it receives a matching response. It trys that on all of the available serial ports in turn. This process happens quite rapidly, as the PC repeatedly pulses the reset line and tries a new combination. The trial always starts with the stamp type that is defined in the current open window. The Stache module emulates any Stamp, so it always responds "present" to any ping for any type of stamp.

Cloning banks in the BS2p or BS2pe, using STORE

top

The new command STORE in the BS2p and BS2pe make cloning a program from one Stamp to another much easier. A program running in bank 0, say, can copy itself to bank 7. Or, a program running in bank 0 can receive data from the serial port and WRITE that data directly into bank 7, and then run it as a program. (A checksum would probably be a good idea!)  This allows programming a Stamp over a modem or RF connection.

' {$STAMP BS2P}
' {$PBASIC 2.5}
' CloneP07.bsp for bank 0 or BS2p
' copies a program in bank 0 over to bank 7
' and then runs it from bank 7
'
x VAR byte
i VAR Word
READ 127,x ' retrieve current bank number
IF x & $f = 7 THEN
DEBUG CR,"Now running in bank 7",CR, bell
STOP
ELSE
FOR i=0 to 2047
STORE 0
READ i,x
STORE 7
WRITE i,x ' this is what takes time, ~ 5 milliseconds
DEBUG home,dec i ' show progress
NEXT
RUN 7
END


<top> <index> <home> logo < mailto:info@emesystems.com>