STM32 C-Code Problem

Gast #5819337
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 :)
Gast #5819362
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...
Gast #5819412
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.
Gast #5819428
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.
Gast #5819762
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
Gast #5819857
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....

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren