Ho to reuse FullDuplexSerial from multiple COGs? [RESOLVED - use cserial]
Andrey Demenev
Posts: 386
I have 2 cogs running SPIN code, and need to write data to serial port from each. I have tried, the following, without success:
debug.spin
main.spin:
I receive "MAIN" twice, then nothing.
What is the correct way of doing this?
Post Edited (Andrey Demenev) : 5/5/2010 1:49:55 AM GMT
debug.spin
VAR
LONG gLock
OBJ
fd : "FullDuplexSerial"
PUB init
gLock := lockNew
fd.start(31, 30, 0, 115200)
PUB str(s)
repeat until not lockSet(gLock)
result := fd.str(s)
lockClr(gLock)
PUB tx(b)
repeat until not lockSet(gLock)
result := fd.tx(b)
lockClr(gLock)
PUB dec(b)
repeat until not lockSet(gLock)
result := fd.dec(b)
lockClr(gLock)
PUB hex(b, n)
repeat until not lockSet(gLock)
result := fd.hex(b,n)
lockClr(gLock)
main.spin:
CON
_CLKMODE = XTAL1 + PLL8X
_CLKFREQ = 96_000_000
OBJ
debug: "debug"
another: "another"
PUB main
debug.init
another.start
repeat
debug.str(string("MAIN", $0D))
WAITCNT(CLKFREQ + CNT)
OBJ
debug: "debug"
var
LONG stack[noparse][[/noparse]32]
PUB start
CogNew(main, @stack)
PUB main
repeat
debug.str(string("ANOTHER", $0D))
WAITCNT(CLKFREQ + CNT)
I receive "MAIN" twice, then nothing.
What is the correct way of doing this?
Post Edited (Andrey Demenev) : 5/5/2010 1:49:55 AM GMT

Comments
What you would have to do is to write an object that can stuff data to the tx buffer of the (once) running fd object. Therefore you need to know the fd object's tx_head, tx_tail and tx_buffer pointers. You would then do the same as the fd.tx itself does: check if long[noparse]/noparse]tx_head_ptr]+1 == long[noparse][[/noparse]tx_tail], and wait if they are equal. Otherwise write byte[noparse][[/noparse]tx_buffer][noparse][[/noparse]long[noparse][[/noparse]tx_head := data and add 1 to the head with wrapping at the buffer size: long[noparse][[/noparse]tx_head_ptr] := (long[noparse][[/noparse]tx_head_ptr] + 1) & 15
In code - add this to FullDuplexSerial.spin
and in your debug.init code write:
PUB init(head, tail, buffer) tx_head_ptr := head tx_tail_ptr := tail tx_buffer_ptr := buffer PUB chr(ch) '' Print a character by stuffing it to the tx buffer of a running FullDuplexSerial object repeat while ((long[noparse][[/noparse]tx_head_ptr] + 1) & 15) == long[noparse][[/noparse]tx_tail_ptr] byte[noparse][[/noparse]tx_buffer_ptr][noparse][[/noparse]long[noparse][[/noparse]tx_head_ptr]] := ch long[noparse][[/noparse]tx_head_ptr] := (long[noparse][[/noparse]tx_head_ptr] + 1) & 15 PUB str(strptr) | index '' Print a NUL terminated string repeat index from 0 to strsize(strptr) chr(byte[noparse][[/noparse]strptr][noparse][[/noparse]index]) PUB dec(value) | _i '' Print a decimal number result := 0 if value < 0 chr("-") if (value == NEGX) chr("2") value += 2_000_000_000 -value _i := 1_000_000_000 repeat 10 if value => _i chr(value / _i + "0") value //= _i result~~ elseif result or _i == 1 chr("0") _i /= 10 PUB hex(value, digits) '' Print a hexadecimal number value <<= (8 - digits) << 2 repeat digits chr(lookupz((value <-= 4) & $F : "0".."9", "A".."F")) DAT tx_head_ptr long 0 tx_tail_ptr long 0 tx_buffer_ptr long 0The other methods of debug should then use chr(ch) to send bytes to the fd object.
From main you call fd.init() once and then debug.init(fd.get_tx_head, fd.get_tx_tail, fd.get_tx_buffer) to setup the pointers.
Every object that wants to use debug would then have to be passed the 3 pointers as well. You could set up an array of 3 longs and put the 3 pointers in there, then you'd have to pass just the address of that array to your objects, which would then call debug.init() with the 3 values from the array.
Locking is not strictly necessary, but if you want to add it, you would pass the lock handle as well and try to acquire the lock at the start of each function in debug.spin, then release it at the end of the function.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Pullmoll's Propeller Projects
Post Edited (pullmoll) : 5/4/2010 8:05:02 AM GMT
· fd.start(31, 30, %10000, 115200)
The·start method·should only be called once, normally from cog 0 in the top object.· Check out the test program in CLib.· I have several cogs waiting on the same flag, and then they all print at the same time.
You can download CLib from the OBEX at http://obex.parallax.com/objects/594/·.
Dave
main.spin
CON _CLKMODE = XTAL1 + PLL8X _CLKFREQ = 96_000_000 OBJ debug: "cserial" another: "another" PUB main debug.start(31, 30, %10000, 115200) another.start repeat debug.str(string("MAIN", $0D)) WAITCNT(CLKFREQ + CNT)another.spin
OBJ debug: "cserial" var LONG stack[noparse][[/noparse]32] PUB start CogNew(main, @stack) PUB main repeat debug.str(string("ANOTHER", $0D)) WAITCNT(CLKFREQ + CNT)I have also attached cserial.spin.
Dave