5

What is the best way to reset a PIC18 using C code with the HiTech Pic18 C compiler?

Edit:

I am currenlty using

void reset()
{
#asm 
  reset
#endasm
}

but there must be a better way

1
  • 3
    could there be a better way to do anything then calling a single ASM instruction? why do you need to reset the whole controller? are you intending to reset all peripherals? just written to PGM memory flash? (that's about the only good excuse to do it) Commented May 21, 2009 at 18:18

6 Answers 6

8

The compilers usually have their own reset() function built in, but it just does exactly what your function does, and the actual name may vary from compiler to compiler.

You are already doing it the best possible way.

Sign up to request clarification or add additional context in comments.

Comments

5

Your answer is the best way I know of. The key is that you have the assembly instruction inside a function call, all by itself. The compiler will not optimize a function that has inline assembly in it, so if you include the reset instruction inline to a very large function, the compiler will not optimize any of the code in that function. You have avoided this by putting Reset in its own function. The code in this function won't be optimized, but who cares, since it is such a small function.

Comments

2

There's a FAQ here.

Q: How do I reset the micro?

One way is to reset all variables to their defaults, as listed in the PIC manual. Then, use assembly language to jump to location 0x0000 in the micro.

#asm ljmp 0x0000

#endasm

This is quite safe to use, even when called within interrupts or procedures. The PIC 16x series micros have 8 stack levels. Each time a procedure is called, one stack level is used up for the return address. It is a circular buffer, so even if the micro is 7 procedure levels deep and in an interrupt when a reset is called, this is the new start of the stack buffer, and the micro will continue as per normal.

Another way is to set watchdog the timer when the chip is programmed, and use CLRWDT() instructions all through the code. When you want the micro to reset, stop clearing the watchdog bit and the micro will reset after around 18ms to 2 seconds depending on the prescaler.

5 Comments

The jump to 0x0000 won't reset any hardware peripherals. I'd use the watchdog or the reset assembly instruction.
I know this is a very old question, but I stumbled upon it with a similar issue. According to the Microchip youtube page link there are some new enhanced instructions added to the PICs. One of them being a reset instruction. I've not got this working yet, and can't find much info on it but it looks like there is a way.
@DanTwining: thanks for the update. It would make sense for Microchip to add this enhancement in the 3 years that have passed :)
Jumping to 0x0000 will not reset the stack, do this enough times from within a function and you will get a stack overflow !
@Cobusve: this answer is 7 years old. It would be more constructive to propose edits that update it to the modern answer, to help folks who stumble into this question. Here, I turned it into "community wiki" to make updates easier.
1

As Mike has edited this original question from 11 years ago it seems doubtful the Original Poster needs a comprehensive answer. In fact the OP seems to have asked about or responded on just 2 topics regarding microcontrollers in the past 9 years.

Given all that it may be helpful to look at some of the ways the PIC18F controller can be caused to begin execution from the reset vector with code that compiles with Hi-Tech C or XC8 as it is now called by Microchip.

This code has been tested using MPLABX v5.25, XC8 v2.05 and the PIC18F45K20 controller.

/*
 * File:     main.c
 * Author:   dan1138
 * Target:   PIC18F45K20
 * Compiler: XC8 v2.05
 *
 *                                                             PIC18F46K20
 *                 +---------+                 +---------+                 +----------+                 +----------+
 *           <>  1 : RC7/RX  :           -- 12 : NC      :           <> 23 : RA4      :           -- 34 : NC       :
 *      LED4 <>  2 : RD4     :           -- 13 : NC      :           <> 24 : RA5      : 32.768KHz -> 35 : RC1/SOSI :
 *      LED5 <>  3 : RD5     :           <> 14 : RB4     :           <> 25 : RE0      :           <> 36 : RC2      :
 *      LED6 <>  4 : RD6     :           <> 15 : RB5/PGM :           <> 26 : RE1      :           <> 37 : RC3      :
 *       GND ->  5 : VSS     :       PGC <> 16 : RB6/PGC :           <> 27 : RE2      :      LED0 <> 38 : RD0      :
 *       3v3 ->  6 : VDD     :       PGD <> 17 : RB7/PGD :       3v3 -> 28 : VDD      :      LED1 <> 39 : RD1      :
 *       SW1 <>  7 : RB0/INT :       VPP -> 18 : RE3/VPP :       GND -> 29 : VSS      :      LED2 <> 40 : RD2      :
 *           <>  8 : RB1     :       POT <> 19 : RA0/AN0 :      4MHz -> 30 : RA7/OSC1 :      LED3 <> 41 : RD3      :
 *           <>  9 : RB2     :           <> 20 : RA1     :      4MHz <- 31 : RA6/OSC2 :           <> 42 : RC4      :
 *           <> 10 : RB3     :           <> 21 : RA2     : 32.767KHz <- 32 : RC0/SOSO :           <> 43 : RC5      :
 *      LED7 <> 11 : RD7     :           <> 22 : RA3     :           -- 33 : NC       :           <> 44 : RC6/TX   :
 *                 +---------+                 +---------+                 +----------+                 +----------+
 *                                                              TQFP-44
 *
 *
 * Created on December 21, 2019, 2:26 PM
 */

/* Target specific configuration words */
#pragma config FOSC = INTIO67, FCMEN = OFF
#pragma config IESO = OFF, PWRT = OFF, BOREN = SBORDIS, BORV = 18
#pragma config WDTEN = OFF, WDTPS = 32768, CCP2MX = PORTC, PBADEN = OFF
#pragma config LPT1OSC = ON, HFOFST = ON
#pragma config MCLRE = ON, STVREN = ON, LVP = OFF, XINST = OFF
#pragma config CP0 = OFF, CP1 = OFF, CP2 = OFF, CP3 = OFF
#pragma config CPB = OFF, CPD = OFF
#pragma config WRT0 = OFF, WRT1 = OFF, WRT2 = OFF, WRT3 = OFF
#pragma config WRTC = OFF, WRTB = OFF, WRTD = OFF
#pragma config EBTR0 = OFF, EBTR1 = OFF, EBTR2 = OFF, EBTR3 = OFF
#pragma config EBTRB = OFF

/* Target specific definitions for special function registers */
#include <xc.h>

/* Declare the system oscillator frequency setup by the code */
#define _XTAL_FREQ (4000000UL)

/* reset instruction */
void ResetMethod_1(void)
{
    asm(" reset");
}

/* long jump to absolute address zero */
void ResetMethod_2(void)
{
    INTCON = 0;
    asm(" pop\n ljmp 0");
}

/* return to absolute address zero */
void ResetMethod_3(void)
{
    INTCON = 0;
    asm(" clrf TOSU\n clrf TOSH\n clrf TOSL\n");
}

/* provoke stackoverflow reset */
void ResetMethod_4(void)
{
    INTCON = 0;
    while (1) 
    {
        asm(" push\n");
    }
}

/* provoke stackunderflow reset */
void ResetMethod_5(void)
{
    INTCON = 0;
    STKPTR = 0;
}

/* clear the program counter */
void ResetMethod_6(void)
{
    INTCON = 0;
    asm(" clrf PCLATU\n clrf PCLATH\n clrf PCL\n");
}

void main(void)
{
    INTCON = 0;             /* Disable all interrupt sources */
    PIE1 = 0;
    PIE2 = 0;
    INTCON3bits.INT1IE = 0;
    INTCON3bits.INT2IE = 0;

    OSCCON = 0x50;          /* set internal oscillator to 4MHz */
    OSCTUNEbits.TUN = 0;    /* use factory calibration of internal oscillator */
    ANSEL = 0;
    ANSELH = 0;
    
    if(!RCONbits.nPOR)
    {
        RCONbits.nPOR = 1;
        LATD = 0;
    }
    
    TRISD = 0;
    /*
     * Application loop
     */
    while(1)
    {
        __delay_ms(500);
        if (LATDbits.LD0 == 0)
        {
            LATDbits.LD0 = 1;
            ResetMethod_1();
        }
        
        if (LATDbits.LD1 == 0)
        {
            LATDbits.LD1 = 1;
            ResetMethod_2();
        }

        if (LATDbits.LD2 == 0)
        {
            LATDbits.LD2 = 1;
            ResetMethod_3();
        }
        
        if (LATDbits.LD3 == 0)
        {
            LATDbits.LD3 = 1;
            ResetMethod_4();
        }

        if (LATDbits.LD4 == 0)
        {
            LATDbits.LD4 = 1;
            ResetMethod_5();
        }

        if (LATDbits.LD5 == 0)
        {
            LATDbits.LD5 = 1;
            ResetMethod_6();
        }
    }
}

Comments

0

Unless there's a library function defined by the compiler vendor's runtime library (if such a lib even exists in the microcontroller world ... but it should), then no. C itself certainly won't help you out, doing "a reset" is far too much of a platform-specific issue for C to cover it.

Comments

0

I use the ccsinfo.com compiler, which has a similar API call for resetting the PIC, but I would think the compiler's solution would do the right thing.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.