简体   繁体   English

FreeRTOS任务不是上下文切换

[英]FreeRTOS tasks are not context switching

I'm using FreeRTOS port for PIC32 microcontroller on the PIC32MX starter kit. 我在PIC32MX入门工具包上使用FreeRTOS端口用于PIC32单片机。 Was just playing with tasks but the tasks aren't context switching. 只是玩任务但任务不是上下文切换。 Here are my main config settings: 这是我的主要配置设置:

#define configMAX_PRIORITIES    ( ( unsigned portBASE_TYPE ) 5 )
#define configKERNEL_INTERRUPT_PRIORITY         0x01
#define configMAX_SYSCALL_INTERRUPT_PRIORITY    0x03
#define configTICK_RATE_HZ              ( ( portTickType ) 100 )

Now I have two tasks defined which blink two LEDs. 现在我定义了两个闪烁两个LED的任务。 Both have priority of 4(highest). 两者的优先级均为4(最高)。 Under normal operation the LEDs should alternatively blink for each 100 ticks. 在正常操作下,LED应该每100个刻度闪烁一次。 But this doesn't happen. 但这不会发生。 The second LED blinks for 100 ticks and the control goes to the general exception handler. 第二个LED闪烁100个刻度,控制进入常规异常处理程序。 Why does this happen? 为什么会这样? Seems like there is no scheduling at all. 好像根本没有调度。

FreeRTOS is a priority based pre-emptive scheduler, tasks of equal priority that do not yield processor time will be round-robin scheduled. FreeRTOS是基于优先级的先发制人调度程序,不会产生处理器时间的相同优先级的任务将被循环调度。 Relying on round-robin scheduling is seldom suitable for real-time tasks, and depending on the configured time slice, that may mess up your timing. 依靠循环调度很少适合实时任务,并且根据配置的时间片,可能会使您的时间陷入困境。 Time-slicing may even be disabled. 甚至可以禁用时间分片。

Your tasks must enter the Blocked state waiting on some event (such as elapsed time) to allow each other to run as intended. 您的任务必须进入阻止状态,等待某些事件(例如已用时间)以允许彼此按预期运行。

That said, entering the exception handler rather than simply one task starving another or not running with the intended timing is a different matter. 也就是说,进入异常处理程序而不是简单地一个任务饿死另一个或没有按预期的时间运行是另一回事。 For that you will need to post additional information, though your first approach should be to deploy your debugger. 为此,您需要发布其他信息,但第一种方法应该是部署调试器。

The absolute first thing to check is your "tick" interrupt. 首先要检查的是你的“滴答”中断。 Often interrupts are not enabled, timers aren't set up right, clocks are not configured properly in the #pragma's that set up the PIC32.. and all those issues manifest themselves first in a lack of a "tick". 通常没有启用中断,定时器设置不正确,在设置PIC32的#pragma中没有正确配置时钟......所有这些问题首先表现为缺少“滴答”。

This is the #1 cause of not task switching: if you're not getting the tick interrupt. 这是没有任务切换的首要原因:如果你没有得到嘀嗒中断。 That's where the normal pre-emptive task switching happens. 这就是正常的先发制人任务切换发生的地方。

Assuming you're using the "off the shelf demo", in MPLAB, set a breakpoint in the void vPortIncrementTick( void ) function (around line 177 in FreeRTOS\\Source\\portable\\MPLAB\\PIC32MX\\port.c) and run your code. 假设您正在使用“现成的演示”,在MPLAB中,在void vPortIncrementTick( void )函数中设置断点(在FreeRTOS \\ Source \\ portable \\ _PDF \\ MPLAB \\ PIC32MX \\ port.c中的第177行附近)并运行您的代码。 If it breakpoints in there, your timer tick is working. 如果它在那里断点,你的计时器滴答工作正常。

Do you have a round-robin scheduler? 你有循环调度程序吗? Are your tasks sleeping for any length of time, or just yielding (or busy waiting)? 你的任务是否在任何时间内都在睡觉,或只是屈服(或忙着等待)?

A very common gotcha in embedded OSs is that the scheduler will frequently not attempt to schedule multiple processes of the same priority fairly. 嵌入式操作系统中非常常见的问题是调度程序经常不会尝试公平地调度具有相同优先级的多个进程。 That is, once A yields, if A is runnable A may get scheduled again immediately even if B has not had any CPU for ages. 也就是说,一旦A产生,如果A是可运行的,即使B没有任何年龄的CPU,A也可能立即再次进行调度。 This is very counterintuitive if you're used to desktop OSs which go to a lot of effort to do fair scheduling (or at least, it was to me). 如果你习惯于那些需要付出很多努力去做公平调度的桌面操作系统(或者至少对我而言),这是非常违反直觉的。

If you're running into this, you'll want to make sure that your tasks look like this: 如果你遇到这个问题,你需要确保你的任务看起来像这样:

for (;;)
{
  led(on); sleep(delay);
  led(off); sleep(delay);
}

...to ensure that the task actually stops being runnable between blinks. ...确保任务实际上在闪烁之间停止运行。 It won't work if it looks like this: 如果看起来像这样,它将无法工作:

for (;;)
{
  led(on);
  led(off);
}

(Also, as a general rule, you want to use normal priority rather than high priority unless you know you'll really need it --- if you starve a system task the system can behave oddly or crash.) (另外,作为一般规则,你想使用普通优先级而不是高优先级,除非你知道你真的需要它 - 如果你饿了系统任务,系统会表现得很奇怪或崩溃。)

Are you sure both tasks are well registered and the scheduler has been launched? 您确定这两项任务都已完好注册且调度程序已启动吗?

Something like the following code would do the job: 像下面的代码一样可以完成这项工作:

xTaskCreate( yourFirstTask, "firstTask", STACK_SIZE, NULL, TASK_PRIORITY, NULL );
xTaskCreate( yourSecondTask, "secondTask", STACK_SIZE, NULL, TASK_PRIORITY, NULL );
vTaskStartScheduler();

You can also add an application tick hook to see if the tick interruption occurs correctly or if there is a problem with the tick timer. 您还可以添加应用程序勾选挂钩,以查看是否正确发生了嘀嗒中断或者是否存在嘀嗒计时器问题。

There are standard demo tasks that just blink LEDs in the FreeRTOS/Demo/Common/Minimal/flash.c source file. 有一些标准的演示任务只会使FreeRTOS / Demo / Common / Minimal / flash.c源文件中的LED闪烁。 The tasks created in that file are included in the standard PIC32 demo application (which targets the Microchip Explorer16 board). 在该文件中创建的任务包含在标准PIC32演示应用程序(面向Microchip Explorer16板)中。

In its very simplest form, a task that just toggles and LED every 500ms would look like this: 在最简单的形式中,每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 );
    }        
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM