boards/serpente: add serpente board

See https://serpente.solder.party
This commit is contained in:
Benjamin Valentin 2020-02-22 23:37:29 +01:00 committed by Benjamin Valentin
parent 59f3c1b48b
commit cddb929d0c
11 changed files with 587 additions and 0 deletions

5
boards/serpente/Makefile Normal file
View File

@ -0,0 +1,5 @@
MODULE = board
DIRS = $(RIOTBOARD)/common/samd21-arduino-bootloader
include $(RIOTBASE)/Makefile.base

View File

@ -0,0 +1,18 @@
ifneq (,$(filter mtd,$(USEMODULE)))
USEMODULE += mtd_spi_nor
endif
ifneq (,$(filter saul_default,$(USEMODULE)))
USEMODULE += saul_gpio
endif
# use arduino-bootloader only if no other stdio_% other than stdio_cdc_acm
# is requested
ifeq (,$(filter-out stdio_cdc_acm,$(filter stdio_%,$(USEMODULE))))
USEMODULE += boards_common_samd21-arduino-bootloader
endif
ifneq (,$(filter boards_common_samd21-arduino-bootloader,$(USEMODULE)))
# setup the samd21 arduino bootloader related dependencies
include $(RIOTBOARD)/common/samd21-arduino-bootloader/Makefile.dep
endif

View File

@ -0,0 +1,13 @@
CPU = samd21
CPU_MODEL = samd21e18a
# Put defined MCU peripherals here (in alphabetical order)
FEATURES_PROVIDED += bootloader_arduino
FEATURES_PROVIDED += periph_adc
FEATURES_PROVIDED += periph_i2c
FEATURES_PROVIDED += periph_rtc
FEATURES_PROVIDED += periph_rtt
FEATURES_PROVIDED += periph_spi
FEATURES_PROVIDED += periph_timer
FEATURES_PROVIDED += periph_uart
FEATURES_PROVIDED += periph_usbdev

View File

@ -0,0 +1,20 @@
PORT_LINUX ?= /dev/ttyACM0
PORT_DARWIN ?= $(firstword $(sort $(wildcard /dev/tty.usbmodem*)))
CONFIG_USB_VID=0x239A
CONFIG_USB_PID=0x0057
CFLAGS += -DBOOTLOADER_UF2
# setup serial terminal
include $(RIOTMAKE)/tools/serial.inc.mk
# setup the flash tool used
ifeq ($(PROGRAMMER),jlink)
# in case J-Link is attached to SWD pins, use a plain CPU memory model
JLINK_DEVICE := atsamd21
include $(RIOTMAKE)/tools/jlink.inc.mk
endif
# Include all definitions for flashing with bossa other USB
include $(RIOTBOARD)/common/samd21-arduino-bootloader/Makefile.include

72
boards/serpente/board.c Normal file
View File

@ -0,0 +1,72 @@
/*
* Copyright (C) 2020 Benjamin Valentin
*
* 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_serpente
* @{
*
* @file
* @brief Board specific implementations for the Serpente board
*
* @author Benjamin Valentin <benpicco@googlemail.com>
*
* @}
*/
#include "cpu.h"
#include "board.h"
#include "mtd.h"
#include "mtd_spi_nor.h"
#include "periph/gpio.h"
#include "periph/spi.h"
#include "timex.h"
#ifdef MODULE_MTD
/* GD25Q32C */
static const mtd_spi_nor_params_t _serpente_nor_params = {
.opcode = &mtd_spi_nor_opcode_default,
.wait_chip_erase = 15LU * US_PER_SEC,
.wait_32k_erase = 250LU * US_PER_MS,
.wait_sector_erase = 50LU * US_PER_MS,
.wait_4k_erase = 150LU * US_PER_MS,
.wait_chip_wake_up = 1LU * US_PER_MS,
.clk = SERPENTE_NOR_SPI_CLK,
.flag = SERPENTE_NOR_FLAGS,
.spi = SERPENTE_NOR_SPI_DEV,
.mode = SERPENTE_NOR_SPI_MODE,
.cs = SERPENTE_NOR_SPI_CS,
.addr_width = 3,
};
static mtd_spi_nor_t serpente_nor_dev = {
.base = {
.driver = &mtd_spi_nor_driver,
.page_size = SERPENTE_NOR_PAGE_SIZE,
.pages_per_sector = SERPENTE_NOR_PAGES_PER_SECTOR,
.sector_count = SERPENTE_NOR_SECTOR_COUNT,
},
.params = &_serpente_nor_params,
};
mtd_dev_t *mtd0 = (mtd_dev_t *)&serpente_nor_dev;
#endif /* MODULE_MTD */
void board_init(void)
{
/* initialize the CPU */
cpu_init();
/* initialize the on-board red LEDs */
gpio_init(LED0_PIN, GPIO_OUT);
gpio_init(LED1_PIN, GPIO_OUT);
gpio_init(LED2_PIN, GPIO_OUT);
LED0_OFF;
LED1_OFF;
LED2_OFF;
}

45
boards/serpente/doc.txt Normal file
View File

@ -0,0 +1,45 @@
/**
@defgroup boards_serpente Serpente R2
@ingroup boards
@brief Support for the Serpente board.
### General information
The [Serpente boards](https://serpente.solder.party/) are low-cost development boards designed
to be used with Adafruits CircuitPython.
Three versions of the board board exist, but they all the same except for the USB connector.
The standard Serpente board contains a female USB Type-C connector, the Serpente Plug C
contains a male USB Type-C connector, and the Serpente Plug uses the board itself as a Type-A USB plug.
If you are familiar with the Digispark boards, you may notice some similarities.
This fact is of course not incidental, the Serpente boards are inspired by the Digispark,
both in form-factor as well as use-cases. The Serpente boards are meant to be used as quick
and dirty, yet flexible, prototyping tools.
### Pinout
\image html https://serpente.solder.party/r2/pinout.png width=66%
### Flash the board
Use `BOARD=serpente` with the `make` command.<br/>
Example with `micropython` application:
```
make BOARD=serpente -C examples/micropython flash
```
RIOT will automatically trigger a reset to the bootloader, but this only works if RIOT is still
running on the board.
If your application has crashed or got erased, `make flash` will not be able to trigger a bootloader reset.
To manually enter the bootloader, quickly press the Reset button twice.
You know you've successfully entered the bootloader when the LED begins flashing blue.
Sometimes flashing fails and the board gets stuck in the bootloader.
In this case, just run `make flash` again when the device is not busy anymore.
### Accessing STDIO via UART
STDIO of RIOT is directly available over the USB port.
*/

View File

@ -0,0 +1,94 @@
/*
* Copyright (C) 2020 Benjamin Valentin
*
* 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_serpente
* @brief Support for the Serpente board.
* @{
*
* @file
* @brief Board specific definitions for the Serpente
* board
*
* @author Benjamin Valentin <benpicco@googlemail.com>
*/
#ifndef BOARD_H
#define BOARD_H
#include "cpu.h"
#include "periph_conf.h"
#include "mtd.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @name LED pin definitions and handlers
* @{
*/
#define LED_PORT PORT->Group[PA]
#define LED0_PIN GPIO_PIN(PA, 22)
#define LED0_MASK (1 << 22)
#define LED0_NAME "LED(Red)"
#define LED0_OFF (LED_PORT.OUTSET.reg = LED0_MASK)
#define LED0_ON (LED_PORT.OUTCLR.reg = LED0_MASK)
#define LED0_TOGGLE (LED_PORT.OUTTGL.reg = LED0_MASK)
#define LED1_PIN GPIO_PIN(PA, 19)
#define LED1_MASK (1 << 19)
#define LED1_NAME "LED(Green)"
#define LED1_OFF (LED_PORT.OUTSET.reg = LED1_MASK)
#define LED1_ON (LED_PORT.OUTCLR.reg = LED1_MASK)
#define LED1_TOGGLE (LED_PORT.OUTTGL.reg = LED1_MASK)
#define LED2_PIN GPIO_PIN(PA, 23)
#define LED2_MASK (1 << 23)
#define LED2_NAME "LED(Blue)"
#define LED2_OFF (LED_PORT.OUTSET.reg = LED2_MASK)
#define LED2_ON (LED_PORT.OUTCLR.reg = LED2_MASK)
#define LED2_TOGGLE (LED_PORT.OUTTGL.reg = LED2_MASK)
/** @} */
/**
* @name Serpente NOR flash hardware configuration
* @{
*/
#define SERPENTE_NOR_PAGE_SIZE (256)
#define SERPENTE_NOR_PAGES_PER_SECTOR (16)
#define SERPENTE_NOR_SECTOR_COUNT (1024)
#define SERPENTE_NOR_FLAGS (SPI_NOR_F_SECT_4K | SPI_NOR_F_SECT_32K)
#define SERPENTE_NOR_SPI_DEV SPI_DEV(0)
#define SERPENTE_NOR_SPI_CLK SPI_CLK_10MHZ
#define SERPENTE_NOR_SPI_CS GPIO_PIN(PA, 15)
#define SERPENTE_NOR_SPI_MODE SPI_MODE_3
/** @} */
/**
* @name MTD configuration
* @{
*/
extern mtd_dev_t *mtd0;
#define MTD_0 mtd0
/** @} */
/**
* @brief Initialize board specific hardware, including clock, LEDs and std-IO
*/
void board_init(void);
#ifdef __cplusplus
}
#endif
#endif /* BOARD_H */
/** @} */

View File

@ -0,0 +1,59 @@
/*
* Copyright (C) 2020 Benjamin Valentin
*
* 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_serpente
* @{
*
* @file
* @brief Board specific configuration of direct mapped GPIOs
*
* @author Benjamin Valentin <benpicco@googlemail.com>
*/
#ifndef GPIO_PARAMS_H
#define GPIO_PARAMS_H
#include "board.h"
#include "saul/periph.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief GPIO pin configuration
*/
static const saul_gpio_params_t saul_gpio_params[] =
{
{
.name = LED0_NAME,
.pin = LED0_PIN,
.mode = GPIO_OUT,
.flags = SAUL_GPIO_INVERTED,
},
{
.name = LED1_NAME,
.pin = LED1_PIN,
.mode = GPIO_OUT,
.flags = SAUL_GPIO_INVERTED,
},
{
.name = LED2_NAME,
.pin = LED2_PIN,
.mode = GPIO_OUT,
.flags = SAUL_GPIO_INVERTED,
},
};
#ifdef __cplusplus
}
#endif
#endif /* GPIO_PARAMS_H */
/** @} */

View File

@ -0,0 +1,259 @@
/*
* Copyright (C) 2020 Benjamin Valentin
*
* 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_serpente
* @{
*
* @file
* @brief Configuration of CPU peripherals for the Serpente board
*
* @author Benjamin Valentin <benpicco@googlemail.com>
*/
#ifndef PERIPH_CONF_H
#define PERIPH_CONF_H
#include <stdint.h>
#include "cpu.h"
#include "periph_cpu.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @name External oscillator and clock configuration
*
* For selection of the used CORECLOCK, we have implemented two choices:
*
* - usage of the PLL fed by the internal 8MHz oscillator divided by 8
* - usage of the internal 8MHz oscillator directly, divided by N if needed
*
*
* The PLL option allows for the usage of a wider frequency range and a more
* stable clock with less jitter. This is why we use this option as default.
*
* The target frequency is computed from the PLL multiplier and the PLL divisor.
* Use the following formula to compute your values:
*
* CORECLOCK = ((PLL_MUL + 1) * 1MHz) / PLL_DIV
*
* NOTE: The PLL circuit does not run with less than 32MHz while the maximum PLL
* frequency is 96MHz. So PLL_MULL must be between 31 and 95!
*
*
* The internal Oscillator used directly can lead to a slightly better power
* efficiency to the cost of a less stable clock. Use this option when you know
* what you are doing! The actual core frequency is adjusted as follows:
*
* CORECLOCK = 8MHz / DIV
*
* NOTE: A core clock frequency below 1MHz is not recommended
*
* @{
*/
#define CLOCK_USE_PLL (1)
#if CLOCK_USE_PLL
/* edit these values to adjust the PLL output frequency */
#define CLOCK_PLL_MUL (47U) /* must be >= 31 & <= 95 */
#define CLOCK_PLL_DIV (1U) /* adjust to your needs */
#define CLOCK_CORECLOCK (((CLOCK_PLL_MUL + 1) * 1000000U) / CLOCK_PLL_DIV)
#else
/* edit this value to your needs */
#define CLOCK_DIV (1U)
/* generate the actual core clock frequency */
#define CLOCK_CORECLOCK (8000000 / CLOCK_DIV)
#endif
/** @} */
/**
* @name Timer peripheral configuration
* @{
*/
static const tc32_conf_t timer_config[] = {
{ /* Timer 0 - System Clock */
.dev = TC3,
.irq = TC3_IRQn,
.pm_mask = PM_APBCMASK_TC3,
.gclk_ctrl = GCLK_CLKCTRL_ID_TCC2_TC3,
#if CLOCK_USE_PLL || CLOCK_USE_XOSC32_DFLL
.gclk_src = SAM0_GCLK_1MHZ,
.prescaler = TC_CTRLA_PRESCALER_DIV1,
#else
.gclk_src = SAM0_GCLK_MAIN,
.prescaler = TC_CTRLA_PRESCALER_DIV8,
#endif
.flags = TC_CTRLA_MODE_COUNT16,
},
{ /* Timer 1 */
.dev = TC4,
.irq = TC4_IRQn,
.pm_mask = PM_APBCMASK_TC4 | PM_APBCMASK_TC5,
.gclk_ctrl = GCLK_CLKCTRL_ID_TC4_TC5,
#if CLOCK_USE_PLL || CLOCK_USE_XOSC32_DFLL
.gclk_src = SAM0_GCLK_1MHZ,
.prescaler = TC_CTRLA_PRESCALER_DIV1,
#else
.gclk_src = SAM0_GCLK_MAIN,
.prescaler = TC_CTRLA_PRESCALER_DIV8,
#endif
.flags = TC_CTRLA_MODE_COUNT32,
}
};
#define TIMER_0_MAX_VALUE 0xffff
/* interrupt function name mapping */
#define TIMER_0_ISR isr_tc3
#define TIMER_1_ISR isr_tc4
#define TIMER_NUMOF ARRAY_SIZE(timer_config)
/** @} */
/**
* @name UART configuration
* @{
*/
static const uart_conf_t uart_config[] = {
{
.dev = &SERCOM2->USART,
.rx_pin = GPIO_PIN(PA, 9), /* D5 */
.tx_pin = GPIO_PIN(PA, 8), /* D4 */
.mux = GPIO_MUX_D,
.rx_pad = UART_PAD_RX_1,
.tx_pad = UART_PAD_TX_0,
.flags = UART_FLAG_NONE,
.gclk_src = SAM0_GCLK_MAIN,
},
{
.dev = &SERCOM0->USART,
.rx_pin = GPIO_PIN(PA, 5), /* D1 */
.tx_pin = GPIO_PIN(PA, 4), /* D0 */
.mux = GPIO_MUX_D,
.rx_pad = UART_PAD_RX_1,
.tx_pad = UART_PAD_TX_0,
.flags = UART_FLAG_NONE,
.gclk_src = SAM0_GCLK_MAIN,
}
};
/* interrupt function name mapping */
#define UART_0_ISR isr_sercom2
#define UART_1_ISR isr_sercom0
#define UART_NUMOF ARRAY_SIZE(uart_config)
/** @} */
/**
* @name SPI configuration
* @{
*/
static const spi_conf_t spi_config[] = {
{ /* Flash */
.dev = &SERCOM1->SPI,
.miso_pin = GPIO_PIN(PA, 18),
.mosi_pin = GPIO_PIN(PA, 16),
.clk_pin = GPIO_PIN(PA, 17),
.miso_mux = GPIO_MUX_C,
.mosi_mux = GPIO_MUX_C,
.clk_mux = GPIO_MUX_C,
.miso_pad = SPI_PAD_MISO_2,
.mosi_pad = SPI_PAD_MOSI_0_SCK_1,
.gclk_src = SAM0_GCLK_MAIN,
},
{ /* D0 … D2 (user pins) */
.dev = &SERCOM0->SPI,
.miso_pin = GPIO_PIN(PA, 6), /* D2 */
.mosi_pin = GPIO_PIN(PA, 4), /* D0 */
.clk_pin = GPIO_PIN(PA, 5), /* D1 */
.miso_mux = GPIO_MUX_D,
.mosi_mux = GPIO_MUX_D,
.clk_mux = GPIO_MUX_D,
.miso_pad = SPI_PAD_MISO_2,
.mosi_pad = SPI_PAD_MOSI_0_SCK_1,
.gclk_src = SAM0_GCLK_MAIN,
},
};
#define SPI_NUMOF ARRAY_SIZE(spi_config)
/** @} */
/**
* @name I2C configuration
* @{
*/
static const i2c_conf_t i2c_config[] = {
{
.dev = &(SERCOM2->I2CM),
.speed = I2C_SPEED_NORMAL,
.scl_pin = GPIO_PIN(PA, 9), /* D5 */
.sda_pin = GPIO_PIN(PA, 8), /* D4 */
.mux = GPIO_MUX_D,
.gclk_src = SAM0_GCLK_MAIN,
.flags = I2C_FLAG_NONE
}
};
#define I2C_NUMOF ARRAY_SIZE(i2c_config)
/** @} */
/**
* @name RTT configuration
* @{
*/
#define RTT_MAX_VALUE (0xffffffff)
#define RTT_FREQUENCY (32768U) /* in Hz. For changes see `rtt.c` */
/** @} */
/**
* @name ADC Default values
* @{
*/
#define ADC_PRESCALER ADC_CTRLB_PRESCALER_DIV512
#define ADC_NEG_INPUT ADC_INPUTCTRL_MUXNEG_GND
#define ADC_GAIN_FACTOR_DEFAULT ADC_INPUTCTRL_GAIN_1X
#define ADC_REF_DEFAULT ADC_REFCTRL_REFSEL_INT1V
static const adc_conf_chan_t adc_channels[] = {
/* port, pin, muxpos */
{GPIO_PIN(PA, 4), ADC_INPUTCTRL_MUXPOS_PIN4},
{GPIO_PIN(PA, 5), ADC_INPUTCTRL_MUXPOS_PIN5},
{GPIO_PIN(PA, 6), ADC_INPUTCTRL_MUXPOS_PIN6},
{GPIO_PIN(PA, 7), ADC_INPUTCTRL_MUXPOS_PIN7},
{GPIO_PIN(PA, 8), ADC_INPUTCTRL_MUXPOS_PIN16},
{GPIO_PIN(PA, 9), ADC_INPUTCTRL_MUXPOS_PIN17},
};
#define ADC_NUMOF ARRAY_SIZE(adc_channels)
/** @} */
/**
* @name USB peripheral configuration
* @{
*/
static const sam0_common_usb_config_t sam_usbdev_config[] = {
{
.dm = GPIO_PIN(PA, 24),
.dp = GPIO_PIN(PA, 25),
.d_mux = GPIO_MUX_G,
.device = &USB->DEVICE,
.gclk_src = SAM0_GCLK_MAIN,
}
};
/** @} */
#ifdef __cplusplus
}
#endif
#endif /* PERIPH_CONF_H */
/** @} */

View File

@ -66,6 +66,7 @@ BOARD_INSUFFICIENT_MEMORY := \
samr34-xpro \ samr34-xpro \
seeeduino_arch-pro \ seeeduino_arch-pro \
sensebox_samd21 \ sensebox_samd21 \
serpente \
slstk3401a \ slstk3401a \
sltb001a \ sltb001a \
slwstk6000b-slwrb4150a \ slwstk6000b-slwrb4150a \

View File

@ -1,4 +1,5 @@
BOARD_INSUFFICIENT_MEMORY := \ BOARD_INSUFFICIENT_MEMORY := \
im880b \ im880b \
olimexino-stm32 \ olimexino-stm32 \
serpente \
# #