mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2025-12-25 14:33:52 +01:00
16782: drivers/mfrc522: add new driver r=benpicco a=HendrikVE ### Contribution description This PR adds support for the MFRC522. It is quite common in the Arduino world and it is quite cheap. The driver connects to the MFRC522 via SPI and is heavily based on the Arduino driver available [here](https://github.com/miguelbalboa/rfid). Basically it was ported, but with several improvements in readability and documentation. ### Testing procedure The given (manual) test provides single commands for some driver functions. 19201: cpu/gd32v: add periph_i2c support r=benpicco a=gschorcht ### Contribution description This PR provides the `periph_i2c` support and is one of a bunch of PRs that complete the peripheral drivers for GD32VF103. The driver is a modified version of the driver for STM32F1 with some changes that were necessary to get it working on GD32V. As for STM32F1, the driver is using polling instead of interrupts for now. It will be implemented interrupt-driven later. ### Testing procedure `tests/periph_i2c` as well as a test with any I2C sensor should work. The driver was tested with `tests/driver_l3gxxxx` and `tests/driver_bmp180`. ### Issues/PRs references Co-authored-by: Hendrik van Essen <hendrik.ve@fu-berlin.de> Co-authored-by: Gunar Schorcht <gunar@schorcht.net>
368 lines
10 KiB
C
368 lines
10 KiB
C
/*
|
|
* Copyright (C) 2020 Koen Zandberg <koen@bergzand.net>
|
|
*
|
|
* 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_gd32v
|
|
* @{
|
|
*
|
|
* @file
|
|
* @brief CPU specific definitions for internal peripheral handling
|
|
*
|
|
* @author Koen Zandberg <koen@bergzand.net>
|
|
*/
|
|
|
|
#ifndef PERIPH_CPU_H
|
|
#define PERIPH_CPU_H
|
|
|
|
#include <inttypes.h>
|
|
|
|
#include "cpu.h"
|
|
#include "clic.h"
|
|
#include "kernel_defines.h"
|
|
#include "macros/units.h"
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
/**
|
|
* @name Power management configuration
|
|
* @{
|
|
*/
|
|
/**
|
|
* @brief Number of usable low power modes
|
|
*/
|
|
#define PM_NUM_MODES (3U) /**< Number of usable low power modes */
|
|
|
|
/**
|
|
* @brief Power modes
|
|
*
|
|
* The GD32V has three power modes (terminology as defined by GigaDevice).
|
|
* - Sleep: Only the clock of the RISC-V core is switched off.
|
|
* - Deep sleep: The RISC-V core including all AHB and APB peripheralsa and all
|
|
* high speed clocks are off. The LDO is in operation and the
|
|
* SRAM is retained.
|
|
* The MCU can be woken up by external interrupts or events
|
|
* without restart.
|
|
* - Standby: The RISC-V core including all AHB and APB peripherals, all
|
|
* high-speed clocks, and the LDO are off. The SRAM is not
|
|
* retained.
|
|
* The MCU can be woken up by WKUP or the NRST pin, watchdog
|
|
* reset and RTC alarms with restart.
|
|
*/
|
|
enum {
|
|
GD32V_PM_STANDBY = 0, /**< STANDBY mode, */
|
|
GD32V_PM_DEEPSLEEP = 1, /**< DEEPSLEEP mode, corresponds to STOP mode of STM32 */
|
|
GD32V_PM_IDLE = 2 /**< IDLE mode */
|
|
};
|
|
|
|
/**
|
|
* @brief Wake-up pin used
|
|
*/
|
|
#ifndef CONFIG_PM_EWUP_USED
|
|
#define CONFIG_PM_EWUP_USED (0U)
|
|
#endif
|
|
/** @} */
|
|
|
|
/**
|
|
* @brief On-Chip buses
|
|
*/
|
|
typedef enum {
|
|
AHB, /**< Advanced High-performance Bus */
|
|
APB1, /**< Advanced Peripheral Bus 1 */
|
|
APB2, /**< Advanced Peripheral Bus 2 */
|
|
} bus_t;
|
|
|
|
/**
|
|
* @brief Available GPIO ports
|
|
*/
|
|
enum {
|
|
#ifdef GPIOA
|
|
PORT_A = 0, /**< port A */
|
|
#endif
|
|
#ifdef GPIOB
|
|
PORT_B = 1, /**< port B */
|
|
#endif
|
|
#ifdef GPIOC
|
|
PORT_C = 2, /**< port C */
|
|
#endif
|
|
#ifdef GPIOD
|
|
PORT_D = 3, /**< port D */
|
|
#endif
|
|
#ifdef GPIOE
|
|
PORT_E = 4, /**< port E */
|
|
#endif
|
|
};
|
|
|
|
#ifndef DOXYGEN
|
|
/**
|
|
* @brief Overwrite the default gpio_t type definition
|
|
* @{
|
|
*/
|
|
#define HAVE_GPIO_T
|
|
typedef uint32_t gpio_t;
|
|
/** @} */
|
|
|
|
/**
|
|
* @brief Definition of a fitting UNDEF value
|
|
*/
|
|
#define GPIO_UNDEF (0xffffffff)
|
|
|
|
/**
|
|
* @brief Define a CPU specific GPIO pin generator macro
|
|
*/
|
|
#define GPIO_PIN(x, y) ((GPIOA_BASE + (x << 10)) | y)
|
|
|
|
/**
|
|
* @brief Generate GPIO mode bitfields
|
|
*
|
|
* We use 5 bit to encode the mode:
|
|
* - bit 0+1: pin mode (input / output)
|
|
* - bit 2+3: pull resistor configuration
|
|
* - bit 4: output type (0: push-pull, 1: open-drain)
|
|
*/
|
|
#define GPIO_MODE(io, pr, ot) ((io << 0) | (pr << 2) | (ot << 4))
|
|
|
|
/**
|
|
* @brief Override GPIO mode options
|
|
*
|
|
* We use 4 bit to encode CNF and MODE.
|
|
* @{
|
|
*/
|
|
#define HAVE_GPIO_MODE_T
|
|
typedef enum {
|
|
GPIO_IN = GPIO_MODE(0, 1, 0), /**< input w/o pull R */
|
|
GPIO_IN_PD = GPIO_MODE(0, 2, 0), /**< input with pull-down */
|
|
GPIO_IN_PU = GPIO_MODE(0, 2, 1), /**< input with pull-up */
|
|
GPIO_OUT = GPIO_MODE(3, 0, 0), /**< push-pull output */
|
|
GPIO_OD = GPIO_MODE(3, 1, 0), /**< open-drain w/o pull R */
|
|
GPIO_OD_PU = (0xff) /**< not supported by HW */
|
|
} gpio_mode_t;
|
|
/** @} */
|
|
|
|
/**
|
|
* @brief Override flank configuration values
|
|
* @{
|
|
*/
|
|
#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 Override alternative GPIO mode options
|
|
*/
|
|
typedef enum {
|
|
GPIO_AF_OUT_PP = 0xb, /**< alternate function output - push-pull */
|
|
GPIO_AF_OUT_OD = 0xf, /**< alternate function output - open-drain */
|
|
} gpio_af_t;
|
|
|
|
/**
|
|
* @brief GD32V timers have 4 capture-compare channels
|
|
*/
|
|
#define TIMER_CHANNEL_NUMOF (4U)
|
|
|
|
/**
|
|
* @brief Macro for accessing the capture/compare register of a timer channel
|
|
*/
|
|
#define TIMER_CHANNEL(tim, chan) *(&dev(tim)->CH0CV + (chan * 2))
|
|
|
|
/**
|
|
* @brief Timer configuration
|
|
*/
|
|
typedef struct {
|
|
TIMER_Type *dev; /**< timer device */
|
|
uint32_t max; /**< maximum value to count to (16/32 bit) */
|
|
uint32_t rcu_mask; /**< corresponding bit in the RCC register */
|
|
uint8_t bus; /**< APBx bus the timer is clock from */
|
|
uint8_t irqn; /**< global IRQ channel */
|
|
} timer_conf_t;
|
|
|
|
/**
|
|
* @brief Structure for UART configuration data
|
|
*/
|
|
typedef struct {
|
|
USART_Type *dev; /**< UART device base register address */
|
|
uint32_t rcu_mask; /**< bit in clock enable register */
|
|
gpio_t rx_pin; /**< RX pin */
|
|
gpio_t tx_pin; /**< TX pin */
|
|
uint8_t bus; /**< APB bus */
|
|
uint8_t irqn; /**< IRQ channel */
|
|
} uart_conf_t;
|
|
|
|
/**
|
|
* @brief UART interrupt priority
|
|
*/
|
|
#define UART_ISR_PRIO (2)
|
|
|
|
/**
|
|
* @name This CPU makes use of the following shared SPI functions
|
|
* @{
|
|
*/
|
|
#define PERIPH_SPI_NEEDS_TRANSFER_BYTE 1
|
|
#define PERIPH_SPI_NEEDS_TRANSFER_REG 1
|
|
#define PERIPH_SPI_NEEDS_TRANSFER_REGS 1
|
|
/** @} */
|
|
|
|
/**
|
|
* @brief Structure for SPI configuration data
|
|
*/
|
|
typedef struct {
|
|
uint32_t addr; /**< SPI control register address */
|
|
gpio_t mosi; /**< MOSI pin */
|
|
gpio_t miso; /**< MISO pin */
|
|
gpio_t sclk; /**< SCLK pin */
|
|
} spi_conf_t;
|
|
|
|
/**
|
|
* @name Use the shared I2C functions
|
|
* @{
|
|
*/
|
|
/** Use read reg function from periph common */
|
|
#define PERIPH_I2C_NEED_READ_REG
|
|
/** Use write reg function from periph common */
|
|
#define PERIPH_I2C_NEED_WRITE_REG
|
|
/** Use read regs function from periph common */
|
|
#define PERIPH_I2C_NEED_READ_REGS
|
|
/** Use write regs function from periph common */
|
|
#define PERIPH_I2C_NEED_WRITE_REGS
|
|
/** @} */
|
|
|
|
#ifndef DOXYGEN
|
|
/**
|
|
* @brief Default mapping of I2C bus speed values
|
|
* @{
|
|
*/
|
|
#define HAVE_I2C_SPEED_T
|
|
typedef enum {
|
|
I2C_SPEED_LOW = KHZ(10), /**< low speed mode: ~10kit/s */
|
|
I2C_SPEED_NORMAL = KHZ(100), /**< normal mode: ~100kbit/s */
|
|
I2C_SPEED_FAST = KHZ(400), /**< fast mode: ~400kbit/s */
|
|
I2C_SPEED_FAST_PLUS = MHZ(1), /**< fast plus mode: ~1Mbit/s */
|
|
} i2c_speed_t;
|
|
/** @} */
|
|
#endif /* ndef DOXYGEN */
|
|
|
|
/**
|
|
* @brief I2C configuration options
|
|
*/
|
|
typedef struct {
|
|
I2C_Type *dev; /**< i2c device */
|
|
i2c_speed_t speed; /**< i2c bus speed */
|
|
gpio_t scl_pin; /**< scl pin number */
|
|
gpio_t sda_pin; /**< sda pin number */
|
|
uint32_t rcu_mask; /**< bit in clock enable register */
|
|
uint8_t irqn; /**< I2C event interrupt number */
|
|
} i2c_conf_t;
|
|
|
|
/**
|
|
* @brief PWM channel
|
|
*/
|
|
typedef struct {
|
|
gpio_t pin; /**< GPIO pin mapped to this channel */
|
|
uint8_t cc_chan; /**< capture compare channel used */
|
|
} pwm_chan_t;
|
|
|
|
/**
|
|
* @brief PWM configuration
|
|
*/
|
|
typedef struct {
|
|
TIMER_Type *dev; /**< Timer used */
|
|
uint32_t rcu_mask; /**< bit in clock enable register */
|
|
uint32_t remap; /**< AFIO remap mask to route periph
|
|
to other pins (or zero, if not
|
|
needed) */
|
|
pwm_chan_t chan[TIMER_CHANNEL_NUMOF]; /**< channel mapping set to
|
|
{GPIO_UNDEF, 0} if not used */
|
|
gpio_af_t af; /**< alternate function used */
|
|
uint8_t bus; /**< APB bus */
|
|
} pwm_conf_t;
|
|
|
|
/**
|
|
* @name WDT upper and lower bound times in ms
|
|
* @{
|
|
*/
|
|
#define NWDT_TIME_LOWER_LIMIT (1)
|
|
/* Ensure the internal "count" variable stays within the uint32 bounds.
|
|
This variable corresponds to max_time * RTC_FREQ / MS_PER_SEC. On fe310,
|
|
RTC_FREQ is 32768Hz. The 15 right shift is equivalent to a division by RTC_FREQ.
|
|
*/
|
|
#define NWDT_TIME_UPPER_LIMIT ((UINT32_MAX >> 15) * MS_PER_SEC + 1)
|
|
/** @} */
|
|
|
|
/**
|
|
* @brief WDT interrupt priority: use highest priority
|
|
*/
|
|
#define WDT_INTR_PRIORITY (PLIC_NUM_PRIORITIES)
|
|
|
|
/**
|
|
* @brief No brakes on the WDT train
|
|
*/
|
|
#define WDT_HAS_STOP (0)
|
|
|
|
/**
|
|
* @name RTT/RTC configuration
|
|
* @{
|
|
*/
|
|
#define RTT_DEV RTC /**< RTC is used as RTT device */
|
|
|
|
#define RTT_IRQ RTC_ALARM_IRQn /**< RTC_ALARM_IRQn is used as IRQ number */
|
|
#define RTT_IRQ_PRIORITY (2) /**< RTT interrupt priority */
|
|
#define RTT_MAX_VALUE (0xffffffff) /**< maximum RTT value */
|
|
|
|
#define RTT_MIN_FREQUENCY (1U) /**< minimum RTT frequency in Hz */
|
|
/** @} */
|
|
|
|
/**
|
|
* @brief Enable the given peripheral clock
|
|
*
|
|
* @param[in] bus bus the peripheral is connected to
|
|
* @param[in] mask bit in the RCU enable register
|
|
*/
|
|
void periph_clk_en(bus_t bus, uint32_t mask);
|
|
|
|
/**
|
|
* @brief Disable the given peripheral clock
|
|
*
|
|
* @param[in] bus bus the peripheral is connected to
|
|
* @param[in] mask bit in the RCU enable register
|
|
*/
|
|
void periph_clk_dis(bus_t bus, uint32_t mask);
|
|
|
|
/**
|
|
* @brief Get the actual bus clock frequency for the APB buses
|
|
*
|
|
* @param[in] bus target APBx bus
|
|
*
|
|
* @return bus clock frequency in Hz
|
|
*/
|
|
uint32_t periph_apb_clk(bus_t bus);
|
|
|
|
/**
|
|
* @brief Configure the alternate function for the given pin
|
|
*
|
|
* @param[in] pin pin to configure
|
|
* @param[in] af alternate function to use
|
|
*/
|
|
void gpio_init_af(gpio_t pin, gpio_af_t af);
|
|
|
|
void gd32vf103_clock_init(void);
|
|
void gd32v_enable_irc8(void);
|
|
void gd32v_disable_irc8(void);
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
|
|
#endif /* PERIPH_CPU_H */
|
|
/** @} */
|