-
Notifications
You must be signed in to change notification settings - Fork 134
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[extint] Add external interrupt support for SAM
- Loading branch information
Showing
9 changed files
with
296 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
/* | ||
* Copyright (c) 2020, Erik Henriksson | ||
* | ||
* This file is part of the modm project. | ||
* | ||
* This Source Code Form is subject to the terms of the Mozilla Public | ||
* License, v. 2.0. If a copy of the MPL was not distributed with this | ||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. | ||
*/ | ||
|
||
#include <modm/board.hpp> | ||
|
||
using namespace Board; | ||
using namespace std::chrono_literals; | ||
|
||
static volatile bool blink = true; | ||
|
||
void | ||
isr() { | ||
blink = !blink; | ||
// Kids, please don't do serial logging in ISRs... | ||
MODM_LOG_DEBUG << "blink: " << (blink ? "true" : "false") << modm::endl; | ||
} | ||
|
||
int | ||
main() | ||
{ | ||
Board::initialize(); | ||
ExternalInterrupt::initialize(); | ||
ExtInt<3>::initialize(&isr); | ||
ExtInt<3>::connectPin<D12>(); | ||
while (1) { | ||
if (blink) { | ||
Led::toggle(); | ||
} else { | ||
Led::set(0); | ||
} | ||
modm::delay(100ms); | ||
} | ||
return 0; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
<library> | ||
<extends>modm:feather-m0</extends> | ||
<options> | ||
<option name="modm:build:build.path">../../../build/samd/interrupt</option> | ||
</options> | ||
<modules> | ||
<module>modm:build:scons</module> | ||
<module>modm:platform:extint</module> | ||
</modules> | ||
</library> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
/* | ||
* Copyright (c) 2020, Erik Henriksson | ||
* | ||
* This file is part of the modm project. | ||
* | ||
* This Source Code Form is subject to the terms of the Mozilla Public | ||
* License, v. 2.0. If a copy of the MPL was not distributed with this | ||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. | ||
*/ | ||
// ---------------------------------------------------------------------------- | ||
|
||
#include "extint.hpp" | ||
|
||
void isr(); | ||
|
||
namespace modm | ||
{ | ||
namespace platform | ||
{ | ||
|
||
void | ||
ExternalInterrupt::initialize(ClockGenerator clockGen, int priority) { | ||
NVIC_DisableIRQ(EIC_IRQn); | ||
NVIC_ClearPendingIRQ(EIC_IRQn); | ||
NVIC_SetPriority(EIC_IRQn, priority); | ||
NVIC_EnableIRQ(EIC_IRQn); | ||
|
||
GenericClockController::connect<ClockPeripheral::Eic>(clockGen); | ||
|
||
// Enable EIC | ||
EIC->CTRL.bit.ENABLE = 1; | ||
int waitCycles = 2048; | ||
while (EIC->STATUS.bit.SYNCBUSY == 1 && --waitCycles); | ||
} | ||
|
||
std::array<std::function<void()>, 16> ExternalInterrupt::handlers_ = {}; | ||
|
||
// FIXME: Figure out if it is worth using function pointers here instead | ||
// to get rid of std::function overhead. | ||
MODM_ISR(EIC) { | ||
uint32_t int_flag = EIC->INTFLAG.reg; | ||
uint32_t flags = int_flag << 16; | ||
auto handler = ExternalInterrupt::handlers_.end() - 1; | ||
do { | ||
uint8_t leading_zeros = __builtin_clz(flags); | ||
handler -= leading_zeros; | ||
flags <<= leading_zeros; | ||
if (flags & 1u << 31 && *handler) { | ||
(*handler)(); | ||
flags &= ~(1u << 31); | ||
} | ||
} while (flags); | ||
EIC->INTFLAG.reg |= int_flag; | ||
} | ||
|
||
|
||
} // namespace platform | ||
} // namespace modm |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
/* | ||
* Copyright (c) 2020, Erik Henriksson | ||
* | ||
* This file is part of the modm project. | ||
* | ||
* This Source Code Form is subject to the terms of the Mozilla Public | ||
* License, v. 2.0. If a copy of the MPL was not distributed with this | ||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. | ||
*/ | ||
// ---------------------------------------------------------------------------- | ||
|
||
#include <functional> | ||
#include <modm/architecture/interface/interrupt.hpp> | ||
#include <modm/platform/clock/gclk.hpp> | ||
#include <modm/platform/device.hpp> | ||
#include <modm/platform/gpio/base.hpp> | ||
|
||
#pragma once | ||
|
||
namespace modm | ||
{ | ||
|
||
namespace platform | ||
{ | ||
|
||
MODM_ISR_DECL(EIC); | ||
|
||
/** | ||
* External Interrupt handler for SAMD devices. | ||
* | ||
* @author Erik Henriksson | ||
* @ingroup modm_platform_extint | ||
*/ | ||
class ExternalInterrupt { | ||
friend void EIC_IRQHandler(void); | ||
public: | ||
/** | ||
* Initializes the External Interrupt handler. | ||
* | ||
* @param clockGen | ||
* The clock generator to use for the peripheral. If any interrupts are to | ||
* be used to akeup the CPU from standby mode, make sure this clock is | ||
* actually running in standby. Defaults to external 32.768kHz crystal osc. | ||
*/ | ||
static void initialize( | ||
ClockGenerator clockGen = ClockGenerator::ExternalCrystal32K, | ||
int priority = (1ul << __NVIC_PRIO_BITS) - 1ul); | ||
|
||
protected: | ||
static std::array<std::function<void()>, 16> handlers_; | ||
}; | ||
|
||
/** | ||
* External Interrupt instance for SAMD devices. | ||
* | ||
* @author Erik Henriksson | ||
* @ingroup modm_platform_extint | ||
*/ | ||
template<int instance> class ExtInt : private ExternalInterrupt | ||
{ | ||
public: | ||
/** | ||
* Initializes the External Interrupt instance. | ||
* | ||
* @param handler | ||
* Function that will be called for any interrupts. | ||
* @param trigger | ||
* Specifies the edge detection trigger to use (default is rising edge). | ||
* @param wakeupEnabled | ||
* If true (default), allows the CPU to wakeup from interrupt | ||
* from this instance. | ||
*/ | ||
static void initialize( | ||
std::function<void()> handler, | ||
Gpio::InputTrigger trigger = Gpio::InputTrigger::RisingEdge, | ||
bool wakeupEnabled = true); | ||
|
||
/** | ||
* Connects a GPIO pin to this External Interrupt instance. | ||
* | ||
* @tparam Pin | ||
* The GPIO pin to connect this instance to. | ||
*/ | ||
template<class Pin> | ||
static void | ||
connectPin() { | ||
Pin::template connectInterrupt<instance>(); | ||
} | ||
}; | ||
|
||
} // namespace platform | ||
|
||
} // namespace modm | ||
|
||
#include "extint_impl.hpp" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
/* | ||
* Copyright (c) 2020, Erik Henriksson | ||
* | ||
* This file is part of the modm project. | ||
* | ||
* This Source Code Form is subject to the terms of the Mozilla Public | ||
* License, v. 2.0. If a copy of the MPL was not distributed with this | ||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. | ||
*/ | ||
// ---------------------------------------------------------------------------- | ||
|
||
#pragma once | ||
|
||
namespace modm | ||
{ | ||
namespace platform | ||
{ | ||
|
||
template<int instance> | ||
void | ||
ExtInt<instance>::initialize( | ||
std::function<void()> handler, | ||
Gpio::InputTrigger trigger, | ||
bool wakeupEnabled) { | ||
handlers_[instance] = handler; | ||
if (wakeupEnabled) { | ||
EIC->WAKEUP.reg |= EIC_WAKEUP_WAKEUPEN(1u << instance); | ||
} else { | ||
EIC->WAKEUP.reg &= ~EIC_WAKEUP_WAKEUPEN(1u << instance); | ||
} | ||
constexpr int sensePos = instance*EIC_CONFIG_SENSE1_Pos; | ||
EIC->CONFIG[instance & 0x8].reg &= EIC_CONFIG_SENSE0_Msk << sensePos; | ||
EIC->CONFIG[instance & 0x8].reg |= uint32_t(trigger) << sensePos; | ||
EIC->INTENSET.vec.EXTINT |= 1u << instance; | ||
} | ||
|
||
|
||
} // namespace platform | ||
} // namespace modm |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
#!/usr/bin/env python3 | ||
# -*- coding: utf-8 -*- | ||
# | ||
# Copyright (c) 2020, Erik Henriksson | ||
# | ||
# This file is part of the modm project. | ||
# | ||
# This Source Code Form is subject to the terms of the Mozilla Public | ||
# License, v. 2.0. If a copy of the MPL was not distributed with this | ||
# file, You can obtain one at http://mozilla.org/MPL/2.0/. | ||
# ----------------------------------------------------------------------------- | ||
|
||
import sys | ||
|
||
def init(module): | ||
module.name = ":platform:extint" | ||
module.description = "External Interrupt" | ||
|
||
def prepare(module, options): | ||
if options[":target"].identifier.platform != "sam": | ||
return False | ||
|
||
module.depends(":cmsis:device", ":platform:clock", ":platform:gpio") | ||
|
||
return True | ||
|
||
def build(env): | ||
env.outbasepath = "modm/src/modm/platform/extint" | ||
env.copy("extint.hpp") | ||
env.copy("extint_impl.hpp") | ||
env.copy("extint.cpp") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters