Skip to content

Commit

Permalink
[rcc] Refactor Rcc::{en,dis}able<Peripheral>()
Browse files Browse the repository at this point in the history
Prevents silent failures if peripheral is not known via static_assert
  • Loading branch information
salkinium committed Mar 8, 2019
1 parent e9b09e9 commit 01092cf
Show file tree
Hide file tree
Showing 24 changed files with 104 additions and 76 deletions.
15 changes: 6 additions & 9 deletions src/modm/board/disco_f469ni/board_dsi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
// ----------------------------------------------------------------------------

#include "board.hpp"
#include <modm/platform/clock/rcc.hpp>

extern void
otm8009a_init(uint8_t);
Expand All @@ -18,15 +19,11 @@ otm8009a_init(uint8_t);
void
board_initialize_display(uint8_t ColorCoding)
{
if (RCC->APB2ENR & RCC_APB2ENR_LTDCEN) return;
// Enable clock to LTDC interface
RCC->APB2ENR |= RCC_APB2ENR_LTDCEN;
RCC->APB2RSTR |= RCC_APB2RSTR_LTDCRST;
RCC->APB2RSTR &= ~RCC_APB2RSTR_LTDCRST;
// Enable clock to DSI interface
RCC->APB2ENR |= RCC_APB2ENR_DSIEN;
RCC->APB2RSTR |= RCC_APB2RSTR_DSIRST;
RCC->APB2RSTR &= ~RCC_APB2RSTR_DSIRST;
using namespace modm::platform;
if (Rcc::isEnabled<Peripheral::Ltdc>()) return;
// Enable clock to LTDC, DSI interface
Rcc::enable<Peripheral::Ltdc>();
Rcc::enable<Peripheral::Dsihost>();

{
// Expanded `HAL_DSI_Init()`:
Expand Down
3 changes: 2 additions & 1 deletion src/modm/board/disco_f469ni/module.lb
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ def prepare(module, options):
":debug",
":driver:ft6x06",
":platform:clock",
":platform:rcc",
":platform:core",
":platform:gpio",
":platform:i2c:1",
Expand Down Expand Up @@ -82,4 +83,4 @@ linkerscript_extern_heap = """\
LONG (0x801f)
LONG (__heap_extern_start)
LONG (__heap_extern_end)
"""
"""
4 changes: 3 additions & 1 deletion src/modm/platform/adc/stm32/adc_impl.hpp.in
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
# error "Don't include this file directly, use 'adc_{{ id }}.hpp' instead!"
#endif

#include <modm/platform/clock/rcc.hpp>

template< class SystemClock, modm::frequency_t frequency, modm::percent_t tolerance >
void
modm::platform::Adc{{ id }}::initialize()
Expand Down Expand Up @@ -59,7 +61,7 @@ modm::platform::Adc{{ id }}::initialize()
Prescaler::Div2
)));

RCC->APB2ENR |= RCC_APB2ENR_ADC{{ id }}EN; // start ADC Clock
Rcc::enable<Peripheral::Adc{{id}}>();
ADC{{ id }}->CR2 |= ADC_CR2_ADON; // switch on ADC

setPrescaler(prescaler);
Expand Down
1 change: 1 addition & 0 deletions src/modm/platform/adc/stm32/module.lb
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ def prepare(module, options):
":architecture:register",
":cmsis:device",
":platform:gpio",
":platform:rcc",
":utils")

for instance in listify(device.get_driver("adc")["instance"]):
Expand Down
4 changes: 3 additions & 1 deletion src/modm/platform/adc/stm32f0/adc_impl.hpp.in
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,13 @@
# error "Don't include this file directly, use 'adc.hpp' instead!"
#endif

#include <modm/platform/clock/rcc.hpp>

uint16_t
modm::platform::Adc::initialize(const ClockMode clk,
const CalibrationMode cal)
{
RCC->APB2ENR |= RCC_APB2ENR_ADC1EN;
Rcc::enable<Peripheral::Adc>();

if (clk == ClockMode::Dedicated14MHzClock) {
RCC->CR2 |= RCC_CR2_HSI14ON;
Expand Down
3 changes: 2 additions & 1 deletion src/modm/platform/adc/stm32f0/module.lb
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ def prepare(module, options):
":architecture:delay",
":architecture:register",
":cmsis:device",
":platform:gpio")
":platform:gpio",
":platform:rcc")
return True

def build(env):
Expand Down
7 changes: 3 additions & 4 deletions src/modm/platform/adc/stm32f3/adc_impl.hpp.in
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#endif

#include <modm/architecture/interface/delay.hpp> // modm::delayMicroseconds
#include <modm/platform/clock/rcc.hpp>

void
modm::platform::Adc{{ id }}::initialize(const ClockMode clk,
Expand All @@ -31,7 +32,7 @@ modm::platform::Adc{{ id }}::initialize(const ClockMode clk,
%% if target["family"] in ["f3"]
RCC->AHBENR |= RCC_AHBENR_ADC{{ id_common }}EN;
%% elif target["family"] in ["l4"]
RCC->AHB2ENR |= RCC_AHB2ENR_ADCEN;
Rcc::enable<Peripheral::Adc1>();
%% endif

%% if clock_mux
Expand All @@ -47,8 +48,6 @@ modm::platform::Adc{{ id }}::initialize(const ClockMode clk,
// reset ADC
// FIXME: not a good idea since you can only reset both
// ADC1/ADC2 or ADC3/ADC4 at once ....
// RCC->APB2RSTR |= RCC_APB2RSTR_ADC{{ id }}RST;
// RCC->APB2RSTR &= ~RCC_APB2RSTR_ADC{{ id }}RST;

// set ADC "analog" clock source
if (clk != ClockMode::DoNotChange) {
Expand Down Expand Up @@ -90,7 +89,7 @@ modm::platform::Adc{{ id }}::disable(const bool blocking)
%% if target["family"] in ["f3"]
RCC->AHBENR &= ~RCC_AHBENR_ADC{{ id_common }}EN;
%% elif target["family"] in ["l4"]
RCC->AHB2ENR &= ~RCC_AHB2ENR_ADCEN;
Rcc::disable<Peripheral::Adc1>();
%% endif
}

Expand Down
3 changes: 2 additions & 1 deletion src/modm/platform/adc/stm32f3/module.lb
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,8 @@ def prepare(module, options):
":architecture:delay",
":architecture:register",
":cmsis:device",
":platform:gpio")
":platform:gpio",
":platform:rcc")

for instance in listify(device.get_driver("adc")["instance"]):
module.add_submodule(Instance(int(instance)))
Expand Down
18 changes: 7 additions & 11 deletions src/modm/platform/can/stm32/can.cpp.in
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include <modm/architecture/interface/assert.hpp>
#include <modm/architecture/interface/interrupt.hpp>
#include <modm/architecture/interface/delay.hpp>
#include <modm/platform/clock/rcc.hpp>

%% if id == ""
#include "can.hpp"
Expand Down Expand Up @@ -49,26 +50,21 @@ modm::platform::Can{{ id }}::initializeWithPrescaler(
uint32_t interruptPriority, Mode startupMode, bool overwriteOnOverrun)
{
%% macro enable_reset(instance)
// enable clock
RCC->APB1ENR{{ apb_post }} |= RCC_APB1ENR{{ apb_post }}_{{ instance }}EN;

// reset controller
RCC->APB1RSTR{{ apb_post }} |= RCC_APB1RSTR{{ apb_post }}_{{ instance }}RST;
RCC->APB1RSTR{{ apb_post }} &= ~RCC_APB1RSTR{{ apb_post }}_{{ instance }}RST;
Rcc::enable<Peripheral::Can{{ instance }}>();
%% endmacro
%% if type == "Slave"
// enable and reset master if disabled
if (!(RCC->APB1ENR{{ apb_post }} & RCC_APB1ENR{{ apb_post }}_{{ reg_other }}EN)) {
{{ enable_reset(reg_other) | lbuild.indent(4) }}
if (not Rcc::isEnabled<Peripheral::Can{{ other_instance }}>()) {
{{ enable_reset(other_instance) | lbuild.indent(4) }}
}
%% endif
%% if type == "Master"
// skip enable and reset if device has already been enabled by slave
if (!(RCC->APB1ENR{{ apb_post }} & RCC_APB1ENR{{ apb_post }}_{{ reg }}EN)) {
{{ enable_reset(reg) | lbuild.indent(4) }}
if (not Rcc::isEnabled<Peripheral::Can{{ own_instance }}>()) {
{{ enable_reset(own_instance) | lbuild.indent(4) }}
}
%% else
{{ enable_reset(reg) }}
{{ enable_reset(id) }}
%% endif

// CAN Master Reset
Expand Down
5 changes: 3 additions & 2 deletions src/modm/platform/can/stm32/module.lb
Original file line number Diff line number Diff line change
Expand Up @@ -87,9 +87,9 @@ def get_substitutions(instance, device, env):

subs = {
"id": "" if instance == 0 else str(instance),
"apb_post": "1" if target["family"] in ["l4"] else "",
"own_instance": cm[instance].register,
"other_instance": cm[other].register if other in cm else None,
"reg": "CAN" + cm[instance].register,
"reg_other": ("CAN" + cm[other].register) if other in cm else None,
"type": cm[instance].type.name if not is_single else CanType.Single.name
}

Expand Down Expand Up @@ -145,6 +145,7 @@ def prepare(module, options):
":debug",
":platform:can.common",
":platform:gpio",
":platform:rcc",
":utils")

driver = device.get_driver("can")
Expand Down
36 changes: 29 additions & 7 deletions src/modm/platform/clock/stm32/module.lb
Original file line number Diff line number Diff line change
Expand Up @@ -74,22 +74,44 @@ def build(env):
env.template("rcc.cpp.in")
env.template("rcc.hpp.in")

all_peripherals = []
all_peripherals = set()
all_drivers = [d for d in device._properties["driver"] if d["name"] not in ["gpio", "core"]]
translate = lambda s: "".join(p.capitalize() for p in s.split("_"))
for d in all_drivers:
dname = translate(d["name"])
if "instance" in d:
all_peripherals.extend([dname + translate(i) for i in d["instance"]])
all_peripherals.update(dname + translate(i) for i in d["instance"])
else:
all_peripherals.append(dname)
all_peripherals = sorted(list(set(all_peripherals)))
all_peripherals.add(dname)
all_peripherals = sorted(list(all_peripherals))

rcc_map = env.query(":cmsis:device:rcc-map")
rcc_map = {per:v for per,v in rcc_map.items() if per.capitalize() in all_peripherals}
rcc_enable = {}
rcc_reset = {}

for per, mode in rcc_map.items():
nper = per
# Fix CAN vs CAN1
if "Can" in all_peripherals and per == "CAN1":
per = "CAN"
nper = "CAN1"
# Fix ADC vs ADC1
if "Adc1" in all_peripherals and per == "ADC":
per = "ADC1"
nper = "ADC"
# Fix DSIHOST vs DSI
if "Dsihost" in all_peripherals and per == "DSI":
per = "Dsihost"
nper = "DSI"
if per.capitalize() not in all_peripherals:
continue
if "EN" in mode:
rcc_enable[per.capitalize()] = (nper, mode["EN"])
if "RST" in mode:
rcc_reset[nper] = mode["RST"]

env.substitutions.update({
"peripherals": rcc_map.keys(),
"rcc_map": rcc_map,
"rcc_enable": rcc_enable,
"rcc_reset": rcc_reset,
})
env.template("rcc_impl.hpp.in")
7 changes: 3 additions & 4 deletions src/modm/platform/clock/stm32/rcc.hpp.in
Original file line number Diff line number Diff line change
Expand Up @@ -441,20 +441,19 @@ public:
enable();

template< Peripheral peripheral >
static void
disable();
static bool
isEnabled();

template< Peripheral peripheral >
static void
reset();
disable();

private:
struct flash_latency
{
uint32_t latency;
uint32_t max_frequency;
};

static constexpr flash_latency
computeFlashLatency(uint32_t Core_Hz, uint16_t Core_mV);
};
Expand Down
60 changes: 39 additions & 21 deletions src/modm/platform/clock/stm32/rcc_impl.hpp.in
Original file line number Diff line number Diff line change
Expand Up @@ -91,46 +91,64 @@ Rcc::updateCoreFrequency()
modm::clock::ns_per_loop = ::round({{loops}}000.f / (Core_Hz / 1'000'000));
}

constexpr bool
rcc_check_enable(Peripheral peripheral)
{
switch(peripheral) {
%% for peripheral in rcc_enable | sort
case Peripheral::{{ peripheral }}:
%% endfor
return true;
default:
return false;
}
}

template< Peripheral peripheral >
inline void
void
Rcc::enable()
{
static_assert(rcc_check_enable(peripheral),
"Rcc::enable() doesn't know this peripheral!");

__DSB();
%% for peripheral in peripherals | sort if "EN" in rcc_map[peripheral]
%% set register = rcc_map[peripheral]["EN"]
if constexpr (peripheral == Peripheral::{{ peripheral | capitalize }})
{ RCC->{{register}} |= RCC_{{register}}_{{peripheral}}EN; }
%% for peripheral, (st_per, bus) in rcc_enable.items() | sort
if constexpr (peripheral == Peripheral::{{ peripheral }})
if (not Rcc::isEnabled<peripheral>()) {
RCC->{{bus}} |= RCC_{{bus}}_{{st_per}}EN;{% if st_per in rcc_reset %} __DSB();
RCC->{{rcc_reset[st_per]}} |= RCC_{{rcc_reset[st_per]}}_{{st_per}}RST; __DSB();
RCC->{{rcc_reset[st_per]}} &= ~RCC_{{rcc_reset[st_per]}}_{{st_per}}RST;{% endif %}
}
%% endfor
__DSB();
}

template< Peripheral peripheral >
inline void
void
Rcc::disable()
{
static_assert(rcc_check_enable(peripheral),
"Rcc::disable() doesn't know this peripheral!");

__DSB();
%% for peripheral in peripherals | sort if "EN" in rcc_map[peripheral]
%% set register = rcc_map[peripheral]["EN"]
if constexpr (peripheral == Peripheral::{{ peripheral | capitalize }})
{ RCC->{{register}} &= ~RCC_{{register}}_{{peripheral}}EN; }
%% for peripheral, (st_per, bus) in rcc_enable.items() | sort
if constexpr (peripheral == Peripheral::{{ peripheral }})
RCC->{{bus}} &= ~RCC_{{bus}}_{{st_per}}EN;
%% endfor
__DSB();
}

template< Peripheral peripheral >
inline void
Rcc::reset()
bool
Rcc::isEnabled()
{
__DSB();
%% for peripheral in peripherals | sort if "RST" in rcc_map[peripheral]
%% set register = rcc_map[peripheral]["RST"]
if constexpr (peripheral == Peripheral::{{ peripheral | capitalize }})
{
RCC->{{register}} |= RCC_{{register}}_{{peripheral}}RST; __DSB();
RCC->{{register}} &= ~RCC_{{register}}_{{peripheral}}RST;
}
static_assert(rcc_check_enable(peripheral),
"Rcc::isEnabled() doesn't know this peripheral!");

%% for peripheral, (st_per, bus) in rcc_enable.items() | sort
if constexpr (peripheral == Peripheral::{{ peripheral }})
return RCC->{{bus}} & RCC_{{bus}}_{{st_per}}EN;
%% endfor
__DSB();
}

} // namespace modm::platform
Expand Down
1 change: 0 additions & 1 deletion src/modm/platform/dma/stm32/dma_impl.hpp.in
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ void
modm::platform::Dma{{ id }}::enable()
{
Rcc::enable<Peripheral::Dma{{id}}>();
Rcc::reset<Peripheral::Dma{{id}}>();
}

void
Expand Down
2 changes: 0 additions & 2 deletions src/modm/platform/fsmc/stm32/fsmc.cpp.in
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,6 @@
void
modm::platform::Fsmc::initialize()
{
//RCC->AHB3RSTR |= RCC_AHB3RSTR_FSMCRST;

enable();
}

Expand Down
1 change: 0 additions & 1 deletion src/modm/platform/fsmc/stm32/fsmc.hpp.in
Original file line number Diff line number Diff line change
Expand Up @@ -300,7 +300,6 @@ namespace modm
enable()
{
Rcc::enable<Peripheral::{{ FMC | capitalize }}>();
Rcc::reset<Peripheral::{{ FMC | capitalize }}>();
}

static inline void
Expand Down
1 change: 0 additions & 1 deletion src/modm/platform/i2c/stm32-extended/i2c_master.cpp.in
Original file line number Diff line number Diff line change
Expand Up @@ -497,7 +497,6 @@ void
modm::platform::I2cMaster{{ id }}::initializeWithPrescaler(uint32_t timingRegisterValue)
{
Rcc::enable<Peripheral::I2c{{id}}>();
Rcc::reset<Peripheral::I2c{{id}}>();

// Disable the I2C peripheral which causes a software reset
I2C{{ id }}->CR1 &= ~I2C_CR1_PE;
Expand Down
Loading

0 comments on commit 01092cf

Please sign in to comment.