Shop OBEX P1 Docs P2 Docs Learn Events
Newbie Question: Using HUBSET in C — Parallax Forums

Newbie Question: Using HUBSET in C

Hello,

I'm new to the Propeller P2. I'm used to using PIC32MZ's.... I do have a question about configuring the clock speed.

How would I implement this in C:

HUBSET ##%0_000000_0000000000_1111_00_00 // set 20 MHz+ (RCFAST) mode
HUBSET ##%1_100111_0100101000_1111_10_00 // enable crystal+PLL, stay in RCFAST mode
WAITX ##20_000_000/100 // wait ~10ms for crystal+PLL to stabilize
HUBSET ##%1_000000_0000010000_1111_01_10 // set the clock to 320 MHz

Also.... where would I insert the code for this in the beginning of the main.c file, in the beginning of the main.c function or where?

Would I have to create an assembly file first and if so how would I implement that?

Thank you!

Comments

  • RaymanRayman Posts: 14,632

    If this is for FlexProp C and this is just the initial setting of the clock, I do it like this:

    enum { _clkfreq = 300_000_000};

  • evanhevanh Posts: 15,910
    edited 2023-12-24 22:18

    Lol, good point. I presumed he wanted to dynamically change at runtime but you're right, probably just wants to set it.

    Here's an example using the above object anyway:

    #include <stdio.h>
    
    
    enum {
        // _xinfreq = 20_000_000,  // Use for EC Edge Card
        _xtlfreq = 20_000_000,    // Use for Eval Board
        _clkfreq = 4_000_000,
    };
    
    
    struct __using("pllset.spin2")  lib;
    
    
    void  main(void)
    {
        int freq;
    
        printf( "   clkfreq = %d   clkmode = 0x%x\n", _clockfreq(), _clockmode() );
    
        for( freq = 80; freq <= 85; freq++ ) {
            _waitms( 1 );    // allow comms to empty before adjusting clock
            lib.pllset( freq * 1000_000 );
            printf( "clkfreq = %d   clkmode = 0x%x\n", _clockfreq(), _clockmode() );
        }
    
        puts( "Done." );
    }
    
  • RossHRossH Posts: 5,462
    edited 2023-12-24 22:49

    I can only answer for Catalina, but I'm sure the other C compilers would be similar.

    First, you would not usually either want or need to do this in C. One reason is that unless you also tell the various C libraries and supporting drivers (Catalina calls these 'plugins') that you are changing the clock speed (which your code does not do) some things may stop working - such as your file system or serial ports. So you would usually at least want to use the C library functions to do this - e.g. in Catalina this might be done using _clockinit(mode, frequency).

    However, in Catalina, you generally configure the clock mode and speed in the platform support file, which is used by the C startup code before the C program is even launched. Or you specify the clock speed on the compilation command line. Either way, this allows Catalina to pass the information on to everything that needs to know the clock speed.

    However, you CAN do exactly what you have specified, using inline PASM. For example, here is what your code would look like in a complete Catalina C program - I have just modified your formatting to make it acceptable to the C compiler:

    void main() {
       PASM(
          " HUBSET ##%0_000000_0000000000_1111_00_00 ' set 20 MHz+ (RCFAST) mode\n"
          " HUBSET ##%1_100111_0100101000_1111_10_00 ' enable crystal+PLL, stay in RCFAST mode\n"
          " WAITX ##20_000_000/100 ' wait ~10ms for crystal+PLL to stabilize\n"
          " HUBSET ##%1_000000_0000010000_1111_01_10 'set the clock to 320 MHz\n"
       );
    }
    

    Here is the code actually generated by compiling this:

    015c8              C_main ' <symbol:main>
    015c8     ff800000  HUBSET ##%0_000000_0000000000_1111_00_00 ' set 20 MHz+ (RCFAST) mode
    015cc     fd65e000 
    015d0     ff80ce94  HUBSET ##%1_100111_0100101000_1111_10_00 ' enable crystal+PLL, stay in RCFAST mode
    015d4     fd65f000 
    015d8     ff800186  WAITX ##20_000_000/100 ' wait ~10ms for crystal+PLL to stabilize
    015dc     fd66801f 
    015e0     ff808008  HUBSET ##%1_000000_0000010000_1111_01_10 'set the clock to 320 MHz
    015e4     fd65ec00                   
    015e8     fd8015a4  jmp #\@C__exit
    
  • MisterHemiMisterHemi Posts: 9
    edited 2023-12-24 23:14

    Thanks to all of you!

    I'm using simpleIDE and the P2 Edge Module

    Let me see if any of those are applicable to simpleIDE.

    I want to set the speed upon booting/starting the P2

  • RaymanRayman Posts: 14,632

    I'm not sure SimpleIDE works with P2... Does it?

    If not, I'd try FlexProp or Catalina.

  • @Rayman said:
    I'm not sure SimpleIDE works with P2... Does it?

    If not, I'd try FlexProp or Catalina.

    Supposedly it does, IIRC according to the note/comment in the downloads section, but I'll see.

    Otherwise I'll have to get FlexProp or Catalina.

  • MisterHemiMisterHemi Posts: 9
    edited 2023-12-25 00:07

    Ok... FYI... I did find this and it builds without errors but I have yet to test it.

    define clkset (0xF6, 320000000 ) // set the clock to 320 MHz (external 20MHz clock/oscillator)

  • SimpleIDE does not support the P2. The instruction set and boot process are totally different and will not work with SimpleIDE.

    Mike

  • @iseries said:
    SimpleIDE does not support the P2. The instruction set and boot process are totally different and will not work with SimpleIDE.

    Mike

    Thanks Mike... I installed flex prop. That solved some problems. I was able to set the clock speed but now I have to solve some other problems which may be something minor.

    If it helps someone here is how I set the clock speed:

    void initSys(){
    __asm {
    HUBSET ##0_000000_0000000000_1111_00_00 // set 20 MHz+ (RCFAST) mode\n"
    HUBSET ##1_100111_0100101000_1111_10_00 // enable crystal+PLL, stay in RCFAST mode\n"
    WAITX ##20_000_000/100 // wait ~10ms for crystal+PLL to stabilize\n"
    HUBSET ##1_000000_0000010000_1111_01_10 // set the clock to 320 MHz\n"
    }

    }

  • evanhevanh Posts: 15,910

    @MisterHemi said:
    If it helps someone here is how I set the clock speed:

    That's not an ideal solution. In fact it has a bug as well, but that's beside the point. There is two well proven methods already provided.

    If you just want to set initial clock frequency then use the enum {} method built into the compiler.
    If you want to dynamically change the clock frequency multiple times then use the "pllset" object I linked.

  • Here is a sample flex prop program:

    #include <stdio.h>
    #include <propeller.h>
    
    #define LED1 56
    #define LED2 57
    
    
    int main()
    {
        int i;
    
        _pinh(LED1);
        _pinh(LED2);
    
        i = 0;
        while (1)
        {
            _waitms(1000);
            i++;
            if (i & 0x01)
                _pinh(LED1);
            else
                _pinl(LED1);
            if (i & 0x02)
                _pinh(LED2);
            else
                _pinl(LED2);
        }
    }
    

    Note no clock is set at all. Flex prop uses a default value if none is set (160Mhz).
    You can see this because flex prop creates an assembly version along with the binary file name ending in P2ASM.

    con
        _clkfreq = 192000000
        _clkmode = 17838075
    dat
        nop
        cogid   pa
        coginit pa,##$404
        orgh    $10
        long    0   'reserved
        long    0 ' clock frequency: will default to 192000000
        long    0 ' clock mode: will default to $1102ffb
        orgh    $400
     _ret_  mov result1, #0
        org 0
    entry
        cmp ptra, #0 wz
     if_ne  jmp #spininit
        mov ptra, ptr_stackspace_
        rdlong  pa, #20 wz
     if_ne  jmp #skip_clock_set_
        hubset  #0
        hubset  ##17838072
        waitx   ##200000
        mov pa, ##17838075
        hubset  pa
        wrlong  pa, #24
        wrlong  ##192000000, #20
        jmp #skip_clock_set_
        orgf    128
    skip_clock_set_
        call    #_main
    cogexit
        waitx   ##160000
        cogid   arg01
        cogstop arg01
    spininit
        rdlong  objptr, ptra++
        rdlong  result1, ptra++
        setq    #3
        rdlong  arg01, ptra
        sub ptra, #4
        call    result1
        jmp #cogexit
    FCACHE_LOAD_
        mov fcache_tmpb_,ptrb
        pop ptrb
        altd    pa,ret_instr_
        mov  0-0, ret_instr_
        setq    pa
        rdlong  $0, ptrb++
        push    ptrb
        mov ptrb,fcache_tmpb_
        jmp #\$0 ' jmp to cache
    ret_instr_
        _ret_ cmp inb,#0
    fcache_tmpb_
        long 0
    fcache_load_ptr_
        long FCACHE_LOAD_
    builtin_bytefill_
            shr arg03, #1 wc
     if_c   wrbyte  arg02, arg01
     if_c   add arg01, #1
            movbyts arg02, #0
    builtin_wordfill_
            shr arg03, #1 wc
     if_c   wrword  arg02, arg01
     if_c   add arg01, #2
            setword arg02, arg02, #1
    builtin_longfill_
            wrfast  #0,arg01
            cmp arg03, #0 wz
     if_nz  rep #1, arg03
     if_nz  wflong  arg02
            ret
    COUNT_
        long 0
    RETADDR_
        long 0
    fp
        long 0
    pushregs_
        pop  pa
        pop  RETADDR_
        tjz  COUNT_, #pushregs_done_
        altd  COUNT_, #511
        setq #0-0
        wrlong local01, ptra++
    pushregs_done_
        setq #2 ' push 3 registers starting at COUNT_
        wrlong COUNT_, ptra++
        mov    fp, ptra
        jmp  pa
     popregs_
        pop    pa
        setq   #2
        rdlong COUNT_, --ptra
        djf    COUNT_, #popregs__ret
        setq   COUNT_
        rdlong local01, --ptra
    popregs__ret
        push   RETADDR_
        jmp    pa
    
    objptr
        long    @objmem
    ptr_stackspace_
        long    @stackspace
    result1
        long    0
    COG_BSS_START
        fit 480
        orgh
    hubentry
    
    _main
        mov COUNT_, #1
        call    #pushregs_
        drvh    #56
        drvh    #57
        mov local01, #0
    LR__0001
        mov arg01, ##1000
        call    #__system___waitms
        add local01, #1
        test    local01, #1 wz
        drvnz   #56
        test    local01, #2 wz
     if_ne  drvh    #57
     if_ne  jmp #LR__0001
        drvl    #57
        jmp #LR__0001
        mov ptra, fp
        call    #popregs_
    _main_ret
        ret
    hubexit
        jmp #cogexit
    
    __system___waitms
        mov _var01, arg01
        getct   _var02
        rdlong  _var03, #20
        callpa  #(@LR__0011-@LR__0010)>>2,fcache_load_ptr_
    LR__0010
        cmps    _var01, ##1000 wc
     if_b   jmp #LR__0012
        add _var02, _var03
        mov arg01, _var02
        addct1  arg01, #0
        waitct1
        sub _var01, ##1000
        jmp #LR__0010
    LR__0011
    LR__0012
        cmps    _var01, #1 wc
     if_b   jmp #LR__0013
        qmul    _var01, _var03
        mov arg03, ##1000
        getqy   result1
        getqx   arg01
        setq    result1
        qdiv    arg01, arg03
        getqx   arg01
        addct1  arg01, _var02
        waitct1
    LR__0013
    __system___waitms_ret
        ret
    objmem
        long    0[0]
    stackspace
        long    0[1]
        org COG_BSS_START
    _var01
        res 1
    _var02
        res 1
    _var03
        res 1
    arg01
        res 1
    arg02
        res 1
    arg03
        res 1
    arg04
        res 1
    local01
        res 1
        fit 480
    

    I like to run my P2 as 200Mhz but you will see at the top of the program it has done the hubset for you with the correct values.
    I have one of the different P2 units that has an oscillator running at 19.2Mhz instead of the 20Mhz.

    Mike

  • Thank you everyone!

Sign In or Register to comment.