CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

How to use FCMEN correctly & startup clock switching to

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
apakSeO



Joined: 07 Dec 2016
Posts: 60
Location: Northeast USA

View user's profile Send private message

How to use FCMEN correctly & startup clock switching to
PostPosted: Thu Sep 05, 2019 12:31 pm     Reply with quote

PIC16F1779
CCS v5.081

I have search/viewed every similar topic here but have not found an adequate solution as of yet, so I am posting a new topic.

There is a TCXO = 30.72MHz connected to the OSC IN pin of the uC. In my test setup where the TXCO was always enabled ( its EN pin hard-wired to VDD ) I get expected results, expected delays, etc. This is achieved using the usual #fuses ECH statement for external high-speed oscillators.

In the real application, the TCXO is off by default because power isn't applied to the system yet. My goal is to (1) first have the uC boot and startup using some/any internal oscillator, (2) the first instruction in main() flips the EN pin of the TCXO high, thus starting the TCXO (3) The uC switches to using the 30.72MHz external clock from that point on, executing instructions in the remaining program. (4) At some future point in its operation, the uC will be put into a sleep state, the EN pin of TCXO will be pulled low, and the uC will go to sleep. Upon a wake-from-sleep routine, the uC again begins operation using one of its internal clocks ( doesn't matter which; not a time-sensitive startup in my application ), executes a few user-interface reads, and then again flips EN of the TCXO high again to resume using the fast external clock.

The first part of my inquiry involves the use of #fuses FCMEN If the ECH clock isn't found, FCMEN reverts the clock to some failsafe internal clock. But that is not what I am seeing. I see that no instructions are ever executed ... EN_TCXO never goes high ... until I manually poke the EN pin of the TCXO with 3.3V at which point the uC starts executing instructions.

Its as if #fuses FCMEN does not do what it intends to do ... code example below.


Code:

#include <16F1779.h>
#device PIC16F1779
#device ICD=TRUE                                             
#device ADC=10
#use delay(OSC=30.72MHZ, CLOCK=30.72MHZ)   // Sets default system oscillator thru FOSC bits in OSCCON
#fuses ECH
#fuses NOWDT     
#fuses FCMEN                  // Fail-safe clock monitor enable ... check this works over all corners!!!
#fuses NOPROTECT
#fuses DEBUG
#fuses CLKOUT
#fuses NOBROWNOUT
#fuses NOPUT

#define EN_TCXO             PIN_A0
#define TEST_LED            PIN_B0

void main(void)
{
    output_high(EN_TCXO);

    while(1)
    {
        output_high(TEST_LED);
        delay_ms(500);
        output_low(TEST_LED);
        delay_ms(500);
    }

}


So TEST_LED never goes high, until I manually poke EN_TCXO with 3.3V, then code executes as expected.

Why, despite the FCMEN fuse being enabled, is the first instruction to set high EN_TCXO never executed?

Now, the second part Laughing of this question involves switching back and forth between any internal clock <--> ECH clock. Are there any code examples out there for doing this exact back-and-forth clock source switching? It may simplify matters to know that any low-speed/internal clock being used will only be used right after a power-on condition or a wake-from-sleep condition, then execute a few pin reads, and flip EN_TCXO high. No delays, no timers used during this wake/PUC phase.
Ttelmah



Joined: 11 Mar 2010
Posts: 19536

View user's profile Send private message

PostPosted: Thu Sep 05, 2019 12:58 pm     Reply with quote

This is one of the things (like the watchdog), that the often doesn't work with
ICD. Check the actual fuses being generated (in the .lst file). You may well
find that FSCM is actually off. This is done because it causes issues on
some debuggers.
You have to test it for real, not with the debugger.
apakSeO



Joined: 07 Dec 2016
Posts: 60
Location: Northeast USA

View user's profile Send private message

PostPosted: Thu Sep 05, 2019 1:57 pm     Reply with quote

Ttelmah wrote:
This is one of the things (like the watchdog), that the often doesn't work with
ICD. Check the actual fuses being generated (in the .lst file). You may well
find that FSCM is actually off. This is done because it causes issues on
some debuggers.
You have to test it for real, not with the debugger.


Thanks Ttelmah, you are correct yet again.

Removing both the #device ICD=TRUE and the #fuses DEBUG lines allows FCMEN to do its thing, thus allowing the example program to run, albeit with bad timing due to the delay() function thinking its running at 30.72MHz. I'll fix that soon.

Now that I got FCMEN out of the way ... onto switching between an internal RC oscillator <--> external ECH oscillator ...

The setup_oscillator() prototype bif in the header file shows the following options only for the 16F1779:

Code:

/////////////////// INTERNAL RC
// Oscillator Prototypes:
_bif void setup_oscillator(int8 mode);
// Constants used in setup_oscillator() are:
// First parameter:
#define OSC_31KHZ   0
#define OSC_31250   (2*8)
#define OSC_62KHZ   (4*8)
#define OSC_125KHZ  (5*8)
#define OSC_250KHZ  (6*8)
#define OSC_500KHZ  (7*8)
#define OSC_1MHZ    (11*8)
#define OSC_2MHZ    (12*8)
#define OSC_4MHZ    (13*8)
#define OSC_8MHZ    (14*8)
#define OSC_16MHZ   (15*8)
// The following may be OR'ed in with the above using |
#define OSC_TIMER1  1
#define OSC_INTRC   2
#define OSC_NORMAL  0
// The following may be OR'ed in with the above using |
#define OSC_PLL_ON  0x80
#define OSC_PLL_OFF 0


How does one use setup_oscillator() to switch between internal RC and external ECH during program run time? I do not see an option for ECH in the header file. Is there another way to achieve this clock source switching?
gaugeguy



Joined: 05 Apr 2011
Posts: 303

View user's profile Send private message

PostPosted: Fri Sep 06, 2019 6:16 am     Reply with quote

OSC_NORMAL selects whatever the fuses specify
OSC_INTRC selects the internal oscillator
OSC_TIMER1 selects the secondary oscillator on Timer1

Make sure your fuses select your external oscillator and then this is the OSC_NORMAL selection.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group