0

我正在运行的几个任务遇到了一些问题。我有三个任务,其中一个是 LCD 更新任务,另外两个是电机驱动器任务。我还有两个 ISR 可以向两个电机驱动任务发布消息。至于安全地传递指针,我正在考虑创建一个结构:

  typedef struct message{
  enum BUTTON_1 = 0, BUTTON_2 = 1, NO_BUTTON = 3; //button ISR to increase motor drive  
  int timestamp; //A timestamp for the RPM of the motors
  }

现在共享内存的问题出现了,所以我在想:

  struct message* update_msg = (struct message*)malloc(sizeof(struct message)); //from here I dont know how to creat an object that fills the space allocated.

然后我将通过队列将指针发送到结构:

  OSTASKQPOST((void *)(st_size)
  ....
  )

在最后一个任务收到消息并使用成员变量完成所需的操作后,我将不得不释放内存。

  free(st_size)

这样的事情是合理的吗?

4

1 回答 1

2

这是线程间通信数据的“线程间通信 101”方法。它会正常工作。假设 32 位宽的队列,随着消息大小的增加,发布结构地址或对象实例开始很快获胜(超过直接按值发布数据)。

还有其他机制。在我的 ARM 嵌入式项目中,RAM 有限且内存空间比速度更重要,我倾向于使用 255 个全局消息实例的数组作为池,(保留一个值,例如 255,用于“无效索引”很有用) . 这意味着每条消息只能被一个字节引用,并且每条消息中的两个字节允许它们链接到列表中或链接到列表之外。一个链表头字节、一个互斥体和一个信号量为线程间通信创建了一个阻塞队列——不需要额外的存储空间。所有消息在启动时都链接到一个“池”队列中,并被弹出、在线程之间排队并由应用线程释放回池中。

从硬件接收数据的 ISR 不能调用 malloc、获取互斥锁或等待消息索引的信号量。我使用另一个没有锁的队列类,只是一个字节索引的循环队列。我在启动时推送了一些消息。中断处理程序可以从这个'ISRpool'中取出消息,从硬件中填充它们,设置一个int,(位域!),以识别ISR,将消息索引推送到'ISRout'循环队列,发出信号量并通过退出操作系统。在信号量上等待的线程醒来并知道 ISRout 上有数据,将其弹出并将其排队到处理来自该 ISR 的消息的任何线程。该“ISRhandler”线程还负责用消息“充值”ISRpool,以便 ISR 在数据到达时始终准备好消息。这个简单的、共享的 '

以类似的方式,tx ISR 的消息被推送到循环队列中以供 ISR 拾取,(中断被暂时禁用以查看硬件是否空闲并且硬件 FIFO 需要“启动”以再次启动 tx 中断) . 'Used' tx 消息被转储到 rx ISRpool - 它们也可以重新用于输入。

池化方案有一些不是立即显而易见的优势。一个是'没有malloc,没有免费'。消息肯定会泄露,但我很快注意到 - 我的“监视器/调试器”运行的 UART 的终端提示是“223>”,数字是池级别。如果这个数字下降并且不再回升,我知道我已经泄露了。当您不能只在 Valgrind 下运行应用程序时,这一点非常重要 :)

于 2012-04-27T00:17:06.647 回答