BSCIF
module reference#include <bscif.h>Makefile :
bscif
is already included by default
The BSCIF (Backup System Control Interface) manages the low-power clocks, the internal voltage regulator and brown-out detectors, and a few general-purpose backup registers.
Core::init()
.32768
.32768
.1000000
.n
must be between 0 and 3.storeBackupData
. n
must be between 0 and 3.The configuration of the voltage regulator and brown-out detectors is not implemented. For applications that require more advanced management and monitoring of the power source, look at the §12.6.3 Brown-Out Detector (BOD) Operation and §12.6.4 Voltage Regulator (VREG) sections in the datasheet for more details about these features.
#ifndef _BSCIF_H_ #define _BSCIF_H_ #include <stdint.h> // Backup System Control Interface // This module manages low-power clocks, the voltage regulator and // some general-purpose backup data registers namespace BSCIF { // Peripheral memory space base address const uint32_t BSCIF_BASE = 0x400F0400; // Registers addresses const uint32_t OFFSET_IER = 0x0000; // Interrupt Enable Register const uint32_t OFFSET_IDR = 0x0004; // Interrupt Disable Register const uint32_t OFFSET_IMR = 0x0008; // Interrupt Mask Register const uint32_t OFFSET_ISR = 0x000C; // Interrupt Status Register const uint32_t OFFSET_ICR = 0x0010; // Interrupt Clear Register const uint32_t OFFSET_PCLKSR = 0x0014; // Power and Clocks Status Register const uint32_t OFFSET_UNLOCK = 0x0018; // Unlock Register const uint32_t OFFSET_CSCR = 0x001C; // Chip Specific Configuration Register const uint32_t OFFSET_OSCCTRL32 = 0x0020; // Oscillator 32 Control Register const uint32_t OFFSET_RC32KCR = 0x0024; // 32kHz RC Oscillator Control Register const uint32_t OFFSET_RC32KTUNE = 0x0028; // 32kHz RC Oscillator Tuning Register const uint32_t OFFSET_BOD33CTRL = 0x002C; // BOD33 Control Register const uint32_t OFFSET_BOD33LEVEL = 0x0030; // BOD33 Level Register const uint32_t OFFSET_BOD33SAMPLING = 0x0034; // BOD33 Sampling Control Register const uint32_t OFFSET_BOD18CTRL = 0x0038; // BOD18 Control Register const uint32_t OFFSET_BOD18LEVEL = 0x003C; // BOD18 Level Register const uint32_t OFFSET_BOD18SAMPLING = 0x0040; // BOD18 Sampling Control Register const uint32_t OFFSET_VREGCR = 0x0044; // Voltage Regulator Configuration Register const uint32_t OFFSET_RC1MCR = 0x0048; // 1MHz RC Clock Configuration Register const uint32_t OFFSET_BGCTRL = 0x0060; // Bandgap Control Register const uint32_t OFFSET_BGSR = 0x0064; // Bandgap Status Register const uint32_t OFFSET_BR = 0x0078; // Backup register // Subregisters const uint32_t PCLKSR_OSC32RDY = 0; const uint32_t PCLKSR_RC32KRDY = 1; const uint32_t PCLKSR_RC32KLOCK = 2; const uint32_t PCLKSR_RC32KREFE = 3; const uint32_t PCLKSR_RC32SAT = 4; const uint32_t PCLKSR_BOD33DET = 5; const uint32_t PCLKSR_BOD18DET = 6; const uint32_t PCLKSR_BOD33SYNRDY = 7; const uint32_t PCLKSR_BOD18SYNRDY = 8; const uint32_t PCLKSR_SSWRDY = 9; const uint32_t PCLKSR_VREGOK = 10; const uint32_t PCLKSR_RC1MRDY = 11; const uint32_t PCLKSR_LPBGRDY = 12; const uint32_t OSCCTRL32_OSC32EN = 0; const uint32_t OSCCTRL32_EN32K = 2; const uint32_t OSCCTRL32_EN1K = 3; const uint32_t OSCCTRL32_MODE = 8; const uint32_t OSCCTRL32_SELCURR = 12; const uint32_t OSCCTRL32_STARTUP = 16; const uint32_t RC32KCR_EN = 0; const uint32_t RC32KCR_TCEN = 1; const uint32_t RC32KCR_EN32K = 2; const uint32_t RC32KCR_EN1K = 3; const uint32_t RC32KCR_MODE = 4; const uint32_t RC32KCR_REF = 5; const uint32_t RC32KCR_FCD = 7; const uint32_t RC1MCR_CLKOEN = 0; // Constants const uint32_t UNLOCK_KEY = 0xAA << 24; // Module API void enableOSC32K(); unsigned long getOSC32KFrequency(); void enableRC32K(); unsigned long getRC32KFrequency(); void enableRC1M(); unsigned long getRC1MFrequency(); void storeBackupData(int register, uint32_t data); uint32_t readBackupData(int register); } #endif
#include "bscif.h" #include "bpm.h" namespace BSCIF { unsigned long _osc32kFrequency = 0; unsigned long _rc32kFrequency = 0; unsigned long _rc1mFrequency = 0; void enableOSC32K() { // Save the frequency for future use _osc32kFrequency = 32768; // Unlock the OSCCTRL32 register, which is locked by default as a safety mesure (*(volatile uint32_t*)(BSCIF_BASE + OFFSET_UNLOCK)) = UNLOCK_KEY // KEY : Magic word (see datasheet) | OFFSET_OSCCTRL32; // ADDR : unlock OSCCTRL32 // Configure OSC32 (*(volatile uint32_t*)(BSCIF_BASE + OFFSET_OSCCTRL32)) = 1 << OSCCTRL32_EN32K // EN32K : enable 32kHz output | 1 << OSCCTRL32_EN1K // EN1K : enable 1kHz output | 3 << OSCCTRL32_MODE // MODE : crystal | 8 << OSCCTRL32_SELCURR // SELCURR : current driven into the crystal | 0 << OSCCTRL32_STARTUP; // STARTUP : oscillator startup time // Enable OSC32 (*(volatile uint32_t*)(BSCIF_BASE + OFFSET_OSCCTRL32)) |= 1 << OSCCTRL32_OSC32EN; // OSC32EN : enable crystal // Wait for OSC32K to be ready while (!((*(volatile uint32_t*)(BSCIF_BASE + OFFSET_PCLKSR)) & (1 << PCLKSR_OSC32RDY))); // Select OSC32K as the 32KHz clock source BPM::set32KHzClockSource(BPM::CLK32KSource::OSC32K); } unsigned long getOSC32KFrequency() { return _osc32kFrequency; } void enableRC32K() { // Save the frequency for future use _rc32kFrequency = 32768; // Unlock the RC32KCR register, which is locked by default as a safety mesure (*(volatile uint32_t*)(BSCIF_BASE + OFFSET_UNLOCK)) = UNLOCK_KEY // KEY : Magic word (see datasheet) | OFFSET_RC32KCR; // ADDR : unlock RC32KCR // Configure RC32K (*(volatile uint32_t*)(BSCIF_BASE + OFFSET_RC32KCR)) = 1 << RC32KCR_TCEN // TCEN : enable temperature compensation | 1 << RC32KCR_EN32K // EN32K : enable 32kHz output | 1 << RC32KCR_EN1K // EN1K : enable 1kHz output | 1 << RC32KCR_MODE // MODE : closed loop mode | 0 << RC32KCR_REF; // REF : closed loop mode reference : OSC32K // Enable RC32K (*(volatile uint32_t*)(BSCIF_BASE + OFFSET_RC32KCR)) |= 1 << RC32KCR_EN; // EN : enable generic clock source // Wait for RC32K to be ready while (!((*(volatile uint32_t*)(BSCIF_BASE + OFFSET_PCLKSR)) & ((1 << PCLKSR_RC32KRDY) | (1 << PCLKSR_RC32KLOCK)))); // Select RC32K as the 32KHz clock source BPM::set32KHzClockSource(BPM::CLK32KSource::RC32K); } unsigned long getRC32KFrequency() { return _rc32kFrequency; } void enableRC1M() { // Save the frequency for future use _rc1mFrequency = 1000000; // Unlock the RC1MCR register, which is locked by default as a safety mesure (*(volatile uint32_t*)(BSCIF_BASE + OFFSET_UNLOCK)) = UNLOCK_KEY // KEY : Magic word (see datasheet) | OFFSET_RC1MCR; // ADDR : unlock RC1MCR // Configure RC1M (*(volatile uint32_t*)(BSCIF_BASE + OFFSET_RC1MCR)) = 1 << RC1MCR_CLKOEN; // CLKOEN : enable oscillator // Wait for RC1M to be ready while (!((*(volatile uint32_t*)(BSCIF_BASE + OFFSET_PCLKSR)) & (1 << PCLKSR_RC1MRDY))); } unsigned long getRC1MFrequency() { return _rc1mFrequency; } // Store data in one of the four 32-bit backup registers // This data is kept even in BACKUP low-power mode, when all other // registers not in the Backup domain are lost void storeBackupData(int n, uint32_t data) { // Register offset if (n < 0 || n > 3) { return; } const uint32_t offset = OFFSET_BR + n * 4; // Unlock the BRn register, which is locked by default as a safety mesure (*(volatile uint32_t*)(BSCIF_BASE + OFFSET_UNLOCK)) = UNLOCK_KEY // KEY : Magic word (see datasheet) | offset; // ADDR : unlock BRn // Store data (*(volatile uint32_t*)(BSCIF_BASE + offset)) = data; } // Read data from one of the four 32-bit backup registers uint32_t readBackupData(int n) { // Register offset if (n < 0 || n > 3) { return 0; } const uint32_t offset = OFFSET_BR + n * 4; return (*(volatile uint32_t*)(BSCIF_BASE + offset)); } }