mikrocontroller.net

Forum: Compiler & IDEs wie schreibt man eine Vektortabelle für Cortex-M4?


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.
von Bauform B. (bauformb)


Bewertung
0 lesenswert
nicht lesenswert
// vector-table.c
  
#include <stddef.h>
#include "irqn.h"
#include "vectortable.h"
#include "syslib.h"

extern crt0_type  crt0;
extern isr_type   crash;  // All-purpose fault handler
extern isr_type   syscall_isr, pendsv_isr, systick_isr;
extern isr_type   pvd_isr;
extern isr_type   uart0_isr, uart1_isr, uart2_isr, uart3_isr, uart4_isr;
extern uint32_t   tos;

#pragma GCC diagnostic ignored "-Woverride-init"
#pragma GCC diagnostic ignored "-pedantic"
const vector_struct __attribute__ ((aligned (512), section ".vector_table")))
vector_table = {
   &tos,                  //   0   0  Initial SP, defined in linker script
   crt0,                  //   1   4  Initial PC = Reset-"Handler"
   crash,                 //   2   8  CSS Clock security system, NMI
   crash,                 //   3   c  Hard fault (double fault)
   crash,                 //   4  10  Memory protection
   crash,                 //   5  14  Bus fault
   crash,                 //   6  18  Usage fault
   crash,                 //   7  1c  -
   crash,                 //   8  20  -
   crash,                 //   9  24  -
   crash,                 //  10  28  -
   syscall_isr,           //  11  2c  SVC instruction
   crash,                 //  12  30  Debug monitor
   crash,                 //  13  34  -
   pendsv_isr,            //  14  38  Pendable request for system service
   systick_isr,           //  15  3c  System tick timer
   {  
      [__extension__ 0 ... 111] = crash,
      [PVD_PVM_IRQn] = pvd_isr,   // PVD thru EXTI line detection
      [UART0_IRQn] = uart0_isr,
      [UART1_IRQn] = uart1_isr,
      [UART2_IRQn] = uart2_isr,
      [UART3_IRQn] = uart3_isr,
      [UART4_IRQn] = uart4_isr
   }
};
Also so geht es schon mal nicht. Und ohne die #pragma geht es noch 
schlechter. Aber wirklich übel ist die Warnung, obwohl ich _extension_ 
dazu schreibe:
warning: ISO C forbids specifying range of elements to initialize
ISO C meint also, ich sollte über 100 mal crash schreiben? Damit man 
dann die uart_isr mittendrin nicht wiederfindet?

Wie macht ihr das?

von Jim M. (turboj)


Bewertung
0 lesenswert
nicht lesenswert
Das Linker Skript ist der entscheidende Teil, und den haste natürlich 
nicht gepostet. So kann das nicht tun.

Bauform B. schrieb:
> warning: ISO C forbids specifying range of elements to initialize

Was haste denn als C-Dialekt eingestellt? Ich verwende i.d.R. -std=gnu99 
oder -std=gnu11 je nach GCC Version. Ohne das "gnu" sind Extensions 
nicht aktiv IMHO (oder erzeugen Warnings).

von Bauform B. (bauformb)


Bewertung
0 lesenswert
nicht lesenswert
Jim M. schrieb:
> Das Linker Skript ist der entscheidende Teil, und den haste natürlich
> nicht gepostet. So kann das nicht tun.

??? Hier geht's doch um C-Syntax oder maximal -Semantik ???

> Was haste denn als C-Dialekt eingestellt? Ich verwende i.d.R. -std=gnu99
> oder -std=gnu11 je nach GCC Version.
-std=c2x

> Ohne das "gnu" sind Extensions nicht aktiv IMHO (oder erzeugen Warnings).

Eigentlich logisch, aber für 0b01010101 hat extension funktioniert? 
Rätselhaft.

von Bernd K. (prof7bit)


Bewertung
1 lesenswert
nicht lesenswert

#define SECT_VECTABLE           __attribute__((section(".isr_vector"), __used__))
#define WEAK_DEFAULT            __attribute__((weak, alias("Default_Handler")))


void Default_Handler(void) {
    while(1);
}


WEAK_DEFAULT void NMI_Handler(void);
WEAK_DEFAULT void HardFault_Handler(void);
WEAK_DEFAULT void MemManage_Handler(void);
WEAK_DEFAULT void BusFault_Handler(void);
WEAK_DEFAULT void UsageFault_Handler(void);
WEAK_DEFAULT void SVC_Handler(void);
WEAK_DEFAULT void DebugMon_Handler(void);
WEAK_DEFAULT void PendSV_Handler(void);
WEAK_DEFAULT void SysTick_Handler(void);
WEAK_DEFAULT void WWDG_IRQHandler(void);                /* Window WatchDog              */
WEAK_DEFAULT void PVD_IRQHandler(void);                 /* PVD through EXTI Line detection */
WEAK_DEFAULT void TAMP_STAMP_IRQHandler(void);          /* Tamper and TimeStamps through the EXTI line */
WEAK_DEFAULT void RTC_WKUP_IRQHandler(void);            /* RTC Wakeup through the EXTI line */
WEAK_DEFAULT void FLASH_IRQHandler(void);               /* FLASH                        */
WEAK_DEFAULT void RCC_IRQHandler(void);                 /* RCC                          */
WEAK_DEFAULT void EXTI0_IRQHandler(void);               /* EXTI Line0                   */
WEAK_DEFAULT void EXTI1_IRQHandler(void);               /* EXTI Line1                   */
WEAK_DEFAULT void EXTI2_IRQHandler(void);               /* EXTI Line2                   */
WEAK_DEFAULT void EXTI3_IRQHandler(void);               /* EXTI Line3                   */
WEAK_DEFAULT void EXTI4_IRQHandler(void);               /* EXTI Line4                   */
WEAK_DEFAULT void DMA1_Stream0_IRQHandler(void);        /* DMA1 Stream 0                */
WEAK_DEFAULT void DMA1_Stream1_IRQHandler(void);        /* DMA1 Stream 1                */
WEAK_DEFAULT void DMA1_Stream2_IRQHandler(void);        /* DMA1 Stream 2                */
WEAK_DEFAULT void DMA1_Stream3_IRQHandler(void);        /* DMA1 Stream 3                */
WEAK_DEFAULT void DMA1_Stream4_IRQHandler(void);        /* DMA1 Stream 4                */
WEAK_DEFAULT void DMA1_Stream5_IRQHandler(void);        /* DMA1 Stream 5                */
WEAK_DEFAULT void DMA1_Stream6_IRQHandler(void);        /* DMA1 Stream 6                */
WEAK_DEFAULT void ADC_IRQHandler(void);                 /* ADC1(void); ADC2 and ADC3s   */
WEAK_DEFAULT void EXTI9_5_IRQHandler(void);             /* External Line[9:5]s          */
WEAK_DEFAULT void TIM1_BRK_TIM9_IRQHandler(void);       /* TIM1 Break and TIM9          */
WEAK_DEFAULT void TIM1_UP_TIM10_IRQHandler(void);       /* TIM1 Update and TIM10        */
WEAK_DEFAULT void TIM1_TRG_COM_TIM11_IRQHandler(void);  /* TIM1 Trigger and Commutation and TIM11 */
WEAK_DEFAULT void TIM1_CC_IRQHandler(void);             /* TIM1 Capture Compare         */
WEAK_DEFAULT void TIM2_IRQHandler(void);                /* TIM2                         */
WEAK_DEFAULT void TIM3_IRQHandler(void);                /* TIM3                         */
WEAK_DEFAULT void TIM4_IRQHandler(void);                /* TIM4                         */
WEAK_DEFAULT void I2C1_EV_IRQHandler(void);             /* I2C1 Event                   */
WEAK_DEFAULT void I2C1_ER_IRQHandler(void);             /* I2C1 Error                   */
WEAK_DEFAULT void I2C2_EV_IRQHandler(void);             /* I2C2 Event                   */
WEAK_DEFAULT void I2C2_ER_IRQHandler(void);             /* I2C2 Error                   */
WEAK_DEFAULT void SPI1_IRQHandler(void);                /* SPI1                         */
WEAK_DEFAULT void SPI2_IRQHandler(void);                /* SPI2                         */
WEAK_DEFAULT void USART1_IRQHandler(void);              /* USART1                       */
WEAK_DEFAULT void USART2_IRQHandler(void);              /* USART2                       */
WEAK_DEFAULT void EXTI15_10_IRQHandler(void);           /* External Line[15:10]s        */
WEAK_DEFAULT void RTC_Alarm_IRQHandler(void);           /* RTC Alarm (A and B) through EXTI Line */
WEAK_DEFAULT void OTG_FS_WKUP_IRQHandler(void);         /* USB OTG FS Wakeup through EXTI line */
WEAK_DEFAULT void DMA1_Stream7_IRQHandler(void);        /* DMA1 Stream7                 */
WEAK_DEFAULT void SDIO_IRQHandler(void);                /* SDIO                         */
WEAK_DEFAULT void TIM5_IRQHandler(void);                /* TIM5                         */
WEAK_DEFAULT void SPI3_IRQHandler(void);                /* SPI3                         */
WEAK_DEFAULT void DMA2_Stream0_IRQHandler(void);        /* DMA2 Stream 0                */
WEAK_DEFAULT void DMA2_Stream1_IRQHandler(void);        /* DMA2 Stream 1                */
WEAK_DEFAULT void DMA2_Stream2_IRQHandler(void);        /* DMA2 Stream 2                */
WEAK_DEFAULT void DMA2_Stream3_IRQHandler(void);        /* DMA2 Stream 3                */
WEAK_DEFAULT void DMA2_Stream4_IRQHandler(void);        /* DMA2 Stream 4                */
WEAK_DEFAULT void OTG_FS_IRQHandler(void);              /* USB OTG FS                   */
WEAK_DEFAULT void DMA2_Stream5_IRQHandler(void);        /* DMA2 Stream 5                */
WEAK_DEFAULT void DMA2_Stream6_IRQHandler(void);        /* DMA2 Stream 6                */
WEAK_DEFAULT void DMA2_Stream7_IRQHandler(void);        /* DMA2 Stream 7                */
WEAK_DEFAULT void USART6_IRQHandler(void);              /* USART6                       */
WEAK_DEFAULT void I2C3_EV_IRQHandler(void);             /* I2C3 event                   */
WEAK_DEFAULT void I2C3_ER_IRQHandler(void);             /* I2C3 error                   */
WEAK_DEFAULT void FPU_IRQHandler(void);                 /* FPU                          */
WEAK_DEFAULT void SPI4_IRQHandler(void);                /* SPI4                         */


typedef struct {
    long* initial_stack;
    void(*vectors[])(void);
} vector_table_t;


SECT_VECTABLE const vector_table_t __vector_table = {
    .initial_stack = __stack,
    .vectors = {
        /*
         * Exception handlers that belong to the ARM core itself
         */
        Reset_Handler,
        NMI_Handler,
        HardFault_Handler,
        MemManage_Handler,
        BusFault_Handler,
        UsageFault_Handler,
        0,
        0,
        0,
        0,
        SVC_Handler,
        DebugMon_Handler,
        0,
        PendSV_Handler,
        SysTick_Handler,

        /* External Interrupts */
        WWDG_IRQHandler,                    /* Window WatchDog              */
        PVD_IRQHandler,                     /* PVD through EXTI Line detection */
        TAMP_STAMP_IRQHandler,              /* Tamper and TimeStamps through the EXTI line */
        RTC_WKUP_IRQHandler,                /* RTC Wakeup through the EXTI line */
        FLASH_IRQHandler,                   /* FLASH                        */
        RCC_IRQHandler,                     /* RCC                          */
        EXTI0_IRQHandler,                   /* EXTI Line0                   */
        EXTI1_IRQHandler,                   /* EXTI Line1                   */
        EXTI2_IRQHandler,                   /* EXTI Line2                   */
        EXTI3_IRQHandler,                   /* EXTI Line3                   */
        EXTI4_IRQHandler,                   /* EXTI Line4                   */
        DMA1_Stream0_IRQHandler,            /* DMA1 Stream 0                */
        DMA1_Stream1_IRQHandler,            /* DMA1 Stream 1                */
        DMA1_Stream2_IRQHandler,            /* DMA1 Stream 2                */
        DMA1_Stream3_IRQHandler,            /* DMA1 Stream 3                */
        DMA1_Stream4_IRQHandler,            /* DMA1 Stream 4                */
        DMA1_Stream5_IRQHandler,            /* DMA1 Stream 5                */
        DMA1_Stream6_IRQHandler,            /* DMA1 Stream 6                */
        ADC_IRQHandler,                     /* ADC1, ADC2 and ADC3s         */
        0,                                  /* Reserved                     */
        0,                                  /* Reserved                     */
        0,                                  /* Reserved                     */
        0,                                  /* Reserved                     */
        EXTI9_5_IRQHandler,                 /* External Line[9:5]s          */
        TIM1_BRK_TIM9_IRQHandler,           /* TIM1 Break and TIM9          */
        TIM1_UP_TIM10_IRQHandler,           /* TIM1 Update and TIM10        */
        TIM1_TRG_COM_TIM11_IRQHandler,      /* TIM1 Trigger and Commutation and TIM11 */
        TIM1_CC_IRQHandler,                 /* TIM1 Capture Compare         */
        TIM2_IRQHandler,                    /* TIM2                         */
        TIM3_IRQHandler,                    /* TIM3                         */
        TIM4_IRQHandler,                    /* TIM4                         */
        I2C1_EV_IRQHandler,                 /* I2C1 Event                   */
        I2C1_ER_IRQHandler,                 /* I2C1 Error                   */
        I2C2_EV_IRQHandler,                 /* I2C2 Event                   */
        I2C2_ER_IRQHandler,                 /* I2C2 Error                   */
        SPI1_IRQHandler,                    /* SPI1                         */
        SPI2_IRQHandler,                    /* SPI2                         */
        USART1_IRQHandler,                  /* USART1                       */
        USART2_IRQHandler,                  /* USART2                       */
        0,                                  /* Reserved                     */
        EXTI15_10_IRQHandler,               /* External Line[15:10]s        */
        RTC_Alarm_IRQHandler,               /* RTC Alarm (A and B) through EXTI Line */
        OTG_FS_WKUP_IRQHandler,             /* USB OTG FS Wakeup through EXTI line */
        0,                                  /* Reserved                     */
        0,                                  /* Reserved                     */
        0,                                  /* Reserved                     */
        0,                                  /* Reserved                     */
        DMA1_Stream7_IRQHandler,            /* DMA1 Stream7                 */
        0,                                  /* Reserved                     */
        SDIO_IRQHandler,                    /* SDIO                         */
        TIM5_IRQHandler,                    /* TIM5                         */
        SPI3_IRQHandler,                    /* SPI3                         */
        0,                                  /* Reserved                     */
        0,                                  /* Reserved                     */
        0,                                  /* Reserved                     */
        0,                                  /* Reserved                     */
        DMA2_Stream0_IRQHandler,            /* DMA2 Stream 0                */
        DMA2_Stream1_IRQHandler,            /* DMA2 Stream 1                */
        DMA2_Stream2_IRQHandler,            /* DMA2 Stream 2                */
        DMA2_Stream3_IRQHandler,            /* DMA2 Stream 3                */
        DMA2_Stream4_IRQHandler,            /* DMA2 Stream 4                */
        0,                                  /* Reserved                     */
        0,                                  /* Reserved                     */
        0,                                  /* Reserved                     */
        0,                                  /* Reserved                     */
        0,                                  /* Reserved                     */
        0,                                  /* Reserved                     */
        OTG_FS_IRQHandler,                  /* USB OTG FS                   */
        DMA2_Stream5_IRQHandler,            /* DMA2 Stream 5                */
        DMA2_Stream6_IRQHandler,            /* DMA2 Stream 6                */
        DMA2_Stream7_IRQHandler,            /* DMA2 Stream 7                */
        USART6_IRQHandler,                  /* USART6                       */
        I2C3_EV_IRQHandler,                 /* I2C3 event                   */
        I2C3_ER_IRQHandler,                 /* I2C3 error                   */
        0,                                  /* Reserved                     */
        0,                                  /* Reserved                     */
        0,                                  /* Reserved                     */
        0,                                  /* Reserved                     */
        0,                                  /* Reserved                     */
        0,                                  /* Reserved                     */
        0,                                  /* Reserved                     */
        FPU_IRQHandler,                     /* FPU                          */
        0,                                  /* Reserved                     */
        0,                                  /* Reserved                     */
        SPI4_IRQHandler                     /* SPI4                         */
    }
};

Komplettes Beispiel hier: 
https://github.com/prof7bit/bare_metal_stm32f401xe

: Bearbeitet durch User
von Bauform B. (bauformb)


Bewertung
0 lesenswert
nicht lesenswert
Bernd K. schrieb:
>   SVC_Handler,
>   DebugMon_Handler,
>   0,
>   PendSV_Handler,

Die Nuller sind ja äußerst interessant. Dann könnte ich ja die [0...111] 
Initialisierung weglassen und es wäre perfekt -- keine Warnungen, auch 
ohne #pragma usw.

Aber: führt 0 wirklich zu einem Usage Fault? Ja, weil das T-Bit nicht 
gesetzt ist; nein, weil das eine Adresse ist und deshalb die 
Stack-Adresse als Befehl ausgeführt würde. Das allerdings mit T-Bit = 0, 
hmm.

Also vermutlich ist es definiert aber reicht mir das? Dass irgendjemand 
bei ST (oder wer war das?) das so richtig findet heißt ja nun garnichts. 
Und wenn das Verhalten mit 0 definiert wäre, könnte man doch die ganzen 
weak-Einträge weglassen?

Ich hasse es, wenn es so verlockende Angebote gibt, die man dann doch 
nicht nutzen kann.

von Bernd K. (prof7bit)


Bewertung
0 lesenswert
nicht lesenswert
Diese Vektoren existieren nicht, die werden nie aufgerufen, also kann da 
stehen was will.

von Bernd K. (prof7bit)


Bewertung
0 lesenswert
nicht lesenswert
Bauform B. schrieb:
> könnte man doch die ganzen weak-Einträge weglassen?

Die welche nicht Null sind existieren, könnten also aufgerufen werden, 
also braucht man einen Mechanismus mit dem sich die Anwendung da bei 
Bedarf beim Linken einhaken kann, dieser Mechanismus ist weak.

Wenn die Anwendung keinen eigenen Handler mitbringt gilt der weiche 
Alias auf den Default Handler und dessen Adresse wird eingesetzt, 
andernfalls setzt der Linker die Adresse des starken Handlers aus der 
Anwendung ein.

: Bearbeitet durch User
von Bernd K. (prof7bit)


Bewertung
0 lesenswert
nicht lesenswert
Bauform B. schrieb:
> Ich hasse es, wenn es so verlockende Angebote gibt, die man dann doch
> nicht nutzen kann.

Was laberst Du? Natürlich kannst du es nutzen, deshalb hab ich's doch 
geschrieben! Du kannst auch das vom Hersteller nutzen, das ist dann halt 
in Assembler, funktioniert aber nach dem exakt selben Prinzip.

von Bauform B. (bauformb)


Bewertung
0 lesenswert
nicht lesenswert
Bernd K. schrieb:
> Diese Vektoren existieren nicht, die werden nie aufgerufen, also kann da
> stehen was will.

Was ist mit dem Software trigger interrupt register (NVIC_STIR)? Darüber 
kann man doch jeden Interrupt per Software triggern? ST meint, alle von 
0 bis (256-16), das heißt, meine Tabelle muss noch doppelt so groß 
werden. Danke für den Tipp.

Bernd K. schrieb:
> Die welche nicht Null sind existieren, könnten also aufgerufen werden,
> also braucht man einen Mechanismus mit dem sich die Anwendung da bei
> Bedarf beim Linken einhaken kann, dieser Mechanismus ist weak.

Genau das mache ich ja auch, nur mit viel weniger Zeilen.
   [0 ... (128-16-1)] = crash
trägt überall den Default Handler ein und mit
   [PVD_PVM_IRQn] = pvd_isr,   // PVD thru EXTI line detection
   [UART0_IRQn] = uart0_isr,
klinkt sich die Anwendung mit ihrem Bedarf da ein.
Als Bonus ist auch bei denen, die nicht existieren, etwas eingetragen.

Leider meint der GCC, dass "array[0 ... n]=foo" auch in C2x noch nicht 
erlaubt ist und außerdem warnt er bei den folgenden Zeilen. Letztere 
Warnung kann ich einfach abschalten aber die erste nervt; vor allem, 
weil extension nichts nützt. Ideal wäre es, wenn 0 statt crash sauber 
funktionieren würde. Deswegen:
>> Ich hasse es, wenn es so verlockende Angebote gibt, die man dann doch
>> nicht nutzen kann.

Bernd K. schrieb:
> Komplettes Beispiel hier:
> https://github.com/prof7bit/bare_metal_stm32f401xe

Irgendwie passt "bare_metal" und der weak-Mechanismus nicht zusammen. 
Solche Konstruktionen braucht man doch nur in IDE, wo möglichst viel vor 
dem Benutzer versteckt werden soll.

: Bearbeitet durch User
von Bernd K. (prof7bit)


Bewertung
0 lesenswert
nicht lesenswert
Bauform B. schrieb:
> Irgendwie passt "bare_metal" und der weak-Mechanismus nicht zusammen.

Du redest wirr. Wie soll man es Deiner Meinung nach sonst machen wenn 
die Vektortabelle im ROM liegt? Die Tabelle ins RAM zu legen und 
kostbares RAM verschwenden auch wenn überhaupt kein zwingender Grund 
vorliegt das im RAM zu haben?

Ich glaub Du hast noch nicht recht verstanden was es mit weak auf sich 
hat und warum man genau das und nichts anderes an dieser Stelle 
verwendet denn genau für solche Sachen wurde das erfunden. Du wirst es 
sicherlich irgendwann verstehen wenn Du Dich noch ein wenig länger damit 
beschäftigst. Google einfach mit dem Stichwort und lies Dir alles durch, 
solange bis es "klick" macht.

> Darüber kann man doch jeden Interrupt per Software triggern?

Dann setz halt dort überall den Default_Handler ein statt 0 wenn Dir 
dabei wohler ist. Macht zwar sonst auch keiner aber schaden kanns auch 
nicht.

: Bearbeitet durch User
von Bernd K. (prof7bit)


Bewertung
0 lesenswert
nicht lesenswert
Bauform B. schrieb:

>> dieser Mechanismus ist weak.
>
> Genau das mache ich ja auch, nur mit viel weniger Zeilen.

Ich seh kein einziges weak in Deinem geposteten Code. Wo soll die 
Anwendung ihre eigenen Handler einhängen? Willst Du jedesmal von Hand 
den Startup anpassen? Das ist doch Käse hoch 3!

von Squierrel (Gast)


Bewertung
2 lesenswert
nicht lesenswert
Aber im Zusammenhang mit "weak" aufpassen, solltest du einen Handler 
über eine separat gebaute Library einführen!
Aber wenn das ganze Thema verstanden ist, ist das auch klar … nur 
manchmal denkt man ja nicht direkt an so Dinge.

von Bauform B. (bauformb)


Bewertung
0 lesenswert
nicht lesenswert
Bernd K. schrieb:
> Bauform B. schrieb:
>> Irgendwie passt "bare_metal" und der weak-Mechanismus nicht zusammen.
>
> Du redest wirr.
Das tut mir leid, es ist nicht böse gemeint.

> Wie soll man es Deiner Meinung nach sonst machen wenn
> die Vektortabelle im ROM liegt?

Genau so wie ich es ganz oben geschrieben habe. Warum sollte das im 
Flash nicht funktionieren? RAM brauchst du doch nur, wenn du ISRs "im 
Flug" austauschen willst. Das kann sehr praktisch sein, keine Frage, 
aber meistens geht es doch ohne RAM.

Bernd K. schrieb:
> Ich glaub Du hast noch nicht recht verstanden was es mit weak auf sich
> hat und warum man genau das und nichts anderes an dieser Stelle
> verwendet denn genau für solche Sachen wurde das erfunden.

Den weak-Mechanismus habe ich schon im letzten Jahrtausend gerne 
benutzt. Warum man ihn hier verwendet ist mir nicht klar, aber es ist 
ja auch Geschmackssache. Es gibt mehrere Möglichkeiten und jede hat ihre 
Vor- und Nachteile. Wenn man die Tabelle im RAM haben will, wird man es 
evt. anders machen.

Bernd K. schrieb:
> Ich seh kein einziges weak in Deinem geposteten Code.

Da soll auch keins drin stehen. Warum soll ich einen spezial-Mechanismus 
nutzen, wenn es auch ohne geht?

> Wo soll die Anwendung ihre eigenen Handler einhängen?
[UART0_IRQn] = uart0_isr,
> Willst Du jedesmal von Hand den Startup anpassen?

Nicht den Startup, nur diese eine Tabelle, und nur, wenn eine neue ISR 
dazu kommt.

> Das ist doch Käse hoch 3!
Das ist ein angenehmer Nebeneffekt für jemand, der wenig Fleisch isst ;)

: Bearbeitet durch User
von Bauform B. (bauformb)


Bewertung
0 lesenswert
nicht lesenswert
Squierrel schrieb:
> Aber im Zusammenhang mit "weak" aufpassen, solltest du einen
> Handler
> über eine separat gebaute Library einführen!

Danke, also hatte mein Bauch doch Recht, weak schmeckt uns nicht ;)
Im Ernst, wenn man mit weak aufpassen muss und ohne eine Fehlermeldung 
bekommt -- wer würde da freiwillig weak verwenden?

von Squierrel (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Bauform B. schrieb:
> Im Ernst, wenn man mit weak aufpassen muss und ohne eine Fehlermeldung
> bekommt -- wer würde da freiwillig weak verwenden?

Hier! ;)
Aber im ernst, ein großer Fan bin ich nicht. Es ist öfters einfach die 
beste/praktischste Variante. Bin auch kein Freund von Libs :D …

von Bernd K. (prof7bit)


Bewertung
0 lesenswert
nicht lesenswert
Bauform B. schrieb:
>> Wo soll die Anwendung ihre eigenen Handler einhängen?[UART0_IRQn] = uart0_isr,>
> Willst Du jedesmal von Hand den Startup anpassen?
>
> Nicht den Startup, nur diese eine Tabelle, und nur, wenn eine neue ISR
> dazu kommt.

Naja gut, wenn Du das so umständlich haben willst, dann bitte. Niemand 
hindert Dich daran.

Aber Du hast ja explizit gefragt wie "man" das macht. Und "man" nimmt 
halt normalerweise den weak-Mechanismus der ja genau wie gemacht für 
diese Sache ist, sei es in Assembler oder in C, und es keinerlei Sinn 
oder Vorteil ergäbe darauf zu verzichten, im Gegenteil, ohne weak wirds 
auf jeden Fall unhandlicher, egal wie Du es drehst oder wendest.

von Nop (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Ich nehme dafür auch kein "weak", sondern kopiere N mal den 
Default-Handler da hart hin (N wie im zugehörigen Chip-Manual 
beschrieben), gruppiere die hübsch in Zehnergruppen und mache Kommentare 
dazu, welche Zehnergruppe gerade beginnt.

Bei Bedarf trage ich da an der richtigen Stelle den Interrupt ein, den 
das Manual dort vorsieht. Die richtige Dekade sehe ich am Kommentar, und 
zählen bis 10 bekomme ich gerade noch so hin.

Dann sehe ich wenigstens schon am Linker-Ergebnis, ob er den richtigen 
Handler da jetzt einträgt oder nicht. Außerdem sehe ich direkt an der 
Vektortabelle, was für Interrupts überhaupt genutzt werden.

von Johannes S. (jojos)


Bewertung
0 lesenswert
nicht lesenswert
nur wenn der IRQ Handler in einem C++ Modul liegt und man das C Linkage 
vergißt, kann man lange am Laufzeitfehler suchen.

von Bauform B. (bauformb)


Bewertung
1 lesenswert
nicht lesenswert
Bernd K. schrieb:
> Aber Du hast ja explizit gefragt wie "man" das macht. Und "man" nimmt
> halt normalerweise den weak-Mechanismus der ja genau wie gemacht für
> diese Sache ist

Ja, stimmt. Natürlich hatte ich gehofft, dass "man" das anders macht. 
Aber mit den Nullen in deiner Tabelle hast du den entscheidenden Tipp 
geliefert. Man muss keinen Default Handler eintragen, 0 tut es auch. Da 
0 automatisch eingetragen wird, reicht es, wenn man nur die benutzten 
ISRs hinschreibt.

Nop schrieb:
> Ich nehme dafür auch kein "weak", sondern kopiere N mal den
> Default-Handler da hart hin (...)
> Bei Bedarf trage ich da an der richtigen Stelle den Interrupt ein, den
> das Manual dort vorsieht.

Die richtige Stelle sagen einem die IRQn_enum, z.B. SPI1_IRQn. Das Array 
der vector_table kann man dann einfach mit
  [SPI1_IRQn] = spi_isr,
 intialisieren. Nix abzählen, nur genau so viele Zeilen wie nötig, keine 
magischen Zahlen, keine Mecker vom GCC, bei allen unbenutzten Interrupts 
steht automatisch die 0 drin. Das funktioniert so, als ob der Usage 
Fault Handler eingetragen wäre. Welcher Eintrag gefehlt hat, steht 
hinterher im IPSR.
Aus dem ARM v7-M Architecture ® Reference Manual, ARM DDI0403E.d

B1.5.3 The vector table
  All [other] entries must have bit[0] set to 1, because this bit
  defines the EPSR.T bit on exception entry.
  On exception entry, if bit[0] of the associated vector table entry
  is set to 0, execution of the first instruction causes an INVSTATE
  UsageFault, see The special-purpose Program Status Registers, xPSR

B1.5.6 Exception entry behavior
  (...)
  tmp = MemA[VectorTable+4*ExceptionNumber,4];
  BranchTo(tmp AND 0xFFFFFFFE<31:0>);
  tbit = tmp<0>;
  CurrentMode = Mode_Handler;
  APSR = bits(32) UNKNOWN;
  IPSR<8:0> = ExceptionNumber<8:0>;
  EPSR.T = tbit;
  (...)

B1.3.3 Execution state
  Setting EPSR.T to zero in an ARMv7-M processor causes a fault
  when the next instruction executes, because in this state all
  instructions are UNDEFINED.
Ich hätte gern noch den Pseudo-Code für die eigentliche 
Befehlsausführung gefunden, zwecks wann das T-Bit abgefragt wird. Aber 
ich glaube, es ist auch so überzeugend. Immerhin wird der "Befehl" auf 
Adresse 0 (nicht) ausgeführt, damit fallen viele andere 
Fehlermöglichkeiten weg. Und selbst wenn die Exception im Hard Fault 
Handler endet, kann man noch gut debuggen.

Rein theoretisch könnte es auch mit einem Lockup enden. Aber bis die 
Dekodierung von dem "Befehl" beginnt ist alles noch völlig normal und 
ohne Tricks. Also, was könnte schief gehen?

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.