我在PIC32MX入门工具包上使用FreeRTOS端口用于PIC32单片机。只是玩任务但任务不是上下文切换。以下是我的主要配置设置:
#define configMAX_PRIORITIES ( ( unsigned portBASE_TYPE ) 5 )
#define configKERNEL_INTERRUPT_PRIORITY 0x01
#define configMAX_SYSCALL_INTERRUPT_PRIORITY 0x03
#define configTICK_RATE_HZ ( ( portTickType ) 100 )
现在我定义了两个闪烁两个LED的任务。两者的优先级均为4(最高)。在正常操作下,LED应该每100个刻度闪烁一次。但这不会发生。第二个LED闪烁100个刻度,控制进入常规异常处理程序。为什么会这样?好像根本没有安排。
答案 0 :(得分:6)
FreeRTOS是一种基于优先级的先发制人调度程序,不会产生处理器时间的相同优先级的任务将被循环调度。依靠循环调度很少适合实时任务,并且根据配置的时间片,可能会使您的时间陷入困境。甚至可以禁用时间分片。
您的任务必须进入阻止状态,等待某些事件(例如已用时间)以允许彼此按预期运行。
也就是说,进入异常处理程序而不是简单地一个任务挨饿另一个或者没有按预期的时间运行是另一回事。为此,您需要发布其他信息,但第一种方法应该是部署调试器。
答案 1 :(得分:5)
首先要检查的是你的“滴答”中断。通常没有启用中断,定时器设置不正确,在设置PIC32的#pragma中没有正确配置时钟..所有这些问题首先表现为缺少“滴答”。
这是没有任务切换的首要原因:如果你没有得到嘀嗒中断。这就是正常的先发制人任务切换发生的地方。
假设您正在使用“现成的演示”,在MPLAB中,在void vPortIncrementTick( void )
函数中设置一个断点(在FreeRTOS \ Source \ portable \ _PDFLAB \ PIC32MX \ port.c中的第177行附近)并且运行你的代码。如果它在那里断点,你的计时器滴答工作正常。
答案 2 :(得分:4)
你有循环调度程序吗?你的任务是否在任何时间内都在睡觉,或只是屈服(或忙着等待)?
嵌入式操作系统中一个非常常见的问题是调度程序经常不会尝试公平地调度多个具有相同优先级的进程。也就是说,一旦A产生,如果A是可运行的,即使B没有任何年龄的CPU,A也可能立即再次进行调度。如果你习惯于那些需要花费大量精力来做公平调度的桌面操作系统(或者至少对我而言),这是非常违反直觉的。
如果你遇到这种情况,你需要确保你的任务看起来像这样:
for (;;)
{
led(on); sleep(delay);
led(off); sleep(delay);
}
...确保任务实际上在闪烁之间停止运行。如果它看起来像这样:
for (;;)
{
led(on);
led(off);
}
(另外,作为一般规则,你要使用普通优先级而不是高优先级,除非你知道你真的需要它 - 如果你饿了系统任务,系统会表现得很奇怪或崩溃。)
答案 3 :(得分:4)
您确定这两项任务都已妥善注册且计划程序已启动吗?
以下代码可以完成这项工作:
xTaskCreate( yourFirstTask, "firstTask", STACK_SIZE, NULL, TASK_PRIORITY, NULL );
xTaskCreate( yourSecondTask, "secondTask", STACK_SIZE, NULL, TASK_PRIORITY, NULL );
vTaskStartScheduler();
您还可以添加一个应用程序勾选钩子,以查看是否正确发生了嘀嗒中断或者嘀嗒计时器是否存在问题。
答案 4 :(得分:3)
有一些标准的演示任务只会使FreeRTOS / Demo / Common / Minimal / flash.c源文件中的LED闪烁。该文件中创建的任务包含在标准PIC32演示应用程序中(针对Microchip Explorer16板)。
在最简单的形式中,每500毫秒切换一次的LED任务看起来像这样:
/* Standard task prototype, the parameter is not used in this case. */
void vADummyTask( void *pvParameters )
{
const portTickType xDelayTime = 500 / portTICK_RATE_MS;
for( ;; )
{
ToggleLED();
vTaskDelay( xDelayTime );
}
}