Forum: Compiler & IDEs zweite SPI im SAM D mit Atmel Studio ASF hängt


von thomas (Gast)


Lesenswert?

Moin,

ich benötige mehrere SPIs im SAMD21.
Beim Einbinden der zweiten SPI hängt das Programm im
1
startup_samd21.c
2
3
void Dummy_Handler(void)
4
{  while (1) {}
5
}

Einen SPI habe ich mit der RadioHead-Library in Verwendung:
1
Sercom* H_spiNumber=SERCOM3;
2
3
HardwareSPI::HardwareSPI(uint32_t spiPortNumber) :_spiPortNumber(spiPortNumber)
4
{  switch (spiPortNumber)
5
  {
6
  case 0: H_spiNumber=SERCOM0; break;
7
...bla...
8
  }
9
}

Die zweite SPI soll ein externes Flash AT25DFx bedienen. Wurde mit dem 
ASF generiert:
1
void EM_configure_spi_master(void)
2
{   struct at25dfx_chip_config  vat25dfx_chip_config;
3
    struct spi_config vat25dfx_spi_config;
4
5
   at25dfx_spi_get_config_defaults(&vat25dfx_spi_config);
6
   vat25dfx_spi_config.mode_specific.master.baudrate = AT25DFX_CLOCK_SPEED;
7
   vat25dfx_spi_config.mux_setting = SPI_SIGNAL_MUX_SETTING_D;
8
   vat25dfx_spi_config.pinmux_pad0 = PINMUX_PB02D_SERCOM5_PAD0;
9
   vat25dfx_spi_config.pinmux_pad1 = PINMUX_PB03D_SERCOM5_PAD1;
10
   vat25dfx_spi_config.pinmux_pad2 = PINMUX_UNUSED;
11
   vat25dfx_spi_config.pinmux_pad3 = PINMUX_PB23D_SERCOM5_PAD3;
12
   spi_init(&at25dfx_spi, EM_spiNumber, &vat25dfx_spi_config);
13
   spi_enable(&at25dfx_spi);
14
   vat25dfx_chip_config.type = AT25DFX_512B;
15
   vat25dfx_chip_config.cs_pin = PINMUX_PB23D_SERCOM5_PAD3;
16
   at25dfx_chip_init(&at25dfx_chip, &at25dfx_spi, &vat25dfx_chip_config);
17
}

Wenn ich den Code in EM_configure_spi_master() auskommentiere, läuft die 
Kiste an. Sobald der Code aktiv ist, endet es im Dummy_Handler() (s.o.)

Hat jemand eine Idee?


Kann jemand erklären, wie die Logik der Funktion __libc_init_array() im 
Reset_Handler() ist?
Mit dem Debugger komme ich da im Single Step nicht rein.

Mit aktivem EM_configure_spi_master() springt das Programm vom 
__libc_init_array() direkt in den Dummy_Handler(). Warum?

1
startup_samd21.c
2
3
void Reset_Handler(void)
4
{
5
... bla ...
6
        __libc_init_array();        /* Initialize the C library */
7
        main();             /* Branch to main function */
8
        while (1);        /* Infinite loop */
9
}


Vielen Dank für eine Hilfe :o)

von Andi (Gast)


Lesenswert?

Hast du mal alle Fault-Handler, also UsageFault, BusFault etc., 
implementiert? Dann dürfte es etwas klarer werden, was für eine 
Exception auftritt, der Dummy-Handler ist nur eine Fallbacklösung und 
sagt relativ wenig aus. Die Fault-Handler müssen alle noch explizit 
aktiviert werden, das geschieht System Handler Control and State 
Register (SHCSR), welches (wenn ich mich recht erinner) im System 
Control Block (SCB) liegen dürfte.

von Andi (Gast)


Lesenswert?

Nachtrag: Genauer Informationen zu der aufgetretenen Exception sind dann 
im Configurable Fault Status Register (CFSR) im SCB zu finden.

von Christopher J. (christopher_j23)


Lesenswert?

thomas schrieb:
> Kann jemand erklären, wie die Logik der Funktion __libc_init_array() im
> Reset_Handler() ist?

Die Funktion ruft statische Konstruktoren auf. Das du im Dummy-Handler 
landest kann verschiedene Gründe haben, z.B. einen Bus-Fault oder aber 
auch ganz einfach das du im SPI-IRQ-Handler landest, der aber nicht 
implementiert ist und damit landest du im Dummy-Handler. Um das Problem 
weiter eingrenzen zu können sind die Tips von Andi sicher hilfreich. 
Ansonsten kann bei sowas auch ein Assembler-Listing nicht schaden.

von Thomas K. (technomicro)


Lesenswert?

Danke Christopher und Andi,

ich habe den Dummy_Handler erweitert:
1
void Dummy_Handler(void)
2
{  volatile int i,j,p;
3
  
4
  HardFault_HandlerAsm();
5
    while (1) {
6
    i=__get_IPSR();
7
    j=__get_APSR();
8
    p=__get_xPSR();
9
  }
10
}
11
/**
12
 * HardFault_HandlerAsm:
13
 * Alternative Hard Fault handler to help debug the reason for a fault.
14
 * To use, edit the vector table to reference this function in the HardFault vector
15
 * This code is suitable for Cortex-M3 and Cortex-M0 cores
16
 */
17
18
// Use the 'naked' attribute so that C stacking is not used.
19
__attribute__((naked))
20
void HardFault_HandlerAsm(void)
21
{        /*
22
         * Get the appropriate stack pointer, depending on our mode,
23
         * and use it as the parameter to the C handler. This function
24
         * will never return
25
         */
26
27
        __asm(  ".syntax unified\n"
28
                        "MOVS   R0, #4  \n"
29
                        "MOV    R1, LR  \n"
30
                        "TST    R0, R1  \n"
31
                        "BEQ    _MSP    \n"
32
                        "MRS    R0, PSP \n"
33
                        "B      HardFault_HandlerC      \n"
34
                "_MSP:  \n"
35
                        "MRS    R0, MSP \n"
36
                        "B      HardFault_HandlerC      \n"
37
                ".syntax divided\n") ;
38
}
39
40
/**
41
 * HardFaultHandler_C:
42
 * This is called from the HardFault_HandlerAsm with a pointer the Fault stack
43
 * as the parameter. We can then read the values from the stack and place them
44
 * into local variables for ease of reading.
45
 * We then read the various Fault Status and Address Registers to help decode
46
 * cause of the fault.
47
 * The function ends with a BKPT instruction to force control back into the debugger
48
 */
49
void HardFault_HandlerC(unsigned long *hardfault_args){
50
        volatile unsigned long stacked_r0 ;
51
        volatile unsigned long stacked_r1 ;
52
        volatile unsigned long stacked_r2 ;
53
        volatile unsigned long stacked_r3 ;
54
        volatile unsigned long stacked_r12 ;
55
        volatile unsigned long stacked_lr ;
56
        volatile unsigned long stacked_pc ;
57
        volatile unsigned long stacked_psr ;
58
        volatile unsigned long _CFSR ;
59
        volatile unsigned long _HFSR ;
60
        volatile unsigned long _DFSR ;
61
        volatile unsigned long _AFSR ;
62
        volatile unsigned long _BFAR ;
63
        volatile unsigned long _MMAR ;
64
65
        stacked_r0 = ((unsigned long)hardfault_args[0]) ;
66
        stacked_r1 = ((unsigned long)hardfault_args[1]) ;
67
        stacked_r2 = ((unsigned long)hardfault_args[2]) ;
68
        stacked_r3 = ((unsigned long)hardfault_args[3]) ;
69
        stacked_r12 = ((unsigned long)hardfault_args[4]) ;
70
        stacked_lr = ((unsigned long)hardfault_args[5]) ;
71
        stacked_pc = ((unsigned long)hardfault_args[6]) ;
72
        stacked_psr = ((unsigned long)hardfault_args[7]) ;
73
74
        // Configurable Fault Status Register
75
        // Consists of MMSR, BFSR and UFSR
76
        _CFSR = (*((volatile unsigned long *)(0xE000ED28))) ;   
77
78
        // Hard Fault Status Register
79
        _HFSR = (*((volatile unsigned long *)(0xE000ED2C))) ;
80
81
        // Debug Fault Status Register
82
        _DFSR = (*((volatile unsigned long *)(0xE000ED30))) ;
83
84
        // Auxiliary Fault Status Register
85
        _AFSR = (*((volatile unsigned long *)(0xE000ED3C))) ;
86
87
        // Read the Fault Address Registers. These may not contain valid values.
88
        // Check BFARVALID/MMARVALID to see if they are valid values
89
        // MemManage Fault Address Register
90
        _MMAR = (*((volatile unsigned long *)(0xE000ED34))) ;
91
        // Bus Fault Address Register
92
        _BFAR = (*((volatile unsigned long *)(0xE000ED38))) ;
93
94
        __asm("BKPT #0\n") ; // Break into the debugger
95
96
}
97
/**
98
 * \brief Default interrupt handler for unused IRQs.
99
  __get_IPSR();:
100
    ISR_NUMBER (IPSR[8:0])
101
        =0 Thread mode
102
        =1 Reserved
103
        =2 NMI
104
        =3 HardFault
105
        =4 MemManage
106
        =5 BusFault
107
        =6 UsageFault
108
        =7-10 Reserved
109
        =11 SVCall
110
        =12 Reserved for Debug
111
        =13 Reserved
112
        =14 PendSV
113
        =15 SysTick
114
        =16 IRQ0
115
        ...
116
        =n+15 IRQ(n-1)
117
118
119
 */

Beim Steppen fiel mir dann ein HardFault auf.
Nachdem ich den
1
//RHReliableDatagram  rf95reliable(rf95, rf95CLIENT_ADDRESS);
auskommentiert hatte, ging es.

Scheint eine Kollision zwischen RHReliableDatagram und ASF:AT25FFx zu 
sein. Das bedarf noch weitere Forschung.

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.