The ROM is now done. It spans from hub byte address $00000 to $00EFF, with $F00 to $1FFFF being RAM. The ROM contains the booter (SPI Flash or Serial) with SHA-256/HMAC authentication to facilitate code protection, and a serial (RX/TX) monitor which starts up if there's no authenticated loader to execute and no security key programmed into the first 128 fuses - you just hit <space> and it auto-bauds and gives you a prompt. The monitor could be used as a very simple development interface, where you just send text scripts to load code and start cogs.
Below is the code for the monitor which uses the new hardware multi-threading to run concurrent auto-baud detection, serial input, and main monitor code:
'********************************************************'* *'* Propeller II ROM Monitor *'* *'* Version 0.1 *'* *'* 11/01/2012 *'* *'********************************************************CON
branch1_ = 0
branch2_ = branch1_ + 31
branch3_ = branch2_ + 35
hello_ = branch3_ + 15
error_ = hello_ + 33
hitspace_ = error_ + 11
spacesq_ = hitspace_ + 10
quotecr_ = spacesq_ + 4
help_ = quotecr_ + 3DAT'********'* 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_fill, ":"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
spacesq byte" '",0'4 bytes
quotecr byte"'",13,0'3 bytes
help byte13, "~HUB -",13byte"{adr{.adr}}", "`View",13byte"{adr{.adr}}/{dat{ dat}}", "`Search",13byte"{adr{.adr}}:dat{ dat}", "`Enter",13byte"adr.adr[</>]adr", "`Move",13byte"adr.adr^", "`Checksum",13byte"adr@", "`Watch",13byte"[Y/W/N]", "`Byte/word/long",13byte"~COGS -",13byte"cog+pgm{+ptr}", "`Start",13byte"cog-", "`Stop",13byte"M", "`Map",13byte"~PINS -",13byte"{pin}[H/L/T/Z/R]", "`High/low/toggle/off/read",13byte"pin#", "`Watch",13byte"pin|cfg", "`Configure",13byte"dat\", "`Set DACs",13byte"~MISC -",13byte"dat*", "`Set clock",13byte"'", "`Repeat",13byte"Q", "`Quit",13byte0
longs long'*********'* Entry *'*********
monitor org
rx_pin reps #$1F6-reserves,#1'clear reserves (first 5 registers get reused)
tx_pin setinda reserves
tx_time mov inda++,#0
v1 getptrb base 'get data base pointer
v2 sub base,#longs << 2
s0 long0'start of search data = 0/nop (s0..s1 get reused)
getptra rx_pin 'get rx pinshr rx_pin,#8
getptra tx_pin 'get tx pin
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
s1 'end of search data'*************'* 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 rangemov y,#0'reset search size
setinda s0 'point to search data
movs enter_str,#enter_search 'set search modecall #parse_str 'get search stringsub y,#1wc'get search sizeif_ncmov ssize,y 'if 0, search old data again
:start setptra v1 'start search, point to search address
setinda s0 '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,ssize wc'word match, increment match counterif_ncjmp #:word'if more words to match, compare next wordmov v2,ssize '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_enter2 mov enter,v1 'addr:, set enter addressand enter,amask 'trim enter address
cmd_enter mov z,#0':, reset fill countcall #parse_enter 'parse and enter datajmp #cmd_loop 'next command''' Fill data'
cmd_fill call #check_range 'addr.addr:, check range, z=words to fillmov enter,v1 'set initial enter addresscall #parse_enter 'parse and enter fill-pattern data (jumps to cmd_loop if fill complete)cmp enter,v1 wz'any data entered?if_zjmp #cmd_error 'if no data entered, errormov y,enter 'get end-of-fill-pattern address (current enter)
setptra v1 'set start-of-fill-pattern address (initial enter)
:loop getptra x 'get current-fill-pattern addresscmp x,y wz'compare against end-of-fill-pattern addressif_z setptra v1 'if same, reset to start-of-fill-pattern addresscall #rdxxxx 'get fill-pattern wordcall #enter_data 'enter word (jumps to cmd_loop when fill complete)jmp #:loop 'loop to fill next word''' 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
h0001FFFF long$0001FFFF''' 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
crlf long1 << 18 + $0A << 10 + $0D''' Parse string of hex/text for enter/fill or search'
parse_enter movs enter_str,#enter_data
parse_str call #parse_next 'hex loop, check hexif_nzcall #enter_str 'if hex, enter valuecmp x,#" "wz'check for space (more hex)if_zjmp #parse_str 'if more hex, loopcmp x,#"'"wz'not hex, "'"?if_nzjmp #parse_str_ret 'if not "'", done
:text addspa #2'text looppopa x 'get and point to next chrcmp x,#"'"wz'check for "'"if_zjmp #parse_str 'if "'", back to hextjz x,#parse_str_ret 'if eol, donemov value,x 'text chrcall #enter_str 'enter chrjmp #:text 'loop
parse_enter_ret
parse_str_ret ret
enter_str jmp #enter_data 'jump to enter_data or enter_search
enter_search incmod y,#s1-s0 wc'search, check if search limit exceededif_cjmp #cmd_error 'if search limit exceeded, errormov inda++,value 'store value in search datajmp #enter_str_ret 'return
enter_data setptrb enter 'enter/fill, get pointercall #wrxxxx 'store value in memory
getptrb enter 'update pointerdjz z,#cmd_loop 'if fill done, abort (don't return)
enter_data_ret
enter_str_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 #spacesq_ '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, donecmp 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
dspace long1 << 18 + " " << 10 + "-"''' 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 tx_time 'get initial time
:loop add tx_time,period 'add bit period to time
passcnt tx_time '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
ctr long%100_01001'ctr configuration for timing low on rx pin'*************'* Variables *'*************
reserves
base res1'main task
x res1
y res1
z res1
value res1
view res1
enter res1
pin res1
ssize res1
hsize res1
wsize res1
shift res1
amask 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
I never got around to adding the SDRAM boot, as it was a lot of work just to get what's in there ironed out. Of the 3,840 ROM bytes, the monitor takes 2,384 bytes, which is a lot, but I think it's a really nice thing to have. Both the monitor and the SHA-256/HMAC programs can be executed independently from user application code and are very simple to operate.
The ROM is now done. It spans from hub byte address $00000 to $00EFF, with $F00 to $1FFFF being RAM. The ROM contains the booter (SPI Flash or Serial) with SHA-256/HMAC authentication to facilitate code protection, and a serial (RX/TX) monitor which starts up if there's no authenticated loader to execute and no security key programmed into the first 128 fuses - you just hit <space> and it auto-bauds and gives you a prompt. The monitor could be used as a very simple development interface, where you just send text scripts to load code and start cogs.
Below is the code for the monitor which uses the new hardware multi-threading to run concurrent auto-baud detection, serial input, and main monitor code:
'********************************************************'* *'* Propeller II ROM Monitor *'* *'* Version 0.1 *'* *'* 11/01/2012 *'* *'********************************************************CON
branch1_ = 0
branch2_ = branch1_ + 31
branch3_ = branch2_ + 35
hello_ = branch3_ + 15
error_ = hello_ + 33
hitspace_ = error_ + 11
spacesq_ = hitspace_ + 10
quotecr_ = spacesq_ + 4
help_ = quotecr_ + 3DAT'********'* 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_fill, ":"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
spacesq byte" '",0'4 bytes
quotecr byte"'",13,0'3 bytes
help byte13, "~HUB -",13byte"{adr{.adr}}", "`View",13byte"{adr{.adr}}/{dat{ dat}}", "`Search",13byte"{adr{.adr}}:dat{ dat}", "`Enter",13byte"adr.adr[</>]adr", "`Move",13byte"adr.adr^", "`Checksum",13byte"adr@", "`Watch",13byte"[Y/W/N]", "`Byte/word/long",13byte"~COGS -",13byte"cog+pgm{+ptr}", "`Start",13byte"cog-", "`Stop",13byte"M", "`Map",13byte"~PINS -",13byte"{pin}[H/L/T/Z/R]", "`High/low/toggle/off/read",13byte"pin#", "`Watch",13byte"pin|cfg", "`Configure",13byte"dat\", "`Set DACs",13byte"~MISC -",13byte"dat*", "`Set clock",13byte"'", "`Repeat",13byte"Q", "`Quit",13byte0
longs long'*********'* Entry *'*********
monitor org
rx_pin reps #$1F6-reserves,#1'clear reserves (first 5 registers get reused)
tx_pin setinda reserves
tx_time mov inda++,#0
v1 getptrb base 'get data base pointer
v2 sub base,#longs << 2
s0 long0'start of search data = 0/nop (s0..s1 get reused)
getptra rx_pin 'get rx pinshr rx_pin,#8
getptra tx_pin 'get tx pin
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
s1 'end of search data'*************'* 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 rangemov y,#0'reset search size
setinda s0 'point to search data
movs enter_str,#enter_search 'set search modecall #parse_str 'get search stringsub y,#1wc'get search sizeif_ncmov ssize,y 'if 0, search old data again
:start setptra v1 'start search, point to search address
setinda s0 '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,ssize wc'word match, increment match counterif_ncjmp #:word'if more words to match, compare next wordmov v2,ssize '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_enter2 mov enter,v1 'addr:, set enter addressand enter,amask 'trim enter address
cmd_enter mov z,#0':, reset fill countcall #parse_enter 'parse and enter datajmp #cmd_loop 'next command''' Fill data'
cmd_fill call #check_range 'addr.addr:, check range, z=words to fillmov enter,v1 'set initial enter addresscall #parse_enter 'parse and enter fill-pattern data (jumps to cmd_loop if fill complete)cmp enter,v1 wz'any data entered?if_zjmp #cmd_error 'if no data entered, errormov y,enter 'get end-of-fill-pattern address (current enter)
setptra v1 'set start-of-fill-pattern address (initial enter)
:loop getptra x 'get current-fill-pattern addresscmp x,y wz'compare against end-of-fill-pattern addressif_z setptra v1 'if same, reset to start-of-fill-pattern addresscall #rdxxxx 'get fill-pattern wordcall #enter_data 'enter word (jumps to cmd_loop when fill complete)jmp #:loop 'loop to fill next word''' 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
h0001FFFF long$0001FFFF''' 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
crlf long1 << 18 + $0A << 10 + $0D''' Parse string of hex/text for enter/fill or search'
parse_enter movs enter_str,#enter_data
parse_str call #parse_next 'hex loop, check hexif_nzcall #enter_str 'if hex, enter valuecmp x,#" "wz'check for space (more hex)if_zjmp #parse_str 'if more hex, loopcmp x,#"'"wz'not hex, "'"?if_nzjmp #parse_str_ret 'if not "'", done
:text addspa #2'text looppopa x 'get and point to next chrcmp x,#"'"wz'check for "'"if_zjmp #parse_str 'if "'", back to hextjz x,#parse_str_ret 'if eol, donemov value,x 'text chrcall #enter_str 'enter chrjmp #:text 'loop
parse_enter_ret
parse_str_ret ret
enter_str jmp #enter_data 'jump to enter_data or enter_search
enter_search incmod y,#s1-s0 wc'search, check if search limit exceededif_cjmp #cmd_error 'if search limit exceeded, errormov inda++,value 'store value in search datajmp #enter_str_ret 'return
enter_data setptrb enter 'enter/fill, get pointercall #wrxxxx 'store value in memory
getptrb enter 'update pointerdjz z,#cmd_loop 'if fill done, abort (don't return)
enter_data_ret
enter_str_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 #spacesq_ '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, donecmp 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
dspace long1 << 18 + " " << 10 + "-"''' 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 tx_time 'get initial time
:loop add tx_time,period 'add bit period to time
passcnt tx_time '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
ctr long%100_01001'ctr configuration for timing low on rx pin'*************'* Variables *'*************
reserves
base res1'main task
x res1
y res1
z res1
value res1
view res1
enter res1
pin res1
ssize res1
hsize res1
wsize res1
shift res1
amask 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
I never got around to adding the SDRAM boot, as it was a lot of work just to get what's in there ironed out. Of the 3,840 ROM bytes, the monitor takes 2,384 bytes, which is a lot, but I think it's a really nice thing to have. Both the monitor and the SHA-256/HMAC programs can be executed independently from user application code and are very simple to operate.
No flipping or hurt feelings here. I was just pointing out that such an OS choice would not light the fires of community support.
I'm sure QNX is quite fine, I have used many such embedded operating systems and would always advise against trying to use Linux for fast real-time work. Linux was never intended for that use. Try flipping a GPIO pin on a Raspi with any hard timing constaints and you'll see what I mean (See I'm not such a "fanboi").
In the context of my little dream system a hard real-time OS is not required anyway. As I said the Prop takes care of the hard real-time, multi-threaded, real world interfacing and the ARM can slouch along doing the heavy lifting of file system, networking, GUI, and other such tasks.
I might add that one reason I am a fan of the Propeller, and dare I say it XMOS, is that it does not require an OS to get that multi-tasking, real-time work done. Now that the Prop II has the abilty to run multiple threads in a COG that situation is made even better.
The ROM contains the booter (SPI Flash or Serial) with SHA-256/HMAC authentication to facilitate code protection, and a serial (RX/TX)
What is the smallest/cheapest SPI device supported ?
Will this boot from a QuadSPI part (even if first load is in 1 bit SPI mode ? )
I can see SOT23-6 SPI parts, but they seem to cost more than the 13c/3K that a SO8 SPI part costs.
Unlike i2c, where SOT23 are among the lowest cost parts available
The ROM is now done. It spans from hub byte address $00000 to $00EFF, with $F00 to $1FFFF being RAM. The ROM contains the booter (SPI Flash or Serial) with SHA-256/HMAC authentication to facilitate code protection, and a serial (RX/TX) monitor which starts up if there's no authenticated loader to execute and no security key programmed into the first 128 fuses - you just hit <space> and it auto-bauds and gives you a prompt. The monitor could be used as a very simple development interface, where you just send text scripts to load code and start cogs.
...
I never got around to adding the SDRAM boot, as it was a lot of work just to get what's in there ironed out. Of the 3,840 ROM bytes, the monitor takes 2,384 bytes, which is a lot, but I think it's a really nice thing to have. Both the monitor and the SHA-256/HMAC programs can be executed independently from user application code and are very simple to operate.
Of the 3,840 ROM bytes, the monitor takes 2,384 bytes, which is a lot, but I think it's a really nice thing to have. Both the monitor and the SHA-256/HMAC programs can be executed independently from user application code and are very simple to operate.
The monitor looks really cool but are you sure we're not going be sorry we lost the extra 2K hub RAM bytes? I know we have a lot more hub RAM space in P2 but competing microcontrollers often have twice the program space and a fair amount of SRAM as well.
IMHO, the real question is whether or not that RAM would make the difference. I don't think it would, and we've got some better means of employing external storage in P2.
The monitor looks really cool but are you sure we're not going be sorry we lost the extra 2K hub RAM bytes? I know we have a lot more hub RAM space in P2 but competing microcontrollers often have twice the program space and a fair amount of SRAM as well.
If the Monitor was Top-level single mask stuff, then that would allow some choice, (and cheaper bug fixes) but it sounds like it is compile-time ROM, which is really cast-in-stone stuff. You have to be very sure there are no bugs, and no drop-dead's.
At what size, does true-rom ( or even OTP ?) become more area efficient than Ram-As-Rom ?
With no tables anymore, this ROM does not need to be RAM-stealing, from an operational viewpoint.
It has to load into COG-RAM anyway, and does not have to be in the time-critical address decode/mux path ?
Is 2K worth an additional plan, synthesize, test, cycle? That is the cost of changing it to some copy to COG on boot option...
Basically, this makes the monitor a freebie. High value add, little to no downside. (Of course, I'm a fan too, so the high value is in the eyes of all of us.)
I can say I approve this ROM. Things are looking easy from on - it would also come in handy for the debugging purpose - at least for the host microcontroller (like MPC5200 or ARM9/M4 MCUs in clustered system), even when dealing with a bad flash.
And it could be possible that you might be able to run QNX RTOS. Same for FreeRTOS if you want open source. (uCLinux is already a RTOS anyhow.)
Nevertheless, I am waiting for when it is released so I can buy Quickstart-like board to start doing prototype software - maybe a port of uCLinux. And, afterwards start designing the hardware.
I'm a big fan of bootstrapping through a serial link. It is exactly how I want to deploy my first Prop2. Also very exciting is how quickly you've implemented and exploited the hardware multi-threading hook. Great stuff!
Would it be possible to get the information at the following links (and referenced PDFs) updated? I'm particularly interested in more detailed documentation of the new instructions, but can probably fill in some of the details by looking at their usage in the posted monitor code.
I may be doing too much reading between the lines, but does this mean that the product is going to officially be called "Propeller II"?
Good question. Their preliminary feature list calls it "Propeller 2" so they've used both names. I call it "P2" myself because I'm too lazy to type the longer name! :-)
I'm in two minds about this monitor idea.
Chip has said "Of the 3,840 ROM bytes, the monitor takes 2,384 bytes,"
What does this mean?. I thought there was leeway to swap RAM and ROM around now it seems 3,840 ROM bytes are fixed already.
A monitor is nice but how often would it be used in production? In many apps people run up aganst a RAM limit first.
I would rather have the RAM space for apps and data than consumed by a monitor that will rarely be used in finished products.
You can always load a monitor if you like for tinkering about, as the Forth guys will tell you.
What big SDRAMS? This is a micro-contoller, it should stand alone in most applications. Those external RAMs are just for us freaks who want to turn an MCU into a CP/M machine or other such off the wall stuff for fun.
2K out of a possible 128 K is almost 2% or RAM wasted. That's huge given that it will rarely be used.
Early on, I didn't think there was a 1:1 exchange rate for RAM and ROM. I thought RAM was more expensive space-wise. I almost thought it was like 1:6, if so then 2K of ROM would be only 350 bytes of RAM. But to your point, the poor guy that never uses the monitor but has a program 300 bytes too big! Then there will always be the "if only I had 20 more bytes" scenario at some upper boundary.
If I understand the situation correcty RAM cells are much bigger than ROM cells. In the Prop II we have space for 128K of RAM.
BUT it is possible to butcher some of the RAM cells to make ROM, in the same address space. Still taking the same physical space as what would have been RAM.
So, the more code you make in ROM the less RAM you have. Ergo the ROM monitor is eating valuable RAM for little benifit in general usage.
Point taken! I can't speak to the value of having an in-ROM monitor in an embedded device that won't boot. I'm just a hobbyist so my failure and recovery scenarios are different than a production user.
I can see Chip's vision being drowned out by us yokels always seeing a feature or something different as a problem. Someone will always find and hit a wall and want to knock it down. Someone will always want more of A than B. Someone will always want more of B then A. Someone will always want an MCU to be an MPU. Someone will always want you to do it their way even though it's your baby. Someone is us.
I've been pretty much just sitting back just waiting for that apple pie to come out of the oven. Knowing the cook I'm sure that even though he messes the recipe it's going to extremely tasty. I just want to sit down and enjoy, and make the most of it.
Yes, sorry, being a Brit I'm prone to the affliction observed by Charles Babbage:
"Propose to an Englishman any principle, or any instrument, however admirable, and you will observe that the whole effort of the English mind is directed to find a difficulty, a defect, or an impossibility in it. If you speak to him of a machine for peeling a potato, he will pronounce it impossible: if you peel a potato with it before his eyes, he will declare it useless, because it will not slice a pineapple. Impart the same principle or show the same machine to an American or to one of our Colonists, and you will observe that the whole effort of his mind is to find some new application of the principle, some new use for the instrument. "
Yes, sorry, being a Brit I'm prone to the affliction observed by Charles Babbage:
"Propose to an Englishman any principle, or any instrument, however admirable, and you will observe that the whole effort of the English mind is directed to find a difficulty, a defect, or an impossibility in it. If you speak to him of a machine for peeling a potato, he will pronounce it impossible: if you peel a potato with it before his eyes, he will declare it useless, because it will not slice a pineapple. Impart the same principle or show the same machine to an American or to one of our Colonists, and you will observe that the whole effort of his mind is to find some new application of the principle, some new use for the instrument. "
This might be true for your comment about large SDRAMs?
While I confess being part of that bunch that wants to turn the MCU in MPU, I thought bandwidth is going to be adequate for a graphics display and many more "serious" applications too.
Without initializing, RAM bits come up in a random state. Instead of ROM, would it be possible simply to bias those corresponding bits of RAM on power-up to contain the "ROM" code? Then they could be reused by the app program.
Without initializing, RAM bits come up in a random state. Instead of ROM, would it be possible simply to bias those corresponding bits of RAM on power-up to contain the "ROM" code? Then they could be reused by the app program.
-Phil
I asked exactly that a while back, but it was determined that 7t SRAM cells won't fit where 6t SRAM cells are designed to go.
I wonder, would it be possible to swap on the 6T-SRAM for 7T-SRAM with reset? Could "ROM" be done by having the reset mode of some cells be different than others, in order to make the ROM code? That way we wouldn't lose the RAM space for ROM, but would still be able to boot easily.
If we had more area within the bit cell and more wiring space, we could do a 7T cell with initialization. Too late for that now, though. 6T or less is all that will fit in those bit cell spaces.
Comments
The ROM is now done. It spans from hub byte address $00000 to $00EFF, with $F00 to $1FFFF being RAM. The ROM contains the booter (SPI Flash or Serial) with SHA-256/HMAC authentication to facilitate code protection, and a serial (RX/TX) monitor which starts up if there's no authenticated loader to execute and no security key programmed into the first 128 fuses - you just hit <space> and it auto-bauds and gives you a prompt. The monitor could be used as a very simple development interface, where you just send text scripts to load code and start cogs.
Below is the code for the monitor which uses the new hardware multi-threading to run concurrent auto-baud detection, serial input, and main monitor code:
'******************************************************** '* * '* Propeller II ROM Monitor * '* * '* Version 0.1 * '* * '* 11/01/2012 * '* * '******************************************************** CON branch1_ = 0 branch2_ = branch1_ + 31 branch3_ = branch2_ + 35 hello_ = branch3_ + 15 error_ = hello_ + 33 hitspace_ = error_ + 11 spacesq_ = hitspace_ + 10 quotecr_ = spacesq_ + 4 help_ = quotecr_ + 3 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_fill, ":" 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 spacesq byte " '",0 '4 bytes quotecr byte "'",13,0 '3 bytes help byte 13, "~HUB -",13 byte "{adr{.adr}}", "`View",13 byte "{adr{.adr}}/{dat{ dat}}", "`Search",13 byte "{adr{.adr}}:dat{ dat}", "`Enter",13 byte "adr.adr[</>]adr", "`Move",13 byte "adr.adr^", "`Checksum",13 byte "adr@", "`Watch",13 byte "[Y/W/N]", "`Byte/word/long",13 byte "~COGS -",13 byte "cog+pgm{+ptr}", "`Start",13 byte "cog-", "`Stop",13 byte "M", "`Map",13 byte "~PINS -",13 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 -",13 byte "dat*", "`Set clock",13 byte "'", "`Repeat",13 byte "Q", "`Quit",13 byte 0 longs long '********* '* Entry * '********* monitor org rx_pin reps #$1F6-reserves,#1 'clear reserves (first 5 registers get reused) tx_pin setinda reserves tx_time mov inda++,#0 v1 getptrb base 'get data base pointer v2 sub base,#longs << 2 s0 long 0 'start of search data = 0/nop (s0..s1 get reused) getptra rx_pin 'get rx pin shr rx_pin,#8 getptra tx_pin 'get tx pin 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 s1 'end of search data '************* '* 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 mov y,#0 'reset search size setinda s0 'point to search data movs enter_str,#enter_search 'set search mode call #parse_str 'get search string sub y,#1 wc 'get search size if_nc mov ssize,y 'if 0, search old data again :start setptra v1 'start search, point to search address setinda s0 '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,ssize wc 'word match, increment match counter if_nc jmp #:word 'if more words to match, compare next word mov v2,ssize '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_enter2 mov enter,v1 'addr:, set enter address and enter,amask 'trim enter address cmd_enter mov z,#0 ':, reset fill count call #parse_enter 'parse and enter data jmp #cmd_loop 'next command ' ' ' Fill data ' cmd_fill call #check_range 'addr.addr:, check range, z=words to fill mov enter,v1 'set initial enter address call #parse_enter 'parse and enter fill-pattern data (jumps to cmd_loop if fill complete) cmp enter,v1 wz 'any data entered? if_z jmp #cmd_error 'if no data entered, error mov y,enter 'get end-of-fill-pattern address (current enter) setptra v1 'set start-of-fill-pattern address (initial enter) :loop getptra x 'get current-fill-pattern address cmp x,y wz 'compare against end-of-fill-pattern address if_z setptra v1 'if same, reset to start-of-fill-pattern address call #rdxxxx 'get fill-pattern word call #enter_data 'enter word (jumps to cmd_loop when fill complete) jmp #:loop 'loop to fill next word ' ' ' 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 h0001FFFF long $0001FFFF ' ' ' 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 crlf long 1 << 18 + $0A << 10 + $0D ' ' ' Parse string of hex/text for enter/fill or search ' parse_enter movs enter_str,#enter_data parse_str call #parse_next 'hex loop, check hex if_nz call #enter_str 'if hex, enter value cmp x,#" " wz 'check for space (more hex) if_z jmp #parse_str 'if more hex, loop cmp x,#"'" wz 'not hex, "'"? if_nz jmp #parse_str_ret 'if not "'", done :text addspa #2 'text loop popa x 'get and point to next chr cmp x,#"'" wz 'check for "'" if_z jmp #parse_str 'if "'", back to hex tjz x,#parse_str_ret 'if eol, done mov value,x 'text chr call #enter_str 'enter chr jmp #:text 'loop parse_enter_ret parse_str_ret ret enter_str jmp #enter_data 'jump to enter_data or enter_search enter_search incmod y,#s1-s0 wc 'search, check if search limit exceeded if_c jmp #cmd_error 'if search limit exceeded, error mov inda++,value 'store value in search data jmp #enter_str_ret 'return enter_data setptrb enter 'enter/fill, get pointer call #wrxxxx 'store value in memory getptrb enter 'update pointer djz z,#cmd_loop 'if fill done, abort (don't return) enter_data_ret enter_str_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 #spacesq_ '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 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 dspace long 1 << 18 + " " << 10 + "-" ' ' ' 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 tx_time 'get initial time :loop add tx_time,period 'add bit period to time passcnt tx_time '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 ctr long %100_01001 'ctr configuration for timing low on rx pin '************* '* Variables * '************* reserves base res 1 'main task x res 1 y res 1 z res 1 value res 1 view res 1 enter res 1 pin res 1 ssize res 1 hsize res 1 wsize res 1 shift res 1 amask 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
Here is a conversation with it, from start-up:
=== Propeller II 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+pgm{+ptr} - 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 >0. 00000- 50 72 6F 70 65 6C 6C 65 72 20 49 49 20 20 76 31 'Propeller II v1' 00010- 45 FE C1 0D E3 B6 FC 0C 01 D0 7C 0C 01 D0 7C 0D 'E.........|...|.' 00020- 01 D0 FC 80 1F D0 7C 62 01 EE FC 30 6D 0C A8 80 '......|b...0m...' 00030- 01 D8 7C 0C 5A BE FC 1C 83 08 BD A0 5A BE FC 1C '..|.Z.......Z...' 00040- 83 08 BD 80 01 08 FD 28 FA FE FC A0 5A BE FC 1C '.......(....Z...' 00050- 01 D6 7C 62 24 00 64 1C B2 D6 7C 61 01 D6 FC 34 '..|b$.d...|a...4' 00060- 0F FE FC F6 02 FF FC A0 08 FE 7C 86 52 D6 E8 A0 '..........|.R...' 00070- 01 D6 7C 62 60 CE FC 1C B2 D6 7C 61 01 D6 FC 34 '..|b`.....|a...4' 00080- 16 FE FC F6 2F 00 7C 1C 77 43 FC 0C 0D 04 FD 0C '..../.|.wC......' 00090- 69 04 BD 80 6A D4 3C FF 57 43 FC 0C 00 00 4C 1C 'i...j.<.WC....L.' 000A0- 04 FE FC A0 DB B2 FC 0C DA B0 FC 0C 44 3E C0 0D '............D>..' 000B0- DA B2 FC 0C 01 FE 7C E1 01 D8 CC 27 DC AE FC 0C '......|....'....' 000C0- DB B0 FC 0C DA B0 FC 0C 25 FE FC F6 B2 E6 7C 0C '........%.....|.' 000D0- 6D FE BC A0 20 00 FD A0 5A BE E8 1C D6 AC D4 0D 'm... ...Z.......' 000E0- DB B0 D4 0C DA B0 D4 0C 01 02 FD 34 32 00 FD F6 '...........42...' 000F0- C1 02 7D 08 31 FE FC F6 40 0E C0 0D 77 00 04 E0 '..}.1...@...w...' >n >0. 00000- 706F7250 656C6C65 49492072 31762020 'Propeller II v1' 00010- 0DC1FE45 0CFCB6E3 0C7CD001 0D7CD001 'E.........|...|.' 00020- 80FCD001 627CD01F 30FCEE01 80A80C6D '......|b...0m...' 00030- 0C7CD801 1CFCBE5A A0BD0883 1CFCBE5A '..|.Z.......Z...' 00040- 80BD0883 28FD0801 A0FCFEFA 1CFCBE5A '.......(....Z...' 00050- 627CD601 1C640024 617CD6B2 34FCD601 '..|b$.d...|a...4' 00060- F6FCFE0F A0FCFF02 867CFE08 A0E8D652 '..........|.R...' 00070- 627CD601 1CFCCE60 617CD6B2 34FCD601 '..|b`.....|a...4' 00080- F6FCFE16 1C7C002F 0CFC4377 0CFD040D '..../.|.wC......' 00090- 80BD0469 FF3CD46A 0CFC4357 1C4C0000 'i...j.<.WC....L.' 000A0- A0FCFE04 0CFCB2DB 0CFCB0DA 0DC03E44 '............D>..' 000B0- 0CFCB2DA E17CFE01 27CCD801 0CFCAEDC '......|....'....' 000C0- 0CFCB0DB 0CFCB0DA F6FCFE25 0C7CE6B2 '........%.....|.' 000D0- A0BCFE6D A0FD0020 1CE8BE5A 0DD4ACD6 'm... ...Z.......' 000E0- 0CD4B0DB 0CD4B0DA 34FD0201 F6FD0032 '...........42...' 000F0- 087D02C1 F6FCFE31 0DC00E40 E0040077 '..}.1...@...w...' >y >0/'Propeller 00000- 50 72 6F 70 65 6C 6C 65 72 'Propeller' >/ 005CF- 50 72 6F 70 65 6C 6C 65 72 'Propeller' >e00. 00E00- 00 00 7C 1C 80 D4 FF 68 17 D6 FF 0E EA D7 17 86 '..|....h........' 00E10- 16 D6 D7 0C A2 D4 57 0C 18 BC D7 0C 16 D4 D7 0C '......W.........' 00E20- A2 D6 57 0C 00 00 7C 1C 17 00 7C 0E A3 00 E9 0C '..W...|...|.....' 00E30- 09 DC FF A0 F5 D9 BF A4 01 D8 FF 38 BA 01 FC F8 '...........8....' 00E40- 0C D8 FF 0C 01 DA FF 30 F5 D9 BF 80 0D D8 7F 0C '.......0........' 00E50- D6 00 7C 0D BC DD FF F6 18 DA FF 28 AB DA 7F 0C '..|........(....' 00E60- B5 01 7C 1C 00 B8 BF 54 25 B9 FF 0D F0 B8 7F 0C '..|....T%.......' 00E70- EF E5 8F A0 04 E4 CF 28 F2 E7 8F A4 EF E5 8F 80 '.......(........' 00E80- EF E7 8F 80 F0 E9 8F A0 06 E8 CF 10 F2 E9 0F E1 '................' 00E90- F3 E9 0F 85 F1 E9 8F A0 03 E8 CF 10 F2 E9 0F E1 '................' 00EA0- F3 E9 0F 85 F1 DF 8F 80 03 DE CF 28 EF EB 8F A0 '...........(....' 00EB0- F0 DF BF A0 F1 E1 BF A0 3A E2 FF 0C C5 E3 7F FA '........:.......' 00EC0- D9 01 7C 1C 89 00 00 00 00 00 00 00 9A 62 22 77 '..|..........b"w' 00ED0- 20 43 6F 70 79 72 69 67 68 74 20 32 30 31 33 20 ' Copyright 2013 ' 00EE0- 20 50 61 72 61 6C 6C 61 78 2C 20 49 6E 63 2E 20 ' Parallax, Inc. ' 00EF0- 77 77 77 2E 70 61 72 61 6C 6C 61 78 2E 63 6F 6D 'www.parallax.com' >.. 00F00- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 '................' 00F10- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 '................' 00F20- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 '................' 00F30- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 '................' 00F40- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 '................' 00F50- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 '................' 00F60- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 '................' 00F70- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 '................' 00F80- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 '................' 00F90- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 '................' 00FA0- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 '................' 00FB0- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 '................' 00FC0- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 '................' 00FD0- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 '................' 00FE0- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 '................' 00FF0- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 '................' 01000- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 '................' 01010- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 '................' 01020- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 '................' 01030- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 '................' 01040- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 '................' 01050- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 '................' 01060- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 '................' 01070- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 '................' 01080- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 '................' 01090- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 '................' 010A0- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 '................' 010B0- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 '................' 010C0- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 '................' 010D0- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 '................' 010E0- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 '................' 010F0- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 '................' >1ff00. 1FF00- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 '................' 1FF10- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 '................' 1FF20- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 '................' 1FF30- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 '................' 1FF40- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 '................' 1FF50- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 '................' 1FF60- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 '................' 1FF70- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 '................' 1FF80- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 '................' 1FF90- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 '................' 1FFA0- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 '................' 1FFB0- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 '................' 1FFC0- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 '................' 1FFD0- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 '................' 1FFE0- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 '................' 1FFF0- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 '................' >f00:1 2 3 4 5 6 >f00.f0f 00F00- 01 02 03 04 05 06 00 00 00 00 00 00 00 00 00 00 '................' >f10:'Hello!' 77 >f00. 00F00- 01 02 03 04 05 06 00 00 00 00 00 00 00 00 00 00 '................' 00F10- 48 65 6C 6C 6F 21 77 00 00 00 00 00 00 00 00 00 'Hello!w.........' 00F20- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 '................' 00F30- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 '................' 00F40- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 '................' 00F50- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 '................' 00F60- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 '................' 00F70- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 '................' 00F80- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 '................' 00F90- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 '................' 00FA0- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 '................' 00FB0- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 '................' 00FC0- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 '................' 00FD0- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 '................' 00FE0- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 '................' 00FF0- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 '................' >f00.f1f>f80 >f00. 00F00- 01 02 03 04 05 06 00 00 00 00 00 00 00 00 00 00 '................' 00F10- 48 65 6C 6C 6F 21 77 00 00 00 00 00 00 00 00 00 'Hello!w.........' 00F20- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 '................' 00F30- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 '................' 00F40- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 '................' 00F50- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 '................' 00F60- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 '................' 00F70- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 '................' 00F80- 01 02 03 04 05 06 00 00 00 00 00 00 00 00 00 00 '................' 00F90- 48 65 6C 6C 6F 21 77 00 00 00 00 00 00 00 00 00 'Hello!w.........' 00FA0- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 '................' 00FB0- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 '................' 00FC0- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 '................' 00FD0- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 '................' 00FE0- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 '................' 00FF0- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 '................' >f30.f7f:'abc >f00. 00F00- 01 02 03 04 05 06 00 00 00 00 00 00 00 00 00 00 '................' 00F10- 48 65 6C 6C 6F 21 77 00 00 00 00 00 00 00 00 00 'Hello!w.........' 00F20- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 '................' 00F30- 61 62 63 61 62 63 61 62 63 61 62 63 61 62 63 61 'abcabcabcabcabca' 00F40- 62 63 61 62 63 61 62 63 61 62 63 61 62 63 61 62 'bcabcabcabcabcab' 00F50- 63 61 62 63 61 62 63 61 62 63 61 62 63 61 62 63 'cabcabcabcabcabc' 00F60- 61 62 63 61 62 63 61 62 63 61 62 63 61 62 63 61 'abcabcabcabcabca' 00F70- 62 63 61 62 63 61 62 63 61 62 63 61 62 63 61 62 'bcabcabcabcabcab' 00F80- 01 02 03 04 05 06 00 00 00 00 00 00 00 00 00 00 '................' 00F90- 48 65 6C 6C 6F 21 77 00 00 00 00 00 00 00 00 00 'Hello!w.........' 00FA0- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 '................' 00FB0- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 '................' 00FC0- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 '................' 00FD0- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 '................' 00FE0- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 '................' 00FF0- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 '................' >m 0 0 0 0 0 0 0 M >6+1ec+1000 >m 0 1 0 0 0 0 0 M >6- >m 0 0 0 0 0 0 0 M >
I never got around to adding the SDRAM boot, as it was a lot of work just to get what's in there ironed out. Of the 3,840 ROM bytes, the monitor takes 2,384 bytes, which is a lot, but I think it's a really nice thing to have. Both the monitor and the SHA-256/HMAC programs can be executed independently from user application code and are very simple to operate.
From that I assume You have now info on dedicated PIN's for -- Serial and SPI.
Can Ypu post that so it be possible to made experimenting PCB for Propeller II.
Ps. In my opinion -- bad decision on SD -- But that is life.
Pure Genius indeed.
No flipping or hurt feelings here. I was just pointing out that such an OS choice would not light the fires of community support.
I'm sure QNX is quite fine, I have used many such embedded operating systems and would always advise against trying to use Linux for fast real-time work. Linux was never intended for that use. Try flipping a GPIO pin on a Raspi with any hard timing constaints and you'll see what I mean (See I'm not such a "fanboi").
In the context of my little dream system a hard real-time OS is not required anyway. As I said the Prop takes care of the hard real-time, multi-threaded, real world interfacing and the ARM can slouch along doing the heavy lifting of file system, networking, GUI, and other such tasks.
I might add that one reason I am a fan of the Propeller, and dare I say it XMOS, is that it does not require an OS to get that multi-tasking, real-time work done. Now that the Prop II has the abilty to run multiple threads in a COG that situation is made even better.
What is the smallest/cheapest SPI device supported ?
Will this boot from a QuadSPI part (even if first load is in 1 bit SPI mode ? )
I can see SOT23-6 SPI parts, but they seem to cost more than the 13c/3K that a SO8 SPI part costs.
Unlike i2c, where SOT23 are among the lowest cost parts available
my thoughts:
- The monitor looks great!
- Lack of SD boot is not a big deal, SPI flash is dirt cheap now.
- the rom now fully occupies the RDxxxx/WRxxxx direct address range
(Unless of course you've already changed the "upper" address bits for the direct 8 bit address to correspond to the last 256 bytes of ram...)
Did I mention that the monitor looks great???? :-)
If the Monitor was Top-level single mask stuff, then that would allow some choice, (and cheaper bug fixes) but it sounds like it is compile-time ROM, which is really cast-in-stone stuff. You have to be very sure there are no bugs, and no drop-dead's.
At what size, does true-rom ( or even OTP ?) become more area efficient than Ram-As-Rom ?
With no tables anymore, this ROM does not need to be RAM-stealing, from an operational viewpoint.
It has to load into COG-RAM anyway, and does not have to be in the time-critical address decode/mux path ?
I'm not convinced it would.
Is 2K worth an additional plan, synthesize, test, cycle? That is the cost of changing it to some copy to COG on boot option...
Basically, this makes the monitor a freebie. High value add, little to no downside. (Of course, I'm a fan too, so the high value is in the eyes of all of us.)
And it could be possible that you might be able to run QNX RTOS. Same for FreeRTOS if you want open source. (uCLinux is already a RTOS anyhow.)
Nevertheless, I am waiting for when it is released so I can buy Quickstart-like board to start doing prototype software - maybe a port of uCLinux. And, afterwards start designing the hardware.
setdacs -
http://www.parallaxsemiconductor.com/Products/propeller2specs
http://www.parallax.com/Propeller2FeatureList/tabid/898/Default.aspx
I may be doing too much reading between the lines, but does this mean that the product is going to officially be called "Propeller II"?
Chip has said "Of the 3,840 ROM bytes, the monitor takes 2,384 bytes,"
What does this mean?. I thought there was leeway to swap RAM and ROM around now it seems 3,840 ROM bytes are fixed already.
A monitor is nice but how often would it be used in production? In many apps people run up aganst a RAM limit first.
I would rather have the RAM space for apps and data than consumed by a monitor that will rarely be used in finished products.
You can always load a monitor if you like for tinkering about, as the Forth guys will tell you.
Anybody remember how much RAM P2 will have?
I believe it's 128k minus the size of the ROM.
What big SDRAMS? This is a micro-contoller, it should stand alone in most applications. Those external RAMs are just for us freaks who want to turn an MCU into a CP/M machine or other such off the wall stuff for fun.
2K out of a possible 128 K is almost 2% or RAM wasted. That's huge given that it will rarely be used.
If I understand the situation correcty RAM cells are much bigger than ROM cells. In the Prop II we have space for 128K of RAM.
BUT it is possible to butcher some of the RAM cells to make ROM, in the same address space. Still taking the same physical space as what would have been RAM.
So, the more code you make in ROM the less RAM you have. Ergo the ROM monitor is eating valuable RAM for little benifit in general usage.
I've been pretty much just sitting back just waiting for that apple pie to come out of the oven. Knowing the cook I'm sure that even though he messes the recipe it's going to extremely tasty. I just want to sit down and enjoy, and make the most of it.
EDIT: I missed Peter's post while I was posting my message. So now I understand. The extra code is needed to monitor the apple pie while it's baking.
Yes, sorry, being a Brit I'm prone to the affliction observed by Charles Babbage:
"Propose to an Englishman any principle, or any instrument, however admirable, and you will observe that the whole effort of the English mind is directed to find a difficulty, a defect, or an impossibility in it. If you speak to him of a machine for peeling a potato, he will pronounce it impossible: if you peel a potato with it before his eyes, he will declare it useless, because it will not slice a pineapple. Impart the same principle or show the same machine to an American or to one of our Colonists, and you will observe that the whole effort of his mind is to find some new application of the principle, some new use for the instrument. "
This might be true for your comment about large SDRAMs?
While I confess being part of that bunch that wants to turn the MCU in MPU, I thought bandwidth is going to be adequate for a graphics display and many more "serious" applications too.
-Phil
Edit: Found it!