For a project I have to fulfill the following conditions:
1)
Setup interrupts on the ARM Cortex MCU using CMSIS APIs
a)
Show how to initialise global interrupts on the ARM Cortex for GPIO pins and timers.
b)
What are the default CMSIS ISR functions on the ARM Cortex M0+ for servicing interrupts on GPIO pins and timers?
2)
Configure a TCCx timer in interrupt mode.
a)
Write a class of methods to initialise a TCCx timer to count to a maximum period of 1 minute with a timer tick time of 1 ms.
b)
Add a method to configure and attach a GPIO pin of choice to this TCCx timer.
c)
Write any necessary start and stop methods.
d)
Initialise the NVIC and ISR to trigger on an interrupt from TCCx.
#include "sam.h"
// ---------------- LED + Button ----------------
#define NUM_LEDS 6
const uint8_t LED_PINS[NUM_LEDS] = {6, 18, 20, 21, 16, 19}; // PAxx pins
#define BUTTON_PIN 2 // PA02
// Knight Rider state
typedef enum { STOPPED, RUNNING } State;
volatile State systemState = STOPPED;
volatile int krIndex = 0;
volatile int krDir = 1;
// ---------------- TCC Timer ----------------
#define STEP_INTERVAL_MS 500 // 500ms per step
typedef struct {
Tcc* tcc; // Pointer to TCCx registers
uint32_t tick_ms; // Tick time in ms
uint32_t max_count; // Max count (for 1 step)
IRQn_Type irq; // NVIC IRQ number
} MyTCC_Timer;
MyTCC_Timer tcc1Timer;
// ----------------- LED Init -----------------
void initLEDs(void) {
for (int i = 0; i < NUM_LEDS; i++) {
PORT->Group[0].DIRSET.reg = (1 << LED_PINS[i]); // output
PORT->Group[0].OUTCLR.reg = (1 << LED_PINS[i]); // off
}
}
// ----------------- Button Init -----------------
void initButton(void) {
PM->APBAMASK.reg |= PM_APBAMASK_EIC; // Enable EIC clock
// GCLK for EIC (use GCLK3)
GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID_EIC | GCLK_CLKCTRL_GEN_GCLK3 | GCLK_CLKCTRL_CLKEN;
while (GCLK->STATUS.bit.SYNCBUSY);
// Configure PA02 as input for button
PORT->Group[0].DIRCLR.reg = (1 << BUTTON_PIN);
PORT->Group[0].PINCFG[BUTTON_PIN].bit.PMUXEN = 1;
PORT->Group[0].PMUX[BUTTON_PIN >> 1].bit.PMUXE = PORT_PMUX_PMUXE_A; // function A = EIC
// Configure external interrupt for falling edge
EIC->CONFIG[0].reg |= EIC_CONFIG_SENSE2_FALL;
EIC->INTENSET.reg = (1 << BUTTON_PIN);
EIC->CTRL.bit.ENABLE = 1;
while (EIC->STATUS.bit.SYNCBUSY);
NVIC_EnableIRQ(EIC_IRQn);
}
// ----------------- TCC Init -----------------
void TCC_Init(MyTCC_Timer* timer, Tcc* tcc_instance, uint32_t tick_ms, uint32_t step_ms, IRQn_Type irq) {
timer->tcc = tcc_instance;
timer->tick_ms = tick_ms;
timer->max_count = step_ms / tick_ms; // ticks per step
timer->irq = irq;
// Enable TCC1 clock
PM->APBCMASK.bit.TCC1_ = 1;
// Generic clock for TCC1 (GCLK3)
GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID_TCC2_TC3 | GCLK_CLKCTRL_GEN_GCLK3 | GCLK_CLKCTRL_CLKEN;
while (GCLK->STATUS.bit.SYNCBUSY);
// Reset TCC
tcc_instance->CTRLA.bit.SWRST = 1;
while (tcc_instance->SYNCBUSY.bit.SWRST);
// Configure prescaler, period
tcc_instance->CTRLA.reg = TCC_CTRLA_PRESCALER_DIV1024; // 1ms tick
tcc_instance->PER.reg = timer->max_count;
while (tcc_instance->SYNCBUSY.bit.PER);
// Enable overflow interrupt
tcc_instance->INTENSET.reg = TCC_INTENSET_OVF;
NVIC_EnableIRQ(timer->irq);
}
void TCC_Start(MyTCC_Timer* timer) {
timer->tcc->CTRLA.bit.ENABLE = 1;
while (timer->tcc->SYNCBUSY.bit.ENABLE);
}
void TCC_Stop(MyTCC_Timer* timer) {
timer->tcc->CTRLA.bit.ENABLE = 0;
while (timer->tcc->SYNCBUSY.bit.ENABLE);
}
// ----------------- Button ISR -----------------
void EIC_Handler(void) {
static uint32_t lastPress = 0;
uint32_t now = SysTick->VAL; // crude debounce
if ((lastPress - now) & 0xFFFFFFF) return; // ignore bounces
lastPress = now;
EIC->INTFLAG.reg = (1 << BUTTON_PIN); // clear interrupt
if (systemState == STOPPED) systemState = RUNNING;
else if (systemState == RUNNING) systemState = STOPPED;
}
// ----------------- TCC1 ISR -----------------
void TCC1_Handler(void) {
if (TCC1->INTFLAG.bit.OVF) {
TCC1->INTFLAG.reg = TCC_INTFLAG_OVF; // clear flag
if (systemState == RUNNING) {
PORT->Group[0].OUTCLR.reg = (1 << LED_PINS[krIndex]); // turn off old LED
krIndex += krDir;
if (krIndex == 0 || krIndex == NUM_LEDS-1) krDir = -krDir;
PORT->Group[0].OUTSET.reg = (1 << LED_PINS[krIndex]); // turn on new LED
}
}
}
// ----------------- Main -----------------
int main(void) {
SystemInit();
initLEDs();
initButton();
TCC_Init(&tcc1Timer, TCC1, 1, STEP_INTERVAL_MS, TCC1_IRQn); // 1ms tick, 500ms per step
TCC_Start(&tcc1Timer);
__enable_irq(); // enable global interrupts
while (1) {
// Main loop empty: all handled by interrupts
}
}
When I try to upload the sketch, my board disconnects and doesnt reconnect. When I use arduino commands like millis() it works fine. I am unable to figure out the issue. Please guide me