1
0
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:
Dylan Laduranty 2025-02-17 15:39:06 +00:00 committed by GitHub
commit cdceb084f2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
31 changed files with 727 additions and 118 deletions

View File

@ -0,0 +1,3 @@
MODULE = board
include $(RIOTBASE)/Makefile.base

View 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

View 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
View 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
View 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
![sam4s-xpro image](https://www.microchip.com/content/dam/mchp/mrt-dam/devtools/1801-atsam4s-xpro.jpg)
### 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`
*/

View 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 */
/** @} */

View 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 */
/** @} */

View File

@ -1 +1 @@
include $(RIOTCPU)/cortexm_common/Makefile.dep
include $(RIOTCPU)/sam_common/Makefile.dep

View File

@ -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

View File

@ -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
View 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
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)/sam_common
# (file triggers compiler bug. see #5775)
SRC_NOLTO += vectors.c
include $(RIOTBASE)/Makefile.base

1
cpu/sam4s/Makefile.dep Normal file
View File

@ -0,0 +1 @@
include $(RIOTCPU)/sam_common/Makefile.dep

View File

@ -0,0 +1,6 @@
CPU_CORE = cortex-m4
CPU_FAM = sam4s
FEATURES_PROVIDED += cortexm_mpu
include $(RIOTCPU)/cortexm_common/Makefile.features

View 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
View 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
View 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
*/

View 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 */
/** @} */

View File

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

106
cpu/sam4s/vectors.c Normal file
View 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 */
};

View File

@ -1 +1,3 @@
DIRS = periph
include $(RIOTBASE)/Makefile.base

View File

@ -0,0 +1,4 @@
# include sam common periph drivers
USEMODULE += sam_common_periph
include $(RIOTCPU)/cortexm_common/Makefile.dep

View File

@ -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

View 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 */
/** @} */

View File

@ -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

View File

@ -0,0 +1,3 @@
MODULE = sam_common_periph
include $(RIOTMAKE)/periph.mk

View File

@ -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 */

View File

@ -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);

View File

@ -7,7 +7,7 @@
*/
/**
* @ingroup cpu_sam3
* @ingroup cpu_sam_common
* @ingroup drivers_periph_uart
* @{
*

View File

@ -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:

View File

@ -87,6 +87,7 @@ FEATURES_EXISTING := \
cpu_qn908x \
cpu_rpx0xx \
cpu_sam3 \
cpu_sam4s \
cpu_samd21 \
cpu_samd5x \
cpu_saml1x \