Forum: Compiler & IDEs STM32 C-Code Problem


von SiCnifikant (Gast)


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:
1
#include "main.h"
2
3
void SystemClock_Config(void);
4
static void MX_GPIO_Init(void);
5
6
#include <stdio.h>
7
#include "untitled.h"                 
8
#include "rtwtypes.h"
9
                  
10
extern RT_MODEL_untitled *const untitled_M;
11
extern void untitled_SetEventsForThisBaseStep(boolean_T*);
12
static boolean_T OverrunFlags[1];
13
static volatile uint32_t autoReloadTimerLoopVal_S = 1;
14
static volatile uint32_t remainAutoReloadTimerLoopVal_S = 1;
15
16
int main(void)
17
{
18
  int_T i;
19
  HAL_Init();
20
  SystemClock_Config();
21
  MX_GPIO_Init();
22
  
23
  /* Systick configuration and enable SysTickHandler interrupt */
24
  if (SysTick_Config((uint32_t)(SystemCoreClock * 0.0001))) {
25
    autoReloadTimerLoopVal_S = 1;
26
    do {
27
      autoReloadTimerLoopVal_S++;
28
    } while ((uint32_t)(SystemCoreClock * 0.0001)/autoReloadTimerLoopVal_S >
29
             SysTick_LOAD_RELOAD_Msk);
30
31
    SysTick_Config((uint32_t)(SystemCoreClock * 0.0001)/autoReloadTimerLoopVal_S);
32
  }
33
34
  remainAutoReloadTimerLoopVal_S = autoReloadTimerLoopVal_S;//Set nb of loop to do
35
36
    for (i=0;i<1;i++) {
37
    OverrunFlags[i] = 0;
38
  }
39
40
  untitled_initialize();
41
42
    while (1) {
43
    /*Process tasks every solver time*/
44
    if (remainAutoReloadTimerLoopVal_S == 0) {
45
      remainAutoReloadTimerLoopVal_S = autoReloadTimerLoopVal_S;
46
47
      /* Check base rate for overrun */
48
      if (OverrunFlags[0]) {
49
        rtmSetErrorStatus(untitled_M, "Overrun");
50
      }
51
52
      OverrunFlags[0] = true;
53
54
      untitled_step();
55
/* Indicate task for base rate complete */
56
      OverrunFlags[0] = false;
57
    }
58
  }
59
60
}
61
62
void HAL_SYSTICK_Callback(void)
63
{
64
  if (remainAutoReloadTimerLoopVal_S) {
65
    remainAutoReloadTimerLoopVal_S--;
66
  }
67
}

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 :)

von Dr. Sommer (Gast)


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...

von SiCnifikant (Gast)


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
1
if (remainAutoReloadTimerLoopVal_S == 0)
Wird auf jeden fall nie wahr. Um den Code zum laufen zu bekommen muss 
ich
1
  if (remainAutoReloadTimerLoopVal_S == 0) {
2
      remainAutoReloadTimerLoopVal_S = autoReloadTimerLoopVal_S;
3
      if (OverrunFlags[0]) {
4
        rtmSetErrorStatus(untitled_M, "Overrun");
5
      }
6
7
      OverrunFlags[0] = true;
8
      untitled_step();
9
      OverrunFlags[0] = false;
10
    } else {
11
      untitled_step();
12
    }
schreiben.

von Dr. Sommer (Gast)


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.

von SiCnifikant (Gast)


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?

von Dr. Sommer (Gast)


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?

von SiCnifikant (Gast)


Lesenswert?

Hallo nochmal,

verschiedene NVIC-Funktionen werden durch die HAL_Init() aufgerufen, 
darunter auch SysTick
1
__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks)
2
{
3
  if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk)
4
  {
5
    return (1UL);                                                   /* Reload value impossible */
6
  }
7
8
  SysTick->LOAD  = (uint32_t)(ticks - 1UL);                         /* set reload register */
9
  NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */
10
  SysTick->VAL   = 0UL;                                             /* Load the SysTick Counter Value */
11
  SysTick->CTRL  = SysTick_CTRL_CLKSOURCE_Msk |
12
                   SysTick_CTRL_TICKINT_Msk   |
13
                   SysTick_CTRL_ENABLE_Msk;                         /* Enable SysTick IRQ and SysTick Timer */
14
  return (0UL);                                                     /* Function successful */
15
}
_enable_irq () konnte ich jetzt auch nicht finden

von RAc (Gast)


Lesenswert?

welche Einsprungsadresse steht denn in der IVT für den SysTick Handler?

von SiCnifikant (Gast)


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

von SiCnifikant (Gast)


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.
1
void SysTick_Handler(void)
2
{
3
  /* USER CODE BEGIN SysTick_IRQn 0 */
4
5
  /* USER CODE END SysTick_IRQn 0 */
6
  HAL_IncTick();
7
  HAL_SYSTICK_Callback();
8
  /* USER CODE BEGIN SysTick_IRQn 1 */
9
10
  /* USER CODE END SysTick_IRQn 1 */
11
}

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....

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.