/* * Copyright (C) 2020 iosabi * * 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_qn908x * @{ * * @file * @brief CPU specific definitions for internal peripheral handling * * @author iosabi */ #ifndef PERIPH_CPU_H #define PERIPH_CPU_H #include #include #include "cpu.h" #ifdef __cplusplus extern "C" { #endif /** * @name CPU specific gpio_t type definition * @{ */ #define HAVE_GPIO_T typedef uint16_t gpio_t; /** @} */ /** * @brief Definition of a fitting UNDEF value */ #define GPIO_UNDEF (0xffff) /** * @brief Define a CPU specific GPIO pin generator macro. * * This generates the GPIO port base address with a mask of the GPIO_PIN value * to avoid a memory access. The value 12 here is selected as an optimization * to be able to derive the GPIO port address with a simple mask of the GPIO_PIN * value. */ #define GPIO_PIN(x, y) (((x) << 12u) | (y)) /* QN908x has a unique default Bluetooth address in the Flash Information Page * descriptor. This value is set in the factory and cannot be modified by * users. However, the actual Bluetooth address used by the stack may be * different, this is just the default. */ /** * @brief Starting offset of CPU_ID */ #define CPUID_ADDR (FSL_FEATURE_FLASH_ADDR_OF_VENDOR_BD_ADDR) /** * @brief Length of the CPU_ID in octets */ #define CPUID_LEN (6U) /** * @brief Watchdog clock can be stopped independently of other clocks. */ #define WDT_HAS_STOP (1) /** * @name WDT upper and lower bound times in ms * @{ */ /** The WDT clock can run up to 16MHz (via CLK_APB) and the WDT counter is * 32-bit so the maximum value in ms we can wait is ((1 << 32) - 1) / 16000. * TODO: A much larger limit (~1.5 days) can be set if the WDT runs from the * 32 KHz clock. However, this is likely decided by the board and depends on the * clocks installed on the board. Figure out a way to configure this limit based * on the clock used. */ #define NWDT_TIME_LOWER_LIMIT (1U) #define NWDT_TIME_UPPER_LIMIT (268435U) #define WWDT_TIME_LOWER_LIMIT (1U) #define WWDT_TIME_UPPER_LIMIT (268435U) /** @} */ /** * @brief Generate GPIO mode bitfields * * The GPIO_MODE has the following structure: * - bit 0: open-drain: 1 for enabled (open-drain mode) and 0 for disabled. * - bit 1: output-enabled: 1 output mode, 0 input mode. * - bit 4-5: pull_mode: 0 for hi-z (no pull-up or down), 1 for pull-down and 2 * for pull-up. These correspond to the IOCON_MODE macros. */ #define GPIO_MODE(open_drain, out_enabled, pull_mode) \ ((open_drain) | ((out_enabled) << 1) | ((pull_mode) << 4)) #ifndef DOXYGEN /** * @name GPIO pin modes * @{ */ #define HAVE_GPIO_MODE_T typedef enum { GPIO_IN = GPIO_MODE(0, 0, 0), /**< IN */ GPIO_IN_PD = GPIO_MODE(0, 0, 1), /**< IN with pull-down */ GPIO_IN_PU = GPIO_MODE(0, 0, 2), /**< IN with pull-up */ GPIO_OUT = GPIO_MODE(0, 1, 0), /**< OUT (push-pull) */ GPIO_OD = GPIO_MODE(1, 1, 0), /**< OD */ GPIO_OD_PU = GPIO_MODE(1, 1, 2), /**< OD with pull-up */ } gpio_mode_t; /** @} */ #endif /* ndef DOXYGEN */ #ifndef DOXYGEN /** * @name GPIO flank configuration values * @{ */ #define HAVE_GPIO_FLANK_T typedef enum { GPIO_LOW = 0, /**< emit interrupt when the value is low */ GPIO_HIGH = 1, /**< emit interrupt when the value is high */ GPIO_RISING = 2, /**< emit interrupt on rising flank */ GPIO_FALLING = 3, /**< emit interrupt on falling flank */ GPIO_BOTH = 4, /**< not supported -- rising and falling flanks */ } gpio_flank_t; /** @} */ #endif /* ndef DOXYGEN */ /** * @brief Available ports on the QN908x. */ enum { PORT_A = 0, /**< port A */ PORT_B = 1, /**< port B */ GPIO_PORTS_NUMOF /**< overall number of available ports */ }; /** * @name ADC CPU configuration * @{ */ #if DOXYGEN /** * @brief Define if ADC external capacitor is connected to PA06 pin. * * The ADC block can use an external capacitor to better stabilize the reference * voltage. This capacitor is optional, but if it is present on the board this * macro should be defined by the board to make the ADC block use it. */ #define BOARD_HAS_ADC_PA06_CAP #endif #ifndef DOXYGEN /** * @name ADC resolution values * @{ */ #define HAVE_ADC_RES_T typedef enum { ADC_RES_6BIT = 6u, /**< ADC resolution: 6 bit + sign */ ADC_RES_8BIT = 8u, /**< ADC resolution: 8 bit + sign */ ADC_RES_10BIT = 10u, /**< ADC resolution: 10 bit + sign */ ADC_RES_12BIT = 12u, /**< ADC resolution: 12 bit + sign */ ADC_RES_14BIT = 14u, /**< ADC resolution: 14 bit + sign */ ADC_RES_16BIT = 16u, /**< ADC resolution: 16 bit + sign */ /* Extra modes supported by this CPU. */ ADC_RES_MAX = 22u, /**< Full ADC resolution: 22 bit + sign */ ADC_RES_UV = 23u, /**< ADC resolution: signed int in uV */ } adc_res_t; /** @} */ #endif /* ifndef DOXYGEN */ /** * @brief ADC oversample clock configuration * * The ADC runs at a given ADC clock frequency which is derived from either the * high frequency clock (16 or 32 MHz) or the low frequency one (32 or * 32.768 KHz). Running the ADC from the 32 KHz source can be useful in low * power applications where the high speed clock is not running. * * The ADC sample rate for adc_sample() will be about 128 times slower than the * ADC clock, due to the decimation filter, meaning that the maximum sampling * rate is 31.25 KHz. */ typedef enum { ADC_CLOCK_4M, /**< 4 MHz from the high speed clock. */ ADC_CLOCK_2M, /**< 2 MHz from the high speed clock. */ ADC_CLOCK_1M, /**< 1 MHz from the high speed clock. */ ADC_CLOCK_500K, /**< 500 KHz from the high speed clock. */ ADC_CLOCK_250K, /**< 250 KHz from the high speed clock. */ ADC_CLOCK_125K, /**< 125 KHz from the high speed clock. */ ADC_CLOCK_62K5, /**< 62.5 KHz from the high speed clock. */ ADC_CLOCK_31K25, /**< 31.25 KHz from the high speed clock. */ ADC_CLOCK_32K, /**< 32 KHz or 32.768 KHz from the low speed clock. */ } qn908x_adc_clock_t; #ifdef DOXYGEN /** @brief Selected ADC oversample clock. * * Define to one of the qn908x_adc_clock_t values. */ #define QN908X_ADC_CLOCK /** @} */ #endif /* ifdef DOXYGEN */ /** * @brief ADC channel pair configuration * * The following are the possible combinations of + and - inputs to the ADC * sigma delta. Some of these combinations reference the "Vinn" signal which can * be independently selected, see @ref qn908x_adc_vinn_t for details. * * The first signal is connected to the positive side while the second one is * connected to the negative side. For example, ADC_CHANNEL_ADC0_ADC1 will read * a positive value if ADC0 voltage is higher than ADC1. * * The @ref ADC_CHANNEL_TEMP uses the internal temperature signal and * @ref ADC_CHANNEL_VCC4_VINN connects the + side to Vcc/4, which is useful to * measure the battery level when Vcc is directly connected to a battery. */ typedef enum { ADC_CHANNEL_ADC0_ADC1 = 0u << 9u, /**< Sample ADC0 / ADC1 */ ADC_CHANNEL_ADC2_ADC3 = 1u << 9u, /**< Sample ADC2 / ADC3 */ ADC_CHANNEL_ADC4_ADC5 = 2u << 9u, /**< Sample ADC4 / ADC5 */ ADC_CHANNEL_ADC6_ADC7 = 3u << 9u, /**< Sample ADC6 / ADC7 */ ADC_CHANNEL_ADC0_VINN = 4u << 9u, /**< Sample ADC0 / Vinn */ ADC_CHANNEL_ADC1_VINN = 5u << 9u, /**< Sample ADC1 / Vinn */ ADC_CHANNEL_ADC2_VINN = 6u << 9u, /**< Sample ADC2 / Vinn */ ADC_CHANNEL_ADC3_VINN = 7u << 9u, /**< Sample ADC3 / Vinn */ ADC_CHANNEL_ADC4_VINN = 8u << 9u, /**< Sample ADC4 / Vinn */ ADC_CHANNEL_ADC5_VINN = 9u << 9u, /**< Sample ADC5 / Vinn */ ADC_CHANNEL_ADC6_VINN = 10u << 9u, /**< Sample ADC6 / Vinn */ ADC_CHANNEL_ADC7_VINN = 11u << 9u, /**< Sample ADC7 / Vinn */ ADC_CHANNEL_TEMP = 13u << 9u, /**< Sample internal temperature */ ADC_CHANNEL_VCC4_VINN = 14u << 9u, /**< Sample 1/4 Vcc / Vinn */ ADC_CHANNEL_VINN_VINN = 15u << 9u, /**< Sample Vinn / Vinn */ ADC_CHANNEL_VINN_VSS = 20u << 9u, /**< Sample Vinn / Vss */ } qn908x_adc_channel_t; /** * @brief ADC Vref configuration * * This value affects the reference voltage used by the ADC as the full range. * It is also used in some cases to generate the Vinn signal are is only relevant for the channels that reference Vinn when it was * set by @ref qn908x_adc_vinn_t to use Vref. The actual values match the field * VREF_SEL in ADC CTRL register. */ typedef enum { ADC_VREF_1V2 = 0x0000u, /**< Vref := internal 1.2V. */ ADC_VREF_VREF = 0x4000u, /**< Vref := external ADC_VREFI pin */ ADC_VREF_VEXT = 0x8000u, /**< Vref := external ADC_VREFI with the driver */ ADC_VREF_VCC = 0xC000u, /**< Vref := Vcc */ } qn908x_adc_vref_t; /** * @brief ADC Vref x1.5 multiplier flag * * Note, this is the same value as ADC_CFG_VREF_GAIN_MASK. When enabled the * Vref voltage will be multiplied by 1.5x. */ #define ADC_VREF_GAIN_X15 (0x100u) /** * @brief ADC PGA Enabled flag * * Flag to enable the Programmable Gain Amplifier (PGA) with a gain of 1x. This * is only useful if the source signal doesn't have any driving capability since * the gain is set to 1x. The hardware supports other gain combinations but * those are not supported by the driver. * * Note: this value is defined as the inverse of ADC_CFG_PGA_BP_MASK which is * defined if the PGA is bypassed. */ #define ADC_PGA_ENABLE (0x08u) /** * @brief ADC Vinn configuration * * This value is only relevant for the channels that reference Vinn. The value * is the same as the PGA_VINN in ADC CFG register with a logic xor 0x30u to * make the default AVSS (analog Vss pad). */ typedef enum { ADC_VINN_VREF = 0x30u, /**< Use Vinn := Vref */ ADC_VINN_VREF_3_4 = 0x20u, /**< Use Vinn := 3/4 * Vref */ ADC_VINN_VREF_2 = 0x10u, /**< Use Vinn := 1/2 * Vref */ ADC_VINN_AVSS = 0x00u, /**< Use Vinn := Vss */ } qn908x_adc_vinn_t; /** * @brief ADC SD Gain configuration * * This multiplies the sampled value (difference between +/- signals) by the * given value. * * Note: these values logic xor 0x40 match the values for ADC_CFG_ADC_GAIN * field. This is selected so that omitting this flag in the config field * defaults to x1.0 gain but it can still be converted to the ADC_GAIN field * with a simple logic xor. */ typedef enum { ADC_GAIN_X05 = 0x40u, /**< Use gain := 0.5 */ ADC_GAIN_X1 = 0x00u, /**< Use gain := 1 */ ADC_GAIN_X15 = 0xC0u, /**< Use gain := 1.5 */ ADC_GAIN_X20 = 0x80u, /**< Use gain := 2 */ } qn908x_adc_gain_t; /** * @brief CPU specific ADC configuration * * ADC Channel, Vinn, Vref and gain configuration. * * This value should be set to the logic or between the following values: * * bit 3: the optional flag @ref ADC_PGA_ENABLE, * * bits 4-5: a @ref qn908x_adc_vinn_t value defining Vinn if needed, * * bits 6-7: a @ref qn908x_adc_gain_t optional gain value, * * bit 8: the optional flag @ref ADC_VREF_GAIN_X15, * * bits 9-13: the selected @ref qn908x_adc_channel_t, and * * bits 14-15: the @ref qn908x_adc_vref_t value defining Vref. * * The same channels with different settings can be configured as different ADC * lines in the board, just using different adc_conf_t entries. */ typedef uint16_t adc_conf_t; /** @} */ /** * @brief CPU specific timer Counter/Timers (CTIMER) configuration * @{ */ #define TIMER_CHANNELS (4) #define TIMER_MAX_VALUE (0xffffffff) /** @} */ /** * @brief I2C bus speed values in kbit/s. * * @note We support arbitrary speed values up to 400 kbit/s. * * @{ */ #define HAVE_I2C_SPEED_T typedef enum { I2C_SPEED_LOW = 10000u, /**< low speed mode: ~10 kbit/s */ I2C_SPEED_NORMAL = 100000u, /**< normal mode: ~100 kbit/s */ I2C_SPEED_FAST = 400000u, /**< fast mode: ~400 kbit/s */ I2C_SPEED_FAST_PLUS = 400000u, /**< not supported, capped at 400 kbit/s */ I2C_SPEED_HIGH = 400000u, /**< not supported, capped at 400 kbit/s */ } i2c_speed_t; /** @} */ /** * @brief I2C configuration options */ typedef struct { I2C_Type *dev; /**< hardware device */ gpio_t pin_scl; /**< SCL pin */ gpio_t pin_sda; /**< SDA pin */ uint32_t speed; /**< bus speed in bit/s */ } i2c_conf_t; /** * @name Use shared I2C functions * @{ */ #define PERIPH_I2C_NEED_READ_REG #define PERIPH_I2C_NEED_READ_REGS #define PERIPH_I2C_NEED_WRITE_REG #define PERIPH_I2C_NEED_WRITE_REGS /** @} */ /** * @name Define macros for sda and scl pins. * @{ */ #define i2c_pin_sda(dev) i2c_config[dev].pin_sda #define i2c_pin_scl(dev) i2c_config[dev].pin_scl /** @} */ /** * @brief UART module configuration options * * QN908x doesn't have any UART standalone blocks, but it has two FLEXCOMM * blocks that can be put in UART mode. The USART_Type* address is one of the * FLEXCOMM_Type* addresses as well. */ typedef struct { USART_Type *dev; /**< Pointer to module hardware registers */ gpio_t rx_pin; /**< RX pin, GPIO_UNDEF disables RX. */ gpio_t tx_pin; /**< TX pin, GPIO_UNDEF disables TX. */ } uart_conf_t; /** * @brief Invalid UART mode mask * * Signals that the mode is invalid or not supported by the CPU. */ #define UART_INVALID_MODE (0x80) /** * @brief Definition of possible parity modes * * These are defined to match the values of the USART->CFG : PARITYSEL bit * field. * @{ */ typedef enum { UART_PARITY_NONE = 0, /**< no parity */ UART_PARITY_EVEN = 2, /**< even parity */ UART_PARITY_ODD = 3, /**< odd parity */ UART_PARITY_MARK = 0x10 | UART_INVALID_MODE, /**< mark parity */ UART_PARITY_SPACE = 0x20 | UART_INVALID_MODE, /**< space parity */ } uart_parity_t; #define HAVE_UART_PARITY_T /** @} */ /** * @brief Definition of possible data bits lengths in a UART frame * * These are defined to match the values of the USART->CFG : DATALEN bit field. * @{ */ typedef enum { UART_DATA_BITS_5 = 0x10 | UART_INVALID_MODE, /**< 5 data bits */ UART_DATA_BITS_6 = 0x20 | UART_INVALID_MODE, /**< 6 data bits */ UART_DATA_BITS_7 = 0, /**< 7 data bits */ UART_DATA_BITS_8 = 1, /**< 8 data bits */ /* Note: There's a UART_DATA_BITS_9 possible in this hardware. */ } uart_data_bits_t; #define HAVE_UART_DATA_BITS_T /** @} */ /** * @brief Definition of possible stop bits lengths * * These are defined to match the values of the USART->CFG : STOPLEN bit field. * @{ */ typedef enum { UART_STOP_BITS_1 = 0, /**< 1 stop bit */ UART_STOP_BITS_2 = 1, /**< 2 stop bits */ } uart_stop_bits_t; #define HAVE_UART_STOP_BITS_T /** @} */ #ifdef __cplusplus } #endif #endif /* PERIPH_CPU_H */ /** @} */