Important changes to forums and questions
All forums and questions are now archived. To start a new conversation or read the latest updates go to forums.mbed.com.
7 years, 2 months ago.
access to members from within a callback
I wrote an encapsulation over a Serial() instance to build a clean interface with an external device. Something like this :
class ConnectIt { private: Serial link; void handler(int event); //callback of the Serial.read() public: ConnectIt(PinName tx, PinName rx); // constructor int info[16]; // parsed info stored here }
handler
is a callback function passed to the Serial.read()
call. handler
should be able to parse the buffer and fill the info array.
But callback functions have no access to properties or members (this is not defined), and std::bind is not available on the mbed environment, even with <functional>.
How to bind the callback to the object instance ?
1 Answer
7 years, 2 months ago.
Hello yota,
I think callback functions have access to class members. The code below is using RawSerial
that doesn't use streams, thus making it safe to use in interrupt handlers with the RTOS. It worked for me on an LPC1768 board.
ConnectIt.h
#ifndef CONNECT_IT_H #define CONNECT_IT_H #define RX_MAXLEN 10 #define INFO_MAXLEN 16 #define DELIMITER ',' #include "mbed.h" class ConnectIt { RawSerial link; void handler(); int rxLen; char rxBuf[RX_MAXLEN]; int infoLen; int info[INFO_MAXLEN]; public: ConnectIt(PinName tx, PinName rx); }; #endif
ConnectIt.cpp
#include "ConnectIt.h" ConnectIt::ConnectIt(PinName tx, PinName rx) : link(tx, rx), rxLen(0), infoLen(0) { link.attach(callback(this, &ConnectIt::handler), Serial::RxIrq); } void ConnectIt::handler() { while (link.readable()) { if (rxLen < RX_MAXLEN) { rxBuf[rxLen] = link.getc(); if (rxBuf[rxLen] == DELIMITER) { rxBuf[rxLen] = '\0'; rxLen = 0; if (infoLen >= INFO_MAXLEN) infoLen = 0; info[infoLen] = atoi(rxBuf); printf("info[%d] = %d\r\n", infoLen, info[infoLen]); infoLen++; } else rxLen++; } else rxLen = 0; } }
main.cpp
#include "mbed.h" #include "ConnectIt.h" DigitalOut led1(LED1); ConnectIt connectIt(USBTX, USBRX); int main() { while (true) { led1 = !led1; wait(0.5); } }
NOTE:
- Since I was not able to figure out how to pass member function arguments to the callback function the
handler
function takes no arguments. - DELIMITER char shall be applied also after the last number sent in a serial message.
Interesting... up to now, I used Serial.read(), The main problem I see with your while( link.readable() ) is that the loop is always active, instead of using events (like SERIAL_EVENT_RX_COMPLETE or SERIAL_EVENT_RX_CHARACTER_MATCH). Nonetheless, thank you for your example, I'll test it... and accept it after that :)
posted by 18 Sep 2017The while(link.readable())
loop isn't normally active. It's triggered only on serial receive interrupt. The main purpose for looping here is to improve the overall performance when the serial message is longer than one byte (The program will work also after removing the looping). Also remember, there is no magic done by hardware even when using events. The relevant code is in that case included by MBED OS, not by you. Anyway, in both cases it is possible to link the callback to the object's instance as shown above in the constructor of ConnectIt
class.