diff --git a/cpu/cc26x2_cc13x2/aux.c b/cpu/cc26x2_cc13x2/aux.c index be69f8c77c..9007e81dfe 100644 --- a/cpu/cc26x2_cc13x2/aux.c +++ b/cpu/cc26x2_cc13x2/aux.c @@ -40,6 +40,7 @@ static const uint8_t _opmode_to_order[4] = { OPMODE_PDA_ORDER, OPMODE_PDLP_ORDER }; + /** Array to map an order to an operation mode, used to get the next operation * mode. This is because we need to change the operation in ordered steps */ static const uint8_t _order_to_opmode[4] = { diff --git a/cpu/cc26x2_cc13x2/include/cc26x2_cc13x2_prcm.h b/cpu/cc26x2_cc13x2/include/cc26x2_cc13x2_prcm.h index ff36c05545..9c17ed4e35 100644 --- a/cpu/cc26x2_cc13x2/include/cc26x2_cc13x2_prcm.h +++ b/cpu/cc26x2_cc13x2/include/cc26x2_cc13x2_prcm.h @@ -75,8 +75,12 @@ typedef struct { * @brief DDI_0_OSC register values * @{ */ -#define DDI_0_OSC_CTL0_SCLK_HF_SRC_SEL 0x00000001 -#define DDI_0_OSC_CTL0_SCLK_LF_SRC_SEL 0x0000000C +#define DDI_0_OSC_CTL0_SCLK_HF_SRC_SEL_m 0x00000001 +#define DDI_0_OSC_CTL0_SCLK_HF_SRC_SEL_s 0 +#define DDI_0_OSC_CTL0_SCLK_HF_SRC_SEL_XOSC 0x00000001 +#define DDI_0_OSC_CTL0_SCLK_HF_SRC_SEL_RCOSC 0x00000000 +#define DDI_0_OSC_CTL0_SCLK_LF_SRC_SEL_m 0x0000000C +#define DDI_0_OSC_CTL0_SCLK_LF_SRC_SEL_s 2 #define DDI_0_OSC_CTL0_ACLK_TDC_SRC_SEL 0x00000180 #define DDI_0_OSC_CTL0_CLK_LOSS_EN 0x00000200 #define DDI_0_OSC_CTL0_XOSC_LF_DIG_BYPASS 0x00000400 @@ -89,6 +93,11 @@ typedef struct { #define DDI_0_OSC_CTL0_BYPASS_RCOSC_LF_CLK_QUAL 0x10000000 #define DDI_0_OSC_CTL0_BYPASS_XOSC_LF_CLK_QUAL 0x20000000 #define DDI_0_OSC_CTL0_XTAL_IS_24M 0x80000000 +#define DDI_0_OSC_STAT0_PENDINGSCLKHFSWITCHING 0x00000001 +#define DDI_0_OSC_STAT0_SCLK_HF_SRC_m 0x10000000 +#define DDI_0_OSC_STAT0_SCLK_HF_SRC_s 28 +#define DDI_0_OSC_STAT0_SCLK_LF_SRC_m 0x60000000 +#define DDI_0_OSC_STAT0_SCLK_LF_SRC_s 29 /** @} */ /** @@ -120,6 +129,28 @@ typedef struct { */ #define DDI_0_OSC_M16 ((ddi0_osc_regs_m16_t *) (DDI0_OSC_BASE_M16)) +/** + * @brief SCLK_HF oscillators. + * @{ + */ +#define OSC_RCOSC_HF 0x00000000 /**< Internal HF RC oscillator */ +#define OSC_XOSC_HF 0x00000001 /**< External HF crystal oscillator */ +/** @} */ + +/** + * @brief DDI_0_OSC functions + * @{ + */ +/** + * @brief Switch the high frequency clock. + * + * @note This function will not return until the clock source has been switched. + * + * @param[in] osc The oscillator to use. + */ +void osc_hf_source_switch(uint32_t osc); +/** @} */ + /** * @brief AON_PMCTL registers */ diff --git a/cpu/cc26x2_cc13x2/osc.c b/cpu/cc26x2_cc13x2/osc.c new file mode 100644 index 0000000000..dd9378b748 --- /dev/null +++ b/cpu/cc26x2_cc13x2/osc.c @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2020 Locha Inc + * + * 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_cc26x2_cc13x2 + * @{ + * + * @file + * @brief CC26x2/CC13x2 Oscillator functions + * + * @author Jean Pierre Dudey + * @} + */ + +#include +#include "cpu.h" + +static inline bool _hf_source_ready(void) +{ + if (DDI_0_OSC->STAT0 & DDI_0_OSC_STAT0_PENDINGSCLKHFSWITCHING) { + return true; + } + return false; +} + +static inline uint32_t _hf_source_get(void) +{ + return (DDI_0_OSC->STAT0 & DDI_0_OSC_STAT0_SCLK_HF_SRC_m) >> + DDI_0_OSC_STAT0_SCLK_HF_SRC_s; +} + +static inline void _hf_source_set(uint32_t osc) +{ + uint32_t mask = DDI_0_OSC_CTL0_SCLK_HF_SRC_SEL_m; + uint32_t ctl = osc << DDI_0_OSC_CTL0_SCLK_HF_SRC_SEL_s; + + /* Use a 16-bit masked write, target bits are on the lower 16-bit + * half */ + DDI_0_OSC_M16->CTL0.LOW = (mask << 16) | ctl; +} + +void osc_hf_source_switch(uint32_t osc) +{ + if (_hf_source_get() == osc) { + return; + } + + /* Request oscillator change */ + _hf_source_set(osc); + + /* Wait for the oscillator to be ready */ + while (_hf_source_ready()) {} + + /* If target clock source is RCOSC, change clock source for DCDC to RCOSC */ + if (osc == OSC_RCOSC_HF) { + /* Force DCDC to use RCOSC before switching SCLK_HF to RCOSC */ + uint32_t mask = DDI_0_OSC_CTL0_CLK_DCDC_SRC_SEL_m; + uint32_t data = DDI_0_OSC_CTL0_CLK_DCDC_SRC_SEL_m >> 16; + DDI_0_OSC_M16->CTL0.HIGH = mask | data; + + /* Dummy read to ensure that the write has propagated */ + DDI_0_OSC->CTL0; + } + + /* Switch the HF clock source */ + rom_hapi_hf_source_safe_switch(); + + /* If target clock source is XOSC, change clock source for DCDC to "auto" */ + if (osc == OSC_XOSC_HF) { + /* Set DCDC clock source back to "auto" after SCLK_HF was switched to + * XOSC */ + uint32_t mask = DDI_0_OSC_CTL0_CLK_DCDC_SRC_SEL_m; + uint32_t data = 0; + + DDI_0_OSC_M16->CTL0.HIGH = mask | data; + } +} diff --git a/cpu/cc26xx_cc13xx/include/cc26xx_cc13xx.h b/cpu/cc26xx_cc13xx/include/cc26xx_cc13xx.h index 4214adf4cb..f58b1d35ed 100644 --- a/cpu/cc26xx_cc13xx/include/cc26xx_cc13xx.h +++ b/cpu/cc26xx_cc13xx/include/cc26xx_cc13xx.h @@ -144,8 +144,8 @@ typedef enum IRQn #define FLASH_BASE 0x00000000 /**< FLASH base address */ #define PERIPH_BASE 0x40000000 /**< Peripheral base address */ #define PERIPH_BASE_NONBUF 0x60000000 /**< Peripheral base address (nonbuf) */ +#define ROM_HARD_API_BASE 0x10000048 /**< ROM Hard-API base address */ #define ROM_API_TABLE ((uint32_t *) 0x10000180) /**< ROM API table */ - /*@}*/ /** diff --git a/cpu/cc26xx_cc13xx/include/cc26xx_cc13xx_hard_api.h b/cpu/cc26xx_cc13xx/include/cc26xx_cc13xx_hard_api.h new file mode 100644 index 0000000000..b27868781f --- /dev/null +++ b/cpu/cc26xx_cc13xx/include/cc26xx_cc13xx_hard_api.h @@ -0,0 +1,97 @@ +/* + * Copyright (C) 2020 Locha Inc + * + * 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_cc26xx_cc13xx_definitions + * @{ + * + * @file + * @brief CC26xx/CC13xx ROM Hard-API + * + * @author Jean Pierre Dudey + */ + +#ifndef CC26XX_CC13XX_HARD_API_H +#define CC26XX_CC13XX_HARD_API_H + +#include "cc26xx_cc13xx.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief ROM Hard-API + */ +typedef struct { + /** CRC-32 */ + uint32_t (* crc32)(uint8_t *data, uint32_t bytecount, uint32_t repeatcount); + uint32_t (* get_fl_size)(void); /**< Get flash size */ + uint32_t (* get_chip_id)(void); /**< Get chip ID */ + uint32_t (* __reserved0)(uint32_t); /**< Reserved */ + uint32_t (* __reserved1)(void); /**< Reserved */ + uint32_t (* __reserved2)(uint8_t *, uint32_t, uint32_t); /**< Reserved */ + void (* resetdev)(void); /**< Reset device */ + uint32_t (* fletcher32)(uint16_t *data, uint16_t wordcount, + uint16_t repeatcount); /**< Fletcher-32 */ + /** Min. value */ + uint32_t (* min_val)(uint32_t *buffer, uint32_t datacount); + /** Max. value */ + uint32_t (* max_val)(uint32_t *databuffer, uint32_t datacount); + /** Mean. value */ + uint32_t (* mean_val)(uint32_t *databuffer, uint32_t datacount); + /** Standard deviation value */ + uint32_t (* stdd_val)(uint32_t *databuffer, uint32_t datacount); + void (* hf_source_safe_switch)(void); /**< HF source safe-switch */ + void (* __reserved3)(uint32_t); /**< Reserved */ + void (* __reserved4)(uint32_t); /**< Reserved */ + void (* compa_in)(uint8_t signal); /**< Select CompA input */ + void (* compa_ref)(uint8_t signal); /**< Select CompA reference */ + void (* adc_compb_in)(uint8_t signal); /**< Select ADC CompB input */ +#ifdef CPU_VARIANT_X2 + void (* dac_vref)(uint8_t signal); /**< Select DAC vref */ +#else + void (* compb_ref)(uint8_t signal); /**< Select CompB reference */ +#endif +} hard_api_t; + +/** + * @brief Hard-API function table + */ +#define HARD_API ((hard_api_t *) ROM_HARD_API_BASE) + +/** + * @brief Hard-API functions + * @{ + */ +#define rom_hapi_crc32(a, b, c) (HARD_API->crc32((a), (b), (c))) +#define rom_hapi_get_flashsize() (HARD_API->get_fl_size()) +#define rom_hapi_get_chipid() (HARD_API->get_chip_id()) +#define rom_hapi_reset_device() (HARD_API->resetdev()) +#define rom_hapi_fletcher32(a, b, c) (HARD_API->fletcher32((a), (b), (c))) +#define rom_hapi_min_value(a, b) (HARD_API->min_val((a), (b))) +#define rom_hapi_max_value(a, b) (HARD_API->max_val((a), (b))) +#define rom_hapi_mean_value(a, b) (HARD_API->mean_val((a), (b))) +#define rom_hapi_std_deviation_value(a, b) (HARD_API->stdd_val((a), (b))) +#define rom_hapi_hf_source_safe_switch() (HARD_API->hf_source_safe_switch()) +#define rom_hapi_select_compa_input(a) (HARD_API->compa_in((a))) +#define rom_hapi_select_compa_ref(a) (HARD_API->compa_ref((a))) +#define rom_hapi_select_adc_compb_input(a) (HARD_API->adc_compb_in((a))) +#ifdef CPU_VARIANT_X2 +#define rom_hapi_select_dac_vref(a) (HARD_API->dac_vref((a))) +#else +#define rom_hapi_select_compb_ref(a) (HARD_API->compb_vref((a))) +#endif +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* CC26XX_CC13XX_HARD_API_H */ +/** @} */ diff --git a/cpu/cc26xx_cc13xx/include/cpu_conf_cc26xx_cc13xx.h b/cpu/cc26xx_cc13xx/include/cpu_conf_cc26xx_cc13xx.h index 1c2a730b66..60e1c0d84e 100644 --- a/cpu/cc26xx_cc13xx/include/cpu_conf_cc26xx_cc13xx.h +++ b/cpu/cc26xx_cc13xx/include/cpu_conf_cc26xx_cc13xx.h @@ -28,6 +28,7 @@ #include "cc26xx_cc13xx_ccfg.h" #include "cc26xx_cc13xx_gpio.h" #include "cc26xx_cc13xx_gpt.h" +#include "cc26xx_cc13xx_hard_api.h" #include "cc26xx_cc13xx_i2c.h" #include "cc26xx_cc13xx_ioc.h" #include "cc26xx_cc13xx_rfc.h"