在C ++ 11中模拟类似Arduino的中断 [英] Simulate Arduino-like Interrupts in C++11

查看:65
本文介绍了在C ++ 11中模拟类似Arduino的中断的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用原始的Arduino模拟器.它的主要功能应该是测试由控制结构,循环,开关和子例程组成的简单代码.

I am working on a crude Arduino simulator. It's main function should be to test simple code consisting of control structures, loops, switches and subroutines.

我的主要想法是自己简单地提供Arduino库的功能,例如 digitalWrite() digitalRead()之类的函数,它们会读取并发送固定与外部应用程序(例如虚拟面包板)之间的状态.

My main idea is to simply provide the functions of the Arduino library myself, for example functions like digitalWrite() or digitalRead(), which would read and send the pin states from and to an external application (like a virtual breadboard).

下图显示了我当前的概念.模拟器基本上是一个线程执行一次 setup()函数,然后开始执行 loop()函数,直到停止.可以从控制(主)线程停止或暂停它.

The following diagram shows my current concept. The simulator is basically a thread which executes the setup() function once and then starts to execute the loop() function until stopped. It can be stopped or paused from the control (main) thread.

setup() loop()函数的实现以及一些变量由用户提供并且无法修改或访问.

The implemention of the setup() and loop() function, as well as some variables, are provided by the user and cannot be modified or accessed.

到目前为止,太好了.现在我要模拟中断.当模拟器线程正在执行 loop()函数时外部应用程序触发中断.这应该导致执行中断处理程序 isr(),这也是用户提供的,无法更改.

So far, so good. Now I want so simulate interrupts. While the simulator thread is executing the loop() function the external application triggers an interrupt. This should result in the execution of the interrupt handler isr(), which is also provided by the user and cannot be changed.

对于这个问题,我有两种不同的解决方法:

I had two different approaches to this problem:

  1. 挂起模拟器线程,在另一个线程中执行中断处理程序,然后继续模拟器线程.
  2. 改为使用信号处理程序,在发生中断时将信号发送到进程.

两种方法都有其自身的问题.对于第一个,我需要以某种方式同步状态,这看起来更像是一个可怕的骇客.据我所知,对于第二个选项,我无法指定哪个线程将执行信号处理程序.

Both approaches have their own problems. With the first one, I need to synchronize state somehow, and it seems more like a horrible hack. For the second option, as far as I know, I can't specify which thread will execute the signal handler.

如果可能,该解决方案应独立于平台.但是,该解决方案绝对需要编译并在Windows下运行()(MinGW甚至Cygwin).

If possible, the solution should be platform independent. However, the solution absolutely needs to compile and run under Windows (MinGW or even Cygwin).

推荐答案

IMO所有的中断都可以被认为是等待时间非常短的线程(或基本线程),因此空闲线程是主要的,而int线程可以抢占主线程,但不抢占.

IMO all the interrupts might be considered as threads (or rudimentary threads) with a very low latency, so the idle thread is the main and the int-threads can preempts the main thread but not be preempted.

因此,基本上,目的是执行所有线程,直到满足其中一个int线程中的条件为止,这种情况发生时,阻塞所有线程(关键区域类型,即

So basically, the purpose is to execute all the threads until a condition in one of the int-threads is met, when that happens, block all the threads (kind of critical region, i.e. mutex or condition variable) until the int-thread finishes its job. After that, execute all the threads again (the less time in the interrupt the better):

void interrupt1_thd(void) {
    // try_lock the mutex
    // check the condition of this interrupt
    // if true, do the job
    // release the mutex if locked

]


由于低端uC看起来很简单(即ATmega328P),因此没有嵌套的中断也没有优先级.随着更昂贵的uC(例如ATSAMD51 Cortex M4),事情变得更加复杂.现在,这些线程必须能够触发,阻塞所有其他较低或相等优先级的线程,并且能够被较高优先级的线程阻塞.基于优先级的线程没什么大不了的( pthread_setschedparam SetThreadPriority ),但嵌套了互斥体没有死锁的线程中的处理并非易事,因此这里的 condition_variable 更有意义,因为它具有通知功能:


With low-end uCs looks simple ( i.e. ATmega328P), there are not nested interrupts nor priorities. With more expensive uCs (let´s say an ATSAMD51 Cortex M4), things are much more complicated. Now the threads have to be able to trigger, block all the other lower or equal priority threads and be able to be blocked by higher priority threads. Threads based on priorities is not a big deal (pthread_setschedparam or SetThreadPriority), but nested mutexs in threads without deadlocks is not trivial, so here condition_variable makes more sense due to the capabilities of notifying:

Event:                      Int1   Int3   Int2  Int3         Int3
Main           : -----------                              ---              --------
Task1 (mid)    :             -------------            ----
Task2 (high)   :                          ----------
Task3 (low)    :                                             --------------
Take mutexLow  :            ---------- by 1 ---------        ---- by 3 ----
Take mutexMid  :            ---------- by 1 ---------
Take mutexHigh :                          -- by 2 --

如果(通过高优先级任务)采用了 mutexHigh ,则 Task1 Task3 等到 Task2 通知所有线程.

If mutexHigh is taken (by a high prio task), Task1 and Task3 waits until Task2 notifies to all the threads.

如果采用了 mutexLow (像Task3一样由低优先级任务),则 Task3 执行其工作(包括检查较高的通知),而 Task1 Task2 继续检查其条件.

If mutexLow is taken (by a low prio task as Task3 is), Task3 performs its job (which includes checking higher notifications), whilst Task1 and Task2 keep checking their conditions.

为了避免添加更多的同步机制,我将避免在不同优先级之间共享资源.

I would avoid sharing resources between different levels of priorities in order to not add more sync mechanisms.

所有这些取决于您要仿真的Arduino和要实现的仿真级别,不确定是否要更深入并包括中断队列以最大程度地减少延迟,上下文切换等.

All of this depends on the Arduino you want to simulate and the level of simulation you want to achieve, not sure if you want to go deeper and include interrupts queue to minimise the latency, context switching,...

这篇关于在C ++ 11中模拟类似Arduino的中断的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆