1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00

cpu/samd5x: add support for samd5x/same5x MCUs

This adds supoprt for the Atmel SAMD51 & SAME54 SoC.
The SAME5x/SAMD5x is a line of Cortex-M4F MCUs that share peripherals
with the samd2x Cortex-M0+ and saml1x Cortex-M23 parts.
This commit is contained in:
Benjamin Valentin 2019-03-12 13:57:27 +01:00
parent 3cd119a6e6
commit f375b00ff3
18 changed files with 751 additions and 47 deletions

View File

@ -10,6 +10,10 @@ ifneq (,$(filter saml10e16a saml11e16a,$(CPU_MODEL)))
ROM_LEN ?= 64K
RAM_LEN ?= 16K
endif
ifneq (,$(filter samd51j20a same54p20a,$(CPU_MODEL)))
ROM_LEN ?= 1024K
RAM_LEN ?= 256K
endif
ROM_START_ADDR ?= 0x00000000
RAM_START_ADDR ?= 0x20000000

View File

@ -24,6 +24,8 @@
#include "cpu_conf_common.h"
#if defined(CPU_SAML1X)
#include "vendor/sam23.h"
#elif defined(CPU_SAMD5X)
#include "vendor/samd5x.h"
#else
#include "vendor/sam0.h"
#endif
@ -52,11 +54,22 @@ extern "C" {
* @{
*/
/* a flashpage in RIOT is mapped to a flash row on the SAM0s */
#define FLASHPAGE_SIZE (256U)
#if defined(NVMCTRL_ROW_SIZE)
#define FLASHPAGE_SIZE (NVMCTRL_ROW_SIZE)
#elif defined(NVMCTRL_BLOCK_SIZE)
#define FLASHPAGE_SIZE (NVMCTRL_BLOCK_SIZE)
#elif defined(NVMCTRL_PAGE_SIZE)
/* saml1x: The NVM is organized into rows, where each row contains four pages,
as shown in the NVM Row Organization figure. */
#define FLASHPAGE_SIZE (4 * NVMCTRL_PAGE_SIZE)
#else
#error "Unsupported Device"
#endif
/* one SAM0 row contains 4 SAM0 pages, so 4 SAM0 pages contain
* the amount of a RIOT flashpage
*/
#define FLASHPAGE_PAGES_PER_ROW (4)
#define FLASHPAGE_PAGES_PER_ROW (FLASHPAGE_SIZE/FLASH_PAGE_SIZE)
/* number of RIOT flashpages on device */
#define FLASHPAGE_NUMOF (FLASH_NB_OF_PAGES / FLASHPAGE_PAGES_PER_ROW)
/* The minimum block size which can be written is 16B. However, the erase

View File

@ -82,6 +82,7 @@ enum {
PA = 0, /**< port A */
PB = 1, /**< port B */
PC = 2, /**< port C */
PD = 3, /**< port D */
};
/**
@ -368,11 +369,20 @@ static inline int sercom_id(const void *sercom)
*/
static inline void sercom_clk_en(void *sercom)
{
const uint8_t id = sercom_id(sercom);
#if defined(CPU_FAM_SAMD21)
PM->APBCMASK.reg |= (PM_APBCMASK_SERCOM0 << sercom_id(sercom));
PM->APBCMASK.reg |= (PM_APBCMASK_SERCOM0 << id);
#elif defined (CPU_FAM_SAMD5X)
if (id < 2) {
MCLK->APBAMASK.reg |= (1 << (id + 12));
} else if (id < 4) {
MCLK->APBBMASK.reg |= (1 << (id + 7));
} else {
MCLK->APBDMASK.reg |= (1 << (id - 4));
}
#else
if (sercom_id(sercom) < 5) {
MCLK->APBCMASK.reg |= (MCLK_APBCMASK_SERCOM0 << sercom_id(sercom));
if (id < 5) {
MCLK->APBCMASK.reg |= (MCLK_APBCMASK_SERCOM0 << id);
}
#if defined(CPU_FAM_SAML21)
else {
@ -389,11 +399,20 @@ static inline void sercom_clk_en(void *sercom)
*/
static inline void sercom_clk_dis(void *sercom)
{
const uint8_t id = sercom_id(sercom);
#if defined(CPU_FAM_SAMD21)
PM->APBCMASK.reg &= ~(PM_APBCMASK_SERCOM0 << sercom_id(sercom));
PM->APBCMASK.reg &= ~(PM_APBCMASK_SERCOM0 << id);
#elif defined (CPU_FAM_SAMD5X)
if (id < 2) {
MCLK->APBAMASK.reg &= ~(1 << (id + 12));
} else if (id < 4) {
MCLK->APBBMASK.reg &= ~(1 << (id + 7));
} else {
MCLK->APBDMASK.reg &= ~(1 << (id - 4));
}
#else
if (sercom_id(sercom) < 5) {
MCLK->APBCMASK.reg &= ~(MCLK_APBCMASK_SERCOM0 << sercom_id(sercom));
if (id < 5) {
MCLK->APBCMASK.reg &= ~(MCLK_APBCMASK_SERCOM0 << id);
}
#if defined (CPU_FAM_SAML21)
else {
@ -403,6 +422,17 @@ static inline void sercom_clk_dis(void *sercom)
#endif
}
#ifdef CPU_FAM_SAMD5X
static inline uint8_t _sercom_gclk_id_core(uint8_t sercom_id) {
if (sercom_id < 2)
return sercom_id + 7;
if (sercom_id < 4)
return sercom_id + 21;
else
return sercom_id + 30;
}
#endif
/**
* @brief Configure generator clock for given SERCOM device
*
@ -411,19 +441,20 @@ static inline void sercom_clk_dis(void *sercom)
*/
static inline void sercom_set_gen(void *sercom, uint32_t gclk)
{
const uint8_t id = sercom_id(sercom);
#if defined(CPU_FAM_SAMD21)
GCLK->CLKCTRL.reg = (GCLK_CLKCTRL_CLKEN | gclk |
(SERCOM0_GCLK_ID_CORE + sercom_id(sercom)));
(SERCOM0_GCLK_ID_CORE + id));
while (GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY) {}
#elif defined(CPU_FAM_SAMD5X)
GCLK->PCHCTRL[_sercom_gclk_id_core(id)].reg = (GCLK_PCHCTRL_CHEN | gclk);
#else
if (sercom_id(sercom) < 5) {
GCLK->PCHCTRL[SERCOM0_GCLK_ID_CORE + sercom_id(sercom)].reg =
(GCLK_PCHCTRL_CHEN | gclk);
if (id < 5) {
GCLK->PCHCTRL[SERCOM0_GCLK_ID_CORE + id].reg = (GCLK_PCHCTRL_CHEN | gclk);
}
#if defined(CPU_FAM_SAML21)
else {
GCLK->PCHCTRL[SERCOM5_GCLK_ID_CORE].reg =
(GCLK_PCHCTRL_CHEN | gclk);
GCLK->PCHCTRL[SERCOM5_GCLK_ID_CORE].reg = (GCLK_PCHCTRL_CHEN | gclk);
}
#endif /* CPU_FAM_SAML21 */
#endif

View File

@ -25,11 +25,17 @@
#include "periph/cpuid.h"
#ifdef CPU_SAMD5X
#define WORD0 (*(volatile uint32_t *)0x008061FC)
#define WORD1 (*(volatile uint32_t *)0x00806010)
#define WORD2 (*(volatile uint32_t *)0x00806014)
#define WORD3 (*(volatile uint32_t *)0x00806018)
#else
#define WORD0 (*(volatile uint32_t *)0x0080A00C)
#define WORD1 (*(volatile uint32_t *)0x0080A040)
#define WORD2 (*(volatile uint32_t *)0x0080A044)
#define WORD3 (*(volatile uint32_t *)0x0080A048)
#endif
void cpuid_get(void *id)
{

View File

@ -47,7 +47,7 @@
static inline void wait_nvm_is_ready(void) __attribute__((always_inline));
static inline void wait_nvm_is_ready(void)
{
#ifdef CPU_SAML1X
#if defined(CPU_SAML1X) || defined(CPU_SAMD5X)
while (!_NVMCTRL->STATUS.bit.READY) {}
#else
while (!_NVMCTRL->INTFLAG.bit.READY) {}
@ -57,7 +57,7 @@ static inline void wait_nvm_is_ready(void)
static void _unlock(void)
{
/* remove peripheral access lock for the NVMCTRL peripheral */
#if defined(CPU_FAM_SAML21) || defined(CPU_SAML1X)
#ifdef REG_PAC_WRCTRL
PAC->WRCTRL.reg = (PAC_WRCTRL_KEY_CLR | ID_NVMCTRL);
#else
if (PAC1->WPSET.reg & NVMCTRL_PAC_BIT) {
@ -69,7 +69,7 @@ static void _unlock(void)
static void _lock(void)
{
/* put peripheral access lock for the NVMCTRL peripheral */
#if defined(CPU_FAM_SAML21) || defined(CPU_SAML1X)
#ifdef REG_PAC_WRCTRL
PAC->WRCTRL.reg = (PAC_WRCTRL_KEY_SET | ID_NVMCTRL);
#else
if (PAC1->WPCLR.reg & NVMCTRL_PAC_BIT) {
@ -113,7 +113,11 @@ void flashpage_write_raw(void *target_addr, const void *data, size_t len)
len /= 4;
_unlock();
#ifdef NVMCTRL_CTRLB_CMDEX_KEY
_NVMCTRL->CTRLB.reg = (NVMCTRL_CTRLB_CMDEX_KEY | NVMCTRL_CTRLB_CMD_PBC);
#else
_NVMCTRL->CTRLA.reg = (NVMCTRL_CTRLA_CMDEX_KEY | NVMCTRL_CTRLA_CMD_PBC);
#endif
wait_nvm_is_ready();
for (unsigned i = 0; i < len; i++) {
*dst++ = *data_addr++;
@ -128,7 +132,11 @@ void flashpage_write_raw(void *target_addr, const void *data, size_t len)
#endif
} else {
#endif
#ifdef NVMCTRL_CTRLB_CMDEX_KEY
_NVMCTRL->CTRLB.reg = (NVMCTRL_CTRLB_CMDEX_KEY | NVMCTRL_CTRLB_CMD_WP);
#else
_NVMCTRL->CTRLA.reg = (NVMCTRL_CTRLA_CMDEX_KEY | NVMCTRL_CTRLA_CMD_WP);
#endif
#ifdef FLASHPAGE_RWWEE_NUMOF
}
#endif
@ -156,7 +164,7 @@ void flashpage_write(int page, const void *data)
/* erase given page (the ADDR register uses 16-bit addresses) */
_unlock();
#ifdef CPU_SAML1X
#if defined(CPU_SAML1X) || defined(CPU_SAMD5X)
/* Ensure address alignment */
_NVMCTRL->ADDR.reg = (((uint32_t)page_addr) & 0xfffffffe);
#else
@ -172,7 +180,11 @@ void flashpage_write(int page, const void *data)
#endif
} else {
#endif
#ifdef NVMCTRL_CTRLB_CMDEX_KEY
_NVMCTRL->CTRLB.reg = (NVMCTRL_CTRLB_CMDEX_KEY | NVMCTRL_CTRLB_CMD_EB);
#else
_NVMCTRL->CTRLA.reg = (NVMCTRL_CTRLA_CMDEX_KEY | NVMCTRL_CTRLA_CMD_ER);
#endif
#ifdef FLASHPAGE_RWWEE_NUMOF
}
#endif

View File

@ -205,6 +205,8 @@ int gpio_init_int(gpio_t pin, gpio_mode_t mode, gpio_flank_t flank,
#ifdef CPU_SAML1X
/* EXTI[4..7] are binded to EIC_OTHER_IRQn */
NVIC_EnableIRQ((exti > 3 )? EIC_OTHER_IRQn : (EIC_0_IRQn + exti));
#elif defined(CPU_SAMD5X)
NVIC_EnableIRQ(EIC_0_IRQn + exti);
#else
NVIC_EnableIRQ(EIC_IRQn);
#endif
@ -253,31 +255,34 @@ void isr_eic(void)
cortexm_isr_end();
}
#ifdef CPU_SAML1X
void isr_eic0(void)
{
isr_eic();
#if defined(CPU_SAML1X) || defined(CPU_SAMD5X)
#define ISR_EICn(n) \
void isr_eic ## n (void) \
{ \
isr_eic(); \
}
void isr_eic1(void)
{
isr_eic();
}
void isr_eic2(void)
{
isr_eic();
}
void isr_eic3(void)
{
isr_eic();
}
void isr_eic_other(void)
{
isr_eic();
}
ISR_EICn(0)
ISR_EICn(1)
ISR_EICn(2)
ISR_EICn(3)
#if defined(CPU_SAMD5X)
ISR_EICn(4)
ISR_EICn(5)
ISR_EICn(6)
ISR_EICn(7)
ISR_EICn(8)
ISR_EICn(9)
ISR_EICn(10)
ISR_EICn(11)
ISR_EICn(12)
ISR_EICn(13)
ISR_EICn(14)
ISR_EICn(15)
#else
ISR_EICn(_other)
#endif /* CPU_SAML1X */
#endif /* CPU_SAML1X || CPU_SAMD5X */
#endif /* MODULE_PERIPH_GPIO_IRQ */

View File

@ -44,7 +44,7 @@
#define BUSSTATE_OWNER SERCOM_I2CM_STATUS_BUSSTATE(2)
#define BUSSTATE_BUSY SERCOM_I2CM_STATUS_BUSSTATE(3)
#if defined(CPU_SAML21) || defined(CPU_SAML1X)
#if defined(CPU_SAML21) || defined(CPU_SAML1X) || defined(CPU_SAMD5X)
#define SERCOM_I2CM_CTRLA_MODE_I2C_MASTER SERCOM_I2CM_CTRLA_MODE(5)
#endif

View File

@ -99,7 +99,7 @@ int uart_init(uart_t uart, uint32_t baudrate, uart_rx_cb_t rx_cb, void *arg)
if ((rx_cb) && (uart_config[uart].rx_pin != GPIO_UNDEF)) {
uart_ctx[uart].rx_cb = rx_cb;
uart_ctx[uart].arg = arg;
#if defined (CPU_SAML1X)
#if defined (CPU_SAML1X) || defined (CPU_SAMD5X)
NVIC_EnableIRQ(SERCOM0_2_IRQn + (sercom_id(dev(uart)) * 4));
#else
NVIC_EnableIRQ(SERCOM0_IRQn + sercom_id(dev(uart)));

View File

@ -229,17 +229,24 @@ static bool _syncbusy_swrst(sam0_common_usb_t *dev)
static inline void _poweron(void)
{
#if defined(CPU_FAM_SAMD21)
#if defined(MCLK)
MCLK->AHBMASK.reg |= MCLK_AHBMASK_USB;
MCLK->APBBMASK.reg |= MCLK_APBBMASK_USB;
#else
PM->AHBMASK.reg |= PM_AHBMASK_USB;
PM->APBBMASK.reg |= PM_APBBMASK_USB;
#endif
#if defined(CPU_FAM_SAMD21)
GCLK->CLKCTRL.reg = (uint32_t)(GCLK_CLKCTRL_CLKEN |
GCLK_CLKCTRL_GEN_GCLK0 |
(GCLK_CLKCTRL_ID(USB_GCLK_ID)));
#elif defined(CPU_FAM_SAML21)
MCLK->AHBMASK.reg |= MCLK_AHBMASK_USB;
MCLK->APBBMASK.reg |= MCLK_APBBMASK_USB;
GCLK->PCHCTRL[USB_GCLK_ID].reg = GCLK_PCHCTRL_CHEN |
GCLK_PCHCTRL_GEN_GCLK0;
#elif defined(CPU_FAM_SAMD5X)
GCLK->PCHCTRL[USB_GCLK_ID].reg = GCLK_PCHCTRL_CHEN |
GCLK_PCHCTRL_GEN_GCLK6;
#else
#error "Unknown CPU family for sam0 common usbdev driver"
#endif
@ -356,7 +363,14 @@ static void _usbdev_init(usbdev_t *dev)
_block_pm();
usbdev->usbdev.cb(&usbdev->usbdev, USBDEV_EVENT_HOST_CONNECT);
/* Interrupt configuration */
#ifdef CPU_FAM_SAMD5X
NVIC_EnableIRQ(USB_0_IRQn);
NVIC_EnableIRQ(USB_1_IRQn);
NVIC_EnableIRQ(USB_2_IRQn);
NVIC_EnableIRQ(USB_3_IRQn);
#else
NVIC_EnableIRQ(USB_IRQn);
#endif
}
static void usb_attach(sam0_common_usb_t *dev)
@ -504,6 +518,24 @@ void isr_usb(void)
cortexm_isr_end();
}
void isr_usb0(void)
{
isr_usb();
}
void isr_usb1(void)
{
isr_usb();
}
void isr_usb2(void)
{
isr_usb();
}
void isr_usb3(void)
{
isr_usb();
}
static void _usbdev_esr(usbdev_t *dev)
{
sam0_common_usb_t *usbdev = (sam0_common_usb_t *)dev;

10
cpu/samd5x/Makefile Normal file
View File

@ -0,0 +1,10 @@
# 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

View File

@ -0,0 +1 @@
include $(RIOTCPU)/sam0_common/Makefile.features

View File

@ -0,0 +1,12 @@
export CPU_ARCH = cortex-m4f
export CPU_FAM = samd5x
# Slot size is determined by "((total_flash_size - RIOTBOOT_LEN) / 2)".
# If RIOTBOOT_LEN uses an uneven number of flashpages, the remainder of the
# flash cannot be divided by two slots while staying FLASHPAGE_SIZE aligned.
RIOTBOOT_LEN ?= 0x2000
USEMODULE += pm_layered
include $(RIOTCPU)/sam0_common/Makefile.include
include $(RIOTMAKE)/arch/cortexm.inc.mk

127
cpu/samd5x/cpu.c Normal file
View File

@ -0,0 +1,127 @@
/*
* Copyright (C) 2019 ML!PA Consulting GmbH
*
* 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_samd5x
* @{
*
* @file cpu.c
* @brief Implementation of the CPU initialization for Microchip SAMD5x/SAME5x MCUs
*
* @author Benjamin Valentin <benjamin.valentin@ml-pa.com>
* @}
*/
#include "cpu.h"
#include "periph_conf.h"
#include "periph/init.h"
static void xosc32k_init(void)
{
OSC32KCTRL->XOSC32K.reg = OSC32KCTRL_XOSC32K_ENABLE | OSC32KCTRL_XOSC32K_XTALEN
| OSC32KCTRL_XOSC32K_EN32K | OSC32KCTRL_XOSC32K_RUNSTDBY
| OSC32KCTRL_XOSC32K_STARTUP(7);
while (!OSC32KCTRL->STATUS.bit.XOSC32KRDY) {}
}
#ifdef MODULE_PERIPH_USBDEV
static void dfll_init(void)
{
uint32_t reg = OSCCTRL_DFLLCTRLB_QLDIS
#ifdef OSCCTRL_DFLLCTRLB_WAITLOCK
| OSCCTRL_DFLLCTRLB_WAITLOCK
#endif
;
OSCCTRL->DFLLCTRLB.reg = reg;
OSCCTRL->DFLLCTRLA.reg = OSCCTRL_DFLLCTRLA_ENABLE;
}
#endif
static void fdpll0_init(uint32_t f_cpu)
{
const uint32_t LDR = ((f_cpu << 5) / 32768);
GCLK->PCHCTRL[OSCCTRL_GCLK_ID_FDPLL0].reg = GCLK_PCHCTRL_GEN(1) | GCLK_PCHCTRL_CHEN;
OSCCTRL->Dpll[0].DPLLRATIO.reg = OSCCTRL_DPLLRATIO_LDRFRAC(LDR & 0x1F)
| OSCCTRL_DPLLRATIO_LDR((LDR >> 5) - 1);
OSCCTRL->Dpll[0].DPLLCTRLB.reg = OSCCTRL_DPLLCTRLB_REFCLK_GCLK
| OSCCTRL_DPLLCTRLB_WUF
| OSCCTRL_DPLLCTRLB_LBYPASS;
OSCCTRL->Dpll[0].DPLLCTRLA.reg = OSCCTRL_DPLLCTRLA_ENABLE;
while (!(OSCCTRL->Dpll[0].DPLLSTATUS.bit.CLKRDY &&
OSCCTRL->Dpll[0].DPLLSTATUS.bit.LOCK)) {}
}
static void gclk_connect(uint8_t id, uint8_t src, uint32_t flags) {
GCLK->GENCTRL[id].reg = GCLK_GENCTRL_SRC(src) | GCLK_GENCTRL_GENEN | flags | GCLK_GENCTRL_IDC;
}
/**
* @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_OSC32KCTRL
| MCLK_APBAMASK_GCLK
#ifdef MODULE_PERIPH_GPIO_IRQ
| MCLK_APBAMASK_EIC
#endif
;
#ifdef MODULE_PERIPH_GPIO
MCLK->APBBMASK.reg = MCLK_APBBMASK_PORT;
#endif
/* enable the Cortex M Cache Controller */
CMCC->CTRL.bit.CEN = 1;
/* 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) {}
xosc32k_init();
gclk_connect(1, GCLK_SOURCE_XOSC32K, 0);
fdpll0_init(CLOCK_CORECLOCK);
/* main clock */
gclk_connect(0, GCLK_SOURCE_DPLL0, 0);
/* clock used by xtimer */
gclk_connect(5, GCLK_SOURCE_DPLL0, GCLK_GENCTRL_DIV(CLOCK_CORECLOCK / 8000000));
#ifdef MODULE_PERIPH_USBDEV
dfll_init();
gclk_connect(6, GCLK_SOURCE_DFLL, 0);
#endif
while (GCLK->SYNCBUSY.reg) {}
#ifdef MODULE_PERIPH_PM
/* enable power managemet module */
MCLK->APBAMASK.reg |= MCLK_APBAMASK_PM;
#endif
#ifdef MODULE_PERIPH_FLASHPAGE
MCLK->APBBMASK.reg |= MCLK_APBBMASK_NVMCTRL;
#endif
/* trigger static peripheral initialization */
periph_init();
}

9
cpu/samd5x/doc.txt Normal file
View File

@ -0,0 +1,9 @@
/**
* @defgroup cpu_samd5x Microchip SAMD5x/SAME5x
* @ingroup cpu
* @brief Microchip SAMD5x/SAME5x Cortex-M4F MCU specific implementation.
*
* This module contains Microchip SAMD5x/SAME5x specific code and definition.
*
* @see cpu_sam0_common
*/

View File

@ -0,0 +1,70 @@
/*
* Copyright (C) 2019 ML!PA Consulting GmbH
*
* 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_samd5x
* @brief CPU specific definitions for internal peripheral handling
* @{
*
* @file
* @brief CPU specific definitions for internal peripheral handling
*
* @author Benjamin Valentin <benjamin.valentin@ml-pa.com>
*/
#ifndef PERIPH_CPU_H
#define PERIPH_CPU_H
#include <limits.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[4][32] = {
#ifdef CPU_MODEL_SAMD51J20A
{ 0, 1, 2, 3, 4, 5, 6, 7, -1, 9, 10, 11, 12, 13, 14, 15,
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, 11, -1, -1, 14, 15 },
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
0, 1, -1, -1, -1, -1, 6, 7, -1, -1, -1, -1, -1, -1, 14, 15 },
{-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
#elif CPU_MODEL_SAME54P20A
{ 0, 1, 2, 3, 4, 5, 6, 7, -1, 9, 10, 11, 12, 13, 14, 15,
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, 11, -1, -1, 14, 15 },
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 12, 13, 14, 15, 14, 15 },
{ 0, 1, 2, 3, 4, 5, 6, 9, -1, -1, 10, 11, 12, 13, 14, 15,
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, -1, 14, 15 },
{ 0, 1, -1, -1, -1, -1, -1, -1, 3, 4, 5, 6, 7, -1, -1, -1,
-1, -1, -1, -1, 10, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }
#else
#error Please define a proper CPU_MODEL.
#endif
};
/**
* @brief Override SPI hardware chip select macro
*
* As of now, we do not support HW CS, so we always set it to a fixed value
*/
#define SPI_HWCS(x) (UINT_MAX - 1)
#ifdef __cplusplus
}
#endif
#endif /* PERIPH_CPU_H */
/** @} */

View File

@ -0,0 +1 @@
include $(RIOTMAKE)/periph.mk

66
cpu/samd5x/periph/pm.c Normal file
View File

@ -0,0 +1,66 @@
/*
* Copyright (C) 2019 ML!PA Consulting GmbH
*
* 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_samd5x
* @ingroup drivers_periph_pm
* @{
*
* @file
* @brief Implementation of the kernels power management interface
*
* @author Benjamin Valentin <benjamin.valentin@ml-pa.com>
*
* @}
*/
#include "periph/pm.h"
#define ENABLE_DEBUG (0)
#if ENABLE_DEBUG
#define DEBUG(s) puts(s)
#else
#define DEBUG(s)
#endif
void pm_set(unsigned mode)
{
bool deep = 0;
uint32_t _mode;
switch (mode) {
case 0:
DEBUG("pm_set(): setting BACKUP mode.");
_mode = PM_SLEEPCFG_SLEEPMODE_BACKUP;
deep = 1;
break;
case 1:
DEBUG("pm_set(): setting HIBERNATE mode.");
_mode = PM_SLEEPCFG_SLEEPMODE_HIBERNATE;
deep = 1;
break;
case 2:
DEBUG("pm_set(): setting STANDBY mode.");
_mode = PM_SLEEPCFG_SLEEPMODE_STANDBY;
deep = 1;
break;
default: /* Falls through */
case 3:
DEBUG("pm_set(): setting IDLE2 mode.");
_mode = PM_SLEEPCFG_SLEEPMODE_IDLE2;
break;
}
/* write sleep configuration */
PM->SLEEPCFG.bit.SLEEPMODE = _mode;
/* make sure value has been set */
while (PM->SLEEPCFG.bit.SLEEPMODE != _mode) {}
cortexm_sleep(deep);
}

305
cpu/samd5x/vectors.c Normal file
View File

@ -0,0 +1,305 @@
/*
* Copyright (C) 2019 ML!PA Consulting GmbH
*
* 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_samd5x
* @{
*
* @file
* @brief Startup code and interrupt vector definition
*
* @author Benjamin Valentin <benjamin.valentin@ml-pa.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();
}
/* SAME54 specific interrupt vector */
WEAK_DEFAULT void isr_pm ( void );
WEAK_DEFAULT void isr_mclk ( void );
WEAK_DEFAULT void isr_oscctrl0 ( void );
WEAK_DEFAULT void isr_oscctrl1 ( void );
WEAK_DEFAULT void isr_oscctrl2 ( void );
WEAK_DEFAULT void isr_oscctrl3 ( void );
WEAK_DEFAULT void isr_oscctrl4 ( void );
WEAK_DEFAULT void isr_osc32kctrl ( void );
WEAK_DEFAULT void isr_supc0 ( void );
WEAK_DEFAULT void isr_supc1 ( 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_eic4 ( void );
WEAK_DEFAULT void isr_eic5 ( void );
WEAK_DEFAULT void isr_eic6 ( void );
WEAK_DEFAULT void isr_eic7 ( void );
WEAK_DEFAULT void isr_eic8 ( void );
WEAK_DEFAULT void isr_eic9 ( void );
WEAK_DEFAULT void isr_eic10 ( void );
WEAK_DEFAULT void isr_eic11 ( void );
WEAK_DEFAULT void isr_eic12 ( void );
WEAK_DEFAULT void isr_eic13 ( void );
WEAK_DEFAULT void isr_eic14 ( void );
WEAK_DEFAULT void isr_eic15 ( void );
WEAK_DEFAULT void irq_freqm ( void );
WEAK_DEFAULT void isr_nvmctrl0 ( void );
WEAK_DEFAULT void isr_nvmctrl1 ( 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_dmac4 ( 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_evsys4 ( void );
WEAK_DEFAULT void isr_pac ( void );
WEAK_DEFAULT void irq_ramecc ( 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_3 ( 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_3 ( 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_3 ( void );
WEAK_DEFAULT void isr_sercom3_0 ( void );
WEAK_DEFAULT void isr_sercom3_1 ( void );
WEAK_DEFAULT void isr_sercom3_2 ( void );
WEAK_DEFAULT void isr_sercom3_3 ( void );
WEAK_DEFAULT void isr_sercom4_0 ( void );
WEAK_DEFAULT void isr_sercom4_1 ( void );
WEAK_DEFAULT void isr_sercom4_2 ( void );
WEAK_DEFAULT void isr_sercom4_3 ( void );
WEAK_DEFAULT void isr_sercom5_0 ( void );
WEAK_DEFAULT void isr_sercom5_1 ( void );
WEAK_DEFAULT void isr_sercom5_2 ( void );
WEAK_DEFAULT void isr_sercom5_3 ( void );
WEAK_DEFAULT void isr_sercom6_0 ( void );
WEAK_DEFAULT void isr_sercom6_1 ( void );
WEAK_DEFAULT void isr_sercom6_2 ( void );
WEAK_DEFAULT void isr_sercom6_3 ( void );
WEAK_DEFAULT void isr_sercom7_0 ( void );
WEAK_DEFAULT void isr_sercom7_1 ( void );
WEAK_DEFAULT void isr_sercom7_2 ( void );
WEAK_DEFAULT void isr_sercom7_3 ( void );
WEAK_DEFAULT void isr_can0 ( void );
WEAK_DEFAULT void isr_can1 ( void );
WEAK_DEFAULT void isr_usb0 ( void );
WEAK_DEFAULT void isr_usb1 ( void );
WEAK_DEFAULT void isr_usb2 ( void );
WEAK_DEFAULT void isr_usb3 ( void );
WEAK_DEFAULT void isr_gmac ( void );
WEAK_DEFAULT void isr_tcc0_0 ( void );
WEAK_DEFAULT void isr_tcc0_1 ( void );
WEAK_DEFAULT void isr_tcc0_2 ( void );
WEAK_DEFAULT void isr_tcc0_3 ( void );
WEAK_DEFAULT void isr_tcc0_4 ( void );
WEAK_DEFAULT void isr_tcc0_5 ( void );
WEAK_DEFAULT void isr_tcc0_6 ( void );
WEAK_DEFAULT void isr_tcc1_0 ( void );
WEAK_DEFAULT void isr_tcc1_1 ( void );
WEAK_DEFAULT void isr_tcc1_2 ( void );
WEAK_DEFAULT void isr_tcc1_3 ( void );
WEAK_DEFAULT void isr_tcc1_4 ( void );
WEAK_DEFAULT void isr_tcc2_0 ( void );
WEAK_DEFAULT void isr_tcc2_1 ( void );
WEAK_DEFAULT void isr_tcc2_2 ( void );
WEAK_DEFAULT void isr_tcc2_3 ( void );
WEAK_DEFAULT void isr_tcc3_0 ( void );
WEAK_DEFAULT void isr_tcc3_1 ( void );
WEAK_DEFAULT void isr_tcc3_2 ( void );
WEAK_DEFAULT void isr_tcc4_0 ( void );
WEAK_DEFAULT void isr_tcc4_1 ( void );
WEAK_DEFAULT void isr_tcc4_2 ( void );
WEAK_DEFAULT void isr_tc0 ( void );
WEAK_DEFAULT void isr_tc1 ( void );
WEAK_DEFAULT void isr_tc2 ( void );
WEAK_DEFAULT void isr_tc3 ( void );
WEAK_DEFAULT void isr_tc4 ( void );
WEAK_DEFAULT void isr_tc5 ( void );
WEAK_DEFAULT void isr_tc6 ( void );
WEAK_DEFAULT void isr_tc7 ( void );
WEAK_DEFAULT void isr_pdec0 ( void );
WEAK_DEFAULT void isr_pdec1 ( void );
WEAK_DEFAULT void isr_pdec2 ( void );
WEAK_DEFAULT void isr_adc0_0 ( void );
WEAK_DEFAULT void isr_adc0_1 ( void );
WEAK_DEFAULT void isr_adc1_0 ( void );
WEAK_DEFAULT void isr_adc1_1 ( void );
WEAK_DEFAULT void isr_ac ( void );
WEAK_DEFAULT void isr_dac0 ( void );
WEAK_DEFAULT void isr_dac1 ( void );
WEAK_DEFAULT void isr_dac2 ( void );
WEAK_DEFAULT void isr_dac3 ( void );
WEAK_DEFAULT void isr_dac4 ( void );
WEAK_DEFAULT void isr_i2s ( void );
WEAK_DEFAULT void isr_pcc ( void );
WEAK_DEFAULT void isr_aes ( void );
WEAK_DEFAULT void isr_trng ( void );
WEAK_DEFAULT void isr_icm ( void );
WEAK_DEFAULT void isr_pukcc ( void );
WEAK_DEFAULT void isq_qspi ( void );
WEAK_DEFAULT void isr_sdhc0 ( void );
WEAK_DEFAULT void isr_sdhc1 ( void );
/* CPU specific interrupt vector table */
ISR_VECTOR(1) const isr_t vector_cpu[CPU_IRQ_NUMOF] = {
isr_pm, /* 0 Power Manager */
isr_mclk, /* 1 Main Clock */
isr_oscctrl0, /* 2 Oscillators Control IRQ 0 */
isr_oscctrl1, /* 3 Oscillators Control IRQ 1 */
isr_oscctrl2, /* 4 Oscillators Control IRQ 2 */
isr_oscctrl3, /* 5 Oscillators Control IRQ 3 */
isr_oscctrl4, /* 6 Oscillators Control IRQ 4 */
isr_osc32kctrl, /* 7 32kHz Oscillators Control */
isr_supc0, /* 8 Supply Controller IRQ 0 */
isr_supc1, /* 9 Supply Controller IRQ 1 */
isr_wdt, /* 10 Watchdog Timer */
isr_rtc, /* 11 Real-Time Counter */
isr_eic0, /* 12 External Interrupt Controller IRQ 0 */
isr_eic1, /* 13 External Interrupt Controller IRQ 1 */
isr_eic2, /* 14 External Interrupt Controller IRQ 2 */
isr_eic3, /* 15 External Interrupt Controller IRQ 3 */
isr_eic4, /* 16 External Interrupt Controller IRQ 4 */
isr_eic5, /* 17 External Interrupt Controller IRQ 5 */
isr_eic6, /* 18 External Interrupt Controller IRQ 6 */
isr_eic7, /* 19 External Interrupt Controller IRQ 7 */
isr_eic8, /* 20 External Interrupt Controller IRQ 8 */
isr_eic9, /* 21 External Interrupt Controller IRQ 9 */
isr_eic10, /* 22 External Interrupt Controller IRQ 10 */
isr_eic11, /* 23 External Interrupt Controller IRQ 11 */
isr_eic12, /* 24 External Interrupt Controller IRQ 12 */
isr_eic13, /* 25 External Interrupt Controller IRQ 13 */
isr_eic14, /* 26 External Interrupt Controller IRQ 14 */
isr_eic15, /* 27 External Interrupt Controller IRQ 15 */
irq_freqm, /* 28 Frequency Meter */
isr_nvmctrl0, /* 29 Non-Volatile Memory Controller IRQ 0 */
isr_nvmctrl1, /* 30 Non-Volatile Memory Controller IRQ 1 */
isr_dmac0, /* 31 Direct Memory Access Controller IRQ 0 */
isr_dmac1, /* 32 Direct Memory Access Controller IRQ 1 */
isr_dmac2, /* 33 Direct Memory Access Controller IRQ 2 */
isr_dmac3, /* 34 Direct Memory Access Controller IRQ 3 */
isr_dmac4, /* 35 Direct Memory Access Controller IRQ 4 */
isr_evsys0, /* 36 Event System Interface IRQ 0 */
isr_evsys1, /* 37 Event System Interface IRQ 1 */
isr_evsys2, /* 38 Event System Interface IRQ 2 */
isr_evsys3, /* 39 Event System Interface IRQ 3 */
isr_evsys4, /* 40 Event System Interface IRQ 4 */
isr_pac, /* 41 Peripheral Access Controller */
dummy_handler,
dummy_handler,
dummy_handler,
irq_ramecc, /* 45 RAM ECC */
isr_sercom0_0, /* 46 Serial Communication Interface 0 IRQ 0 */
isr_sercom0_1, /* 47 Serial Communication Interface 0 IRQ 1 */
isr_sercom0_2, /* 48 Serial Communication Interface 0 IRQ 2 */
isr_sercom0_3, /* 49 Serial Communication Interface 0 IRQ 3 */
isr_sercom1_0, /* 50 Serial Communication Interface 1 IRQ 0 */
isr_sercom1_1, /* 51 Serial Communication Interface 1 IRQ 1 */
isr_sercom1_2, /* 52 Serial Communication Interface 1 IRQ 2 */
isr_sercom1_3, /* 53 Serial Communication Interface 1 IRQ 3 */
isr_sercom2_0, /* 54 Serial Communication Interface 2 IRQ 0 */
isr_sercom2_1, /* 55 Serial Communication Interface 2 IRQ 1 */
isr_sercom2_2, /* 56 Serial Communication Interface 2 IRQ 2 */
isr_sercom2_3, /* 57 Serial Communication Interface 2 IRQ 3 */
isr_sercom3_0, /* 58 Serial Communication Interface 3 IRQ 0 */
isr_sercom3_1, /* 59 Serial Communication Interface 3 IRQ 1 */
isr_sercom3_2, /* 60 Serial Communication Interface 3 IRQ 2 */
isr_sercom3_3, /* 61 Serial Communication Interface 3 IRQ 3 */
isr_sercom4_0, /* 62 Serial Communication Interface 4 IRQ 0 */
isr_sercom4_1, /* 63 Serial Communication Interface 4 IRQ 1 */
isr_sercom4_2, /* 64 Serial Communication Interface 4 IRQ 2 */
isr_sercom4_3, /* 65 Serial Communication Interface 4 IRQ 3 */
isr_sercom5_0, /* 66 Serial Communication Interface 5 IRQ 0 */
isr_sercom5_1, /* 67 Serial Communication Interface 5 IRQ 1 */
isr_sercom5_2, /* 68 Serial Communication Interface 5 IRQ 2 */
isr_sercom5_3, /* 69 Serial Communication Interface 5 IRQ 3 */
isr_sercom6_0, /* 70 Serial Communication Interface 6 IRQ 0 */
isr_sercom6_1, /* 71 Serial Communication Interface 6 IRQ 1 */
isr_sercom6_2, /* 72 Serial Communication Interface 6 IRQ 2 */
isr_sercom6_3, /* 73 Serial Communication Interface 6 IRQ 3 */
isr_sercom7_0, /* 74 Serial Communication Interface 7 IRQ 0 */
isr_sercom7_1, /* 75 Serial Communication Interface 7 IRQ 1 */
isr_sercom7_2, /* 76 Serial Communication Interface 7 IRQ 2 */
isr_sercom7_3, /* 77 Serial Communication Interface 7 IRQ 3 */
isr_can0, /* 78 Control Area Network 0 */
isr_can1, /* 79 Control Area Network 1 */
isr_usb0, /* 80 Universal Serial Bus IRQ 0 */
isr_usb1, /* 81 Universal Serial Bus IRQ 1 */
isr_usb2, /* 82 Universal Serial Bus IRQ 2 */
isr_usb3, /* 83 Universal Serial Bus IRQ 3 */
isr_gmac, /* 84 Ethernet MAC */
isr_tcc0_0, /* 85 Timer Counter Control 0 IRQ 0 */
isr_tcc0_1, /* 86 Timer Counter Control 0 IRQ 1 */
isr_tcc0_2, /* 87 Timer Counter Control 0 IRQ 2 */
isr_tcc0_3, /* 88 Timer Counter Control 0 IRQ 3 */
isr_tcc0_4, /* 89 Timer Counter Control 0 IRQ 4 */
isr_tcc0_5, /* 90 Timer Counter Control 0 IRQ 5 */
isr_tcc0_6, /* 91 Timer Counter Control 0 IRQ 6 */
isr_tcc1_0, /* 92 Timer Counter Control 1 IRQ 0 */
isr_tcc1_1, /* 93 Timer Counter Control 1 IRQ 1 */
isr_tcc1_2, /* 94 Timer Counter Control 1 IRQ 2 */
isr_tcc1_3, /* 95 Timer Counter Control 1 IRQ 3 */
isr_tcc1_4, /* 96 Timer Counter Control 1 IRQ 4 */
isr_tcc2_0, /* 97 Timer Counter Control 2 IRQ 0 */
isr_tcc2_1, /* 98 Timer Counter Control 2 IRQ 1 */
isr_tcc2_2, /* 99 Timer Counter Control 2 IRQ 2 */
isr_tcc2_3, /* 100 Timer Counter Control 2 IRQ 3 */
isr_tcc3_0, /* 101 Timer Counter Control 3 IRQ 0 */
isr_tcc3_1, /* 102 Timer Counter Control 3 IRQ 1 */
isr_tcc3_2, /* 103 Timer Counter Control 3 IRQ 2 */
isr_tcc4_0, /* 104 Timer Counter Control 4 IRQ 0 */
isr_tcc4_1, /* 105 Timer Counter Control 4 IRQ 1 */
isr_tcc4_2, /* 106 Timer Counter Control 4 IRQ 2 */
isr_tc0, /* 107 Basic Timer Counter 0 */
isr_tc1, /* 108 Basic Timer Counter 1 */
isr_tc2, /* 109 Basic Timer Counter 2 */
isr_tc3, /* 110 Basic Timer Counter 3 */
isr_tc4, /* 111 Basic Timer Counter 4 */
isr_tc5, /* 112 Basic Timer Counter 5 */
isr_tc6, /* 113 Basic Timer Counter 6 */
isr_tc7, /* 114 Basic Timer Counter 7 */
isr_pdec0, /* 115 Quadrature Decodeur IRQ 0 */
isr_pdec1, /* 116 Quadrature Decodeur IRQ 1 */
isr_pdec2, /* 117 Quadrature Decodeur IRQ 2 */
isr_adc0_0, /* 118 Analog Digital Converter 0 IRQ 0 */
isr_adc0_1, /* 119 Analog Digital Converter 0 IRQ 1 */
isr_adc1_0, /* 120 Analog Digital Converter 1 IRQ 0 */
isr_adc1_1, /* 121 Analog Digital Converter 1 IRQ 1 */
isr_ac, /* 122 Analog Comparators */
isr_dac0, /* 123 Digital-to-Analog Converter IRQ 0 */
isr_dac1, /* 124 Digital-to-Analog Converter IRQ 1 */
isr_dac2, /* 125 Digital-to-Analog Converter IRQ 2 */
isr_dac3, /* 126 Digital-to-Analog Converter IRQ 3 */
isr_dac4, /* 127 Digital-to-Analog Converter IRQ 4 */
isr_i2s, /* 128 Inter-IC Sound Interface */
isr_pcc, /* 129 Parallel Capture Controller */
isr_aes, /* 130 Advanced Encryption Standard */
isr_trng, /* 131 True Random Generator */
isr_icm, /* 132 Integrity Check Monitor */
isr_pukcc, /* 133 PUblic-Key Cryptography Controller */
isq_qspi, /* 134 Quad SPI interface */
isr_sdhc0, /* 135 SD/MMC Host Controller 0 */
isr_sdhc1, /* 136 SD/MMC Host Controller 1 */
};