..
In case anyone's missed it, the spin2ui 1.3.6 version at least fails to give any warning about duplicate
labels leading to unpredictable behaviour if you accidentally create duplicates (copy and paste for example).
Does this release fix it ? 2019-02-24 : There is a new release of spin2gui and of fastspin. The changes are:
...
- Fixed checking for duplicate labels
I have found that the SETQ value remains persistent for multiple MUXQ instructions.
Here is an example...
setq ##$0000FFFF
muxq x,y ' x -> 1122CCDD
muxq a,b ' a -> 556600FF
or v,w
muxq y,b ' y -> AABB00FF
muxq b,x ' b -> 99EECCDD
x long $11223344
y long $AABBCCDD
a long $55667788
b long $99EE00FF
Chip,
Is this a legitimate use of SETQ and MUXQ ?
Hey, I didn't know MUXQ existed. I've wanted to do that operation too.
No, it won't work like that Cluso. Easy enough to test ...
Oh, I'm wrong. Yes, you can issue as many additional MUXQ's as you like. And can be interspersed with other instructions as well.
That's quite revealing. SETQ, the instruction, must be doing two things. One is moving the specified data to special Q register. The other is arming a special flag for telling certain other instructions they can use the value in Q.
MUXQ is different to the rest of those Q using instructions because it ignores that flag and always uses the value in Q irrespective of if a SETQ has been executed or not.
Q is maintained indefinitely.
One SETQ for multiple MUXQ's could prove handy. However, there is a potential trap here if interrupts change Q, which could apply to one SETQ+MUXQ when these two instructions are not consecutive, e.g. there are three other instructions in between here.
..
In case anyone's missed it, the spin2ui 1.3.6 version at least fails to give any warning about duplicate
labels leading to unpredictable behaviour if you accidentally create duplicates (copy and paste for example).
Does this release fix it ? 2019-02-24 : There is a new release of spin2gui and of fastspin. The changes are:
...
- Fixed checking for duplicate labels
Q is 32 bits therefore storage is one longword. But another is also needed for MUXQ to mask against.
some_isr
'save Q
mov qbackup, #0 'qbackup must be zeroed each time
muxq qbackup, qmask 'qmask must contain $FFFF_FFFF
...
'restore Q
setq qbackup
reti 'presumes RETI isn't modified by the SETQ
qbackup long 0
qmask long $FFFF_FFFF
I think this will work too (not at home to test). If so, it's even better...
Thinking some more, I think it will end up in qbackup as the complement
some_isr
'save Q
neg qbackup, #1 'qbackup must be $FFFF_FFFF each time
muxq qbackup, #0 '
...
'restore Q
setq qbackup
reti 'presumes RETI isn't modified by the SETQ
qbackup long 0
Rather than clog the reference thread, here is a suggestion that can be discussed further...
I am going to suggest we also keep the crystal/oscillator frequency _XTALFREQ and _XOSC setting as this will permit easy changes in clock later. I've called this _XTALSPEC for want of a better name.
I have been using this for the clock calculations.
Note the alternative P2-EVAL and P2D2 sections. This keeps the crystal or oscillator setting together.
CON
'+-------[ Select for P2-EVAL ]------------------------------------------------+
_XTALFREQ = 20_000_000 ' crystal frequency
_XDIV = 2 '\ '\ crystal divider to give 10.0MHz
_XMUL = 15 '| 150 MHz '| crystal / div * mul to give 150MHz
_XDIVP = 1 '/ '/ crystal / div * mul /divp to give 150MHz
_XOSC = %10 '15pF ' %00=OFF, %01=OSC, %10=15pF, %11=30pF
'+-------[ Select for P2D2 ]---------------------------------------------------+
_XTALFREQ = 12_000_000 ' crystal frequency
_XDIV = 4 '\ '\ crystal divider to give 3.0MHz
_XMUL = 99 '| 148.5MHz '| crystal / div * mul to give 297.0MHz
_XDIVP = 2 '/ '/ crystal / div * mul /divp to give 148.5MHz
_XOSC = %01 'OSC ' %00=OFF, %01=OSC, %10=15pF, %11=30pF
'+-----------------------------------------------------------------------------+
_XTALSPEC = _XOSC<<30 + _XTALFREQ ' xtal specifications (frequency & osc/0pF/15pF/30pF)
_XSEL = %11 'XI+PLL ' %00=rcfast(20+MHz), %01=rcslow(~20KHz), %10=XI(5ms), %11=XI+PLL(10ms)
_XPPPP = ((_XDIVP>>1) + 15) & $F ' 1->15, 2->0, 4->1, 6->2...30->14
_CLOCKFREQ = _XTALFREQ / _XDIV * _XMUL / _XDIVP ' internal clock frequency
_SETFREQ = 1<<24 + (_XDIV-1)<<18 + (_XMUL-1)<<8 + _XPPPP<<4 + _XOSC<<2 ' %0000_000e_dddddd_mmmmmmmmmm_pppp_cc_00 ' setup oscillator
_ENAFREQ = _SETFREQ + _XSEL ' %0000_000e_dddddd_mmmmmmmmmm_pppp_cc_ss ' enable oscillator
'+-----------------------------------------------------------------------------+
_1us = _clockfreq/1_000_000 ' 1us
'+-----------------------------------------------------------------------------+
DAT orgh 0
org 0
entry jmp #_init
long 0,0,0
clk_xspec long _XTALSPEC 'hubRAM addr $00010 - xtal/osc specs
clk_freq long _CLOCKFREQ 'hubRAM addr $00014 - clock frequency in Hz
clk_mode long 0 'hubRAM addr $00018 - clock mode config word (boot-loader to fill)
asyn_baud long _BAUD 'hubRAM addr $0001C - monitor comport baud (baud rate)
'+-------[ Set Xtal ]----------------------------------------------------------+
_init hubset clk_mode 'switch to RCFAST using known prior mode (~24MHz)
mov clk_mode, ##_SETFREQ 'replace old with new
hubset clk_mode 'setup new mode, still at RCFAST
waitx ##20_000_000/100 '~10ms for xtal/PLL to settle
hubset ##_ENAFREQ 'enable oscillator
'+-----------------------------------------------------------------------------+
...
Note the use of baud. It is not baudrate as baud implies rate - it is the symbol rate which is commonly bits/sec
If one is setting a sysclock rate then clk_mode is used.
If one is gauging the sysclock rate then clk_freq is used.
clk_xspec just feels like excess to me.
For an intermediate preset in a dynamic calculation I'd combine multiple parts into a private variable. Anything like clk_xspec should be just that, a private variable. It's not like the calculation is difficult to code up when we've got the cordic at hand.
Huh, in the docs for interrupts, there's no mention of GETQX/GETQY. I gather that means they can be interrupted and will be re-executed when the ISR returns. Anyone know otherwise?
If one is setting a sysclock rate then clk_mode is used.
Anything like clk_xspec should be just that, a private variable. It's not like the calculation is difficult to code up when we've got the cordic at hand.
if the code to do the calculation takes up more space than just having the result, then it's better to have this additional variable to read. If it is going to be commonly used.
Crystal frequency may be a determinant for some OBEX code where it's trying to stay within certain parameters like min or max VCO, etc. or even feasibility.
An example I can see is shared SD Card code. Where the card can be placed into different boards that have different crystal frequencies, and the initial loader/shell would set up these predefined longs related to the clock. Subsequent programs loaded from the shell would then have these numbers at hand, which cannot be predefined constant values.
It's a bit much to have each program loaded by the shell have to backtrack and calculate it themselves (which they wouldn't).
A lot of these problems would not have popped up if the hubset register area was readable.
A lot of these problems would not have popped up if the hubset register area was readable.
Perhaps that might happen in the future, using either the spare C opcode bit in HUBSET to read the configuration, or the instruction slot that appears to exist between COGID and COGSTOP with bits[8:0] = 000000010. When I asked about the latter before, I was told that it's part of COGID but I don't understand how.
If you're gonna have some sort of OS with binary exchanging of code then that is another conversation beyond loading of stand-alone programs. The OS can have many other system variables stored outside the program being loaded. Those programs will have another whole protocol that has nothing to do with stand-alones, likely with an API/ABI and the likes.
That said, there is one spare longword. So if there is nothing else to put there then it's no loss using it for crystal frequency spec.
As for wishful changes to HUBSET instruction, there is a ton of spare single operand instruction slots. So no issue on encoding space. I don't Chip ever want to split the instruction up though.
I asked once about reordering the encoding of the operand data to reduce the size of many of the immediates that are required but Chip didn't think it was worth persuing. In hindsight I wish I'd been more dogged because part of that approach was to create an extra entry in the table just for changing the clock source selection. Which would have conveniently avoided the flaw showing at all.
I've lost track of the original posting but here's the sort of thing I suggested, albeit updated:
HUBSET {#}D - Configure global circuit selected by least significant bits
%0000_0000_0000_0000_0000_000C_CSS1_0000 Set clock generator mode - can do all ops within 9-bit immediate
%0000_DDDD_DDMM_MMMM_MMMM_PPPP_E100_0000 Set up clock PLL - can be turned off with 9-bit immediate
%0000_0000_0000_0000_0000_0001_0000_0000 Hard reset, reboots chip - works with 9-bit immediate
%0000_00LW_DDDD_DDDD_DDDD_DDDD_1000_0000 Set write-protect and debug enables - L and W require AUG intentionally
%0000_0000_0000_0000_0000_0TTT_TTLL_RR10 Set filter R to length L and tap T - only upper two TT require AUG
%DDDD_DDDD_DDDD_DDDD_DDDD_DDDD_DDDD_DDD1 Seed Xoroshiro128** PRNG with D
RE: \ or @ addressing - which to use? "trap".
Should this get extended to the hub rd/wr byte/word/long p2asm instructions?
You can use rdlong reg, ##@hub_symbol immediate and pnut/p2asm/fastspin/ don't complain, but using ##\hub_symbol or ##\@hub_symbol generates a compiler error.
A preceding loc pa, #\@hub_symbol can be used, but it would be convenient to also have a one-line immediate option, even though both generate two instructions. More useful in a spin environment than pure p2asm, but does free up a pointer register and cover all addressing modes?
RE: \ or @ addressing - which to use? "trap".
Should this get extended to the hub rd/wr byte/word/long p2asm instructions?
rd/wr byte/wrod/long always use absolute addressing, there's no option for relative addressing (the hardware does not support PC-relative addresses for these instructions). That's why using ##\hub_symbol generates an error -- "\" is only valid for instructions where relative addressing is an option, and in that case it overrides the relative address to force an absolute address. If somehow the compiler were changed to accept (and ignore) the "\", then rdlong reg, ##@hub_symbol and rdlong reg, ##\@hub_symbol would generate exactly the same code.
I'm making a Spin2 instruction to set the clock frequency and I just want to verify with you that the potential clock-crash problem had only to do with changing to and from mode %PPPP = %1111. This mode is different than %0000..%1110, since rather than select a 2^n post-divider for the VCO, it selects the VCO frequency directly, and can therefore glitch if changed. However, by always retreating to RCFAST mode for all clock-mode-bit changes, and waiting an appropriate amount, we can then switch to any clock configuration without trouble, right? Thanks.
I'm making a Spin2 instruction to set the clock frequency and I just want to verify with you that the potential clock-crash problem had only to do with changing to and from mode %PPPP = %1111. This mode is different than %0000..%1110, since rather than select a 2^n post-divider for the VCO, it selects the VCO frequency directly, and can therefore glitch if changed. However, by always retreating to RCFAST mode for all clock-mode-bit changes, and waiting an appropriate amount, we can then switch to any clock configuration without trouble, right? Thanks.
Yes, that's how I remember it.
I recall in tests being able to crash P2, by selecting Xtal & not waiting for the Osc to actually start-up.
I'm making a Spin2 instruction to set the clock frequency and I just want to verify with you that the potential clock-crash problem had only to do with changing to and from mode %PPPP = %1111. This mode is different than %0000..%1110, since rather than select a 2^n post-divider for the VCO, it selects the VCO frequency directly, and can therefore glitch if changed. However, by always retreating to RCFAST mode for all clock-mode-bit changes, and waiting an appropriate amount, we can then switch to any clock configuration without trouble, right? Thanks.
Yes, that's how I remember it.
I recall in tests being able to crash P2, by selecting Xtal & not waiting for the Osc to actually start-up.
Yes, I remember that one. There was at least one more subtle issue. I think it had to do with direct VCO selection.
... to verify with you that the potential clock-crash problem had only to do with changing to and from mode %PPPP = %1111. This mode is different than %0000..%1110, ...
Err: Rereading it myself, maybe I over compensated because you are saying that DIVP == %1111 is a special case. Which means only that one has to be treated carefully.
Comments
Does this release fix it ?
2019-02-24 : There is a new release of spin2gui and of fastspin. The changes are:
...
- Fixed checking for duplicate labels
One SETQ for multiple MUXQ's could prove handy. However, there is a potential trap here if interrupts change Q, which could apply to one SETQ+MUXQ when these two instructions are not consecutive, e.g. there are three other instructions in between here.
There are lots of interesting features in this P2.
Yes, it's fixed in 1.3.9
How many longs in total for this?
Thinking some more, I think it will end up in qbackup as the complement
Evan did great detective work to track down the problem.
forums.parallax.com/discussion/comment/1466702/#Comment_1466702
Rather than clog the reference thread, here is a suggestion that can be discussed further...
I am going to suggest we also keep the crystal/oscillator frequency _XTALFREQ and _XOSC setting as this will permit easy changes in clock later. I've called this _XTALSPEC for want of a better name.
I have been using this for the clock calculations.
Note the alternative P2-EVAL and P2D2 sections. This keeps the crystal or oscillator setting together.
Note the use of baud. It is not baudrate as baud implies rate - it is the symbol rate which is commonly bits/sec
If one is gauging the sysclock rate then clk_freq is used.
clk_xspec just feels like excess to me.
For an intermediate preset in a dynamic calculation I'd combine multiple parts into a private variable. Anything like clk_xspec should be just that, a private variable. It's not like the calculation is difficult to code up when we've got the cordic at hand.
if the code to do the calculation takes up more space than just having the result, then it's better to have this additional variable to read. If it is going to be commonly used.
Crystal frequency may be a determinant for some OBEX code where it's trying to stay within certain parameters like min or max VCO, etc. or even feasibility.
An example I can see is shared SD Card code. Where the card can be placed into different boards that have different crystal frequencies, and the initial loader/shell would set up these predefined longs related to the clock. Subsequent programs loaded from the shell would then have these numbers at hand, which cannot be predefined constant values.
It's a bit much to have each program loaded by the shell have to backtrack and calculate it themselves (which they wouldn't).
A lot of these problems would not have popped up if the hubset register area was readable.
Perhaps that might happen in the future, using either the spare C opcode bit in HUBSET to read the configuration, or the instruction slot that appears to exist between COGID and COGSTOP with bits[8:0] = 000000010. When I asked about the latter before, I was told that it's part of COGID but I don't understand how.
That said, there is one spare longword. So if there is nothing else to put there then it's no loss using it for crystal frequency spec.
I asked once about reordering the encoding of the operand data to reduce the size of many of the immediates that are required but Chip didn't think it was worth persuing. In hindsight I wish I'd been more dogged because part of that approach was to create an extra entry in the table just for changing the clock source selection. Which would have conveniently avoided the flaw showing at all.
I've lost track of the original posting but here's the sort of thing I suggested, albeit updated:
Should this get extended to the hub rd/wr byte/word/long p2asm instructions?
You can use rdlong reg, ##@hub_symbol immediate and pnut/p2asm/fastspin/ don't complain, but using ##\hub_symbol or ##\@hub_symbol generates a compiler error.
A preceding loc pa, #\@hub_symbol can be used, but it would be convenient to also have a one-line immediate option, even though both generate two instructions. More useful in a spin environment than pure p2asm, but does free up a pointer register and cover all addressing modes?
Handy, but low priority.
I'm making a Spin2 instruction to set the clock frequency and I just want to verify with you that the potential clock-crash problem had only to do with changing to and from mode %PPPP = %1111. This mode is different than %0000..%1110, since rather than select a 2^n post-divider for the VCO, it selects the VCO frequency directly, and can therefore glitch if changed. However, by always retreating to RCFAST mode for all clock-mode-bit changes, and waiting an appropriate amount, we can then switch to any clock configuration without trouble, right? Thanks.
Yes, that's how I remember it.
I recall in tests being able to crash P2, by selecting Xtal & not waiting for the Osc to actually start-up.
Yes, I remember that one. There was at least one more subtle issue. I think it had to do with direct VCO selection.
Err: Rereading it myself, maybe I over compensated because you are saying that DIVP == %1111 is a special case. Which means only that one has to be treated carefully.