Kinetis NVIC and C++

取消
显示结果 
显示  仅  | 搜索替代 
您的意思是: 
已解决

Kinetis NVIC and C++

跳至解决方案
2,908 次查看
weblar
Contributor V

Hi,

I'm wanting to redirect the UART IRQ handler to an instance function in a C++ class.

Does anyone have any experience of doing this in a bare-metal fashion?

As I'm wanting this to work in an interrupt driven manor, I guess the same will eventually apply to the ADC and I2C peripherals too.

Thanks in advance,

Kev

标签 (1)
1 解答
2,286 次查看
JimDon
Senior Contributor III

I handle this with a static member function. That is how it is done, and is 100% possible.

Not  sure why you need to use a Delegate in this case. Also, be very careful of using new in general with a relatively small amount of RAM.

You can have the static member function take a pointer to an instance of the object.

class CSerialPort {

private:

    void DoStuff();

public:

     static void HandleInterrupt(CSerialPort* pThis);

}

void CSerialPort::HandleInterrupt(CSerialPort* pThis)

{

    pThis->DoStuff();

}

CSerialPort UART0( required init parms);

CSerialPort UART1( required init parms);

void UART0InterruptHandler()

{

  CSerialPort::HandleInterrupt(&UART0);

}

void UART1InterruptHandler()

{

  CSerialPort::HandleInterrupt(&UART1);

}

在原帖中查看解决方案

7 回复数
2,287 次查看
JimDon
Senior Contributor III

I handle this with a static member function. That is how it is done, and is 100% possible.

Not  sure why you need to use a Delegate in this case. Also, be very careful of using new in general with a relatively small amount of RAM.

You can have the static member function take a pointer to an instance of the object.

class CSerialPort {

private:

    void DoStuff();

public:

     static void HandleInterrupt(CSerialPort* pThis);

}

void CSerialPort::HandleInterrupt(CSerialPort* pThis)

{

    pThis->DoStuff();

}

CSerialPort UART0( required init parms);

CSerialPort UART1( required init parms);

void UART0InterruptHandler()

{

  CSerialPort::HandleInterrupt(&UART0);

}

void UART1InterruptHandler()

{

  CSerialPort::HandleInterrupt(&UART1);

}

2,286 次查看
weblar
Contributor V

That sounds like just the ticket.

I think the pointer to the UART passed in to the static HandleInterrupt rountine was what I was missing.

Thanks to everyone for their suggestions.

0 项奖励
回复
2,286 次查看
ndavies
Contributor V

You may want to look into the use of Delegates. Delegates provide a class wrapper template that links the pointer to the object with a pointer to the member function. It simplifies the calling sequence and works with the tight typcasting done in C++. They work well for interrupt and call back functions in C++. We use them extensivly in our in-house C++ based RTOS. We run our RTOS on several processors and compilers, The delegate templates helped solve some of our portability issues.

Do a search for delegates and fast delegates in C++. There's numerous examples out there.

2,286 次查看
weblar
Contributor V

Hi,

Thanks for your suggestions.

I'm not sure how a delegate would help me in this situation - it might be just my understanding though.

If I have the following class in C++, how would I then go about using a delegate to point to my instance method?

// ============================================================================

// CSerialPort class

// ============================================================================

// ----------------------------------------------------------------------------

// Declarations

// ----------------------------------------------------------------------------

class CSerialPort;

typedef CSerialPort *PSerialPort;

// ----------------------------------------------------------------------------

// Definitions

// ----------------------------------------------------------------------------

class CSerialPort {

  public:

  CSerialPort(UART_MemMapPtr uart);

  private:

  void InterruptHandler(void);

  UART_MemMapPtr m_pUart;

};

// ----------------------------------------------------------------------------

// Implementation

// ----------------------------------------------------------------------------

// Constructor

CSerialPort::CSerialPort(UART_MemMapPtr uart) {

  m_pUart = uart;

  // Here I need to modify the NVIC so that the UARTn IRQ points to the

  // CSerialPort->InterruptHandler function

}

// This routine should be registered in the NVIC vector table

void CSerialPort::InterruptHandler(void) {

  // UARTn_IRQHandler routine

}

// The usual UARTn interrupt handler which is to be replaced somehow

void UART0_IRQHandler(void) {


}

Sorry about the formatting.

Thanks,

Kev

0 项奖励
回复
2,286 次查看
ndavies
Contributor V

It works very similar to Dick Hollenbeck's solution. Delegates just allow extra flexibility.

Delegates may be a little bit overboard for your example with one UART. They will simplify things if you have multiple interrupts calling different ISR classes chained off one ISR input, or multiple interrupts calling different instances of one class. They are needed if you dynamically load ISR vectors and you need to load two different classes at two different times. The advantage from using delegates comes about by masking some of the type casting requirements in C++.

Example, Syntax may not be completely correct but should give you the idea of what should happen:

delegate *UartD;

main_loop()

{

    CSerialPort *PSerialPort = new CSerialPort;

     UartD = MakeDelegate(PSerialPort,&CSerialPort::InterruptHandler);

}

// The usual UARTn interrupt handler which is to be replaced somehow

void UART0_IRQHandler(void) {

     *UartD(); //(if delegate Template overrides ())
}

This is a much better explanation of their use than I can come up with:

Member Function Pointers and the Fastest Possible C++ Delegates - CodeProject

2,286 次查看
weblar
Contributor V

Thank you for the clarification.

The device I'm using has 5 uarts but I'm wanting to implement a fairly flexible class which allows me to use any of the 5 uarts, either one at a time or many at once, but for each to be interrupt driven. Ideally, uart0 (or in my sample code CSerialPort(UART0_BASE_PTR) ) would map to uart0_irq, uart1 to uart1_irq, etc.

I can see how delegates can work but I'm still not certain how I can make them fit for what I'm trying to do - or even if what I'm trying to do is possible.

Sorry if I'm missing something, its been a long week...

0 项奖励
回复
2,286 次查看
dickelbeck
Contributor II

static OBJ* obj;     // set this sometime.

extern "C" uartHandler()

{

     obj->memberFunc();

}