J'utilise un Microchip dsPIC30F6012a. J'ai cette puce sur plusieurs PCB, tous exécutant le même logiciel, et j'observe le même problème sur chacun d'eux. Cela implique un problème systémique, pas un problème de production ponctuel. Le problème est également reproductible, ce qui implique que je devrais pouvoir le tuer si je sais où chercher. Mais j'ai toujours des difficultés surprenantes à déboguer l'application.
La carte testée accepte 24V, qui descend à 5V via un V7805. La puce fonctionne sur son oscillateur interne, avec une PLL 16x, donnant une vitesse de fonctionnement de ~ 29,5 MIPS. Le code pertinent sur cette carte est essentiellement très simple: réveillez-vous, lisez les données de l'EEPROM, puis entrez dans une boucle infinie. Interrompez toutes les millisecondes, observez certaines données environnementales et écrivez une valeur mise à jour dans l'EEPROM. Il y a d'autres choses en cours, mais le problème persiste même si le code non lié est commenté, donc je peux être raisonnablement certain qu'il n'est pas pertinent pour le problème en question.
En général, 95% du temps, la carte se réveille avec la bonne valeur en mémoire et continue ses activités. Les 5% restants, cependant, il se réveille avec une valeur incorrecte. Plus précisément, il se réveille avec une version inversée des données qu'il est censé contenir. C'est un long non signé de quatre octets que je regarde, et le mot supérieur ou inférieur du long peut être inversé. Par exemple, 10 devient 2 ^ 16-10, qui devient plus tard 2 ^ 32-10. Je peux reproduire le pépin en coupant manuellement l'alimentation plusieurs dizaines de fois, mais ce n'est pas très cohérent, et mon interrupteur s'use.
Afin de reproduire le problème de manière contrôlée, j'ai construit une deuxième carte qui alimente l'alimentation 24 V de la carte en cours de test. (Un autre dsPIC pilotant un optocoupleur Darlington.) La carte testeur éteint le 24 V pendant 1,5 seconde (assez longtemps pour que le rail 5 V tombe à essentiellement 0 et y reste pendant une seconde), puis allume le 24 V pendant une durée configurable . Avec un temps d'activation d'environ 520 mS, je peux reproduire ce pépin EEPROM en cinq cycles d'alimentation, à chaque fois.
Le rail 5V se comporte raisonnablement. Il s'installe à 5 V dans 1 mS de mise sous tension, avec peut-être 0,4 V de dépassement, en supposant que je peux faire confiance à ma portée. À l'arrêt, il décroît à 0 V de façon exponentielle, atteignant 1 V à moins de 50 mS. Je n'ai aucun avertissement de construction qui semble pertinent, juste des variables inutilisées et des sauts de ligne manquants à la fin des fichiers.
J'ai essayé plusieurs choses:
- Activation / désactivation du MCLR
- Activation / désactivation du WDT
- Activation / désactivation de la protection du code
- Activation / désactivation / modification de la coupure de détection de tension
- Activation / désactivation / modification de la minuterie de mise sous tension
- Différents paramètres PLL sur l'oscillateur interne principal
- Connexion / déconnexion de mon programmateur PICkit 3
- Ajout de 470 uF de capacité au rail 5V
- Ajout / suppression de 0,1 uF dans le pullup de 4,7 k sur ma broche MCLR
- Désactiver toutes les interruptions du code et ne laisser que des mises à jour EEPROM dans la boucle principale
- Ajout d'un délai de 1,5 seconde à ma routine de démarrage avant de commencer à lire l'EEPROM
J'ai également écrit un code de test séparé qui ne fait rien d'autre que d'écrire continuellement des valeurs dans l'EEPROM, puis de les relire, en m'assurant que la valeur n'a pas changé. Des dizaines de milliers d'itérations n'ont donné aucune erreur. Tout ce que je peux conclure, c'est que quelque chose ne va pas avec la lecture ou l'écriture de l'EEPROM, en particulier à la mise sous tension / hors tension.
J'utilise les mêmes bibliothèques EEPROM depuis 2007. J'ai vu des problèmes occasionnels, mais rien de reproductible. Le code correspondant peut être trouvé ici:
http://srange.net/code/eeprom.c
http://srange.net/code/readEEByte.s
http://srange.net/code/eraseEEWord.s
http: / /srange.net/code/writeEEWord.s
J'ai déjà vu des erreurs EEPROM dans d'autres applications, mais toujours comme des problèmes ponctuels, rien de reproductible ou cohérent.
Quelqu'un a-t-il une idée de ce qui se passe? Je suis à court de choses à essayer.
la source
Réponses:
Deux choses me viennent à l'esprit:
Tout d'abord, selon la fiche technique, un cycle d'effacement-écriture prend au moins 0,8 ms et jusqu'à 2,6 ms. Vous dites que vous avez une interruption toutes les 1 ms, ce qui peut entraîner une opération d'écriture. J'ai vu dans le code que vous désactivez les interruptions pour certaines parties de l'effacement et pour certaines parties de la fonction d'écriture. Mais vous pourriez toujours obtenir un entrelacement amusant des appels de fonction. Peut-être que cela aide lorsque vous désactivez les interruptions pour toute la séquence d'effacement et d'écriture?
Deuxièmement - vous souhaiterez peut-être écrire pendant que l'alimentation est coupée et l'écriture EEPROM se produit exactement au moment où la tension d'alimentation descend en dessous de la tension de fonctionnement. Vous pouvez essayer de surveiller la tension d'alimentation et refuser une écriture lorsqu'elle est en dessous, disons 4,5V. Cela suppose qu'il reste suffisamment longtemps au-dessus de 2,7 V en tant que tension de fonctionnement minimale, et la détection de brunissement est définie pour se déclencher uniquement en dessous de ce point.
la source
Vous avez examiné de nombreux problèmes matériels possibles. C'est bien, mais c'est probablement un bug de firmware.
Malheureusement, votre code source est mal documenté et est formaté pour être difficile à suivre visuellement. Votre premier fichier contient la déclaration des routines externes en haut:
Non seulement c'est une mauvaise idée de mettre des déclarations comme celle-ci privées dans les modules clients, il n'y a pas un seul commentaire en vue! Nous ne pouvons que deviner ce que vous voulez que ces routines fassent à partir de leur nom, et les arguments d'appel sont complètement non documentés. Plus loin dans ce fichier, vous avez différentes lignes commençant par "//" et une ligne entière de signes égaux. Ceux-ci ajoutent un encombrement visuel, ce qui rend trop difficile de suivre le code.
Vous pouvez dire que rien de tout cela n'a d'importance pour le fonctionnement du code. Cependant, les mauvaises pratiques de programmation comme celle-ci comptent beaucoup. Ils provoquent une mauvaise écriture du code et rendent difficile la détection de bogues ou même ce que le code est censé faire. Tout cela se traduit par des problèmes difficiles à trouver, comme vous le découvrez. Vous avez même dit vous-même que vous aviez occasionnellement vu des défauts de ce code depuis 2007. Cela aurait dû être un indice fort d'un bug, peut-être même d'une mauvaise conception globale.
Corrigez le désordre, documentez correctement toutes les interfaces et placez des déclarations communes dans les fichiers d'inclusion que vous écrivez une fois, puis référencez-les si nécessaire. De plus, votre déclaration de Je n'ai aucun avertissement de construction qui semble pertinent est un énorme drapeau rouge. Encore une fois, corrigez le désordre. Lors du débogage, recherchez toujours d'abord les problèmes facilement reproductibles et réparables. Parfois, ce sont en fait la cause des problèmes difficiles, ou parfois en les résolvant, vous découvrez la cause d'autres problèmes. Le compilateur vous avertit de la négligence sur un plateau d'argent. Que veux-tu de plus? Vous ne devriez pas avoir de variables inutilisées car elles causent de la confusion à quiconque essaie de donner un sens à votre code, et il n'y a aucune excuse pour manquer de nouvelles lignes. Encore une fois, corrigez-les clairement, surtout avant de demander à quelqu'un d'autre de regarder votre code.
La propreté et l'attention aux détails comptent . Beaucoup.
la source
J'ai eu un comportement identique avec 4 pièces de dsPIC30F6014A (environ 10 utilisées au cours des derniers mois ..), la seule façon d'éviter la corruption sporadique des données lors de la mise hors tension est de mettre à zéro le MCLR juste avant l'arrêt.
Evidemment ce n'est pas faisable en pratique, j'ai donc opté pour le remplacement du "mauvais" dsPIC, si quelqu'un a une autre solution à la place ...
la source