Forum: Mikrocontroller und Digitale Elektronik AVR: Rogue Pointer oder böser Geist verursachen Abstürze


von Alex (Gast)


Lesenswert?

Hallo Leute vom µC.net

vorweg: ich verwende Atmel Studio 6 und einen AVRICE2 mit JTAG zum 
Debuggen/Flashen.
Die Software, welche ich benutze ist ein Professioneller Treiber von HMS 
Industrial Networks und laut deren Entwicklungsabteilung mehrmals 
getestet.
Dieser generische Treiber besteht aus ca. 80 Header- und Sourcefiles in 
C und wird mit ein paar wenigen Callback-funktionen und #defines auf 
eine Plattform zugeschnitten. Veröffentlichen darf ich davon nichts...


So ich hoffe das sind ausreichend Infos. So jetzt zur Sache ich habe 
einen "Fehler" der mich langsam zur Verzweiflung treibt:

Ich hatte zufällige Abstürze mit meinem AT90CAN128, also habe ich ein 
wenig Nachforschung betrieben und bin zu der Erkenntnis gekommen, dass 
ein "rogue Pointer" mir das Leben schwer macht.
Also habe ich den RAM mit 0xFF (mit memset, ausgeführt aus .init3) 
geflutet und einen Databreakpoint auf die geflutete Sektion angesetzt.
So, nachdem der Breakpoint getriggert wurde, schau ich in den Speicher 
und sehe folgendes:
1
data 0x0C94  ff ff ff ff ff ff ff ff ff ff 00 00 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ÿÿÿÿÿÿÿÿÿÿ..ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
2
data 0x0CB1  ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
3
data 0x0CCE  ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
4
data 0x0CEB  ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
5
data 0x0D08  ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
6
data 0x0D25  ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
7
data 0x0D42  ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
8
data 0x0D5F  ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff 00 00 ff ff ff ff ff ff ff ff ff ff ff  ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ..ÿÿÿÿÿÿÿÿÿÿÿ
9
data 0x0D7C  ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
10
data 0x0D99  ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
11
data 0x0DB6  ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
12
data 0x0DD3  ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
13
data 0x0DF0  ff ff ff ff ff ff ff ff ff ff ff 00 00 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ÿÿÿÿÿÿÿÿÿÿÿ..ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
14
data 0x0E0D  ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
15
data 0x0E2A  ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
16
data 0x0E47  ff ff ff ff ff ff ff ff ff ff ff ff ff 00 00 ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ÿÿÿÿÿÿÿÿÿÿÿÿÿ..ÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
17
data 0x0E64  ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
18
data 0x0E81  ff ff ff ff ff ff 00 00 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ÿÿÿÿÿÿ..ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
19
data 0x0E9E  ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
20
data 0x0EBB  ff ff ff ff 00 00 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff 00 00 ff  ÿÿÿÿ..ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ..ÿ
21
data 0x0ED8  ff ff ff ff ff ff ff ff ff ff ff ff 00 00 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ÿÿÿÿÿÿÿÿÿÿÿÿ..ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
22
data 0x0EF5  ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
23
data 0x0F12  ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
24
data 0x0F2F  ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
25
data 0x0F4C  ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
26
data 0x0F69  ff ff ff ff ff ff ff ff ff ff ff 00 00 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ÿÿÿÿÿÿÿÿÿÿÿ..ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
27
data 0x0F86  ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
28
data 0x0FA3  ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
29
data 0x0FC0  ff ff ff ff ff ff ff ff ff ff ff ff ff 00 00 ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ÿÿÿÿÿÿÿÿÿÿÿÿÿ..ÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
30
data 0x0FDD  ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
31
data 0x0FFA  ff ff ff ff ff ff 00 00 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ÿÿÿÿÿÿ..ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
32
data 0x1017  ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
33
data 0x1034  ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
34
data 0x1051  ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
35
data 0x106E  ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
36
data 0x108B  ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
37
data 0x10A8  ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ

wie man sieht "schiesst" mir hier irgendwas 16bit Nullfolgen in meinen 
RAM und zwar an zufälligen stellen. (ich habe das experiment wiederholt 
und es waren jedes mal andere Speicherpositionen)

Nun versuche ich herauszufinden, welche pointervariable dafür 
verantwortlich ist und komme nicht weiter... kann mir von euch jemand 
helfen?
Gibt es auch workarounds, falls ich den Pointer nicht finde oder nicht 
ändern kann?


viele Grüße

Alex


P.S. Alle Ideen zur Lösung des Problems sind willkommen (meine Deadline 
läuft Ende diesen Monats ab :/ )

von ich (Gast)


Lesenswert?

Zeile 2A ist der Fehler.
Des weiteren damit die Anderen es auch sehen, Source etc. wäre schon 
cool.
Bild des Aufbaues etc.
MfG
ich

von Peter D. (peda)


Lesenswert?

Korrelieren die Abstürze mit bestimmten Aktivitäten (CAN-Traffic usw.)?

Da hilft wohl nur, den Code abzuspecken, bis der Fehler nicht mehr 
auftritt.
Also Code halbieren, vierteln usw. d.h. binäre Suche.

von Peter D. (peda)


Lesenswert?

Testweise mal nen externen Quarzoszillator benutzen, nicht daß der Quarz 
rumzickt.

von Alex (Gast)


Lesenswert?

@ich (Gast)
Ich fragte nur nach einer Weiteren Vorgehensweise, nicht danach wo der 
Fehler steckt.

ich schrieb:
> Zeile 2A ist der Fehler.
> Des weiteren damit die Anderen es auch sehen, Source etc. wäre schon
> cool.
> Bild des Aufbaues etc.
> MfG
> ich

Würde euch die 160 files an code ja hochladen, um jedem jegliche 
Langeweile der nächsten Wochen zu nehmen, aber leider:
1
** This code is the property of HMS Industrial Networks AB.                   **
2
** The source code may not be reproduced, distributed, or used without        **
3
** permission. When used together with a product from HMS, permission is      **
4
** granted to modify, reproduce and distribute the code in binary form        **
5
** without any restrictions.                                                  **

Peter D. schrieb:
> Korrelieren die Abstürze mit bestimmten Aktivitäten (CAN-Traffic usw.)?
>
> Da hilft wohl nur, den Code abzuspecken, bis der Fehler nicht mehr
> auftritt.
> Also Code halbieren, vierteln usw. d.h. binäre Suche.

Ich sollte erwähnen, dass ich nur den SPI und GPIO pins nutze. Das sind 
die einzigen features die implementiert werden.
CAN benutze ich (noch) garnicht.

Code halbieren bzw. vierteln geht leider nicht, weil der Treiber 
Drittanbietersoftware ist und nur als Verbund funktioniert.

von Alex (Gast)


Lesenswert?

Der AT90 läuft auf einem ADV90CAN1 Developement board :( da is leider 
nix mit Quartz runterlöten.
Ansonsten geb ich dir recht.

von Hans (Gast)


Lesenswert?

Hi,

zuerst -Wextra -Wall im gcc einschalten und warnings durchforsten

dann statische codeanalyse probieren

mehrfach getestet != fehlerfrei...

73

von Andreas B. (buyman)


Lesenswert?

Wie schnell greift der Breakpoint? Du könntest dir ja ansehen was auf 
dem Stack los ist und so darauf schließen was vorher passiert ist.

von ich (Gast)


Lesenswert?

Naja, hast du einen Stand bei dem der Fehler nicht auftrat?
MfG
ich

von Peter D. (peda)


Lesenswert?

Alex schrieb:
> Die Software, welche ich benutze ist ein Professioneller Treiber von HMS
> Industrial Networks und laut deren Entwicklungsabteilung mehrmals
> getestet.

Getestet und Fehlerfreiheit sind verschiedenen Dinge.
Wurde auf dem AVR getestet (welcher) und benutzt Du den gleichen 
Compiler mit den gleichen Einstellungen (Optimierungslevel usw.)?

Entweder Du nimmst den Verkäufer der SW in die Pflicht oder debuggst 
selber.
Es scheint ja, daß Du die Sourcen hast und nicht nur die Lib.

Einfach ist Code teilen nicht. Man muß für die fehlenden Teile 
Simulatoren schreiben.

SPI ist auf den AVRs recht heikel, insbesondere der Slave-Mode ist fast 
unbenutzbar.

von Alex (Gast)


Lesenswert?

@buyman
Der Breakpoint greift schon bei .init3 allerdings werden zwischen zwei 
Trigger events größere Blöcke von Daten geschrieben (mit größer meine 
ich 261 Bytes). Also "verpasst" der debugger viele schreibvorgänge.

@Hans
Alles Klar, wird gemacht! :)

von Alex (Gast)


Lesenswert?

Peter D. schrieb:
> SPI ist auf den AVRs recht heikel, insbesondere der Slave-Mode ist fast
> unbenutzbar.

Das wäre nicht gut, was gibts da denn für Probleme?

von Peter D. (peda)


Lesenswert?

Alex schrieb:
> Das wäre nicht gut, was gibts da denn für Probleme?

Das AVR-SPI hat keinen Sendepuffer. Der Master muß also nach jedem Byte 
lange Gedenkpausen einlegen, damit der Slave garantiert mögliche andere 
Interrupts beenden kann, dann in den SPI-Interrupt springen und dann das 
zu sendende Byte aus dem RAM holen und endlich in das Schieberegister 
schreiben kann.
Würde der Master mit maximalem Takt laufen, hätte der AVR-Slave gerade 
mal einen halben SPI-Takt Zeit dafür.

Da hätte bei Atmel die AVR-Division mal ruhig von der 8051-Division 
abkupfern sollen.
Z.B. der AT89C51CC03 hat gepuffertes SPI und obendrein 4 
Prioritätslevel, um andere Interrupts sofort unterbrechen zu können:

"When a transmission is in progress a new data can be queued and sent as 
soon as transmission has been completed. So it is possible to transmit 
bytes without latency, useful in some applications."

Natürlich darf deshalb noch lange nicht eine Lib im SRAM unkontrolliert 
rumtrampeln, sondern sollte einfach nur einen Datenfehler signalisieren.

: Bearbeitet durch User
von H.Joachim S. (crazyhorse)


Lesenswert?

Hardware komplett tauschen ist auch ein guter Ansatz bei 
"unerklärlichen" Symptomen.

von Du (Gast)


Lesenswert?

Poste doch nur mal den Teil,in dem du die lib verwendest, ohne die lib. 
Vllt kann man da ja schon was erkennen...

von Alex (Gast)


Lesenswert?

PortA sind 8LEDs, die ich zum Debuggerlosen Fehlersuchen verwende.
Es gibt auch viele Debug features die troz des Auskommentierten 
debugStart noch aktiv sind.
Alles was mit "abcc", "ad" oder "appl" anfängt gehört zur Lib.
Die Reset funktion symbolisiert einen Resetwunsch des Geräts (deshalb 
wird kein wiklicher Reset ausgelöst), die Funktion wurde bisher aber nie 
aufgerufen.

Die Interrupt, welche ich unten abfange sind alle welche es gibt. Dies 
dient der Stabilität.
1
//#define debugStart
2
#define F_CPU 8000000
3
4
#include <avr/io.h>
5
#include <util/delay.h>
6
#include <stdlib.h>
7
#include <avr/interrupt.h>
8
9
#include "abcc_td.h"
10
#include "abcc.h"
11
#include "abcc_sys_adapt.h"
12
#include "ad_obj.h"
13
#include "appl_abcc_handler.h"
14
15
#include "abcc_spi_drv.h"  // NUR DEBUG, diese zeile samt der datei wieder entfernen! Dient einzig und allein dem Zugriff auf ABCC_DrvSpiGetAnybusState()
16
17
#define APPL_TIMER_MS    5
18
#define USE_TIMER_INTERRUPT  0
19
20
#if( USE_TIMER_INTERRUPT )
21
static void TimerIsr( void )
22
{
23
  ABCC_RunTimerSystem( APPL_TIMER_MS );
24
}
25
26
static void SetupTimerInterrupt( void )
27
{
28
}
29
#else
30
static void DelayMs( UINT32 lDelayMs )
31
{
32
  _delay_ms(lDelayMs);
33
}
34
#endif
35
36
static void Reset( void )
37
{
38
  while(1)
39
  {
40
    _delay_ms(500);
41
    PORTA = 0xFF;
42
  }
43
  
44
}
45
46
#ifdef debugStart
47
  uint32_t getHSFM();  // CUSTOM for diagnosis
48
  volatile uint32_t HSFM = 0;
49
  volatile uint8_t MCUSR_save = 0;
50
#endif
51
52
53
static void ERROR( void )
54
{
55
  while(1)
56
  {
57
    _delay_ms(1500);
58
    PORTA = ~PORTA;
59
    _delay_ms(500);
60
    PORTA = ~PORTA;
61
  }
62
  
63
}
64
65
__attribute__((naked, section(".init3"))) void myinit(void) 
66
{
67
  memset((void*)0x0bff,0xFF,0x02FF);
68
}
69
70
volatile unsigned char internalState = 0xFF;
71
int main()
72
{
73
  
74
  #ifdef debugStart
75
  //MCUSR_save = MCUSR;  // CUstom code diagnostic
76
  
77
  MCUSR &= ~(31);
78
  #endif
79
  
80
  DDRA = 0xFF;  // 8 LEDs zur statusanzeige des Systems
81
  
82
  #ifdef debugStart
83
    PORTA = MCUSR_save;
84
    _delay_ms(2000);
85
    PORTA = 0xFF;
86
    _delay_ms(2000);
87
    PORTA = 0;
88
    
89
  HSFM = getHSFM();
90
  #endif
91
   /*
92
   ** Make sure the ABCC reset signal is kept low by the platform specific
93
   ** initialization to keep the ABCC module in reset until the driver releases
94
   ** it.
95
   */
96
  volatile APPL_AbccHandlerStatusType eAbccHandlerStatus = APPL_MODULE_NO_ERROR;
97
98
  if( ABCC_HwInit() != ABCC_EC_NO_ERROR )
99
  {
100
    return( 0 );
101
  }
102
  PORTA |= 1;
103
  _delay_ms(1000);
104
  
105
#if( USE_TIMER_INTERRUPT )
106
  SetupTimerInterrupt();
107
#endif
108
109
  while( eAbccHandlerStatus == APPL_MODULE_NO_ERROR )
110
  {
111
    
112
    if ((PINE & (1<<PINE7)) == 0)
113
    {
114
      #ifdef debugStart
115
      HSFM = getHSFM();
116
      #endif
117
      
118
      PORTA = 0b11000000;
119
      break;
120
    }
121
    internalState = ABCC_DrvSpiGetAnybusState();
122
    eAbccHandlerStatus = APPL_HandleAbcc();
123
    
124
    PORTA &= 0b00011000;
125
    PORTA |= ((uint8_t)internalState); // Internal state auf den rechten LEDs, Handler state auf den linken LEDs
126
    PORTA |= (((uint8_t)eAbccHandlerStatus)<<5);
127
    
128
#if( !USE_TIMER_INTERRUPT )
129
    ABCC_RunTimerSystem( APPL_TIMER_MS );
130
    DelayMs( APPL_TIMER_MS );
131
#endif
132
133
    switch( eAbccHandlerStatus )
134
    {
135
      case APPL_MODULE_RESET:
136
        Reset();
137
        break;
138
      default:
139
        break;
140
    }
141
  }
142
  ABCC_ShutdownDriver();
143
  
144
145
  ERROR();
146
  return( 0 );
147
}
148
149
/*
150
ABCC handler status:
151
APPL_MODULE_NO_ERROR,         //   0 Module OK
152
APPL_MODULE_NOT_DETECTED,     //   1 No module plugged
153
APPL_MODULE_NOT_SUPPORTED,    //  10 Unsupported module detected
154
APPL_MODULE_NOT_ANSWERING,    //  11 Possible reasons: Wrong API selected, defect module
155
APPL_MODULE_RESET,            // 100 Reset requested from ABCC
156
APPL_MODULE_SHUTDOWN,         // 101 Shutdown requested
157
APPL_MODULE_UNEXPECTED_ERROR  // 110 Unexpected error occurred
158
*/
159
160
#ifdef debugStart
161
162
  // CUSTOM FUNKTION TO MEASURE HEAP/STACK free memory:
163
  uint32_t getHSFM()
164
  {
165
    volatile char *str;
166
    str = (volatile char*)malloc(1);
167
  
168
    volatile uint8_t stackVariable = 0xAA;
169
    volatile uint8_t*pointerToSV = &stackVariable;
170
  
171
    volatile uint32_t result = ( ((uint32_t)pointerToSV) - ((uint32_t)str) );
172
  
173
    free((void*)str);
174
  
175
    return result;
176
  
177
  }
178
179
#endif
180
181
void badISRError(uint8_t numb)
182
{
183
  #ifdef debugStart
184
  while(1)
185
  {
186
    PORTA = 0xAA;
187
    _delay_ms(2000);
188
    PORTA = debugItem1;
189
    _delay_ms(2000);
190
  }
191
  #endif
192
  
193
}
194
195
ISR(BADISR_vect)
196
{
197
  PORTA = 0xAA;
198
  cli();
199
  EIMSK = 0;
200
  //ERROR();
201
}
202
203
#ifdef debugStart
204
ISR(_VECTOR(1))
205
{
206
  badISRError(1);
207
}
208
209
ISR(_VECTOR(2))
210
{
211
  badISRError(2);
212
}
213
214
ISR(_VECTOR(3))
215
{
216
  badISRError(3);
217
}
218
219
ISR(_VECTOR(4))
220
{
221
  badISRError(4);
222
}
223
224
ISR(_VECTOR(5))
225
{
226
  badISRError(5);
227
}
228
229
ISR(_VECTOR(6))
230
{
231
  badISRError(6);
232
}
233
234
ISR(_VECTOR(7))
235
{
236
  badISRError(7);
237
}
238
239
ISR(_VECTOR(8))
240
{
241
  badISRError(8);
242
}
243
244
ISR(_VECTOR(9))
245
{
246
  badISRError(9);
247
}
248
249
ISR(_VECTOR(10))
250
{
251
  badISRError(10);
252
}
253
254
ISR(_VECTOR(11))
255
{
256
  badISRError(11);
257
}
258
259
ISR(_VECTOR(12))
260
{
261
  badISRError(12);
262
}
263
264
ISR(_VECTOR(13))
265
{
266
  badISRError(13);
267
}
268
269
ISR(_VECTOR(14))
270
{
271
  badISRError(14);
272
}
273
274
ISR(_VECTOR(15))
275
{
276
  badISRError(15);
277
}
278
279
ISR(_VECTOR(16))
280
{
281
  badISRError(16);
282
}
283
284
ISR(_VECTOR(17))
285
{
286
  badISRError(17);
287
}
288
289
ISR(_VECTOR(18))
290
{
291
  badISRError(18);
292
}
293
294
ISR(_VECTOR(19))
295
{
296
  badISRError(19);
297
}
298
299
ISR(_VECTOR(20))
300
{
301
  badISRError(20);
302
}
303
304
ISR(_VECTOR(21))
305
{
306
  badISRError(21);
307
}
308
309
ISR(_VECTOR(22))
310
{
311
  badISRError(22);
312
}
313
314
ISR(_VECTOR(23))
315
{
316
  badISRError(23);
317
}
318
319
ISR(_VECTOR(24))
320
{
321
  badISRError(24);
322
}
323
324
ISR(_VECTOR(25))
325
{
326
  badISRError(25);
327
}
328
329
ISR(_VECTOR(26))
330
{
331
  badISRError(26);
332
}
333
334
ISR(_VECTOR(27))
335
{
336
  badISRError(27);
337
}
338
339
ISR(_VECTOR(28))
340
{
341
  badISRError(28);
342
}
343
344
ISR(_VECTOR(29))
345
{
346
  badISRError(29);
347
}
348
349
ISR(_VECTOR(30))
350
{
351
  badISRError(30);
352
}
353
354
ISR(_VECTOR(31))
355
{
356
  badISRError(31);
357
}
358
359
ISR(_VECTOR(32))
360
{
361
  badISRError(32);
362
}
363
364
ISR(_VECTOR(33))
365
{
366
  badISRError(33);
367
}
368
369
ISR(_VECTOR(34))
370
{
371
  badISRError(34);
372
}
373
374
ISR(_VECTOR(35))
375
{
376
  badISRError(35);
377
}
378
379
ISR(_VECTOR(36))
380
{
381
  badISRError(36);
382
}
383
384
#endif

Die Initialisierung der Ports und ähnliches steckt in einer Callback 
funkton des Treibers und sieht folgendermaßen aus:
1
DDRB = (1<<0) | (1<<1) | (1<<2);  //SPI PINS
2
   DDRC = (1<<1);  // ABCC Reset Pin
3
   DDRC &= ~((1<<0) | (1<<3) | (1<<4) | (1<<5)); //MI1,MD1,MD0,MI0
4
   DDRD = 0;    // Later Interrupt pin
5
   DDRE &= ~(1<<7);
6
   
7
   PORTB |= (1<<0);
8
   
9
   PORTC = (3<<3);  // ABCC ModuleDetection Pins, aktiviere internen Pullup
10
   PORTC &= ~(1<<1);  //Pull reset Low
11
   
12
   PORTD = (1<<0);
13
   
14
   MCUCR &= ~(1<<PUD);    //Global-Pulldown-Disable = off (Pulldowns are enabled)
15
   EICRA = 0;        // Make sure that no external interrupt can be triggered
16
   EICRB = 0;
17
   EIMSK = 0;
18
   
19
   PORTE |= (1<<7);
20
   
21
   //CUSTOM: CODE: Pull down reset to activate it
22
   #ifdef SPI_RATE_4MHz
23
   SPCR = (1<<SPE) | (1<<MSTR) /*| (1<<CPOL) | (1<<CPHA)*/;// | (1<<SPR1);// | (1<<SPR0);// | (1<<SPIE);
24
   #endif
25
   
26
   #ifdef SPI_RATE_1MHz
27
   SPCR = (1<<SPE) | (1<<MSTR) /*| (1<<CPOL) | (1<<CPHA)*/ | (1<<SPR0);// | (1<<SPR0);// | (1<<SPIE);
28
   #endif
29
30
   #ifdef SPI_RATE_500kHz
31
   SPCR = (1<<SPE) | (1<<MSTR) /*| (1<<CPOL) | (1<<CPHA)*/ | (1<<SPR0);// | (1<<SPR1);// | (1<<SPIE);
32
   #endif
33
   
34
   #ifdef SPI_RATE_125kHz
35
   SPCR = (1<<SPE) | (1<<MSTR) /*| (1<<CPOL) | (1<<CPHA)*/ | (1<<SPR1) | (1<<SPR0);// | (1<<SPIE);
36
   #endif
37
   
38
   SPCR &= ~(1<<DORD);  // MSBit first
39
   
40
   #ifdef SPI_RATE_4MHz
41
   SPSR |= (1<<SPI2X);
42
   #endif
43
   
44
   #ifdef SPI_RATE_1MHz
45
   SPSR |= (1<<SPI2X);
46
   #endif
47
   
48
   #ifdef SPI_RATE_125kHz
49
   SPSR |= (1<<SPI2X);
50
   #endif
51
   
52
   return TRUE;

von Alex (Gast)


Lesenswert?

@crazyhorse:
Ich habe alle Hardware doppelt und vor kurzem mal ausgetauscht, leider 
hat sich dadurch absolut nichts geändert.

@Peda:
Guter Tip! Leider benutze ich keine Interrupts im Master. Und der Slave 
ist für mich ne black box...

von Peter D. (peda)


Lesenswert?

Hau erstmal den ganzen unnützen Kram raus, d.h. alle überflüssigen #if 
und #ifdef.
Und auch diese unnütze BadIsr Geraffel, oder triggert das etwa?

Du mußt schon etwas freundlich zu den Helfern sein und allen Füllstoff 
selber entfernen.

Alex schrieb:
> Die Initialisierung der Ports und ähnliches steckt in einer Callback
> funkton des Treibers und sieht folgendermaßen aus:

So auf keinen Fall, da muß schon ne Funktion darum stehen, sonst gibts 
vom Compiler was auf den Deckel.

von Alex (Gast)


Lesenswert?

Peter D. schrieb:
> Hau erstmal den ganzen unnützen Kram raus, d.h. alle überflüssigen #if
> und #ifdef.
> Und auch diese unnütze BadIsr Geraffel, oder triggert das etwa?

BadISR triggert. Obwohl Interrupts vom Treiber nicht gesetzt werden 
können (da der treiber die Register nicht kennt) und ich Interrupts 
explizit abschalte.

Peter D. schrieb:
> So auf keinen Fall, da muß schon ne Funktion darum stehen, sonst gibts
> vom Compiler was auf den Deckel.

Natürlich steht das in einer funktion, diese wird auch sauber 
aufgerufen. Und die ini läuft durch.
Der ganze Start funktioniert einwandfrei.

Alles klar, dann poste ich den code nochmals moment...

von Pandur S. (jetztnicht)


Lesenswert?

2 Kommentare von mir :
- nie dynamische Variablen verwenden
- nie Delays verwenden. Schon gar nicht in Interrupts.

von Peter D. (peda)


Lesenswert?

Alex schrieb:
> BadISR triggert.

Und warum sagst Du es dann nicht?
Welcher Vector, wo wird der enabled?
Du mußt schon alles ganz genau sagen, was beim Debuggen passiert. Wir 
können doch nicht hellsehen.

von Alex (Gast)


Lesenswert?

Oder D. schrieb:
> - nie dynamische Variablen verwenden
> - nie Delays verwenden. Schon gar nicht in Interrupts.

1. Ok
2. Das triggern eines Interrupts in meiner anwendung stellt einen 
schweren fehler dar, das Programm soll an der Stelle festgehalten werden 
und die LEDs müssen den Fehler eindeutig anzeigen.

von Alex (Gast)


Lesenswert?

Hier nochmal der Code mit allen #ifdefs entfernt
1
#define F_CPU 8000000
2
3
#include <avr/io.h>
4
#include <util/delay.h>
5
#include <stdlib.h>
6
#include <avr/interrupt.h>
7
8
#include "abcc_td.h"
9
#include "abcc.h"
10
#include "abcc_sys_adapt.h"
11
#include "ad_obj.h"
12
#include "appl_abcc_handler.h"
13
14
#include "abcc_spi_drv.h"  // NUR DEBUG, diese zeile samt der datei wieder entfernen! Dient einzig und allein dem Zugriff auf ABCC_DrvSpiGetAnybusState()
15
16
#define APPL_TIMER_MS    5
17
#define USE_TIMER_INTERRUPT  0
18
19
static void DelayMs( UINT32 lDelayMs )
20
{
21
  _delay_ms(lDelayMs);
22
}
23
24
static void Reset( void )
25
{
26
  while(1)
27
  {
28
    _delay_ms(500);
29
    PORTA = 0xFF;
30
  }
31
  
32
}
33
34
static void ERROR( void )
35
{
36
  while(1)
37
  {
38
    _delay_ms(1500);
39
    PORTA = ~PORTA;
40
    _delay_ms(500);
41
    PORTA = ~PORTA;
42
  }
43
  
44
}
45
46
__attribute__((naked, section(".init3"))) void myinit(void) 
47
{
48
  memset((void*)0x0bff,0xFF,0x02FF);
49
}
50
51
volatile unsigned char internalState = 0xFF;
52
int main()
53
{
54
  
55
  DDRA = 0xFF;  // 8 LEDs zur statusanzeige des Systems
56
57
  volatile APPL_AbccHandlerStatusType eAbccHandlerStatus = APPL_MODULE_NO_ERROR;
58
59
  if( ABCC_HwInit() != ABCC_EC_NO_ERROR )
60
  {
61
    return( 0 );
62
  }
63
  PORTA |= 1;
64
  _delay_ms(1000);
65
  
66
  while( eAbccHandlerStatus == APPL_MODULE_NO_ERROR )
67
  {
68
    
69
    if ((PINE & (1<<PINE7)) == 0)
70
    {
71
      #ifdef debugStart
72
      HSFM = getHSFM();
73
      #endif
74
      
75
      PORTA = 0b11000000;
76
      break;
77
    }
78
    internalState = ABCC_DrvSpiGetAnybusState();
79
    eAbccHandlerStatus = APPL_HandleAbcc();
80
    
81
    PORTA &= 0b00011000;
82
    PORTA |= ((uint8_t)internalState); // Internal state auf den rechten LEDs, Handler state auf den linken LEDs
83
    PORTA |= (((uint8_t)eAbccHandlerStatus)<<5);
84
    
85
    ABCC_RunTimerSystem( APPL_TIMER_MS );
86
    DelayMs( APPL_TIMER_MS );
87
88
    switch( eAbccHandlerStatus )
89
    {
90
      case APPL_MODULE_RESET:
91
        Reset();
92
        break;
93
      default:
94
        break;
95
    }
96
  }
97
  ABCC_ShutdownDriver();
98
  
99
100
  ERROR();
101
  return( 0 );
102
}
103
104
/*
105
ABCC handler status:
106
APPL_MODULE_NO_ERROR,         //   0 Module OK
107
APPL_MODULE_NOT_DETECTED,     //   1 No module plugged
108
APPL_MODULE_NOT_SUPPORTED,    //  10 Unsupported module detected
109
APPL_MODULE_NOT_ANSWERING,    //  11 Possible reasons: Wrong API selected, defect module
110
APPL_MODULE_RESET,            // 100 Reset requested from ABCC
111
APPL_MODULE_SHUTDOWN,         // 101 Shutdown requested
112
APPL_MODULE_UNEXPECTED_ERROR  // 110 Unexpected error occurred
113
*/
114
115
void badISRError(uint8_t numb)
116
{
117
  
118
}
119
120
ISR(BADISR_vect)
121
{
122
  PORTA = 0xAA;
123
  cli();
124
  EIMSK = 0;
125
  //ERROR();
126
}

Alles zusammen:
Also BADISR wird getriggert vom externen Interrupt 6 und 7.
Diese setze ich aber im Verlauf der ini 0 (EIMSK)

Der Program counter des µC geht zu scheinbar zufälligen Zeitpunkten auf 
den Reset Vector. Allerdings wird kein Flag in MCUSR gesetzt. Den Stack 
kann ich sehen aber nicht deuten (Google weiß nicht wie man eine 
Rücksprungadresse von Bytefoo unterscheidet und wie man sie einer 
Funktion zuordnet oder ich hab keine ahnung nach was ich suchen soll)

Die SPI Kommunikation welche ich hier realisiere gibt NIE eine valide 
Prüfsumme zurück, obwohl ich die Frames überprüft habe und sie eindeutig 
stimmen. Auch die Bitreihenfolge und die Bytereihenfolge sind richtig, 
ebenfalls ist der Inhalt der Frames gültig.

Die Ausführungszeit des Programms verlangsamt sich manchmal extrem 
(~Faktor 10000).

Ebenfalls meldet mir der Treiber manchmal (nur manchmal), dass meine 
Peripherie defekt sei. Was definitiv nicht der Fall ist (ich habe die 
Hardware mehrfach ausgetauscht).

So, ich denke, dass dies alles folgen eines "Amoklaufenden" etwas im RAM 
ist.
Aus diesem Grund habe ich die eben genannten Punkte nicht im 
Originalpost aufgeführt.

Ich hoffe ich habe nichts vergessen

von Uwe (Gast)


Lesenswert?

Hi,
>Also BADISR wird getriggert vom externen Interrupt 6 und 7.
hast du an was gemerkt?
hast du mal das I-Flag bei Eintritt in die "ISR(BADISR_vect)"getestet?
nicht das "Interrupt 6 und 7" einfach "nur" ein Sprungziel war.
Das braucht auf jeden Fall etwas Geduld und eine gute Strategie.
Übrigens wenn ich mal sowas suchen muss haben meine Programmmodule 
Durchlaufzahlen in einem Register und ich kann nachher schauen wo das 
Prog. kurz vorher war.

Viel Erfolg, Uwe

von R. F. (rfr)


Lesenswert?

Ich habe ein Problem ähnlichen Auftretens gehabt, als Ursache stellten 
sich spikes auf der Versorgung heraus. Beim simulieren habe ich die 
Spannung langsam (!) heruntergeregelt und dann pulsartig wieder hoch.

Die bits im MCUSR waren alle low. Der Prozessor resette sich, dies 
konnte gezielt durch das sprungartige hochsetzen der Spannung von 
lowlevel aus erreicht werden, auch reproduzierbar.

Das ist allerdings lange her.

Grüsse.

Robert

von Alex (Gast)


Lesenswert?

Ich habe rausgefunden, dass der Treibercode vom Hersteller auf einem 32 
Bit MCU getestet wurde. Ich verwende allerdings einen 8Bitter.
Nach was muss ich ausschau halten wenn ich den Code Portieren möchte? 
Oder was für Probleme soll ich erwarten?

von Peter D. (peda)


Lesenswert?

Alex schrieb:
> Nach was muss ich ausschau halten wenn ich den Code Portieren möchte?

Alle int durch long int ersetzen oder besser durch int32_t bzw. 
uint32_t.

von B. S. (bestucki)


Lesenswert?

Alex schrieb:
> Ich habe rausgefunden, dass der Treibercode vom Hersteller auf einem 32
> Bit MCU getestet wurde. Ich verwende allerdings einen 8Bitter.
> Nach was muss ich ausschau halten wenn ich den Code Portieren möchte?
> Oder was für Probleme soll ich erwarten?

Auf alles, das sich auf die absolute oder minimale Breite eines 
Datentyps verlässt. Prüfen würde ich sicher alle "nackten" Typen, also 
short, int, long und long long. Ausserdem, ob die (u)int_fastXX_t Typen 
in den Berechnungen wirklich nur XX Bits benötigen. Berechnungen werden 
grundsätzlich in int oder grösser ausgeführt, da könnte ein Cast nach 32 
Bit fehlen, wo einer nötig ist.

von Alex (Gast)


Lesenswert?

Peter D. schrieb:
> Alex schrieb:
>> Nach was muss ich ausschau halten wenn ich den Code Portieren möchte?
>
> Alle int durch long int ersetzen oder besser durch int32_t bzw.
> uint32_t.

Das war der entscheidende Hinweis! Vielen vielen Dank! Alle Probleme mit 
dem At90 haben sich nun bustäblich in Luft aufgelöst. Habe die 
Datentypen durch die jeweiligen (u)intXX_t ersetzt (außer float) und es 
geht!

So nebenbei, was ist der unterschied zwischen unsigned char und uint8_t? 
Bzw. short, long usw. worin unterscheiden die sich zu den (u)intXX_t 
datentypen?

von Cyblord -. (cyblord)


Lesenswert?

Alex schrieb:

>
> So nebenbei, was ist der unterschied zwischen unsigned char und uint8_t?
> Bzw. short, long usw. worin unterscheiden die sich zu den (u)intXX_t
> datentypen?

Merkwürdig dass du das noch nicht verstanden hast, da genau hier ja dein 
Problem lag und jetzt beseitigt wurde. Da müsste dir ein Licht aufgehen.

Schau dir einfach mal die Definition der uintXX_t Datentypen an.

uintXX_t geben eine feste Bitlänge an und werden dann je nach Zielsystem 
auf die nativen Datentypen (char, int, Long usw.) gemappt). Es ist also 
nur eine hardwareübergreifende Möglichkeit Datentypen mit spezifischer 
Bitbreite angeben zu können.

von Alex (Gast)


Lesenswert?

Danke ;)
Ein Erfahrener kann in einem Dialog mehr Infos und Erfahrung mitteilen 
als in ein Fachbuch passt. Deshalb hab ich nochmal nachgefragt.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.