Didn't he publish the source in an earlier message in this thread? I think we already know what he came up with. :-)
Exactly! I read every word Chip wrote, four times over. I also copied the monitor code and examined every line carefully. I'm totally excited about the monitor in ROM, for all the reasons Chip has given. I've had enough of fancy chips that require a 2GB IDE and a $500 programming pod...just to squeeze out "Hello World." This one feature gives the Prop2 a giant leap forward in being able to host its own development system.
Exactly! I read every word Chip wrote, four times over. I also copied the monitor code and examined every line carefully. I'm totally excited about the monitor in ROM, for all the reasons Chip has given. I've had enough of fancy chips that require a 2GB IDE and a $500 programming pod...just to squeeze out "Hello World." This one feature gives the Prop2 a giant leap forward in being able to host its own development system.
I don't understand. A monitor is not a development system. You'll still need a tool on the host to compile or assemble code and download it into the P2 chip. This is really no different from the way P1 works. I guess you could use the monitor as a "development environment" if you like entering your code in hex. Is that what you mean?
One could do what Sun Microsystems did with their workstation. Allow users to boot up into a Forth system to run diagnostics and such. But I don't think that would be appropriate for the P2 since it has no flash and is just a micro controller. There are plenty of engineers who know how work with such chips using C and since it has not JTAG port, one doesn't have to worry about a expensive program dongle.
It is more universally accessible than the binary/HMAC-signed downloader because it sends and receives only standard ASCII characters $20..$7E (space.."~").
Some programming languages, serial interfaces, and OS's have issues with sending and receiving full binary ($00..$FF). For this reason, you might have to jump through some hoops to get the more-efficient binary downloader working on a given host system. The monitor, on the other hand, can talk to anything that speaks serial, without concern over non-ASCII characters. It is so simple that it can't NOT work on any host machine that has a serial port. Plus, it doesn't force an ordered protocol, but is conversational in operation. I've been using the Parallax Serial Terminal program to talk to it as well as PUTTY, which is free on the 'net and very tidy.
My thinking might be a little anachronistic, but I've seen many host-level systems which are big on brains and storage, but for which the serial interfaces were fleeting afterthoughts, and full binary can trigger unwanted events. The monitor will play politely and offer no offense to any host.
The reason I put a help menu in the monitor was so that you could quickly get command syntax without having to refer to any documents. You might launch the monitor from within an app you want to debug and you'll need to search memory for a string of data to get your bearings. The help menu will be handy then.
Here is the ROM now:
=== Propeller II Monitor ===
>0.e7f
00000- 5072 6F 7032 2E 30200020 7C 0C 03 D0 7C 0C 'Prop2.0 . |...|.'00010- 45 FE C1 0D E3 B6 FC 0C 01 C2 7C 0C 01 C2 7C 0D 'E.........|...|.'00020- 01 C2 FC 80 1F C2 7C 6201 E0 FC 3066 0C A8 80'......|b...0f...'00030- 01 CA 7C 0C 2A DE FC FA 5B C0 FC 1C 7C FA BC A0 '..|.*...[...|...'00040- 5B C0 FC 1C 7C FA BC 8001 FA FC 28 FA F0 FC A0 '[...|......(....'00050- 5B C0 FC 1C 01 C8 7C 62 2A 0064 1C B2 C8 7C 61'[.....|b*.d...|a'00060- 01 C8 FC 3410 F0 FC F6 02 F1 FC A0 08 F0 7C 86'...4..........|.'00070- 52 C8 E8 A0 01 C8 7C 622552 FC 1C DA B4 FC 0C 'R.....|b%R......'00080- 2552 FC 1C DF B4 FC 0C 2552 FC 1C DB B4 FC 0C '%R......%R......'00090- 2552 FC 1C B2 C8 7C 6101 C8 FC 3417 F0 FC F6 '%R....|a...4....'
000A0- 3500 7C 1C 0D F6 FC 0C 62 F6 BC 8063 C6 BC FF '5.|.....b...c...'
000B0- 37 4F FC 0C 0000 4C 1C 04 F0 FC A0 DB B2 FC 0C '7O....L.........'
000C0- DA B0 FC 0C 44 3E C0 0D DA B2 FC 0C 01 F0 7C E1 '....D>........|.'
000D0- 01 CA CC 27 DC AE FC 0C DB B0 FC 0C DA B0 FC 0C '...'............'
000E0- 2B F0 FC F6 B2 D8 7C 0C 66 F0 BC A0 20 F2 FC A0 '+.....|.f... ...'
000F0- 5B C0 E8 1C D6 AC D4 0D DB B0 D4 0C DA B0 D4 0C '[...............'00100- 01 F4 FC 3438 F2 FC F6 C1 F4 7C 0837 F0 FC F6 '...48.....|.7...'00110- 40 0E C0 0D 700004 E0 C1 EC 5308 6B F0 3C 08'@...p.....S.k.<.'00120- E0 02 FC 0C 6B D4 3C 0C 670004 E0 03 F0 FC A0 '....k.<.g.......'00130- 6B EC 1308 6B F4 BC 0A 49 F4 7C FA 48 F0 FC F6 'k...k...I.|.H...'00140- 03 1C 7C 0C 42 0E C0 0D E0 00 FC 0C 30 F2 FC 08'..|.B.......0...'00150- C1 F4 FC 08 7A F2 2886 6D D8 28 0C 41 FE FF 0F '....z.(.m.(.A...'00160- 01 DC 7C 0C C1 F0 7C 08 C1 F0 7C 0871 E0 BC 6A '..|...|...|.q..j'00170- 73 E4 A8 6A 08 DC D4 A0 6F DC 3C 0C 2552 FC 1C 's..j....o.<.%R..'00180- 0D F8 FC 0C 2552 FC 1C 0C F8 FC 0C 7D F8 3C 85'....%R......}.<.'00190- 0000 7C 1C 00020000 C0 C6 2D 0000000008'..|.......-.....'
001A0- 5000000000000003000200008016 1E 40'P..............@'
001B0- 80 0E BE 8F A0 1600 C0 D0 010000 C0 160000'................'
001C0- 80 0E 00008016000010070000 5B B4 0000'............[...'
001D0- CA E0 FD 0C 4696 FC 1C 00 9E FE 0802 9E 7E F8 '....F.........~.'
001E0- B3 9E 7E 0C 4F CB BD A0 02 CA FD 2C 13 CA FD 28'..~.O......,...('
001F0- 01 CA FD 80 1E 9E FE 280800 7C 0C 10 9E FE F4 '.......(..|.....'00200- 1D 9E FE F4 21 9E FE F4 0030 7D 080200 7C 1C '....!....0}...|.'00210- 3596 FC 1C 00 9E FE A0 E4 CA 3D E1 C1 9F F2 01'5.........=.....'00220- 36 9E FE 6C 4C A6 FC 1C 110054 1C 41 1E C0 0D '6..lL.....T.A...'00230- 07 CF 15 E0 F6 EF 87 A0 9A EE 93 6C 01 C6 FD A0 '...........l....'00240- 0E 00 7C 1C C1 9F FE 01 4C A6 FC 1C 1D CA FD F6 '..|.....L.......'00250- 0E 00 7C 1C 2C C6 7D F8 3596 FC 1C 40 1E C0 0D '..|.,.}.5...@...'00260- E7 0E 16 E0 F6 EF 97 A0 54 2E FD 1C 40 0E C0 0D '........T...@...'00270- FF 0E 16 E0 F6 EF 97 A0 0F 99 FC 5460 C8 FD A0 '...........T`...'00280- 3596 FC 1C FF 0004 E0 08 CA FD A0 4106 C0 0D '5...........A...'00290- F6 9F 86 A0 08 9E FE 24 C1 9F 7E 00 2F CA FD F6 '.......$..~./...'
002A0- 0E 00 7C 1C E4 CC BD A0 03 CC FD 2C 80 9E FE A0 '..|........,....'
002B0- 4C A6 FC 1C E4 9E BE A0 3F 9E FE 6038 9E 7E 86'L.......?..`8.~.'
002C0- 00 9E FE A0 380054 1C 04 C8 7D 6108 CC F1 24'....8.T...}a...$'
002D0- E6 9E B2 A0 4C A6 FC 1C 3E 0054 1C 40 0E C0 0D '....L...>.T.@...'
002E0- F7 FE 15 E0 F6 EF 97 A0 40 0E C0 0D 9B EE 15 E0 '........@.......'
002F0- F6 EF 97 A0 00 C6 FD A0 00 C8 FD A0 0000 7C 1C '..............|.'00300- 4F 0F 3E 1401 C8 FD 8003 C8 7D 629998 A8 80'O.>.......}b....'00310- 3F C8 7D 620799 E8 5454 2E E9 1C 0000 7C 1C '?.}b...TT.....|.'00320- 53 5E C0 0D 0F 2F 16 E0 F9 01 0C E0 F6 EF 8B A0 'S^.../..........'00330- F7 9F 82 A0 0B 9E FE 24 F7 9F 82 6C 12 9E FE 20'.......$...l... '00340- 03 EE C3 28 4F EF 83 6C F6 EF 8380 0E 00 0C E0 '...(O..l........'00350- F6 9F 82 A0 4F A1 BE A0 02 A0 FE 24 4F A1 BE 6C '....O......$O..l'00360- 13 A0 FE 20 0A 9E FE 2850 9F BE 6C 4F EF 8380'... ...(P..lO...'00370- FB 01 0C E0 F6 EF 938040 0E C0 0D F7 8E 16 E0 '........@.......'00380- F6 EF 97 A0 64 7E C0 0D 074715 E0 4D 9F BE A0 '....d~...G..M...'00390- 4C 9F BE 6C 4B 9F BE 60 4D 9F BE 6C 4B A1 BE A0 'L..lK..`M..lK...'
003A0- 05 A0 FE 24 4B A1 BE 6C 0E A0 FE 24 4B A1 BE 6C '...$K..l...$K..l'
003B0- 19 A0 FE 2050 9F BE 80 F7 9F 8680 F6 9F 8680'... P...........'
003C0- 4E 9F BE 8049 A1 BE A0 48 A1 BE 6047 A1 BE 68'N...I...H..`G..h'
003D0- 49 9D BE A0 48 9D BE 68 4E A1 BE 6047 9D BE A0 'I...H..hN..`G...'
003E0- 0B 9C FE 2447 9D BE 6C 09 9C FE 2447 9D BE 6C '...$G..l...$G..l'
003F0- 16 9C FE 20 4E A1 BE 80 4D 9D BE A0 4C 9B BE A0 '... N...M...L...'00400- 4B 99 BE A0 4A 97 BE A0 4995 BE A0 4893 BE A0 'K...J...I...H...'00410- 4791 BE A0 4F 97 BE 80 4F 8F BE A0 50 8F BE 80'G...O...O...P...'00420- 40 0E C0 0D 47 EF 15 E0 F6 EF 97800000 7C 1C '@...G.........|.'00430- 0000000000020000 6A 6A 6A 6A 67 E6 09 6A '........jjjjg..j'00440- 85 AE 67 BB 72 F3 6E 3C 3A F5 4F A5 7F 52 0E 51'..g.r.n<:.O..R.Q'00450- 8C 6805 9B AB D9 83 1F 19 CD E0 5B 98 2F 8A 42'.h.........[./.B'00460- 91443771 CF FB C0 B5 A5 DB B5 E9 5B C2 5639'.D7q........[.V9'00470- F1 11 F1 59 A4 82 3F 92 D5 5E 1C AB 98 AA 07 D8 '...Y..?..^......'00480- 01 5B 8312 BE 853124 C3 7D 0C 5574 5D BE 72'.[....1$.}.Ut].r'00490- FE B1 DE 80 A7 06 DC 9B 74 F1 9B C1 C1 69 9B E4 '........t....i..'
004A0- 8647 BE EF C6 9D C1 0F CC A1 0C 24 6F 2C E9 2D '.G.........$o,.-'
004B0- AA 8474 4A DC A9 B0 5C DA 88 F9 765251 3E 98'..tJ...\...vRQ>.'
004C0- 6D C6 31 A8 C8 2703 B0 C7 7F 59 BF F3 0B E0 C6 'm.1..'....Y.....'
004D0- 4791 A7 D5 5163 CA 066729291485 0A B7 27'G...Qc..g))....''
004E0- 3821 1B 2E FC 6D 2C 4D 13 0D 38535473 0A 65'8!...m,M..8STs.e'
004F0- BB 0A 6A 76 2E C9 C2 8185 2C 7292 A1 E8 BF A2 '..jv.....,r.....'00500- 4B 66 1A A8 70 8B 4B C2 A3 51 6C C7 19 E8 92 D1 'Kf..p.K..Ql.....'00510- 240699 D6 8535 0E F4 70 A0 6A 1016 C1 A4 19'$....5..p.j.....'00520- 08 6C 37 1E 4C 774827 B5 BC B0 34 B3 0C 1C 39'.l7.LwH'...4...9'00530- 4A AA D8 4E 4F CA 9C 5B F3 6F 2E 68 EE 82 8F 74'J..NO..[.o.h...t'00540- 6F 63 A5 781478 C8 840802 C7 8C FA FF BE 90'oc.x.x..........'00550- EB 6C 50 A4 F7 A3 F9 BE F2 7871 C6 1200 2A 59'.lP......xq...*Y'00560- 2B 57 2C 4E 32 2E 3B 2F 55 3A A1 4D AD 4C AE 48'+W,N2.;/U:.M.L.H'00570- AF 54 B0 5A B1 52 9E 51 BD 3F 003800382024'.T.Z.R.Q.?.8.8 $'00580- 2E 3C 2F 53 3A 8240 8F 2A 96 2B 9F 2D AD 4C AE '.</S:.@.*.+.-.L.'00590- 48 AF 54 B0 5A B1 528023 B6 7C BB 5C 003900'H.T.Z.R.#.|.\.9.'
005A0- 3920 3D 2F 51 3A 5F 3E 5F 3C 77 5E 00 0D 0D 3D '9 =/Q:_>_<w^...='
005B0- 3D 3D 205072 6F 7065 6C 6C 657220494920'== Propeller II '
005C0- 4D 6F 6E 6974 6F 7220 3D 3D 3D 0D 0D 00 3F 20'Monitor ===...? '
005D0- 2D 204865 6C 70 0D 070048697420535041'- Help...Hit SPA'
005E0- 4345002020270027 0D 0020 2D 0D 80 7B 61'CE. '.'.. -..{a'
005F0- 6472 7B 2E 616472 7D 7D 80 7B 646174 7B 20'dr{.adr}}.{dat{ '00600- 646174 7D 7D 8061647280 0D 7E 485542 8E 'dat}}.adr..~HUB.'00610- 926056696577 0D 92 2F 9E 605365617263'.`View../.`Searc'00620- 68 0D 92 3A 9E 6045 6E 746572 0D AA 2E AA 5B 'h..:.`Enter....['00630- 3C 2F 3E 5D AA 60 4D 6F 7665 0D AA 2E AA 5E 60'</>].`Move....^`'00640- 43686563 6B 7375 6D 0D AA 406057617463'Checksum..@`Watc'00650- 68 0D 5B 59 2F 57 2F 4E 5D 6042797465 2F 77'h.[Y/W/N]`Byte/w'00660- 6F 7264 2F 6C 6F 6E 67 0D 7E 43 4F 4753 8E 63'ord/long.~COGS.c'00670- 6F 67 2B AA 7B 2B AA 7D 605374617274 0D 63'og+.{+.}`Start.c'00680- 6F 67 2D 605374 6F 70 0D 4D 60 4D 6170 0D 7E 'og-`Stop.M`Map.~'00690- 5049 4E 53 8E 7B 7069 6E 7D 5B 48 2F 4C 2F 54'PINS.{pin}[H/L/T'
006A0- 2F 5A 2F 52 5D 6048696768 2F 6C 6F 77 2F 74'/Z/R]`High/low/t'
006B0- 6F 6767 6C 65 2F 6F 6666 2F 72656164 0D 70'oggle/off/read.p'
006C0- 69 6E 23605761746368 0D 7069 6E 7C 6366'in#`Watch.pin|cf'
006D0- 676043 6F 6E 666967757265 0D 646174 5C 'g`Configure.dat\'
006E0- 605365742044414373 0D 7E 4D 495343 8E '`Set DACs.~MISC.'
006F0- 646174 2A 605365742063 6C 6F 63 6B 0D 27'dat*`Set clock.''00700- 60526570656174 0D 516051756974 0D 00'`Repeat.Q`Quit..'00710- 0000000040 3C C0 0D D7 0104 E0 00 EC D3 A0 '....@<..........'00720- 12 CC FF 0C 12 CE FF 0C 09 CE FF 28 DB CE 7F 0C '...........(....'00730- 9274 FF 0C CB 22 FC 0C 0A E6 7F F8 9456 FF 0C '.t...".......V..'00740- CB 32 FC 0C 01 C6 FF A0 D2 BE FD 1C AA 00 FC 0C '.2..............'00750- B2 A2 FC 0C 6F E3 FE 1C E9 1A FE 1C 2B 73 FE 1C '....o.......+s..'00760- 2F B0 6B F8 1900 7C 1C 0B 1B FE 1C A4 02 FC 0C '/.k...|.........'00770- 2B 73 FE 1C 1F 0054 1C DA 65 FD 54 B2 00 FC 0C '+s....T..e.T....'00780- C0 84 FD 1C B2 E4 FC 0C 1100 7C 1C DD B7 BF A0 '..........|.....'00790- E0 65 FD 54 B2 3E FC 0C C0 84 FD 1C 3800 7C 1C '.e.T.>......8.|.'
007A0- 2A 73 FE 1C 350068 1C DD B9 BF A0 B2 84 FC 0C '*s..5.h.........'
007B0- C0 84 FD 1C 3900 7C 1C 01 C6 FF A2 02 C6 EB A2 '....9.|.........'
007C0- 04 C6 EB A0 D2 BE FD 1C 1700 7C 1C 0F B8 FF A0 '..........|.....'
007D0- 49 DD FE 1C 1200 7C 1C FF B8 FF A0 49 DD FE 1C 'I.....|.....I...'
007E0- 1700 7C 1C FF B8 FF A0 4A DD FE 1C 1800 7C 1C '..|.....J.....|.'
007F0- DB B9 BF A0 4C DD FE 1C 1800 7C 1C DE B7 BF A0 '....L.....|.....'00800- E5 B9 BF A0 C7 A2 FD 1C 0E 45 FE 1C B2 B6 7F 0C '.........E......'00810- 000004 E0 00 B0 FF A0 E5 CC FD 1C F6 BB 0786'................'00820- 4B 0068 1C E3 B7 BF 80 DC B7 3F 87 3F 0078 1C 'K.h.......?.?.x.'00830- DB BD BF A0 E5 BD BF 601800 7C 1C E1 B1 BF E9 '.......`..|.....'00840- 4200 4C 1C E1 B9 BF A0 E4 B9 BF 2C DB B9 BF 80'B.L........,....'00850- 3900 7C 1C C7 A2 FD 1C 01 B2 FF A0 DB BF BF A0 '9.|.............'00860- E5 BF BF 60 0E 45 FE 1C 59 B2 7F FA E1 B5 BF A0 '...`.E..Y.......'00870- 01 B4 FF 80 B3 BE 7F 0C F6 BB 87 A0 E7 D0 FD 1C '................'00880- 5A B4 FF F6 13 BE FF 0C 1800 7C 1C D8 B3 BF A0 'Z.........|.....'00890- C7 A2 FD 1C 2753 FE 1C E5 BB BF 4C E5 BB BF 60'....'S.....L...`'
008A0- 3C B2 7F 86 DB B1 AB A0 DD B7 AB A0 D8 BB AB A0 '<...............'
008B0- DD B7 3F 85 DA B1 B3 A0 E4 B1 B3 2C D8 B7 B3 80'..?........,....'
008C0- D8 BB B3 80 7E CA F1 6C 7E CE F1 6C B2 B6 7F 0C '....~..l~..l....'
008D0- B3 BA 7F 0C E5 CC FD 1C E7 D0 FD 1C 71 B4 FF F6 '............q...'
008E0- 7E CA F1 6C 7E CE F1 6C 1800 7C 1C C7 A2 FD 1C '~..l~..l..|.....'
008F0- B2 B6 7F 0C E5 CC FD 1C DD B3 BF 8079 B4 FF F6 '............y...'00900- D9 BB BF A0 08 C4 FF A0 85 1B FF 1C 1600 7C 1C '..............|.'00910- E6 C6 FD 5201 C4 FF A0 E4 C6 E9 50 E3 C5 AB A0 '...R.......P....'00920- 01 C4 EB 2C E0 CC FD 1C DD B5 BF A0 85 1B FF 1C '...,............'00930- 90 3D FF 1C A2 55 FF 1C 160054 1C E0 CC FD 1C '.=...U....T.....'00940- DA BB 3F 86890068 1C 8600 7C 1C B2 FA FC 0C '..?...h...|.....'00950- 6F E3 FE 1C 00 B6 7F 0C 9F 43 FF 1C 20 B0 7F 86'o........C.. ...'00960- 920054 1C 1600 7C 1C E0 B6 7F 0C 2753 FE 1C '..T...|.....'S..'00970- DD B3 BF A0 00 BA FF A0 2B B0 7F 862753 EA 1C '........+...'S..'00980- DD B3 3F 0C 1800 7C 1C 01 B6 FF 0C 03 B6 7F 0C '..?...|.........'00990- 1700 7C 1C 07 B2 FF A0 90 3D FF 1C D9 B1 BF A0 '..|......=......'
009A0- 01 B0 FF 0D D9 B1 3F 8630 B0 CF A0 31 B0 F3 A0 '......?.0...1...'
009B0- 4D B0 EB A0 96 3D FF 1C 01 B2 FF 85 A2 00 4C 1C 'M....=........L.'
009C0- 1600 7C 1C DA 66 FD 52 DB 66 E9 52 D9 66 E9 52'..|..f.R.f.R.f.R'
009D0- D8 66 E9 52 D6 66 E9 50 DB C1 BF A0 D6 C0 7F 0D '.f.R.f.P........'
009E0- A5 0068 1C 1700 7C 1C 2753 FE 1C E3 B6 7F 0C '..h...|.'S......'
009F0- 23 B6 FF 0C DD B7 3F E8 1800 7C 1C D5 B6 7F 0C '#.....?...|.....'
00A00- 1700 7C 1C B2 5C FD 0C 6F E3 FE 1C 1600 7C 1C '..|..\..o.....|.'
00A10- B4 A4 7F 0C C1 B4 FF 0000 B4 7F F8 C1 B2 FF 00'................'
00A20- D8 B3 BF 6E C1 0054 1C DA 01 3C 1C E5 B7 BF 4C '...n..T...<....L'
00A30- E5 B7 BF 60 E5 B9 BF 4C E5 B9 BF 60 DB B9 3F 85'...`...L...`..?.'
00A40- 1D 0070 1C DC B5 BF A0 DB B5 BF 84 E4 B5 BF 28'..p............('
00A50- 01 B4 FF 800000 7C 1C 02 C6 7F 61 9A CB FD 0C '......|....a....'
00A60- 9A CF FD 0C 04 C6 7F 61 9B CB FD 0C 9B CF FD 0C '.......a........'
00A70- E3 C9 BF A0 01 C8 FF 28 E3 CB BF A0 01 CA FF 84'.......(........'
00A80- D3 CB BF 6C E5 BD BF 60 E5 BF BF 600000 7C 1C '...l...`...`..|.'
00A90- D6 B6 7F 0D 00 BA CF A0 01 BA F3 A0 E6 00 7C 1C '..............|.'
00AA0- B2 B6 7F 0C C1 BA FF 000000 7C 1C C1 BB 7F 00'..........|.....'
00AB0- 0000 7C 1C A2 00 FC 0C 3E B0 FF A0 96 3D FF 1C '..|.....>....=..'
00AC0- 9F 43 FF 1C 27 B0 7F 86 F4 0054 1C 18 B0 FF 0E '.C..'.....T.....'
00AD0- 96 3D D7 1C EF 0054 1C 0A 01 7C 1C 9F 43 FF 1C '.=....T...|..C..'
00AE0- 0D B0 7F 86090168 1C 08 B0 7F 86 7F B0 5786'......h.......W.'
00AF0- 010168 1C 20 B0 7F 85 7E B0 4F E1 F3 0070 1C '..h. ...~.O...p.'
00B00- AA B0 7F 0C 1600 7C 0D A6 02 F0 0C 96 3D CF 1C '......|......=..'
00B10- F3 00 7C 1C 1600 7C 0E A8 B0 57 0C 96 3D D7 1C '..|...|...W..=..'
00B20- 90 3D D7 1C 18 B0 D7 0C 96 3D D7 1C A6 02 D4 0C '.=.......=......'
00B30- F3 00 7C 1C AA 00 FC 0C A2 00 FC 0C D4 B1 BF A0 '..|.............'
00B40- 96 3D FF 1C 0000 7C 1C 00 AE FF A0 000004 E0 '.=....|.........'
00B50- 2A 73 FE 1C 23 4D D6 1C 20 B0 7F 86100168 1C '*s..#M.. .....h.'
00B60- 27 B0 7F 86 1E 0154 1C A4 04 FC 0C 1A B0 FF 0C ''.....T.........'
00B70- 27 B0 7F 86100168 1C 1E B1 7F F8 D8 BB BF A0 ''.....h.........'
00B80- 23 4D FE 1C 1601 7C 1C 01 AE FF 85 D7 C3 8F A0 '#M....|.........'
00B90- E1 43 BE 54000004 E4 0000 7C 1C 11 AE FF E9 '.C.T......|.....'
00BA0- 1D 0070 1C DD ED 93 A0 0000 7C 1C 2A 73 FE 1C '..p.......|.*s..'
00BB0- 1D 0068 1C 0000 7C 1C A4 02 FC 0C 00 BA FF A2 '..h...|.........'
00BC0- 3A 7D FE 1E 18 B0 FF 0C 3F 91 FE 1C 04 BA F3 2C ':}......?......,'
00BD0- D8 BB B3 68 2D 0170 1E A6 02 FC 0C 3A 7D FE 1E '...h-.p.....:}..'
00BE0- 3F 91 FE 1C 1A B0 F3 0C 60 B0 7F E1 7B B0 7385'?.......`...{.s.'
00BF0- 20 B0 F3 840000 7C 1C 18 B0 FF 0C 20 B0 7F 86' .....|..... ...'
00C00- 3A 0168 1C A6 02 FC 0C 0000 7C 1E 2F B0 7F E1 ':.h.......|./...'
00C10- 3A B0 738507 B0 F3 8040 B0 4F E1 47 B0 7385':.s.....@.O.G.s.'
00C20- 20 B0 F3 8060 B0 4F E1 67 B0 738557 B0 F3 84' ...`.O.g.s.W...'
00C30- 0000 7C 1C DE B7 BF A0 E5 B9 BF 60 DB B9 BF 80'..|........`....'
00C40- C7 A2 FD 1C DB BD BF A0 DE BB BF A0 05 C4 FF A0 '................'
00C50- 85 1B FF 1C 8E 3D FF 1C E3 B1 BF A0 1B B0 FF 3C '.....=.........<'
00C60- DA B7 BF A0 D8 B7 BF 4C DB B9 BF A0 E4 B9 BF 2C '.......L.......,'
00C70- DB B5 BF 84 B2 BC 7F 0C E5 CC FD 1C E3 C5 BF A0 '................'
00C80- 01 C4 FF 2C 85 1B FF 1C 90 3D FF 1C 5A B7 FF F6 '...,.....=..Z...'
00C90- B2 0E FD 0C 6F E3 FE 1C B2 BC 7F 0C C1 B0 FF 00'....o...........'
00CA0- 20 B0 7F 85 7E B0 4F E1 2E B0 F3 A0 96 3D FF 1C ' ...~.O......=..'
00CB0- 63 B9 FF F6 12 BC FF 0C B2 16 FD 0C 6F E3 FE 1C 'c...........o...'
00CC0- A2 55 FF 1C 4E B5 6B FA 0000 7C 1C B4 A4 7F 0C '.U..N.k...|.....'
00CD0- C1 B0 FF 0000 B0 7F F8 80 B0 7F 6228 E1 D6 0C '...........b(...'
00CE0- B3 B0 57 0C B5 A4 57 0C 700154 1C 60 B0 7F 86'..W...W.p.T.`...'
00CF0- 10 B2 EB E0 7E B0 578610 B2 EB 8090 3D EB 1C '....~.W......=..'
00D00- 7B B3 EB F6 8E 3D EB 1C 700168 1C 0D B0 7F 86'{....=..p.h.....'
00D10- 0B 1B EA 1C 00 B2 EB A0 96 3D D7 1C 01 B2 D7 80'.........=......'
00D20- 7001 7C 1C E2 B3 BF A0 02 B2 FF 2C D9 BB BF 20'p.|........,... '
00D30- E2 B3 BF A0 04 BA FF 24 DD B1 BF A0 92 3D FF 1C '.......$.....=..'
00D40- 89 B3 FF F6 0000 7C 1C D5 B1 BF A0 9601 7C 1C '......|.......|.'
00D50- 20 B0 FF A0 9601 7C 1C 0F B0 FF 60 0A B0 7F 85' .....|....`....'
00D60- 30 B0 F3 8037 B0 CF 8001 B0 FF 2C 69 B1 FF 0C '0...7......,i...'
00D70- 0D AE FF 0C F3 AF BF 80 0D AE 7F 0C 01 B0 FF 29'...............)'
00D80- DC CE 7F 0C 99 B1 7F FA 0000 7C 1C A2 55 FF 1C '..........|..U..'
00D90- 9F 0168 1C 0000 7C 1C 80 D0 FF 6817 D2 FF 0E '..h...|....h....'
00DA0- E8 D3 178616 D2 D7 0C A2 D0 57 0C 18 B0 D7 0C '..........W.....'
00DB0- 16 D0 D7 0C A2 D2 57 0C 0000 7C 1C 1700 7C 0E '......W...|...|.'
00DC0- A3 00 E9 0C 09 D8 FF A0 F3 D5 BF A4 01 D4 FF 38'...............8'
00DD0- B0 CD FF F8 0C D4 FF 0C 01 D6 FF 30 F3 D5 BF 80'...........0....'
00DE0- 0D D4 7F 0C D6 CC 7F 0D B2 D9 FF F6 18 D6 FF 28'...............('
00DF0- AB D6 7F 0C AB 01 7C 1C E6 AD BF 5425 AD FF 0D '......|....T%...'
00E00- F0 AC 7F 0C ED E1 8F A0 04 E0 CF 28 F0 E3 8F A4 '...........(....'
00E10- ED E1 8F 80 ED E3 8F 80 EE E5 8F A0 06 E4 CF 10'................'
00E20- F0 E5 0F E1 F1 E5 0F 85 EF E5 8F A0 03 E4 CF 10'................'
00E30- F0 E5 0F E1 F1 E5 0F 85 EF DB 8F 8003 DA CF 28'...............('
00E40- ED E7 8F A0 EE DB BF A0 EF DD BF A0 3A DE FF 0C '............:...'
00E50- BB DF 7F FA CF 01 7C 1C 5C 050000 FF FF 0100'......|.\.......'
00E60- 0D 280400 2D 8004008900000078 CF 68 9D '.(..-.......x.h.'
00E70- 3D 3D 2045 6E 6420 6F 662052 4F 4D 20 3D 3D '== End of ROM =='
It is now 128 bytes shorter than it used to be, since I've used this time during full-chip verification being done by Beau and Open Silicon to pack things more efficiently.
Here is the binary/HMAC-signed loader (it's only $70 longs and starts at $000):
'********************************************************'* *'* Propeller II ROM Booter *'* *'* Version 0.1 *'* *'* 11/01/2012 *'* *'********************************************************CON
rx_pin = 91
tx_pin = 90
spi_cs = 89
spi_ck = 88
spi_di = 87
spi_do = 86
base = $E80DAT''' Version (@$000)'byte"Prop2.0 "''' Shut down (@$008)'orgclkset h001+offset 'set clock to rc slowcogstop h200+offset 'stop cog0
offset
''' Entry, read fuses (@$010)'org
reps #256,@:fuse 'ready to read 256 fuses
setport #rx_pin 'set rx_pin port for bootingcogid fuse_read nr 'read fuses (172 fuses + 84 zeros)cogid fuse_read nr,wc'(last iteration initializes cnt to $00000000_00000001)add fuse_read,#1test fuse_read,#$1Fwz
:fusex rcr fuses,#1
:fuse if_zadd :fusex,h200
cogid spi_read nr 'disable fuses and enable cnt (spi_read[10..0] = 0)''' Attempt to boot from serial'
jnp monitor_ptr,#boot_flash 'if rx_pin is low, skip serial and boot from flashcall #rx_bit 'measure low rx calibration pulses (host $F9 -> %1..010011111..)mov threshold,delta 'and calculate thresholdcall #rx_bit '(any timeout results in flash boot)add threshold,delta
h001 shr threshold,#1'(9 lsb's are $001)mov count,#250'ready to receive/verify 250 lfsr bits
:lfsrin call #rx_bit 'receive bit ($FE/$FF) into ctest lfsr,#$01wz'get lfsr bit into nzif_c_eq_zjmp #boot_flash 'if mismatch, boot from flashtest lfsr,#$B2wc'advance lfsrrcl lfsr,#1djnz count,#:lfsrin 'loop for next bit inmov count,#250+8'ready to transmit 250 lfsr bits + 8 version bits
:lfsrout cmp count,#8wz'if last 8 bits, set lfsr so that version will be outputif_zmov lfsr,#$52'$52 results in version $20 being sent (%00000100)test lfsr,#$01wz'get lfsr/version bit into nz, z=1 on last iterationcall #wait_rx 'wait for rx low (convey incoming $F9 on rx_pin to $FE/$FF on tx_pin)
clrp #tx_pin 'make tx lowcall #wait_rx 'wait for rx high
setpnz #tx_pin 'make tx lfsr/version bitcall #wait_rx 'wait for rx low
setp #tx_pin 'make tx highcall #wait_rx 'wait for rx hightest lfsr,#$B2wc'advance lfsrrcl lfsr,#1djnz count,#:lfsrout 'loop for next bit outjmp #load 'serial handshake done, attempt to load from serial (z=1)''' Wait for rx low/high - if timeout, attempt to boot from flash'
wait_rx getcnt time 'ready timeoutadd time,timeout
:waitpxx waitpne rx_mask,rx_mask wc'wait for rx low/high with timeout
notb :waitpxx,#23'toggle waitpeq/waitpne
wait_rx_ret if_ncret'return if not timeout (boot_flash follows)''' Attempt to boot from flash'
boot_flash mov count,#4'ready for 3 resets and 1 read command
:cmd setp #spi_cs 'spi_cs high
clrp #spi_ck 'spi_ck low
reps #32,@:bit 'ready for 32 command bits
clrp #spi_cs 'spi_cs lowcmpr count,#1wc'first 3 commands = $FF_FF_FF_FF (reset)if_ncrol spi_read,#1wc,wz'last command = $03_00_00_00 (read from 0), z=0
setpc #spi_di
setp #spi_ck 'cycle spi_ck
:bit clrp #spi_ck
djnz count,#:cmd 'loop for next spi command''' Load from serial (z=1) or flash (z=0)'
load setptra loader_pgm 'load loader into base+$000..$7DF, HMAC into base+$7E0..$7FFmov count,h200 'ready to input $200 longs
:longmov bits,#32'ready to input 32 data bits
:bit if_zcall #rx_bit 'input serial bit (serial mode)if_nz getp #spi_do wc'input spi_do (flash mode)if_nz setp #spi_ck 'high spi_ck (flash mode)if_nz clrp #spi_ck 'low spi_ck (flash_mode)rcl data,#1'shift bit into longdjnz bits,#:bit 'loop, adequate time for next flash bitwrlong data,ptra++ 'store long in hub ram (ptra=base+$800 after)djnz count,#:long'loop for next long (count=0 after)''' Compute loader HMAC signature for loader authentication'' base+$000..$7DF = loader ($1F8 longs)' base+$7E0..$7FF = loader HMAC signature (8 longs)' base+$800..$81F = fuses, 1st half are HMAC key (8 longs)' base+$820..$83F = proper HMAC signature (8 longs)' base+$840..$843 = sha256 command interface (1 long)'
reps #8,#1'store 128-bit key + 44 extra fuses + 84 zero bits
setinda fuses 'into base+$800..$81Fwrlong inda++,ptra++ '(ptra = base+$820, afterwards)wrlong count,sha256_ptr 'clear sha256 command
setcog #1'launch sha256 in cog1coginit sha256_pgm,sha256_ptr
setinda begin_hmac 'do sha256 commands to compute proper loader hmacmov count,#3'ready for 3 commands: begin_hmac, hash_bytes, read_hash
:cmd wrlong inda++,sha256_ptr 'set command
:wait rdlong data,sha256_ptr wz'wait for command donetjnz data,#:wait
djnz count,#:cmd 'loop for next command (count=0, z=1 after)cogstop h001 'done with sha256, stop cog1''' If loader authenticates, run it'
reps #8,@:cmp'verify loader hmac signature (z=1 on entry)
setcog #0'ready to relaunch cog0 with loader/monitorrdlong bits,ptra[-$10] 'get loader hmac signature longrdlong data,ptra++ 'get proper hmac signature long
:cmpif_zcmp bits,data wz'compare, z=1 if authenticatedif_zcoginit loader_pgm,loader_ptr 'if loader authenticated, relaunch cog0 with loader''' Authentication failed, hide fuses and clear memory'
reps #$20000/8,@:clr 'clear all memorycogid monitor_pgm nr 'hide fuses (bit 10 set)wrlong count,ptra++ '(count=0)
:clr wrlong count,ptra++
''' If key <> 0, shut down - else, monitor'or fuses+0,fuses+1wz'check if 128-bit key = 0if_zor fuses+2,fuses+3wzif_nzmov monitor_pgm,#$008'if key <> 0, shut downcoginit monitor_pgm,monitor_ptr 'relaunch cog0 with shut down or monitor''' Receive bit (c) - compare incoming pulse to threshold'
rx_bit call #wait_rx 'wait for rx low
getcnt delta 'get timecall #wait_rx 'wait for rx high
subcnt delta 'get time deltacmp delta,threshold wc'compare time delta to threshold
rx_bit_ret ret''' Constants'
fuse_read long$200'(gets modified to $300)
timeout long20_000_000 / 1000 * 150'150ms @20MHz (rcfast)
rx_mask long1 << (rx_pin & $1F)
lfsr long"P"
spi_read long$03_000000
h200 long$200
begin_hmac long1<<30 + (($004<<2)-1)<<17 + base+$800'begin_hmac, loads key at base+$800 (4 longs)
hash_bytes long2<<30 + (($1F8<<2)-1)<<17 + base+$000'hash_bytes, hashes message at base+$000 ($1F8 longs)
read_hash long3<<30 + base+$820'read_hash, writes hash at base+$820 (8 longs)
sha256_pgm long$1D0'sha256 program address
sha256_ptr long base+$840'sha256 parameter (points to command)
loader_pgm long base+$000'loader program address
loader_ptr long base+$800'loader parameter (points to fuses)
monitor_pgm long$55C+$1B4'monitor program address
monitor_ptr long tx_pin<<9 + rx_pin 'monitor parameter (conveys pins)''' Variables'
fuses res8
count res1
bits res1
data res1
time res1
delta res1
threshold res1
Here is the SHA-256/HMAC program used to authenticate code (thanks to Pedward for making this happen):
'********************************************************'* *'* Propeller II ROM SHA-256/HMAC *'* *'* Version 0.1 *'* *'* 11/01/2012 *'* *'********************************************************'' Usage: commandlong := 0 'pre-clear command long' cognew($1D0, @commandlong) 'start SHA-256/HMAC in new cog'' Start here for HMAC: commandlong := 1<<30 + (keysize-1)<<17 + @key 'start HMAC with key of keysize bytes (1..64)' repeat while commandlong '(wait for command done)'' Start here for SHA-256: commandlong := 2<<30 + (msgsize-1)<<17 + @msg 'hash msg of msgsize bytes (1..8192)' repeat while commandlong '(wait for command done)'' {issue more 2<<30 commands if msg > 8192 bytes}'' commandlong := 3<<30 + @hashbuffer 'read resulting hash into hashbuffer (32 bytes)' repeat while commandlong '(wait for command done)'' {hasbuffer now contains result, ready for new 1<<30 or 2<<30 command}'DATorg
setf #%0_1111_0000'configure movf for sbyte0 -> {dbyte3,dbyte2,dbyte1,dbyte0,dbyte3,...}call #init_hash 'init hash, clear hmac mode, reset byte count''' Command Loop'
command rdlong x,ptra'wait for command (%cc_nnnnnnnnnnnnn_ppppppppppppppppp)tjz x,#command
setptrb x 'get pointer (%ppppppppppppppppp)mov count,x 'get count (%nnnnnnnnnnnnn)shl count,#2shr count,#2+17add count,#1'+1 for 1..8192 rangeshr x,#32-2'get command (%cc)
cachex 'invalidate cache for fresh rdbytec'sdjz x,#begin_hmac '1 = begin hmac, pointer @key (count+1 bytes, 1..64)djz x,#hash_bytes '2 = hash bytes, pointer @message (count+1 bytes, 1..8192)djz x,#read_hash '3 = read hash, pointer @hashbuffer (32 bytes)
done wrlong zero,ptra'clear command to signal donejmp #command 'get next command''' Begin HMAC'
begin_hmac call #end_hash 'end any hash in progress
:ipad mov x,#$00'get and hash ipad key (full block)cmpr count,bytes wc'after key bytes, hash $00's to fill blockif_c rdbytec x,ptrb++
xor x,#$36'xor bytes with ipad ($36)call #hash_byte '(last iteration triggers hash_block, z=1)if_nzjmp #:ipad
reps #16,#2'save opad key
setinds opad_key,w
mov indb,inda++
xor indb++,opad 'xor bytes with opad ($5C)mov hmac,#1'set hmac modejmp #done
''' Hash Bytes'
hash_bytes rdbytec x,ptrb++ 'hash bytescall #hash_byte
djnz count,#hash_bytes
jmp #done
''' Read Hash'
read_hash tjz hmac,#:not'if not hmac, output hashcall #end_hash 'hmac, end current hash
reps #16,#1'get opad key into w[0..15] (full block)
setinds w,opad_key
mov indb++,inda++
call #hash_block 'hash opad key
reps #8,#1'get hashx[0..7] into w[0..7]
setinds w,hashx
mov indb++,inda++
movd hash_byte,#w+8'account for opad key and hashx bytesmov bytes,#64+32'(1-1/2 blocks, 1/2 block needs end_hash)
:notcall #end_hash 'end current hash
setinda hashx 'store hashx[0..7] at pointer, big-endianmov count,#8
:out reps #4,#2mov x,inda++
rol x,#8wrbyte x,ptrb++
djnz count,#:out
jmp #done
''' End Hash - hash $80, any $00's needed to get to offset $38, then 8-byte length'
end_hash mov length,bytes 'get message length in bitsshl length,#3mov x,#$80'hash end-of-message byte ($80)
:fill call #hash_byte '(may trigger hash_block)mov x,bytes 'hash any $00's needed to get to offset $38and x,#$3Fcmp x,#$38wzmov x,#$00if_nzjmp #:fill
:len test bytes,#$04wc'hash 8-byte length, big-endianif_crol length,#8'(hash four $00's, then four length bytes)if_cmov x,length
call #hash_byte '(last iteration triggers hash_block)if_nzjmp #:len
reps #8,#1'save hash[0..7] into hashx[0..7]
setinds hashx,hash
mov indb++,inda++
init_hash reps #8,#1'copy hash_init[0..7] into hash[0..7]
setinds hash,hash_init
mov indb++,inda++
mov hmac,#0'clear hmac modemov bytes,#0'reset byte count
init_hash_ret
end_hash_ret ret''' Hash Byte - add byte to w[0..15] and hash block if full (z=1)'
hash_byte movf w,x 'store byte into w[0..15], big-endianadd bytes,#1'increment byte counttest bytes,#$03wz'every 4th byte, increment w pointerif_zadd hash_byte,d0
test bytes,#$3Fwz'every 64th byte, reset w pointerif_z movd hash_byte,#w
if_zcall #hash_block 'every 64th byte, hash block
hash_byte_ret ret''' Hash Block - first extend w[0..15] into w[16..63] to generate schedule'
hash_block reps #48,@:sch 'i = 16..63
setinds w+16,w+16-15+7'indb = @w[i], inda = @w[i-15+7]
setinda --7's0 = (w[i-15] -> 7) ^ (w[i-15] -> 18) ^ (w[i-15] >> 3)mov indb,inda--
mov x,indb
rol x,#18-7xor x,indb
ror x,#18shr indb,#3xor indb,x
add indb,inda 'w[i] = s0 + w[i-16]
setinda ++14's1 = (w[i-2] -> 17) ^ (w[i-2] -> 19) ^ (w[i-2] >> 10)mov x,inda
mov y,x
rol y,#19-17xor y,x
ror y,#19shr x,#10xor x,y
add indb,x 'w[i] = s0 + w[i-16] + s1
setinda --5'w[i] = s0 + w[i-16] + s1 + w[i-7]
:sch add indb++,inda
' Load variables from hash
reps #8,#1'copy hash[0..7] into a..h
setinds a,hash
mov indb++,inda++
' Do 64 hash iterations on variables
reps #64,@:itr 'i = 0..63
setinds k+0,w+0'indb = @k[i], inda = @w[i]mov x,g 'ch = (e & f) ^ (!e & g)xor x,f
and x,e
xor x,g
mov y,e 's1 = (e -> 6) ^ (e -> 11) ^ (e -> 25)rol y,#11-6xor y,e
rol y,#25-11xor y,e
ror y,#25add x,y 't1 = ch + s1add x,indb++ 't1 = ch + s1 + k[i]add x,inda++ 't1 = ch + s1 + k[i] + w[i]add x,h 't1 = ch + s1 + k[i] + w[i] + hmov y,c 'maj = (a & b) ^ (b & c) ^ (c & a)and y,b
or y,a
mov h,c
or h,b
and y,h
mov h,a 's0 = (a -> 2) ^ (a -> 13) ^ (a -> 22)rol h,#13-2xor h,a
rol h,#22-13xor h,a
ror h,#22add y,h 't2 = maj + s0mov h,g 'h = gmov g,f 'g = fmov f,e 'f = emov e,d 'e = dmov d,c 'd = cmov c,b 'c = bmov b,a 'b = aadd e,x 'e = e + t1mov a,x 'a = t1 + t2
:itr add a,y
' Add variables back into hash
reps #8,#1'add a..h into hash[0..7]
setinds hash,a
add indb++,inda++
hash_block_ret ret''' Defined data'
zero long0
d0 long1 << 9
opad long$36363636 ^ $5C5C5C5C
hash_init long$6A09E667, $BB67AE85, $3C6EF372, $A54FF53A, $510E527F, $9B05688C, $1F83D9AB, $5BE0CD19'fractionals of square roots of primes 2..19
k long$428A2F98, $71374491, $B5C0FBCF, $E9B5DBA5, $3956C25B, $59F111F1, $923F82A4, $AB1C5ED5'fractionals of cube roots of primes 2..311long$D807AA98, $12835B01, $243185BE, $550C7DC3, $72BE5D74, $80DEB1FE, $9BDC06A7, $C19BF174long$E49B69C1, $EFBE4786, $0FC19DC6, $240CA1CC, $2DE92C6F, $4A7484AA, $5CB0A9DC, $76F988DAlong$983E5152, $A831C66D, $B00327C8, $BF597FC7, $C6E00BF3, $D5A79147, $06CA6351, $14292967long$27B70A85, $2E1B2138, $4D2C6DFC, $53380D13, $650A7354, $766A0ABB, $81C2C92E, $92722C85long$A2BFE8A1, $A81A664B, $C24B8B70, $C76C51A3, $D192E819, $D6990624, $F40E3585, $106AA070long$19A4C116, $1E376C08, $2748774C, $34B0BCB5, $391C0CB3, $4ED8AA4A, $5B9CCA4F, $682E6FF3long$748F82EE, $78A5636F, $84C87814, $8CC70208, $90BEFFFA, $A4506CEB, $BEF9A3F7, $C67178F2''' Undefined data'
hmac res1
bytes res1
count res1
length res1
opad_key res16
hash res8
hashx res8
w res64
a res1
b res1
c res1
d res1
e res1
f res1
g res1
h res1
x res1
y res1
And here's the monitor, shrunk and improved:
'********************************************************'* *'* Propeller II ROM Monitor *'* *'* Version 0.1 *'* *'* 11/01/2012 *'* *'********************************************************'' Usage: cognew($738, tx_pin << 9 + rx_pin) 'start monitor in new cog'CON
branch1_ = 0
branch2_ = branch1_ + 31
branch3_ = branch2_ + 35
hello_ = branch3_ + 15
error_ = hello_ + 33
hitspace_ = error_ + 11
spquote_ = hitspace_ + 10
quotecr_ = spquote_ + 4
sub0_ = quotecr_ + 3'must be => $80
sub1_ = sub0_ + 4
sub2_ = sub1_ + 12
sub3_ = sub2_ + 12
help_ = sub3_ + 4DAT'********'* Data *'********
branch1 byte cmd_new, 0byte cmd_byte, "Y"byte cmd_word, "W"byte cmd_long, "N"byte cmd_viewp, "."byte cmd_search, "/"byte cmd_enter, ":"byte cmd_map, "M"byte cmd_clrp, "L"byte cmd_setp, "H"byte cmd_notp, "T"byte cmd_offp, "Z"byte cmd_getp, "R"byte cmd_quit, "Q"byte cmd_help, "?"byte0'31 bytes
branch2 byte cmd_view2, 0byte cmd_view2, " "byte cmd_range, "."byte cmd_search2, "/"byte cmd_enter2, ":"byte cmd_watch, "@"byte cmd_clkset, "*"byte cmd_coginit, "+"byte cmd_cogstop, "-"byte cmd_clrp, "L"byte cmd_setp, "H"byte cmd_notp, "T"byte cmd_offp, "Z"byte cmd_getp, "R"byte cmd_watchp, "#"byte cmd_cfgp, "|"byte cmd_setdacs, "\"byte0'35 bytes
branch3 byte cmd_view3, 0byte cmd_view3, " "byte cmd_search3, "/"byte cmd_enter3, ":"byte cmd_move, ">"byte cmd_move, "<"byte cmd_checksum, "^"byte0'15 bytes
hello byte13,13,"=== Propeller II Monitor ===",13,13byte0'33 bytes
error byte"? - Help"byte13,7,0'11 bytes
hitspace byte"Hit SPACE",0'10 bytes
spquote byte" '",0'4 bytes
quotecr byte"'",13,0'3 bytes
sub0 byte" -",13,$80'4 bytes
sub1 byte"{adr{.adr}}",$80'12 bytes
sub2 byte"{dat{ dat}}",$80'12 bytes
sub3 byte"adr",$80'4 bytes
help byte13, "~HUB",sub0_
byte sub1_, "`View",13byte sub1_,"/",sub2_, "`Search",13byte sub1_,":",sub2_, "`Enter",13byte sub3_,".",sub3_,"[</>]",sub3_, "`Move",13byte sub3_,".",sub3_,"^", "`Checksum",13byte sub3_,"@", "`Watch",13byte"[Y/W/N]", "`Byte/word/long",13byte"~COGS",sub0_
byte"cog+",sub3_,"{+",sub3_,"}", "`Start",13byte"cog-", "`Stop",13byte"M", "`Map",13byte"~PINS",sub0_
byte"{pin}[H/L/T/Z/R]", "`High/low/toggle/off/read",13byte"pin#", "`Watch",13byte"pin|cfg", "`Configure",13byte"dat\", "`Set DACs",13byte"~MISC",sub0_
byte"dat*", "`Set clock",13byte"'", "`Repeat",13byte"Q", "`Quit",13'(0 long follows)
longs long'*********'* Entry *'*********orglong0'start of data string = 0/nop
reps #$1F6-reserves,#1'clear reserves
setinda reserves
mov inda++,#0
getptra rx_pin 'get rx/tx pins
getptra tx_pin
shr tx_pin,#9
setp tx_pin
jmptask #baud_task,#%0010'enable baud detector task
settask #%%0101tjz period,#$ 'wait for <space> to set period
jmptask #rx_task,#%0100'enable serial receiver task
settask #%%0121mov wsize,#1'init word size to bytecall #set_size
pusha #0'init input line to <enter>
setptra #hello_ 'print hello message
dmax 'end of data string'*************'* Main Task *'*************
message call #tx_string 'print hello/error message
cmd_new call #rx_line 'get input linecall #parse 'parse first termif_ztjz x,#cmd_viewl 'if no hex and eol, view datajmp #cmd_go 'else, process command
cmd_next_crlf call #tx_crlf 'print cr/lf
cmd_next addspa #1'skip chr
cmd_loop call #parse 'parse next term
cmd_go if_nzjmp #cmd_hex 'if hex, branch
movd pinx,#z 'pin update redirected to z
setptra #branch1_ 'not hex, vector by chrcall #vector 'if returns, no match
cmd_error setptra #error_ 'print error messagejmp #message
cmd_hex mov v1,value 'hex, save v1
movd pinx,#pin 'pin update okay
setptra #branch2_ 'vector by chrcall #vector 'if returns, no matchjmp #cmd_view2 'view data
cmd_range call #parse_next 'hex., get hexif_zjmp #cmd_viewp2 'if no hex, view datamov v2,value 'hex.hex, save v2
setptra #branch3_ 'vector by chrcall #vector 'if returns, no matchjmp #cmd_view3 'view data''' Byte/word/long data'
cmd_byte mov wsize,#1wz'set byte mode, z=0
cmd_word if_zmov wsize,#2wz'set word mode, z=0
cmd_long if_zmov wsize,#4'set long modecall #set_size
jmp #cmd_next 'next command''' View data'
cmd_viewl mov v2,#$F'<enter> (eol), show line of datacall #tx_range1
jmp #cmd_new
cmd_viewp mov v2,#$FF'. (more), show page of datacall #tx_range1
jmp #cmd_next
cmd_viewp2 mov v2,#$FF'addr. (more), show page of datacall #tx_range2
jmp #cmd_loop
cmd_view2 mov v2,v1 'addr, show unit of data
cmd_view3 call #tx_range 'addr.addr, show range of datajmp #cmd_loop
''' Search'
cmd_search mov v1,view '/, search from view to end
cmd_search2 mov v2,amask 'addr/, search from address to end
cmd_search3 call #check_range 'addr.addr/, search rangecall #parse_data 'parse data string
:start setptra v1 'start search, point to search address
setinda 0'point to search datamov x,#0'reset word match counter
:wordcall #rdxxxx 'get memory wordcmp value,inda++ wz'compare against search data wordif_zjmp #:match 'if word match, check if string matchadd v1,wsize 'word mismatch, advance search addresscmp v1,v2 wz,wc'at end of range?if_bejmp #:start 'if not, start next searchmov view,v1 'else, update viewand view,amask
jmp #cmd_loop 'next command
:match incmod x,dsize wc'word match, increment match counterif_ncjmp #:word'if more words to match, compare next wordmov v2,dsize 'got string matchshl v2,shift 'v1 = start of found dataadd v2,v1 'v2 = end of found datajmp #cmd_view3 'show found data''' Enter data'
cmd_enter3 call #check_range 'addr.addr:, check range, z=words to fillmov y,#1'set fill flag
cmd_enter2 mov enter,v1 'addr:, set enter addressand enter,amask 'trim enter address (in case cmd_enter2)
cmd_enter call #parse_data ':, parse datatjnz y,#:go 'if not fill, set z to data sizemov z,dsize
add z,#1
:go setptrb enter 'get pointer
:loop mov value,inda++ 'get word from string datacall #wrxxxx 'store value in memorydjnz z,#:loop 'loop until enter done
getptrb enter 'update pointerjmp #cmd_loop 'next command''' Move data'
cmd_move mov y,x 'save ">"/"<"call #check_range 'check 1st address range, get number of wordscall #parse_hex 'get 2nd address
max value,amask 'v1=1st, value=2nd, z=words, y=">"/"<"and value,amask
cmp y,#"<"wz'if "<", swap v1 and valueif_zmov x,v1
if_zmov v1,value
if_zmov value,x 'v1=from, value=to, z=wordscmp v1,value wc'if from < to, downward moveif_cmov x,z
if_cshl x,shift
if_cadd v1,x
if_cadd value,x
if_cxor rdxxxx,#%001_111110'modify 'rdxxxx value,--ptra'if_cxor wrxxxx,#%001_111110'modify 'wrxxxx value,--ptrb'
setptra v1 'set pointers
setptrb value
:loop call #rdxxxx 'move datacall #wrxxxx
djnz z,#:loop
if_cxor rdxxxx,#%001_111110'restore 'rdxxxx value,ptra++'if_cxor wrxxxx,#%001_111110'restore 'wrxxxx value,ptrb++'jmp #cmd_loop 'next command''' Checksum'
cmd_checksum call #check_range 'check range
setptra v1 'sum bytes
:loop call #rdxxxx
add y,value
djnz z,#:loop
mov value,y 'print summov hsize,#8call #tx_hex
jmp #cmd_next_crlf 'next command''' Watch'
cmd_watchp movs rdxxxj,#rdxxxx_ret wz'set pin mode, z=0mov hsize,#1
cmd_watch if_z movs rdxxxj,#rdxxxm 'set mem modeif_zmov hsize,wsize 'set hex size by word sizeif_zshl hsize,#1call #rdxxxp 'get initial value
:loop mov z,value 'preserve valuecall #tx_hex 'print valuecall #tx_space 'print space
:wait call #rx_check 'if key hit, exitif_nzjmp #cmd_next_crlf
call #rdxxxp 'get current valuecmp value,z wz'if same, check againif_zjmp #:wait
jmp #:loop 'new value, loop''' Clkset'
cmd_clkset setptra #hitspace_ 'print hit-space messagecall #tx_string
clkset v1 'set clk
:wait call #rx 'wait for spacecmp x,#" "wzif_nzjmp #:wait
jmp #cmd_next_crlf 'next command''' Coginit'
cmd_coginit setcog v1 'set cogcall #parse_hex 'get program addressmov y,value 'save program addressmov value,#0'clear pointer addresscmp x,#"+"wz'if '+', get pointer addressif_zcall #parse_hex
coginit y,value 'do 'coginit program,pointer'jmp #cmd_loop 'next command''' Cogstop' Quit'
cmd_quit cogid v1 'quit
cmd_cogstop cogstop v1 'stop cogjmp #cmd_next 'next command''' Map'
cmd_map mov y,#7'ready for 7..0
cmd_map_loop call #tx_space 'print spacemov x,y 'get cog statuscogid x wc
cmd_map_c cmp x,y wzif_ncmov x,#"0"'get 0/1/M chrif_cmov x,#"1"if_zmov x,#"M"call #tx 'print chrsub y,#1wcif_ncjmp #cmd_map_loop 'loop until donejmp #cmd_next_crlf 'next command''' Pin writes clrp/setp/notp/offp' Pin read'
cmd_clrp movs pinop,#$DAwz'clrp, z=0
cmd_setp if_z movs pinop,#$DBwz'setp, z=0
cmd_notp if_z movs pinop,#$D9wz'notp, z=0
cmd_offp if_z movs pinop,#$D8wz'offp, z=0
cmd_getp if_z movs pinop,#$D6'getp, z=1
pinx mov pin,v1 'if hex, get pin (d = pin/z)
pinop getp pin wc'becomes clrp/setp/notp/offp/getpif_zjmp #cmd_map_c 'if getp, show pin valuejmp #cmd_next 'next command''' Pin configuration'
cmd_cfgp call #parse_hex 'get configuration
setport v1 'set pin port
decod5 v1 'get pin mask
cfgpins v1,value 'configure pinjmp #cmd_loop 'next command''' Setdacs'
cmd_setdacs setdacs v1 'set all four dacs with 8-bit valuesjmp #cmd_next 'next command''' Help'
cmd_help setptra #help_ 'print help messagecall #tx_string
jmp #cmd_next_crlf 'next command'*************************'* Main Task Subroutines *'*************************''' Vector branch'
vector addptra base 'add data base pointer
vector_loop rdbyte z,ptra++ 'get jump address
vector_ret tjz z,#0'if 0, no match found, returnrdbyte y,ptra++ 'get targetxor y,x wz'compare to xif_nzjmp #vector_loop 'if no match, loopjmp z 'match found, jump, y=0, z=1''' Check address range (v1..v2)'
check_range max v1,amask 'trim v1and v1,amask
max v2,amask 'trim v2and v2,amask
cmp v2,v1 wc'make sure v2 => v1if_cjmp #cmd_error
mov z,v2 'get number of wordssub z,v1
shr z,shift
add z,#1
check_range_ret ret''' Set rdxxxx/wrxxxx and others by word size'
set_size test wsize,#%010wc'set rdxxxx/wrxxxx by word size
setbc rdxxxx,#26
setbc wrxxxx,#26test wsize,#%100wc
setbc rdxxxx,#27
setbc wrxxxx,#27mov shift,wsize 'set shift by word sizeshr shift,#1mov amask,wsize 'set amask by word sizesub amask,#1xor amask,h0001FFFF
and view,amask 'trim viewand enter,amask 'trim enter
set_size_ret ret
rdxxxp getp v1 wc'read pin as "0" or "1"if_ncmov value,#0if_cmov value,#1
rdxxxj jmp #rdxxxx_ret 'd = rdxxxx_ret/rdxxxm
rdxxxm setptra v1 'read mem
rdxxxx rdbyte value,ptra++ 'rdbyte/rdword/rdlong
rdxxxp_ret
rdxxxx_ret ret
wrxxxx wrbyte value,ptrb++ 'wrbyte/wrword/wrlong
wrxxxx_ret ret''' Input line'
rx_line setspa #0'point to start of linemov x,#">"'show promptcall #tx
call #rx 'get first chrcmp x,#"'"wz'check for repeatif_nzjmp #:first 'if not repeat, first chr
:show popar x wz'repeat, show lineif_nzcall #tx
if_nzjmp #:show
jmp #:done
:loop call #rx 'get next chr
:first cmp x,#13wz'cr?if_zjmp #:cr
cmp x,#8wz'backspace?if_nzcmp x,#127wzif_zjmp #:bs
cmp x,#" "wc'visible chr?if_nccmpr x,#"~"wcif_cjmp #:loop
pusha x 'visible chr, append to line
chkspa wc'overflow?if_c subspa #1'if overflow, back upif_nccall #tx 'if not overflow, print chrjmp #:loop
:bs chkspa wz'backspace, line empty?if_nz pushar x 'if not empty,if_nzcall #tx '..print backspaceif_nzcall #tx_space '..print spaceif_nz popar x '..print backspaceif_nzcall #tx
if_nz subspa #1'..back upjmp #:loop
:cr pusha #0'cr, end line with 0
:done setspa #0'point to start of line
tx_crlf mov x,crlf 'print cr/lfcall #tx
tx_crlf_ret
rx_line_ret ret''' Parse hex/text data'
parse_data mov w,#0'reset data count
setinda 0'point to string data
:hex call #parse_next 'hex loop, check hexif_nzcall #enter_data 'if hex, enter valuecmp x,#" "wz'check for space (more hex)if_zjmp #:hex 'if more hex, loopcmp x,#"'"wz'not hex, "'"?if_nzjmp #:done 'if not "'", done
:text addspa #2'text looppopa x 'get and point to next chrcmp x,#"'"wz'check for "'"if_zjmp #:hex 'if "'", back to hextjz x,#:done 'if eol, donemov value,x 'text chrcall #enter_data 'enter chrjmp #:text 'loop
:done sub w,#1wc'get data countif_ncmov dsize,w 'if 0, reuse old data
movd :fix,dsize 'form circular buffer
:fix fixinda 0,0'(no instruction-modification problem with 1:4 threading)
parse_data_ret ret
enter_data incmod w,#dmax wc'check if data limit exceededif_cjmp #cmd_error 'if data limit exceeded, errormov inda++,value 'store value in data
enter_data_ret ret''' Parse hex'
parse_hex call #parse_next 'try to parse hexif_zjmp #cmd_error 'if no hex, error
parse_hex_ret ret''' Parse line (@spa), z=0 if hex (value)'
parse_next addspa #1'advance to next chr
parse mov value,#0wz'z=1call #skip_spaces wz'skip any spaces (preserve z)
:loop popar x 'get chrcall #check_hex 'check hexif_cshl value,#4'if hex, append nibble and loopif_cor value,x
if_cjmp #:loop wz'z=0
subspa #1'repoint to non-hex chrcall #skip_spaces wz'skip any post-hex spaces (preserve z)call #check_hex 'check hexif_cpopa x 'if hex, back up to space chrcmpr x,#"a"-1wc'make non-hex chr uppercaseif_ccmp x,#"z"+1wcif_csub x,#"a"-"A"
parse_next_ret
parse_ret ret''' Skip spaces (@spa)'
skip_spaces popar x 'skip space chr(s)cmp x,#" "wzif_zjmp #skip_spaces
subspa #1'back up to non-space chr
skip_spaces_ret retwz'restore z''' Check hex (x), c=1 if hex (x)'
check_hex cmpr x,#"0"-1wc'"0".."9" -> $0..$9if_ccmp x,#"9"+1wcif_cadd x,#"A"-"9"-1if_nccmpr x,#"A"-1wc'"A".."F" -> $A..$Fif_ccmp x,#"F"+1wcif_cadd x,#"a"-"A"if_nccmpr x,#"a"-1wc'"a".."f" -> $A..$Fif_ccmp x,#"f"+1wcif_csub x,#"a"-10
check_hex_ret ret''' Print range (v1..v2)'
tx_range1 mov v1,view 'view..view + v2
tx_range2 and v2,amask 'v1..v1 + v2add v2,v1
tx_range call #check_range 'check rangemov view,v1 'set address
:line mov value,view 'print 5-digit addressmov hsize,#5call #tx_hex
call #tx_dspace 'print "- "mov x,wsize 'get number of words on linerev x,#32-5mov v1,z
max v1,x
mov v2,v1 'get number of ascii bytes on lineshl v2,shift
sub z,v1 'update number of words left
setptra view 'print hex words
:hex call #rdxxxx
mov hsize,wsize
shl hsize,#1call #tx_hex
call #tx_space
djnz v1,#:hex
setptra #spquote_ 'print " '"call #tx_string
setptra view 'print ascii bytes
:ascii rdbyte x,ptra++
cmp x,#" "wc'visible chr?if_nccmpr x,#"~"wcif_cmov x,#"."'substitute "." for non-visible chrscall #tx
djnz v2,#:ascii
getptra view 'update address
setptra #quotecr_ 'print "'" + crcall #tx_string
call #rx_check 'check key hitif_ztjnz z,#:line 'if no key hit and more words left, print another line
tx_range1_ret
tx_range2_ret
tx_range_ret ret''' Print string (@ptra)'
tx_string addptra base 'add data base pointer
tx_string_loop rdbyte x,ptra++ 'get chr
tx_string_ret tjz x,#0'if 0, donetest x,#$80wz'substring?if_nz notb tx_string_loop,#8'toggle ptra/ptrbif_nz setptrb x 'ptrb points to substringif_nz addptrb base
if_nzjmp #tx_string_loop 'start substring or resume stringcmp x,#"`"wz'long tab?if_zsubr y,#32-16if_nzcmp x,#"~"wz'short tab?if_zadd y,#16
:tab if_zcall #tx_space
if_zdjnz y,#:tab
if_zcall #tx_dspace
if_zjmp #tx_string_loop
cmp x,#13wz'cr?if_zcall #tx_crlf
if_zmov y,#0if_nzcall #tx 'other?if_nzadd y,#1jmp #tx_string_loop
''' Print hex (value)'
tx_hex mov y,hsize 'pre-rotate to get 1st nibble in topshl y,#2ror value,y
mov y,hsize 'print nibbles
:loop rol value,#4mov x,value
call #tx_nib
djnz y,#:loop
tx_hex_ret ret''' Print "- "'
tx_dspace mov x,dspace
jmp #tx
''' Print space'
tx_space mov x,#" "jmp #tx
''' Print nibble (x)'
tx_nib and x,#$F'isolate nibblecmp x,#$Awc'alpha or numeric?if_cadd x,#"0"'numericif_ncadd x,#"A"-$A'alpha''' Transmit chr (x)'
tx shl x,#1'insert start bit
setb x,#9'set stop bit
getcnt w 'get initial time
:loop add w,period 'add bit period to time
passcnt w 'loop until bit period elapsedshr x,#1wc'get next bit into c
setpc tx_pin 'write c to tx pintjnz x,#:loop 'loop until bits done
tx_dspace_ret
tx_space_ret
tx_nib_ret
tx_ret ret''' Receive chr (x)'
rx call #rx_check 'wait for rx chrif_zjmp #rx
rx_ret ret''' Check receiver, z=0 if chr (x)'
rx_check or rx_tail,#$80'if start or rollover, reset tail
getspb rx_temp wz'if head uninitialized, z=1if_nzcmp rx_temp,rx_tail wz'if head-tail mismatch, byte ready, z=0if_nz getspa rx_temp 'preserve spaif_nz setspa rx_tail 'get tailif_nz popar x 'get byte at tailif_nz getspa rx_tail 'update tailif_nz setspa rx_temp 'restore spa
rx_check_ret ret'************************'* Serial Receiver Task *'************************
rx_task chkspb wz'if start or rollover, reset headif_z setspb #$80mov rx_bits,#9'ready for 8 data bits + 1 stop bitneg rx_time,period 'get -0.5 periodsar rx_time,#1
jp rx_pin,#$ 'wait for start bit
subcnt rx_time 'get time + 0.5 period for initial 1.5 period delay
:bit rcr rx_data,#1'rotate c into byteadd rx_time,period 'add 1 period
passcnt rx_time 'wait for center of next bit
getp rx_pin wc'read rx pin into cdjnz rx_bits,#:bit 'loop until 8 data bits + 1 stop bit receivedshr rx_data,#32-8'align bytepushb rx_data 'store byte at head, inc headjmp #rx_task 'wait for next byte'**********************'* Baud Detector Task *'**********************
baud_task movd ctr,rx_pin 'set ctra to time rx pin states
:loop notb ctr,#5wc'if 1,0 sample set, c=0
setctra ctr '($20 -> 10000001001 -> 1, 6x 0, 1x 1, 2x 0, 1)if_ncmov limh,buff0 'if 1,0 sample set,if_ncshr limh,#4'..make window from 1st 0 (6x if $20)if_ncneg liml,limh
if_ncadd limh,buff0
if_ncadd liml,buff0
if_ncmov comp,buff1 'if 1,0 sample set,if_ncmul comp,#6'..normalize 2nd 1 (1x if $20) to 6xif_nccmpr comp,limh wc'..check if within windowif_nccmp comp,liml wcif_ncmov comp,buff2 'if 1,0 sample set,if_ncmul comp,#3'..normalize 2nd 0 (2x if $20) to 6xif_nccmpr comp,limh wc'..check if within windowif_nccmp comp,liml wcif_ncadd buff0,buff2 'if $20,if_ncshr buff0,#3'..compute period from 6x 0 and 2x 0if_ncmov period,buff0 '..update periodmov buff0,buff1 'scroll sample buffermov buff1,buff2
:wait getcosa buff2 'wait for next sampletjnz buff2,#:loop
jmp #:wait
'*************'* Constants *'*************
base long$55C'start of byte data
h0001FFFF long$0001FFFF'memory limit
crlf long1<<18 + $0A<<10 + $0D'cr/lf
dspace long1<<18 + " "<<10 + "-"'dash/space
ctr long%100_01001'ctr configuration for timing low on rx pin'*************'* Variables *'*************
reserves
w res1'main task
x res1
y res1
z res1
v1 res1
v2 res1
value res1
view res1
enter res1
pin res1
dsize res1
hsize res1
wsize res1
shift res1
amask res1
rx_pin res1
tx_pin res1
rx_tail res1'serial receiver task
rx_temp res1
rx_time res1
rx_data res1
rx_bits res1
buff0 res1'baud detector task
buff1 res1
buff2 res1
limh res1
liml res1
comp res1
period res1
One thing I'm are curious Why You not implemented Intel HEX loader in monitor with checksum cheking.
That have ben nice to use as Loader from any Terminal program.
Ps. In 8080 assembly it is only some lines of code.
It is more universally accessible than the binary/HMAC-signed downloader because it sends and receives only standard ASCII characters $20..$7E (space.."~").
Some programming languages, serial interfaces, and OS's have issues with sending and receiving full binary ($00..$FF). For this reason, you might have to jump through some hoops to get the more-efficient binary downloader working on a given host system. The monitor, on the other hand, can talk to anything that speaks serial, without concern over non-ASCII characters. It is so simple that it can't NOT work on any host machine that has a serial port. Plus, it doesn't force an ordered protocol, but is conversational in operation. I've been using the Parallax Serial Terminal program to talk to it as well as PUTTY, which is free on the 'net and very tidy.
My thinking might be a little anachronistic, but I've seen many host-level systems which are big on brains and storage, but for which the serial interfaces were fleeting afterthoughts, and full binary can trigger unwanted events. The monitor will play politely and offer no offense to any host.
The reason I put a help menu in the monitor was so that you could quickly get command syntax without having to refer to any documents. You might launch the monitor from within an app you want to debug and you'll need to search memory for a string of data to get your bearings. The help menu will be handy then.
Here is the ROM now:
=== Propeller II Monitor ===
>0.e7f
00000- 5072 6F 7032 2E 30200020 7C 0C 03 D0 7C 0C 'Prop2.0 . |...|.'00010- 45 FE C1 0D E3 B6 FC 0C 01 C2 7C 0C 01 C2 7C 0D 'E.........|...|.'00020- 01 C2 FC 80 1F C2 7C 6201 E0 FC 3066 0C A8 80'......|b...0f...'00030- 01 CA 7C 0C 2A DE FC FA 5B C0 FC 1C 7C FA BC A0 '..|.*...[...|...'00040- 5B C0 FC 1C 7C FA BC 8001 FA FC 28 FA F0 FC A0 '[...|......(....'00050- 5B C0 FC 1C 01 C8 7C 62 2A 0064 1C B2 C8 7C 61'[.....|b*.d...|a'00060- 01 C8 FC 3410 F0 FC F6 02 F1 FC A0 08 F0 7C 86'...4..........|.'00070- 52 C8 E8 A0 01 C8 7C 622552 FC 1C DA B4 FC 0C 'R.....|b%R......'00080- 2552 FC 1C DF B4 FC 0C 2552 FC 1C DB B4 FC 0C '%R......%R......'00090- 2552 FC 1C B2 C8 7C 6101 C8 FC 3417 F0 FC F6 '%R....|a...4....'
000A0- 3500 7C 1C 0D F6 FC 0C 62 F6 BC 8063 C6 BC FF '5.|.....b...c...'
000B0- 37 4F FC 0C 0000 4C 1C 04 F0 FC A0 DB B2 FC 0C '7O....L.........'
000C0- DA B0 FC 0C 44 3E C0 0D DA B2 FC 0C 01 F0 7C E1 '....D>........|.'
000D0- 01 CA CC 27 DC AE FC 0C DB B0 FC 0C DA B0 FC 0C '...'............'
000E0- 2B F0 FC F6 B2 D8 7C 0C 66 F0 BC A0 20 F2 FC A0 '+.....|.f... ...'
000F0- 5B C0 E8 1C D6 AC D4 0D DB B0 D4 0C DA B0 D4 0C '[...............'00100- 01 F4 FC 3438 F2 FC F6 C1 F4 7C 0837 F0 FC F6 '...48.....|.7...'00110- 40 0E C0 0D 700004 E0 C1 EC 5308 6B F0 3C 08'@...p.....S.k.<.'00120- E0 02 FC 0C 6B D4 3C 0C 670004 E0 03 F0 FC A0 '....k.<.g.......'00130- 6B EC 1308 6B F4 BC 0A 49 F4 7C FA 48 F0 FC F6 'k...k...I.|.H...'00140- 03 1C 7C 0C 42 0E C0 0D E0 00 FC 0C 30 F2 FC 08'..|.B.......0...'00150- C1 F4 FC 08 7A F2 2886 6D D8 28 0C 41 FE FF 0F '....z.(.m.(.A...'00160- 01 DC 7C 0C C1 F0 7C 08 C1 F0 7C 0871 E0 BC 6A '..|...|...|.q..j'00170- 73 E4 A8 6A 08 DC D4 A0 6F DC 3C 0C 2552 FC 1C 's..j....o.<.%R..'00180- 0D F8 FC 0C 2552 FC 1C 0C F8 FC 0C 7D F8 3C 85'....%R......}.<.'00190- 0000 7C 1C 00020000 C0 C6 2D 0000000008'..|.......-.....'
001A0- 5000000000000003000200008016 1E 40'P..............@'
001B0- 80 0E BE 8F A0 1600 C0 D0 010000 C0 160000'................'
001C0- 80 0E 00008016000010070000 5B B4 0000'............[...'
001D0- CA E0 FD 0C 4696 FC 1C 00 9E FE 0802 9E 7E F8 '....F.........~.'
001E0- B3 9E 7E 0C 4F CB BD A0 02 CA FD 2C 13 CA FD 28'..~.O......,...('
001F0- 01 CA FD 80 1E 9E FE 280800 7C 0C 10 9E FE F4 '.......(..|.....'00200- 1D 9E FE F4 21 9E FE F4 0030 7D 080200 7C 1C '....!....0}...|.'00210- 3596 FC 1C 00 9E FE A0 E4 CA 3D E1 C1 9F F2 01'5.........=.....'00220- 36 9E FE 6C 4C A6 FC 1C 110054 1C 41 1E C0 0D '6..lL.....T.A...'00230- 07 CF 15 E0 F6 EF 87 A0 9A EE 93 6C 01 C6 FD A0 '...........l....'00240- 0E 00 7C 1C C1 9F FE 01 4C A6 FC 1C 1D CA FD F6 '..|.....L.......'00250- 0E 00 7C 1C 2C C6 7D F8 3596 FC 1C 40 1E C0 0D '..|.,.}.5...@...'00260- E7 0E 16 E0 F6 EF 97 A0 54 2E FD 1C 40 0E C0 0D '........T...@...'00270- FF 0E 16 E0 F6 EF 97 A0 0F 99 FC 5460 C8 FD A0 '...........T`...'00280- 3596 FC 1C FF 0004 E0 08 CA FD A0 4106 C0 0D '5...........A...'00290- F6 9F 86 A0 08 9E FE 24 C1 9F 7E 00 2F CA FD F6 '.......$..~./...'
002A0- 0E 00 7C 1C E4 CC BD A0 03 CC FD 2C 80 9E FE A0 '..|........,....'
002B0- 4C A6 FC 1C E4 9E BE A0 3F 9E FE 6038 9E 7E 86'L.......?..`8.~.'
002C0- 00 9E FE A0 380054 1C 04 C8 7D 6108 CC F1 24'....8.T...}a...$'
002D0- E6 9E B2 A0 4C A6 FC 1C 3E 0054 1C 40 0E C0 0D '....L...>.T.@...'
002E0- F7 FE 15 E0 F6 EF 97 A0 40 0E C0 0D 9B EE 15 E0 '........@.......'
002F0- F6 EF 97 A0 00 C6 FD A0 00 C8 FD A0 0000 7C 1C '..............|.'00300- 4F 0F 3E 1401 C8 FD 8003 C8 7D 629998 A8 80'O.>.......}b....'00310- 3F C8 7D 620799 E8 5454 2E E9 1C 0000 7C 1C '?.}b...TT.....|.'00320- 53 5E C0 0D 0F 2F 16 E0 F9 01 0C E0 F6 EF 8B A0 'S^.../..........'00330- F7 9F 82 A0 0B 9E FE 24 F7 9F 82 6C 12 9E FE 20'.......$...l... '00340- 03 EE C3 28 4F EF 83 6C F6 EF 8380 0E 00 0C E0 '...(O..l........'00350- F6 9F 82 A0 4F A1 BE A0 02 A0 FE 24 4F A1 BE 6C '....O......$O..l'00360- 13 A0 FE 20 0A 9E FE 2850 9F BE 6C 4F EF 8380'... ...(P..lO...'00370- FB 01 0C E0 F6 EF 938040 0E C0 0D F7 8E 16 E0 '........@.......'00380- F6 EF 97 A0 64 7E C0 0D 074715 E0 4D 9F BE A0 '....d~...G..M...'00390- 4C 9F BE 6C 4B 9F BE 60 4D 9F BE 6C 4B A1 BE A0 'L..lK..`M..lK...'
003A0- 05 A0 FE 24 4B A1 BE 6C 0E A0 FE 24 4B A1 BE 6C '...$K..l...$K..l'
003B0- 19 A0 FE 2050 9F BE 80 F7 9F 8680 F6 9F 8680'... P...........'
003C0- 4E 9F BE 8049 A1 BE A0 48 A1 BE 6047 A1 BE 68'N...I...H..`G..h'
003D0- 49 9D BE A0 48 9D BE 68 4E A1 BE 6047 9D BE A0 'I...H..hN..`G...'
003E0- 0B 9C FE 2447 9D BE 6C 09 9C FE 2447 9D BE 6C '...$G..l...$G..l'
003F0- 16 9C FE 20 4E A1 BE 80 4D 9D BE A0 4C 9B BE A0 '... N...M...L...'00400- 4B 99 BE A0 4A 97 BE A0 4995 BE A0 4893 BE A0 'K...J...I...H...'00410- 4791 BE A0 4F 97 BE 80 4F 8F BE A0 50 8F BE 80'G...O...O...P...'00420- 40 0E C0 0D 47 EF 15 E0 F6 EF 97800000 7C 1C '@...G.........|.'00430- 0000000000020000 6A 6A 6A 6A 67 E6 09 6A '........jjjjg..j'00440- 85 AE 67 BB 72 F3 6E 3C 3A F5 4F A5 7F 52 0E 51'..g.r.n<:.O..R.Q'00450- 8C 6805 9B AB D9 83 1F 19 CD E0 5B 98 2F 8A 42'.h.........[./.B'00460- 91443771 CF FB C0 B5 A5 DB B5 E9 5B C2 5639'.D7q........[.V9'00470- F1 11 F1 59 A4 82 3F 92 D5 5E 1C AB 98 AA 07 D8 '...Y..?..^......'00480- 01 5B 8312 BE 853124 C3 7D 0C 5574 5D BE 72'.[....1$.}.Ut].r'00490- FE B1 DE 80 A7 06 DC 9B 74 F1 9B C1 C1 69 9B E4 '........t....i..'
004A0- 8647 BE EF C6 9D C1 0F CC A1 0C 24 6F 2C E9 2D '.G.........$o,.-'
004B0- AA 8474 4A DC A9 B0 5C DA 88 F9 765251 3E 98'..tJ...\...vRQ>.'
004C0- 6D C6 31 A8 C8 2703 B0 C7 7F 59 BF F3 0B E0 C6 'm.1..'....Y.....'
004D0- 4791 A7 D5 5163 CA 066729291485 0A B7 27'G...Qc..g))....''
004E0- 3821 1B 2E FC 6D 2C 4D 13 0D 38535473 0A 65'8!...m,M..8STs.e'
004F0- BB 0A 6A 76 2E C9 C2 8185 2C 7292 A1 E8 BF A2 '..jv.....,r.....'00500- 4B 66 1A A8 70 8B 4B C2 A3 51 6C C7 19 E8 92 D1 'Kf..p.K..Ql.....'00510- 240699 D6 8535 0E F4 70 A0 6A 1016 C1 A4 19'$....5..p.j.....'00520- 08 6C 37 1E 4C 774827 B5 BC B0 34 B3 0C 1C 39'.l7.LwH'...4...9'00530- 4A AA D8 4E 4F CA 9C 5B F3 6F 2E 68 EE 82 8F 74'J..NO..[.o.h...t'00540- 6F 63 A5 781478 C8 840802 C7 8C FA FF BE 90'oc.x.x..........'00550- EB 6C 50 A4 F7 A3 F9 BE F2 7871 C6 1200 2A 59'.lP......xq...*Y'00560- 2B 57 2C 4E 32 2E 3B 2F 55 3A A1 4D AD 4C AE 48'+W,N2.;/U:.M.L.H'00570- AF 54 B0 5A B1 52 9E 51 BD 3F 003800382024'.T.Z.R.Q.?.8.8 $'00580- 2E 3C 2F 53 3A 8240 8F 2A 96 2B 9F 2D AD 4C AE '.</S:.@.*.+.-.L.'00590- 48 AF 54 B0 5A B1 528023 B6 7C BB 5C 003900'H.T.Z.R.#.|.\.9.'
005A0- 3920 3D 2F 51 3A 5F 3E 5F 3C 77 5E 00 0D 0D 3D '9 =/Q:_>_<w^...='
005B0- 3D 3D 205072 6F 7065 6C 6C 657220494920'== Propeller II '
005C0- 4D 6F 6E 6974 6F 7220 3D 3D 3D 0D 0D 00 3F 20'Monitor ===...? '
005D0- 2D 204865 6C 70 0D 070048697420535041'- Help...Hit SPA'
005E0- 4345002020270027 0D 0020 2D 0D 80 7B 61'CE. '.'.. -..{a'
005F0- 6472 7B 2E 616472 7D 7D 80 7B 646174 7B 20'dr{.adr}}.{dat{ '00600- 646174 7D 7D 8061647280 0D 7E 485542 8E 'dat}}.adr..~HUB.'00610- 926056696577 0D 92 2F 9E 605365617263'.`View../.`Searc'00620- 68 0D 92 3A 9E 6045 6E 746572 0D AA 2E AA 5B 'h..:.`Enter....['00630- 3C 2F 3E 5D AA 60 4D 6F 7665 0D AA 2E AA 5E 60'</>].`Move....^`'00640- 43686563 6B 7375 6D 0D AA 406057617463'Checksum..@`Watc'00650- 68 0D 5B 59 2F 57 2F 4E 5D 6042797465 2F 77'h.[Y/W/N]`Byte/w'00660- 6F 7264 2F 6C 6F 6E 67 0D 7E 43 4F 4753 8E 63'ord/long.~COGS.c'00670- 6F 67 2B AA 7B 2B AA 7D 605374617274 0D 63'og+.{+.}`Start.c'00680- 6F 67 2D 605374 6F 70 0D 4D 60 4D 6170 0D 7E 'og-`Stop.M`Map.~'00690- 5049 4E 53 8E 7B 7069 6E 7D 5B 48 2F 4C 2F 54'PINS.{pin}[H/L/T'
006A0- 2F 5A 2F 52 5D 6048696768 2F 6C 6F 77 2F 74'/Z/R]`High/low/t'
006B0- 6F 6767 6C 65 2F 6F 6666 2F 72656164 0D 70'oggle/off/read.p'
006C0- 69 6E 23605761746368 0D 7069 6E 7C 6366'in#`Watch.pin|cf'
006D0- 676043 6F 6E 666967757265 0D 646174 5C 'g`Configure.dat\'
006E0- 605365742044414373 0D 7E 4D 495343 8E '`Set DACs.~MISC.'
006F0- 646174 2A 605365742063 6C 6F 63 6B 0D 27'dat*`Set clock.''00700- 60526570656174 0D 516051756974 0D 00'`Repeat.Q`Quit..'00710- 0000000040 3C C0 0D D7 0104 E0 00 EC D3 A0 '....@<..........'00720- 12 CC FF 0C 12 CE FF 0C 09 CE FF 28 DB CE 7F 0C '...........(....'00730- 9274 FF 0C CB 22 FC 0C 0A E6 7F F8 9456 FF 0C '.t...".......V..'00740- CB 32 FC 0C 01 C6 FF A0 D2 BE FD 1C AA 00 FC 0C '.2..............'00750- B2 A2 FC 0C 6F E3 FE 1C E9 1A FE 1C 2B 73 FE 1C '....o.......+s..'00760- 2F B0 6B F8 1900 7C 1C 0B 1B FE 1C A4 02 FC 0C '/.k...|.........'00770- 2B 73 FE 1C 1F 0054 1C DA 65 FD 54 B2 00 FC 0C '+s....T..e.T....'00780- C0 84 FD 1C B2 E4 FC 0C 1100 7C 1C DD B7 BF A0 '..........|.....'00790- E0 65 FD 54 B2 3E FC 0C C0 84 FD 1C 3800 7C 1C '.e.T.>......8.|.'
007A0- 2A 73 FE 1C 350068 1C DD B9 BF A0 B2 84 FC 0C '*s..5.h.........'
007B0- C0 84 FD 1C 3900 7C 1C 01 C6 FF A2 02 C6 EB A2 '....9.|.........'
007C0- 04 C6 EB A0 D2 BE FD 1C 1700 7C 1C 0F B8 FF A0 '..........|.....'
007D0- 49 DD FE 1C 1200 7C 1C FF B8 FF A0 49 DD FE 1C 'I.....|.....I...'
007E0- 1700 7C 1C FF B8 FF A0 4A DD FE 1C 1800 7C 1C '..|.....J.....|.'
007F0- DB B9 BF A0 4C DD FE 1C 1800 7C 1C DE B7 BF A0 '....L.....|.....'00800- E5 B9 BF A0 C7 A2 FD 1C 0E 45 FE 1C B2 B6 7F 0C '.........E......'00810- 000004 E0 00 B0 FF A0 E5 CC FD 1C F6 BB 0786'................'00820- 4B 0068 1C E3 B7 BF 80 DC B7 3F 87 3F 0078 1C 'K.h.......?.?.x.'00830- DB BD BF A0 E5 BD BF 601800 7C 1C E1 B1 BF E9 '.......`..|.....'00840- 4200 4C 1C E1 B9 BF A0 E4 B9 BF 2C DB B9 BF 80'B.L........,....'00850- 3900 7C 1C C7 A2 FD 1C 01 B2 FF A0 DB BF BF A0 '9.|.............'00860- E5 BF BF 60 0E 45 FE 1C 59 B2 7F FA E1 B5 BF A0 '...`.E..Y.......'00870- 01 B4 FF 80 B3 BE 7F 0C F6 BB 87 A0 E7 D0 FD 1C '................'00880- 5A B4 FF F6 13 BE FF 0C 1800 7C 1C D8 B3 BF A0 'Z.........|.....'00890- C7 A2 FD 1C 2753 FE 1C E5 BB BF 4C E5 BB BF 60'....'S.....L...`'
008A0- 3C B2 7F 86 DB B1 AB A0 DD B7 AB A0 D8 BB AB A0 '<...............'
008B0- DD B7 3F 85 DA B1 B3 A0 E4 B1 B3 2C D8 B7 B3 80'..?........,....'
008C0- D8 BB B3 80 7E CA F1 6C 7E CE F1 6C B2 B6 7F 0C '....~..l~..l....'
008D0- B3 BA 7F 0C E5 CC FD 1C E7 D0 FD 1C 71 B4 FF F6 '............q...'
008E0- 7E CA F1 6C 7E CE F1 6C 1800 7C 1C C7 A2 FD 1C '~..l~..l..|.....'
008F0- B2 B6 7F 0C E5 CC FD 1C DD B3 BF 8079 B4 FF F6 '............y...'00900- D9 BB BF A0 08 C4 FF A0 85 1B FF 1C 1600 7C 1C '..............|.'00910- E6 C6 FD 5201 C4 FF A0 E4 C6 E9 50 E3 C5 AB A0 '...R.......P....'00920- 01 C4 EB 2C E0 CC FD 1C DD B5 BF A0 85 1B FF 1C '...,............'00930- 90 3D FF 1C A2 55 FF 1C 160054 1C E0 CC FD 1C '.=...U....T.....'00940- DA BB 3F 86890068 1C 8600 7C 1C B2 FA FC 0C '..?...h...|.....'00950- 6F E3 FE 1C 00 B6 7F 0C 9F 43 FF 1C 20 B0 7F 86'o........C.. ...'00960- 920054 1C 1600 7C 1C E0 B6 7F 0C 2753 FE 1C '..T...|.....'S..'00970- DD B3 BF A0 00 BA FF A0 2B B0 7F 862753 EA 1C '........+...'S..'00980- DD B3 3F 0C 1800 7C 1C 01 B6 FF 0C 03 B6 7F 0C '..?...|.........'00990- 1700 7C 1C 07 B2 FF A0 90 3D FF 1C D9 B1 BF A0 '..|......=......'
009A0- 01 B0 FF 0D D9 B1 3F 8630 B0 CF A0 31 B0 F3 A0 '......?.0...1...'
009B0- 4D B0 EB A0 96 3D FF 1C 01 B2 FF 85 A2 00 4C 1C 'M....=........L.'
009C0- 1600 7C 1C DA 66 FD 52 DB 66 E9 52 D9 66 E9 52'..|..f.R.f.R.f.R'
009D0- D8 66 E9 52 D6 66 E9 50 DB C1 BF A0 D6 C0 7F 0D '.f.R.f.P........'
009E0- A5 0068 1C 1700 7C 1C 2753 FE 1C E3 B6 7F 0C '..h...|.'S......'
009F0- 23 B6 FF 0C DD B7 3F E8 1800 7C 1C D5 B6 7F 0C '#.....?...|.....'
00A00- 1700 7C 1C B2 5C FD 0C 6F E3 FE 1C 1600 7C 1C '..|..\..o.....|.'
00A10- B4 A4 7F 0C C1 B4 FF 0000 B4 7F F8 C1 B2 FF 00'................'
00A20- D8 B3 BF 6E C1 0054 1C DA 01 3C 1C E5 B7 BF 4C '...n..T...<....L'
00A30- E5 B7 BF 60 E5 B9 BF 4C E5 B9 BF 60 DB B9 3F 85'...`...L...`..?.'
00A40- 1D 0070 1C DC B5 BF A0 DB B5 BF 84 E4 B5 BF 28'..p............('
00A50- 01 B4 FF 800000 7C 1C 02 C6 7F 61 9A CB FD 0C '......|....a....'
00A60- 9A CF FD 0C 04 C6 7F 61 9B CB FD 0C 9B CF FD 0C '.......a........'
00A70- E3 C9 BF A0 01 C8 FF 28 E3 CB BF A0 01 CA FF 84'.......(........'
00A80- D3 CB BF 6C E5 BD BF 60 E5 BF BF 600000 7C 1C '...l...`...`..|.'
00A90- D6 B6 7F 0D 00 BA CF A0 01 BA F3 A0 E6 00 7C 1C '..............|.'
00AA0- B2 B6 7F 0C C1 BA FF 000000 7C 1C C1 BB 7F 00'..........|.....'
00AB0- 0000 7C 1C A2 00 FC 0C 3E B0 FF A0 96 3D FF 1C '..|.....>....=..'
00AC0- 9F 43 FF 1C 27 B0 7F 86 F4 0054 1C 18 B0 FF 0E '.C..'.....T.....'
00AD0- 96 3D D7 1C EF 0054 1C 0A 01 7C 1C 9F 43 FF 1C '.=....T...|..C..'
00AE0- 0D B0 7F 86090168 1C 08 B0 7F 86 7F B0 5786'......h.......W.'
00AF0- 010168 1C 20 B0 7F 85 7E B0 4F E1 F3 0070 1C '..h. ...~.O...p.'
00B00- AA B0 7F 0C 1600 7C 0D A6 02 F0 0C 96 3D CF 1C '......|......=..'
00B10- F3 00 7C 1C 1600 7C 0E A8 B0 57 0C 96 3D D7 1C '..|...|...W..=..'
00B20- 90 3D D7 1C 18 B0 D7 0C 96 3D D7 1C A6 02 D4 0C '.=.......=......'
00B30- F3 00 7C 1C AA 00 FC 0C A2 00 FC 0C D4 B1 BF A0 '..|.............'
00B40- 96 3D FF 1C 0000 7C 1C 00 AE FF A0 000004 E0 '.=....|.........'
00B50- 2A 73 FE 1C 23 4D D6 1C 20 B0 7F 86100168 1C '*s..#M.. .....h.'
00B60- 27 B0 7F 86 1E 0154 1C A4 04 FC 0C 1A B0 FF 0C ''.....T.........'
00B70- 27 B0 7F 86100168 1C 1E B1 7F F8 D8 BB BF A0 ''.....h.........'
00B80- 23 4D FE 1C 1601 7C 1C 01 AE FF 85 D7 C3 8F A0 '#M....|.........'
00B90- E1 43 BE 54000004 E4 0000 7C 1C 11 AE FF E9 '.C.T......|.....'
00BA0- 1D 0070 1C DD ED 93 A0 0000 7C 1C 2A 73 FE 1C '..p.......|.*s..'
00BB0- 1D 0068 1C 0000 7C 1C A4 02 FC 0C 00 BA FF A2 '..h...|.........'
00BC0- 3A 7D FE 1E 18 B0 FF 0C 3F 91 FE 1C 04 BA F3 2C ':}......?......,'
00BD0- D8 BB B3 68 2D 0170 1E A6 02 FC 0C 3A 7D FE 1E '...h-.p.....:}..'
00BE0- 3F 91 FE 1C 1A B0 F3 0C 60 B0 7F E1 7B B0 7385'?.......`...{.s.'
00BF0- 20 B0 F3 840000 7C 1C 18 B0 FF 0C 20 B0 7F 86' .....|..... ...'
00C00- 3A 0168 1C A6 02 FC 0C 0000 7C 1E 2F B0 7F E1 ':.h.......|./...'
00C10- 3A B0 738507 B0 F3 8040 B0 4F E1 47 B0 7385':.s.....@.O.G.s.'
00C20- 20 B0 F3 8060 B0 4F E1 67 B0 738557 B0 F3 84' ...`.O.g.s.W...'
00C30- 0000 7C 1C DE B7 BF A0 E5 B9 BF 60 DB B9 BF 80'..|........`....'
00C40- C7 A2 FD 1C DB BD BF A0 DE BB BF A0 05 C4 FF A0 '................'
00C50- 85 1B FF 1C 8E 3D FF 1C E3 B1 BF A0 1B B0 FF 3C '.....=.........<'
00C60- DA B7 BF A0 D8 B7 BF 4C DB B9 BF A0 E4 B9 BF 2C '.......L.......,'
00C70- DB B5 BF 84 B2 BC 7F 0C E5 CC FD 1C E3 C5 BF A0 '................'
00C80- 01 C4 FF 2C 85 1B FF 1C 90 3D FF 1C 5A B7 FF F6 '...,.....=..Z...'
00C90- B2 0E FD 0C 6F E3 FE 1C B2 BC 7F 0C C1 B0 FF 00'....o...........'
00CA0- 20 B0 7F 85 7E B0 4F E1 2E B0 F3 A0 96 3D FF 1C ' ...~.O......=..'
00CB0- 63 B9 FF F6 12 BC FF 0C B2 16 FD 0C 6F E3 FE 1C 'c...........o...'
00CC0- A2 55 FF 1C 4E B5 6B FA 0000 7C 1C B4 A4 7F 0C '.U..N.k...|.....'
00CD0- C1 B0 FF 0000 B0 7F F8 80 B0 7F 6228 E1 D6 0C '...........b(...'
00CE0- B3 B0 57 0C B5 A4 57 0C 700154 1C 60 B0 7F 86'..W...W.p.T.`...'
00CF0- 10 B2 EB E0 7E B0 578610 B2 EB 8090 3D EB 1C '....~.W......=..'
00D00- 7B B3 EB F6 8E 3D EB 1C 700168 1C 0D B0 7F 86'{....=..p.h.....'
00D10- 0B 1B EA 1C 00 B2 EB A0 96 3D D7 1C 01 B2 D7 80'.........=......'
00D20- 7001 7C 1C E2 B3 BF A0 02 B2 FF 2C D9 BB BF 20'p.|........,... '
00D30- E2 B3 BF A0 04 BA FF 24 DD B1 BF A0 92 3D FF 1C '.......$.....=..'
00D40- 89 B3 FF F6 0000 7C 1C D5 B1 BF A0 9601 7C 1C '......|.......|.'
00D50- 20 B0 FF A0 9601 7C 1C 0F B0 FF 60 0A B0 7F 85' .....|....`....'
00D60- 30 B0 F3 8037 B0 CF 8001 B0 FF 2C 69 B1 FF 0C '0...7......,i...'
00D70- 0D AE FF 0C F3 AF BF 80 0D AE 7F 0C 01 B0 FF 29'...............)'
00D80- DC CE 7F 0C 99 B1 7F FA 0000 7C 1C A2 55 FF 1C '..........|..U..'
00D90- 9F 0168 1C 0000 7C 1C 80 D0 FF 6817 D2 FF 0E '..h...|....h....'
00DA0- E8 D3 178616 D2 D7 0C A2 D0 57 0C 18 B0 D7 0C '..........W.....'
00DB0- 16 D0 D7 0C A2 D2 57 0C 0000 7C 1C 1700 7C 0E '......W...|...|.'
00DC0- A3 00 E9 0C 09 D8 FF A0 F3 D5 BF A4 01 D4 FF 38'...............8'
00DD0- B0 CD FF F8 0C D4 FF 0C 01 D6 FF 30 F3 D5 BF 80'...........0....'
00DE0- 0D D4 7F 0C D6 CC 7F 0D B2 D9 FF F6 18 D6 FF 28'...............('
00DF0- AB D6 7F 0C AB 01 7C 1C E6 AD BF 5425 AD FF 0D '......|....T%...'
00E00- F0 AC 7F 0C ED E1 8F A0 04 E0 CF 28 F0 E3 8F A4 '...........(....'
00E10- ED E1 8F 80 ED E3 8F 80 EE E5 8F A0 06 E4 CF 10'................'
00E20- F0 E5 0F E1 F1 E5 0F 85 EF E5 8F A0 03 E4 CF 10'................'
00E30- F0 E5 0F E1 F1 E5 0F 85 EF DB 8F 8003 DA CF 28'...............('
00E40- ED E7 8F A0 EE DB BF A0 EF DD BF A0 3A DE FF 0C '............:...'
00E50- BB DF 7F FA CF 01 7C 1C 5C 050000 FF FF 0100'......|.\.......'
00E60- 0D 280400 2D 8004008900000078 CF 68 9D '.(..-.......x.h.'
00E70- 3D 3D 2045 6E 6420 6F 662052 4F 4D 20 3D 3D '== End of ROM =='
It is now 128 bytes shorter than it used to be, since I've used this time during full-chip verification being done by Beau and Open Silicon to pack things more efficiently.
Here is the binary/HMAC-signed loader (it's only $70 longs and starts at $000):
'********************************************************'* *'* Propeller II ROM Booter *'* *'* Version 0.1 *'* *'* 11/01/2012 *'* *'********************************************************CON
rx_pin = 91
tx_pin = 90
spi_cs = 89
spi_ck = 88
spi_di = 87
spi_do = 86
base = $E80DAT''' Version (@$000)'byte"Prop2.0 "''' Shut down (@$008)'orgclkset h001+offset 'set clock to rc slowcogstop h200+offset 'stop cog0
offset
''' Entry, read fuses (@$010)'org
reps #256,@:fuse 'ready to read 256 fuses
setport #rx_pin 'set rx_pin port for bootingcogid fuse_read nr 'read fuses (172 fuses + 84 zeros)cogid fuse_read nr,wc'(last iteration initializes cnt to $00000000_00000001)add fuse_read,#1test fuse_read,#$1Fwz
:fusex rcr fuses,#1
:fuse if_zadd :fusex,h200
cogid spi_read nr 'disable fuses and enable cnt (spi_read[10..0] = 0)''' Attempt to boot from serial'
jnp monitor_ptr,#boot_flash 'if rx_pin is low, skip serial and boot from flashcall #rx_bit 'measure low rx calibration pulses (host $F9 -> %1..010011111..)mov threshold,delta 'and calculate thresholdcall #rx_bit '(any timeout results in flash boot)add threshold,delta
h001 shr threshold,#1'(9 lsb's are $001)mov count,#250'ready to receive/verify 250 lfsr bits
:lfsrin call #rx_bit 'receive bit ($FE/$FF) into ctest lfsr,#$01wz'get lfsr bit into nzif_c_eq_zjmp #boot_flash 'if mismatch, boot from flashtest lfsr,#$B2wc'advance lfsrrcl lfsr,#1djnz count,#:lfsrin 'loop for next bit inmov count,#250+8'ready to transmit 250 lfsr bits + 8 version bits
:lfsrout cmp count,#8wz'if last 8 bits, set lfsr so that version will be outputif_zmov lfsr,#$52'$52 results in version $20 being sent (%00000100)test lfsr,#$01wz'get lfsr/version bit into nz, z=1 on last iterationcall #wait_rx 'wait for rx low (convey incoming $F9 on rx_pin to $FE/$FF on tx_pin)
clrp #tx_pin 'make tx lowcall #wait_rx 'wait for rx high
setpnz #tx_pin 'make tx lfsr/version bitcall #wait_rx 'wait for rx low
setp #tx_pin 'make tx highcall #wait_rx 'wait for rx hightest lfsr,#$B2wc'advance lfsrrcl lfsr,#1djnz count,#:lfsrout 'loop for next bit outjmp #load 'serial handshake done, attempt to load from serial (z=1)''' Wait for rx low/high - if timeout, attempt to boot from flash'
wait_rx getcnt time 'ready timeoutadd time,timeout
:waitpxx waitpne rx_mask,rx_mask wc'wait for rx low/high with timeout
notb :waitpxx,#23'toggle waitpeq/waitpne
wait_rx_ret if_ncret'return if not timeout (boot_flash follows)''' Attempt to boot from flash'
boot_flash mov count,#4'ready for 3 resets and 1 read command
:cmd setp #spi_cs 'spi_cs high
clrp #spi_ck 'spi_ck low
reps #32,@:bit 'ready for 32 command bits
clrp #spi_cs 'spi_cs lowcmpr count,#1wc'first 3 commands = $FF_FF_FF_FF (reset)if_ncrol spi_read,#1wc,wz'last command = $03_00_00_00 (read from 0), z=0
setpc #spi_di
setp #spi_ck 'cycle spi_ck
:bit clrp #spi_ck
djnz count,#:cmd 'loop for next spi command''' Load from serial (z=1) or flash (z=0)'
load setptra loader_pgm 'load loader into base+$000..$7DF, HMAC into base+$7E0..$7FFmov count,h200 'ready to input $200 longs
:longmov bits,#32'ready to input 32 data bits
:bit if_zcall #rx_bit 'input serial bit (serial mode)if_nz getp #spi_do wc'input spi_do (flash mode)if_nz setp #spi_ck 'high spi_ck (flash mode)if_nz clrp #spi_ck 'low spi_ck (flash_mode)rcl data,#1'shift bit into longdjnz bits,#:bit 'loop, adequate time for next flash bitwrlong data,ptra++ 'store long in hub ram (ptra=base+$800 after)djnz count,#:long'loop for next long (count=0 after)''' Compute loader HMAC signature for loader authentication'' base+$000..$7DF = loader ($1F8 longs)' base+$7E0..$7FF = loader HMAC signature (8 longs)' base+$800..$81F = fuses, 1st half are HMAC key (8 longs)' base+$820..$83F = proper HMAC signature (8 longs)' base+$840..$843 = sha256 command interface (1 long)'
reps #8,#1'store 128-bit key + 44 extra fuses + 84 zero bits
setinda fuses 'into base+$800..$81Fwrlong inda++,ptra++ '(ptra = base+$820, afterwards)wrlong count,sha256_ptr 'clear sha256 command
setcog #1'launch sha256 in cog1coginit sha256_pgm,sha256_ptr
setinda begin_hmac 'do sha256 commands to compute proper loader hmacmov count,#3'ready for 3 commands: begin_hmac, hash_bytes, read_hash
:cmd wrlong inda++,sha256_ptr 'set command
:wait rdlong data,sha256_ptr wz'wait for command donetjnz data,#:wait
djnz count,#:cmd 'loop for next command (count=0, z=1 after)cogstop h001 'done with sha256, stop cog1''' If loader authenticates, run it'
reps #8,@:cmp'verify loader hmac signature (z=1 on entry)
setcog #0'ready to relaunch cog0 with loader/monitorrdlong bits,ptra[-$10] 'get loader hmac signature longrdlong data,ptra++ 'get proper hmac signature long
:cmpif_zcmp bits,data wz'compare, z=1 if authenticatedif_zcoginit loader_pgm,loader_ptr 'if loader authenticated, relaunch cog0 with loader''' Authentication failed, hide fuses and clear memory'
reps #$20000/8,@:clr 'clear all memorycogid monitor_pgm nr 'hide fuses (bit 10 set)wrlong count,ptra++ '(count=0)
:clr wrlong count,ptra++
''' If key <> 0, shut down - else, monitor'or fuses+0,fuses+1wz'check if 128-bit key = 0if_zor fuses+2,fuses+3wzif_nzmov monitor_pgm,#$008'if key <> 0, shut downcoginit monitor_pgm,monitor_ptr 'relaunch cog0 with shut down or monitor''' Receive bit (c) - compare incoming pulse to threshold'
rx_bit call #wait_rx 'wait for rx low
getcnt delta 'get timecall #wait_rx 'wait for rx high
subcnt delta 'get time deltacmp delta,threshold wc'compare time delta to threshold
rx_bit_ret ret''' Constants'
fuse_read long$200'(gets modified to $300)
timeout long20_000_000 / 1000 * 150'150ms @20MHz (rcfast)
rx_mask long1 << (rx_pin & $1F)
lfsr long"P"
spi_read long$03_000000
h200 long$200
begin_hmac long1<<30 + (($004<<2)-1)<<17 + base+$800'begin_hmac, loads key at base+$800 (4 longs)
hash_bytes long2<<30 + (($1F8<<2)-1)<<17 + base+$000'hash_bytes, hashes message at base+$000 ($1F8 longs)
read_hash long3<<30 + base+$820'read_hash, writes hash at base+$820 (8 longs)
sha256_pgm long$1D0'sha256 program address
sha256_ptr long base+$840'sha256 parameter (points to command)
loader_pgm long base+$000'loader program address
loader_ptr long base+$800'loader parameter (points to fuses)
monitor_pgm long$55C+$1B4'monitor program address
monitor_ptr long tx_pin<<9 + rx_pin 'monitor parameter (conveys pins)''' Variables'
fuses res8
count res1
bits res1
data res1
time res1
delta res1
threshold res1
Here is the SHA-256/HMAC program used to authenticate code (thanks to Pedward for making this happen):
'********************************************************'* *'* Propeller II ROM SHA-256/HMAC *'* *'* Version 0.1 *'* *'* 11/01/2012 *'* *'********************************************************'' Usage: commandlong := 0 'pre-clear command long' cognew($1D0, @commandlong) 'start SHA-256/HMAC in new cog'' Start here for HMAC: commandlong := 1<<30 + (keysize-1)<<17 + @key 'start HMAC with key of keysize bytes (1..64)' repeat while commandlong '(wait for command done)'' Start here for SHA-256: commandlong := 2<<30 + (msgsize-1)<<17 + @msg 'hash msg of msgsize bytes (1..8192)' repeat while commandlong '(wait for command done)'' {issue more 2<<30 commands if msg > 8192 bytes}'' commandlong := 3<<30 + @hashbuffer 'read resulting hash into hashbuffer (32 bytes)' repeat while commandlong '(wait for command done)'' {hasbuffer now contains result, ready for new 1<<30 or 2<<30 command}'DATorg
setf #%0_1111_0000'configure movf for sbyte0 -> {dbyte3,dbyte2,dbyte1,dbyte0,dbyte3,...}call #init_hash 'init hash, clear hmac mode, reset byte count''' Command Loop'
command rdlong x,ptra'wait for command (%cc_nnnnnnnnnnnnn_ppppppppppppppppp)tjz x,#command
setptrb x 'get pointer (%ppppppppppppppppp)mov count,x 'get count (%nnnnnnnnnnnnn)shl count,#2shr count,#2+17add count,#1'+1 for 1..8192 rangeshr x,#32-2'get command (%cc)
cachex 'invalidate cache for fresh rdbytec'sdjz x,#begin_hmac '1 = begin hmac, pointer @key (count+1 bytes, 1..64)djz x,#hash_bytes '2 = hash bytes, pointer @message (count+1 bytes, 1..8192)djz x,#read_hash '3 = read hash, pointer @hashbuffer (32 bytes)
done wrlong zero,ptra'clear command to signal donejmp #command 'get next command''' Begin HMAC'
begin_hmac call #end_hash 'end any hash in progress
:ipad mov x,#$00'get and hash ipad key (full block)cmpr count,bytes wc'after key bytes, hash $00's to fill blockif_c rdbytec x,ptrb++
xor x,#$36'xor bytes with ipad ($36)call #hash_byte '(last iteration triggers hash_block, z=1)if_nzjmp #:ipad
reps #16,#2'save opad key
setinds opad_key,w
mov indb,inda++
xor indb++,opad 'xor bytes with opad ($5C)mov hmac,#1'set hmac modejmp #done
''' Hash Bytes'
hash_bytes rdbytec x,ptrb++ 'hash bytescall #hash_byte
djnz count,#hash_bytes
jmp #done
''' Read Hash'
read_hash tjz hmac,#:not'if not hmac, output hashcall #end_hash 'hmac, end current hash
reps #16,#1'get opad key into w[0..15] (full block)
setinds w,opad_key
mov indb++,inda++
call #hash_block 'hash opad key
reps #8,#1'get hashx[0..7] into w[0..7]
setinds w,hashx
mov indb++,inda++
movd hash_byte,#w+8'account for opad key and hashx bytesmov bytes,#64+32'(1-1/2 blocks, 1/2 block needs end_hash)
:notcall #end_hash 'end current hash
setinda hashx 'store hashx[0..7] at pointer, big-endianmov count,#8
:out reps #4,#2mov x,inda++
rol x,#8wrbyte x,ptrb++
djnz count,#:out
jmp #done
''' End Hash - hash $80, any $00's needed to get to offset $38, then 8-byte length'
end_hash mov length,bytes 'get message length in bitsshl length,#3mov x,#$80'hash end-of-message byte ($80)
:fill call #hash_byte '(may trigger hash_block)mov x,bytes 'hash any $00's needed to get to offset $38and x,#$3Fcmp x,#$38wzmov x,#$00if_nzjmp #:fill
:len test bytes,#$04wc'hash 8-byte length, big-endianif_crol length,#8'(hash four $00's, then four length bytes)if_cmov x,length
call #hash_byte '(last iteration triggers hash_block)if_nzjmp #:len
reps #8,#1'save hash[0..7] into hashx[0..7]
setinds hashx,hash
mov indb++,inda++
init_hash reps #8,#1'copy hash_init[0..7] into hash[0..7]
setinds hash,hash_init
mov indb++,inda++
mov hmac,#0'clear hmac modemov bytes,#0'reset byte count
init_hash_ret
end_hash_ret ret''' Hash Byte - add byte to w[0..15] and hash block if full (z=1)'
hash_byte movf w,x 'store byte into w[0..15], big-endianadd bytes,#1'increment byte counttest bytes,#$03wz'every 4th byte, increment w pointerif_zadd hash_byte,d0
test bytes,#$3Fwz'every 64th byte, reset w pointerif_z movd hash_byte,#w
if_zcall #hash_block 'every 64th byte, hash block
hash_byte_ret ret''' Hash Block - first extend w[0..15] into w[16..63] to generate schedule'
hash_block reps #48,@:sch 'i = 16..63
setinds w+16,w+16-15+7'indb = @w[i], inda = @w[i-15+7]
setinda --7's0 = (w[i-15] -> 7) ^ (w[i-15] -> 18) ^ (w[i-15] >> 3)mov indb,inda--
mov x,indb
rol x,#18-7xor x,indb
ror x,#18shr indb,#3xor indb,x
add indb,inda 'w[i] = s0 + w[i-16]
setinda ++14's1 = (w[i-2] -> 17) ^ (w[i-2] -> 19) ^ (w[i-2] >> 10)mov x,inda
mov y,x
rol y,#19-17xor y,x
ror y,#19shr x,#10xor x,y
add indb,x 'w[i] = s0 + w[i-16] + s1
setinda --5'w[i] = s0 + w[i-16] + s1 + w[i-7]
:sch add indb++,inda
' Load variables from hash
reps #8,#1'copy hash[0..7] into a..h
setinds a,hash
mov indb++,inda++
' Do 64 hash iterations on variables
reps #64,@:itr 'i = 0..63
setinds k+0,w+0'indb = @k[i], inda = @w[i]mov x,g 'ch = (e & f) ^ (!e & g)xor x,f
and x,e
xor x,g
mov y,e 's1 = (e -> 6) ^ (e -> 11) ^ (e -> 25)rol y,#11-6xor y,e
rol y,#25-11xor y,e
ror y,#25add x,y 't1 = ch + s1add x,indb++ 't1 = ch + s1 + k[i]add x,inda++ 't1 = ch + s1 + k[i] + w[i]add x,h 't1 = ch + s1 + k[i] + w[i] + hmov y,c 'maj = (a & b) ^ (b & c) ^ (c & a)and y,b
or y,a
mov h,c
or h,b
and y,h
mov h,a 's0 = (a -> 2) ^ (a -> 13) ^ (a -> 22)rol h,#13-2xor h,a
rol h,#22-13xor h,a
ror h,#22add y,h 't2 = maj + s0mov h,g 'h = gmov g,f 'g = fmov f,e 'f = emov e,d 'e = dmov d,c 'd = cmov c,b 'c = bmov b,a 'b = aadd e,x 'e = e + t1mov a,x 'a = t1 + t2
:itr add a,y
' Add variables back into hash
reps #8,#1'add a..h into hash[0..7]
setinds hash,a
add indb++,inda++
hash_block_ret ret''' Defined data'
zero long0
d0 long1 << 9
opad long$36363636 ^ $5C5C5C5C
hash_init long$6A09E667, $BB67AE85, $3C6EF372, $A54FF53A, $510E527F, $9B05688C, $1F83D9AB, $5BE0CD19'fractionals of square roots of primes 2..19
k long$428A2F98, $71374491, $B5C0FBCF, $E9B5DBA5, $3956C25B, $59F111F1, $923F82A4, $AB1C5ED5'fractionals of cube roots of primes 2..311long$D807AA98, $12835B01, $243185BE, $550C7DC3, $72BE5D74, $80DEB1FE, $9BDC06A7, $C19BF174long$E49B69C1, $EFBE4786, $0FC19DC6, $240CA1CC, $2DE92C6F, $4A7484AA, $5CB0A9DC, $76F988DAlong$983E5152, $A831C66D, $B00327C8, $BF597FC7, $C6E00BF3, $D5A79147, $06CA6351, $14292967long$27B70A85, $2E1B2138, $4D2C6DFC, $53380D13, $650A7354, $766A0ABB, $81C2C92E, $92722C85long$A2BFE8A1, $A81A664B, $C24B8B70, $C76C51A3, $D192E819, $D6990624, $F40E3585, $106AA070long$19A4C116, $1E376C08, $2748774C, $34B0BCB5, $391C0CB3, $4ED8AA4A, $5B9CCA4F, $682E6FF3long$748F82EE, $78A5636F, $84C87814, $8CC70208, $90BEFFFA, $A4506CEB, $BEF9A3F7, $C67178F2''' Undefined data'
hmac res1
bytes res1
count res1
length res1
opad_key res16
hash res8
hashx res8
w res64
a res1
b res1
c res1
d res1
e res1
f res1
g res1
h res1
x res1
y res1
And here's the monitor, shrunk and improved:
[code]
'********************************************************
'* *
'* Propeller II ROM Monitor *
'* *
'* Version 0.1 *
'* *
'* 11/01/2012 *
'* *
'********************************************************
'
' Usage: cognew($738, tx_pin << 9 + rx_pin) 'start monitor in new cog
'
cmd_loop call #parse 'parse next term
cmd_go if_nz jmp #cmd_hex 'if hex, branch
movd pinx,#z 'pin update redirected to z
setptra #branch1_ 'not hex, vector by chr
call #vector 'if returns, no match
cmd_hex mov v1,value 'hex, save v1
movd pinx,#pin 'pin update okay
setptra #branch2_ 'vector by chr
call #vector 'if returns, no match
jmp #cmd_view2 'view data
cmd_range call #parse_next 'hex., get hex
if_z jmp #cmd_viewp2 'if no hex, view data
mov v2,value 'hex.hex, save v2
setptra #branch3_ 'vector by chr
call #vector 'if returns, no match
jmp #cmd_view3 'view data
'
'
' Byte/word/long data
'
cmd_byte mov wsize,#1 wz 'set byte mode, z=0
cmd_word if_z mov wsize,#2 wz 'set word mode, z=0
cmd_long if_z mov wsize,#4 'set long mode
call #set_size
jmp #cmd_next 'next command
'
'
' View data
'
cmd_viewl mov v2,#$F '<enter> (eol), show line of data
call #tx_range1
jmp #cmd_new
cmd_viewp mov v2,#$FF '. (more), show page of data
call #tx_range1
jmp #cmd_next
cmd_viewp2 mov v2,#$FF 'addr. (more), show page of data
call #tx_range2
jmp #cmd_loop
cmd_view2 mov v2,v1 'addr, show unit of data
cmd_view3 call #tx_range 'addr.addr, show range of data
jmp #cmd_loop
'
'
' Search
'
cmd_search mov v1,view '/, search from view to end
cmd_search2 mov v2,amask 'addr/, search from address to end
cmd_search3 call #check_range 'addr.addr/, search range
call #parse_data 'parse data string
:start setptra v1 'start search, point to search address
setinda 0 'point to search data
mov x,#0 'reset word match counter
:word call #rdxxxx 'get memory word
cmp value,inda++ wz 'compare against search data word
if_z jmp #:match 'if word match, check if string match
add v1,wsize 'word mismatch, advance search address
cmp v1,v2 wz,wc 'at end of range?
if_be jmp #:start 'if not, start next search
:match incmod x,dsize wc 'word match, increment match counter
if_nc jmp #:word 'if more words to match, compare next word
mov v2,dsize 'got string match
shl v2,shift 'v1 = start of found data
add v2,v1 'v2 = end of found data
jmp #cmd_view3 'show found data
'
'
' Enter data
'
cmd_enter3 call #check_range 'addr.addr:, check range, z=words to fill
mov y,#1 'set fill flag
cmd_enter2 mov enter,v1 'addr:, set enter address
and enter,amask 'trim enter address (in case cmd_enter2)
cmd_enter call #parse_data ':, parse data
tjnz y,#:go 'if not fill, set z to data size
mov z,dsize
add z,#1
:go setptrb enter 'get pointer
:loop mov value,inda++ 'get word from string data
call #wrxxxx 'store value in memory
djnz z,#:loop 'loop until enter done
mov z,v2 'get number of words
sub z,v1
shr z,shift
add z,#1
check_range_ret ret
'
'
' Set rdxxxx/wrxxxx and others by word size
'
set_size test wsize,#%010 wc 'set rdxxxx/wrxxxx by word size
setbc rdxxxx,#26
setbc wrxxxx,#26
test wsize,#%100 wc
setbc rdxxxx,#27
setbc wrxxxx,#27
mov shift,wsize 'set shift by word size
shr shift,#1
mov amask,wsize 'set amask by word size
sub amask,#1
xor amask,h0001FFFF
and view,amask 'trim view
and enter,amask 'trim enter
set_size_ret ret
rdxxxp getp v1 wc 'read pin as "0" or "1"
if_nc mov value,#0
if_c mov value,#1
rdxxxj jmp #rdxxxx_ret 'd = rdxxxx_ret/rdxxxm
rdxxxm setptra v1 'read mem
rdxxxx rdbyte value,ptra++ 'rdbyte/rdword/rdlong
rdxxxp_ret
rdxxxx_ret ret
wrxxxx wrbyte value,ptrb++ 'wrbyte/wrword/wrlong
wrxxxx_ret ret
'
'
' Input line
'
rx_line setspa #0 'point to start of line
mov x,#">" 'show prompt
call #tx
call #rx 'get first chr
cmp x,#"'" wz 'check for repeat
if_nz jmp #:first 'if not repeat, first chr
:show popar x wz 'repeat, show line
if_nz call #tx
if_nz jmp #:show
jmp #:done
call #rx_check 'check key hit
if_z tjnz z,#:line 'if no key hit and more words left, print another line
tx_range1_ret
tx_range2_ret
tx_range_ret ret
'
'
' Print string (@ptra)
'
tx_string addptra base 'add data base pointer
tx_string_loop rdbyte x,ptra++ 'get chr
tx_string_ret tjz x,#0 'if 0, done
test x,#$80 wz 'substring?
if_nz notb tx_string_loop,#8 'toggle ptra/ptrb
if_nz setptrb x 'ptrb points to substring
if_nz addptrb base
if_nz jmp #tx_string_loop 'start substring or resume string
:loop add w,period 'add bit period to time
passcnt w 'loop until bit period elapsed
shr x,#1 wc 'get next bit into c
setpc tx_pin 'write c to tx pin
tjnz x,#:loop 'loop until bits done
tx_dspace_ret
tx_space_ret
tx_nib_ret
tx_ret ret
'
'
' Receive chr (x)
'
rx call #rx_check 'wait for rx chr
if_z jmp #rx
rx_ret ret
'
'
' Check receiver, z=0 if chr (x)
'
rx_check or rx_tail,#$80 'if start or rollover, reset tail
'************************
'* Serial Receiver Task *
'************************
rx_task chkspb wz 'if start or rollover, reset head
if_z setspb #$80
mov rx_bits,#9 'ready for 8 data bits + 1 stop bit
neg rx_time,period 'get -0.5 period
sar rx_time,#1
jp rx_pin,#$ 'wait for start bit
subcnt rx_time 'get time + 0.5 period for initial 1.5 period delay
:bit rcr rx_data,#1 'rotate c into byte
add rx_time,period 'add 1 period
passcnt rx_time 'wait for center of next bit
getp rx_pin wc 'read rx pin into c
djnz rx_bits,#:bit 'loop until 8 data bits + 1 stop bit received
shr rx_data,#32-8 'align byte
pushb rx_data 'store byte at head, inc head
One thing I'm are curious Why You not implemented Intel HEX loader in monitor with checksum cheking.
That have ben nice to use as Loader from any Terminal program.
Ps. In 8080 assembly it is only some lines of code.
Because it's burdensome to have to remember how to compose Intel Hex lines and compute those checksum bytes. That's work for a computer, not a person. The monitor has a checksum command that can sum data within an address range in whatever mode you are are in (bytes/word/long) and return a 32-bit sum. You could just do one of those after loading your code and make sure it comes back with what you expect.
With Intel HEX Loader it is possible to have automated Loader that can know what place in memory I will place my data. And automatically test after every line if transfer was correct.
Because it's burdensome to have to remember how to compose Intel Hex lines and compute those checksum bytes. That's work for a computer, not a person. The monitor has a checksum command that can sum data within an address range in whatever mode you are are in (bytes/word/long) and return a 32-bit sum. You could just do one of those after loading your code and make sure it comes back with what you expect.
With Intel HEX Loader it is possible to have automated Loader that can know what place in memory I will place my data. And automatically test after every line if transfer was correct.
In steps You describe it is impossible.
Here is how you'd enter code with the monitor and get a checksum:
=== Propeller II Monitor ===
>1000:5072 6F 7032 2E 30200020 7C 0C 03 D0 7C 0C
>1010:45 FE C1 0D E3 B6 FC 0C 01 C2 7C 0C 01 C2 7C 0D
>1020:01 C2 FC 80 1F C2 7C 6201 E0 FC 3066 0C A8 80
>1030:01 CA 7C 0C 2A DE FC FA 5B C0 FC 1C 7C FA BC A0
>1000.103F^
00001C98
>
Here is Intel Hex (as used by Altera's FPGA tool):
BUT still Alteras HEX not give complete hex code. It is missing last line in it - That are not necessary in it BUT important in CPU's (computers).
It is starting point of loaded code to automatically start that Loaded program.
In time I worked with control systems only possibility to update systems I have build was 300 baud modem -- And with Intel hex it give me possibility to Update them from Malmoe even if them was placed in Stockholm.
I see Yours monitors possibility to show me HEX but still show me how I can use it with automated LOADER that can use simple serial communication ---- That Load code from serial test it if it is correct -- And then start it without my intervention.
Here is how you'd enter code with the monitor and get a checksum:
=== Propeller II Monitor ===
>01000:5072 6F 7032 2E 30200020 7C 0C 03 D0 7C 0C
>01010:45 FE C1 0D E3 B6 FC 0C 01 C2 7C 0C 01 C2 7C 0D
>01020:01 C2 FC 80 1F C2 7C 6201 E0 FC 3066 0C A8 80
>01030:01 CA 7C 0C 2A DE FC FA 5B C0 FC 1C 7C FA BC A0
>1000.103F^
00001C98
>
Here is Intel Hex (as used by Altera's FPGA tool):
BUT still Alteras HEX not give complete hex code. It is missing last line in it - That are not necessary in it BUT important in CPU's (computers).
It is starting point of loaded code to automatically start that Loaded program.
In time I worked with control systems only possibility to update systems I have build was 300 baud modem -- And with Intel hex it give me possibility to Update them from Malmoe even if them was placed in Stockholm.
I see Yours monitors possibility to show me HEX but still show me how I can use it with automated LOADER that can use simple serial communication ---- That Load code from serial test it if it is correct -- And then start it without my intervention.
After you load the hub memory, you can start a cog from it. For example, if you wanted to restart cog0 (which is running the monitor) with a program at $1000, you'd just type "0+1000" that would start cog0 at $1000.
So my question are -- Can I in time I Load that program in memory some 1000 Km by simple serial modem be sure as it loaded correctly so it can be Started.
If I load in my systems that Intel HEX LOADER automatically check for errors and only start that code if error free.
If not give me prompt with info on load error.
Ps. It is not as I say You need implement that -- BUT only debate with You what are usable.
Lets say I send system with Propeller II up in one balloon and then see I need update it by some serial interface as simply as possible -- BUT need have security that will work correctly.
Steps You describe -- NOT give me automated update possibility's.
It is line that are missing in Altera HEX code that give automated Start of Loaded code.
Line to start loaded code - xx checksum of this line
:0000 1000 XX
Ps 2. --- I see I need add to my signature line You wreit on --- And see it is usable
After you load the hub memory, you can start a cog from it. For example, if you wanted to restart cog0 (which is running the monitor) with a program at $1000, you'd just type "0+1000" that would start cog0 at $1000.
3. your remote loader program checks if this is correct and if not repeats the steps 1 and 2
4. if all is fine you start your code where you want with
cog+adr{+adr} - Start
so the only difference I see to your approach is that the check if the checksum is correct is done on the loader program and not inside the loaded PROP2
If you like you can even do this line by line
load the line, calc checksum, if ok proceed, else resend the line.
But for automated HEX loader it need have possibility to send from Terminal simple text file in Intel HEX that MONITOR automatically load in correct place and if al OK then START it without any extra commands from You !!
3. your remote loader program checks if this is correct and if not repeats the steps 1 and 2
4. if all is fine you start your code where you want with
so the only difference I see to your approach is that the check if the checksum is correct is done on the loader program and not inside the loaded PROP2
If you like you can even do this line by line
load the line, calc checksum, if ok proceed, else resend the line.
After you load the hub memory, you can start a cog from it. For example, if you wanted to restart cog0 (which is running the monitor) with a program at $1000, you'd just type "0+1000" that would start cog0 at $1000.
Are there any (effortless) means of patching only part of the running monitor, perhaps a new command to control that behavior, to extend (or ablate) funcionality without having to serialy re-send and re-check the entire (new) monitor then stoping, loading and restarting Cog 0?
Can that be done by the use of self modifying code that acts based on Hub memory contents detected by the running monitor and/or a specific triggering event (command, piece of code or anything else)?
I *REALLY* like the monitor - it will be extremely handy.
BUT
What did you end up doing with the direct mode of {RD|WR}{BYTE|WORD|LONG|QUAD} ?
The reason I ask that with the rom in low memory, the direct mode for the instructions would now be useless; knowing you, I expect you would have found a new use for it... I am guessing one of:
A) added the extra bit to the offset moved the direct addressing to the end of memory (by substituting all 1's instead of all 0's when it is used)
C) using it to select from among four pointer registers (instead of two)
Inquiring minds want to know...
(I suspect it is either A or B, C would be a pretty big change)
I *REALLY* like the monitor - it will be extremely handy.
BUT
What did you end up doing with the direct mode of {RD|WR}{BYTE|WORD|LONG|QUAD} ?
The reason I ask that with the rom in low memory, the direct mode for the instructions would now be useless; knowing you, I expect you would have found a new use for it... I am guessing one of:
A) added the extra bit to the offset moved the direct addressing to the end of memory (by substituting all 1's instead of all 0's when it is used)
C) using it to select from among four pointer registers (instead of two)
Inquiring minds want to know...
(I suspect it is either A or B, C would be a pretty big change)
Regards,
Bill
There is no more direct addressing for RDxxxx/WRxxxx instructions. Any immediate #S value is treated as a pointer. So, I think "A" is the answer, if I understand.
Are there any (effortless) means of patching only part of the running monitor, perhaps a new command to control that behavior, to extend (or ablate) funcionality without having to serialy re-send and re-check the entire (new) monitor then stoping, loading and restarting Cog 0?
Can that be done by the use of self modifying code that acts based on Hub memory contents detected by the running monitor and/or a specific triggering event (command, piece of code or anything else)?
(crossing my fingers and praying here
Yanomani
I don't understand exactly what you are asking, but it sounds like you would like the monitor to have a restricted mode where it only allows a subset of commands to enable a verifiable download-and-execute procedure?
I don't understand. A monitor is not a development system. You'll still need a tool on the host to compile or assemble code and download it into the P2 chip. This is really no different from the way P1 works. I guess you could use the monitor as a "development environment" if you like entering your code in hex. Is that what you mean?
I wasn't comparing P2 to P1, but P2 to most of the 32-bit embedded world.
You are certainly right...a monitor is not a development system. That's why I referred to it as a giant leap toward that end. It's a needed hook, especially if you're taking an incremental approach like I intend to do.
Of course the P2 has other resources that would also contribute to it hosting a development system: More screen memory, and more hooks to fast external memory.
Great, I can get started on P2, with my Tandy Model 100 now! Just having a little fun.
That's really not so far-fetched an idea. I did a lot of in-field program loading, testing and debugging on my Z8671 systems with a Model 100. They were a great little machine for that and easy for field personnel to understand and use. In fact, they are still being used by loyal fans:
I know it's not. I use mine on occasion for notes on a meeting and such. It's always hilarious! Many people recognize it, and the discussion is always a good one. Great little computer. Got mine mint for a song out of a thrift store last year. It was $10, and I could not resist. Great curio. Everybody comes in with laptops, cords and the usual stuff. I just turn it on, in my lap and go, near instantly. When the right people are in the building, I find the entertainment worth it. The rest of the time, it is on my desk, with somebody tinkering with it every week.
The keyboard is awesome! Heck, maybe I can gut another one for other uses. The thing runs about 20 hours on a nice set of batteries. And that's 20 hours just ON. If one is careful about not leaving it on, it's not unusual to go a week, using it when needed.
I'm now wondering whether or not somebody did an 80 or 64 column display ROM for it.
Could use the Apple as well. And I will too, just for some fun.
Honestly, a P2 with some external RAM can probably do reasonable development. Bet we see a prop only system within a year. Can't wait, because I may well gut something, get that all installed and run portable, all prop! I've been collecting displays and such for that purpose as I find them cheap.
Not sure what such a system would look like yet, but I know it will have two SD card slots, display, keyboard, battery, I/O, RAM. Lots of time for that once P2 gets completed.
NO -- My thinking was have alternate Loader -- That can load Simple ASCI HEX file from any terminal program and execute it.
If You read entire Forum You will find that many people have problems with Load Propeller from all type of wireless serial communication.
With Intel HEX Loader I talk on - that problem can be resolved.
Ps. That give possibility to use send FILE mode in terminal program to load and start code automaticaly
Ps 2. --- That system give possibility to update Program code by any type of Radio / Serial -Link.
I'd agree with this, part of the terminal access cut/paste/copy/send file facility, should include blocks of intel hex.
Things like Help strings, really do not need to be consuming valuable RAM space - put them in the terminal.
Also things like Move and Fill and even Search, those can easily be done from a configured terminal, and are so rare
the speed difference is not going to matter.
In contrast, the RAM space is precious, and needed by everyone.
Instead, put stuff in the smallest possible Monitor that allows human and non-human systems to easily slave the Prop II.
Intel hex is universal, and comes from many tools, and a tiny micro can either compose Intel Hex, or Block-copy it.
Given all intel hex lines start with :, it should be a safe syntax to include.
This also give you a simple way to transport library files, that turn this into a really useful I/O Expander.
Intel hex also allows comments, and you can append any single 'Load and go' line you like.
Any common comment tag can be used ; or // or -- ; is my first guess, but may be close to :
Someone can Select the I/O Function Library(s) from the configured terminal (or just paste it in), and then connect and test with their Host,
and when they have decided that works, they paste their HEX library into their Host-loader, and they are on-air.
They do not need to know any PASM, and it is a safe-step from terminal to field, as they can compose a single text script like file as they work.
This target user is a total Prop II novice, but they are system experts. Make integration easy for them.
Comments
It is more universally accessible than the binary/HMAC-signed downloader because it sends and receives only standard ASCII characters $20..$7E (space.."~").
Some programming languages, serial interfaces, and OS's have issues with sending and receiving full binary ($00..$FF). For this reason, you might have to jump through some hoops to get the more-efficient binary downloader working on a given host system. The monitor, on the other hand, can talk to anything that speaks serial, without concern over non-ASCII characters. It is so simple that it can't NOT work on any host machine that has a serial port. Plus, it doesn't force an ordered protocol, but is conversational in operation. I've been using the Parallax Serial Terminal program to talk to it as well as PUTTY, which is free on the 'net and very tidy.
My thinking might be a little anachronistic, but I've seen many host-level systems which are big on brains and storage, but for which the serial interfaces were fleeting afterthoughts, and full binary can trigger unwanted events. The monitor will play politely and offer no offense to any host.
The reason I put a help menu in the monitor was so that you could quickly get command syntax without having to refer to any documents. You might launch the monitor from within an app you want to debug and you'll need to search memory for a string of data to get your bearings. The help menu will be handy then.
Here is the ROM now:
=== Propeller II Monitor === >0.e7f 00000- 50 72 6F 70 32 2E 30 20 00 20 7C 0C 03 D0 7C 0C 'Prop2.0 . |...|.' 00010- 45 FE C1 0D E3 B6 FC 0C 01 C2 7C 0C 01 C2 7C 0D 'E.........|...|.' 00020- 01 C2 FC 80 1F C2 7C 62 01 E0 FC 30 66 0C A8 80 '......|b...0f...' 00030- 01 CA 7C 0C 2A DE FC FA 5B C0 FC 1C 7C FA BC A0 '..|.*...[...|...' 00040- 5B C0 FC 1C 7C FA BC 80 01 FA FC 28 FA F0 FC A0 '[...|......(....' 00050- 5B C0 FC 1C 01 C8 7C 62 2A 00 64 1C B2 C8 7C 61 '[.....|b*.d...|a' 00060- 01 C8 FC 34 10 F0 FC F6 02 F1 FC A0 08 F0 7C 86 '...4..........|.' 00070- 52 C8 E8 A0 01 C8 7C 62 25 52 FC 1C DA B4 FC 0C 'R.....|b%R......' 00080- 25 52 FC 1C DF B4 FC 0C 25 52 FC 1C DB B4 FC 0C '%R......%R......' 00090- 25 52 FC 1C B2 C8 7C 61 01 C8 FC 34 17 F0 FC F6 '%R....|a...4....' 000A0- 35 00 7C 1C 0D F6 FC 0C 62 F6 BC 80 63 C6 BC FF '5.|.....b...c...' 000B0- 37 4F FC 0C 00 00 4C 1C 04 F0 FC A0 DB B2 FC 0C '7O....L.........' 000C0- DA B0 FC 0C 44 3E C0 0D DA B2 FC 0C 01 F0 7C E1 '....D>........|.' 000D0- 01 CA CC 27 DC AE FC 0C DB B0 FC 0C DA B0 FC 0C '...'............' 000E0- 2B F0 FC F6 B2 D8 7C 0C 66 F0 BC A0 20 F2 FC A0 '+.....|.f... ...' 000F0- 5B C0 E8 1C D6 AC D4 0D DB B0 D4 0C DA B0 D4 0C '[...............' 00100- 01 F4 FC 34 38 F2 FC F6 C1 F4 7C 08 37 F0 FC F6 '...48.....|.7...' 00110- 40 0E C0 0D 70 00 04 E0 C1 EC 53 08 6B F0 3C 08 '@...p.....S.k.<.' 00120- E0 02 FC 0C 6B D4 3C 0C 67 00 04 E0 03 F0 FC A0 '....k.<.g.......' 00130- 6B EC 13 08 6B F4 BC 0A 49 F4 7C FA 48 F0 FC F6 'k...k...I.|.H...' 00140- 03 1C 7C 0C 42 0E C0 0D E0 00 FC 0C 30 F2 FC 08 '..|.B.......0...' 00150- C1 F4 FC 08 7A F2 28 86 6D D8 28 0C 41 FE FF 0F '....z.(.m.(.A...' 00160- 01 DC 7C 0C C1 F0 7C 08 C1 F0 7C 08 71 E0 BC 6A '..|...|...|.q..j' 00170- 73 E4 A8 6A 08 DC D4 A0 6F DC 3C 0C 25 52 FC 1C 's..j....o.<.%R..' 00180- 0D F8 FC 0C 25 52 FC 1C 0C F8 FC 0C 7D F8 3C 85 '....%R......}.<.' 00190- 00 00 7C 1C 00 02 00 00 C0 C6 2D 00 00 00 00 08 '..|.......-.....' 001A0- 50 00 00 00 00 00 00 03 00 02 00 00 80 16 1E 40 'P..............@' 001B0- 80 0E BE 8F A0 16 00 C0 D0 01 00 00 C0 16 00 00 '................' 001C0- 80 0E 00 00 80 16 00 00 10 07 00 00 5B B4 00 00 '............[...' 001D0- CA E0 FD 0C 46 96 FC 1C 00 9E FE 08 02 9E 7E F8 '....F.........~.' 001E0- B3 9E 7E 0C 4F CB BD A0 02 CA FD 2C 13 CA FD 28 '..~.O......,...(' 001F0- 01 CA FD 80 1E 9E FE 28 08 00 7C 0C 10 9E FE F4 '.......(..|.....' 00200- 1D 9E FE F4 21 9E FE F4 00 30 7D 08 02 00 7C 1C '....!....0}...|.' 00210- 35 96 FC 1C 00 9E FE A0 E4 CA 3D E1 C1 9F F2 01 '5.........=.....' 00220- 36 9E FE 6C 4C A6 FC 1C 11 00 54 1C 41 1E C0 0D '6..lL.....T.A...' 00230- 07 CF 15 E0 F6 EF 87 A0 9A EE 93 6C 01 C6 FD A0 '...........l....' 00240- 0E 00 7C 1C C1 9F FE 01 4C A6 FC 1C 1D CA FD F6 '..|.....L.......' 00250- 0E 00 7C 1C 2C C6 7D F8 35 96 FC 1C 40 1E C0 0D '..|.,.}.5...@...' 00260- E7 0E 16 E0 F6 EF 97 A0 54 2E FD 1C 40 0E C0 0D '........T...@...' 00270- FF 0E 16 E0 F6 EF 97 A0 0F 99 FC 54 60 C8 FD A0 '...........T`...' 00280- 35 96 FC 1C FF 00 04 E0 08 CA FD A0 41 06 C0 0D '5...........A...' 00290- F6 9F 86 A0 08 9E FE 24 C1 9F 7E 00 2F CA FD F6 '.......$..~./...' 002A0- 0E 00 7C 1C E4 CC BD A0 03 CC FD 2C 80 9E FE A0 '..|........,....' 002B0- 4C A6 FC 1C E4 9E BE A0 3F 9E FE 60 38 9E 7E 86 'L.......?..`8.~.' 002C0- 00 9E FE A0 38 00 54 1C 04 C8 7D 61 08 CC F1 24 '....8.T...}a...$' 002D0- E6 9E B2 A0 4C A6 FC 1C 3E 00 54 1C 40 0E C0 0D '....L...>.T.@...' 002E0- F7 FE 15 E0 F6 EF 97 A0 40 0E C0 0D 9B EE 15 E0 '........@.......' 002F0- F6 EF 97 A0 00 C6 FD A0 00 C8 FD A0 00 00 7C 1C '..............|.' 00300- 4F 0F 3E 14 01 C8 FD 80 03 C8 7D 62 99 98 A8 80 'O.>.......}b....' 00310- 3F C8 7D 62 07 99 E8 54 54 2E E9 1C 00 00 7C 1C '?.}b...TT.....|.' 00320- 53 5E C0 0D 0F 2F 16 E0 F9 01 0C E0 F6 EF 8B A0 'S^.../..........' 00330- F7 9F 82 A0 0B 9E FE 24 F7 9F 82 6C 12 9E FE 20 '.......$...l... ' 00340- 03 EE C3 28 4F EF 83 6C F6 EF 83 80 0E 00 0C E0 '...(O..l........' 00350- F6 9F 82 A0 4F A1 BE A0 02 A0 FE 24 4F A1 BE 6C '....O......$O..l' 00360- 13 A0 FE 20 0A 9E FE 28 50 9F BE 6C 4F EF 83 80 '... ...(P..lO...' 00370- FB 01 0C E0 F6 EF 93 80 40 0E C0 0D F7 8E 16 E0 '........@.......' 00380- F6 EF 97 A0 64 7E C0 0D 07 47 15 E0 4D 9F BE A0 '....d~...G..M...' 00390- 4C 9F BE 6C 4B 9F BE 60 4D 9F BE 6C 4B A1 BE A0 'L..lK..`M..lK...' 003A0- 05 A0 FE 24 4B A1 BE 6C 0E A0 FE 24 4B A1 BE 6C '...$K..l...$K..l' 003B0- 19 A0 FE 20 50 9F BE 80 F7 9F 86 80 F6 9F 86 80 '... P...........' 003C0- 4E 9F BE 80 49 A1 BE A0 48 A1 BE 60 47 A1 BE 68 'N...I...H..`G..h' 003D0- 49 9D BE A0 48 9D BE 68 4E A1 BE 60 47 9D BE A0 'I...H..hN..`G...' 003E0- 0B 9C FE 24 47 9D BE 6C 09 9C FE 24 47 9D BE 6C '...$G..l...$G..l' 003F0- 16 9C FE 20 4E A1 BE 80 4D 9D BE A0 4C 9B BE A0 '... N...M...L...' 00400- 4B 99 BE A0 4A 97 BE A0 49 95 BE A0 48 93 BE A0 'K...J...I...H...' 00410- 47 91 BE A0 4F 97 BE 80 4F 8F BE A0 50 8F BE 80 'G...O...O...P...' 00420- 40 0E C0 0D 47 EF 15 E0 F6 EF 97 80 00 00 7C 1C '@...G.........|.' 00430- 00 00 00 00 00 02 00 00 6A 6A 6A 6A 67 E6 09 6A '........jjjjg..j' 00440- 85 AE 67 BB 72 F3 6E 3C 3A F5 4F A5 7F 52 0E 51 '..g.r.n<:.O..R.Q' 00450- 8C 68 05 9B AB D9 83 1F 19 CD E0 5B 98 2F 8A 42 '.h.........[./.B' 00460- 91 44 37 71 CF FB C0 B5 A5 DB B5 E9 5B C2 56 39 '.D7q........[.V9' 00470- F1 11 F1 59 A4 82 3F 92 D5 5E 1C AB 98 AA 07 D8 '...Y..?..^......' 00480- 01 5B 83 12 BE 85 31 24 C3 7D 0C 55 74 5D BE 72 '.[....1$.}.Ut].r' 00490- FE B1 DE 80 A7 06 DC 9B 74 F1 9B C1 C1 69 9B E4 '........t....i..' 004A0- 86 47 BE EF C6 9D C1 0F CC A1 0C 24 6F 2C E9 2D '.G.........$o,.-' 004B0- AA 84 74 4A DC A9 B0 5C DA 88 F9 76 52 51 3E 98 '..tJ...\...vRQ>.' 004C0- 6D C6 31 A8 C8 27 03 B0 C7 7F 59 BF F3 0B E0 C6 'm.1..'....Y.....' 004D0- 47 91 A7 D5 51 63 CA 06 67 29 29 14 85 0A B7 27 'G...Qc..g))....'' 004E0- 38 21 1B 2E FC 6D 2C 4D 13 0D 38 53 54 73 0A 65 '8!...m,M..8STs.e' 004F0- BB 0A 6A 76 2E C9 C2 81 85 2C 72 92 A1 E8 BF A2 '..jv.....,r.....' 00500- 4B 66 1A A8 70 8B 4B C2 A3 51 6C C7 19 E8 92 D1 'Kf..p.K..Ql.....' 00510- 24 06 99 D6 85 35 0E F4 70 A0 6A 10 16 C1 A4 19 '$....5..p.j.....' 00520- 08 6C 37 1E 4C 77 48 27 B5 BC B0 34 B3 0C 1C 39 '.l7.LwH'...4...9' 00530- 4A AA D8 4E 4F CA 9C 5B F3 6F 2E 68 EE 82 8F 74 'J..NO..[.o.h...t' 00540- 6F 63 A5 78 14 78 C8 84 08 02 C7 8C FA FF BE 90 'oc.x.x..........' 00550- EB 6C 50 A4 F7 A3 F9 BE F2 78 71 C6 12 00 2A 59 '.lP......xq...*Y' 00560- 2B 57 2C 4E 32 2E 3B 2F 55 3A A1 4D AD 4C AE 48 '+W,N2.;/U:.M.L.H' 00570- AF 54 B0 5A B1 52 9E 51 BD 3F 00 38 00 38 20 24 '.T.Z.R.Q.?.8.8 $' 00580- 2E 3C 2F 53 3A 82 40 8F 2A 96 2B 9F 2D AD 4C AE '.</S:.@.*.+.-.L.' 00590- 48 AF 54 B0 5A B1 52 80 23 B6 7C BB 5C 00 39 00 'H.T.Z.R.#.|.\.9.' 005A0- 39 20 3D 2F 51 3A 5F 3E 5F 3C 77 5E 00 0D 0D 3D '9 =/Q:_>_<w^...=' 005B0- 3D 3D 20 50 72 6F 70 65 6C 6C 65 72 20 49 49 20 '== Propeller II ' 005C0- 4D 6F 6E 69 74 6F 72 20 3D 3D 3D 0D 0D 00 3F 20 'Monitor ===...? ' 005D0- 2D 20 48 65 6C 70 0D 07 00 48 69 74 20 53 50 41 '- Help...Hit SPA' 005E0- 43 45 00 20 20 27 00 27 0D 00 20 2D 0D 80 7B 61 'CE. '.'.. -..{a' 005F0- 64 72 7B 2E 61 64 72 7D 7D 80 7B 64 61 74 7B 20 'dr{.adr}}.{dat{ ' 00600- 64 61 74 7D 7D 80 61 64 72 80 0D 7E 48 55 42 8E 'dat}}.adr..~HUB.' 00610- 92 60 56 69 65 77 0D 92 2F 9E 60 53 65 61 72 63 '.`View../.`Searc' 00620- 68 0D 92 3A 9E 60 45 6E 74 65 72 0D AA 2E AA 5B 'h..:.`Enter....[' 00630- 3C 2F 3E 5D AA 60 4D 6F 76 65 0D AA 2E AA 5E 60 '</>].`Move....^`' 00640- 43 68 65 63 6B 73 75 6D 0D AA 40 60 57 61 74 63 'Checksum..@`Watc' 00650- 68 0D 5B 59 2F 57 2F 4E 5D 60 42 79 74 65 2F 77 'h.[Y/W/N]`Byte/w' 00660- 6F 72 64 2F 6C 6F 6E 67 0D 7E 43 4F 47 53 8E 63 'ord/long.~COGS.c' 00670- 6F 67 2B AA 7B 2B AA 7D 60 53 74 61 72 74 0D 63 'og+.{+.}`Start.c' 00680- 6F 67 2D 60 53 74 6F 70 0D 4D 60 4D 61 70 0D 7E 'og-`Stop.M`Map.~' 00690- 50 49 4E 53 8E 7B 70 69 6E 7D 5B 48 2F 4C 2F 54 'PINS.{pin}[H/L/T' 006A0- 2F 5A 2F 52 5D 60 48 69 67 68 2F 6C 6F 77 2F 74 '/Z/R]`High/low/t' 006B0- 6F 67 67 6C 65 2F 6F 66 66 2F 72 65 61 64 0D 70 'oggle/off/read.p' 006C0- 69 6E 23 60 57 61 74 63 68 0D 70 69 6E 7C 63 66 'in#`Watch.pin|cf' 006D0- 67 60 43 6F 6E 66 69 67 75 72 65 0D 64 61 74 5C 'g`Configure.dat\' 006E0- 60 53 65 74 20 44 41 43 73 0D 7E 4D 49 53 43 8E '`Set DACs.~MISC.' 006F0- 64 61 74 2A 60 53 65 74 20 63 6C 6F 63 6B 0D 27 'dat*`Set clock.'' 00700- 60 52 65 70 65 61 74 0D 51 60 51 75 69 74 0D 00 '`Repeat.Q`Quit..' 00710- 00 00 00 00 40 3C C0 0D D7 01 04 E0 00 EC D3 A0 '....@<..........' 00720- 12 CC FF 0C 12 CE FF 0C 09 CE FF 28 DB CE 7F 0C '...........(....' 00730- 92 74 FF 0C CB 22 FC 0C 0A E6 7F F8 94 56 FF 0C '.t...".......V..' 00740- CB 32 FC 0C 01 C6 FF A0 D2 BE FD 1C AA 00 FC 0C '.2..............' 00750- B2 A2 FC 0C 6F E3 FE 1C E9 1A FE 1C 2B 73 FE 1C '....o.......+s..' 00760- 2F B0 6B F8 19 00 7C 1C 0B 1B FE 1C A4 02 FC 0C '/.k...|.........' 00770- 2B 73 FE 1C 1F 00 54 1C DA 65 FD 54 B2 00 FC 0C '+s....T..e.T....' 00780- C0 84 FD 1C B2 E4 FC 0C 11 00 7C 1C DD B7 BF A0 '..........|.....' 00790- E0 65 FD 54 B2 3E FC 0C C0 84 FD 1C 38 00 7C 1C '.e.T.>......8.|.' 007A0- 2A 73 FE 1C 35 00 68 1C DD B9 BF A0 B2 84 FC 0C '*s..5.h.........' 007B0- C0 84 FD 1C 39 00 7C 1C 01 C6 FF A2 02 C6 EB A2 '....9.|.........' 007C0- 04 C6 EB A0 D2 BE FD 1C 17 00 7C 1C 0F B8 FF A0 '..........|.....' 007D0- 49 DD FE 1C 12 00 7C 1C FF B8 FF A0 49 DD FE 1C 'I.....|.....I...' 007E0- 17 00 7C 1C FF B8 FF A0 4A DD FE 1C 18 00 7C 1C '..|.....J.....|.' 007F0- DB B9 BF A0 4C DD FE 1C 18 00 7C 1C DE B7 BF A0 '....L.....|.....' 00800- E5 B9 BF A0 C7 A2 FD 1C 0E 45 FE 1C B2 B6 7F 0C '.........E......' 00810- 00 00 04 E0 00 B0 FF A0 E5 CC FD 1C F6 BB 07 86 '................' 00820- 4B 00 68 1C E3 B7 BF 80 DC B7 3F 87 3F 00 78 1C 'K.h.......?.?.x.' 00830- DB BD BF A0 E5 BD BF 60 18 00 7C 1C E1 B1 BF E9 '.......`..|.....' 00840- 42 00 4C 1C E1 B9 BF A0 E4 B9 BF 2C DB B9 BF 80 'B.L........,....' 00850- 39 00 7C 1C C7 A2 FD 1C 01 B2 FF A0 DB BF BF A0 '9.|.............' 00860- E5 BF BF 60 0E 45 FE 1C 59 B2 7F FA E1 B5 BF A0 '...`.E..Y.......' 00870- 01 B4 FF 80 B3 BE 7F 0C F6 BB 87 A0 E7 D0 FD 1C '................' 00880- 5A B4 FF F6 13 BE FF 0C 18 00 7C 1C D8 B3 BF A0 'Z.........|.....' 00890- C7 A2 FD 1C 27 53 FE 1C E5 BB BF 4C E5 BB BF 60 '....'S.....L...`' 008A0- 3C B2 7F 86 DB B1 AB A0 DD B7 AB A0 D8 BB AB A0 '<...............' 008B0- DD B7 3F 85 DA B1 B3 A0 E4 B1 B3 2C D8 B7 B3 80 '..?........,....' 008C0- D8 BB B3 80 7E CA F1 6C 7E CE F1 6C B2 B6 7F 0C '....~..l~..l....' 008D0- B3 BA 7F 0C E5 CC FD 1C E7 D0 FD 1C 71 B4 FF F6 '............q...' 008E0- 7E CA F1 6C 7E CE F1 6C 18 00 7C 1C C7 A2 FD 1C '~..l~..l..|.....' 008F0- B2 B6 7F 0C E5 CC FD 1C DD B3 BF 80 79 B4 FF F6 '............y...' 00900- D9 BB BF A0 08 C4 FF A0 85 1B FF 1C 16 00 7C 1C '..............|.' 00910- E6 C6 FD 52 01 C4 FF A0 E4 C6 E9 50 E3 C5 AB A0 '...R.......P....' 00920- 01 C4 EB 2C E0 CC FD 1C DD B5 BF A0 85 1B FF 1C '...,............' 00930- 90 3D FF 1C A2 55 FF 1C 16 00 54 1C E0 CC FD 1C '.=...U....T.....' 00940- DA BB 3F 86 89 00 68 1C 86 00 7C 1C B2 FA FC 0C '..?...h...|.....' 00950- 6F E3 FE 1C 00 B6 7F 0C 9F 43 FF 1C 20 B0 7F 86 'o........C.. ...' 00960- 92 00 54 1C 16 00 7C 1C E0 B6 7F 0C 27 53 FE 1C '..T...|.....'S..' 00970- DD B3 BF A0 00 BA FF A0 2B B0 7F 86 27 53 EA 1C '........+...'S..' 00980- DD B3 3F 0C 18 00 7C 1C 01 B6 FF 0C 03 B6 7F 0C '..?...|.........' 00990- 17 00 7C 1C 07 B2 FF A0 90 3D FF 1C D9 B1 BF A0 '..|......=......' 009A0- 01 B0 FF 0D D9 B1 3F 86 30 B0 CF A0 31 B0 F3 A0 '......?.0...1...' 009B0- 4D B0 EB A0 96 3D FF 1C 01 B2 FF 85 A2 00 4C 1C 'M....=........L.' 009C0- 16 00 7C 1C DA 66 FD 52 DB 66 E9 52 D9 66 E9 52 '..|..f.R.f.R.f.R' 009D0- D8 66 E9 52 D6 66 E9 50 DB C1 BF A0 D6 C0 7F 0D '.f.R.f.P........' 009E0- A5 00 68 1C 17 00 7C 1C 27 53 FE 1C E3 B6 7F 0C '..h...|.'S......' 009F0- 23 B6 FF 0C DD B7 3F E8 18 00 7C 1C D5 B6 7F 0C '#.....?...|.....' 00A00- 17 00 7C 1C B2 5C FD 0C 6F E3 FE 1C 16 00 7C 1C '..|..\..o.....|.' 00A10- B4 A4 7F 0C C1 B4 FF 00 00 B4 7F F8 C1 B2 FF 00 '................' 00A20- D8 B3 BF 6E C1 00 54 1C DA 01 3C 1C E5 B7 BF 4C '...n..T...<....L' 00A30- E5 B7 BF 60 E5 B9 BF 4C E5 B9 BF 60 DB B9 3F 85 '...`...L...`..?.' 00A40- 1D 00 70 1C DC B5 BF A0 DB B5 BF 84 E4 B5 BF 28 '..p............(' 00A50- 01 B4 FF 80 00 00 7C 1C 02 C6 7F 61 9A CB FD 0C '......|....a....' 00A60- 9A CF FD 0C 04 C6 7F 61 9B CB FD 0C 9B CF FD 0C '.......a........' 00A70- E3 C9 BF A0 01 C8 FF 28 E3 CB BF A0 01 CA FF 84 '.......(........' 00A80- D3 CB BF 6C E5 BD BF 60 E5 BF BF 60 00 00 7C 1C '...l...`...`..|.' 00A90- D6 B6 7F 0D 00 BA CF A0 01 BA F3 A0 E6 00 7C 1C '..............|.' 00AA0- B2 B6 7F 0C C1 BA FF 00 00 00 7C 1C C1 BB 7F 00 '..........|.....' 00AB0- 00 00 7C 1C A2 00 FC 0C 3E B0 FF A0 96 3D FF 1C '..|.....>....=..' 00AC0- 9F 43 FF 1C 27 B0 7F 86 F4 00 54 1C 18 B0 FF 0E '.C..'.....T.....' 00AD0- 96 3D D7 1C EF 00 54 1C 0A 01 7C 1C 9F 43 FF 1C '.=....T...|..C..' 00AE0- 0D B0 7F 86 09 01 68 1C 08 B0 7F 86 7F B0 57 86 '......h.......W.' 00AF0- 01 01 68 1C 20 B0 7F 85 7E B0 4F E1 F3 00 70 1C '..h. ...~.O...p.' 00B00- AA B0 7F 0C 16 00 7C 0D A6 02 F0 0C 96 3D CF 1C '......|......=..' 00B10- F3 00 7C 1C 16 00 7C 0E A8 B0 57 0C 96 3D D7 1C '..|...|...W..=..' 00B20- 90 3D D7 1C 18 B0 D7 0C 96 3D D7 1C A6 02 D4 0C '.=.......=......' 00B30- F3 00 7C 1C AA 00 FC 0C A2 00 FC 0C D4 B1 BF A0 '..|.............' 00B40- 96 3D FF 1C 00 00 7C 1C 00 AE FF A0 00 00 04 E0 '.=....|.........' 00B50- 2A 73 FE 1C 23 4D D6 1C 20 B0 7F 86 10 01 68 1C '*s..#M.. .....h.' 00B60- 27 B0 7F 86 1E 01 54 1C A4 04 FC 0C 1A B0 FF 0C ''.....T.........' 00B70- 27 B0 7F 86 10 01 68 1C 1E B1 7F F8 D8 BB BF A0 ''.....h.........' 00B80- 23 4D FE 1C 16 01 7C 1C 01 AE FF 85 D7 C3 8F A0 '#M....|.........' 00B90- E1 43 BE 54 00 00 04 E4 00 00 7C 1C 11 AE FF E9 '.C.T......|.....' 00BA0- 1D 00 70 1C DD ED 93 A0 00 00 7C 1C 2A 73 FE 1C '..p.......|.*s..' 00BB0- 1D 00 68 1C 00 00 7C 1C A4 02 FC 0C 00 BA FF A2 '..h...|.........' 00BC0- 3A 7D FE 1E 18 B0 FF 0C 3F 91 FE 1C 04 BA F3 2C ':}......?......,' 00BD0- D8 BB B3 68 2D 01 70 1E A6 02 FC 0C 3A 7D FE 1E '...h-.p.....:}..' 00BE0- 3F 91 FE 1C 1A B0 F3 0C 60 B0 7F E1 7B B0 73 85 '?.......`...{.s.' 00BF0- 20 B0 F3 84 00 00 7C 1C 18 B0 FF 0C 20 B0 7F 86 ' .....|..... ...' 00C00- 3A 01 68 1C A6 02 FC 0C 00 00 7C 1E 2F B0 7F E1 ':.h.......|./...' 00C10- 3A B0 73 85 07 B0 F3 80 40 B0 4F E1 47 B0 73 85 ':.s.....@.O.G.s.' 00C20- 20 B0 F3 80 60 B0 4F E1 67 B0 73 85 57 B0 F3 84 ' ...`.O.g.s.W...' 00C30- 00 00 7C 1C DE B7 BF A0 E5 B9 BF 60 DB B9 BF 80 '..|........`....' 00C40- C7 A2 FD 1C DB BD BF A0 DE BB BF A0 05 C4 FF A0 '................' 00C50- 85 1B FF 1C 8E 3D FF 1C E3 B1 BF A0 1B B0 FF 3C '.....=.........<' 00C60- DA B7 BF A0 D8 B7 BF 4C DB B9 BF A0 E4 B9 BF 2C '.......L.......,' 00C70- DB B5 BF 84 B2 BC 7F 0C E5 CC FD 1C E3 C5 BF A0 '................' 00C80- 01 C4 FF 2C 85 1B FF 1C 90 3D FF 1C 5A B7 FF F6 '...,.....=..Z...' 00C90- B2 0E FD 0C 6F E3 FE 1C B2 BC 7F 0C C1 B0 FF 00 '....o...........' 00CA0- 20 B0 7F 85 7E B0 4F E1 2E B0 F3 A0 96 3D FF 1C ' ...~.O......=..' 00CB0- 63 B9 FF F6 12 BC FF 0C B2 16 FD 0C 6F E3 FE 1C 'c...........o...' 00CC0- A2 55 FF 1C 4E B5 6B FA 00 00 7C 1C B4 A4 7F 0C '.U..N.k...|.....' 00CD0- C1 B0 FF 00 00 B0 7F F8 80 B0 7F 62 28 E1 D6 0C '...........b(...' 00CE0- B3 B0 57 0C B5 A4 57 0C 70 01 54 1C 60 B0 7F 86 '..W...W.p.T.`...' 00CF0- 10 B2 EB E0 7E B0 57 86 10 B2 EB 80 90 3D EB 1C '....~.W......=..' 00D00- 7B B3 EB F6 8E 3D EB 1C 70 01 68 1C 0D B0 7F 86 '{....=..p.h.....' 00D10- 0B 1B EA 1C 00 B2 EB A0 96 3D D7 1C 01 B2 D7 80 '.........=......' 00D20- 70 01 7C 1C E2 B3 BF A0 02 B2 FF 2C D9 BB BF 20 'p.|........,... ' 00D30- E2 B3 BF A0 04 BA FF 24 DD B1 BF A0 92 3D FF 1C '.......$.....=..' 00D40- 89 B3 FF F6 00 00 7C 1C D5 B1 BF A0 96 01 7C 1C '......|.......|.' 00D50- 20 B0 FF A0 96 01 7C 1C 0F B0 FF 60 0A B0 7F 85 ' .....|....`....' 00D60- 30 B0 F3 80 37 B0 CF 80 01 B0 FF 2C 69 B1 FF 0C '0...7......,i...' 00D70- 0D AE FF 0C F3 AF BF 80 0D AE 7F 0C 01 B0 FF 29 '...............)' 00D80- DC CE 7F 0C 99 B1 7F FA 00 00 7C 1C A2 55 FF 1C '..........|..U..' 00D90- 9F 01 68 1C 00 00 7C 1C 80 D0 FF 68 17 D2 FF 0E '..h...|....h....' 00DA0- E8 D3 17 86 16 D2 D7 0C A2 D0 57 0C 18 B0 D7 0C '..........W.....' 00DB0- 16 D0 D7 0C A2 D2 57 0C 00 00 7C 1C 17 00 7C 0E '......W...|...|.' 00DC0- A3 00 E9 0C 09 D8 FF A0 F3 D5 BF A4 01 D4 FF 38 '...............8' 00DD0- B0 CD FF F8 0C D4 FF 0C 01 D6 FF 30 F3 D5 BF 80 '...........0....' 00DE0- 0D D4 7F 0C D6 CC 7F 0D B2 D9 FF F6 18 D6 FF 28 '...............(' 00DF0- AB D6 7F 0C AB 01 7C 1C E6 AD BF 54 25 AD FF 0D '......|....T%...' 00E00- F0 AC 7F 0C ED E1 8F A0 04 E0 CF 28 F0 E3 8F A4 '...........(....' 00E10- ED E1 8F 80 ED E3 8F 80 EE E5 8F A0 06 E4 CF 10 '................' 00E20- F0 E5 0F E1 F1 E5 0F 85 EF E5 8F A0 03 E4 CF 10 '................' 00E30- F0 E5 0F E1 F1 E5 0F 85 EF DB 8F 80 03 DA CF 28 '...............(' 00E40- ED E7 8F A0 EE DB BF A0 EF DD BF A0 3A DE FF 0C '............:...' 00E50- BB DF 7F FA CF 01 7C 1C 5C 05 00 00 FF FF 01 00 '......|.\.......' 00E60- 0D 28 04 00 2D 80 04 00 89 00 00 00 78 CF 68 9D '.(..-.......x.h.' 00E70- 3D 3D 20 45 6E 64 20 6F 66 20 52 4F 4D 20 3D 3D '== End of ROM =='
It is now 128 bytes shorter than it used to be, since I've used this time during full-chip verification being done by Beau and Open Silicon to pack things more efficiently.
Here is the binary/HMAC-signed loader (it's only $70 longs and starts at $000):
'******************************************************** '* * '* Propeller II ROM Booter * '* * '* Version 0.1 * '* * '* 11/01/2012 * '* * '******************************************************** CON rx_pin = 91 tx_pin = 90 spi_cs = 89 spi_ck = 88 spi_di = 87 spi_do = 86 base = $E80 DAT ' ' ' Version (@$000) ' byte "Prop2.0 " ' ' ' Shut down (@$008) ' org clkset h001+offset 'set clock to rc slow cogstop h200+offset 'stop cog0 offset ' ' ' Entry, read fuses (@$010) ' org reps #256,@:fuse 'ready to read 256 fuses setport #rx_pin 'set rx_pin port for booting cogid fuse_read nr 'read fuses (172 fuses + 84 zeros) cogid fuse_read nr,wc '(last iteration initializes cnt to $00000000_00000001) add fuse_read,#1 test fuse_read,#$1F wz :fusex rcr fuses,#1 :fuse if_z add :fusex,h200 cogid spi_read nr 'disable fuses and enable cnt (spi_read[10..0] = 0) ' ' ' Attempt to boot from serial ' jnp monitor_ptr,#boot_flash 'if rx_pin is low, skip serial and boot from flash call #rx_bit 'measure low rx calibration pulses (host $F9 -> %1..010011111..) mov threshold,delta 'and calculate threshold call #rx_bit '(any timeout results in flash boot) add threshold,delta h001 shr threshold,#1 '(9 lsb's are $001) mov count,#250 'ready to receive/verify 250 lfsr bits :lfsrin call #rx_bit 'receive bit ($FE/$FF) into c test lfsr,#$01 wz 'get lfsr bit into nz if_c_eq_z jmp #boot_flash 'if mismatch, boot from flash test lfsr,#$B2 wc 'advance lfsr rcl lfsr,#1 djnz count,#:lfsrin 'loop for next bit in mov count,#250+8 'ready to transmit 250 lfsr bits + 8 version bits :lfsrout cmp count,#8 wz 'if last 8 bits, set lfsr so that version will be output if_z mov lfsr,#$52 '$52 results in version $20 being sent (%00000100) test lfsr,#$01 wz 'get lfsr/version bit into nz, z=1 on last iteration call #wait_rx 'wait for rx low (convey incoming $F9 on rx_pin to $FE/$FF on tx_pin) clrp #tx_pin 'make tx low call #wait_rx 'wait for rx high setpnz #tx_pin 'make tx lfsr/version bit call #wait_rx 'wait for rx low setp #tx_pin 'make tx high call #wait_rx 'wait for rx high test lfsr,#$B2 wc 'advance lfsr rcl lfsr,#1 djnz count,#:lfsrout 'loop for next bit out jmp #load 'serial handshake done, attempt to load from serial (z=1) ' ' ' Wait for rx low/high - if timeout, attempt to boot from flash ' wait_rx getcnt time 'ready timeout add time,timeout :waitpxx waitpne rx_mask,rx_mask wc 'wait for rx low/high with timeout notb :waitpxx,#23 'toggle waitpeq/waitpne wait_rx_ret if_nc ret 'return if not timeout (boot_flash follows) ' ' ' Attempt to boot from flash ' boot_flash mov count,#4 'ready for 3 resets and 1 read command :cmd setp #spi_cs 'spi_cs high clrp #spi_ck 'spi_ck low reps #32,@:bit 'ready for 32 command bits clrp #spi_cs 'spi_cs low cmpr count,#1 wc 'first 3 commands = $FF_FF_FF_FF (reset) if_nc rol spi_read,#1 wc,wz 'last command = $03_00_00_00 (read from 0), z=0 setpc #spi_di setp #spi_ck 'cycle spi_ck :bit clrp #spi_ck djnz count,#:cmd 'loop for next spi command ' ' ' Load from serial (z=1) or flash (z=0) ' load setptra loader_pgm 'load loader into base+$000..$7DF, HMAC into base+$7E0..$7FF mov count,h200 'ready to input $200 longs :long mov bits,#32 'ready to input 32 data bits :bit if_z call #rx_bit 'input serial bit (serial mode) if_nz getp #spi_do wc 'input spi_do (flash mode) if_nz setp #spi_ck 'high spi_ck (flash mode) if_nz clrp #spi_ck 'low spi_ck (flash_mode) rcl data,#1 'shift bit into long djnz bits,#:bit 'loop, adequate time for next flash bit wrlong data,ptra++ 'store long in hub ram (ptra=base+$800 after) djnz count,#:long 'loop for next long (count=0 after) ' ' ' Compute loader HMAC signature for loader authentication ' ' base+$000..$7DF = loader ($1F8 longs) ' base+$7E0..$7FF = loader HMAC signature (8 longs) ' base+$800..$81F = fuses, 1st half are HMAC key (8 longs) ' base+$820..$83F = proper HMAC signature (8 longs) ' base+$840..$843 = sha256 command interface (1 long) ' reps #8,#1 'store 128-bit key + 44 extra fuses + 84 zero bits setinda fuses 'into base+$800..$81F wrlong inda++,ptra++ '(ptra = base+$820, afterwards) wrlong count,sha256_ptr 'clear sha256 command setcog #1 'launch sha256 in cog1 coginit sha256_pgm,sha256_ptr setinda begin_hmac 'do sha256 commands to compute proper loader hmac mov count,#3 'ready for 3 commands: begin_hmac, hash_bytes, read_hash :cmd wrlong inda++,sha256_ptr 'set command :wait rdlong data,sha256_ptr wz 'wait for command done tjnz data,#:wait djnz count,#:cmd 'loop for next command (count=0, z=1 after) cogstop h001 'done with sha256, stop cog1 ' ' ' If loader authenticates, run it ' reps #8,@:cmp 'verify loader hmac signature (z=1 on entry) setcog #0 'ready to relaunch cog0 with loader/monitor rdlong bits,ptra[-$10] 'get loader hmac signature long rdlong data,ptra++ 'get proper hmac signature long :cmp if_z cmp bits,data wz 'compare, z=1 if authenticated if_z coginit loader_pgm,loader_ptr 'if loader authenticated, relaunch cog0 with loader ' ' ' Authentication failed, hide fuses and clear memory ' reps #$20000/8,@:clr 'clear all memory cogid monitor_pgm nr 'hide fuses (bit 10 set) wrlong count,ptra++ '(count=0) :clr wrlong count,ptra++ ' ' ' If key <> 0, shut down - else, monitor ' or fuses+0,fuses+1 wz 'check if 128-bit key = 0 if_z or fuses+2,fuses+3 wz if_nz mov monitor_pgm,#$008 'if key <> 0, shut down coginit monitor_pgm,monitor_ptr 'relaunch cog0 with shut down or monitor ' ' ' Receive bit (c) - compare incoming pulse to threshold ' rx_bit call #wait_rx 'wait for rx low getcnt delta 'get time call #wait_rx 'wait for rx high subcnt delta 'get time delta cmp delta,threshold wc 'compare time delta to threshold rx_bit_ret ret ' ' ' Constants ' fuse_read long $200 '(gets modified to $300) timeout long 20_000_000 / 1000 * 150 '150ms @20MHz (rcfast) rx_mask long 1 << (rx_pin & $1F) lfsr long "P" spi_read long $03_000000 h200 long $200 begin_hmac long 1<<30 + (($004<<2)-1)<<17 + base+$800 'begin_hmac, loads key at base+$800 (4 longs) hash_bytes long 2<<30 + (($1F8<<2)-1)<<17 + base+$000 'hash_bytes, hashes message at base+$000 ($1F8 longs) read_hash long 3<<30 + base+$820 'read_hash, writes hash at base+$820 (8 longs) sha256_pgm long $1D0 'sha256 program address sha256_ptr long base+$840 'sha256 parameter (points to command) loader_pgm long base+$000 'loader program address loader_ptr long base+$800 'loader parameter (points to fuses) monitor_pgm long $55C+$1B4 'monitor program address monitor_ptr long tx_pin<<9 + rx_pin 'monitor parameter (conveys pins) ' ' ' Variables ' fuses res 8 count res 1 bits res 1 data res 1 time res 1 delta res 1 threshold res 1
Here is the SHA-256/HMAC program used to authenticate code (thanks to Pedward for making this happen):
'******************************************************** '* * '* Propeller II ROM SHA-256/HMAC * '* * '* Version 0.1 * '* * '* 11/01/2012 * '* * '******************************************************** ' ' Usage: commandlong := 0 'pre-clear command long ' cognew($1D0, @commandlong) 'start SHA-256/HMAC in new cog ' ' Start here for HMAC: commandlong := 1<<30 + (keysize-1)<<17 + @key 'start HMAC with key of keysize bytes (1..64) ' repeat while commandlong '(wait for command done) ' ' Start here for SHA-256: commandlong := 2<<30 + (msgsize-1)<<17 + @msg 'hash msg of msgsize bytes (1..8192) ' repeat while commandlong '(wait for command done) ' ' {issue more 2<<30 commands if msg > 8192 bytes} ' ' commandlong := 3<<30 + @hashbuffer 'read resulting hash into hashbuffer (32 bytes) ' repeat while commandlong '(wait for command done) ' ' {hasbuffer now contains result, ready for new 1<<30 or 2<<30 command} ' DAT org setf #%0_1111_0000 'configure movf for sbyte0 -> {dbyte3,dbyte2,dbyte1,dbyte0,dbyte3,...} call #init_hash 'init hash, clear hmac mode, reset byte count ' ' ' Command Loop ' command rdlong x,ptra 'wait for command (%cc_nnnnnnnnnnnnn_ppppppppppppppppp) tjz x,#command setptrb x 'get pointer (%ppppppppppppppppp) mov count,x 'get count (%nnnnnnnnnnnnn) shl count,#2 shr count,#2+17 add count,#1 '+1 for 1..8192 range shr x,#32-2 'get command (%cc) cachex 'invalidate cache for fresh rdbytec's djz x,#begin_hmac '1 = begin hmac, pointer @key (count+1 bytes, 1..64) djz x,#hash_bytes '2 = hash bytes, pointer @message (count+1 bytes, 1..8192) djz x,#read_hash '3 = read hash, pointer @hashbuffer (32 bytes) done wrlong zero,ptra 'clear command to signal done jmp #command 'get next command ' ' ' Begin HMAC ' begin_hmac call #end_hash 'end any hash in progress :ipad mov x,#$00 'get and hash ipad key (full block) cmpr count,bytes wc 'after key bytes, hash $00's to fill block if_c rdbytec x,ptrb++ xor x,#$36 'xor bytes with ipad ($36) call #hash_byte '(last iteration triggers hash_block, z=1) if_nz jmp #:ipad reps #16,#2 'save opad key setinds opad_key,w mov indb,inda++ xor indb++,opad 'xor bytes with opad ($5C) mov hmac,#1 'set hmac mode jmp #done ' ' ' Hash Bytes ' hash_bytes rdbytec x,ptrb++ 'hash bytes call #hash_byte djnz count,#hash_bytes jmp #done ' ' ' Read Hash ' read_hash tjz hmac,#:not 'if not hmac, output hash call #end_hash 'hmac, end current hash reps #16,#1 'get opad key into w[0..15] (full block) setinds w,opad_key mov indb++,inda++ call #hash_block 'hash opad key reps #8,#1 'get hashx[0..7] into w[0..7] setinds w,hashx mov indb++,inda++ movd hash_byte,#w+8 'account for opad key and hashx bytes mov bytes,#64+32 '(1-1/2 blocks, 1/2 block needs end_hash) :not call #end_hash 'end current hash setinda hashx 'store hashx[0..7] at pointer, big-endian mov count,#8 :out reps #4,#2 mov x,inda++ rol x,#8 wrbyte x,ptrb++ djnz count,#:out jmp #done ' ' ' End Hash - hash $80, any $00's needed to get to offset $38, then 8-byte length ' end_hash mov length,bytes 'get message length in bits shl length,#3 mov x,#$80 'hash end-of-message byte ($80) :fill call #hash_byte '(may trigger hash_block) mov x,bytes 'hash any $00's needed to get to offset $38 and x,#$3F cmp x,#$38 wz mov x,#$00 if_nz jmp #:fill :len test bytes,#$04 wc 'hash 8-byte length, big-endian if_c rol length,#8 '(hash four $00's, then four length bytes) if_c mov x,length call #hash_byte '(last iteration triggers hash_block) if_nz jmp #:len reps #8,#1 'save hash[0..7] into hashx[0..7] setinds hashx,hash mov indb++,inda++ init_hash reps #8,#1 'copy hash_init[0..7] into hash[0..7] setinds hash,hash_init mov indb++,inda++ mov hmac,#0 'clear hmac mode mov bytes,#0 'reset byte count init_hash_ret end_hash_ret ret ' ' ' Hash Byte - add byte to w[0..15] and hash block if full (z=1) ' hash_byte movf w,x 'store byte into w[0..15], big-endian add bytes,#1 'increment byte count test bytes,#$03 wz 'every 4th byte, increment w pointer if_z add hash_byte,d0 test bytes,#$3F wz 'every 64th byte, reset w pointer if_z movd hash_byte,#w if_z call #hash_block 'every 64th byte, hash block hash_byte_ret ret ' ' ' Hash Block - first extend w[0..15] into w[16..63] to generate schedule ' hash_block reps #48,@:sch 'i = 16..63 setinds w+16,w+16-15+7 'indb = @w[i], inda = @w[i-15+7] setinda --7 's0 = (w[i-15] -> 7) ^ (w[i-15] -> 18) ^ (w[i-15] >> 3) mov indb,inda-- mov x,indb rol x,#18-7 xor x,indb ror x,#18 shr indb,#3 xor indb,x add indb,inda 'w[i] = s0 + w[i-16] setinda ++14 's1 = (w[i-2] -> 17) ^ (w[i-2] -> 19) ^ (w[i-2] >> 10) mov x,inda mov y,x rol y,#19-17 xor y,x ror y,#19 shr x,#10 xor x,y add indb,x 'w[i] = s0 + w[i-16] + s1 setinda --5 'w[i] = s0 + w[i-16] + s1 + w[i-7] :sch add indb++,inda ' Load variables from hash reps #8,#1 'copy hash[0..7] into a..h setinds a,hash mov indb++,inda++ ' Do 64 hash iterations on variables reps #64,@:itr 'i = 0..63 setinds k+0,w+0 'indb = @k[i], inda = @w[i] mov x,g 'ch = (e & f) ^ (!e & g) xor x,f and x,e xor x,g mov y,e 's1 = (e -> 6) ^ (e -> 11) ^ (e -> 25) rol y,#11-6 xor y,e rol y,#25-11 xor y,e ror y,#25 add x,y 't1 = ch + s1 add x,indb++ 't1 = ch + s1 + k[i] add x,inda++ 't1 = ch + s1 + k[i] + w[i] add x,h 't1 = ch + s1 + k[i] + w[i] + h mov y,c 'maj = (a & b) ^ (b & c) ^ (c & a) and y,b or y,a mov h,c or h,b and y,h mov h,a 's0 = (a -> 2) ^ (a -> 13) ^ (a -> 22) rol h,#13-2 xor h,a rol h,#22-13 xor h,a ror h,#22 add y,h 't2 = maj + s0 mov h,g 'h = g mov g,f 'g = f mov f,e 'f = e mov e,d 'e = d mov d,c 'd = c mov c,b 'c = b mov b,a 'b = a add e,x 'e = e + t1 mov a,x 'a = t1 + t2 :itr add a,y ' Add variables back into hash reps #8,#1 'add a..h into hash[0..7] setinds hash,a add indb++,inda++ hash_block_ret ret ' ' ' Defined data ' zero long 0 d0 long 1 << 9 opad long $36363636 ^ $5C5C5C5C hash_init long $6A09E667, $BB67AE85, $3C6EF372, $A54FF53A, $510E527F, $9B05688C, $1F83D9AB, $5BE0CD19 'fractionals of square roots of primes 2..19 k long $428A2F98, $71374491, $B5C0FBCF, $E9B5DBA5, $3956C25B, $59F111F1, $923F82A4, $AB1C5ED5 'fractionals of cube roots of primes 2..311 long $D807AA98, $12835B01, $243185BE, $550C7DC3, $72BE5D74, $80DEB1FE, $9BDC06A7, $C19BF174 long $E49B69C1, $EFBE4786, $0FC19DC6, $240CA1CC, $2DE92C6F, $4A7484AA, $5CB0A9DC, $76F988DA long $983E5152, $A831C66D, $B00327C8, $BF597FC7, $C6E00BF3, $D5A79147, $06CA6351, $14292967 long $27B70A85, $2E1B2138, $4D2C6DFC, $53380D13, $650A7354, $766A0ABB, $81C2C92E, $92722C85 long $A2BFE8A1, $A81A664B, $C24B8B70, $C76C51A3, $D192E819, $D6990624, $F40E3585, $106AA070 long $19A4C116, $1E376C08, $2748774C, $34B0BCB5, $391C0CB3, $4ED8AA4A, $5B9CCA4F, $682E6FF3 long $748F82EE, $78A5636F, $84C87814, $8CC70208, $90BEFFFA, $A4506CEB, $BEF9A3F7, $C67178F2 ' ' ' Undefined data ' hmac res 1 bytes res 1 count res 1 length res 1 opad_key res 16 hash res 8 hashx res 8 w res 64 a res 1 b res 1 c res 1 d res 1 e res 1 f res 1 g res 1 h res 1 x res 1 y res 1
And here's the monitor, shrunk and improved:
'******************************************************** '* * '* Propeller II ROM Monitor * '* * '* Version 0.1 * '* * '* 11/01/2012 * '* * '******************************************************** ' ' Usage: cognew($738, tx_pin << 9 + rx_pin) 'start monitor in new cog ' CON branch1_ = 0 branch2_ = branch1_ + 31 branch3_ = branch2_ + 35 hello_ = branch3_ + 15 error_ = hello_ + 33 hitspace_ = error_ + 11 spquote_ = hitspace_ + 10 quotecr_ = spquote_ + 4 sub0_ = quotecr_ + 3 'must be => $80 sub1_ = sub0_ + 4 sub2_ = sub1_ + 12 sub3_ = sub2_ + 12 help_ = sub3_ + 4 DAT '******** '* Data * '******** branch1 byte cmd_new, 0 byte cmd_byte, "Y" byte cmd_word, "W" byte cmd_long, "N" byte cmd_viewp, "." byte cmd_search, "/" byte cmd_enter, ":" byte cmd_map, "M" byte cmd_clrp, "L" byte cmd_setp, "H" byte cmd_notp, "T" byte cmd_offp, "Z" byte cmd_getp, "R" byte cmd_quit, "Q" byte cmd_help, "?" byte 0 '31 bytes branch2 byte cmd_view2, 0 byte cmd_view2, " " byte cmd_range, "." byte cmd_search2, "/" byte cmd_enter2, ":" byte cmd_watch, "@" byte cmd_clkset, "*" byte cmd_coginit, "+" byte cmd_cogstop, "-" byte cmd_clrp, "L" byte cmd_setp, "H" byte cmd_notp, "T" byte cmd_offp, "Z" byte cmd_getp, "R" byte cmd_watchp, "#" byte cmd_cfgp, "|" byte cmd_setdacs, "\" byte 0 '35 bytes branch3 byte cmd_view3, 0 byte cmd_view3, " " byte cmd_search3, "/" byte cmd_enter3, ":" byte cmd_move, ">" byte cmd_move, "<" byte cmd_checksum, "^" byte 0 '15 bytes hello byte 13,13,"=== Propeller II Monitor ===",13,13 byte 0 '33 bytes error byte "? - Help" byte 13,7,0 '11 bytes hitspace byte "Hit SPACE",0 '10 bytes spquote byte " '",0 '4 bytes quotecr byte "'",13,0 '3 bytes sub0 byte " -",13,$80 '4 bytes sub1 byte "{adr{.adr}}",$80 '12 bytes sub2 byte "{dat{ dat}}",$80 '12 bytes sub3 byte "adr",$80 '4 bytes help byte 13, "~HUB",sub0_ byte sub1_, "`View",13 byte sub1_,"/",sub2_, "`Search",13 byte sub1_,":",sub2_, "`Enter",13 byte sub3_,".",sub3_,"[</>]",sub3_, "`Move",13 byte sub3_,".",sub3_,"^", "`Checksum",13 byte sub3_,"@", "`Watch",13 byte "[Y/W/N]", "`Byte/word/long",13 byte "~COGS",sub0_ byte "cog+",sub3_,"{+",sub3_,"}", "`Start",13 byte "cog-", "`Stop",13 byte "M", "`Map",13 byte "~PINS",sub0_ byte "{pin}[H/L/T/Z/R]", "`High/low/toggle/off/read",13 byte "pin#", "`Watch",13 byte "pin|cfg", "`Configure",13 byte "dat\", "`Set DACs",13 byte "~MISC",sub0_ byte "dat*", "`Set clock",13 byte "'", "`Repeat",13 byte "Q", "`Quit",13 '(0 long follows) longs long '********* '* Entry * '********* org long 0 'start of data string = 0/nop reps #$1F6-reserves,#1 'clear reserves setinda reserves mov inda++,#0 getptra rx_pin 'get rx/tx pins getptra tx_pin shr tx_pin,#9 setp tx_pin jmptask #baud_task,#%0010 'enable baud detector task settask #%%0101 tjz period,#$ 'wait for <space> to set period jmptask #rx_task,#%0100 'enable serial receiver task settask #%%0121 mov wsize,#1 'init word size to byte call #set_size pusha #0 'init input line to <enter> setptra #hello_ 'print hello message dmax 'end of data string '************* '* Main Task * '************* message call #tx_string 'print hello/error message cmd_new call #rx_line 'get input line call #parse 'parse first term if_z tjz x,#cmd_viewl 'if no hex and eol, view data jmp #cmd_go 'else, process command cmd_next_crlf call #tx_crlf 'print cr/lf cmd_next addspa #1 'skip chr cmd_loop call #parse 'parse next term cmd_go if_nz jmp #cmd_hex 'if hex, branch movd pinx,#z 'pin update redirected to z setptra #branch1_ 'not hex, vector by chr call #vector 'if returns, no match cmd_error setptra #error_ 'print error message jmp #message cmd_hex mov v1,value 'hex, save v1 movd pinx,#pin 'pin update okay setptra #branch2_ 'vector by chr call #vector 'if returns, no match jmp #cmd_view2 'view data cmd_range call #parse_next 'hex., get hex if_z jmp #cmd_viewp2 'if no hex, view data mov v2,value 'hex.hex, save v2 setptra #branch3_ 'vector by chr call #vector 'if returns, no match jmp #cmd_view3 'view data ' ' ' Byte/word/long data ' cmd_byte mov wsize,#1 wz 'set byte mode, z=0 cmd_word if_z mov wsize,#2 wz 'set word mode, z=0 cmd_long if_z mov wsize,#4 'set long mode call #set_size jmp #cmd_next 'next command ' ' ' View data ' cmd_viewl mov v2,#$F '<enter> (eol), show line of data call #tx_range1 jmp #cmd_new cmd_viewp mov v2,#$FF '. (more), show page of data call #tx_range1 jmp #cmd_next cmd_viewp2 mov v2,#$FF 'addr. (more), show page of data call #tx_range2 jmp #cmd_loop cmd_view2 mov v2,v1 'addr, show unit of data cmd_view3 call #tx_range 'addr.addr, show range of data jmp #cmd_loop ' ' ' Search ' cmd_search mov v1,view '/, search from view to end cmd_search2 mov v2,amask 'addr/, search from address to end cmd_search3 call #check_range 'addr.addr/, search range call #parse_data 'parse data string :start setptra v1 'start search, point to search address setinda 0 'point to search data mov x,#0 'reset word match counter :word call #rdxxxx 'get memory word cmp value,inda++ wz 'compare against search data word if_z jmp #:match 'if word match, check if string match add v1,wsize 'word mismatch, advance search address cmp v1,v2 wz,wc 'at end of range? if_be jmp #:start 'if not, start next search mov view,v1 'else, update view and view,amask jmp #cmd_loop 'next command :match incmod x,dsize wc 'word match, increment match counter if_nc jmp #:word 'if more words to match, compare next word mov v2,dsize 'got string match shl v2,shift 'v1 = start of found data add v2,v1 'v2 = end of found data jmp #cmd_view3 'show found data ' ' ' Enter data ' cmd_enter3 call #check_range 'addr.addr:, check range, z=words to fill mov y,#1 'set fill flag cmd_enter2 mov enter,v1 'addr:, set enter address and enter,amask 'trim enter address (in case cmd_enter2) cmd_enter call #parse_data ':, parse data tjnz y,#:go 'if not fill, set z to data size mov z,dsize add z,#1 :go setptrb enter 'get pointer :loop mov value,inda++ 'get word from string data call #wrxxxx 'store value in memory djnz z,#:loop 'loop until enter done getptrb enter 'update pointer jmp #cmd_loop 'next command ' ' ' Move data ' cmd_move mov y,x 'save ">"/"<" call #check_range 'check 1st address range, get number of words call #parse_hex 'get 2nd address max value,amask 'v1=1st, value=2nd, z=words, y=">"/"<" and value,amask cmp y,#"<" wz 'if "<", swap v1 and value if_z mov x,v1 if_z mov v1,value if_z mov value,x 'v1=from, value=to, z=words cmp v1,value wc 'if from < to, downward move if_c mov x,z if_c shl x,shift if_c add v1,x if_c add value,x if_c xor rdxxxx,#%001_111110 'modify 'rdxxxx value,--ptra' if_c xor wrxxxx,#%001_111110 'modify 'wrxxxx value,--ptrb' setptra v1 'set pointers setptrb value :loop call #rdxxxx 'move data call #wrxxxx djnz z,#:loop if_c xor rdxxxx,#%001_111110 'restore 'rdxxxx value,ptra++' if_c xor wrxxxx,#%001_111110 'restore 'wrxxxx value,ptrb++' jmp #cmd_loop 'next command ' ' ' Checksum ' cmd_checksum call #check_range 'check range setptra v1 'sum bytes :loop call #rdxxxx add y,value djnz z,#:loop mov value,y 'print sum mov hsize,#8 call #tx_hex jmp #cmd_next_crlf 'next command ' ' ' Watch ' cmd_watchp movs rdxxxj,#rdxxxx_ret wz 'set pin mode, z=0 mov hsize,#1 cmd_watch if_z movs rdxxxj,#rdxxxm 'set mem mode if_z mov hsize,wsize 'set hex size by word size if_z shl hsize,#1 call #rdxxxp 'get initial value :loop mov z,value 'preserve value call #tx_hex 'print value call #tx_space 'print space :wait call #rx_check 'if key hit, exit if_nz jmp #cmd_next_crlf call #rdxxxp 'get current value cmp value,z wz 'if same, check again if_z jmp #:wait jmp #:loop 'new value, loop ' ' ' Clkset ' cmd_clkset setptra #hitspace_ 'print hit-space message call #tx_string clkset v1 'set clk :wait call #rx 'wait for space cmp x,#" " wz if_nz jmp #:wait jmp #cmd_next_crlf 'next command ' ' ' Coginit ' cmd_coginit setcog v1 'set cog call #parse_hex 'get program address mov y,value 'save program address mov value,#0 'clear pointer address cmp x,#"+" wz 'if '+', get pointer address if_z call #parse_hex coginit y,value 'do 'coginit program,pointer' jmp #cmd_loop 'next command ' ' ' Cogstop ' Quit ' cmd_quit cogid v1 'quit cmd_cogstop cogstop v1 'stop cog jmp #cmd_next 'next command ' ' ' Map ' cmd_map mov y,#7 'ready for 7..0 cmd_map_loop call #tx_space 'print space mov x,y 'get cog status cogid x wc cmd_map_c cmp x,y wz if_nc mov x,#"0" 'get 0/1/M chr if_c mov x,#"1" if_z mov x,#"M" call #tx 'print chr sub y,#1 wc if_nc jmp #cmd_map_loop 'loop until done jmp #cmd_next_crlf 'next command ' ' ' Pin writes clrp/setp/notp/offp ' Pin read ' cmd_clrp movs pinop,#$DA wz 'clrp, z=0 cmd_setp if_z movs pinop,#$DB wz 'setp, z=0 cmd_notp if_z movs pinop,#$D9 wz 'notp, z=0 cmd_offp if_z movs pinop,#$D8 wz 'offp, z=0 cmd_getp if_z movs pinop,#$D6 'getp, z=1 pinx mov pin,v1 'if hex, get pin (d = pin/z) pinop getp pin wc 'becomes clrp/setp/notp/offp/getp if_z jmp #cmd_map_c 'if getp, show pin value jmp #cmd_next 'next command ' ' ' Pin configuration ' cmd_cfgp call #parse_hex 'get configuration setport v1 'set pin port decod5 v1 'get pin mask cfgpins v1,value 'configure pin jmp #cmd_loop 'next command ' ' ' Setdacs ' cmd_setdacs setdacs v1 'set all four dacs with 8-bit values jmp #cmd_next 'next command ' ' ' Help ' cmd_help setptra #help_ 'print help message call #tx_string jmp #cmd_next_crlf 'next command '************************* '* Main Task Subroutines * '************************* ' ' ' Vector branch ' vector addptra base 'add data base pointer vector_loop rdbyte z,ptra++ 'get jump address vector_ret tjz z,#0 'if 0, no match found, return rdbyte y,ptra++ 'get target xor y,x wz 'compare to x if_nz jmp #vector_loop 'if no match, loop jmp z 'match found, jump, y=0, z=1 ' ' ' Check address range (v1..v2) ' check_range max v1,amask 'trim v1 and v1,amask max v2,amask 'trim v2 and v2,amask cmp v2,v1 wc 'make sure v2 => v1 if_c jmp #cmd_error mov z,v2 'get number of words sub z,v1 shr z,shift add z,#1 check_range_ret ret ' ' ' Set rdxxxx/wrxxxx and others by word size ' set_size test wsize,#%010 wc 'set rdxxxx/wrxxxx by word size setbc rdxxxx,#26 setbc wrxxxx,#26 test wsize,#%100 wc setbc rdxxxx,#27 setbc wrxxxx,#27 mov shift,wsize 'set shift by word size shr shift,#1 mov amask,wsize 'set amask by word size sub amask,#1 xor amask,h0001FFFF and view,amask 'trim view and enter,amask 'trim enter set_size_ret ret rdxxxp getp v1 wc 'read pin as "0" or "1" if_nc mov value,#0 if_c mov value,#1 rdxxxj jmp #rdxxxx_ret 'd = rdxxxx_ret/rdxxxm rdxxxm setptra v1 'read mem rdxxxx rdbyte value,ptra++ 'rdbyte/rdword/rdlong rdxxxp_ret rdxxxx_ret ret wrxxxx wrbyte value,ptrb++ 'wrbyte/wrword/wrlong wrxxxx_ret ret ' ' ' Input line ' rx_line setspa #0 'point to start of line mov x,#">" 'show prompt call #tx call #rx 'get first chr cmp x,#"'" wz 'check for repeat if_nz jmp #:first 'if not repeat, first chr :show popar x wz 'repeat, show line if_nz call #tx if_nz jmp #:show jmp #:done :loop call #rx 'get next chr :first cmp x,#13 wz 'cr? if_z jmp #:cr cmp x,#8 wz 'backspace? if_nz cmp x,#127 wz if_z jmp #:bs cmp x,#" " wc 'visible chr? if_nc cmpr x,#"~" wc if_c jmp #:loop pusha x 'visible chr, append to line chkspa wc 'overflow? if_c subspa #1 'if overflow, back up if_nc call #tx 'if not overflow, print chr jmp #:loop :bs chkspa wz 'backspace, line empty? if_nz pushar x 'if not empty, if_nz call #tx '..print backspace if_nz call #tx_space '..print space if_nz popar x '..print backspace if_nz call #tx if_nz subspa #1 '..back up jmp #:loop :cr pusha #0 'cr, end line with 0 :done setspa #0 'point to start of line tx_crlf mov x,crlf 'print cr/lf call #tx tx_crlf_ret rx_line_ret ret ' ' ' Parse hex/text data ' parse_data mov w,#0 'reset data count setinda 0 'point to string data :hex call #parse_next 'hex loop, check hex if_nz call #enter_data 'if hex, enter value cmp x,#" " wz 'check for space (more hex) if_z jmp #:hex 'if more hex, loop cmp x,#"'" wz 'not hex, "'"? if_nz jmp #:done 'if not "'", done :text addspa #2 'text loop popa x 'get and point to next chr cmp x,#"'" wz 'check for "'" if_z jmp #:hex 'if "'", back to hex tjz x,#:done 'if eol, done mov value,x 'text chr call #enter_data 'enter chr jmp #:text 'loop :done sub w,#1 wc 'get data count if_nc mov dsize,w 'if 0, reuse old data movd :fix,dsize 'form circular buffer :fix fixinda 0,0 '(no instruction-modification problem with 1:4 threading) parse_data_ret ret enter_data incmod w,#dmax wc 'check if data limit exceeded if_c jmp #cmd_error 'if data limit exceeded, error mov inda++,value 'store value in data enter_data_ret ret ' ' ' Parse hex ' parse_hex call #parse_next 'try to parse hex if_z jmp #cmd_error 'if no hex, error parse_hex_ret ret ' ' ' Parse line (@spa), z=0 if hex (value) ' parse_next addspa #1 'advance to next chr parse mov value,#0 wz 'z=1 call #skip_spaces wz 'skip any spaces (preserve z) :loop popar x 'get chr call #check_hex 'check hex if_c shl value,#4 'if hex, append nibble and loop if_c or value,x if_c jmp #:loop wz 'z=0 subspa #1 'repoint to non-hex chr call #skip_spaces wz 'skip any post-hex spaces (preserve z) call #check_hex 'check hex if_c popa x 'if hex, back up to space chr cmpr x,#"a"-1 wc 'make non-hex chr uppercase if_c cmp x,#"z"+1 wc if_c sub x,#"a"-"A" parse_next_ret parse_ret ret ' ' ' Skip spaces (@spa) ' skip_spaces popar x 'skip space chr(s) cmp x,#" " wz if_z jmp #skip_spaces subspa #1 'back up to non-space chr skip_spaces_ret ret wz 'restore z ' ' ' Check hex (x), c=1 if hex (x) ' check_hex cmpr x,#"0"-1 wc '"0".."9" -> $0..$9 if_c cmp x,#"9"+1 wc if_c add x,#"A"-"9"-1 if_nc cmpr x,#"A"-1 wc '"A".."F" -> $A..$F if_c cmp x,#"F"+1 wc if_c add x,#"a"-"A" if_nc cmpr x,#"a"-1 wc '"a".."f" -> $A..$F if_c cmp x,#"f"+1 wc if_c sub x,#"a"-10 check_hex_ret ret ' ' ' Print range (v1..v2) ' tx_range1 mov v1,view 'view..view + v2 tx_range2 and v2,amask 'v1..v1 + v2 add v2,v1 tx_range call #check_range 'check range mov view,v1 'set address :line mov value,view 'print 5-digit address mov hsize,#5 call #tx_hex call #tx_dspace 'print "- " mov x,wsize 'get number of words on line rev x,#32-5 mov v1,z max v1,x mov v2,v1 'get number of ascii bytes on line shl v2,shift sub z,v1 'update number of words left setptra view 'print hex words :hex call #rdxxxx mov hsize,wsize shl hsize,#1 call #tx_hex call #tx_space djnz v1,#:hex setptra #spquote_ 'print " '" call #tx_string setptra view 'print ascii bytes :ascii rdbyte x,ptra++ cmp x,#" " wc 'visible chr? if_nc cmpr x,#"~" wc if_c mov x,#"." 'substitute "." for non-visible chrs call #tx djnz v2,#:ascii getptra view 'update address setptra #quotecr_ 'print "'" + cr call #tx_string call #rx_check 'check key hit if_z tjnz z,#:line 'if no key hit and more words left, print another line tx_range1_ret tx_range2_ret tx_range_ret ret ' ' ' Print string (@ptra) ' tx_string addptra base 'add data base pointer tx_string_loop rdbyte x,ptra++ 'get chr tx_string_ret tjz x,#0 'if 0, done test x,#$80 wz 'substring? if_nz notb tx_string_loop,#8 'toggle ptra/ptrb if_nz setptrb x 'ptrb points to substring if_nz addptrb base if_nz jmp #tx_string_loop 'start substring or resume string cmp x,#"`" wz 'long tab? if_z subr y,#32-16 if_nz cmp x,#"~" wz 'short tab? if_z add y,#16 :tab if_z call #tx_space if_z djnz y,#:tab if_z call #tx_dspace if_z jmp #tx_string_loop cmp x,#13 wz 'cr? if_z call #tx_crlf if_z mov y,#0 if_nz call #tx 'other? if_nz add y,#1 jmp #tx_string_loop ' ' ' Print hex (value) ' tx_hex mov y,hsize 'pre-rotate to get 1st nibble in top shl y,#2 ror value,y mov y,hsize 'print nibbles :loop rol value,#4 mov x,value call #tx_nib djnz y,#:loop tx_hex_ret ret ' ' ' Print "- " ' tx_dspace mov x,dspace jmp #tx ' ' ' Print space ' tx_space mov x,#" " jmp #tx ' ' ' Print nibble (x) ' tx_nib and x,#$F 'isolate nibble cmp x,#$A wc 'alpha or numeric? if_c add x,#"0" 'numeric if_nc add x,#"A"-$A 'alpha ' ' ' Transmit chr (x) ' tx shl x,#1 'insert start bit setb x,#9 'set stop bit getcnt w 'get initial time :loop add w,period 'add bit period to time passcnt w 'loop until bit period elapsed shr x,#1 wc 'get next bit into c setpc tx_pin 'write c to tx pin tjnz x,#:loop 'loop until bits done tx_dspace_ret tx_space_ret tx_nib_ret tx_ret ret ' ' ' Receive chr (x) ' rx call #rx_check 'wait for rx chr if_z jmp #rx rx_ret ret ' ' ' Check receiver, z=0 if chr (x) ' rx_check or rx_tail,#$80 'if start or rollover, reset tail getspb rx_temp wz 'if head uninitialized, z=1 if_nz cmp rx_temp,rx_tail wz 'if head-tail mismatch, byte ready, z=0 if_nz getspa rx_temp 'preserve spa if_nz setspa rx_tail 'get tail if_nz popar x 'get byte at tail if_nz getspa rx_tail 'update tail if_nz setspa rx_temp 'restore spa rx_check_ret ret '************************ '* Serial Receiver Task * '************************ rx_task chkspb wz 'if start or rollover, reset head if_z setspb #$80 mov rx_bits,#9 'ready for 8 data bits + 1 stop bit neg rx_time,period 'get -0.5 period sar rx_time,#1 jp rx_pin,#$ 'wait for start bit subcnt rx_time 'get time + 0.5 period for initial 1.5 period delay :bit rcr rx_data,#1 'rotate c into byte add rx_time,period 'add 1 period passcnt rx_time 'wait for center of next bit getp rx_pin wc 'read rx pin into c djnz rx_bits,#:bit 'loop until 8 data bits + 1 stop bit received shr rx_data,#32-8 'align byte pushb rx_data 'store byte at head, inc head jmp #rx_task 'wait for next byte '********************** '* Baud Detector Task * '********************** baud_task movd ctr,rx_pin 'set ctra to time rx pin states :loop notb ctr,#5 wc 'if 1,0 sample set, c=0 setctra ctr '($20 -> 10000001001 -> 1, 6x 0, 1x 1, 2x 0, 1) if_nc mov limh,buff0 'if 1,0 sample set, if_nc shr limh,#4 '..make window from 1st 0 (6x if $20) if_nc neg liml,limh if_nc add limh,buff0 if_nc add liml,buff0 if_nc mov comp,buff1 'if 1,0 sample set, if_nc mul comp,#6 '..normalize 2nd 1 (1x if $20) to 6x if_nc cmpr comp,limh wc '..check if within window if_nc cmp comp,liml wc if_nc mov comp,buff2 'if 1,0 sample set, if_nc mul comp,#3 '..normalize 2nd 0 (2x if $20) to 6x if_nc cmpr comp,limh wc '..check if within window if_nc cmp comp,liml wc if_nc add buff0,buff2 'if $20, if_nc shr buff0,#3 '..compute period from 6x 0 and 2x 0 if_nc mov period,buff0 '..update period mov buff0,buff1 'scroll sample buffer mov buff1,buff2 :wait getcosa buff2 'wait for next sample tjnz buff2,#:loop jmp #:wait '************* '* Constants * '************* base long $55C 'start of byte data h0001FFFF long $0001FFFF 'memory limit crlf long 1<<18 + $0A<<10 + $0D 'cr/lf dspace long 1<<18 + " "<<10 + "-" 'dash/space ctr long %100_01001 'ctr configuration for timing low on rx pin '************* '* Variables * '************* reserves w res 1 'main task x res 1 y res 1 z res 1 v1 res 1 v2 res 1 value res 1 view res 1 enter res 1 pin res 1 dsize res 1 hsize res 1 wsize res 1 shift res 1 amask res 1 rx_pin res 1 tx_pin res 1 rx_tail res 1 'serial receiver task rx_temp res 1 rx_time res 1 rx_data res 1 rx_bits res 1 buff0 res 1 'baud detector task buff1 res 1 buff2 res 1 limh res 1 liml res 1 comp res 1 period res 1
One thing I'm are curious Why You not implemented Intel HEX loader in monitor with checksum cheking.
That have ben nice to use as Loader from any Terminal program.
Ps. In 8080 assembly it is only some lines of code.
Because it's burdensome to have to remember how to compose Intel Hex lines and compute those checksum bytes. That's work for a computer, not a person. The monitor has a checksum command that can sum data within an address range in whatever mode you are are in (bytes/word/long) and return a 32-bit sum. You could just do one of those after loading your code and make sure it comes back with what you expect.
Yes and NO.
With Intel HEX Loader it is possible to have automated Loader that can know what place in memory I will place my data. And automatically test after every line if transfer was correct.
In steps You describe it is impossible.
Here is how you'd enter code with the monitor and get a checksum:
=== Propeller II Monitor === >1000:50 72 6F 70 32 2E 30 20 00 20 7C 0C 03 D0 7C 0C >1010:45 FE C1 0D E3 B6 FC 0C 01 C2 7C 0C 01 C2 7C 0D >1020:01 C2 FC 80 1F C2 7C 62 01 E0 FC 30 66 0C A8 80 >1030:01 CA 7C 0C 2A DE FC FA 5B C0 FC 1C 7C FA BC A0 >1000.103F^ 00001C98 >
Here is Intel Hex (as used by Altera's FPGA tool):
:100100000C7CD0030C7C200020302E32706F72509C :100101000D7CC2010C7CC2010CFCB6E30DC1FE45A6 :1001020080A80C6630FCE001627CC21F80FCC20149 :10010300A0BCFA7C1CFCC05BFAFCDE2A0C7CCA0197
Both give you checksum functions, but the first seems way more human to me.
I agree with your signature line: "If your gonna construct something, make it as simple as possible yet as versatile as possible."
Thanks for that word on my signature.
BUT still Alteras HEX not give complete hex code. It is missing last line in it - That are not necessary in it BUT important in CPU's (computers).
It is starting point of loaded code to automatically start that Loaded program.
In time I worked with control systems only possibility to update systems I have build was 300 baud modem -- And with Intel hex it give me possibility to Update them from Malmoe even if them was placed in Stockholm.
I see Yours monitors possibility to show me HEX but still show me how I can use it with automated LOADER that can use simple serial communication ---- That Load code from serial test it if it is correct -- And then start it without my intervention.
After you load the hub memory, you can start a cog from it. For example, if you wanted to restart cog0 (which is running the monitor) with a program at $1000, you'd just type "0+1000" that would start cog0 at $1000.
Here is the help menu from the monitor:
- HUB - {adr{.adr}} - View {adr{.adr}}/{dat{ dat}} - Search {adr{.adr}}:{dat{ dat}} - Enter adr.adr[</>]adr - Move adr.adr^ - Checksum adr@ - Watch [Y/W/N] - Byte/word/long - COGS - cog+adr{+adr} - Start cog- - Stop M - Map - PINS - {pin}[H/L/T/Z/R] - High/low/toggle/off/read pin# - Watch pin|cfg - Configure dat\ - Set DACs - MISC - dat* - Set clock ' - Repeat Q - Quit
I see we don't understand each other.
So my question are -- Can I in time I Load that program in memory some 1000 Km by simple serial modem be sure as it loaded correctly so it can be Started.
If I load in my systems that Intel HEX LOADER automatically check for errors and only start that code if error free.
If not give me prompt with info on load error.
Ps. It is not as I say You need implement that -- BUT only debate with You what are usable.
Lets say I send system with Propeller II up in one balloon and then see I need update it by some serial interface as simply as possible -- BUT need have security that will work correctly.
Steps You describe -- NOT give me automated update possibility's.
Bytes Address ___ Code ___________________________ Checksum.
:10 0100000C7CD0030C7C200020302E32706F7250 9C :10 0101000D7CC2010C7CC2010CFCB6E30DC1FE45 A6 :10 01020080A80C6630FCE001627CC21F80FCC201 49 :10 010300A0BCFA7C1CFCC05BFAFCDE2A0C7CCA01 97
It is line that are missing in Altera HEX code that give automated Start of Loaded code.
Line to start loaded code - xx checksum of this line
:0000 1000 XX
Ps 2. --- I see I need add to my signature line You wreit on --- And see it is usable
what I understand from Chips messages is:
1. you load memory by this command 2. then you compute the checksum with 3. your remote loader program checks if this is correct and if not repeats the steps 1 and 2
4. if all is fine you start your code where you want with
so the only difference I see to your approach is that the check if the checksum is correct is done on the loader program and not inside the loaded PROP2
If you like you can even do this line by line
load the line, calc checksum, if ok proceed, else resend the line.
Yes I understand that.
But for automated HEX loader it need have possibility to send from Terminal simple text file in Intel HEX that MONITOR automatically load in correct place and if al OK then START it without any extra commands from You !!
so with you mean the part running in the PROP2, not a program on the sender side.
There you want to be able to only do with a simple terminal.
Then this would require a kind of conditional start command in the monitor
like FORTH
Original Intel HEX loader on 8080 check every loaded line for CHECKSUM - if not correct enter Monitor command mode else load next line.
Then if it enter last line with (Byte counter 0) Start address -- Simply transfer Start address to tthis address.
Ps. That give possibility to use send FILE mode in terminal program to load and start code automaticaly
Ps 2. --- That system give possibility to update Program code by any type of Radio / Serial -Link.
Are there any (effortless) means of patching only part of the running monitor, perhaps a new command to control that behavior, to extend (or ablate) funcionality without having to serialy re-send and re-check the entire (new) monitor then stoping, loading and restarting Cog 0?
Can that be done by the use of self modifying code that acts based on Hub memory contents detected by the running monitor and/or a specific triggering event (command, piece of code or anything else)?
(crossing my fingers and praying here
Yanomani
I *REALLY* like the monitor - it will be extremely handy.
BUT
What did you end up doing with the direct mode of {RD|WR}{BYTE|WORD|LONG|QUAD} ?
The reason I ask that with the rom in low memory, the direct mode for the instructions would now be useless; knowing you, I expect you would have found a new use for it... I am guessing one of:
A) added the extra bit to the offset
C) using it to select from among four pointer registers (instead of two)
Inquiring minds want to know...
(I suspect it is either A or B, C would be a pretty big change)
Regards,
Bill
Great, I can get started on P2, with my Tandy Model 100 now!
There is no more direct addressing for RDxxxx/WRxxxx instructions. Any immediate #S value is treated as a pointer. So, I think "A" is the answer, if I understand.
I don't understand exactly what you are asking, but it sounds like you would like the monitor to have a restricted mode where it only allows a subset of commands to enable a verifiable download-and-execute procedure?
I wasn't comparing P2 to P1, but P2 to most of the 32-bit embedded world.
You are certainly right...a monitor is not a development system. That's why I referred to it as a giant leap toward that end. It's a needed hook, especially if you're taking an incremental approach like I intend to do.
Of course the P2 has other resources that would also contribute to it hosting a development system: More screen memory, and more hooks to fast external memory.
great work - I love the monitor.
I think @Sapieha is confused about the Monitor replacing boot over serial. As far as I understand the monitor is the last in the line of duty.
So after failing to boot from serial, and failing to boot from flash the monitor gets activated if NO fuses for encryption are destroyed/set.
So there is still a normals serial boot-loader, right?
Can you please confirm this?
Enjoy!
Mike
-Phil
The keyboard is awesome! Heck, maybe I can gut another one for other uses. The thing runs about 20 hours on a nice set of batteries. And that's 20 hours just ON. If one is careful about not leaving it on, it's not unusual to go a week, using it when needed.
I'm now wondering whether or not somebody did an 80 or 64 column display ROM for it.
Could use the Apple as well. And I will too, just for some fun.
Honestly, a P2 with some external RAM can probably do reasonable development. Bet we see a prop only system within a year. Can't wait, because I may well gut something, get that all installed and run portable, all prop! I've been collecting displays and such for that purpose as I find them cheap.
Not sure what such a system would look like yet, but I know it will have two SD card slots, display, keyboard, battery, I/O, RAM. Lots of time for that once P2 gets completed.
I think he's asking for an easy extension scheme. Boot monitor, "squirt the extensions over" restart, and now it's a monitor, plus some stuff.
Bet it's not hard to do once we get to play with it some.
Re: Intel HEX
Saphia just wants it to run the code sent over without further intervention. [deleted]
NO -- My thinking was have alternate Loader -- That can load Simple ASCI HEX file from any terminal program and execute it.
If You read entire Forum You will find that many people have problems with Load Propeller from all type of wireless serial communication.
With Intel HEX Loader I talk on - that problem can be resolved.
I'd agree with this, part of the terminal access cut/paste/copy/send file facility, should include blocks of intel hex.
Things like Help strings, really do not need to be consuming valuable RAM space - put them in the terminal.
Also things like Move and Fill and even Search, those can easily be done from a configured terminal, and are so rare
the speed difference is not going to matter.
In contrast, the RAM space is precious, and needed by everyone.
Instead, put stuff in the smallest possible Monitor that allows human and non-human systems to easily slave the Prop II.
Intel hex is universal, and comes from many tools, and a tiny micro can either compose Intel Hex, or Block-copy it.
Given all intel hex lines start with :, it should be a safe syntax to include.
This also give you a simple way to transport library files, that turn this into a really useful I/O Expander.
Intel hex also allows comments, and you can append any single 'Load and go' line you like.
Any common comment tag can be used ; or // or -- ; is my first guess, but may be close to :
An example of how this would work :
; Title Comment Library Version 0.124 ; PWM Generation blah etc -- Pin lists, link info - comments simply stripped by both/either Terminal and Monitor :100100000C7CD0030C7C200020302E32706F72509C :100101000D7CC2010C7CC2010CFCB6E30DC1FE45A6 :1001020080A80C6630FCE001627CC21F80FCC20149 :10010300A0BCFA7C1CFCC05BFAFCDE2A0C7CCA0197 :00000001FF // Load above bytes, into Cog2, and Run cog2+0100+103F ; whatever Monitor uses ; Title Comment Library Version 0.124 ; Multi Channel Quadrature Counter : Pins : ; Pin lists, link info - comments simply stripped by both/either Terminal and Monitor :100100000C7CD0030C7C200020302E32706F72509C :100101000D7CC2010C7CC2010CFCB6E30DC1FE45A6 :00000001FF ; Load above bytes, into Cog3, and Run cog3+0100+102F ; whatever Monitor uses
Someone can Select the I/O Function Library(s) from the configured terminal (or just paste it in), and then connect and test with their Host,
and when they have decided that works, they paste their HEX library into their Host-loader, and they are on-air.
They do not need to know any PASM, and it is a safe-step from terminal to field, as they can compose a single text script like file as they work.
This target user is a total Prop II novice, but they are system experts. Make integration easy for them.
You are correct.
One thing I can add to Yours comments are that many of Terminal programs have ---- Send TEXT file command inbuilt that simplify that Loading.