Reset du PIC aléatoire, comment debuguer ?
Répondre à la discussion
Affichage des résultats 1 à 17 sur 17

Reset du PIC aléatoire, comment debuguer ?



  1. #1
    quichedood

    Reset du PIC aléatoire, comment debuguer ?


    ------

    Bonjour,

    Je me bats toujours avec mon PIC 18F45K20 (code via MPLAB en C). Mon programme devient "important" (program memory = 12000 lignes en ASM).

    Je développe avec un PICKIT3.

    Depuis mes dernières modifications je me suis rendu compte que mon pic plante de manière assez aléatoire.
    En affichant le registre RCON sur le LCD c'est le bit 2 qui passe à 0 après le plantage : soit "Watchdog Time-out".

    Je souhaitais savoir si avec simplement un pickit3 j'avais un moyen d'isoler un peu plus précisément la cause du problème.

    (effectivement, je peux revenir en arrière niveau software et hardware mais 1-je n'est pas de versioning et 2-le bug est +/- aléatoire).

    Pour info si certaines personnes expérimentées ont déjà rencontré ce genre de problèmes, je vous mets les bits de config :

    Code:
    // CONFIG1H
    #pragma config FOSC = HS                   
    
    // CONFIG2H
    #pragma config WDTEN = OFF
    
    // CONFIG3H
    #pragma config MCLRE = ON
    #pragma config PBADEN = OFF   
    #pragma config HFOFST = ON
    
    // CONFIG4L
    #pragma config STVREN = OFF
    #pragma config LVP = OFF
    #pragma config XINST = OFF
    #pragma config DEBUG = OFF
    
    TRISB = 0xFF;
    OSCCONbits.SCS0 = 0; // Internal oscillator block  (P.29)
    OSCCONbits.SCS1 = 0; // Internal oscillator block  (P.29)
    OSCCONbits.OSTS = 1; // device is running from the clock defined by FOSC<2:0> (P.29)
    ADCON0bits.ADON = 0; // ADC is disabled and consumes no operating current (P.271)
    SSPCON1bits.SSPM0 = 0;
    SSPCON1bits.SSPM1 = 0;
    SSPCON1bits.SSPM2 = 0;
    SSPCON1bits.SSPM3 = 0;
    SSPCON1bits.SSPEN = 1;
    
    // Timer 0
    T0CONbits.TMR0ON = 1; // Enables Timer0
    T0CONbits.T08BIT = 1; // Timer0 is configured as a 8-bit timer/counter
    T0CONbits.T0CS = 0; // Internal instruction cycle clock (CLKOUT)
    T0CONbits.T0SE = 1; // Increment on high-to-low transition on T0CKI pin
    T0CONbits.PSA = 0; // Timer0 prescaler is assigned. Timer0 clock input comes from prescaler output
    T0CONbits.T0PS0 = 1; // Timer0 Prescaler Select bits (1:2) 000=204.8µs, 111=26ms (presc = 1:16, TMR0L = 101 => 1ms)
    T0CONbits.T0PS1 = 1;
    T0CONbits.T0PS2 = 0;
    
    // ISR
    INTCONbits.GIE = 1; // Global Interrupt Enable bit
    INTCONbits.PEIE = 1; // Peripheral Interrupt Enable bit
    RCONbits.IPEN = 1; // Enable priority levels on interrupts
    
    // ISR-Timer0
    INTCONbits.TMR0IF = 0; // TMR0 register did not overflow
    INTCON2bits.TMR0IP = 1; // Timer0 Interrupt Priority bit (high)
    INTCONbits.TMR0IE = 0; // Disable the TMR0 overflow interrupt (default = watch stopped)
    
    // Timer1
    T1CONbits.RD16 = 0; // Enables register read/write of Timer1 in two 8-bit operations
    T1CONbits.T1CKPS0 = 0; // 1:1 Prescale value
    T1CONbits.T1CKPS1 = 0;	
    T1CONbits.T1OSCEN = 0; // Timer1 oscillator is shut off
    T1CONbits.TMR1CS = 1; // External clock from pin RC0/T1OSO/T13CKI (on the rising edge)
    T1CONbits.TMR1ON = 1; // Enables Timer1
    
    // ISR-INT1
    INTCON3bits.INT1IF = 0; // The port B1 interrupt did not occur
    INTCON3bits.INT1IP = 0; // Port B1 Interrupt Priority bit (low)
    INTCON3bits.INT1IE = 1; // Enables the port B1 interrupt
    
    // ISR-INT2
    INTCON3bits.INT2IF = 0; // The port B2 interrupt did not occur
    INTCON3bits.INT2IP = 0; // Port B2 Interrupt Priority bit (low)
    INTCON3bits.INT2IE = 0; // Enables the port B2 interrupt
    
    // ISR-RB4/7
    INTCONbits.RBIF = 0; // The port B4-7 interrupt did not occur
    INTCON2bits.RBIP = 0; // Port B4-7 Interrupt Priority bit (low)
    INTCONbits.RBIE = 1; // Enables the port B4-7 interrupt
    IOCBbits.IOCB4 = 1; // Enables the port B4 interrupt
    IOCBbits.IOCB5 = 1; // Enables the port B5 interrupt
    IOCBbits.IOCB6 = 1; // Enables the port B6 interrupt
    IOCBbits.IOCB7 = 0; // Enables the port B7 interrupt
    
    // I2C
    OpenI2C(MASTER, SLEW_OFF);	// Initialize I2C module
    SSPADD = 0x3F;				// I2C CLK Adjust
    Je pensais à un overflow sur des variables ou quelque chose d'équivalent tout en sachant que j'utilise des structures de taille importantes

    Pour info j'ai du modifier mon fichier LKR :
    Code:
    DATABANK   NAME=gpr0       START=0x60              END=0xFF
    DATABANK   NAME=gpr1       START=0x100             END=0x1FF
    DATABANK   NAME=big       START=0x200             END=0x37F PROTECTED
    DATABANK   NAME=gpr3       START=0x380             END=0x3FF
    DATABANK   NAME=gpr4       START=0x400             END=0x4FF
    
    SECTION NAME=buffer_scn RAM=big
    Et dans le .c :
    Code:
    #pragma idata buffer_scn
    static unsigned short long buffer[25][4] = {0}, (*splittime_history)[4] = buffer;
    #pragma idata
    Voilà si quelqu'un a une piste sur laquelle je pourrai m'orienter ...

    -----

  2. #2
    r4ph

    Re : Reset du PIC aléatoire, comment debuguer ?

    Je dis peut etre une betise qui parait trop simple mais si il ya un probleme de time out du watchdog, peut etre ton programme devenu consequent prends trop de temps et tu devrais du coup le remettre a zero plus souvent. Pour debuguer, tu peux betement desactiver le watchdog, si tu n'as plus de reset, tu auras ta solution.

  3. #3
    r4ph

    Re : Reset du PIC aléatoire, comment debuguer ?

    bon, wdten = off, faites comme si j'avais rien ecris...

  4. #4
    quichedood

    Re : Reset du PIC aléatoire, comment debuguer ?

    Héhé, c'est l'attention qui compte

    Bon, je me suis décidé à réduire mon code au strict minimum.

    La ligne qui me fait tout planter est la suivante :
    Code:
    sprintf(lcd_buffer,(const far rom char*)"%02d:%02d:%03d %c%02d:%02d:%03d", m1, s1, ms1, neg2, m2, s2, ms2);
    Si je la remplace par :
    Code:
    sprintf(lcd_buffer,(const far rom char*)"%05d %05d", counter_copy, diff_lap);
    Pour le contexte :
    2 temps sont affichés (short long).
    Ce sont des temps (précision au millième), j'ai donc une fonction qui décompose en minutes, secondes, millisecondes ainsi que le signe (+ ou -) qui indique un temps > ou < au temps de référence.

    Notez que dans les 2 cas ci-dessus la fonction de formatage du temps est toujours appelée. C'est uniquement l'affichage qui fait planter ...

    Je file continuer mon investigation ...

  5. A voir en vidéo sur Futura
  6. #5
    invitee23b806b

    Re : Reset du PIC aléatoire, comment debuguer ?

    Salut,

    petite question: est-ce que ton buffer "lcd_buffer" fait au moins 21 caractères? (Si j'ai bien compté!)
    Si il est inférieur à 21, tu as un débordement!

    @ +,

  7. #6
    quichedood

    Re : Reset du PIC aléatoire, comment debuguer ?

    Hello,

    Moi j'ai mis 19 ... maintenant reste à savoir ce qui m'est passé par la tête quand j'ai écrit cette ligne

    Bon par contre, même si je suis entièrement d'accord avec toi qu'il faut mettre 21, là mon programme plante dès ma première interruption (en gros dès la première mise à jour de l'affichage).

    Il y a donc peut-être 2 problèmes. En tout cas je vais creuser de ce coté là, je mettrai à jour le topic en fonction de mes avancées (uniquement le soir malheureusement).

  8. #7
    amoniaque

    Re : Reset du PIC aléatoire, comment debuguer ?

    Salut,

    Tu as essayer d'allonger le temps de ton watchdog?
    Peut-être que tu as une ligne trop longue à exécuter dans ton sprintf ...

    ++

  9. #8
    quichedood

    Re : Reset du PIC aléatoire, comment debuguer ?

    Citation Envoyé par amoniaque Voir le message
    Salut,

    Tu as essayer d'allonger le temps de ton watchdog?
    Peut-être que tu as une ligne trop longue à exécuter dans ton sprintf ...

    ++
    Haha, je dois faire que des erreurs de débutant.

    J'ai commenté toutes les lignes qui semblaient faire planter mon programme (sprintf + fonction de formattage du temps, cf post d'hier soir) et effectivement en reactivant le watchdog j'avais à nouveau des resets.

    Voici les modifications apportées :
    Code:
    #pragma config WDTEN = ON
    #pragma config WDTPS = 32768
    Code:
    void restart_WDT (void) {
      	_asm 
    	CLRWDT
    	_endasm
    }
    et dans ma boucle "while(1)" j'ai mis :
    Code:
    restart_WDT();
    (il faut que je calcul l'équivalent en ms de "WDTPS = 32768" car sans le restart_WDT j'ai toujours des resets aléatoires, ça doit se jouer à pas grand chose).

    Là mon programme ne plante plus (mais attention certaines lignes sont encore commentées). J'ai également passé le lcd_buffer à 21 sans que ça provoque un quelconque plantage.

    ça avance, ça avance, je me penche sur le reste dès ce soir

  10. #9
    quichedood

    Re : Reset du PIC aléatoire, comment debuguer ?

    Je pense avoir trouvé l'endroit du problème, mais ne comprend pas trop le pourquoi du comment.

    Les problèmes de timeout de watchdog et je pense de "lcd_buffer" étaient bien réels (bien vu !!).

    Il y avait de plus un problème au niveau de l'appel de ma fonction de formatage du temps :
    Code:
    FormatTime(counter, (char *)&m, (char *)&s, (int *)&ms, (char *)&neg);
    Lorsqu'elle se trouve dans mon interruption, mon programme plante aléatoirement. Si je déplace les appels à cette fonction directement dans ma boucle while(1) plus de problème.

    Par contre je n'arrive pas à expliquer ce comportement ...

  11. #10
    simon.

    Re : Reset du PIC aléatoire, comment debuguer ?

    Ca ressemble à un débordement de la pile.
    Essaie de reduire le nombre de niveaux d'appels de fonctions : en gros fais des fonctions plus grosses plutot que plein de petites fonctions qui s'appellent les unes les autres.

    Tu peux aussi remplacer les toutes petites fonctions par des macros.

    De mémoire, si tu pretes attention à ce que le compilateur affiche à la compilation, il detecte ce genre de pb et affiche un warning.
    Dernière modification par simon. ; 28/07/2011 à 10h18.

  12. #11
    invitee23b806b

    Re : Reset du PIC aléatoire, comment debuguer ?

    Salut,

    la première chose à faire est de ne pas appeler dans l'interruption les fonctions de la famille "printf".
    Pour cela il suffit de lever un flag dans la routine d'IT et de tester ce flag dans la boucle principale du "main" pour effectuer le sprintf() et de rebaisser le flag.
    Les fonctions de la famille "printf" sont très gourmandes en ressources et en temps, or une bonne routine d'interruption doit être la plus courte possible (surtout en temps) afin de ne pas retarder les éventuelles autres IT.

    @ +,

  13. #12
    RISC

    Re : Reset du PIC aléatoire, comment debuguer ?

    Salut,

    Pour les PIC18, il est très simple de connaitre la source d'un reset à condition...d'avoir écrit un handler de reset.
    Lis le chapitre sur le Reset : en testant différents flags tu peux connaitre la source.
    Attention cependant car en C18 tu as le startup code (C018.o) qui démarre avant ton programme...

    a+

  14. #13
    quichedood

    Re : Reset du PIC aléatoire, comment debuguer ?

    Merci à tous pour vos réponses.

    Simplement pour info, la fonction en question. J'étais persuadé de l'avoir postée précédemment :
    Code:
    void FormatTime(short long inc, char *ptr_m, char *ptr_s, int *ptr_ms, char *ptr_neg) {
    	if(inc < 0) {
    		*ptr_neg = '+';
    	} else {
    		*ptr_neg = '-';
    	}
    	inc = fabs(inc);
    	*ptr_m = inc/60000;
    	*ptr_s = (inc%60000)/1000;
    	*ptr_ms = inc%((inc/1000)*1000);
    }
    Citation Envoyé par simon. Voir le message
    Ca ressemble à un débordement de la pile.
    Essaie de reduire le nombre de niveaux d'appels de fonctions : en gros fais des fonctions plus grosses plutot que plein de petites fonctions qui s'appellent les unes les autres.

    Tu peux aussi remplacer les toutes petites fonctions par des macros.

    De mémoire, si tu pretes attention à ce que le compilateur affiche à la compilation, il detecte ce genre de pb et affiche un warning.
    Je n'ai pas tant de fonctions que ça (j'ai un peu de mal à juger par rapport à un µproc) 12 au total, dont la majorité d'initialisation qui sont donc appelées qu'une seule fois. Pas de warning à la compilation en tout cas.
    Mais je note pour plus tard les "bonnes pratiques".

    Citation Envoyé par Tuxtronic Voir le message
    Salut,

    la première chose à faire est de ne pas appeler dans l'interruption les fonctions de la famille "printf".
    Pour cela il suffit de lever un flag dans la routine d'IT et de tester ce flag dans la boucle principale du "main" pour effectuer le sprintf() et de rebaisser le flag.
    Les fonctions de la famille "printf" sont très gourmandes en ressources et en temps, or une bonne routine d'interruption doit être la plus courte possible (surtout en temps) afin de ne pas retarder les éventuelles autres IT.

    @ +,
    Pas de printf dans mes interruptions (mais pareil je note )
    Pas bête le coup du flag pour externaliser le maximum de traitements de l’interruption, je vais pouvoir optimiser un peu plus.

    Citation Envoyé par RISC Voir le message
    Salut,

    Pour les PIC18, il est très simple de connaitre la source d'un reset à condition...d'avoir écrit un handler de reset.
    Lis le chapitre sur le Reset : en testant différents flags tu peux connaitre la source.
    Attention cependant car en C18 tu as le startup code (C018.o) qui démarre avant ton programme...

    a+
    Tu parles du registre RCON sur les pics j'imagine (cf premier post). C'est le problème du timeout qui ressortait mais une fois résolu j'avais bien un second bug (l'appel de ma fonction dans l'interruption). Plus qu'à refaire planter mon programme pour tester

    En tout cas encore un grand merci à vous tous pour vos précieux conseils !


    Je viens juste d'y penser mais ça serait peut-être pas bête de mettre un pointeur sur le 1er argument dans ma fonction (short long), ça éviterait de dupliquer la variable à chaque appel de la fonction je suppose ...

  15. #14
    RISC

    Re : Reset du PIC aléatoire, comment debuguer ?

    Salut,

    A quelle fréquence fonctionnes-tu ?
    Le PIC18F45K20 peut fonctionner à 64MHz (dans ce cas tu prends un quartz 16MHz et tu actives la PLL interne x4 par les bits de configuration).

    Tu utilises des fonctions de traitement de chaine et tu travailles sur des types assez importants avec en plus pas mal de divisions...
    Il faut donc faire tourner ton PIC18 le plus vite possible.

    a+

  16. #15
    quichedood

    Re : Reset du PIC aléatoire, comment debuguer ?

    Je suis à 10Mhz (bon ok c'était le quartz que j'avais sous la main quand j'ai commencé le projet).

    Aucun souci pour passer à 64Mhz mais j'ai peur au niveau de la consommation (fonctionne sur pile, et j'ai en plus un LCD avec backlight).

    Actuellement je suis déjà à 15mA.

  17. #16
    RISC

    Re : Reset du PIC aléatoire, comment debuguer ?

    Salut,

    Sans changer to quartz, tu peux activer la PLL interne dans les bits de configuration pour multiplier par quatre ta fréquence.
    Je crois qu'au lieu de OSC=HS tu dois mettre OSC=HSPLL (voir le manuel config settings).
    Il faudra bien sûr adapter ton programme qui tournera à 10MIPS au lieu de 2,5MIPS.

    Si tu fonctionnes sur pile, il faut utiliser les mode low power (Sleep ou Idle). C'est la seule manière de réellement réduire la consommation moyenne et d'allonger la durée de vie de ta pile :=)

    a+

  18. #17
    quichedood

    Re : Reset du PIC aléatoire, comment debuguer ?

    Ouaip je vais voir pour la fréquence de fonctionnement mais pour l'instant en 10Mhz ça me semble suffisant.

    Par contre c'est possible qu'avec les quelques fonctions prévues ça commence à devenir limite (je prévois d'implémenter le SPI en software vu que j'utilise déjà l'I2C hardware)

    Je vais regarder les modes sleep et idle mais dans mon cas ça va être difficile à utiliser je pense ...

Discussions similaires

  1. Reset intempestif du PIC
    Par invite953f8104 dans le forum Électronique
    Réponses: 22
    Dernier message: 21/02/2011, 19h21
  2. Pb reset PIC
    Par Beugs68 dans le forum Électronique
    Réponses: 20
    Dernier message: 20/01/2011, 14h27
  3. Reset multiples PIC simultanément
    Par invite60243f9b dans le forum Électronique
    Réponses: 3
    Dernier message: 15/12/2008, 17h32
  4. reset PIC
    Par EmKa69 dans le forum Électronique
    Réponses: 7
    Dernier message: 12/11/2008, 23h25
  5. reset sur pic ou atmel
    Par inviteac54bf81 dans le forum Électronique
    Réponses: 1
    Dernier message: 18/11/2007, 22h05
Découvrez nos comparatifs produits sur l'informatique et les technologies.