HiTech Pic18 C コンパイラで C コードを使用して PIC18 をリセットする最良の方法は何ですか?
編集:
私は現在使用しています
void reset()
{
#asm
reset
#endasm
}
しかし、もっと良い方法があるはずです
通常、コンパイラには独自の reset() 関数が組み込まれていますが、実際の名前はコンパイラによって異なる場合があります。
あなたはすでにそれを可能な限り最善の方法で行っています。
あなたの答えは、私が知っている最良の方法です。重要なのは、関数呼び出し内にアセンブリ命令をすべて単独で含めることです。コンパイラは、インライン アセンブリを含む関数を最適化しません。そのため、リセット命令をインラインで非常に大きな関数に含めると、コンパイラはその関数のコードを最適化しません。独自の関数にリセットを配置することで、これを回避しました。この関数のコードは最適化されませんが、関数は非常に小さいため、気にする必要はありません。
ここにFAQがあります。
Q:マイクロをリセットするにはどうすればよいですか?
1つの方法は、PICマニュアルに記載されているように、すべての変数をデフォルトにリセットすることです。次に、アセンブリ言語を使用して、マイクロ内の0x0000の場所にジャンプします。
#asm ljmp 0x0000
#endasm
これは、割り込みまたはプロシージャ内で呼び出された場合でも、非常に安全に使用できます。PIC16xシリーズマイクロには8つのスタックレベルがあります。プロシージャが呼び出されるたびに、1つのスタックレベルがリターンアドレスに使用されます。これは循環バッファであるため、マイクロが7プロシージャレベルの深さであり、リセットが呼び出されたときに割り込みが発生した場合でも、これはスタックバッファの新しい開始であり、マイクロは通常どおり続行します。
もう1つの方法は、チップがプログラムされているときにウォッチドッグをタイマーに設定し、コード全体でCLRWDT()命令を使用することです。マイクロをリセットする場合は、ウォッチドッグビットのクリアを停止すると、プリスケーラに応じて約18ミリ秒から2秒後にマイクロがリセットされます。
マイクが 11 年前からこの元の質問を編集したため、元の投稿者が包括的な回答を必要としているとは思えません。実際、OP は、過去 9 年間にマイクロコントローラーに関する 2 つのトピックについてのみ質問または回答したようです。
PIC18F コントローラが、現在 Microchip によって呼び出されているように、Hi-Tech C または XC8 でコンパイルされるコードを使用して、リセット ベクターから実行を開始する方法のいくつかを調べることが役立つ場合があります。
このコードは、MPLABX v5.25、XC8 v2.05、および PIC18F45K20 コントローラーを使用してテストされています。
/*
* 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();
}
}
}
私は、PIC をリセットするための同様の API 呼び出しを持つ ccsinfo.com コンパイラを使用していますが、コンパイラのソリューションは正しいことをすると思います。
コンパイラベンダーのランタイムライブラリによって定義されたライブラリ関数がない限り(そのようなライブラリがマイクロコントローラの世界に存在する場合でも...しかし存在するはずです)、いいえ。C自体は確かにあなたを助けません。「リセット」を行うことは、Cがカバーするにはプラットフォーム固有の問題が多すぎます。