[C] Systemtick Problem mit 16-bit Microcontroller



  • Hallo,

    ich programmiere z.Z. in C auf einem (PIC) 16bitµC und habe dort einen Systemtick ("globale" Variable static unsigned char ucBlockFlag = 0) eingeführt:

    Hier die ISR

    // invocation all  1ms
    void __attribute__((__interrupt__, no_auto_psv )) _T1Interrupt(void)
    {
         static unsigned int uc10msCnt = 0; // 10ms vorbei?
    
    	// 10ms Ticker (SYSTEMTICK)
    	if(uc10msCnt>=10)
    	{
    	  	if (ul10msTicks >= 4294967294) 	/* Overflow check */ 
    			ul10msTicks = 0;
    	 	if (ucBlockFlag == 0) 	// double buffering of System Counter 
    	   		ul10msTicks++; 
    		uc10msCnt = 0;
    	}
    }
    

    Ich habe nun eine Funktion außerhalb der ISR, welche den Systemtick kopiert

    unsigned long getTickCount(void)
    { 
      unsigned long ulCurTickCnt = 0;
      ucBlockFlag = 1;  // Blocking of WR on SysCnt 
        ulCurTickCnt = ul10msTicks;
      ucBlockFlag = 0;  // Release of WR on SysCnt 
      return ulCurTickCnt;
    }
    

    für zeitliche Tests nutze ich nun die Funktion getTickCount(), puffere den Wert und vergleiche diesen mit dem aktuellen Systemtick (getTickCount()-ulBufferdTick>=XY). Nun kommt es immer mal wieder (nicht immer) vor, daß die oberen 16 bit der gepufferten Variablen nicht der originalen entsprechen:
    ulOrig = 0x0000978B
    ulKopie = 0xFFFF978B

    Liegt das daran, daß der 16bit Kontroller für die Variable 2 Schritte benötigt?
    Was könnte ich am Coder verändern um Konsistenz zu sichern?
    Ich möchte nicht global auf den Tick zugreifen und mehrere Werte zum Plausibilitätscheck speichere ich auch nur ungern



  • kleiner Nachtrag:

    ich habe eben noch versucht, die Interrupts beim Lesen zu sperren. da aber sowieso nicht gleichzeitig gelesen und geschrieben werden kann, hat das wie erwartet auch nichts gebracht



  • Was machst du denn überhaupt in der T1 ISR?

    Die Variable uc10msCnt wird doch ewig 0 bleiben.

    Auch deine Quelltextkommentare ergeben absolut keinen Sinn und verwirren eher, mal abgesehen davon, dass du mal Englisch und mal Deutsch verwendest.

    Wenn der T1 interrupt jede ms auslöst, brauchst du doch eigentlich einfach nur alle 10 Aufrufe den Tick erhöhen.

    Für "zeitliche Tests" kannst du dann den Tick verwenden.



  • ja sry, hab paar kommentare nachgefügt und nicht gemerkt daß ich nun in deutsch schreibe.

    Zu deinen Fragen: Ja die Variable wird hochgezählt..ich habe die ISR zur Übersichtlichkeit gekürzt und die Zeile "uc10msCnt++;" am Ende vergessen.
    Die Variable uc10msCnt ist nur dazu da, einen 10ms Tick von der 1ms ISR zu bekommen.
    Der Tick an sich funktioniert auch (habs mir am Oszi angeschaut)

    Interessant ist für mich nur die Variable ul10msTicks++; da ich diese anscheinend nicht verlässlich in eine andere Variable via getTickCount() kopieren kann.

    Die Varialbe ucBlockFlag ist dazu da, dass der Tick nicht gelesen wird, wenn er gerade beschrieben wird.



  • Du hast die Variable uc10msCnt mit 0 vorbelegt, danach fragst du ab, ob sie größer als 10 ist. Folglich landest du nie in dem Block, der deine Variablen akualisiert. (es sei denn, du hast dort einen Teil unterschlagen, der die Variable hochzählt)



  • @Cstoll: siehe vorheriger Thread. Ja die Zeile habe ich unterschlagen. Wie gesagt: der tick ist nicht das problem. problem ist es den tick zu kopieren.



  • Ich würde das Blockflag schon vorher testen, dort wo du auch uc10msCnt abfragst, sonst wird das Nullen beim Overflow nicht geblockt. Und dann uc10msCnt nicht auf 0 setzen, sondern 10 subtrahieren, damit die Funktion GetTickCount nicht das Timing versaut.

    Der Overflowtest ist, so wie er da steht, unnötig. Lass die Variable doch einfach überlaufen, wenn sie will.


Anmelden zum Antworten