Newbie Question: Using HUBSET in C
in Propeller 2
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
Use this - https://obex.parallax.com/obex/pllset/
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};
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." ); }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:
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
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.
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
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"
}
}
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 480I 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!