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));
}
}