Shop OBEX P1 Docs P2 Docs Learn Events
Clockfreq, clockmode and others: Agreement for what and where — Parallax Forums

Clockfreq, clockmode and others: Agreement for what and where

What is the agreement for the placement of clockfreq and clockmode in HUB RAM?

IIRC it was $14 and $18? Which is which, what is the format, and what are the labels?

Perhaps this should be in the tricks and traps thread too???

Comments

  • Cluso99 wrote: »
    What is the agreement for the placement of clockfreq and clockmode in HUB RAM?

    IIRC it was $14 and $18? Which is which, what is the format, and what are the labels?

    Perhaps this should be in the tricks and traps thread too???

    2nd!
  • evanhevanh Posts: 15,126
    PS: Peter has already been using hub address $10 for storing the crystal frequency - https://forums.parallax.com/discussion/comment/1474667/#Comment_1474667

  • As Evan linked above, it's already in tricks and traps, but just to fill it out for anyone who comes to this thread looking, the standard used by loadp2, p2gcc, fastspin, and micropython, which is based on the TAQOZ convention, is:
    $10: reserved
    $14: clock  frequency (integer, in Hz)
    $18: clock mode (integer, bottom 2 bits set to 0)
    $1c: serial baud rate (integer, e.g. 115200)
    
    The long at $1c (baud rate) is optional, it's just $14 and $18 that are absolutely required for setting the clock.
  • RossHRossH Posts: 5,336
    I can't really see the need for this, but does anyone know what locations Spin uses?
  • RossH wrote: »
    I can't really see the need for this, but does anyone know what locations Spin uses?

    The need is because there's a hardware bug which can cause a lock-up if you change the clock mode. There is a work-around but it requires knowing the current clock mode. The tricks and traps thread has more details.

    (Knowing the current clock frequency is also pretty useful for programs, and having it in a common location makes it possible for PASM code to get it easily.)

  • evanhevanh Posts: 15,126
    That stopped being the need. Doing an RCFAST handover can be the workaround without using any reserved locations.
  • Cluso99Cluso99 Posts: 18,066
    In P1, pasm programs (objects not at the top level) get _clockfreq from hub $0. P1 spin programs use _clockfreq which again is read from hub $0 (it's just hidden from the user). How often do you do waitcnt(cnt + _clockfreq*n) ?
  • Cluso99Cluso99 Posts: 18,066
    edited 2019-08-08 14:05
    What are we going to call these locations?

    I've posted my code which I believe has been used by others to setup the xtal initially. Here I have already used _clockfreq and _baud, so I'd prefer something else, although it's not too late to change.

    Is _CLOCKMODE set to the value of _SETFREQ below?
    CON
    '                 hub address
    ' _RESERVED     = $0_0010       ' reserved                
      _CLKFRQ       = $0_0014       ' clock  frequency (integer, in Hz)                
      _CLKMODE      = $0_0018       ' clock mode (integer, bottom 2 bits set to 0)
      _SERBAUD      = 115_200       ' serial baud (integer, e.g. 115200)
    
    Postedit: changed above to be _clkfreq, _clkmode, _serbaud

    Here is how I set the clock, etc
    '+-------[ 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
    '+-----------------------------------------------------------------------------+
      _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
    '------------------------------------------------------------------------------------------------
    '  _baud         = 115_200
      _baud         = 230_400
      _bitper       = (_clockfreq / _baud) << 16 + 7          ' 115200 baud, 8 bits
      _txmode       = %0000_0000_000_0000000000000_01_11110_0 'async tx mode, output enabled for smart output
      _rxmode       = %0000_0000_000_0000000000000_00_11111_0 'async rx mode, input  enabled for smart input
    '------------------------------------------------------------------------------------------------
      rx_pin        = 63            ' pin serial receiver
      tx_pin        = 62            ' pin serial transmitter
      spi_cs        = 61            ' pin SPI memory select          (also sd_ck)
      spi_ck        = 60            ' pin SPI memory clock           (also sd_cs)
      spi_di        = 59            ' pin SPI memory data in         (also sd_di)
      spi_do        = 58            ' pin SPI memory data out        (also sd_do)
    '------------------------------------------------------------------------------------------------
    
    DAT
                    orgh    0
                    org     0
    '+-------[ Set Xtal ]----------------------------------------------------------+ 
    entry           hubset  #0                              ' set 20MHz+ mode
                    hubset  ##_SETFREQ                      ' setup oscillator
                    waitx   ##20_000_000/100                ' ~10ms
                    hubset  ##_ENAFREQ                      ' enable oscillator
    
    '+-----------------------------------------------------------------------------+
                    waitx   ##_clockfreq*5                  ' just a delay to get pc terminal running
    
    ''-------[ Start Serial ]------------------------------------------------------ 
                    mov     lmm_bufad,        ##_HUBBUF     ' locn of hub buffer for serial routine 
                    mov     lmm_x,            ##_bitper     ' sets serial baud
                    call    #_SerialInit                    ' initialise serial
    

    BTW It is baud, not baud rate. The definition of baud inherently means rate.
  • Cluso99Cluso99 Posts: 18,066
    edited 2019-08-08 13:54
    How does this look? (untested)
    '===============================================================================================================
    ' Initialisation code (gets copied to cog and run)...
    '===============================================================================================================
                    orgh    0
                    org     0
    ''+-------[ Set Xtal ]---------------------------------------------------------+ 
    init_entry      hubset  #0                              ' set 20MHz+ mode
                    hubset  ##_SETFREQ                      ' setup oscillator
                    waitx   ##20_000_000/100                ' ~10ms
                    hubset  ##_ENAFREQ                      ' enable oscillator
                    setq    #3-1                            '\ copy clkfreq/clockmode/serialbaud
                    wrlong  __clkfreq, #$14                 '/    to hub $14/$18/$1C
    ''+----------------------------------------------------------------------------+
                    .....
                    .....
    
    __clkfreq       long    _CLOCKFREQ
    __clkmode       long    _SETFREQ
    __serbaud       long    _BAUD
    
  • evanhevanh Posts: 15,126
    The first HUBSET #0 doesn't work for either of the workaround methods. At best it does nothing useful because the PLL wasn't selected anyway. But if the PLL was already selected then it can break on the first instruction by tripping up on the flaw.

    Using the RCFAST handover workaround will be fine without the first HUBSET instruction.

    Using the reserved mailboxes workaround needs to actually use the prior clkmode value at the very least.

  • Cluso99Cluso99 Posts: 18,066
    Can you suggest the best way to initialise then?

    The above code is loaded by fastspin/spingui or pnut. The loader overwrites any value that may have been saved in hub $14-$18 so my code above cannot possibly know what the previous xtal mode was.

    BTW I have never found a problem with this method. Perhaps that is because the same clock modes are being set as previously set???
  • evanhevanh Posts: 15,126
    The powerup/reset state is RCFAST. So, if that is not changed by anything else then you are fine just straight setting whatever sysclock you like.

    The RCFAST handover workaround would involve the convention of the loader always changing back to RCFAST before COGINITing the loaded program. eg:
                    ...
                    andn    clkmode, #3             'disable XI+PLL mode
                    hubset  clkmode                 'switch to RCFAST mode
                    hubset  #0                      'turn off all crystal/PLL modes
                    waitx   ##20_000_000/100        'wait 10 ms for crystal shutdown
    
    		coginit	#0,address		'launch cog 0 from address
    


    The reserved mailbox workaround method can be found in the tricks and traps - https://forums.parallax.com/discussion/comment/1466702/#Comment_1466702

  • Cluso99 wrote: »
    Can you suggest the best way to initialise then?

    The above code is loaded by fastspin/spingui or pnut. The loader overwrites any value that may have been saved in hub $14-$18 so my code above cannot possibly know what the previous xtal mode was.

    BTW I have never found a problem with this method. Perhaps that is because the same clock modes are being set as previously set???

    The way I've been doing it is to have my binary laid out so that $14-$18 contains 0 for the clock mode and 22000000 for frequency (or some other approximation to what RCFAST is). The clock frequency changing mode looks like:
    pri clkset(mode, freq, xsel = 3) | oldmode
      oldmode := CLKMODE & !3  ' remove low bits, if any; this is paranoia, normally they should be clear
      mode := mode & !3 ' more paranoia
      CLKFREQ := freq ' save new frequency
      CLKMODE := mode ' save new mode
      asm
        hubset oldmode	' go to RCFAST using known prior mode
        hubset mode		' setup for new mode, still RCFAST
        waitx ##20_000_000/100 ' wait ~10ms
        add  mode, xsel
        hubset mode         ' activate new mode
      endasm
    

    This is only ever an issue if you're changing from something other than RCFAST. If you use the ROM loader then it ends up in RCFAST so there's no problem. But loadp2's fast two-stage loader may leave the chip in a different frequency, and of course if you change mid-program then you have to use this sequence as well.

  • evanhevanh Posts: 15,126
    The source select masking paranoia is a very good move.
  • RossHRossH Posts: 5,336
    evanh wrote: »

    Ah, thanks. I see Chip had the same concerns with using $14 and $18 as I do. A shame. However, if Spin uses them, so will Catalina.
  • Cluso99Cluso99 Posts: 18,066
    If a program needs to use this space, it just needs a warning, and ensure that all objects it uses are ok without these. Otherwise it makes sense to have a standard location.

    At least its all soft.
Sign In or Register to comment.