mikrocontroller.net

Forum: FPGA, VHDL & Co. SJA1000 ansteuern?


Autor: Steffen Hausinger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo zusammen,

ich habe arge Probleme, eine CAN-Kommunikation mit dem SJA1000 
aufzubauen. Grundsätzlich passt alles, aber sporadisch kommt es zu 
Aussetzern bei der Übertragung. Hierbei werden Empfangsbytes fehlerhaft 
eingelesen, die aber vorher nachweisbar korrekt auf dem CAN-Bus lagen.

Da der SJA über ein bidirektionalen Datenbus verfügt, vermute ich stark, 
dass es Probleme mit der Datenrichtung gibt. Aber was ich auch probiere, 
ich komme nicht dahinter, wo genau der Fehler liegt.

Hier meine Beschreibung:
    if Trans_CE = true and rising_edge(CLK_100MHz) then  -- Besteht eine Freigabe, synchron zum Takt arbeiten
      case StateMachine is                      -- Übertragung fortführen
        when 0 =>                          -- t = 00 ns
          AD <= Address;                      -- Adresse anlegen
          AS <= '1';                        -- Übernahme der Adresse vorbereiten
        when 2 =>                          -- t = 20 ns
          AS <= '0';                        -- Adresse übernehmen
        when 3 =>                          -- t = 30 ns
          AD <= "ZZZZZZZZ";                    -- Adresse wieder vom Bus nehmen
        when 4 =>                          -- t = 40 ns
          nWR <= RDnWR;                      -- Übertragungsrichtung übernehmen
          nCS <= '0';                        -- Baustein auswählen
        when 5 =>                          -- t = 50 ns
          E <= '1';                        -- Freischaltung der Daten setzen
          if RDnWR = '0' then                  -- Wollen wir Daten schreiben, ...
            AD <= Data_out;                  -- ...sie jetzt aufschalten
          end if;                          --
        when 11 =>                          -- t = 110 ns
          if RDnWR = '1' then                  -- Wollen wir lesen, ...
            Data_in <= AD;                    -- ...Daten jetzt übernehmen
          end if;                          --
          E <= '0';                        -- Freischaltung der Daten auf Low ziehen
        when 14 =>                          -- t = 140 ns
          AD <= "ZZZZZZZZ";                    -- Daten vom Bus nehmen
          nCS <= '1';                        -- Baustein nicht auswählen
          nWR <= '0';                        -- Übertragungsrichtung "Schreiben" (da als nächstes wieder mit dem Schreiben der Adresse begonnen wird)
          StateMachine := -1;                  -- Abarbeitung beenden
        when others =>                        -- Zu allen anderen Zeitpunkten...
          null;                            -- ...nichts unternehmen
      end case;                            --
      StateMachine := StateMachine + 1;            -- Zur nächsten Zeitmarke wechseln
      
      if StateMachine /= 0 then
        Busy <= '1';
      else
        Busy <= '0';
      end if;
    end if;

Die Pegelwandlung habe ich mit einem 74LVC245 gelöst (siehe 
Beitrag "Re: Anschluß des SJA1000 an FPGA-Pins").


Kann jemand erkennen, wo hier der Fehler liegt? Oder hat jemand einen 
Beispielcode für mich?

Grüße
Steffen

Autor: Martin R. (herki)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo

Wie oft spinnt er denn?

Du hast in dem Code nirgends angegeben wo du die Statemachinevariable 
(den Zeitpunkt in ns) wieder zurücksetzt.

Ich bin auch nicht so ganz firm drin aber ich denke, dass es vielleicht 
was mit der Zählervariable zu tun hat.

Du hast auch in dem jetzigen Code Variablen keinen Initiierungszustand 
wie z.B. nCS, RDnWR angegeben. (Ich hoffe Du hast das irgendwo gemacht)
Ich würde auch irgendwo einen Nullzustand definieren.

VG

Martin

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Kann dein Design überhaupt grundsätzlich mit 100 MHz laufen?
Hast du entsprechende Constraints gesetzt?
Du rechnest zwar hübsch in 10 ns-Schritten, aber das ist schon fast die 
Laufzeit der Signale aus dem FPGA heraus und wieder hinein, dazu kommt 
dann noch das Layout...

Welches FPGA?
Welche Toolchain?

> Grundsätzlich passt alles, aber sporadisch kommt es zu
> Aussetzern bei der Übertragung.
Hört sich dann immer nach Timingverletzungen beim Übergang zwischen 
Taktdomänen an...
Oder alternativ ein asynchroner kombinatorischer Reset...

Poste doch mal etwas mehr Code

Autor: Steffen Hausinger (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hallo

Er spinnt ungefähr alle 25 CAN-Nachrichten und damit alle 250 
Übertragungen zum SJA1000. Es tritt aber meistens an der selben Stelle 
auf. Die Initiierung findet, wir Du jetzt unten sehen kannst, in der 
Deklaration der Entity statt.

Ich denke, es liegt nicht an der Taktgeschwindigkeit des FPGA. Ich habe 
probeweise die "StateMachine"-Zählstande um das 10fache erhöht (siehe 
unten) und der Fehler tritt nach wie vor auf. Was genau meinst Du mit 
"Taktdomänen"? Bei mir existieren insofern keine verschiedenen Takte, 
als dass der FPGA der Master ist und sich der SJA als Slave danach 
richtet...

Hier mein kompletter Code:
-- Description: Sendet die Eingangsdaten an den SJA1000. Der Start der Übertragung muss mit "Start" ein-
--           malig getriggert werden (Übernahme bei steigender Taktflanke). Anschließend geht "Busy"
--           auf High und die Übertragung beginnt. Währenddessen dürfen sämtliche die Eingangsdaten
--           NICHT verändert werden (kein internes Latch vorhanden!). Nachdem die Daten übertragen
--           wurden, geht "Busy" wieder auf Low und es können weitere Daten übertragen werden.
--
--           Bleibt "Start" permanent auf High, werden permanent die Eingangsdaten übertragen, bis
--           es wieder auf Low geht. Erst wenn dies der Fall ist, wird die Übertragung regulär
--           beendet.

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;


entity SJA_IF is
    Port (  -- SJA1000
        AD : inout  STD_LOGIC_VECTOR (7 downto 0) := "ZZZZZZZZ";  -- Gemultiplexter Adress- und Datenbus
        AS : out  STD_LOGIC := '0';                    -- Übernahme der Adresse
        nWR : out  STD_LOGIC := '0';                    -- Transferrichtung (1 = Lesen, 0 = Schreiben)
        E : out  STD_LOGIC := '0';                      -- Freischaltung
        nCS : out  STD_LOGIC := '1';                    -- Bausteinauswahl
        -- Interface zur übergeordneten Ebene
        Address : in STD_LOGIC_VECTOR(7 downto 0);          -- Adresse
        Data_out : in STD_LOGIC_VECTOR(7 downto 0);          -- Zu schreibende Daten
        Data_in : out STD_LOGIC_VECTOR(7 downto 0) := "XXXXXXXX"; -- Ausgelesene Daten
        RDnWR : in STD_LOGIC;                        -- Übertragungsrichtung (0 = Schreiben, 1 = Lesen)
        Start : in boolean;                          -- Aufforderung zum Start der Übertragung
        Busy : out STD_LOGIC := '0';                    -- Aktivitätsstatus der Einheit
        -- Sonstiges
        CLK_100MHz : in STD_LOGIC                      -- Takt (Frequenz = 100 MHz)
      );
end SJA_IF;

architecture Behavioral of SJA_IF is

begin

  -- Übertragung starten/fortführen
  TRANSMISSION : process(CLK_100MHz, Start, RDnWR)
    variable Trans_CE : boolean := false;
    variable StateMachine : integer := 0;
  begin
    Trans_CE := Start or (StateMachine /= 0);
  
    if Trans_CE = true and rising_edge(CLK_100MHz) then  -- Besteht eine Freigabe, synchron zum Takt arbeiten
      case StateMachine is                      -- Übertragung fortführen
        when 0 =>                          -- t = 00 ns
          AD <= Address;                      -- Adresse anlegen
          AS <= '1';                        -- Übernahme der Adresse vorbereiten
        when 20 =>                          -- t = 20 ns
          AS <= '0';                        -- Adresse übernehmen
        when 30 =>                          -- t = 30 ns
          AD <= "ZZZZZZZZ";                    -- Adresse wieder vom Bus nehmen
        when 40 =>                          -- t = 40 ns
          nWR <= RDnWR;                      -- Übertragungsrichtung übernehmen
          nCS <= '0';                        -- Baustein auswählen
        when 50 =>                          -- t = 50 ns
          E <= '1';                        -- Freischaltung der Daten setzen
          if RDnWR = '0' then                  -- Wollen wir Daten schreiben, ...
            AD <= Data_out;                  -- ...sie jetzt aufschalten
          end if;                          --
        when 110 =>                          -- t = 110 ns
          if RDnWR = '1' then                  -- Wollen wir lesen, ...
            Data_in <= AD;                    -- ...Daten jetzt übernehmen
          end if;                          --
          E <= '0';                        -- Freischaltung der Daten auf Low ziehen
        when 140 =>                          -- t = 140 ns
          AD <= "ZZZZZZZZ";                    -- Daten vom Bus nehmen
          nCS <= '1';                        -- Baustein nicht auswählen
          nWR <= '0';                        -- Übertragungsrichtung "Schreiben" (da als nächstes wieder mit dem Schreiben der Adresse begonnen wird)
          StateMachine := -1;                  -- Abarbeitung beenden
        when others =>                        -- Zu allen anderen Zeitpunkten...
          null;                            -- ...nichts unternehmen
      end case;                            --
      StateMachine := StateMachine + 1;            -- Zur nächsten Zeitmarke wechseln
      
      if StateMachine /= 0 then
        Busy <= '1';
      else
        Busy <= '0';
      end if;
    end if;
  end process;
  

end Behavioral;

Im Anhang eine Messung zu dem Fehler. Mir fallen zwei Dinge auf:

(1) Zu sehen ist, dass der bidirektionale AD-Bus nach dem Umschalten der 
Signalrichtung "springt". Die Abtastrate der Messung beträgt 20 ns und 
ist damit weit größer als irgendwelche Skew-Raten des SJA oder des 
LVC245. Trotzdem macht er solche Mätzchen. (Die macht er aber nicht 
immer, auch wenn sie im nächsten Datenzugriff wieder zu sehen sind.)

(2) Der SJA meldet 20h zurück. Auf dem CAN-Bus lag aber definitiv 00h an 
(gemessen mit einer CAN-Card). Warum haut er mir da also 20h raus? Es 
schaut wie ein Fehler des SJA aus, aber es wird eher an der fehlerhaften 
Ansteuerung liegen.


Habt ihr eine Vermutung, was hier schief läuft?

Grüße
Steffen

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Noch unbeantwortet:
Kann dein Design überhaupt 100 MHz?

> Der SJA meldet 20h zurück.
Immer?
> Der SJA meldet 20h zurück.
Wie sieht das Signal auf dem AD-Bus aus?
Irgendwelche verdächtigen Über- oder Unterschwinger?

Autor: Steffen Hausinger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Lothar Miller schrieb:
> Kann dein Design überhaupt 100 MHz?

100 MHz sind das Ziel. So weit bin ich aber noch gar nicht gekommen. 
Denn wie geschrieben, funktioniert das Design nicht einmal mit einem 
Zehntel (und übrigens auch nicht mit einem Zwanzigstel) des Takts. Und 
bei diesem Takt sehe ich ja mit dem Logic Analyzer, dass die 
Steuerleitungen wie gewünscht arbeiten. Nur der Datenbus leider nicht...


Lothar Miller schrieb:
>> Der SJA meldet 20h zurück.
> Immer?

Nein, nicht immer. Mal sind es 0Ch, mal eben auch die erwarteten 00h.


Lothar Miller schrieb:
> Wie sieht das Signal auf dem AD-Bus aus?
> Irgendwelche verdächtigen Über- oder Unterschwinger?

Ja das ist ein guter Punkt. Ich weiß es leider nicht. Bevor ich mich 
darum kümmere, möchte ich ersteinmal abschätzen, ob der Fehler in 
Richtung Hardware oder in Richtung Software zu suchen ist. Denn ich 
komme leider nicht so leicht an ein Oszilloskop heran :-(


Ist meine Beschreibung denn grundsätzlich so in Ordnung? Beispielsweise 
das Umschalten der Adressleitungen auf Tristate? Muss ich am FPGA noch 
irgendetwas umstellen? Interne Pull-Up Widerstände? Was ist mit der 
Driving Strength? Kann man da irgendetwas falsch machen?

Grüße
Steffen

Autor: Steffen Hausinger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ach so, ebenfalls noch unbeantwortet war:

FPGA: Spartan 3e
Toolchain: Xilinx ISE 11.1

Autor: me (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Randbemerkung:
du kämst mit der Häfte an Platz für die SM aus, wenn du
"variable StateMachine : integer range -1 to 140 := 0;" schreiben 
würdest, aber gehört hier ja nicht direkt her...

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> du kämst mit der Häfte an Platz für die SM aus
Oder gar nur ein Viertel vom Platz (1 Byte gegenüber 4 Bytes)...


Die Frage, die eigentlich leicht zu beantworten ist, ist:
>>>> rising_edge(CLK_100MHz)
Kann dein Design die 100MHz?
Hast du ein Constraint auf diesen Takt?

>> Wie sieht das Signal auf dem AD-Bus aus?
> Ich weiß es leider nicht.
> Denn ich komme leider nicht so leicht an ein Oszilloskop heran :-(
Darn solltest du arbeiten...
Wenn du Signale im 10ns Bereich erzeugen willst, dann brauchst du ganz 
einfach ein (wenn möglich recht schnelles) Oszi.

Autor: Steffen Hausinger (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Ok, also ich habe mich inzwischen mit der Taktfrequenz 
auseinandergesetzt.

(1) Laut Oszi benötigt Flanke FPGA -> SJA ungefähr 10 ns (0 -> 3V), die 
Flanke SJA -> FPGA ungefähr 18 ns (0 -> 5V). Beide Messwerten stammen 
von der 5V-Seite. Siehe Anhang.

(2) Hinzu kommt noch die Verzögerung durch den Level-Shifter (74LVC245). 
Laut Datenblatt kann ich hier mit 6,1 ns im Worst Case rechnen.

(3) Das Timing für meine Beschreibung sieht im Moment folgendermaßen 
aus:
----------------------------------------------------------------------------------------------------------
  Constraint                                |    Check    | Worst Case |  Best Case | Timing |   Timing   
                                            |             |    Slack   | Achievable | Errors |    Score   
----------------------------------------------------------------------------------------------------------
  TS_CLK = PERIOD TIMEGRP "CLK" 50 MHz HIGH | SETUP       |     0.668ns|    19.332ns|       0|           0
   40%                                      | HOLD        |     0.741ns|            |       0|           0
------------------------------------------------------------------------------------------------------
  TIMEGRP "SJA_In" OFFSET = IN 3 ns VALID 2 | SETUP       |     0.741ns|     2.259ns|       0|           0
  0 ns BEFORE COMP "CLK" "RISING"           | HOLD        |    15.493ns|            |       0|           0
------------------------------------------------------------------------------------------------------
  TIMEGRP "SJA_Out" OFFSET = OUT 15 ns AFTE | MAXDELAY    |     4.314ns|    10.686ns|       0|           0
  R COMP "CLK"                              |             |            |            |        |            
------------------------------------------------------------------------------------------------------
  TIMEGRP "CLK" OFFSET = IN 6 ns VALID 20 n | N/A         |         N/A|         N/A|     N/A|         N/A
  s BEFORE COMP "CLK" "RISING"              |             |            |            |        |            
------------------------------------------------------------------------------------------------------


Zusammengefasst wird es voraussichtlich nicht für 100 MHz reichen. 
Allerdings habe ich die Taktfrequenz im Zuge meiner Fehlersuche ja schon 
längst auf ein Zwanzigstel, also auf 5 MHz, heruntergefahren:

- Die "CLK_100MHz" werden nun mit 50 MHz gespeist.
- Die Zeitpunkte in der StateMachine habe ich verzehnfacht.

Damit habe ich für den kürzesten Schritt eine Dauer von 200 ns zur 
Verfügung. Meine Verzögerungen betragen einen Bruchteil dieses Werts. 
Aber trotzdem ändert das nichts an meinem Fehler :-(



Das Bild im Anhang stammt von meinem alten DSO. Besser geht es leider 
nicht. Ein Triggern auf den Fehler ist damit nicht möglich, die Flanken 
stammen von einem anderen Zeitpunkt. Die Betriebsspannungen habe ich 
natürlich auch gemessen. Sowohl die 3V als auch die 5V sehen sauber aus. 
Kein Ripple, kein Einbrechen beim Senden. Ich habe auch an jedem IC 
einen 100 nF KerKo und am Eingang einen 2 µF ElKo.


Was kann ich jetzt tun? Sind meine Constraints denn in Ordnung? Ist 
irgendetwas auffällig an meiner Beschreibung oder an meinen Messungen?


Grüße
Steffen

P.s.: Danke für den Tipp mit der "range"-Angabe!

Autor: Steffen Hausinger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Noch ein Hinweis zu den Timing-Angaben:

CLK = CLK_100MHz, da ich ja inzwischen keinen DCM zur Erhöhung auf 100 
MHz mehr einsetze.

Autor: bko (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Darüber bin ich nun gestolpert:

start ist in der Prozess sentitivity list und dann
in der Zeile mit dem  rising_edge clock,  was bezweckst
du damit und was macht die Synthese daraus ?

> -- Übertragung starten/fortführen
>  TRANSMISSION : process(CLK_100MHz, Start, RDnWR) <<-- start
>    variable Trans_CE : boolean := false;
>    variable StateMachine : integer := 0;
>  begin
>    Trans_CE := Start or (StateMachine /= 0);    <<-- verknüpft
>
>    if Trans_CE = true and rising_edge(CLK_100MHz) then <<-- und takt

geht evtl. sowas:

if Trans_CE = true THEN
   StateMachine := StateMachine + 1;

Autor: Steffen Hausinger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Stimmt, ist mir gar nicht aufgefallen. Dabei muss es sich noch um ein 
Relikt aus einer früheren Version handeln. Das "RDnWR" ist ja auch 
völlig deplaziert.

Grundsätzlich kann aber alles aus der Sensivity List weg. Es passiert 
schließlich eh nur dann etwas, wenn eine steigende Flanke von CLK_100MHz 
vorliegt. Dann wird auch "Trans_CE" neu berechnet.

Autor: Steffen Hausinger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich habe inzwischen herausgefunden, dass es sich definitv um ein 
Übertragungsproblem zwischen SJA und FPGA handeln muss. Lese ich das 
fehlerhafte Datenbyte ein zweites Mal aus dem SJA aus, bekomme ich den 
richtigen Wert zurück.

Es ist wie verhext. Ich stehe jetzt schon zwei geschlagene Tage vor 
diesem Fehler und komme einfach nicht weiter :-(

Wie sind denn meine Timing Angaben oben einzuschätzen? Ist da alles in 
Ordnung?

Autor: Martin R. (herki)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi

Wie weit bist Du denn nun?

Was hast Du denn für Constraints bezüglich Slew-Rate (ucf-File: Net 
"port_netname" {FAST oder SLOW}; )


Bin selber noch Student und habe da noch wenig Erfahrung... Es sind 
alles nur Vermutungen.


VG

Martin

Autor: Steffen Hausinger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Martin,

bezüglich Slew-Rate habe ich gar nichts in meinen Constraints stehen => 
Default ist slow.

Inzwischen schließe ich aber Timing-Probleme aus. Zum einen kann ich, 
wie oben bereits erwähnt, mit dem Logic Analyzer die Daten genau 
beobachten. Das Timing ist meines Erachtens korrekt, aber trotzdem gibt 
der SJA1000 ein falsches Datenbyte aus. Zum anderen kann ich das Timing 
bis in den Milisekundenbereich verzögern und es funktioniert trotzdem 
noch nicht.

Ich halte es für möglich, dass der SJA defekt ist. Das ist das einzige, 
was mir dazu noch einfällt...

Grüße
Steffen

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Übernimmt er evtl. die Adresse falsch?
Und du liest so zwar die richtigen Daten, aber von der falschen 
Adresse...

Autor: Besserwisser (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Abschlusswiderstände des CAN-Busses schon überprüft ?

Autor: Steffen Hausinger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Besserwisser schrieb:
> Übernimmt er evtl. die Adresse falsch?
> Und du liest so zwar die richtigen Daten, aber von der falschen
> Adresse...

Das Kuriose ist ja, dass das Auslesen nur sporadisch fehlschlägt. Und 
spätestens beim zweiten Auslesen kommen auch die richtigen Daten zurück. 
Daraus schließe ich, dass meine Logik grundsätzlich richtig ist. Auch 
bezüglich der Adresse.

Zusammengefasst bleiben als Fehlerquellen...

...das Timing -> das schließe ich inzwischen jedoch aus.
...die Spezifikation wird verletzt (Beispiel: SJA sendet schon, der 
Pegelshifter ist aber noch nicht in der Richtung umgeschaltet) -> x-mal 
überprüft.
...das Layout ist schlecht -> schon alles nachgelötet, aber Lochraster 
bleibt Lochraster (darauf ist meine "Sendeeinheit" aufgebaut)
...SJA1000 ist defekt


Besserwisser schrieb:
> Abschlusswiderstände des CAN-Busses schon überprüft ?

Ja, aber das ist es leider auch nicht. Ich habe die Nachricht händisch 
mit dem Logic Analyzer dekodiert. Sie ist eindeutig so, wie ich sie 
sende. Des Weiteren habe ich mir eine professionelle CAN-Karte 
ausgeliehen. Auch sie zeigt mir die richtigen Daten.



Ich bin nun momentan dabei, mir ein Layout für eine richtige Platine 
anzufertigen. Dann kaufe ich mir alle Bauteil noch einmal neu und werde 
alles sauber aufbauen. Mal schauen, wie die Sache dann aussieht!


Euch allen danke ich für Eure vielen Tipps!!
Steffen

Autor: Michael O. (mischu)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Fragen:

1. In welchem Mode läuft der SJA1000?? (Intel / Motorola)

Dein Timingdiagramm sieht sehr seltsam aus! Zumindest müsste /CS sowohl 
beim Lesen als auch Schreiben aktiv sein.

Autor: Steffen Hausinger (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Es läuft im Motorola-Mode. Laut Datenblatt wird CS beim Zugriff auf das 
Datenbyte aktiviert...

Autor: Michael O. (mischu)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Aber wenn Du dir deine Statemachine mal anschaust wirst du sehen, dass 
Du /CS nur zum lesen aktivierst.

Beim Schreiben (siehe unten) fehlt das /CS. Somit ist der Baustein nicht 
korrekt beschrieben. Schau dir das Timing und deine Implemtation nochmal 
an.

> case StateMachine is                      -- Übertragung fortführen
>         when 0 =>                          -- t = 00 ns
>           AD <= Address;                      -- Adresse anlegen
>           AS <= '1';                        -- Übernahme der Adresse vorbereiten
>         when 2 =>                          -- t = 20 ns
>           AS <= '0';                        -- Adresse übernehmen
>         when 3 =>                          -- t = 30 ns
>           AD <= "ZZZZZZZZ";                    -- Adresse wieder vom Bus nehmen
>         when 4 =>                          -- t = 40 ns

Autor: Michael O. (mischu)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sorry, vergiss meinen letzten Post....

Autor: Steffen Hausinger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Michael O. schrieb:
> Sorry, vergiss meinen letzten Post....

Jeder Tipp ist willkommen!

Hast Du Dich schon mit der Ansteuerung des SJA beschäftigt? Kennst Du 
vielleicht auch ein Codebeispiel für VHDL zur Ansteuerung?

Autor: Michael O. (mischu)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Bei CAN kann es auch immer gerne an Masseschleifen oder fehlendem 
Common-Modefilter liegen. Hast Du das CAN-Signal mit dem Oszi (als 
analoges Signal) gemessen?
Welche Hardware nutzt Du?
Bekommt der SJA ein ordentliches Resetsignal?

Wie ist die Clock ausgelegt (Timing Problem beim Decode)?
http://www.mct.net/download/philips/can_timing.pdf


Es gibt bei Opencores.org ein SJA1000 Codeschnipsel, wo der SJA im FPGA 
realisiert wurde (allerdings Verilog). Hilft Dir auch nicht viel weiter, 
gell :)

Autor: Steffen Hausinger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich habe das CAN-Signal direkt am Rx-Pin des SJA1000 angeschaut. Es war 
so, wie ich es gesendet habe. Die CAN-Übertragungsstrecke ist also 
funktionsfähig. Mit dem Oszi habe ich zwar nicht geschaut, aber ich habe 
das Signal hinter dem CAN-Treiber angeschaut. Er hat es richtig erkannt. 
Unwahrscheinlich, dass auf der kurzen Strecke zwischen Treiber und SJA 
ein Fehler einstreut (siehe auch unten).

Das Resetsignal habe ich so aufgebaut, wie es im Datenblatt beschrieben 
ist. Ich resette aber auch nachträglich noch einmal über die 
Schnittstelle.

Das Dekodier-Timing habe ich mir ebenfalls schon angeschaut. Allerdings 
kann man beim Sender die Einstellungen vorgeben. Ich habe diese 
Einstellungen natürlich auch für den Empfänger übernommen.

Die zentrale Reaktion, die fast alle Fehlerursache ausschließt, ist 
aber: Lese ich das Datenbyte einmal aus, ist es sporadisch fehlerhaft. 
Lese ich es ein zweites Mal aus, ist es dagegen korrekt. Demnach kann es 
sich um keinen CAN-Fehler mehr handeln, da es sich immer um ein und 
dieselbe Nachricht handelt.

Autor: Michael O. (mischu)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Kann es daran liegen, dass Du zu langsam liest?
Muss man die Daten auslesen, während kein weiteres Byte empfangen wird 
(Bug / Timingforderung im SJA)??

Lies doch mal dasselbe Byte mehrfach nacheinander aus.

Autor: Steffen Hausinger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Michael O. schrieb:
> Kann es daran liegen, dass Du zu langsam liest?

Nicht ausgeschlossen, aber unwahrscheinlich. Es ist immer das gleiche 
Datenbyte falsch: Byte 2. Alle anderen Bytes funktionieren, die 
Ausleseroutine ist aber natürlich immer die gleiche. Das Datenblatt gibt 
aber auch keine maximale Zyklusdauer vor.



Michael O. schrieb:
> Lies doch mal dasselbe Byte mehrfach nacheinander aus.

Das habe ich probehalber schon gemacht. Siehe:
> Lese ich das Datenbyte einmal aus, ist es sporadisch fehlerhaft.
> Lese ich es ein zweites Mal aus, ist es dagegen korrekt.



Seltsam, oder?

Autor: Duke Scarring (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Steffen Hausinger schrieb:
>> Lese ich es ein zweites Mal aus, ist es dagegen korrekt.
> Seltsam, oder?

Hast Du denn Zeitdruck mit Deinem Projekt? Wenn ja, würde ich als 
Workaround eben immer zweimal auslesen...

Duke

Autor: Michael O. (mischu)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Steffen Hausinger schrieb:
> Das habe ich probehalber schon gemacht. Siehe:
>> Lese ich das Datenbyte einmal aus, ist es sporadisch fehlerhaft.
>> Lese ich es ein zweites Mal aus, ist es dagegen korrekt.

Ich meinte auch nicht zweimal auslesen, sondern 10 - 100 mal und 
schauen, ob es ab dem zweiten mal immer korrekt ist.
Kann es sein, dass Du Probleme mit dem RX-FIFO hast?
z.B. Der SJA empfängt ein weiteres Paket und überschreibt den Bereich?

Oder versuche in der Statemachine mal mit einer anderen Geschwindigkeit 
auszulesen. Vielleicht ist dann ein anderes Byte gestört...

Autor: me (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich habe mal einen Atmel zum Auslesen/Beschreiben eines SJA1000 benutzt. 
Das Wichtigste war, vor dem Lesen irgendwelcher Messages das 
Status-Register - insbesondere das SR.0-bit, welches mir anzeigt, ob 
überhaupt Messages abzuholen sind, abzufragen. Hast du das Auslesen mit 
diesem bit irgendwo synchronisiert? Datasheet page 15.
Kann man ja aus dem bisher geposteten Code nicht erkennen...

Autor: Steffen Hausinger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Duke Scarring schrieb:
> Hast Du denn Zeitdruck mit Deinem Projekt? Wenn ja, würde ich als
> Workaround eben immer zweimal auslesen...

;-)

Michael O. schrieb:
> Ich meinte auch nicht zweimal auslesen, sondern 10 - 100 mal und
> schauen, ob es ab dem zweiten mal immer korrekt ist.

Nein, ist es nicht. Aber die Wahrscheinlichkeit steigt dafür rapide beim 
zweiten Mal. Insofern ist schon gut möglich, dass ich Probleme mit dem 
Rx-FIFO habe. Oder besser gesagt der SJA1000.

Eine zweite Nachricht kommt während dieses Versuchs übrigens nicht 
herein. Der Fehler ist völlig isoliert.


Michael O. schrieb:
> Oder versuche in der Statemachine mal mit einer anderen Geschwindigkeit
> auszulesen. Vielleicht ist dann ein anderes Byte gestört...

Guter Punkt und Du hast dabei völlig Recht!! Es ist nicht nur das zweite 
Datenbyte gestört, sondern auch andere. Das hatte ich vorher noch gar 
nicht überprüft, weil ich mich auf das (übergeordnete) Protokoll 
verlassen habe! Tja, aber ist diese Erkenntnis nun gut oder schlecht?


@me:
Interessanter Tipp, das habe ich tatsächlich nicht gemacht. Ich verwende 
die Interruptleitung zum Signalisieren einer neuen Empfangsnachricht. 
Allerdings ändert auch das Auslesen des Status-Registers nichts an 
meinem Fehler :-(

Hier ist übrigens mein Auslese-Teil:
        -- Empfangene Nachricht abrufen
        elsif State = RecMessage then              -- Empfangen wir eine Nachricht, ...
          RDnWR <= '1';                      -- ...Übertragungsrichtung zu "Lesen" wechseln
          case StateMachine is                  -- Zu derzeitigen Abarbeitungsschritt verzweigen
            when 0 =>                      -- Schritt 0
              Address <= x"03";                -- Interrupt-Register auswählen (wird erst im nächsten Schritt ausgelesen)
              SJATransState := BeginTrans;        -- Übernahme vom SJA anfordern
            when 1 =>                      -- Schritt 1
              if Data_in(0) = '0' then          -- Wird im Interruptregister gar keine neue Empfangsnachricht angezeigt, ...
                iStop <= true;                -- ...Abarbeitung unmittelbar wieder beenden
                StateMachine := 9;            -- Zum Beenden der StateMachine in den letzten Abarbeitungsschritt wechseln
              else                        -- Wird dagegen eine neue Empfangsnachricht angezeigt, ...
                Address <= x"16";              -- ...Register für Datenbyte 0 auswählen (wird erst im nächsten Schritt ausgelesen)
                SJATransState := BeginTrans;      -- Übernahme vom SJA anfordern
              end if;                      --
            when 2 =>                      -- Schritt 2
              Receive(63 downto 56) <= data_in;    -- Datenbyte 0 übernehmen
              Address <= x"17";                -- Register für Datenbyte 1 auswählen (wird erst im nächsten Schritt ausgelesen)
              SJATransState := BeginTrans;        -- Übernahme vom SJA anfordern
            when 3 =>                      -- Schritt 3
              Receive(55 downto 48) <= data_in;    -- Datenbyte 1 übernehmen
              Address <= x"18";                -- Register für Datenbyte 2 auswählen (wird erst im nächsten Schritt ausgelesen)
              SJATransState := BeginTrans;        -- Übernahme vom SJA anfordern
            when 4 =>                      -- Schritt 4
              Receive(47 downto 40) <= data_in;    -- Datenbyte 2 übernehmen
              Address <= x"19";                -- Register für Datenbyte 3 auswählen (wird erst im nächsten Schritt ausgelesen)
              SJATransState := BeginTrans;        -- Übernahme vom SJA anfordern
            when 5 =>                      -- Schritt 5
              Receive(39 downto 32) <= data_in;    -- Datenbyte 3 übernehmen
              Address <= x"1A";                -- Register für Datenbyte 4 auswählen (wird erst im nächsten Schritt ausgelesen)
              SJATransState := BeginTrans;        -- Übernahme vom SJA anfordern
            when 6 =>                      -- Schritt 6
              Receive(31 downto 24) <= data_in;    -- Datenbyte 4 übernehmen
              Address <= x"1B";                -- Register für Datenbyte 5 auswählen (wird erst im nächsten Schritt ausgelesen)
              SJATransState := BeginTrans;        -- Übernahme vom SJA anfordern
            when 7 =>                      -- Schritt 7
              Receive(23 downto 16) <= data_in;    -- Datenbyte 5 übernehmen
              Address <= x"1C";                -- Register für Datenbyte 6 auswählen (wird erst im nächsten Schritt ausgelesen)
              SJATransState := BeginTrans;        -- Übernahme vom SJA anfordern
            when 8 =>                      -- Schritt 8
              Receive(15 downto  8) <= data_in;    -- Datenbyte 6 übernehmen
              Address <= x"1D";                -- Register für Datenbyte 7 auswählen (wird erst im nächsten Schritt ausgelesen)
              SJATransState := BeginTrans;        -- Übernahme vom SJA anfordern
            when 9 =>                      -- Schritt 9
              Receive( 7 downto  0) <= data_in;    -- Datenbyte 7 übernehmen
              RDnWR <= '0';                  -- Übertragungsrichtung zu "Schreiben" wechseln
              Address <= x"01";                -- Command-Register
              Data_out <= x"04";              -- Release Receive Buffer
              SJATransState := BeginTrans;        -- Übernahme vom SJA anfordern
              iStop <= true;                  -- Markieren, dass die Abarbeitung nun fertiggestellt ist
              StateMachine := -1;              -- StateMachine in den Grundzustand versetzen
            when others =>                    -- In allen anderen Fällen...
              null;
          end case;                        --
          StateMachine := StateMachine + 1;        -- In nächsten Schritt der StateMachine wechseln

Das ist nur ein Ausschnitt, aus dem man gut den Ablauf zum Auslesen 
erkennen kann. Das ganze Rahmenwerk habe ich bewusst weggelassen, da ich 
im Logic Analyzer erkennen kann, dass es einwandfrei funktioniert...

Autor: Steffen Hausinger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo zusammen,

es gibt Neuigkeiten: Ich habe mir inzwischen eine Platine anfertigen 
lassen und das gesamte SJA1000-Board neu bestückt. Eben habe ich es dann 
ausprobiert.

Zu Beginn hatte es den Anschein, als wenn jetzt alles funktionieren 
würde. Aber dann - Pustekuchen! Es treten wieder die gleichen Symptome 
wie oben auf. Das Teil macht mich fertig :-((

Allerdings ist mir diesmal etwas aufgefallen: Wenn ich mit meinem Logic 
Analyzer (minila) mitmesse, dann funktioniert die Verbindung in 95% der 
Fälle. Auch wenn ich den Analyzer trenne und nur die Messspitzen 
dranlasse klappt es. Ziehe ich die Spitzen aber ab, treten die Fehler 
auf!


Kann sich das jemand erklären? Am Timing liegt es nicht, das war das 
Ergebnis der bisherigen Diskussion.

Grüße
Steffen

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [vhdl]VHDL-Code[/vhdl]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.