mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2025-12-15 01:23:49 +01:00
Merge pull request #21201 from dylad/pr/cpu/sam4s/add_support
cpu/sam4s: add initial support with SAM4S-XPRO board
This commit is contained in:
commit
cdceb084f2
3
boards/sam4s-xpro/Makefile
Normal file
3
boards/sam4s-xpro/Makefile
Normal file
@ -0,0 +1,3 @@
|
||||
MODULE = board
|
||||
|
||||
include $(RIOTBASE)/Makefile.base
|
||||
7
boards/sam4s-xpro/Makefile.features
Normal file
7
boards/sam4s-xpro/Makefile.features
Normal file
@ -0,0 +1,7 @@
|
||||
CPU = sam4s
|
||||
CPU_MODEL = sam4sd32c
|
||||
|
||||
# Put defined MCU peripherals here (in alphabetical order)
|
||||
FEATURES_PROVIDED += periph_gpio periph_gpio_irq
|
||||
FEATURES_PROVIDED += periph_timer
|
||||
FEATURES_PROVIDED += periph_uart
|
||||
6
boards/sam4s-xpro/Makefile.include
Normal file
6
boards/sam4s-xpro/Makefile.include
Normal file
@ -0,0 +1,6 @@
|
||||
# export this module and its includes
|
||||
INCLUDES += -I$(RIOTBOARD)/sam4s-xpro/include
|
||||
|
||||
# setup flasher (using openOCD)
|
||||
PROGRAMMER ?= openocd
|
||||
PROGRAMMERS_SUPPORTED += openocd edbg
|
||||
2
boards/sam4s-xpro/dist/openocd.cfg
vendored
Normal file
2
boards/sam4s-xpro/dist/openocd.cfg
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
source [find board/atmel_sam4s_xplained_pro.cfg]
|
||||
$_TARGETNAME configure -rtos auto
|
||||
48
boards/sam4s-xpro/doc.txt
Normal file
48
boards/sam4s-xpro/doc.txt
Normal file
@ -0,0 +1,48 @@
|
||||
/**
|
||||
@defgroup boards_sam4s-xpro ATSAM4S Xplained Pro board
|
||||
@ingroup boards
|
||||
@brief Support for the ATSAM4S Xplained Pro board
|
||||
|
||||
## Overview
|
||||
|
||||
The `ATSAM4S Xplained Pro` is an evaluation board by Microchip (formerly Atmel)
|
||||
featuring a SAM4SD32 (Cortex-M4) SoC running up to 120 MHz. This MCU comes with
|
||||
160Kb of RAM and 2048Kb of flash memory.
|
||||
|
||||
## Hardware
|
||||
|
||||

|
||||
|
||||
|
||||
### MCU
|
||||
| MCU | ATSAM4SD32C |
|
||||
|:------------- |:--------------------- |
|
||||
| Family | ARM Cortex-M4 |
|
||||
| Vendor | Microchip |
|
||||
| RAM | 160Kb |
|
||||
| Flash | 2048Kb |
|
||||
| Frequency | up to 120MHz |
|
||||
| FPU | no |
|
||||
| Timers | 2 three channels (16-bit) |
|
||||
| ADCs | 1x 12-bit (16 channels) |
|
||||
| UARTs | 2 UARTs (+ 2 USARTs shared with SPIs) |
|
||||
| SPIs | 2 shared with USARTs |
|
||||
| I2Cs | 2 |
|
||||
| Datasheet | [Datasheet](https://ww1.microchip.com/downloads/aemDocuments/documents/OTH/ProductDocuments/DataSheets/Atmel-11100-32-bitCortex-M4-Microcontroller-SAM4S_Datasheet.pdf) |
|
||||
| Board Manual | [Board Manual](https://ww1.microchip.com/downloads/aemDocuments/documents/OTH/ProductDocuments/UserGuides/Atmel-42075-SAM4S-Xplained-Pro_User-Guide.pdf)|
|
||||
|
||||
### User Interface
|
||||
|
||||
1 User button and 1 LED:
|
||||
|
||||
| Device | PIN |
|
||||
|:------ |:--- |
|
||||
| LED0 | PC23 |
|
||||
| SW0 (button) | PA02 |
|
||||
|
||||
### Flashing options
|
||||
By default, openOCD is used for both flashing and debugging.
|
||||
EDBG programmer is also available with:
|
||||
`PROGRAMMER=edbg BOARD=sam4s-xpro make -C tests/leds flash`
|
||||
|
||||
*/
|
||||
62
boards/sam4s-xpro/include/board.h
Normal file
62
boards/sam4s-xpro/include/board.h
Normal file
@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright (C) 2025 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 boards_sam4s-xpro
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief Board specific definitions for the Microchip SAM 4S Xplained Pro
|
||||
* board
|
||||
*
|
||||
* @author Dylan Laduranty <dylan.laduranty@mesotic.com>
|
||||
*/
|
||||
|
||||
#ifndef BOARD_H
|
||||
#define BOARD_H
|
||||
|
||||
#include "cpu.h"
|
||||
#include "periph_conf.h"
|
||||
#include "periph_cpu.h"
|
||||
#include "periph/gpio.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @name ztimer configuration
|
||||
* @{
|
||||
*/
|
||||
#define CONFIG_ZTIMER_USEC_WIDTH (16)
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name LED pin definitions and handlers
|
||||
* @{
|
||||
*/
|
||||
#define LED0_PIN GPIO_PIN(PC, 23)
|
||||
|
||||
#define LED0_ON (PIOC->PIO_CODR = PIO_PC23)
|
||||
#define LED0_OFF (PIOC->PIO_SODR = PIO_PC23)
|
||||
#define LED0_TOGGLE ((PIOC->PIO_ODSR & PIO_PC23) ? LED0_ON : LED0_OFF)
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name SW0 (Button) pin definitions
|
||||
* @{
|
||||
*/
|
||||
#define BTN0_PIN GPIO_PIN(PA, 2)
|
||||
#define BTN0_MODE GPIO_IN_PU
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* BOARD_H */
|
||||
/** @} */
|
||||
94
boards/sam4s-xpro/include/periph_conf.h
Normal file
94
boards/sam4s-xpro/include/periph_conf.h
Normal file
@ -0,0 +1,94 @@
|
||||
/*
|
||||
* Copyright (C) 2025 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 boards_sam4s-xpro
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief Peripheral MCU configuration for SAM4S Xplained pro
|
||||
*
|
||||
* @author Dylan Laduranty <dylan.laduranty@mesotic.com>
|
||||
*/
|
||||
|
||||
#ifndef PERIPH_CONF_H
|
||||
#define PERIPH_CONF_H
|
||||
|
||||
#include "periph_cpu.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @name Clock configuration
|
||||
* @{
|
||||
*/
|
||||
/* targeted system core clock */
|
||||
#define CLOCK_CORECLOCK MHZ(120)
|
||||
/* external oscillator clock */
|
||||
#define CLOCK_EXT_OSC MHZ(12)
|
||||
/* define PLL configuration
|
||||
*
|
||||
* The values must fulfill this equation:
|
||||
* CORECLOCK = (EXT_OCS / PLL_DIV) * (PLL_MUL + 1)
|
||||
*/
|
||||
#define CLOCK_PLL_MUL (9)
|
||||
#define CLOCK_PLL_DIV (1)
|
||||
|
||||
/* number of wait states before flash read and write operations */
|
||||
#define CLOCK_FWS (5) /* 5 is safe for 120 MHz */
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @brief Enable external oscillator for driving the slow clock
|
||||
*/
|
||||
#define CLOCK_SCLK_XTAL (1)
|
||||
|
||||
/**
|
||||
* @name Timer peripheral configuration
|
||||
* @{
|
||||
*/
|
||||
static const timer_conf_t timer_config[] = {
|
||||
{ .dev = TC0, .id_ch0 = ID_TC0 },
|
||||
{ .dev = TC1, .id_ch0 = ID_TC3 }
|
||||
};
|
||||
|
||||
#define TIMER_0_ISR isr_tc0
|
||||
#define TIMER_1_ISR isr_tc3
|
||||
|
||||
#define TIMER_NUMOF ARRAY_SIZE(timer_config)
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name UART configuration
|
||||
* @{
|
||||
*/
|
||||
static const uart_conf_t uart_config[] = {
|
||||
{
|
||||
.dev = (Uart *)UART1,
|
||||
.rx_pin = GPIO_PIN(PB, 2),
|
||||
.tx_pin = GPIO_PIN(PB, 3),
|
||||
.mux = GPIO_MUX_A,
|
||||
.pmc_id = ID_UART1,
|
||||
.irqn = UART1_IRQn
|
||||
}
|
||||
};
|
||||
|
||||
/* define interrupt vectors */
|
||||
#define UART_0_ISR isr_uart1
|
||||
|
||||
#define UART_NUMOF ARRAY_SIZE(uart_config)
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* PERIPH_CONF_H */
|
||||
/** @} */
|
||||
@ -1 +1 @@
|
||||
include $(RIOTCPU)/cortexm_common/Makefile.dep
|
||||
include $(RIOTCPU)/sam_common/Makefile.dep
|
||||
|
||||
@ -1,2 +1,8 @@
|
||||
ROM_START_ADDR ?= 0x80000
|
||||
RAM_START_ADDR ?= 0x20070000
|
||||
|
||||
ROM_LEN ?= 0x80000
|
||||
RAM_LEN ?= 0x18000
|
||||
|
||||
include $(RIOTCPU)/sam_common/Makefile.include
|
||||
include $(RIOTMAKE)/arch/cortexm.inc.mk
|
||||
|
||||
@ -22,21 +22,12 @@
|
||||
#ifndef PERIPH_CPU_H
|
||||
#define PERIPH_CPU_H
|
||||
|
||||
#include "cpu.h"
|
||||
#include "periph_cpu_common.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef DOXYGEN
|
||||
#define HAVE_GPIO_T
|
||||
typedef uint32_t gpio_t;
|
||||
|
||||
#define GPIO_UNDEF (0xffffffff)
|
||||
|
||||
#define GPIO_PIN(x, y) (((uint32_t)PIOA + (x << 9)) | y)
|
||||
#endif /* DOXYGEN */
|
||||
|
||||
/**
|
||||
* @name Declare needed generic SPI functions
|
||||
* @{
|
||||
@ -52,21 +43,6 @@ typedef uint32_t gpio_t;
|
||||
*/
|
||||
#define CPUID_LEN (16U)
|
||||
|
||||
/**
|
||||
* @brief All SAM3 timers are 32-bit wide
|
||||
*/
|
||||
#define TIMER_MAX_VAL (0xffffffff)
|
||||
|
||||
/**
|
||||
* @brief We use one channel for each defined timer
|
||||
*
|
||||
* While the peripheral provides three channels, the current interrupt
|
||||
* flag handling leads to a race condition where calling timer_clear() on one
|
||||
* channel can disable a pending flag for other channels.
|
||||
* Until resolved, limit the peripheral to only one channel.
|
||||
*/
|
||||
#define TIMER_CHANNEL_NUMOF (1)
|
||||
|
||||
/**
|
||||
* @name RTT configuration
|
||||
* @{
|
||||
@ -77,16 +53,6 @@ typedef uint32_t gpio_t;
|
||||
#define RTT_MAX_FREQUENCY (RTT_CLOCK_FREQUENCY) /* in Hz */
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @brief Generate GPIO mode bitfields
|
||||
*
|
||||
* We use 3 bit to determine the pin functions:
|
||||
* - bit 0: in/out
|
||||
* - bit 1: PU enable
|
||||
* - bit 2: OD enable
|
||||
*/
|
||||
#define GPIO_MODE(io, pu, od) (io | (pu << 1) | (od << 2))
|
||||
|
||||
/**
|
||||
* @name ADC configuration, valid for all boards using this CPU
|
||||
*
|
||||
@ -109,43 +75,6 @@ typedef uint32_t gpio_t;
|
||||
*/
|
||||
#define DAC_NUMOF (2U)
|
||||
|
||||
#ifndef DOXYGEN
|
||||
#define HAVE_GPIO_MODE_T
|
||||
typedef enum {
|
||||
GPIO_IN = GPIO_MODE(0, 0, 0), /**< IN */
|
||||
GPIO_IN_PD = 0xf, /**< not supported by HW */
|
||||
GPIO_IN_PU = GPIO_MODE(0, 1, 0), /**< IN with pull-up */
|
||||
GPIO_OUT = GPIO_MODE(1, 0, 0), /**< OUT (push-pull) */
|
||||
GPIO_OD = GPIO_MODE(1, 0, 1), /**< OD */
|
||||
GPIO_OD_PU = GPIO_MODE(1, 1, 1), /**< OD with pull-up */
|
||||
} gpio_mode_t;
|
||||
|
||||
#define HAVE_GPIO_FLANK_T
|
||||
typedef enum {
|
||||
GPIO_RISING = 1, /**< emit interrupt on rising flank */
|
||||
GPIO_FALLING = 2, /**< emit interrupt on falling flank */
|
||||
GPIO_BOTH = 3 /**< emit interrupt on both flanks */
|
||||
} gpio_flank_t;
|
||||
#endif /* ndef DOXYGEN */
|
||||
|
||||
/**
|
||||
* @brief Available ports on the SAM3X8E
|
||||
*/
|
||||
enum {
|
||||
PA = 0, /**< port A */
|
||||
PB = 1, /**< port B */
|
||||
PC = 2, /**< port C */
|
||||
PD = 3, /**< port D */
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief GPIO mux configuration
|
||||
*/
|
||||
typedef enum {
|
||||
GPIO_MUX_A = 0, /**< alternate function A */
|
||||
GPIO_MUX_B = 1, /**< alternate function B */
|
||||
} gpio_mux_t;
|
||||
|
||||
#ifndef DOXYGEN
|
||||
/**
|
||||
* @brief Override default SPI modes
|
||||
@ -192,26 +121,6 @@ typedef enum {
|
||||
/** @} */
|
||||
#endif /* ndef DOXYGEN */
|
||||
|
||||
/**
|
||||
* @brief Timer configuration data
|
||||
*/
|
||||
typedef struct {
|
||||
Tc *dev; /**< timer device */
|
||||
uint8_t id_ch0; /**< ID of the timer's first channel */
|
||||
} timer_conf_t;
|
||||
|
||||
/**
|
||||
* @brief UART configuration data
|
||||
*/
|
||||
typedef struct {
|
||||
Uart *dev; /**< U(S)ART device used */
|
||||
gpio_t rx_pin; /**< RX pin */
|
||||
gpio_t tx_pin; /**< TX pin */
|
||||
gpio_mux_t mux; /**< MUX used for pins */
|
||||
uint8_t pmc_id; /**< bit in the PMC register of the device*/
|
||||
uint8_t irqn; /**< interrupt number of the device */
|
||||
} uart_conf_t;
|
||||
|
||||
/**
|
||||
* @brief PWM channel configuration data
|
||||
*/
|
||||
@ -232,14 +141,6 @@ typedef struct {
|
||||
gpio_mux_t mux; /**< pin MUX setting */
|
||||
} spi_conf_t;
|
||||
|
||||
/**
|
||||
* @brief Configure the given GPIO pin to be used with the given MUX setting
|
||||
*
|
||||
* @param[in] pin GPIO pin to configure
|
||||
* @param[in] mux MUX setting to use
|
||||
*/
|
||||
void gpio_init_mux(gpio_t pin, gpio_mux_t mux);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
27
cpu/sam4s/Kconfig
Normal file
27
cpu/sam4s/Kconfig
Normal file
@ -0,0 +1,27 @@
|
||||
# Copyright (c) 2025 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.
|
||||
#
|
||||
|
||||
config CPU_FAM_SAM4S
|
||||
bool
|
||||
select CPU_CORE_CORTEX_M4
|
||||
|
||||
## CPU Models
|
||||
config CPU_MODEL_SAM4SD32C
|
||||
bool
|
||||
select CPU_FAM_SAM4S
|
||||
|
||||
## Common CPU symbols
|
||||
config CPU_FAM
|
||||
default "sam4s" if CPU_FAM_SAM4S
|
||||
|
||||
config CPU_MODEL
|
||||
default "sam4sd32c" if CPU_MODEL_SAM4SD32C
|
||||
|
||||
config CPU
|
||||
default "sam4s" if CPU_FAM_SAM4s
|
||||
|
||||
source "$(RIOTCPU)/cortexm_common/Kconfig"
|
||||
10
cpu/sam4s/Makefile
Normal file
10
cpu/sam4s/Makefile
Normal 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)/sam_common
|
||||
|
||||
# (file triggers compiler bug. see #5775)
|
||||
SRC_NOLTO += vectors.c
|
||||
|
||||
include $(RIOTBASE)/Makefile.base
|
||||
1
cpu/sam4s/Makefile.dep
Normal file
1
cpu/sam4s/Makefile.dep
Normal file
@ -0,0 +1 @@
|
||||
include $(RIOTCPU)/sam_common/Makefile.dep
|
||||
6
cpu/sam4s/Makefile.features
Normal file
6
cpu/sam4s/Makefile.features
Normal file
@ -0,0 +1,6 @@
|
||||
CPU_CORE = cortex-m4
|
||||
CPU_FAM = sam4s
|
||||
|
||||
FEATURES_PROVIDED += cortexm_mpu
|
||||
|
||||
include $(RIOTCPU)/cortexm_common/Makefile.features
|
||||
8
cpu/sam4s/Makefile.include
Normal file
8
cpu/sam4s/Makefile.include
Normal file
@ -0,0 +1,8 @@
|
||||
ROM_START_ADDR ?= 0x400000
|
||||
RAM_START_ADDR ?= 0x20000000
|
||||
|
||||
ROM_LEN ?= 0x200000
|
||||
RAM_LEN ?= 0x28000
|
||||
|
||||
include $(RIOTCPU)/sam_common/Makefile.include
|
||||
include $(RIOTMAKE)/arch/cortexm.inc.mk
|
||||
107
cpu/sam4s/cpu.c
Normal file
107
cpu/sam4s/cpu.c
Normal file
@ -0,0 +1,107 @@
|
||||
/*
|
||||
* Copyright (C) 2025 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_sam4s
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief Implementation of the CPU initialization
|
||||
*
|
||||
* @author Dylan Laduranty <dylan.laduranty@mesotic.com>
|
||||
* @}
|
||||
*/
|
||||
|
||||
#include "cpu.h"
|
||||
#include "board.h"
|
||||
#include "kernel_init.h"
|
||||
#include "periph_conf.h"
|
||||
#include "periph/init.h"
|
||||
#include "stdio_base.h"
|
||||
|
||||
#define XTAL_STARTUP (8U)
|
||||
#define PLL_CNT (64U)
|
||||
|
||||
#if ((CLOCK_PLL_MUL < 7) || (CLOCK_PLL_MUL > 62))
|
||||
#error "CLOCK_PLL_MUL has an incorrect value"
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Initialize the CPU, set IRQ priorities
|
||||
*/
|
||||
void cpu_init(void)
|
||||
{
|
||||
/* SAM4s MCUs requires WPKEY for enabling peripheral */
|
||||
PMC->PMC_WPMR = PMC_WPMR_WPKEY_PASSWD;
|
||||
|
||||
/* disable the watchdog timer */
|
||||
WDT->WDT_MR |= WDT_MR_WDDIS;
|
||||
|
||||
/* initialize the Cortex-M core */
|
||||
cortexm_init();
|
||||
|
||||
/* setup the flash wait states */
|
||||
EFC0->EEFC_FMR = EEFC_FMR_FWS(CLOCK_FWS);
|
||||
EFC1->EEFC_FMR = EEFC_FMR_FWS(CLOCK_FWS);
|
||||
|
||||
/* enable the Cortex-M Cache Controller */
|
||||
CMCC->CMCC_CTRL |= CMCC_CTRL_CEN;
|
||||
|
||||
/* unlock write protect register for PMC module */
|
||||
PMC->PMC_WPMR = PMC_WPMR_WPKEY_PASSWD;
|
||||
|
||||
/* activate the external crystal */
|
||||
PMC->CKGR_MOR = CKGR_MOR_KEY_PASSWD
|
||||
| CKGR_MOR_MOSCXTST(XTAL_STARTUP)
|
||||
| CKGR_MOR_MOSCXTEN
|
||||
| CKGR_MOR_MOSCRCEN;
|
||||
|
||||
/* wait for crystal to be stable */
|
||||
while (!(PMC->PMC_SR & PMC_SR_MOSCXTS)) {}
|
||||
|
||||
/* select crystal to clock the main clock */
|
||||
PMC->CKGR_MOR = CKGR_MOR_KEY_PASSWD
|
||||
| CKGR_MOR_MOSCXTST(XTAL_STARTUP)
|
||||
| CKGR_MOR_MOSCXTEN
|
||||
| CKGR_MOR_MOSCRCEN
|
||||
| CKGR_MOR_MOSCSEL;
|
||||
|
||||
/* wait for main oscillator selection to be complete */
|
||||
while (!(PMC->PMC_SR & PMC_SR_MOSCSELS)) {}
|
||||
|
||||
/* setup PLLA */
|
||||
PMC->CKGR_PLLAR = CKGR_PLLAR_ONE
|
||||
| CKGR_PLLAR_PLLACOUNT(PLL_CNT)
|
||||
| CKGR_PLLAR_MULA(CLOCK_PLL_MUL)
|
||||
| CKGR_PLLAR_DIVA(CLOCK_PLL_DIV);
|
||||
|
||||
/* wait for PLL to lock */
|
||||
while (!(PMC->PMC_SR & PMC_SR_LOCKA)) {}
|
||||
|
||||
/* before switching to PLLA, we need to switch to main clock */
|
||||
PMC->PMC_MCKR = PMC_MCKR_CSS_MAIN_CLK;
|
||||
while (!(PMC->PMC_SR & PMC_SR_MCKRDY)) {}
|
||||
|
||||
/* use PLLA as main clock source */
|
||||
PMC->PMC_MCKR = PMC_MCKR_CSS_PLLA_CLK;
|
||||
/* wait for master clock to be ready */
|
||||
while (!(PMC->PMC_SR & PMC_SR_MCKRDY)) {}
|
||||
|
||||
/* setup the SCLK: switch to external oscillator if applicable */
|
||||
#if CLOCK_SCLK_XTAL
|
||||
/* enable external oscillator */
|
||||
SUPC->SUPC_CR = SUPC_CR_KEY_PASSWD | SUPC_CR_XTALSEL;
|
||||
while (!(SUPC->SUPC_SR & SUPC_SR_OSCSEL_CRYST)) {}
|
||||
#endif
|
||||
|
||||
/* initialize stdio prior to periph_init() to allow use of DEBUG() there */
|
||||
early_init();
|
||||
|
||||
/* trigger static peripheral initialization */
|
||||
periph_init();
|
||||
}
|
||||
9
cpu/sam4s/doc.txt
Normal file
9
cpu/sam4s/doc.txt
Normal file
@ -0,0 +1,9 @@
|
||||
/**
|
||||
* @defgroup cpu_sam4s Atmel SAM4S
|
||||
* @ingroup cpu
|
||||
* @brief Atmel SAM4S Cortex-M4 MCU specific implementation.
|
||||
*
|
||||
* This module contains Atmel SAM4S specific code and definition.
|
||||
*
|
||||
* @see cpu_sam_common
|
||||
*/
|
||||
35
cpu/sam4s/include/periph_cpu.h
Normal file
35
cpu/sam4s/include/periph_cpu.h
Normal file
@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright (C) 2025 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_sam4s
|
||||
* @{
|
||||
*
|
||||
* @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"
|
||||
#include "macros/units.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* PERIPH_CPU_H */
|
||||
/** @} */
|
||||
1
cpu/sam4s/periph/Makefile
Normal file
1
cpu/sam4s/periph/Makefile
Normal file
@ -0,0 +1 @@
|
||||
include $(RIOTMAKE)/periph.mk
|
||||
106
cpu/sam4s/vectors.c
Normal file
106
cpu/sam4s/vectors.c
Normal file
@ -0,0 +1,106 @@
|
||||
/*
|
||||
* Copyright (C) 2025 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_sam4s
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @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();
|
||||
}
|
||||
|
||||
/* Cortex-M common interrupt vectors */
|
||||
WEAK_DEFAULT void isr_svc(void);
|
||||
WEAK_DEFAULT void isr_pendsv(void);
|
||||
WEAK_DEFAULT void isr_systick(void);
|
||||
/* SAM4S specific interrupt vector */
|
||||
WEAK_DEFAULT void isr_supc(void);
|
||||
WEAK_DEFAULT void isr_rstc(void);
|
||||
WEAK_DEFAULT void isr_rtc(void);
|
||||
WEAK_DEFAULT void isr_rtt(void);
|
||||
WEAK_DEFAULT void isr_wdt(void);
|
||||
WEAK_DEFAULT void isr_pmc(void);
|
||||
WEAK_DEFAULT void isr_eefc0(void);
|
||||
WEAK_DEFAULT void isr_eefc1(void);
|
||||
WEAK_DEFAULT void isr_uart0(void);
|
||||
WEAK_DEFAULT void isr_uart1(void);
|
||||
WEAK_DEFAULT void isr_smc(void);
|
||||
WEAK_DEFAULT void isr_pioa(void);
|
||||
WEAK_DEFAULT void isr_piob(void);
|
||||
WEAK_DEFAULT void isr_pioc(void);
|
||||
WEAK_DEFAULT void isr_usart0(void);
|
||||
WEAK_DEFAULT void isr_usart1(void);
|
||||
WEAK_DEFAULT void isr_hsmci(void);
|
||||
WEAK_DEFAULT void isr_twi0(void);
|
||||
WEAK_DEFAULT void isr_twi1(void);
|
||||
WEAK_DEFAULT void isr_spi(void);
|
||||
WEAK_DEFAULT void isr_ssc(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_adc(void);
|
||||
WEAK_DEFAULT void isr_dacc(void);
|
||||
WEAK_DEFAULT void isr_pwm(void);
|
||||
WEAK_DEFAULT void isr_crccu(void);
|
||||
WEAK_DEFAULT void isr_acc(void);
|
||||
WEAK_DEFAULT void isr_udp(void);
|
||||
|
||||
/* CPU specific interrupt vector table */
|
||||
ISR_VECTOR(1) const isr_t vector_cpu[CPU_IRQ_NUMOF] = {
|
||||
isr_supc, /* 0 Supply Controller */
|
||||
isr_rstc, /* 1 Reset Controller */
|
||||
isr_rtc, /* 2 Real Time Clock */
|
||||
isr_rtt, /* 3 Real Timer Timer */
|
||||
isr_wdt, /* 4 Watchdog Timer */
|
||||
isr_pmc, /* 5 Power Management Controller */
|
||||
isr_eefc0, /* 6 Enhanced Embedded Flash Controller 0 */
|
||||
isr_eefc1, /* 7 Enhanced Embedded Flash Controller 1 */
|
||||
isr_uart0, /* 8 Universal Asynchronous Receiver Transceiver 0 */
|
||||
isr_uart1, /* 9 Universal Asynchronous Receiver Transceiver 1 */
|
||||
isr_smc, /* 10 Static Memory Controller */
|
||||
isr_pioa, /* 11 GPIO port A */
|
||||
isr_piob, /* 12 GPIO port B */
|
||||
isr_pioc, /* 13 GPIO port C */
|
||||
isr_usart0, /* 14 USART0 */
|
||||
isr_usart1, /* 15 USART1 */
|
||||
(0UL), /* Reserved */
|
||||
(0UL), /* Reserved */
|
||||
isr_hsmci, /* 18 Multimedia Card Interface */
|
||||
isr_twi0, /* 19 Two-wire Interface 0 */
|
||||
isr_twi1, /* 20 Two-wire Interface 1 */
|
||||
isr_spi, /* 21 Serial Peripheral Interface */
|
||||
isr_ssc, /* 22 Synchronous Serial Controller */
|
||||
isr_tc0, /* 23 Timer Counter 0 */
|
||||
isr_tc1, /* 24 Timer Counter 1 */
|
||||
isr_tc2, /* 25 Timer Counter 2 */
|
||||
isr_tc3, /* 26 Timer Counter 3 */
|
||||
isr_tc4, /* 27 Timer Counter 4 */
|
||||
isr_tc5, /* 28 Timer Counter 5 */
|
||||
isr_adc, /* 29 Analog/Digital Converter */
|
||||
isr_dacc, /* 30 Digital/Analog Converter Controller */
|
||||
isr_pwm, /* 31 Pulse Width Modulation */
|
||||
isr_crccu, /* 32 CRC Calculation Unit */
|
||||
isr_acc, /* 33 Analog Comparator Controller */
|
||||
isr_udp, /* 34 USB Device Port */
|
||||
};
|
||||
@ -1 +1,3 @@
|
||||
DIRS = periph
|
||||
|
||||
include $(RIOTBASE)/Makefile.base
|
||||
|
||||
4
cpu/sam_common/Makefile.dep
Normal file
4
cpu/sam_common/Makefile.dep
Normal file
@ -0,0 +1,4 @@
|
||||
# include sam common periph drivers
|
||||
USEMODULE += sam_common_periph
|
||||
|
||||
include $(RIOTCPU)/cortexm_common/Makefile.dep
|
||||
@ -4,12 +4,6 @@ CFLAGS += -DCPU_FAM_$(call uppercase_and_underscore,$(CPU_FAM))
|
||||
# this CPU implementation doesn't use CMSIS initialization
|
||||
CFLAGS += -DDONT_USE_CMSIS_INIT
|
||||
|
||||
ROM_START_ADDR ?= 0x80000
|
||||
RAM_START_ADDR ?= 0x20070000
|
||||
|
||||
ROM_LEN ?= 0x80000
|
||||
RAM_LEN ?= 0x18000
|
||||
|
||||
LINKER_SCRIPT ?= cortexm.ld
|
||||
|
||||
INCLUDES += -I$(RIOTCPU)/sam_common/include
|
||||
|
||||
134
cpu/sam_common/include/periph_cpu_common.h
Normal file
134
cpu/sam_common/include/periph_cpu_common.h
Normal file
@ -0,0 +1,134 @@
|
||||
/*
|
||||
* Copyright (C) 2025 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_sam_common
|
||||
* @brief Common CPU specific definitions for all SAM3/SAM4x based CPUs
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief Common CPU specific definitions for all SAM3/SAM4x based CPUs
|
||||
*
|
||||
* @author Dylan Laduranty <dylan.laduranty@mesotic.com>
|
||||
*/
|
||||
|
||||
#ifndef PERIPH_CPU_COMMON_H
|
||||
#define PERIPH_CPU_COMMON_H
|
||||
|
||||
#include "cpu.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef DOXYGEN
|
||||
#define HAVE_GPIO_T
|
||||
typedef uint32_t gpio_t;
|
||||
|
||||
#define GPIO_UNDEF (0xffffffff)
|
||||
|
||||
#define GPIO_PIN(x, y) (((uint32_t)PIOA + (x << 9)) | y)
|
||||
#endif /* DOXYGEN */
|
||||
|
||||
/**
|
||||
* @brief We use one channel for each defined timer
|
||||
*
|
||||
* While the peripheral provides three channels, the current interrupt
|
||||
* flag handling leads to a race condition where calling timer_clear() on one
|
||||
* channel can disable a pending flag for other channels.
|
||||
* Until resolved, limit the peripheral to only one channel.
|
||||
*/
|
||||
#define TIMER_CHANNEL_NUMOF (1)
|
||||
|
||||
/**
|
||||
* @brief Generate GPIO mode bitfields
|
||||
*
|
||||
* We use 3 bit to determine the pin functions:
|
||||
* - bit 0: in/out
|
||||
* - bit 1: PU enable
|
||||
* - bit 2: OD enable
|
||||
*/
|
||||
#define GPIO_MODE(io, pu, od) (io | (pu << 1) | (od << 2))
|
||||
|
||||
#ifndef DOXYGEN
|
||||
#define HAVE_GPIO_MODE_T
|
||||
typedef enum {
|
||||
GPIO_IN = GPIO_MODE(0, 0, 0), /**< IN */
|
||||
GPIO_IN_PD = 0xf, /**< not supported by HW */
|
||||
GPIO_IN_PU = GPIO_MODE(0, 1, 0), /**< IN with pull-up */
|
||||
GPIO_OUT = GPIO_MODE(1, 0, 0), /**< OUT (push-pull) */
|
||||
GPIO_OD = GPIO_MODE(1, 0, 1), /**< OD */
|
||||
GPIO_OD_PU = GPIO_MODE(1, 1, 1), /**< OD with pull-up */
|
||||
} gpio_mode_t;
|
||||
|
||||
#define HAVE_GPIO_FLANK_T
|
||||
typedef enum {
|
||||
GPIO_RISING = 1, /**< emit interrupt on rising flank */
|
||||
GPIO_FALLING = 2, /**< emit interrupt on falling flank */
|
||||
GPIO_BOTH = 3 /**< emit interrupt on both flanks */
|
||||
} gpio_flank_t;
|
||||
#endif /* ndef DOXYGEN */
|
||||
|
||||
/**
|
||||
* @brief GPIO mux configuration
|
||||
*/
|
||||
typedef enum {
|
||||
GPIO_MUX_A = 0, /**< alternate function A */
|
||||
GPIO_MUX_B = 1, /**< alternate function B */
|
||||
#ifdef CPU_FAM_SAM4S
|
||||
GPIO_MUX_C = 2, /**< alternate function C */
|
||||
GPIO_MUX_D = 3, /**< alternate function D */
|
||||
#endif
|
||||
} gpio_mux_t;
|
||||
|
||||
/**
|
||||
* @brief Available ports on the SAM3/SAM4S based MCUs
|
||||
*/
|
||||
enum {
|
||||
PA = 0, /**< port A */
|
||||
PB = 1, /**< port B */
|
||||
PC = 2, /**< port C */
|
||||
#ifdef CPU_FAM_SAM3
|
||||
PD = 3, /**< port D */
|
||||
#endif
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Configure the given GPIO pin to be used with the given MUX setting
|
||||
*
|
||||
* @param[in] pin GPIO pin to configure
|
||||
* @param[in] mux MUX setting to use
|
||||
*/
|
||||
void gpio_init_mux(gpio_t pin, gpio_mux_t mux);
|
||||
|
||||
/**
|
||||
* @brief Timer configuration data
|
||||
*/
|
||||
typedef struct {
|
||||
Tc *dev; /**< timer device */
|
||||
uint8_t id_ch0; /**< ID of the timer's first channel */
|
||||
} timer_conf_t;
|
||||
|
||||
/**
|
||||
* @brief UART configuration data
|
||||
*/
|
||||
typedef struct {
|
||||
Uart *dev; /**< U(S)ART device used */
|
||||
gpio_t rx_pin; /**< RX pin */
|
||||
gpio_t tx_pin; /**< TX pin */
|
||||
gpio_mux_t mux; /**< MUX used for pins */
|
||||
uint8_t pmc_id; /**< bit in the PMC register of the device*/
|
||||
uint8_t irqn; /**< interrupt number of the device */
|
||||
} uart_conf_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* PERIPH_CPU_COMMON_H */
|
||||
/** @} */
|
||||
14
cpu/sam_common/include/vendor/sam.h
vendored
14
cpu/sam_common/include/vendor/sam.h
vendored
@ -23,13 +23,6 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if defined(CPU_FAM_SAM3) && !defined(PERIPH_COUNT_IRQn)
|
||||
/**
|
||||
* @brief Number of periphical IRQs for SAM3 CPUs
|
||||
*/
|
||||
#define PERIPH_COUNT_IRQn (45U)
|
||||
#endif
|
||||
|
||||
#if defined(CPU_MODEL_SAM3A4C)
|
||||
#include "vendor/sam3x/include/sam3a4c.h"
|
||||
#elif defined(CPU_MODEL_SAM3A8C)
|
||||
@ -82,6 +75,13 @@ extern "C" {
|
||||
#error "Unsupported Atmel SAM variant."
|
||||
#endif
|
||||
|
||||
#if defined(CPU_FAM_SAM3) && !defined(PERIPH_COUNT_IRQn)
|
||||
/**
|
||||
* @brief Number of periphical IRQs for SAM3 CPUs
|
||||
*/
|
||||
#define PERIPH_COUNT_IRQn (45U)
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
3
cpu/sam_common/periph/Makefile
Normal file
3
cpu/sam_common/periph/Makefile
Normal file
@ -0,0 +1,3 @@
|
||||
MODULE = sam_common_periph
|
||||
|
||||
include $(RIOTMAKE)/periph.mk
|
||||
@ -9,7 +9,7 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ingroup cpu_sam3
|
||||
* @ingroup cpu_sam_common
|
||||
* @ingroup drivers_periph_gpio
|
||||
* @{
|
||||
*
|
||||
@ -134,9 +134,14 @@ static inline int _port_num(gpio_t pin)
|
||||
*/
|
||||
static bool _port_valid(Pio *port)
|
||||
{
|
||||
if (port == PIOA || port == PIOB || port == PIOC || port == PIOD) {
|
||||
if (port == PIOA || port == PIOB || port == PIOC) {
|
||||
return true;
|
||||
}
|
||||
#ifdef PIOD
|
||||
if (port == PIOD) {
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -162,6 +167,11 @@ int gpio_init(gpio_t pin, gpio_mode_t mode)
|
||||
/* power on the corresponding port */
|
||||
PMC->PMC_PCER0 = (1 << (port_num + 11));
|
||||
|
||||
/* SAM4s MCUs requires WPKEY for enabling peripheral */
|
||||
#ifdef PIO_WPMR_WPKEY_PASSWD
|
||||
port->PIO_WPMR = PIO_WPMR_WPKEY_PASSWD;
|
||||
#endif
|
||||
|
||||
/* disable interrupt and clear context (to be safe) */
|
||||
port->PIO_IDR = (1 << pin_num);
|
||||
#ifdef MODULE_PERIPH_GPIO_IRQ
|
||||
@ -203,8 +213,19 @@ void gpio_init_mux(gpio_t pin, gpio_mux_t mux)
|
||||
/* give peripheral control over the pin */
|
||||
_port(pin)->PIO_PDR = (1 << _pin_num(pin));
|
||||
/* and configure the MUX */
|
||||
#ifdef PIO_ABCDSR_P0
|
||||
_port(pin)->PIO_ABCDSR[0] &= ~(1 << _pin_num(pin));
|
||||
_port(pin)->PIO_ABCDSR[1] &= ~(1 << _pin_num(pin));
|
||||
if (mux & 0x2) {
|
||||
_port(pin)->PIO_ABCDSR[1] |= 1 << _pin_num(pin);
|
||||
}
|
||||
if (mux & 0x1) {
|
||||
_port(pin)->PIO_ABCDSR[0] |= 1 << _pin_num(pin);
|
||||
}
|
||||
#else
|
||||
_port(pin)->PIO_ABSR &= ~(1 << _pin_num(pin));
|
||||
_port(pin)->PIO_ABSR |= (mux << _pin_num(pin));
|
||||
#endif
|
||||
}
|
||||
|
||||
void gpio_set(gpio_t pin)
|
||||
@ -338,8 +359,10 @@ void isr_pioc(void)
|
||||
isr_handler(PIOC, PC);
|
||||
}
|
||||
|
||||
#ifdef PIOD
|
||||
void isr_piod(void)
|
||||
{
|
||||
isr_handler(PIOD, PD);
|
||||
}
|
||||
#endif
|
||||
#endif /* MODULE_PERIPH_GPIO_IRQ */
|
||||
@ -7,7 +7,7 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ingroup cpu_sam3
|
||||
* @ingroup cpu_sam_common
|
||||
* @ingroup drivers_periph_timer
|
||||
* @{
|
||||
*
|
||||
@ -82,6 +82,11 @@ int timer_init(tim_t tim, uint32_t freq, timer_cb_t cb, void *arg)
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* SAM4s requires this WPKEY for enabling peripheral access */
|
||||
#ifdef TC_WPMR_WPKEY_PASSWD
|
||||
dev(tim)->TC_WPMR = TC_WPMR_WPKEY_PASSWD;
|
||||
#endif
|
||||
|
||||
/* enable the device clock */
|
||||
clk_en(tim);
|
||||
|
||||
@ -7,7 +7,7 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ingroup cpu_sam3
|
||||
* @ingroup cpu_sam_common
|
||||
* @ingroup drivers_periph_uart
|
||||
* @{
|
||||
*
|
||||
@ -246,6 +246,10 @@ groups:
|
||||
features:
|
||||
- name: cpu_sam3
|
||||
help: The MCU has an Atmel/Microchip SAM 3 CPU
|
||||
- title: SAM4S Grouping
|
||||
features:
|
||||
- name: cpu_sam4s
|
||||
help: The MCU has an Atmel/Microchip SAM 4S CPU
|
||||
|
||||
- title: GigaDevice Semiconductor Inc Grouping
|
||||
features:
|
||||
|
||||
@ -87,6 +87,7 @@ FEATURES_EXISTING := \
|
||||
cpu_qn908x \
|
||||
cpu_rpx0xx \
|
||||
cpu_sam3 \
|
||||
cpu_sam4s \
|
||||
cpu_samd21 \
|
||||
cpu_samd5x \
|
||||
cpu_saml1x \
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user