SAM E5x Atmel Start (ASF) ADC handler BUG?

1 post / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Dear SAM Freaks,

 

I am working on ASF4 (Atmel Start) and the SAM E54, E51 MCUs.

 

When I tried to use the ADC peripherial with the Hal code from ASF4 then I had dummy handler issues but not related to ADC handlers, it's a bus fault the mcu was trying to write on 0x0 adresss.

 

I think there is a BUG on the ADC handler.

 

The solution

static void _adc_interrupt_handler(struct _adc_async_device *device)
{
    void *const hw      = device->hw;
    uint8_t channel = hri_adc_get_INPUTCTRL_MUXPOS_bf(hw,0x1F);
    uint8_t     intflag = hri_adc_read_INTFLAG_reg(hw);
    intflag &= hri_adc_read_INTEN_reg(hw);
    if (intflag & ADC_INTFLAG_RESRDY) {
        hri_adc_clear_interrupt_RESRDY_bit(hw);
        device->adc_async_ch_cb.convert_done(device, channel, hri_adc_read_RESULT_reg(hw));
    } else if (intflag & ADC_INTFLAG_OVERRUN) {
        hri_adc_clear_interrupt_OVERRUN_bit(hw);
        device->adc_async_cb.error_cb(device, 0);
    } else if (intflag & ADC_INTFLAG_WINMON) {
        hri_adc_clear_interrupt_WINMON_bit(hw);
        device->adc_async_cb.window_cb(device, 0);
    }
}

 

The original code

static void _adc_interrupt_handler(struct _adc_async_device *device)
{
    void *const hw      = device->hw;
    uint8_t     intflag = hri_adc_read_INTFLAG_reg(hw);
    intflag &= hri_adc_read_INTEN_reg(hw);
    if (intflag & ADC_INTFLAG_RESRDY) {
        hri_adc_clear_interrupt_RESRDY_bit(hw);
        device->adc_async_ch_cb.convert_done(device, 0, hri_adc_read_RESULT_reg(hw));
    } else if (intflag & ADC_INTFLAG_OVERRUN) {
        hri_adc_clear_interrupt_OVERRUN_bit(hw);
        device->adc_async_cb.error_cb(device, 0);
    } else if (intflag & ADC_INTFLAG_WINMON) {
        hri_adc_clear_interrupt_WINMON_bit(hw);
        device->adc_async_cb.window_cb(device, 0);
    }
}

 

The solution it just gets the MUX channel that the ADC is configured so when the ISR fires and the handler goes into the adc_async_ch_cb.convert_done which is the adc_async_channel_conversion_done() then gets the correct index from the descr->channel_map[channel]. Then it can save the result successfully to the correct address inside the ringbuffer_put(&descr_ch->convert, data);