1

At the moment I have a problem. I want to replace the interrupt vector target call for a peripheral driver. What works for now is this:

namespace test
{
  class PortDriver{
  public:
      using InterruptHandler = void(*)();

      constexpr explicit PortDriver(const uint16_t targetAddress) {
          // Assign the interrupt handler directly to the target address
          *reinterpret_cast<InterruptHandler*>(targetAddress) = irqPort;
      }

      static void irqPort(void) 
      {
          ...
      }
  };

But this is not what I want. I want to instantiate it with a pointer to member function. So when I do this:

    constexpr uint16_t targetAddress1 = 0xFFD8;
    PortDriver<targetAddress1> port1Driver;

    constexpr uint16_t targetAddress2 = 0xFF09;
    PortDriver<targetAddress2> port2Driver;

I want to have two irq functions for the two interrupt vectors I have to be created. Best would be at compile time because of performance issues.

I have no clue if and how this could work. Maybe with a lambda but I dont know how.

It should look like this:

template <uint16_t TargetAddress>
class PortDriver {
public:
    using InterruptHandler = void(*)();
    constexpr explicit PinDriver() {
        // Assign the interrupt handler using a lambda function
        *reinterpret_cast<InterruptHandler*>(TargetAddress) = [this]() { irqHandler(); };
    }

    void irqHandler() {
       ...
    } 
};

but this does not compile

5
  • In all decades of my career I never saw such an approach, but granted, I'm just one human. Commonly your compiler and linker provide other means of defining ISR. What target system do you have? And what compiler in which version do you use? According to your declaration of the address being uint16_t, it is machine with 16 bit address bus. (BTW, 0xFFD10 does not fit into 16 bits.) Commented Nov 24, 2023 at 7:05
  • thats true sorry the 0xFFD10 was typo. At the moment I use a GCC in version 9.3. Yes it is a 16 bit micro and yes the compiler provides a special "pragma" for the interrupt routine but I want to have it in another way, at the peripheral driver which uses it. Commented Nov 24, 2023 at 7:21
  • I want to achieve a late binding in the code and a performant way. As you know normally you have a kind of irq controller which abstracts all the low level irqs where you register. but this is not the best way when it comes to performance. I also had a look on this project github.com/intel/compile-time-init-build . I think this is the same direction but in a way I do not get it yet :) Commented Nov 24, 2023 at 7:24
  • also for this dedicated interrupts c linkage is needed, which I want to come around. Maybe Im totally wrong and it is not possible with a kind of pointer to member, could be. I just wanted to test a different approach which is more maintainable. Commented Nov 24, 2023 at 7:45
  • Are you aware that you can edit your question? It's the link of the same name below your question. Please add this new information to your question, nobody expects that in comments. Also, please add which target system you have. Does it use interrupt vectors in RAM at all? Many systems I know need the interrupt vector in read-only memory. Commented Nov 24, 2023 at 8:50

1 Answer 1

1

Something along these lines, perhaps:

template <uint16_t TargetAddress>
class PortDriver {
public:
    using InterruptHandler = void(*)();

    static void Register() {
        *reinterpret_cast<InterruptHandler*>(TargetAddress) = irqHandlerTrampoline;
    }

    static PortDriver& Instance() {
      static PortDriver driver;
      return driver;
    }

    static void irqHandlerTrampoline() {
      Instance().irqHandler();
    }

    void irqHandler() {
       // ...
    } 
};

// To initialize, call
PortDriver<targetAddress1>::Register();

Basically, turn a driver for each port into a singleton; I assume it doesn't make sense to have multiple drivers per port.

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks for the hint Igor. I now followed the mindset of cib github.com/intel/compile-time-init-build and left the interrupt routines as they are and do a very late binding in the final project. The pro is, that the user of a driver do not have to know about the hardware and the driver do not have to be related / know about a hardware interrupt.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.