1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2025-12-24 14:03:55 +01:00

boards: added support for the bitcraze Crazyflie 2.1 main application processor

This commit is contained in:
LeonardHerbst 2025-09-12 16:37:11 +02:00
parent d8de73b1f4
commit f2ac773d4c
11 changed files with 571 additions and 0 deletions

View File

@ -0,0 +1,26 @@
# SPDX-FileCopyrightText: 2025 TU Dresden
# SPDX-License-Identifier: LGPL-2.1-only
config BOARD
default "bitcraze-crazyflie21-main" if BOARD_BITCRAZE_CRAZYFLIE21_MAIN
config BOARD_BITCRAZE_CRAZYFLIE21_MAIN
bool
default y
select CPU_MODEL_STM32F405RG
# Clock configuration
select BOARD_HAS_HSE
select BOARD_HAS_LSE
config CLOCK_HSE
default 8000000
config CLOCK_PLL_M
default 8
config CLOCK_PLL_N
default 336 if USEMODULE_PERIPH_USBDEV_CLK
default 360
source "$(RIOTBOARD)/common/stm32/Kconfig"

View File

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

View File

@ -0,0 +1,5 @@
ifneq (,$(filter saul_default,$(USEMODULE)))
USEMODULE += saul_gpio
endif
include $(RIOTBOARD)/common/makefiles/stdio_cdc_acm.dep.mk

View File

@ -0,0 +1,17 @@
CPU = stm32
CPU_MODEL = stm32f405rg
CFLAGS += -DCONFIG_MOTOR_DRIVER_MAX=3
# Put defined MCU peripherals here (in alphabetical order)
FEATURES_PROVIDED += periph_adc
FEATURES_PROVIDED += periph_dma
FEATURES_PROVIDED += periph_i2c
FEATURES_PROVIDED += periph_pwm
FEATURES_PROVIDED += periph_spi
FEATURES_PROVIDED += periph_timer
FEATURES_PROVIDED += periph_uart
FEATURES_PROVIDED += periph_usbdev
FEATURES_PROVIDED += highlevel_stdio
FEATURES_PROVIDED += motor_driver

View File

@ -0,0 +1,14 @@
# include shared STM32 headers
INCLUDES += -I$(RIOTBOARD)/common/stm32/include
PORT_LINUX ?= /dev/ttyACM0
ROM_OFFSET ?= 0x4000
TERM_DELAY ?= 2
PROGRAMMER ?= dfu-util
PROGRAMMERS_SUPPORTED += dfu-util
DFU_USB_ID ?= 0483:df11
DFU_USE_DFUSE ?= 1
include $(RIOTMAKE)/tools/usb_board_reset.mk

View File

@ -0,0 +1,72 @@
@defgroup boards_bitcraze_crazyflie21_main bitcraze Crazyflie 2.1 Main Application MCU
@ingroup boards
@brief Support for the main application MCU of the bitcraze Crazyflie 2.1 board.
### General information
The Crazyflie 2.1 is an open source flying development platform produced by bitcraze.
It has two onboard microcontrollers, an nRF51822 used for radio communication and power management and
an STM32F405 (this board definition) used for running the main application.
### Pinout
The pinout is part of the [Board Datasheet][board-datasheet].
The [Board Schematics][board-schematics] show which pins are connected to the motors, LEDs, etc.
[board-datasheet]: https://www.bitcraze.io/documentation/hardware/crazyflie_2_1/crazyflie_2_1-datasheet.pdf
[board-schematics]: https://www.bitcraze.io/documentation/hardware/crazyflie_2_1/crazyflie_2.1_schematics_rev.b.pdf
### MCU
| MCU | STM32F405RG |
|:---------------------|:--------------------------------------------|
| Family | ARM Cortex-M4 |
| Vendor | ST Microelectronics |
| Package | LQFP64 |
| RAM | 192 KiB (128 KiB RAM + 64 KiB CCMRAM) |
| Flash | 1024 KiB |
| Frequency | up to 168 MHz (running at 168 MHz) |
| FPU | yes |
| Timers | 14 (12× 16bit, 2× 32bit [TIM2 + TIM5]) |
| ADCs | 3× 16 channel 6 to 12-bit |
| UARTs | 6 |
| SPIs | 3 |
| I2Cs | 3 |
| Vcc | 2.0 V - 3.6 V |
| MCU Datasheet | [MCU Datasheet][mcu-datasheet] |
| MCU Reference Manual | [MCU Reference Manual][mcu-ref] |
[mcu-datasheet]: https://www.st.com/resource/en/datasheet/stm32f405rg.pdf
[mcu-ref]: https://www.st.com/resource/en/reference_manual/dm00031020-stm32f405-415-stm32f407-417-stm32f427-437-and-stm32f429-439-advanced-arm-based-32-bit-mcus-stmicroelectronics.pdf
### Flash the board
Prerequisites:
- the Crazyflie NRF firmware runs on the NRF [instructions](https://www.bitcraze.io/documentation/repository/crazyflie2-nrf-firmware/master/build/build/)
- the original Crazyflie bootloader runs on the STM32 [instructions](https://www.bitcraze.io/documentation/repository/crazyflie-firmware/master/development/dfu/#bootloader-recovery)
- `dfu-util` is installed
- the Crazyflie's battery is disconnected
To flash the board:
- navigate to the folder of the app you want to flash
- Hold down the power button on the Crazyflie
- connect via usb to your computer
- keep holding down the button for four seconds until the blink rate changes (the mcu is now in DFU mode)
- flash the board by running `BOARD=bitcraze-crazyflie21-main make all flash`
### STDIO
By default, STDIO is implemented via the native USB interface.
In order to use STDIO over UART connect your UART adapter as follows:
| PIN board | UART adapter |
|:----------|:-------------|
| PC10 (TX) | RX |
| PC11 (RX) | TX |
| GND | GND |
Now flash the board with stdio over UART:
```
USEMODULE=stdio_uart BOARD=bitcraze-crazyflie21-main make all flash
```
### Known Issues
- `timer_set()`: the callback is never called for timeouts of only one tick.

View File

@ -0,0 +1,131 @@
/*
* SPDX-FileCopyrightText: 2025 TU Dresden
* SPDX-License-Identifier: LGPL-2.1-only
*/
#pragma once
/**
* @ingroup boards_bitcraze_crazyflie21_main
* @{
*
* @file
* @brief Board specific definitions for the Crazyflie 2.1 main application MCU
*
* @author Leonard Herbst <leonard.herbst@tu-dresden.de>
*/
#include "cpu.h"
#include "motor_driver.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @name Macros for controlling the on-board LEDs.
* @{
*/
#define LED0_IS_INVERTED 1
#define LED0_PIN_NUM 3 /* LED top right red */
#define LED0_PORT GPIO_PORT_C
#define LED0_PORT_NUM PORT_C
#define LED1_IS_INVERTED 1
#define LED1_PIN_NUM 2 /* LED top right green */
#define LED1_PORT GPIO_PORT_C
#define LED1_PORT_NUM PORT_C
#define LED2_PIN_NUM 2 /* LED bottom left blue */
#define LED2_PORT GPIO_PORT_D
#define LED2_PORT_NUM PORT_D
#define LED3_IS_INVERTED 1
#define LED3_PIN_NUM 0 /* LED top left red*/
#define LED3_PORT GPIO_PORT_C
#define LED3_PORT_NUM PORT_C
#define LED4_IS_INVERTED 1
#define LED4_PIN_NUM 1 /* LED top left green */
#define LED4_PORT GPIO_PORT_C
#define LED4_PORT_NUM PORT_C
/** @} */
/**
* @name Describe DC motors with PWM channel and GPIOs
* @{
*/
/** Motor driver config. Two driver with three and one motor attached respectively */
static const motor_driver_config_t motor_driver_config[] = {
{
.pwm_dev = 1,
.mode = MOTOR_DRIVER_1_DIR,
.mode_brake = MOTOR_BRAKE_HIGH,
.pwm_mode = PWM_LEFT,
.pwm_frequency = 20000U,
.pwm_resolution = 4200U,
.nb_motors = 3,
.motors = {
{
.pwm_channel = 1,
.gpio_enable = 0,
.gpio_dir0 = 0,
.gpio_dir1_or_brake = 0,
.gpio_dir_reverse = 0,
.gpio_enable_invert = 0,
.gpio_brake_invert = 0,
},
{
.pwm_channel = 3,
.gpio_enable = 0,
.gpio_dir0 = 0,
.gpio_dir1_or_brake = 0,
.gpio_dir_reverse = 0,
.gpio_enable_invert = 0,
.gpio_brake_invert = 0,
},
{
.pwm_channel = 0,
.gpio_enable = 0,
.gpio_dir0 = 0,
.gpio_dir1_or_brake = 0,
.gpio_dir_reverse = 0,
.gpio_enable_invert = 0,
.gpio_brake_invert = 0,
},
},
.cb = NULL,
},
{
.pwm_dev = 2,
.mode = MOTOR_DRIVER_1_DIR,
.mode_brake = MOTOR_BRAKE_HIGH,
.pwm_mode = PWM_LEFT,
.pwm_frequency = 20000U,
.pwm_resolution = 4200U,
.nb_motors = 1,
.motors = {
{
.pwm_channel = 0,
.gpio_enable = 0,
.gpio_dir0 = 0,
.gpio_dir1_or_brake = 0,
.gpio_dir_reverse = 0,
.gpio_enable_invert = 0,
.gpio_brake_invert = 0,
},
},
.cb = NULL,
}
};
/** Number of motor drivers */
#define MOTOR_DRIVER_NUMOF ARRAY_SIZE(motor_driver_config)
/** @} */
#ifdef __cplusplus
}
#endif
#include "stm32_leds.h"
/** @} */

View File

@ -0,0 +1,60 @@
/*
* SPDX-FileCopyrightText: 2025 TU Dresden
* SPDX-License-Identifier: LGPL-2.1-only
*/
#pragma once
/**
* @ingroup boards_bitcraze_crazyflie21_main
* @{
*
* @file
* @brief Board specific definitions for the Crazyflie 2.1 main application MCU
*
* @author Leonard Herbst <leonard.herbst@tu-dresden.de>
*/
#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 = "red LED top right",
.pin = LED0_PIN,
.mode = GPIO_OUT
},
{
.name = "green LED top left",
.pin = LED1_PIN,
.mode = GPIO_OUT
},
{
.name = "blue LED bottom left",
.pin = LED2_PIN,
.mode = GPIO_OUT
},
{
.name = "red LED top left",
.pin = LED3_PIN,
.mode = GPIO_OUT
},
{
.name = "green LED top left",
.pin = LED4_PIN,
.mode = GPIO_OUT
},
};
/** @} */
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,241 @@
/*
* SPDX-FileCopyrightText: 2025 TU Dresden
* SPDX-License-Identifier: LGPL-2.1-only
*/
#pragma once
/**
* @ingroup boards_bitcraze_crazyflie21_main
* @{
*
* @file
* @brief Configuration of CPU peripherals for Crazyflie 2.1 main application MCU
*
* @author Leonard Herbst <leonard.herbst@tu-dresden.de>
*/
/* This board provides an LSE */
#ifndef CONFIG_BOARD_HAS_LSE
# define CONFIG_BOARD_HAS_LSE 1
#endif
/* This board provides an HSE */
#ifndef CONFIG_BOARD_HAS_HSE
# define CONFIG_BOARD_HAS_HSE 1
#endif
/* The HSE provides a 8MHz clock */
#ifndef CONFIG_CLOCK_HSE
# define CONFIG_CLOCK_HSE MHZ(8)
#endif
#include "periph_cpu.h"
#include "clk_conf.h"
#include "cfg_usb_otg_fs.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @name DMA streams configuration
* @{
*/
static const dma_conf_t dma_config[] = {
{ .stream = 11 }, /* DMA2 Stream 3 - SPI1_TX */
{ .stream = 10 }, /* DMA2 Stream 2 - SPI1_RX */
{ .stream = 3 }, /* DMA1 Stream 3 - USART3_TX */
{ .stream = 6 }, /* DMA1 Stream 6 - USART2_TX */
};
#define DMA_0_ISR isr_dma2_stream3
#define DMA_1_ISR isr_dma2_stream2
#define DMA_2_ISR isr_dma1_stream3
#define DMA_3_ISR isr_dma1_stream6
#define DMA_NUMOF ARRAY_SIZE(dma_config)
/** @} */
/**
* @name Timer configuration
*
* Avoiding TIM2 and TIM4 because they are used for pwm
*
* @{
*/
static const timer_conf_t timer_config[] = {
{
.dev = TIM5,
.max = 0xffffffff,
.rcc_mask = RCC_APB1ENR_TIM5EN,
.bus = APB1,
.irqn = TIM5_IRQn,
}
};
#define TIMER_0_ISR isr_tim5
#define TIMER_NUMOF ARRAY_SIZE(timer_config)
/** @} */
/**
* @name UART configuration
* @{
*/
static const uart_conf_t uart_config[] = {
{
.dev = USART3,
.rcc_mask = RCC_APB1ENR_USART3EN,
.rx_pin = GPIO_PIN(PORT_C, 11),
.tx_pin = GPIO_PIN(PORT_C, 10),
.rx_af = GPIO_AF7,
.tx_af = GPIO_AF7,
.bus = APB1,
.irqn = USART3_IRQn,
#ifdef MODULE_PERIPH_DMA
.dma = 2,
.dma_chan = 4
#endif
},
{
.dev = USART2,
.rcc_mask = RCC_APB1ENR_USART2EN,
.rx_pin = GPIO_PIN(PORT_A, 3),
.tx_pin = GPIO_PIN(PORT_A, 2),
.rx_af = GPIO_AF7,
.tx_af = GPIO_AF7,
.bus = APB1,
.irqn = USART2_IRQn,
#ifdef MODULE_PERIPH_DMA
.dma = 3,
.dma_chan = 4
#endif
}
};
#define UART_0_ISR (isr_usart3)
#define UART_1_ISR (isr_usart2)
#define UART_NUMOF ARRAY_SIZE(uart_config)
/** @} */
/**
* @name ADC configuration
* @{
*/
static const adc_conf_t adc_config[] = {
{ .pin = GPIO_PIN(PORT_A, 2), .dev = 0, .chan = 2 },
{ .pin = GPIO_PIN(PORT_A, 3), .dev = 0, .chan = 3 },
{ .pin = GPIO_PIN(PORT_A, 5), .dev = 1, .chan = 5 },
{ .pin = GPIO_PIN(PORT_A, 6), .dev = 1, .chan = 6 },
{ .pin = GPIO_PIN(PORT_A, 7), .dev = 1, .chan = 7 },
{ .pin = GPIO_UNDEF, .dev = 0, .chan = 0}, /* VBAT */
};
/* The radio MCU takes care of power management -> adc line without proper pin. */
#define VBAT_ADC ADC_LINE(5) /**< VBAT ADC line */
#define ADC_NUMOF ARRAY_SIZE(adc_config)
/** @} */
/**
* @name PWM configuration
* @{
*/
static const pwm_conf_t pwm_config[] = {
{
.dev = TIM9,
.rcc_mask = RCC_APB2ENR_TIM9EN,
.chan = {
{ .pin = GPIO_PIN(PORT_A, 2), .cc_chan = 0 },
{ .pin = GPIO_PIN(PORT_A, 3), .cc_chan = 1 },
{ .pin = GPIO_UNDEF, .cc_chan = 0 },
{ .pin = GPIO_UNDEF, .cc_chan = 0 } },
.af = GPIO_AF3,
.bus = APB2,
},
{
.dev = TIM2,
.rcc_mask = RCC_APB1ENR_TIM2EN,
.chan = {
{ .pin = GPIO_PIN(PORT_A, 15), .cc_chan = 0 }, /* Motor 3 */
{ .pin = GPIO_PIN(PORT_A, 1), .cc_chan = 1 }, /* Motor 1 */
{ .pin = GPIO_PIN(PORT_A, 2), .cc_chan = 2 }, /* broken out */
{ .pin = GPIO_PIN(PORT_B, 11), .cc_chan = 3 } /* Motor 2 */ },
.af = GPIO_AF1,
.bus = APB1
},
{
.dev = TIM4,
.rcc_mask = RCC_APB1ENR_TIM4EN,
.chan = {
{ .pin = GPIO_PIN(PORT_B, 9), .cc_chan = 3 }, /* Motor 4 */
{ .pin = GPIO_UNDEF, .cc_chan = 0 },
{ .pin = GPIO_UNDEF, .cc_chan = 0 },
{ .pin = GPIO_UNDEF, .cc_chan = 0 } },
.af = GPIO_AF2,
.bus = APB1
}
};
#define PWM_NUMOF ARRAY_SIZE(pwm_config)
/** @} */
/**
* @name SPI configuration
* @{
*/
static const spi_conf_t spi_config[] = {
{
.dev = SPI1,
.mosi_pin = GPIO_PIN(PORT_A, 7),
.miso_pin = GPIO_PIN(PORT_A, 6),
.sclk_pin = GPIO_PIN(PORT_A, 5),
.cs_pin = GPIO_UNDEF,
.mosi_af = GPIO_AF5,
.miso_af = GPIO_AF5,
.sclk_af = GPIO_AF5,
.cs_af = GPIO_AF5,
.rccmask = RCC_APB2ENR_SPI1EN,
.apbbus = APB2,
#ifdef MODULE_PERIPH_DMA
.tx_dma = 0,
.tx_dma_chan = 3,
.rx_dma = 1,
.rx_dma_chan = 3,
#endif
}
};
#define SPI_NUMOF ARRAY_SIZE(spi_config)
/** @} */
/**
* @name I2C configuration
* @{
*/
static const i2c_conf_t i2c_config[] = {
{
.dev = I2C1,
.speed = I2C_SPEED_NORMAL,
.scl_pin = GPIO_PIN(PORT_B, 6),
.sda_pin = GPIO_PIN(PORT_B, 7),
.scl_af = GPIO_AF4,
.sda_af = GPIO_AF4,
.bus = APB1,
.rcc_mask = RCC_APB1ENR_I2C1EN,
.clk = CLOCK_APB1,
.irqn = I2C1_EV_IRQn
}
};
#define I2C_0_ISR isr_i2c1_ev
#define I2C_NUMOF ARRAY_SIZE(i2c_config)
/** @} */
#ifdef __cplusplus
}
#endif
/** @} */

View File

@ -11,6 +11,7 @@ USEMODULE += ps
# Boards that don't have enough endpoints to use CDC ACM together with CDC ECM
ifeq (,$(filter stdio_%,$(filter-out stdio_cdc_acm,$(USEMODULE))))
BOARD_BLACKLIST += \
bitcraze-crazyflie21-main \
sipeed-longan-nano \
sipeed-longan-nano-tft \
seeedstudio-gd32 \

View File

@ -8,6 +8,7 @@ DISABLE_MODULE += auto_init_xtimer
# Boards that can't run only on xtimer or that always select ztimer
BOARD_BLACKLIST += \
adafruit-feather-nrf52840-express \
bitcraze-crazyflie21-main \
esp32s2-wemos-mini \
hamilton \
mulle \