C ++中的Protothreads

时间:2016-12-17 21:22:03

标签: c++ timer event-handling embedded protothread

您好我正在研究通过串行总线控制电梯的嵌入式系统。 每次我发送一条消息(数据包包含地址,数据长度,数据,crc)我都需要等待电梯响应,这是由确认包表示的。

每次从电梯收到数据包时都会设置ACK。 接收消息是通过中断完成的。 ACK数据包如下所示:

header('Content-Type: application/json');

当它到来时我将ACK设置为0xA0,0x00,0x00,0x00,0x00

这是我的发送功能:

true

这只是尝试,它不起作用。

bool TransferService::send(char recAddr,char dataLength, char *data){
     pc.putc(startByte);
     pc.putc(recAddr);
     pc.putc(controllerAddress);
     pc.putc(dataLength);
     for (int i = 0; i < dataLength; i++) {
       pc.putc(data[i]);
     }
     pc.putc(getCrc(recAddr,controllerAddress,data, dataLength));
     _messageReceived = false;
     timer.reset();
     timer.start();
     ACK = false;
     do {
       if (ACK) {
         break;
       }
     } while(timer.read_ms()<=15);
     timer.stop();
     if (!ACK) {
       send(recAddr,dataLength,data);
     }
}

我的问题是如何使用protothreads使第一个功能正常工作。

1 个答案:

答案 0 :(得分:0)

Protothreads的Adam Dunkels' implementation中的线程函数的结构非常清楚,并且您的函数显然不遵循它。

Protothread线程函数必须返回0.10通常具有签名:

int

并且必须使用int threadfunction( struct pt* pt ) ; 宏来定义:

PT_THREAD

来自 Protothread 文档......

  

protothread函数必须始终返回一个整数,但绝不能返回   显式返回 - 返回在protothread内执行   语句。

查看PT_THREAD( threadfunction( struct pt* pt ) ) { PT_BEGIN(pt) ; // thread body here PT_END(pt) ; } 的定义我什么都看不到会阻止它与C ++成员函数一起使用,或者使用PT_THREAD之外的其他参数,在这种情况下,以下是更接近的纠正:

pt

在你的尝试中,你同时拥有一个do-while循环和一个PT_THREAD( TransferService::send( struct pt* pt, char recAddr, char dataLength, char *data ) { PT_BEGIN( pt ); timer.reset(); timer.start(); pc.putc( startByte ); pc.putc( recAddr ); pc.putc( controllerAddress ); pc.putc( dataLength ); for( int i = 0; i < dataLength; i++ ) { pc.putc( data[i] ); } pc.putc( getCrc( recAddr, controllerAddress, data, dataLength ) ); _messageReceived = false; PT_WAIT_UNTIL( pt, timer.read_ms() > 10 || ACK ); PT_END(); } ,但是WAIT不需要循环。实际上并不需要传递PT_WAIT_UNTIL参数,所需的pt可能是类成员甚至是全局(尽管这是不明智的)。

请注意,上述问题遵循了问题中明显的模式,但这将是一种不同寻常的设计模式;大多数情况下,线程无限期地运行而不是单个事务。在不了解整个应用程序的情况下,我建议线程应该在比单个事务struct pt函数更高的级别运行,这样你就有了一个可以重复执行的“sender”线程发送操作而不退出,如下面的大纲(即不完整或“真实”代码,并有很多假设):

send()

请注意,由于// Constructor... TransferService::TransferService() { PT_INIT( &m_pt ) ; // Where thread state m_pt // is a member variable of // type struct pt (or just pt // since this is C++) ... } // Thread function PT_THREAD(TransferService::senderThread() ) { PT_BEGIN(&m_pt); for(;;) { PT_WAIT_UNTIL( &m_pt, ready_to_send ) ; timer.reset(); timer.start(); send( recAddr, dataLength, data ) ; PT_WAIT_UNTIL( &m_pt, timer.read_ms() > 10 || ACK ); } PT_END(pt); } // Single send transaction function bool TransferService::send( char recAddr, char dataLength, char *data ) { pc.putc( startByte ); pc.putc( recAddr ); pc.putc( controllerAddress ); pc.putc( dataLength ); for( int i = 0; i < dataLength; i++ ) { pc.putc( data[i] ); } pc.putc( getCrc( recAddr, controllerAddress, data, dataLength ) ); _messageReceived = false; } API的工作方式,PT_...必须与PT_WAIT_UNTILPT_BEGIN功能相同,因此移动计时器在上面的代码中等待。