1. Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.
    Dismiss Notice

PIC24FJ128GA406 does not want to change clocks!

Discussion in 'Microcontrollers' started by Rich D., Nov 21, 2017.

  1. Rich D.

    Rich D. Member

    Feb 3, 2014
    West Chester, PA
    It seems I have a stubborn PIC. Try as I might, it seems to always want to run at an instruction cycle of 4 MHz, although I was hoping for 16 MHz.

    Details: I am using the internal FRC oscillator, fixed at about 8 MHz (7.37 actually). I would like it to clock the processor at 30 MHz for maximum performance since there are no batteries involved. According to the specs, I should be able to run it with a 4X PLL, giving me a frequency of 29.48MHz. From that clock, the instruction time (which is /2) works out to 67.843 nSec. As a side note, the specs define a min instruction cycle time of 62.5 nSec, so that is about as fast as it can perform. All cool, I've read over the Specs and Family Reference Manual about four times now, so I thought I had this in the bag.

    Programming this chip using a PicKit 3, I get it to run ok, but an output pin set to low then high in the next instruction gives me a pulse on an oscilloscope of 245 nSec, or about 1/4 the desired speed. I get it, that means I made a mistake somewhere in my config bits or registers used to set the clocks up. But here's the really confusing part: No matter what I change in the program, it never changes on the processor's hardware! Not faster, not slower, but rock-solid at 245 nSec.

    This is what I am doing, these values are pre-set with constants:

    The FOSCSEL configuration register is the first thing defined in the software,
    with the IESO bit high to enable clock switching.
    Also the PLLMODE bits set to 1100 for a 4X PLL. Also the FNOSC bits are set to 001 to define the FRC with postscaler and PLL as the initial oscillator.
    All together that is a byte of 1 1100 001 or 0xE1.

    The other configuration register is FOSC.
    Here I have the FCKSM bits set to 00 to enable clock switching and fail safe monitor.
    IOL1WAY is set to 0 so that the IOLOCK bit can be set and cleared multiple times.
    PLLSS is 0 so that the PLL is driven by the FRC.
    SOSCSEL is also set 0 but my understanding is it doesn't matter here.
    OSCIOFCN is also set 0 but I believe that also isn't relevant here.
    POSCMOD is set to 11 so that the primary oscillator (external, crystal, etc.) is disabled.
    That gives me a byte of 00 0 0 x x 11 or a value of 0x3.

    As far as I know, these two configuration bytes are all that determines the clock used at startup, FOSCSEL = 0xE1 and FOSC = 0x3.

    But there's more, there's always more.

    After the processor starts running, I do the usual of setting the stack pointer W15, write to all the registers with a word to eliminate that reg not initialized oddity, then I start to set the various oscillator registers as needed.

    First, the CLKDIV register is loaded with 0x0020 which defines the following:
    The ROI bit is set to 0, which I believe is not relevant.
    The DOZE bits are set to 000 for a /1, and the DOZEN bit set to 0 to turn off the DOZE divider.
    The RCDIV bits are set to 000 so the RC postscaler is /1
    The CPDIV bits are set to 00 for a /1
    The PLLEN bit is set to 1 so it is always active.

    Next I set the OSCTUN register bits to all zero for no tuning change. (BTW, changing this value does produce a slight frequency change in my Fcy measurements.)

    Now as I understand it I shouldn't have to change the clock at this time, but if I were to do it anyways it should either ignore the change or make a difference within a microsecond or two. Here I used the following code for what I think is the right unlock sequence as described in the specs.

    In this code that follows, NEW_CLOCK_MODE is defined as 0x01, so that the high byte of the OSCCON register gets the bits 001 to use the FRC oscillator with prescaler and PLL.

    disi #16
    mov #NEW_CLOCK_MODE, w0 ;value to move
    mov #OSCCONH, w3 ;where to move it
    mov #0x78, w1 ;unlock bits
    mov #0x9A, w2 ;more unlock bits
    mov.b w1, [w3] ;un...
    mov.b w2, [w3] ;...lock
    mov.b w0, [w3] ;new mode set here
    ;WRITE the OSWEN bit to start switching
    mov #OSCCONL, w3 ;where to move it
    mov #0x46, w1 ;unlock bits
    mov #0x57, w2 ;more unlock bits
    mov.b w1, [w3] ;un...
    mov.b w2, [w3] ;...lock
    bset OSCCON, #0 ;clear starts clock switching
    ;unlock sequence completed, clock switch started. OSCCON bit 0 will be low when completed
    btst OSCCON, #0 ;if not switched, it will hang here
    bra NZ, not_switched ;forever and appear busted.

    There is a booby-trap there so that if the clock switching doesn't happen, it should hang and nothing should execute after that. But it does continue,
    so I assume the switching either worked or it was ignored because the config setting already had the clock set where I wanted it.

    The next thing I do is set up an output pin to flash an LED on the G port's bit #8.
    mov TRISG, w0
    bclr w0, #8
    mov w0, TRISG
    ;drive HIGH for ON
    mov LATG, w0
    bset w0, #8
    mov w0, LATG

    This seems to work ok because the output goes high and the LED illuminates.
    And the last thing I do is to set up the processor to bang a single-cycle low-high to determine the instruction cycle timing.

    mov LATG, w0
    mov LATG, w1
    bclr w0, #8 ;w0 data will drive low/off
    bset w1, #8 ;w1 data will drive high/on
    mov w0, LATG ;driven low
    mov w1, LATG ;driven high again 67.842nS spent
    mov w0, LATG ;driven low *67.842nS spent
    mov w1, LATG ;driven high again *67.842nS spent

    ...just for fun I do it twice, so I can measure two more exact low to high pulses that are not skewed by the different rise-fall and fall-rise times.
    The scope shows this to take 496 or 498 nSec, so divided by two gives me the instruction cycle time.

    I believe this code executes without crashing because after this I have a software delay and toggle the LED state once each 1/2 second in an endless loop, and the led continues to flash for hours.

    What I CAN'T UNDERSTAND, is why I can change all the bits in the various config registers and CLKDIV register, and I always get the same LED timing pulses, and see the LED flash at a consistent 1Hz rate, even after power cycles, reprogramming, and various reboots-of-desperation. What could I possibly be missing?!?

    Any help would keep me from pulling out my remaining hairs.
  2. Nigel Goodwin

    Nigel Goodwin Super Moderator Most Helpful Member

    Nov 17, 2003
    Derbyshire, UK
    I use the 24FJ64GA002 and use the following line:
    Code (text):

    CLKDIV = 0x0000; // set to 16MHz
    This sets the PLL to x4 so it runs at 32MHz, giving a 16MHz instruction clock.

    Here are my config settings:

    Code (text):

    // CONFIG2
    #pragma config POSCMOD = NONE       // Primary Oscillator Select->Primary oscillator disabled
    #pragma config I2C1SEL = PRI        // I2C1 Pin Location Select->Use default SCL1/SDA1 pins
    #pragma config IOL1WAY = OFF        // IOLOCK Protection->Once IOLOCK is set, cannot be changed
    #pragma config OSCIOFNC = ON        // Primary Oscillator Output Function->OSC2/CLKO/RC15 functions as port I/O (RC15)
    #pragma config FCKSM = CSDCMD       // Clock Switching and Monitor->Clock switching and Fail-Safe Clock Monitor are disabled
    #pragma config FNOSC = FRCPLL       // Oscillator Select->Fast RC Oscillator with PLL module (FRCPLL)
    #pragma config SOSCSEL = SOSC       // Sec Oscillator Select->Default Secondary Oscillator (SOSC)
    #pragma config WUTSEL = LEG         // Wake-up timer Select->Legacy Wake-up Timer
    #pragma config IESO = ON            // Internal External Switch Over Mode->IESO mode (Two-Speed Start-up) enabled

    // CONFIG1
    #pragma config WDTPS = PS32768      // Watchdog Timer Postscaler->1:32768
    #pragma config FWPSA = PR128        // WDT Prescaler->Prescaler ratio of 1:128
    #pragma config WINDIS = ON          // Watchdog Timer Window->Standard Watchdog Timer enabled,(Windowed-mode is disabled)
    #pragma config FWDTEN = OFF         // Watchdog Timer Enable->Watchdog Timer is disabled
    #pragma config ICS = PGx1           // Comm Channel Select->Emulator EMUC1/EMUD1 pins are shared with PGC1/PGD1
    #pragma config COE = OFF            // Set Clip On Emulation Mode->Reset Into Operational Mode
    #pragma config BKBUG = OFF          // Background Debug->Device resets into Operational mode
    #pragma config GWRP = OFF           // General Code Segment Write Protect->Writes to program memory are allowed
    #pragma config GCP = OFF            // General Code Segment Code Protect->Code protection is disabled
    #pragma config JTAGEN = OFF         // JTAG Port Enable->JTAG port is disabled
    • Thanks Thanks x 1
  3. Rich D.

    Rich D. Member

    Feb 3, 2014
    West Chester, PA
    Hmmm. It seems my important bits are set mostly the same, but not exactly, but I do have a different processor.

    This comment is wrong, but the instruction to start the clock switching is correct. The comment should read "SET starts clock switching".

    Working further, I now have a clue. It indeed is running at 1/4 speed, because I had to program the UART's baud rate to 4X to get it to communicate to a touchscreen.
    I got the touchscreen working so I can now display debug information. My first clue was even before that.

    On startup I do the simplest command which is to request a beep from the touchscreen. It worked.
    To my surprise it also worked again and again at 135 second intervals...that means that the processor is crashing somehow and restarting.
    The regular intervals suggest it could be a watchdog (which I thought was off!), or maybe a delay counter rolling-over and destroying the execution.
    It could also be the stack running away... too much pushing and not enough popping...stuff like that.

    With the screen working I can display the Power On Reset (POR) information and traps I might have.
    I will create all the POR and trap error messages now, so I may soon have an answer, although not a solution.
  4. dave

    Dave New Member

    Jan 12, 1997

  5. Rich D.

    Rich D. Member

    Feb 3, 2014
    West Chester, PA

    ...yea, it's the frikin' Watchdog Timer Reset. I thought I disabled that!
  6. dknguyen

    dknguyen Well-Known Member

    May 6, 2006
    That's why you always double-tap.
  7. Rich D.

    Rich D. Member

    Feb 3, 2014
    West Chester, PA
    I have a strong hunch that for some unknown reason, my PIC processor isn't being programmed with the chosen config bits to set the oscillator. Any changes I make to clock divider registers does not alter the instruction cycle times.
    I believe that because after getting it running, I read the COSC bits in the OSCCON register (bits 6,5,4) and it shows the current oscillator bits to be 111, which is the default on power-up.
    My hunch is further supported because although I turned off the watchdog timer with config bits, it appears to be on and reset at 130 second intervals - as the power-up default should be. I got around that by the usual CLRWDT instruction.
    In direct conflict with these facts, I couldn't get my processor to run at all because the JTAG was on. That was solved with a config setting of the FICD config word, so that config word appears to program ok.

    I have these lines in the assembly code, where it compiles without any issue.

    #pragma config FNOSC = FRCPLL // Oscillator Select (Fast RC Oscillator with PLL module (FRCPLL))
    #pragma config PLLMODE = PLL4X // Frequency Multiplier Select Bits (4x PLL selected)
    #pragma config IESO = OFF // Internal External Switchover (Start up with user-selected oscillator source)

    So I have to ask why am I not using the PLL set to 4X? Why is the watchdog still enabled? It seems I can't change the clock frequency to save my life.

Share This Page