Using an ATSAMV71N19B, and am really struggling with it. All I'm trying to do is understand how to trigger an ISR to toggle an LED every X seconds, but all I can seem to do is change it between every 100mS and every 200mS or so. In debugging, I'm getting some strange results. This init sequence is directly from START:
int32_t _timer_init(struct _timer_device *const device, void *const hw) { struct tc_configuration *cfg = get_cfg(hw); uint32_t ch_mode = cfg->channel_mode; device->hw = hw; ASSERT(ARRAY_SIZE(_tcs)); if (ch_mode & TC_CMR_WAVE) { /* Enable event control mode */ ch_mode |= (0x02 << 13) | (0x01 << 16) | (0x02 << 18); } hri_tc_write_CMR_reg(hw, 0, ch_mode); hri_tc_write_RA_reg(hw, 0, cfg->ra); hri_tc_write_RC_reg(hw, 0, cfg->rc); hri_tc_set_IMR_reg(hw, 0, TC_IER_CPCS); hri_tc_write_FMR_reg(hw, cfg->fmr); _tc_init_irq_param(hw, device); NVIC_DisableIRQ(cfg->irq); NVIC_ClearPendingIRQ(cfg->irq); NVIC_EnableIRQ(cfg->irq); return ERR_NONE; }
Ignore that you can't see the values I'm loading for RA and RC. But here is a capture of the Watch window from Studio when I hit the ISR:
There are a number of problems here.
1) TC_IER (interrupt enable reg) has nothing set, even though I set the RC compare interrupt here:
hri_tc_set_IMR_reg(hw, 0, TC_IER_CPCS);
The code for this function from the START file:
static inline void hri_tc_set_IMR_reg(const void *const hw, uint8_t submodule_index, hri_tc_imr_reg_t mask) { ((Tc *)hw)->TcChannel[submodule_index].TC_IER = mask; }
Why isn't it "accepting" the write to the IER reg? There's no mention of any other lock bit or anything needing to be set in the datasheet. However, I DO get the appropriate flag in the interrupt mask register (TC_IMR = 0x00000010) after I start debugging. In fact, that flag never seems to go away.
2) Why is the value in the counter value register when the ISR triggers nowhere close to the compare value in TC_RC? Is this real, or an artifact of trying to observe using Watch? The status reg indicates I DID get a RC overflow (TC_SR=0x00070010).