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
已解决! 转到解答。
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);
}
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);
}
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.
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
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
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...