Как сбросить PIC18 в C?

Как лучше всего сбросить PIC18 с помощью кода C с компилятором HiTech Pic18 C?

Редактировать:

Я сейчас использую

void reset()
{
#asm 
  reset
#endasm
}

но должен быть способ получше

может быть лучший способ сделать что-нибудь, чем вызов одной инструкции ASM? зачем вам сбросить весь контроллер? вы собираетесь сбросить все периферийные устройства? только что записано во флеш-память PGM? (это единственный хороший повод сделать это)

jpinto3912 21.05.2009 22:18
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
3
1
8 460
6
Перейти к ответу Данный вопрос помечен как решенный

Ответы 6

Если нет библиотечной функции, определенной библиотекой времени выполнения поставщика компилятора (если такая библиотека даже существует в мире микроконтроллеров ... но должна), тогда нет. Сам по себе C определенно не поможет вам, выполнение «сброса» - это слишком специфическая для платформы проблема, чтобы C мог ее решить.

Я использую компилятор ccsinfo.com, у которого есть аналогичный вызов API для сброса PIC, но я думаю, что решение компилятора будет делать правильные вещи.

Ответ принят как подходящий

Есть FAQ здесь.

В: Как мне сбросить микроконтроллер?

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.

Переход к 0x0000 не приведет к сбросу каких-либо аппаратных периферийных устройств. Я бы использовал сторожевой таймер или инструкцию по сборке сброса.

Robert 22.10.2008 19:37

Я знаю, что это очень старый вопрос, но я наткнулся на него с аналогичной проблемой. Согласно странице Microchip на YouTube связь, к PIC добавлены некоторые новые улучшенные инструкции. Одна из них - инструкция по сбросу. У меня это еще не работает, и я не могу найти много информации о нем, но похоже, что способ есть.

Dan Twining 13.12.2011 04:51

@DanTwining: спасибо за обновление. Для Microchip было бы разумно добавить это усовершенствование через 3 года, которые прошли :)

Eli Bendersky 13.12.2011 08:52

Переход к 0x0000 не приведет к сбросу стека, сделайте это достаточное количество раз из функции, и вы получите переполнение стека!

Cobusve 15.05.2015 10:08

@Cobusve: этому ответу 7 лет. Было бы более конструктивно предложить изменения, которые обновят его до современного ответа, чтобы помочь людям, которые наткнулись на этот вопрос. Здесь я превратил его в «вики сообщества», чтобы упростить обновление.

Eli Bendersky 15.05.2015 16:06

В компиляторы обычно встроена собственная функция reset (), но она выполняет именно то, что делает ваша функция, а фактическое имя может варьироваться от компилятора к компилятору.

Вы уже делаете это наилучшим образом.

Ваш ответ - лучший из известных мне способов. Ключ в том, что у вас есть инструкция по сборке внутри вызова функции, сама по себе. Компилятор не будет оптимизировать функцию, в которой есть встроенная сборка, поэтому, если вы включите встроенную инструкцию сброса в очень большую функцию, компилятор не будет оптимизировать какой-либо код в этой функции. Вы избежали этого, поместив Reset в отдельную функцию. Код в этой функции не будет оптимизирован, но кого это волнует, ведь это такая маленькая функция.

Поскольку Майк редактировал этот исходный вопрос 11 лет назад, кажется сомнительным, что исходный плакат нуждается в исчерпывающем ответе. Фактически, OP, кажется, спросил или ответил только на 2 темы, касающиеся микроконтроллеров, за последние 9 лет.

Учитывая все это, может быть полезно взглянуть на некоторые способы, которыми контроллер PIC18F может быть инициирован для начала выполнения из вектора сброса с кодом, который компилируется с Hi-Tech C или XC8, поскольку он не вызывается Microchip.

Этот код был протестирован с использованием 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();
        }
    }
}

Другие вопросы по теме