我在ARM嵌入式设备上使用RTOS分发版。目前我需要像这个一样切换信号
GPIO_Write(PIN_1, LOW);
vTaskDelay(msec_to_ticks(1));
GPIO_Write(PIN_1, HIGH);
vTaskDelay(msec_to_ticks(1));
GPIO_Write(PIN_1, LOW);
vTaskDelay(msec_to_ticks(3));
GPIO_Write(PIN_1, HIGH);
if (option1){
vTaskDelay(msec_to_ticks(3));
GPIO_Write(PIN_1, LOW);
vTaskDelay(msec_to_ticks(1));
} else {
vTaskDelay(msec_to_ticks(1));
GPIO_Write(PIN_1, LOW);
vTaskDelay(msec_to_ticks(3));
}
GPIO_Write(PIN_1, HIGH);
if (option2){
vTaskDelay(msec_to_ticks(3));
GPIO_Write(PIN_1, LOW);
vTaskDelay(msec_to_ticks(1));
} else {
vTaskDelay(msec_to_ticks(1));
GPIO_Write(PIN_1, LOW);
vTaskDelay(msec_to_ticks(3));
}
GPIO_Write(PIN_1, HIGH);
vTaskDelay(msec_to_ticks(3));
GPIO_Write(PIN_1, LOW);
我注意到,根据我在哪里和何时调用这个函数(单独的线程/任务),信号可能是完全错误的(有时会关闭1-2ms)。
我想知道使用taskENTER_CCRITICAL()和taskEXIT_CRITICAL是否可以帮助我确保信号的准确性。
我的一个想法是,优先级较高的中断可能会在某个地方启动并延迟代码(尽管我已经设置了任务的最大优先级)。另一个原因是时间是正确的,但GPIO_Write没有立即发生。
关于如何确保代码不被中断,还有其他想法吗?
问候,
这里有一些需要考虑的事情。
1)vTaskDelay()
使用的计时器的周期是多少?延迟期间的错误数量可能高达一个刻度。例如,如果您在下一个刻度即将发生之前开始延迟,则延迟可能会短至一个刻度。
如果刻度周期为1毫秒,则无法准确测量1毫秒的延迟,因为计时器的分辨率相对较低,这意味着这些延迟可能长达1毫秒或100%太短。希望刻度周期是0.01毫秒或更小,因为这将允许它在1%或更小的误差下测量1毫秒。
2) FreeRTOS文档解释了为什么vTaskDelay()
不是控制周期性任务频率的好方法。
vTaskDelay()
指定任务希望取消阻止的时间相对于调用CCD_ 4的时间。例如指定100个刻度的阻止周期将导致任务取消阻止调用vTaskDelay()
之后的100个刻度。vTaskDelay()
不因此提供了一种控制周期性任务作为通过代码的路径,以及其他任务和中断活动,将影响vTaskDelay()
被调用,因此是下一个任务的时间执行。请参阅vTaskDelayUntil()
了解API的替代函数设计用于促进固定频率执行。它通过指定一个绝对时间(而不是相对时间)调用任务应取消阻止。
3)在调用vTaskDelay()
时使用taskENTER_CRITICAL
和taskEXIT_CRITICAL
对我来说似乎是个坏主意。调用vTaskDelay()
的原因是在该任务延迟时给其他任务一个运行的机会。因此,用taskENTER_CRITICAL
禁用中断似乎会适得其反。如果您不希望在延迟期间运行其他任务,请调用非阻塞延迟函数,而不是vTaskDelay()
。然后,如果你的非阻塞函数的时间仍然受到中断的影响,那么也许你可以考虑把它放在一个关键部分。
一个问题是,第一个引脚集与RTOS时钟异步发生,因此可能发生在时钟周期的任何地方:
Tick: | | | |
________ __________
Signal: |____| |__________________
<--------->
First transition
may occur anywhere here.
这可以通过在第一次转换之前插入单个刻度延迟来解决。
Tick: | | | |
__ __________
Signal: |__________| |__________________
Delay(1)-^
Transition occurs on the tick boundary
优先级较高的任务和中断可能会延迟转换并导致抖动,但如果锁定调度程序或禁用中断,则这些任务将不会运行,如果您的应用程序可以执行,则会为这些任务分配不适当的优先级。同样,抖动也很严重,那么你的任务优先级不合适,或者相反,高优先级任务的行为和可调度性不合适。
任务优先级不是关于"重要性",而是关于可调度性和截止日期。作为指导,具有严格的实时截止日期和运行时间短的确定期的任务应该具有高优先级。在这种情况下,任务的大部分时间都是延迟的——GPIO开关将占用很少的时钟周期,因此可以安全地为该任务分配高优先级。
行为不确定的任务应该具有较低的优先级,以免影响时间关键的任务。如果这个片段是某个任务的一部分,它会做其他可能不确定的事情,那么您的任务分区可能需要重新思考。任务划分并不总是与"作业"有关,它同样与可调度性有关,直观上单个功能或行为可能需要在多个任务中进行划分。例如,该信号可以由高优先级任务等待由某个低优先级任务触发的事件而产生,而不是直接在低优先级任务中实现。