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
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
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.
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.
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();
}
}
}