Skip to content

Commit

Permalink
feat: extend gpio interrupt interface to enable immediate interrupt h…
Browse files Browse the repository at this point in the history
…andlers (#416)

* extend gpio interrupt interface to enable immediate interrupt handlers

* chore: point to emil branch

* feat: only schedule notifications once until handled when a gpio is used with a dispatched handler

* chore: set emil GIT_TAG to latest main
  • Loading branch information
daantimmer authored Oct 4, 2024
1 parent e9c4ed8 commit d95f21a
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 33 deletions.
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ if (HALST_STANDALONE)
FetchContent_Declare(
emil
GIT_REPOSITORY https://github.com/philips-software/amp-embedded-infra-lib.git
GIT_TAG 4dc5736b2814734a66a1de75d2eabb356d1ed6ff # unreleased
GIT_TAG 95ddf856192b8eb7e7282f3cb6f4e028aef200ad # unreleased
)
FetchContent_MakeAvailable(emil)

Expand Down
43 changes: 36 additions & 7 deletions hal_st/stm32fxxx/GpioStm.cpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,17 @@
#include "hal_st/stm32fxxx/GpioStm.hpp"
#include "hal/interfaces/Gpio.hpp"
#include "hal_st/cortex/InterruptCortex.hpp"
#include "infra/event/EventDispatcher.hpp"
#include "infra/util/BitLogic.hpp"
#include "infra/util/Function.hpp"
#include "infra/util/MemoryRange.hpp"
#include "infra/util/ReallyAssert.hpp"
#include <cassert>
#include <cstddef>
#include <cstdint>
#include <stdlib.h>
#include <utility>
#include DEVICE_HEADER

namespace hal
{
Expand Down Expand Up @@ -160,9 +170,9 @@ namespace hal
GpioStm::Instance().ClearPinReservation(port, index);
}

void GpioPinStm::EnableInterrupt(const infra::Function<void()>& action, InterruptTrigger trigger)
void GpioPinStm::EnableInterrupt(const infra::Function<void()>& action, InterruptTrigger trigger, InterruptType type)
{
GpioStm::Instance().EnableInterrupt(port, index, action, trigger);
GpioStm::Instance().EnableInterrupt(port, index, action, trigger, type);
}

void GpioPinStm::DisableInterrupt()
Expand Down Expand Up @@ -245,7 +255,7 @@ namespace hal
void DummyPinStm::ResetConfig()
{}

void DummyPinStm::EnableInterrupt(const infra::Function<void()>& action, InterruptTrigger trigger)
void DummyPinStm::EnableInterrupt(const infra::Function<void()>& action, InterruptTrigger trigger, InterruptType type)
{}

void DummyPinStm::DisableInterrupt()
Expand Down Expand Up @@ -327,9 +337,9 @@ namespace hal

void MultiGpioPinStm::ConfigPeripheral(PinConfigTypeStm pinConfigType, uint8_t peripheral)
{
for (const std::pair<Port, uint8_t>& portAndIndex : table)
for (const auto& portAndIndex : table)
{
std::pair<const GpioStm::PinPosition&, const GpioStm::PinoutTable&> peripheralPinConfig = GpioStm::Instance().GetPeripheralPinConfig(portAndIndex.first, portAndIndex.second, pinConfigType, peripheral);
const auto peripheralPinConfig = GpioStm::Instance().GetPeripheralPinConfig(portAndIndex.first, portAndIndex.second, pinConfigType, peripheral);

GpioStm::Instance().ReservePin(portAndIndex.first, portAndIndex.second);

Expand Down Expand Up @@ -483,7 +493,7 @@ namespace hal
abort();
}

void GpioStm::EnableInterrupt(Port port, uint8_t index, const infra::Function<void()>& action, InterruptTrigger trigger)
void GpioStm::EnableInterrupt(Port port, uint8_t index, const infra::Function<void()>& action, InterruptTrigger trigger, InterruptType type)
{
#if defined(STM32WBA) || defined(STM32H5)
uint8_t pos = 3;
Expand Down Expand Up @@ -527,6 +537,7 @@ namespace hal
#endif
really_assert(!handlers[index]);
handlers[index] = action;
interruptTypes[index] = type;
}

void GpioStm::DisableInterrupt(Port port, uint8_t index)
Expand Down Expand Up @@ -558,12 +569,30 @@ namespace hal
EXTI->PR &= (1 << line); // Interrupt pending is cleared by writing a 1 to it
#endif
if (handlers[line])
infra::EventDispatcher::Instance().Schedule(handlers[line]);
{
if (interruptTypes[line] == InterruptType::dispatched)
{
DispatchExtiInterrupt(line);
}
else
handlers[line]();
}
NVIC_ClearPendingIRQ(irq);
}
}
}

void GpioStm::DispatchExtiInterrupt(std::size_t line)
{
if (!notificationScheduled[line].exchange(true))
infra::EventDispatcher::Instance().Schedule([this, line]
{
notificationScheduled[line] = false;
if (handlers[line])
handlers[line]();
});
}

void GpioStm::ReservePin(Port port, uint8_t index)
{
assert(static_cast<uint8_t>(port) < assignedPins.size());
Expand Down
59 changes: 34 additions & 25 deletions hal_st/stm32fxxx/GpioStm.hpp
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
#ifndef HAL_GPIO_STM_HPP
#define HAL_GPIO_STM_HPP

#include DEVICE_HEADER
#include "hal/interfaces/Gpio.hpp"
#include "hal_st/cortex/InterruptCortex.hpp"
#include "infra/util/Function.hpp"
#include "infra/util/InterfaceConnector.hpp"
#include "infra/util/MemoryRange.hpp"
#include <array>
#include <atomic>
#include <cstddef>
#include <cstdint>
#include <utility>
#include DEVICE_HEADER

namespace hal
{
Expand Down Expand Up @@ -136,7 +142,7 @@ namespace hal
void Config(PinConfigType config) override;
void Config(PinConfigType config, bool startOutputState) override;
void ResetConfig() override;
void EnableInterrupt(const infra::Function<void()>& action, InterruptTrigger trigger) override;
void EnableInterrupt(const infra::Function<void()>& action, InterruptTrigger trigger, InterruptType type = InterruptType::dispatched) override;
void DisableInterrupt() override;

virtual void ConfigAnalog();
Expand Down Expand Up @@ -167,7 +173,7 @@ namespace hal
void Config(PinConfigType config) override;
void Config(PinConfigType config, bool startOutputState) override;
void ResetConfig() override;
void EnableInterrupt(const infra::Function<void()>& action, InterruptTrigger trigger) override;
void EnableInterrupt(const infra::Function<void()>& action, InterruptTrigger trigger, InterruptType type = InterruptType::dispatched) override;
void DisableInterrupt() override;
void ConfigAnalog() override;
void ConfigPeripheral(PinConfigTypeStm pinConfigType, uint8_t peripheral) override;
Expand Down Expand Up @@ -268,46 +274,49 @@ namespace hal
uint32_t AdcChannel(Port port, uint8_t index, uint8_t adc) const;
uint32_t DacChannel(Port port, uint8_t index, uint8_t dac) const;

void EnableInterrupt(Port port, uint8_t index, const infra::Function<void()>& action, InterruptTrigger trigger);
void EnableInterrupt(Port port, uint8_t index, const infra::Function<void()>& action, InterruptTrigger trigger, InterruptType type);
void DisableInterrupt(Port port, uint8_t index);

void ReservePin(Port port, uint8_t index);
void ClearPinReservation(Port port, uint8_t index);

private:
void ExtiInterrupt(IRQn_Type irq, std::size_t from, std::size_t to);
void DispatchExtiInterrupt(std::size_t line);

infra::MemoryRange<const infra::MemoryRange<const GpioStm::PinoutTable>> pinoutTable;
infra::MemoryRange<const GpioStm::AnalogPinPosition> analogTable;

std::array<infra::Function<void()>, 16> handlers;
std::array<InterruptType, 16> interruptTypes{};
std::array<std::atomic_bool, 16> notificationScheduled{};
std::array<uint32_t, 11> assignedPins;

#if defined(STM32F0) || defined(STM32G0)
DispatchedInterruptHandler interruptDispatcher0_1;
DispatchedInterruptHandler interruptDispatcher2_3;
DispatchedInterruptHandler interruptDispatcher4_15;
ImmediateInterruptHandler interruptDispatcher0_1;
ImmediateInterruptHandler interruptDispatcher2_3;
ImmediateInterruptHandler interruptDispatcher4_15;
#else
DispatchedInterruptHandler interruptDispatcher0;
DispatchedInterruptHandler interruptDispatcher1;
DispatchedInterruptHandler interruptDispatcher2;
DispatchedInterruptHandler interruptDispatcher3;
DispatchedInterruptHandler interruptDispatcher4;
ImmediateInterruptHandler interruptDispatcher0;
ImmediateInterruptHandler interruptDispatcher1;
ImmediateInterruptHandler interruptDispatcher2;
ImmediateInterruptHandler interruptDispatcher3;
ImmediateInterruptHandler interruptDispatcher4;
#if defined(STM32WBA) || defined(STM32H5)
DispatchedInterruptHandler interruptDispatcher5;
DispatchedInterruptHandler interruptDispatcher6;
DispatchedInterruptHandler interruptDispatcher7;
DispatchedInterruptHandler interruptDispatcher8;
DispatchedInterruptHandler interruptDispatcher9;
DispatchedInterruptHandler interruptDispatcher10;
DispatchedInterruptHandler interruptDispatcher11;
DispatchedInterruptHandler interruptDispatcher12;
DispatchedInterruptHandler interruptDispatcher13;
DispatchedInterruptHandler interruptDispatcher14;
DispatchedInterruptHandler interruptDispatcher15;
ImmediateInterruptHandler interruptDispatcher5;
ImmediateInterruptHandler interruptDispatcher6;
ImmediateInterruptHandler interruptDispatcher7;
ImmediateInterruptHandler interruptDispatcher8;
ImmediateInterruptHandler interruptDispatcher9;
ImmediateInterruptHandler interruptDispatcher10;
ImmediateInterruptHandler interruptDispatcher11;
ImmediateInterruptHandler interruptDispatcher12;
ImmediateInterruptHandler interruptDispatcher13;
ImmediateInterruptHandler interruptDispatcher14;
ImmediateInterruptHandler interruptDispatcher15;
#else
DispatchedInterruptHandler interruptDispatcher9_5;
DispatchedInterruptHandler interruptDispatcher15_10;
ImmediateInterruptHandler interruptDispatcher9_5;
ImmediateInterruptHandler interruptDispatcher15_10;
#endif
#endif
};
Expand Down

0 comments on commit d95f21a

Please sign in to comment.