努力成长 发表于 2024-1-21 22:00:59

为什么不能实现时间片轮换

#include "stm32f10x.h"    // Device header
#include "Delay.h"
#include "LED.h"
#include "key.h"
#include "FreeRTOS.h"
#include "task.h"
#include<stdio.h>



portCHAR flag1;
portCHAR flag2;
TaskHandle_t Task1_Handle;
#define TASK1_STACK_SIZE                  128
StackType_t Task1Stack;
StaticTask_t Task1TCB;

TaskHandle_t Task2_Handle;
#define TASK2_STACK_SIZE                  128
StackType_t Task2Stack;
StaticTask_t Task2TCB;


/*
*************************************************************************
*                               函数声明
*************************************************************************
*/
void delay (uint32_t count);
void Task1_Entry(void *p_arg);
void Task2_Entry(void *p_arg);


/*
************************************************************************
*                              main函数
************************************************************************
*/
int main(void)
{       
    /* 硬件初始化 */
        led_init();
        /* 将硬件相关的初始化放在这里,如果是软件仿真则没有相关初始化代码 */


    /* 创建任务 */
    Task1_Handle = xTaskCreateStatic( (TaskFunction_t)Task1_Entry,   /* 任务入口 */
                                                          (char *)"Task1",               /* 任务名称,字符串形式 */
                                                          (uint32_t)TASK1_STACK_SIZE ,   /* 任务栈大小,单位为字 */
                                                          (void *) NULL,               /* 任务形参 */
                                    (UBaseType_t) 9,               /* 任务优先级,数值越大,优先级越高 */
                                                          (StackType_t *)Task1Stack,   /* 任务栈起始地址 */
                                                          (StaticTask_t *)&Task1TCB );          /* 任务控制块 */


    Task2_Handle = xTaskCreateStatic( (TaskFunction_t)Task2_Entry,   /* 任务入口 */
                                                          (char *)"Task2",               /* 任务名称,字符串形式 */
                                                          (uint32_t)TASK2_STACK_SIZE ,   /* 任务栈大小,单位为字 */
                                                          (void *) NULL,               /* 任务形参 */
                                    (UBaseType_t) 9,               /* 任务优先级,数值越大,优先级越高 */                                          
                                                          (StackType_t *)Task2Stack,   /* 任务栈起始地址 */
                                                          (StaticTask_t *)&Task2TCB );          /* 任务控制块 */

      //if(NULL != Task2_Handle)/* 创建成功 */                              
    /* 启动调度器,开始多任务调度,启动成功则不返回 */
    vTaskStartScheduler();                                    

    for(;;)
        {
                /* 系统启动成功不会到达这里 */
        }
}

/*
*************************************************************************
*                               函数实现
*************************************************************************
*/
void delay (uint32_t count)
{
        for(; count!=0; count--);
}
/* 任务1 */
void Task1_Entry(void *p_arg)
{
        for( ;; )
        {
       led2_on();
                Delay_s(2);
                led2_off();
                Delay_s(2);
               
        }
}

/* 任务2 */
void Task2_Entry(void *p_arg)
{
        for( ;; )
        {
          led1_on();
                Delay_s(2);
                led1_off();
                Delay_s(2);
               
        }
}


/* 获取空闲任务的内存 */
StackType_t IdleTaskStack;
StaticTask_t IdleTaskTCB;
void vApplicationGetIdleTaskMemory( StaticTask_t **ppxIdleTaskTCBBuffer,
                                    StackType_t **ppxIdleTaskStackBuffer,
                                    uint32_t *pulIdleTaskStackSize )
{
                *ppxIdleTaskTCBBuffer=&IdleTaskTCB;
                *ppxIdleTaskStackBuffer=IdleTaskStack;
                *pulIdleTaskStackSize=configMINIMAL_STACK_SIZE;
}

StaticTask_t Timer_Task_TCB;
StackType_t Timer_Task_Stack;
void vApplicationGetTimerTaskMemory(StaticTask_t **ppxTimerTaskTCBBuffer,
                                                                        StackType_t **ppxTimerTaskStackBuffer,
                                                                        uint32_t *pulTimerTaskStackSize)
{
        *ppxTimerTaskTCBBuffer=&Timer_Task_TCB;/* 任务控制块内存 */
        *ppxTimerTaskStackBuffer=Timer_Task_Stack;/* 任务堆栈内存 */
        *pulTimerTaskStackSize=configTIMER_TASK_STACK_DEPTH;/* 任务堆栈大小 */
}
为什么这个代码只能使得task1的led灯亮,而不是两个灯都亮

庄永 发表于 2024-1-21 23:12:39

Delay_s怎么实现的

努力成长 发表于 2024-1-22 09:28:38

#include "stm32f10x.h"

/**
* @brief微秒级延时
* @paramxus 延时时长,范围:0~233015
* @retval 无
*/
void Delay_us(uint32_t xus)
{
        SysTick->LOAD = 72 * xus;                                //设置定时器重装值
        SysTick->VAL = 0x00;                                        //清空当前计数值
        SysTick->CTRL = 0x00000005;                                //设置时钟源为HCLK,启动定时器
        while(!(SysTick->CTRL & 0x00010000));        //等待计数到0
        SysTick->CTRL = 0x00000004;                                //关闭定时器
}

/**
* @brief毫秒级延时
* @paramxms 延时时长,范围:0~4294967295
* @retval 无
*/
void Delay_ms(uint32_t xms)
{
        while(xms--)
        {
                Delay_us(1000);
        }
}

/**
* @brief秒级延时
* @paramxs 延时时长,范围:0~4294967295
* @retval 无
*/
void Delay_s(uint32_t xs)
{
        while(xs--)
        {
                Delay_ms(1000);
        }
}
调用的这个函数

努力成长 发表于 2024-1-22 09:41:33

庄永 发表于 2024-1-21 23:12
Delay_s怎么实现的

#include "stm32f10x.h"

/**
* @brief微秒级延时
* @paramxus 延时时长,范围:0~233015
* @retval 无
*/
void Delay_us(uint32_t xus)
{
        SysTick->LOAD = 72 * xus;                                //设置定时器重装值
        SysTick->VAL = 0x00;                                        //清空当前计数值
        SysTick->CTRL = 0x00000005;                                //设置时钟源为HCLK,启动定时器
        while(!(SysTick->CTRL & 0x00010000));        //等待计数到0
        SysTick->CTRL = 0x00000004;                                //关闭定时器
}

/**
* @brief毫秒级延时
* @paramxms 延时时长,范围:0~4294967295
* @retval 无
*/
void Delay_ms(uint32_t xms)
{
        while(xms--)
        {
                Delay_us(1000);
        }
}

/**
* @brief秒级延时
* @paramxs 延时时长,范围:0~4294967295
* @retval 无
*/
void Delay_s(uint32_t xs)
{
        while(xs--)
        {
                Delay_ms(1000);
        }
}
调用的这个函数

鱼小木 发表于 2024-1-22 13:39:58

task1的灯是常亮还是闪烁?能进FREERTOS的空闲中断吗?宏定义 configUSE_TIME_SLICING 和configUSE_PREEMPTION 怎么配置的?

skyshine 发表于 2024-1-22 14:03:03

努力成长 发表于 2024-1-22 09:41
#include "stm32f10x.h"

/**


这几个都没有任务切换的,只是死等,没有把时间让出来给其他任务运行,RTOS的osdelay基本都带任务调度的,比如freertos应该用vTaskDelay这类的,可以看看站里硬汉哥的教程

努力成长 发表于 2024-1-22 14:41:37

skyshine 发表于 2024-1-22 14:03
这几个都没有任务切换的,只是死等,没有把时间让出来给其他任务运行,RTOS的osdelay基本都带任务调度的 ...

我理解您的意思,这个我设置成相同优先级了,不是应该时间经过一个时间片就轮换的嘛

努力成长 发表于 2024-1-22 14:51:03

鱼小木 发表于 2024-1-22 13:39
task1的灯是常亮还是闪烁?能进FREERTOS的空闲中断吗?宏定义 configUSE_TIME_SLICING 和configUSE_PREEMPT ...

是闪烁的,两个宏定义都配置的是1,没有进入空闲中断,我把他们设置成相同优先级,感觉不用系统的延时函数,也可以切换。下面是我把led灯换成标志位,仿真看到的波形

努力成长 发表于 2024-1-22 14:52:38

1A1JMIXMC~FCRU_6P4V)D5L.png

鱼小木 发表于 2024-1-22 16:56:00

或者先把延时换成vTaskDelay(freertos 自己的挂起延时) 试一下。

努力成长 发表于 2024-1-22 18:07:48

鱼小木 发表于 2024-1-22 16:56
或者先把延时换成vTaskDelay(freertos 自己的挂起延时) 试一下。

换成vTaskDelay就可以正常切换了,好奇怪啊,用自定义的延时函数无法从当前任务切换出来,我尝试用比这两个任务优先级高的任务,即使优先级高的任务是就绪态,也无法抢占任务1{:19:}

努力成长 发表于 2024-1-23 10:59:50

庄永 发表于 2024-1-21 23:12
Delay_s怎么实现的

大哥一下点到了关键,这个延时函数是基于滴答定时器去实现的,在延时函数结束的时候关闭了滴答定时器,导致无法实现任务切换,是这个意思嘛

鱼小木 发表于 2024-1-23 12:10:30

configUSE_TIME_SLICING1(使能时间片调度)   configUSE_PREEMPTION1 (使能抢占式调度)有没有可能,此时运行的是抢占式,然后你两个任务优先级相同,任务一使用Delay_s这种延时方式的话,一直占用着CPU。可以把两个任务优先级设置为不同,再用Delay_s试下
页: [1]
查看完整版本: 为什么不能实现时间片轮换