Forum: Mikrocontroller und Digitale Elektronik IAR + STM32: Linker-Fehler


von user (Gast)


Lesenswert?

Hallo,

ich verwende in zwei C Dateien jeweils den gleichen Interrupt-Handler.
1
void EXTI15_10_IRQHandler(void)
2
{
3
4
}

Allerdings für die ankommenden Ereignisse benutze nicht die gleichen 
Pins.
Beim Kompilieren funktioniert alles. Nur beim Linken erhalte ich diese 
Fehlermeldung:

Error[Li006]: duplicate definitions for "EXTI15_10_IRQHandler";

Müsste ich diesen Interrupt-Handler NUR in eine C Datei aufrufen?

von Dr. Sommer (Gast)


Lesenswert?

user schrieb:
> Müsste ich diesen Interrupt-Handler NUR in eine C Datei aufrufen?

Ja. Du kannst nicht 2 Funktionen mit dem gleichen Namen haben. Du kannst 
ja mehrere verschiedene Funktionen schreiben, und diese vom "richtigen" 
Handler aus aufrufen.

von user (Gast)


Lesenswert?

Danke erstmal. Gibt es hierzu ein kleines Beispiel?

von Dr. Sommer (Gast)


Lesenswert?

Wo brauchst du beim Aufruf von Funktionen ein Beispiel?!
1
// Datei1.c
2
void my_2nd_EXTI_Handler (void);
3
4
void EXTI15_10_IRQHandler(void)
5
{
6
  // ...
7
  my_2nd_EXTI_Handler ();
8
}
9
10
// Datei2.c
11
12
void my_2nd_EXTI_Handler (void) {
13
  // ...
14
}

von Little B. (lil-b)


Lesenswert?

z.B. so:
1
/**
2
 * @brief  Interrupt Service routine EXTI 10 to 15
3
 * @ingroup  ELWMD_EXTI_Private
4
 * @brief
5
 * The service routine for external interrupt lines 10 to 15. Only active, if an user
6
 * callback function was registered for one of these lines.
7
 * @param  none
8
 * @return  nothing
9
 */
10
void EXTI15_10_IRQHandler () {
11
  // save exti-flags associated with this IRQ
12
  uint32_t line_backup = EXTI->PR & 0xFC00;
13
14
  // call user-callbacks according to flags
15
  if ( (line_backup & 0x400) && (ELWMD_Exti_UserCallbacks[10] != 0) ) ELWMD_Exti_UserCallbacks[10]();
16
  if ( (line_backup & 0x800) && (ELWMD_Exti_UserCallbacks[11] != 0) ) ELWMD_Exti_UserCallbacks[11]();
17
  if ( (line_backup & 0x1000) && (ELWMD_Exti_UserCallbacks[12] != 0) ) ELWMD_Exti_UserCallbacks[12]();
18
  if ( (line_backup & 0x2000) && (ELWMD_Exti_UserCallbacks[13] != 0) ) ELWMD_Exti_UserCallbacks[13]();
19
  if ( (line_backup & 0x4000) && (ELWMD_Exti_UserCallbacks[14] != 0) ) ELWMD_Exti_UserCallbacks[14]();
20
  if ( (line_backup & 0x8000) && (ELWMD_Exti_UserCallbacks[15] != 0) ) ELWMD_Exti_UserCallbacks[15]();
21
22
  // clear previously saved exti-flags
23
  EXTI_ClearITPendingBit(line_backup);
24
  return;
25
}

von user (Gast)


Lesenswert?

Dieser Interrupt-Handler verwende ich zum einen für die 
Ethernet-Kommunikation und zum anderen in einer anderen Klasse für GPIO.
Damit der Code übersichtlich bleibt müsste ich dann eine separate 
Interrupt Datei erstellen in der die Interrupt-Handler-Routine vorhanden 
ist. Dann müsste ich jeweils die Daten bei einem ankommenden Ereignis in 
den entsprechenden Klassen weiterverarbeiten.

von Little B. (lil-b)


Lesenswert?

user schrieb:
> Dieser Interrupt-Handler verwende ich zum einen für die
> Ethernet-Kommunikation und zum anderen in einer anderen Klasse für GPIO.

Hää?

EXTI15_10 behandelt nicht den Ethernet Interrupt. Der Ethernet Wakeup 
Interrupt (EXTI19) ist IRQn 62 und wird mittels ETH_WKUP implementiert. 
Dieser wird aber auch nicht zwingend für Ethernet Kommunikation 
gebraucht.

Solltest du jedoch einen externen Ethernet Controller verwenden, dann 
solltest du die Interrupt Pins über deine GPIO-Klasse auswerten.

...oder du hast ein falsches Konzept gewählt.

von user (Gast)


Lesenswert?

Den ETH_WKUP Interrupt verwende ich auch nicht. Den EXTI15_10_IRQHandler 
verwende ich eigentlich nur um festzustellen, ob Verbindung da ist oder 
nicht. Dazu benutze ich EXTI_Line14. In einer anderen Klasse für GPIO 
verwende ich ebenfalls den EXTI15_10_IRQHandler allerdings EXTI_Line10.
Alle hardwareabhängigen Codestellen werden immer in einer eigenen C bzw. 
H Datei festgelegt. Blöde wäre jetzt für mich, dass ich den 
EXTI15_10_IRQHandler in einer eigenen C Datei implementieren müsste. 
Hmmm...das macht das ganze unübersichtlich.

von Little B. (lil-b)


Lesenswert?

user schrieb:
> Alle hardwareabhängigen Codestellen werden immer in einer eigenen C bzw.
> H Datei festgelegt.

user schrieb:
> Hmmm...das macht das ganze unübersichtlich.

Da geb ich dir Recht, das macht es wirklich unübersichtlich, und auch 
schwer Wartbar und Portierbar. Besser du fasst alle Hardware 
Abhängigkeiten in einem Softwaremodul zusammen. (lass uns dieses 
Softwaremodul "IOMUX" nennen)

IOMUX kümmert sich um die Initialisierung aller Pins und Alternate 
Functions, damit sich die Schnittstellentreiber nicht mehr darum kümmern 
müssen. Beispiel SPI: Der SPI-Treiber modifiziert nur SPI-Register, 
keine GPIO-Register! So lassen sich Treiber von einem Board auf ein 
anderes portieren, ohne den Code anfassen zu müssen.

IOMUX kann sich dann auch um EXTI kümmern, da diese ja stark von den 
Pins abhängt. Zusätzlich bietet es Makros, die dann die Treiber 
verwenden. z.B. so:
1
iomux.h
2
-------
3
#define SPI_ExtiIrq    EXTI0_IRQHandler
4
#define UART_ExtiIrq   EXTI3_IRQHandler
5
6
#define ETHERNET_ExtiIrq   EXTI14_IRQHandler  /* Dies ist kein Hardware-Handler! */
7
                                              /* Sonder Teil von EXTI15_10 */
8
9
10
iomux.c
11
-------
12
13
#include "iomux.h"
14
15
// externe funktionen bekannt machen
16
extern void ETHERNET_ExtiIrq ();
17
18
//wrapper für exti9_5 und exti15_10
19
void EXTI15_10_IRQHandler () {
20
   if (/*line 14*/) ETHERNET_ExtiIrq();
21
   ...
22
}
23
24
ethernet.c
25
----------
26
#include "iomux.h"
27
28
void ETHERNET_ExtiIrq () {
29
   // deine IRQ
30
}

Dieses konzept muss noch erweitert werden, um die Interrupt Flags zurück 
zu setzen, sowie die initialisierung der EXTI in einer IOMUX_Init().

von user (Gast)


Lesenswert?

Erstmal vielen Dank.

Da müsste ich nun einiges bei mir ändern. In der IOMUX sind dann nur die 
GPIO relevanten Dinge + Interrupt für die GPIO's enthalten. In den 
anderen Dateien z.B. für Ethernet sind dann nur die Dinge enthalten die 
nur für die Ethernet Kommunikation notwendig sind.

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.