mikrocontroller.net

Forum: Compiler & IDEs STM32 C-Code Problem


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
Autor: SiCnifikant (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo zusammen,

ich arbeite gerade an einem Projekt, bei dem ich den Embedded Coder von 
Matlab benutze, um meine bestehende Software von einem bestehenden 
System auf die µC von ST (STM32) zu übertragen.

der Code ist folgendermaßen:
#include "main.h"

void SystemClock_Config(void);
static void MX_GPIO_Init(void);

#include <stdio.h>
#include "untitled.h"                 
#include "rtwtypes.h"
                  
extern RT_MODEL_untitled *const untitled_M;
extern void untitled_SetEventsForThisBaseStep(boolean_T*);
static boolean_T OverrunFlags[1];
static volatile uint32_t autoReloadTimerLoopVal_S = 1;
static volatile uint32_t remainAutoReloadTimerLoopVal_S = 1;

int main(void)
{
  int_T i;
  HAL_Init();
  SystemClock_Config();
  MX_GPIO_Init();
  
  /* Systick configuration and enable SysTickHandler interrupt */
  if (SysTick_Config((uint32_t)(SystemCoreClock * 0.0001))) {
    autoReloadTimerLoopVal_S = 1;
    do {
      autoReloadTimerLoopVal_S++;
    } while ((uint32_t)(SystemCoreClock * 0.0001)/autoReloadTimerLoopVal_S >
             SysTick_LOAD_RELOAD_Msk);

    SysTick_Config((uint32_t)(SystemCoreClock * 0.0001)/autoReloadTimerLoopVal_S);
  }

  remainAutoReloadTimerLoopVal_S = autoReloadTimerLoopVal_S;//Set nb of loop to do

    for (i=0;i<1;i++) {
    OverrunFlags[i] = 0;
  }

  untitled_initialize();

    while (1) {
    /*Process tasks every solver time*/
    if (remainAutoReloadTimerLoopVal_S == 0) {
      remainAutoReloadTimerLoopVal_S = autoReloadTimerLoopVal_S;

      /* Check base rate for overrun */
      if (OverrunFlags[0]) {
        rtmSetErrorStatus(untitled_M, "Overrun");
      }

      OverrunFlags[0] = true;

      untitled_step();
/* Indicate task for base rate complete */
      OverrunFlags[0] = false;
    }
  }

}

void HAL_SYSTICK_Callback(void)
{
  if (remainAutoReloadTimerLoopVal_S) {
    remainAutoReloadTimerLoopVal_S--;
  }
}

Mein Problem ist, dass ich ja die Hauptfunktion "untitled_step" in der 
While (1) Schleife nicht ausführen kann, da der Wert 
remainAutoReloadTimerLoopVal_S niemals 0 wird. Jetzt verstehe ich nicht, 
wie Matlab dazu kommt zu etwas überhaupt zu Coden. Wenn ich meine 
Funktion untitled_step aus der if-Anweisung raus tue ist alles fein. 
Allerdings kann ich nicht durschauen, weshalb mir Matlab aus dem 
Embedded Coder diese Ist-Schleife generiert hat. Hoffe ihr könnt mir 
dabei helfen :)

Autor: Dr. Sommer (Gast)
Datum:

Bewertung
2 lesenswert
nicht lesenswert
SiCnifikant schrieb:
> da der Wert
> remainAutoReloadTimerLoopVal_S niemals 0 wird.

Doch, im SysTick-Interrupt wird es dekrementiert. Warum die 
Step-Funktion aber nicht einfach in der SysTick-ISR aufgerufen wird weiß 
wohl niemand. Du musst also prüfen ob, und wenn nicht warum, der SysTick 
aufgerufen wird.

Praktischerweise verheizt die while-Schleife 100% CPU-Last, weil ständig 
geprüft wird, ob die Zeit schon abgelaufen ist. Ein schlichtes __WFI() 
würde hier Wunder wirken...

Autor: SiCnifikant (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dr. Sommer schrieb:
> Doch, im SysTick-Interrupt wird es dekrementiert. Warum die
> Step-Funktion aber nicht einfach in der SysTick-ISR aufgerufen wird weiß
> wohl niemand. Du musst also prüfen ob, und wenn nicht warum, der SysTick
> aufgerufen wird.

Hallo Dr Sommer,

danke für deine Antwort. Ich kann sie nur noch nicht 100% 
nachvollziehen. Ich verstehe noch nicht so ganz, wie der Interrupt hier 
funktioniert. Die 0.0001 ist auf jeden Fall die discrete sample time aus 
dem Matlab Modell.
Mein Statement
if (remainAutoReloadTimerLoopVal_S == 0)
Wird auf jeden fall nie wahr. Um den Code zum laufen zu bekommen muss 
ich
  if (remainAutoReloadTimerLoopVal_S == 0) {
      remainAutoReloadTimerLoopVal_S = autoReloadTimerLoopVal_S;
      if (OverrunFlags[0]) {
        rtmSetErrorStatus(untitled_M, "Overrun");
      }

      OverrunFlags[0] = true;
      untitled_step();
      OverrunFlags[0] = false;
    } else {
      untitled_step();
    }
schreiben.

Autor: Dr. Sommer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
SiCnifikant schrieb:
> AutoReloadTimerLoopVal_S == 0)
> Wird auf jeden fall nie wahr. Um den Code zum laufen zu bekommen muss
> ich

Das ist aber sinnlos, weil die Schrittgeschwindigkeit dann viel zu hoch 
und auch noch variabel ist.

SiCnifikant schrieb:
> Ich verstehe noch nicht so ganz, wie der Interrupt hier
> funktioniert

Dann schau nach wie Interrupts auf dem STM32 Nutzung der HAL 
funktionieren.

Die HAL_SYSTICK_Callback wird vom Interrupt regelmäßig aufgerufen und 
dekrementiert remainAutoReloadTimerLoopVal_S bis es 0 wird. Dann wird 
die if-Bedingung in der Schleife erfüllt, und 
remainAutoReloadTimerLoopVal_S wieder auf autoReloadTimerLoopVal_S 
gesetzt. Ist praktisch ein Software-Timer.

Autor: SiCnifikant (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich verstehe. Habe mich da jetzt etwas eingelesen. Kann aber nicht 
nachvollziehen, warum es nicht funktioniert. Die HAL_SYSTICK_Callback 
wird im Debugger nicht aufgerufen. Weißt du woran es liegen könnte?

Autor: Dr. Sommer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
SiCnifikant schrieb:
> Weißt du woran es liegen könnte?

Ich sehe im Code keinen Aufruf der NVIC-Funktionen zur Konfiguration des 
Interrupts und auch kein __enable_irq (). Macht die SysTick_Config das?

Autor: SiCnifikant (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo nochmal,

verschiedene NVIC-Funktionen werden durch die HAL_Init() aufgerufen, 
darunter auch SysTick
__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks)
{
  if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk)
  {
    return (1UL);                                                   /* Reload value impossible */
  }

  SysTick->LOAD  = (uint32_t)(ticks - 1UL);                         /* set reload register */
  NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */
  SysTick->VAL   = 0UL;                                             /* Load the SysTick Counter Value */
  SysTick->CTRL  = SysTick_CTRL_CLKSOURCE_Msk |
                   SysTick_CTRL_TICKINT_Msk   |
                   SysTick_CTRL_ENABLE_Msk;                         /* Enable SysTick IRQ and SysTick Timer */
  return (0UL);                                                     /* Function successful */
}
_enable_irq () konnte ich jetzt auch nicht finden

Autor: RAc (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
welche Einsprungsadresse steht denn in der IVT für den SysTick Handler?

Autor: SiCnifikant (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
RAc schrieb:
> welche Einsprungsadresse steht denn in der IVT für den SysTick
> Handler?

Puh da muss ich leider sagen bin ich überfragt. Ich nutze TrueStudio zum 
ersten mal und kann leider nichts sagen, wo ich das auslesen kann

Autor: SiCnifikant (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Also ich habe das jetzt folgendermaßen in den Griff bekommen:

ich habe in dem file stm324xx_it.c bei der Definition des 
Systick_Handlers noch den HAL_SYSTICK_Callback(); hinzugefügt.
void SysTick_Handler(void)
{
  /* USER CODE BEGIN SysTick_IRQn 0 */

  /* USER CODE END SysTick_IRQn 0 */
  HAL_IncTick();
  HAL_SYSTICK_Callback();
  /* USER CODE BEGIN SysTick_IRQn 1 */

  /* USER CODE END SysTick_IRQn 1 */
}

Weiß jetzt nicht ob das ein Workaround ist, der funktioniert oder mich 
einschränkt. Bzw weiß ich nicht wieso der Embedded Coder trotz ARM M4 
Unterstützung das nicht richtig übersetzt....

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]
  • [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.

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