Shop OBEX P1 Docs P2 Docs Learn Events
P2 Tricks, Traps & Differences between P1 (general discussion) - Page 6 — Parallax Forums

P2 Tricks, Traps & Differences between P1 (general discussion)

1468910

Comments

  • jmgjmg Posts: 15,140
    Mark_T wrote: »
    ..
    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
  • evanh wrote: »
    evanh wrote: »
    Cluso99 wrote: »
    SETQ

    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.
  • evanhevanh Posts: 15,126
    Amusingly, Q can be saved and restored using MUXQ and SETQ respectively.
  • Cluso99Cluso99 Posts: 18,066
    evanh wrote: »
    Amusingly, Q can be saved and restored using MUXQ and SETQ respectively.
    Thats an interesting fact :smile:
    There are lots of interesting features in this P2.
  • jmg wrote: »
    Mark_T wrote: »
    ..
    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

    Yes, it's fixed in 1.3.9
  • TonyB_TonyB_ Posts: 2,108
    edited 2019-02-24 12:47
    evanh wrote: »
    Amusingly, Q can be saved and restored using MUXQ and SETQ respectively.

    How many longs in total for this?
  • evanhevanh Posts: 15,126
    edited 2019-02-24 13:31
    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
    
  • Cluso99Cluso99 Posts: 18,066
    edited 2019-02-25 03:21
    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
    

  • Cluso99Cluso99 Posts: 18,066
    Over on the reference thread, evan suggested a clock setup method to avoid the reset lockup issue when changing clock frequency.
    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.
    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
  • evanhevanh Posts: 15,126
    _XTALSPEC ain't got a job as far as I can see.
  • Cluso99Cluso99 Posts: 18,066
    evanh wrote: »
    _XTALSPEC ain't got a job as far as I can see.
    While it's not impossible to backwards calculate, it saves a complex calculation. Much easier to just place it there when it's all available.
  • evanhevanh Posts: 15,126
    edited 2019-03-10 08:52
    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.
  • evanhevanh Posts: 15,126
    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?
  • evanh wrote: »
    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.
  • whicker wrote: »
    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.
    EEEE 1101011 00L DDDDDDDDD 000000000        HUBSET  D/#
    EEEE 1101011 C0L DDDDDDDDD 000000001        COGID   D/#         {WC}
    EEEE 1101011 00L DDDDDDDDD 000000011        COGSTOP D/#
    
  • evanhevanh Posts: 15,126
    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.
  • evanhevanh Posts: 15,126
    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
    
  • evanhevanh Posts: 15,126
    edited 2019-03-13 06:07
    Here's a snippet for deriving crystal frequency from existing parameters:
    		getnib	clk_mul, clk_mode, #4		'extract MUL
    		and	clk_mul, #%0011
    		rolbyte	clk_mul, clk_mode, #1
    		add	clk_mul, #1
    
    		getbyte	clk_div, clk_mode, #2		'extract DIV
    		shr	clk_div, #2
    		add	clk_div, #1
    		getnib	pa, clk_mode, #1		'extract DIVP
    		incmod	pa, #15			wc	'convert to integer
    		rcl	pa, #1				'  "     "     "
    		mul	clk_div, pa			'combine with DIV
    
    		qdiv	clk_freq, clk_mul
    		getqx	xtal_freq
    		qmul	xtal_freq, clk_div
    		getqx	xtal_freq
    
  • Cluso99Cluso99 Posts: 18,066
    Quite a mess when it could have just been saved in a long
  • evanhevanh Posts: 15,126
    It won't be in user code. It's an OS level function.
  • evanhevanh Posts: 15,126
    Oops, that was entirely untested. I'd overlooked the -1 on both XMUL and XDIV. Corrected now.
  • 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?

    Handy, but low priority.
  • garryj wrote: »
    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.
  • Ah. Thank you for the thorough explanation. I was assuming that since the S/# field is address only, it would also do relative.
  • cgraceycgracey Posts: 14,133
    Evanh (or whoever else recalls),

    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.
  • jmgjmg Posts: 15,140
    cgracey wrote: »
    Evanh (or whoever else recalls),

    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.
  • cgraceycgracey Posts: 14,133
    jmg wrote: »
    cgracey wrote: »
    Evanh (or whoever else recalls),

    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.
  • evanhevanh Posts: 15,126
    edited 2019-06-01 05:16
    cgracey wrote: »
    ... 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, ...
    Yes, that did seem reliable but you advised against actually relying on it to always work, hence the method now chosen is generic for all PLL configs. Refresher - https://forums.parallax.com/discussion/comment/1466490/#Comment_1466490 - bottom most post.

    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.
  • evanhevanh Posts: 15,126
    That is my favourite DIVP setting though. So I kind of assumed it's always going to be in the equations.
  • evanhevanh Posts: 15,126
    As for the generic method adopted: Yes, it has been very reliable. It made a number of odd and erratic effects go away.
Sign In or Register to comment.