Forum: Mikrocontroller und Digitale Elektronik SAM3U (Cortex M3) und Atmel Studio, IRQ Problem


von X- R. (x-rocka)


Lesenswert?

Moin,

ich bin gerade dabei, ein Cortex-M3 Projekt eines 
"manuell-installierten" GCC-Compilers auf Atmel Studio 7.0 zu ändern.
Stück für Stück geht es voran, jetzt bleibe ich an einer Sache hängen, 
und zwar wenn ich im ADC_Handler (s.u.) die letzte Zeile nicht drin habe 
(LED wird per Makro ausgeschaltet), macht der Controller gar nichts 
mehr, der startet nicht mal mehr die externe Clock.
Bleibt diese Zeile drin, läuft alles. Ich hatte ein LED an/aus in den 
Handler gepackt, um zu testen, ob er überhaupt reinspringt.
Ideen?
1
/* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
2
/* IRQ 10bit ADC */
3
void ADC_Handler(void)
4
{
5
    u32_t status;
6
    static u8_t adc_channel = 0;
7
    static u16_t vbat_ovsmpl_sum = 0;
8
    static u8_t vbat_ovsmpl_cnt = 0;
9
10
  status = ADC->ADC_SR;
11
12
  if( status & ((u32_t)1 << adc_channel) )
13
  {
14
    if( adc_channel == ADC_CH3_VBAT )
15
    {
16
      vbat_ovsmpl_sum += (u16_t)(ADC->ADC_LCDR & 0x000003FF);
17
      vbat_ovsmpl_cnt++;
18
      if( vbat_ovsmpl_cnt == ADC_OVERSAMPLING_RATE )
19
      {
20
        adc10b_ch[ADC_CH3_VBAT] = vbat_ovsmpl_sum >> ADC_OVERSAMPLING_SHIFT;
21
        vbat_ovsmpl_cnt = 0;
22
        vbat_ovsmpl_sum = 0;
23
      }
24
    }
25
    else
26
    {
27
      adc10b_ch[adc_channel] = (u16_t)(ADC->ADC_LCDR & 0x000003FF);
28
    }
29
30
    /* switch to next channel, dis-/enable interrupts */
31
    ADC->ADC_IDR = ((u32_t)1 << adc_channel);
32
    if( adc_channel == 3 ) adc_channel = 0;
33
    else adc_channel++;
34
    ADC->ADC_IER = ((u32_t)1 << adc_channel);
35
  }
36
37
  if( status & 0x0000000F )  /* mask for adc channels 0-3 */
38
  {
39
    /* ADC control register: re-start conversion */
40
    ADC->ADC_CR = ADC_CR_START;
41
  }
42
43
PIN_LED_RED_OFF;
44
}

von Jim M. (turboj)


Lesenswert?

Klingt komisch. Versuche mal als letzte Zeile:
1
NVIC_ClearPendingIRQ(ADC_IRQn);

Das Tail-Chaining Feature in Zusammenhang mit dem Schreibpuffer ergibt 
bei Interrupts gelegentlich doppelte Auslösungen, was einiges 
durcheinander bringen kann. Kommt insbesondere dann vor wenn das 
auslösende Flag in der letzten Zeile des Handlers erst gelöscht wird.

Bei Taktumschaltung müsste man auch aufpassen dass man den ADC nicht 
überfährt, der verträgt ja nur eine bestimmte maximale Frequenz.

von X- R. (x-rocka)


Lesenswert?

Ich habe das Interrupt-Disable des aktuellen nach vorne gezogen hat 
nichts gebracht.

Das aber schon:
Jim M. schrieb:
> Klingt komisch. Versuche mal als letzte Zeile:
>
1
> NVIC_ClearPendingIRQ(ADC_IRQn);
2
>

Danke! :)

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.