Skip to content
Snippets Groups Projects
Commit adeb1933 authored by Dylan Laduranty's avatar Dylan Laduranty
Browse files

cpu/saml1x: add support for saml10/saml11 MCUs

parent 6d3fda72
No related branches found
No related tags found
No related merge requests found
# define the module that is build
MODULE = cpu
# add a list of subdirectories, that should also be build
DIRS = periph $(RIOTCPU)/cortexm_common $(RIOTCPU)/sam0_common
# (file triggers compiler bug. see #5775)
SRC_NOLTO += vectors.c
include $(RIOTBASE)/Makefile.base
include $(RIOTCPU)/sam0_common/Makefile.features
export CPU_ARCH = cortex-m23
include $(RIOTCPU)/sam0_common/Makefile.include
include $(RIOTMAKE)/arch/cortexm.inc.mk
/*
* Copyright (C) 2018 Mesotic SAS
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @ingroup cpu_saml1x
* @{
*
* @file cpu.c
* @brief Implementation of the CPU initialization for Microchip
* SAML10/SAML11 MCUs
*
* @author Dylan Laduranty <dylan.laduranty@mesotic.com>
* @}
*/
#include "cpu.h"
#include "periph/init.h"
#include "board.h"
static void _gclk_setup(int gclk, uint32_t reg)
{
GCLK->GENCTRL[gclk].reg = reg;
while (GCLK->SYNCBUSY.reg & GCLK_SYNCBUSY_GENCTRL(gclk)) {}
}
/**
* @brief Initialize the CPU, set IRQ priorities, clocks
*/
void cpu_init(void)
{
/* initialize the Cortex-M core */
cortexm_init();
/* turn on only needed APB peripherals */
MCLK->APBAMASK.reg = MCLK_APBAMASK_MCLK
| MCLK_APBAMASK_OSCCTRL
| MCLK_APBAMASK_GCLK
#ifdef MODULE_PERIPH_GPIO_IRQ
| MCLK_APBAMASK_EIC
#endif
#ifdef MODULE_PERIPH_GPIO
| MCLK_APBAMASK_PORT
#endif
;
/* Software reset the GCLK module to ensure it is re-initialized correctly */
GCLK->CTRLA.reg = GCLK_CTRLA_SWRST;
while (GCLK->CTRLA.reg & GCLK_CTRLA_SWRST) {}
while (GCLK->SYNCBUSY.reg & GCLK_SYNCBUSY_SWRST) {}
/* set OSC16M to 16MHz */
OSCCTRL->OSC16MCTRL.bit.FSEL = 3;
OSCCTRL->OSC16MCTRL.bit.ONDEMAND = 0;
OSCCTRL->OSC16MCTRL.bit.RUNSTDBY = 0;
/* Setup GCLK generators */
_gclk_setup(0, GCLK_GENCTRL_GENEN | GCLK_GENCTRL_SRC_OSC16M);
#ifdef MODULE_PERIPH_PM
/* enable power managemet module */
MCLK->APBAMASK.reg |= MCLK_APBAMASK_PM;
#endif
/* trigger static peripheral initialization */
periph_init();
}
/**
* @defgroup cpu_saml1x Microchip SAML10/SAML11
* @ingroup cpu
* @brief Microchip SAML1x Cortex-M23 MCU specific implementation.
*
* This module contains Microchip SAML10/SAML11 specific code and definition.
*
* @see cpu_saml1x
*/
/*
* Copyright (C) 2018 Mesotic SAS
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @ingroup cpu_saml1x
* @brief CPU specific definitions for internal peripheral handling
* @{
*
* @file
* @brief CPU specific definitions for internal peripheral handling
*
* @author Dylan Laduranty <dylan.laduranty@mesotic.com>
*/
#ifndef PERIPH_CPU_H
#define PERIPH_CPU_H
#include "periph_cpu_common.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Mapping of pins to EXTI lines, -1 means not EXTI possible
*/
static const int8_t exti_config[1][32] = {
{ 0, 1, 2, 3, 4, 5, 6, 7, -1, 0, 1, 2, -1, -1, 3, 4,
5, 6, 7, 0, -1, -1, 1, 2, 3, 4, -1, 5, -1, -1, 6, 7},
};
#ifdef __cplusplus
}
#endif
#endif /* PERIPH_CPU_H */
/** @} */
include $(RIOTMAKE)/periph.mk
/*
* Copyright (C) 2017 Kaspar Schleiser <kaspar@schleiser.de>
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @ingroup cpu_saml21
* @ingroup drivers_periph_pm
* @{
*
* @file
* @brief Implementation of the kernels power management interface
*
* @author Kaspar Schleiser <kaspar@schleiser.de>
*
* @}
*/
#include "periph/pm.h"
#define ENABLE_DEBUG (0)
#include "debug.h"
void pm_set(unsigned mode)
{
if (mode < PM_NUM_MODES) {
uint32_t _mode;
switch (mode) {
case 0:
DEBUG("pm_set(): setting STANDBY mode.\n");
_mode = PM_SLEEPCFG_SLEEPMODE_STANDBY;
break;
default: /* Falls through */
case 1:
DEBUG("pm_set(): setting IDLE mode.\n");
_mode = PM_SLEEPCFG_SLEEPMODE_IDLE;
break;
}
/* write sleep configuration */
PM->SLEEPCFG.bit.SLEEPMODE = _mode;
/* make sure value has been set */
while (PM->SLEEPCFG.bit.SLEEPMODE != _mode) {}
}
cortexm_sleep(0);
}
/*
* Copyright (C) 2014 Baptiste CLENET
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @ingroup cpu_saml21
* @ingroup drivers_periph_rtc
* @{
* @file
* @brief Low-level RTC driver implementation
* @author Baptiste Clenet <bapclenet@gmail.com>
* @autor ported to SAML21 by FWX <FWX@dialine.fr>
* @}
*/
#include <time.h>
#include "cpu.h"
#include "periph/rtc.h"
#include "periph_conf.h"
/* SAML21 rev B needs an extra bit, which in rev A defaults to 1, but isn't
* visible. Thus define it here. */
#ifndef RTC_MODE2_CTRLA_CLOCKSYNC
#define RTC_MODE2_CTRLA_CLOCKSYNC_Pos 15
#define RTC_MODE2_CTRLA_CLOCKSYNC (0x1ul << RTC_MODE2_CTRLA_CLOCKSYNC_Pos)
#endif
typedef struct {
rtc_alarm_cb_t cb; /**< callback called from RTC interrupt */
void *arg; /**< argument passed to the callback */
} rtc_state_t;
static rtc_state_t rtc_callback;
/* At 1Hz, RTC goes till 63 years (2^5, see 17.8.22 in datasheet)
* reference_year is set to 100 (offset) to be in our current time (2000)
* Thanks to this, the user will be able to set time in 2000's*/
static uint16_t reference_year = 100;
void rtc_init(void)
{
/* Turn on power manager for RTC */
MCLK->APBAMASK.reg |= MCLK_APBAMASK_RTC | MCLK_APBAMASK_OSC32KCTRL;
/* DISABLE RTC MASTER */
rtc_poweroff();
#if EXTERNAL_OSC32_SOURCE
/* RTC uses External 32,768KHz Oscillator */
OSC32KCTRL->XOSC32K.reg = OSC32KCTRL_XOSC32K_XTALEN
| OSC32KCTRL_XOSC32K_EN1K
| OSC32KCTRL_XOSC32K_RUNSTDBY
| OSC32KCTRL_XOSC32K_ENABLE;
/* Wait XOSC32K Ready */
while (OSC32KCTRL->STATUS.bit.XOSC32KRDY==0);
/* RTC source clock is external oscillator at 1kHz */
OSC32KCTRL->RTCCTRL.reg = OSC32KCTRL_RTCCTRL_RTCSEL_XOSC1K;
#endif /* EXTERNAL_OSC32_SOURCE */
#if INTERNAL_OSC32_SOURCE
uint32_t * pCalibrationArea;
uint32_t osc32kcal;
/* Read OSC32KCAL, calibration data for OSC32 !!! */
pCalibrationArea = (uint32_t*) NVMCTRL_OTP5;
osc32kcal = ( (*pCalibrationArea) & 0x1FC0 ) >> 6;
/* RTC use Low Power Internal Oscillator at 1kHz */
OSC32KCTRL->OSC32K.reg = OSC32KCTRL_OSC32K_RUNSTDBY
| OSC32KCTRL_OSC32K_EN1K
| OSC32KCTRL_OSC32K_CALIB(osc32kcal)
| OSC32KCTRL_OSC32K_ENABLE;
/* Wait OSC32K Ready */
while (OSC32KCTRL->STATUS.bit.OSC32KRDY==0);
/* RTC uses internal 32,768KHz Oscillator */
OSC32KCTRL->RTCCTRL.reg = OSC32KCTRL_RTCCTRL_RTCSEL_OSC1K;
#endif /* INTERNAL_OSC32_SOURCE */
#if ULTRA_LOW_POWER_INTERNAL_OSC_SOURCE
/* RTC uses Ultra Low Power internal 32,768KHz Oscillator */
OSC32KCTRL->RTCCTRL.reg = OSC32KCTRL_RTCCTRL_RTCSEL_ULP1K;
#endif /* ULTRA_LOW_POWER_INTERNAL_OSC_SOURCE */
/* Software Reset the RTC */
RTC->MODE2.CTRLA.bit.SWRST = 1;
/* Wait end of reset */
while (RTC->MODE2.CTRLA.bit.SWRST);
/* RTC config with RTC_MODE2_CTRL_CLKREP = 0 (24h) */
RTC->MODE2.CTRLA.reg = RTC_MODE2_CTRLA_PRESCALER_DIV1024 | /* CLK_RTC_CNT = 1KHz / 1024 -> 1Hz */
RTC_MODE2_CTRLA_CLOCKSYNC | /* Clock Read Synchronization Enable */
RTC_MODE2_CTRLA_MODE_CLOCK; /* Mode 2: Clock/Calendar */
/* Clear interrupt flags */
RTC->MODE2.INTFLAG.reg |= RTC_MODE2_INTFLAG_OVF;
RTC->MODE2.INTFLAG.reg |= RTC_MODE2_INTFLAG_ALARM0;
rtc_poweron();
}
int rtc_set_time(struct tm *time)
{
if ((time->tm_year < reference_year) || (time->tm_year > reference_year + 63)) {
return -1;
}
else {
while (RTC->MODE2.SYNCBUSY.bit.CLOCK);
RTC->MODE2.CLOCK.reg = RTC_MODE2_CLOCK_YEAR(time->tm_year - reference_year)
| RTC_MODE2_CLOCK_MONTH(time->tm_mon + 1)
| RTC_MODE2_CLOCK_DAY(time->tm_mday)
| RTC_MODE2_CLOCK_HOUR(time->tm_hour)
| RTC_MODE2_CLOCK_MINUTE(time->tm_min)
| RTC_MODE2_CLOCK_SECOND(time->tm_sec);
while (RTC->MODE2.SYNCBUSY.bit.CLOCK);
}
return 0;
}
int rtc_get_time(struct tm *time)
{
RTC_MODE2_CLOCK_Type clock;
/* Read register in one time */
clock.reg = RTC->MODE2.CLOCK.reg;
time->tm_year = clock.bit.YEAR + reference_year;
if ((time->tm_year < reference_year) || (time->tm_year > (reference_year + 63))) {
return -1;
}
time->tm_mon = clock.bit.MONTH - 1;
time->tm_mday = clock.bit.DAY;
time->tm_hour = clock.bit.HOUR;
time->tm_min = clock.bit.MINUTE;
time->tm_sec = clock.bit.SECOND;
return 0;
}
int rtc_set_alarm(struct tm *time, rtc_alarm_cb_t cb, void *arg)
{
rtc_clear_alarm();
if ((time->tm_year < reference_year) || (time->tm_year > (reference_year + 63))) {
return -2;
}
else {
RTC->MODE2.Mode2Alarm[0].ALARM.reg = RTC_MODE2_ALARM_YEAR(time->tm_year - reference_year)
| RTC_MODE2_ALARM_MONTH(time->tm_mon + 1)
| RTC_MODE2_ALARM_DAY(time->tm_mday)
| RTC_MODE2_ALARM_HOUR(time->tm_hour)
| RTC_MODE2_ALARM_MINUTE(time->tm_min)
| RTC_MODE2_ALARM_SECOND(time->tm_sec);
RTC->MODE2.Mode2Alarm[0].MASK.reg = RTC_MODE2_MASK_SEL(6);
while (RTC->MODE2.SYNCBUSY.bit.ALARM0);
}
/* Setup interrupt */
NVIC_EnableIRQ(RTC_IRQn);
/* Enable IRQ */
rtc_callback.cb = cb;
rtc_callback.arg = arg;
RTC->MODE2.INTFLAG.reg |= RTC_MODE2_INTFLAG_ALARM0;
RTC->MODE2.INTENSET.bit.ALARM0 = 1;
return 0;
}
int rtc_get_alarm(struct tm *time)
{
RTC_MODE2_ALARM_Type alarm;
/* Read alarm register in one time */
alarm.reg = RTC->MODE2.Mode2Alarm[0].ALARM.reg;
time->tm_year = alarm.bit.YEAR + reference_year;
if ((time->tm_year < reference_year) || (time->tm_year > (reference_year + 63))) {
return -1;
}
time->tm_mon = alarm.bit.MONTH - 1;
time->tm_mday = alarm.bit.DAY;
time->tm_hour = alarm.bit.HOUR;
time->tm_min = alarm.bit.MINUTE;
time->tm_sec = alarm.bit.SECOND;
return 0;
}
void rtc_clear_alarm(void)
{
/* disable interrupt */
RTC->MODE2.INTENCLR.bit.ALARM0 = 1;
rtc_callback.cb = NULL;
rtc_callback.arg = NULL;
}
void rtc_poweron(void)
{
RTC->MODE2.CTRLA.bit.ENABLE = 1;
while (RTC->MODE2.SYNCBUSY.bit.ENABLE);
}
void rtc_poweroff(void)
{
RTC->MODE2.CTRLA.bit.ENABLE = 0;
while (RTC->MODE2.SYNCBUSY.bit.ENABLE);
}
void isr_rtc(void)
{
if (RTC->MODE2.INTFLAG.bit.ALARM0) {
rtc_callback.cb(rtc_callback.arg);
/* clear flag */
RTC->MODE2.INTFLAG.reg |= RTC_MODE2_INTFLAG_ALARM0;
}
if (RTC->MODE2.INTFLAG.bit.OVF) {
/* clear flag */
RTC->MODE2.INTFLAG.reg |= RTC_MODE2_INTFLAG_OVF;
/* At 1Hz, RTC goes till 63 years (2^5, see 17.8.22 in datasheet)
* Start RTC again with reference_year 64 years more (Be careful with alarm set) */
reference_year += 64;
}
cortexm_isr_end();
}
/*
* Copyright (C) 2015 Kaspar Schleiser <kaspar@schleiser.de>
* 2015 FreshTemp, LLC.
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @ingroup cpu_saml21
* @ingroup drivers_periph_rtt
* @{
*
* @file rtt.c
* @brief Low-level RTT driver implementation
*
* @author Kaspar Schleiser <kaspar@schleiser.de>
*
* @}
*/
#include <stdint.h>
#include "periph/rtt.h"
#include "board.h"
#define ENABLE_DEBUG 0
#include "debug.h"
static rtt_cb_t _overflow_cb;
static void* _overflow_arg;
static rtt_cb_t _cmp0_cb;
static void* _cmp0_arg;
void rtt_init(void)
{
DEBUG("%s:%d\n", __func__, __LINE__);
/* Turn on power manager for RTC */
MCLK->APBAMASK.reg |= MCLK_APBAMASK_RTC | MCLK_APBAMASK_OSC32KCTRL;
rtt_poweron();
/* reset */
RTC->MODE0.CTRLA.bit.SWRST = 1;
while(RTC->MODE0.CTRLA.bit.SWRST) {}
/* set 32bit counting mode */
RTC->MODE0.CTRLA.bit.MODE = 0;
/* set clock source */
OSC32KCTRL->RTCCTRL.reg = OSC32KCTRL_RTCCTRL_RTCSEL_ULP32K;
/* enable */
RTC->MODE0.CTRLA.bit.ENABLE = 1;
while(RTC->MODE0.SYNCBUSY.bit.ENABLE) {}
/* initially clear flag */
RTC->MODE0.INTFLAG.reg |= RTC_MODE1_INTFLAG_CMP(1 << 0);
/* enable RTT IRQ */
NVIC_EnableIRQ(RTC_IRQn);
DEBUG("%s:%d %u\n", __func__, __LINE__, (unsigned)rtt_get_counter());
}
void rtt_set_overflow_cb(rtt_cb_t cb, void *arg)
{
DEBUG("%s:%d\n", __func__, __LINE__);
/* clear overflow cb to avoid race while assigning */
rtt_clear_overflow_cb();
/* set callback variables */
_overflow_cb = cb;
_overflow_arg = arg;
/* enable overflow interrupt */
RTC->MODE0.INTENSET.bit.OVF = 1;
}
void rtt_clear_overflow_cb(void)
{
DEBUG("%s:%d\n", __func__, __LINE__);
/* disable overflow interrupt */
RTC->MODE0.INTENCLR.bit.OVF = 1;
}
uint32_t rtt_get_counter(void)
{
DEBUG("%s:%d\n", __func__, __LINE__);
while (RTC->MODE0.SYNCBUSY.bit.COUNT) {}
return RTC->MODE0.COUNT.reg;
}
void rtt_set_alarm(uint32_t alarm, rtt_cb_t cb, void *arg)
{
DEBUG("%s:%d alarm=%u\n", __func__, __LINE__, (unsigned)alarm);
/* disable interrupt to avoid race */
rtt_clear_alarm();
/* set COM register */
while (RTC->MODE0.SYNCBUSY.bit.COMP0) {}
RTC->MODE0.COMP[0].reg = alarm;
/* setup callback */
_cmp0_cb = cb;
_cmp0_arg = arg;
/* enable compare interrupt */
RTC->MODE0.INTENSET.bit.CMP0 = 1;
}
void rtt_clear_alarm(void)
{
DEBUG("%s:%d\n", __func__, __LINE__);
/* clear compare interrupt */
RTC->MODE0.INTENCLR.bit.CMP0 = 1;
}
void rtt_poweron(void)
{
DEBUG("%s:%d\n", __func__, __LINE__);
MCLK->APBAMASK.reg |= MCLK_APBAMASK_RTC;
}
void rtt_poweroff(void)
{
DEBUG("%s:%d\n", __func__, __LINE__);
MCLK->APBAMASK.reg &= ~MCLK_APBAMASK_RTC;
}
void isr_rtc(void)
{
if (RTC->MODE0.INTFLAG.bit.OVF) {
RTC->MODE0.INTFLAG.reg |= RTC_MODE0_INTFLAG_OVF;
if (_overflow_cb) {
_overflow_cb(_overflow_arg);
}
}
if (RTC->MODE0.INTFLAG.bit.CMP0) {
/* clear flag */
RTC->MODE0.INTFLAG.reg |= RTC_MODE1_INTFLAG_CMP(1 << 0);
/* disable interrupt */
RTC->MODE0.INTENCLR.bit.CMP0 = 1;
if (_cmp0_cb) {
_cmp0_cb(_cmp0_arg);
}
}
cortexm_isr_end();
}
/*
* Copyright (C) 2018 Mesotic SAS
*
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @ingroup cpu_saml1x
* @ingroup drivers_periph_timer
* @{
*
* @file timer.c
* @brief Low-level timer driver implementation
*
* @author Dylan Laduranty <dylan.laduranty@mesotic.com>
*
* @}
*/
#include <stdlib.h>
#include <stdio.h>
#include "board.h"
#include "cpu.h"
#include "periph/timer.h"
#include "periph_conf.h"
#define ENABLE_DEBUG (0)
#include "debug.h"
/**
* @brief Timer state memory
*/
static timer_isr_ctx_t config[TIMER_NUMOF];
/* enable timer interrupts */
static inline void _irq_enable(tim_t dev);
/**
* @brief Setup the given timer
*/
int timer_init(tim_t dev, unsigned long freq, timer_cb_t cb, void *arg)
{
/* at the moment, the timer can only run at 1MHz */
if (freq != 1000000ul) {
return -1;
}
/* configure GCLK0 to feed TC0 & TC1*/
GCLK->PCHCTRL[TC0_GCLK_ID].reg |= GCLK_PCHCTRL_CHEN | GCLK_PCHCTRL_GEN_GCLK0;
while (!(GCLK->PCHCTRL[TC0_GCLK_ID].reg & GCLK_PCHCTRL_CHEN)) {}
/* select the timer and enable the timer specific peripheral clocks */
switch (dev) {
#if TIMER_0_EN
case TIMER_0:
if (TIMER_0_DEV.CTRLA.bit.ENABLE) {
return 0;
}
MCLK->APBCMASK.reg |= MCLK_APBCMASK_TC0;
/* reset timer */
TIMER_0_DEV.CTRLA.bit.SWRST = 1;
while (TIMER_0_DEV.SYNCBUSY.bit.SWRST) {}
TIMER_0_DEV.CTRLA.reg |= TC_CTRLA_MODE_COUNT32 | /* choosing 32 bit mode */
TC_CTRLA_PRESCALER(4) | /* sourced by 4MHz with Presc 4 results in 1MHz*/
TC_CTRLA_PRESCSYNC_RESYNC; /* initial prescaler resync */
break;
#endif
case TIMER_UNDEFINED:
default:
return -1;
}
/* save callback */
config[dev].cb = cb;
config[dev].arg = arg;
/* enable interrupts for given timer */
_irq_enable(dev);
timer_start(dev);
return 0;
}
int timer_set_absolute(tim_t dev, int channel, unsigned int value)
{
DEBUG("Setting timer %i channel %i to %i\n", dev, channel, value);
/* get timer base register address */
switch (dev) {
#if TIMER_0_EN
case TIMER_0:
/* set timeout value */
switch (channel) {
case 0:
TIMER_0_DEV.INTFLAG.reg |= TC_INTFLAG_MC0;
TIMER_0_DEV.CC[0].reg = value;
TIMER_0_DEV.INTENSET.bit.MC0 = 1;
break;
case 1:
TIMER_0_DEV.INTFLAG.reg |= TC_INTFLAG_MC1;
TIMER_0_DEV.CC[1].reg = value;
TIMER_0_DEV.INTENSET.bit.MC1 = 1;
break;
default:
return -1;
}
break;
#endif
case TIMER_UNDEFINED:
default:
return -1;
}
return 1;
}
int timer_clear(tim_t dev, int channel)
{
/* get timer base register address */
switch (dev) {
#if TIMER_0_EN
case TIMER_0:
switch (channel) {
case 0:
TIMER_0_DEV.INTFLAG.reg |= TC_INTFLAG_MC0;
TIMER_0_DEV.INTENCLR.bit.MC0 = 1;
break;
case 1:
TIMER_0_DEV.INTFLAG.reg |= TC_INTFLAG_MC1;
TIMER_0_DEV.INTENCLR.bit.MC1 = 1;
break;
default:
return -1;
}
break;
#endif
case TIMER_UNDEFINED:
default:
return -1;
}
return 1;
}
unsigned int timer_read(tim_t dev)
{
switch (dev) {
#if TIMER_0_EN
case TIMER_0:
/* request syncronisation */
TIMER_0_DEV.CTRLBSET.bit.CMD = TC_CTRLBSET_CMD_READSYNC_Val;
while (TIMER_0_DEV.SYNCBUSY.bit.CTRLB) {
/* WORKAROUND to prevent being stuck there if timer not init */
if(!TIMER_0_DEV.CTRLA.bit.ENABLE) {
return 0;
}
}
return TIMER_0_DEV.COUNT.reg;
#endif
default:
return 0;
}
}
void timer_stop(tim_t dev)
{
switch (dev) {
#if TIMER_0_EN
case TIMER_0:
TIMER_0_DEV.CTRLA.bit.ENABLE = 0;
break;
#endif
case TIMER_UNDEFINED:
break;
}
}
void timer_start(tim_t dev)
{
switch (dev) {
#if TIMER_0_EN
case TIMER_0:
TIMER_0_DEV.CTRLA.bit.ENABLE = 1;
break;
#endif
case TIMER_UNDEFINED:
break;
}
}
static inline void _irq_enable(tim_t dev)
{
switch (dev) {
#if TIMER_0_EN
case TIMER_0:
NVIC_EnableIRQ(TC0_IRQn);
break;
#endif
case TIMER_UNDEFINED:
break;
}
}
#if TIMER_0_EN
void TIMER_0_ISR(void)
{
if (TIMER_0_DEV.INTFLAG.bit.MC0 && TIMER_0_DEV.INTENSET.bit.MC0) {
if(config[TIMER_0].cb) {
TIMER_0_DEV.INTFLAG.reg |= TC_INTFLAG_MC0;
TIMER_0_DEV.INTENCLR.reg = TC_INTENCLR_MC0;
config[TIMER_0].cb(config[TIMER_0].arg, 0);
}
}
else if (TIMER_0_DEV.INTFLAG.bit.MC1 && TIMER_0_DEV.INTENSET.bit.MC1) {
if(config[TIMER_0].cb) {
TIMER_0_DEV.INTFLAG.reg |= TC_INTFLAG_MC1;
TIMER_0_DEV.INTENCLR.reg = TC_INTENCLR_MC1;
config[TIMER_0].cb(config[TIMER_0].arg, 1);
}
}
cortexm_isr_end();
}
#endif /* TIMER_0_EN */
/*
* Copyright (C) 2018 Mesotic SAS
*
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @ingroup cpu_saml1x
* @{
*
* @file vectors.c
* @brief Startup code and interrupt vector definition
*
* @author Dylan Laduranty <dylan.laduranty@mesotic.com>
*
* @}
*/
#include <stdint.h>
#include "vectors_cortexm.h"
/* define a local dummy handler as it needs to be in the same compilation unit
* as the alias definition */
void dummy_handler(void) {
dummy_handler_default();
}
/* SAML1x specific interrupt vector */
WEAK_DEFAULT void isr_system(void);
WEAK_DEFAULT void isr_wdt(void);
WEAK_DEFAULT void isr_rtc(void);
WEAK_DEFAULT void isr_eic0(void);
WEAK_DEFAULT void isr_eic1(void);
WEAK_DEFAULT void isr_eic2(void);
WEAK_DEFAULT void isr_eic3(void);
WEAK_DEFAULT void isr_eic_other(void);
WEAK_DEFAULT void isr_freqm(void);
WEAK_DEFAULT void isr_nvmctrl(void);
WEAK_DEFAULT void isr_port(void);
WEAK_DEFAULT void isr_dmac0(void);
WEAK_DEFAULT void isr_dmac1(void);
WEAK_DEFAULT void isr_dmac2(void);
WEAK_DEFAULT void isr_dmac3(void);
WEAK_DEFAULT void isr_dmac_other(void);
WEAK_DEFAULT void isr_evsys0(void);
WEAK_DEFAULT void isr_evsys1(void);
WEAK_DEFAULT void isr_evsys2(void);
WEAK_DEFAULT void isr_evsys3(void);
WEAK_DEFAULT void isr_evsys_nschk(void);
WEAK_DEFAULT void isr_pac(void);
WEAK_DEFAULT void isr_sercom0_0(void);
WEAK_DEFAULT void isr_sercom0_1(void);
WEAK_DEFAULT void isr_sercom0_2(void);
WEAK_DEFAULT void isr_sercom0_other(void);
WEAK_DEFAULT void isr_sercom1_0(void);
WEAK_DEFAULT void isr_sercom1_1(void);
WEAK_DEFAULT void isr_sercom1_2(void);
WEAK_DEFAULT void isr_sercom1_other(void);
WEAK_DEFAULT void isr_sercom2_0(void);
WEAK_DEFAULT void isr_sercom2_1(void);
WEAK_DEFAULT void isr_sercom2_2(void);
WEAK_DEFAULT void isr_sercom2_other(void);
WEAK_DEFAULT void isr_tc0(void);
WEAK_DEFAULT void isr_tc1(void);
WEAK_DEFAULT void isr_tc2(void);
WEAK_DEFAULT void isr_adc_other(void);
WEAK_DEFAULT void isr_adc_resrdy(void);
WEAK_DEFAULT void isr_ac(void);
WEAK_DEFAULT void isr_dac_underrun_a(void);
WEAK_DEFAULT void isr_dac_empty(void);
WEAK_DEFAULT void isr_ptc(void);
WEAK_DEFAULT void isr_trng(void);
WEAK_DEFAULT void isr_tram(void);
/* CPU specific interrupt vector table */
ISR_VECTOR(1) const isr_t vector_cpu[CPU_IRQ_NUMOF] = {
(void*) isr_system, /* 0 Main Clock */
(void*) isr_wdt, /* 1 Watchdog Timer */
(void*) isr_rtc, /* 2 Real-Time Counter */
(void*) isr_eic0, /* 3 External Interrupt Controller */
(void*) isr_eic1, /* 4 External Interrupt Controller */
(void*) isr_eic2, /* 5 External Interrupt Controller */
(void*) isr_eic3, /* 6 External Interrupt Controller */
(void*) isr_eic_other, /* 7 External Interrupt Controller */
(void*) isr_freqm, /* 8 Frequency Meter */
(void*) isr_nvmctrl, /* 9 Non-Volatile Memory Controller */
(void*) isr_port, /* 10 Port Module */
(void*) isr_dmac0, /* 11 Direct Memory Access Controller */
(void*) isr_dmac1, /* 12 Direct Memory Access Controller */
(void*) isr_dmac2, /* 13 Direct Memory Access Controller */
(void*) isr_dmac3, /* 14 Direct Memory Access Controller */
(void*) isr_dmac_other, /* 15 Direct Memory Access Controller */
(void*) isr_evsys0, /* 16 Event System Interface */
(void*) isr_evsys1, /* 17 Event System Interface */
(void*) isr_evsys2, /* 18 Event System Interface */
(void*) isr_evsys3, /* 19 Event System Interface */
(void*) isr_evsys_nschk, /* 20 Event System Interface */
(void*) isr_pac, /* 21 Peripheral Access Controller */
(void*) isr_sercom0_0, /* 22 Serial Communication Interface */
(void*) isr_sercom0_1, /* 23 Serial Communication Interface */
(void*) isr_sercom0_2, /* 24 Serial Communication Interface */
(void*) isr_sercom0_other, /* 25 Serial Communication Interface */
(void*) isr_sercom1_0, /* 26 Serial Communication Interface */
(void*) isr_sercom1_1, /* 27 Serial Communication Interface */
(void*) isr_sercom1_2, /* 28 Serial Communication Interface */
(void*) isr_sercom1_other, /* 29 Serial Communication Interface */
(void*) isr_sercom2_0, /* 30 Serial Communication Interface */
(void*) isr_sercom2_1, /* 31 Serial Communication Interface */
(void*) isr_sercom2_2, /* 32 Serial Communication Interface */
(void*) isr_sercom2_other, /* 33 Serial Communication Interface */
(void*) isr_tc0, /* 34 Basic Timer Counter */
(void*) isr_tc1, /* 35 Basic Timer Counter */
(void*) isr_tc2, /* 36 Basic Timer Counter */
(void*) isr_adc_other, /* 37 Analog Digital Converter */
(void*) isr_adc_resrdy, /* 38 Analog Digital Converter */
(void*) isr_ac, /* 39 Analog Comparators */
(void*) isr_dac_underrun_a, /* 40 Digital Analog Converter */
(void*) isr_dac_empty, /* 41 Analog Digital Converter */
(void*) isr_ptc, /* 42 Peripheral Touch Controller */
(void*) isr_trng, /* 43 True Random Number Generator */
(void*) isr_tram, /* 44 Trust RAM */
};
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment