ANO anonymous flight control time slice scheduling transplanted to ordinary STM32 project

engineering structure

The codes related to time slice scheduling are located in the scheduler and Task files in the scheduler directory. The original clock of anonymous flight control is provided by the external interrupt realized by the 1ms pulse output by the sensor. In order to make the time slice scheduling algorithm can be used in general engineering, the 1ms timer interrupt of timer TIM7 is used here, Timer file located in the hardware directory (reason: TIM7 of f407 cannot be used for PWM output. Using timer TIM7 can reduce the conflict of transplantation. If necessary, it can be changed to other timers)

Specific code

1.Task.c is used to store user task functions. The execution of user tasks in threads should not take too long

#include "Task.h"
#include "usart.h"
#include "delay.h"
void task1()
{
	
	printf("Task 1 execution\r\n");

	
	
}

void task2()
{

	printf("Task 2 execution\r\n");
	
	
}

void task3()
{
	printf("Task 3 execution\r\n");
	
}


2.Scheduler.c. The scheduler initialization function, scheduler running function and user tasks are stored in this file (such as task2() and task1() functions)

#include "Scheduler.h"
#include "Task.h"
//
//User program scheduler
//

static void Loop_1000Hz(void) //Once in 1ms
{
	//

	//
}

static void Loop_500Hz(void) //Execute once in 2ms
{
	//

	//
}

static void Loop_200Hz(void) //Once every 5ms
{
	//

	//
}

static void Loop_100Hz(void) //Once in 10ms
{
	//

	//
}

static void Loop_50Hz(void) //Once every 20ms
{
	//
	
	//
}

static void Loop_20Hz(void) //Once every 50ms
{
	//
	task2();
	//
}

static void Loop_2Hz(void) //Once every 500ms
{
	//
	task1();
	
	//
}
//
//Scheduler initialization
//
//System task configuration to create "threads" with different execution frequencies
static sched_task_t sched_tasks[] =
	{
		{Loop_1000Hz, 1000, 0, 0},
		{Loop_500Hz, 500, 0, 0},
		{Loop_200Hz, 200, 0, 0},
		{Loop_100Hz, 100, 0, 0},
		{Loop_50Hz, 50, 0, 0},
		{Loop_20Hz, 20, 0, 0},
		{Loop_2Hz, 2, 0, 0},
};
//Determine the number of threads according to the length of the array
#define TASK_NUM (sizeof(sched_tasks) / sizeof(sched_task_t))

void Scheduler_Setup(void)
{
	uint8_t index = 0;
	//Initialize task table
	for (index = 0; index < TASK_NUM; index++)
	{
		//Calculate the number of delay cycles for each task
		sched_tasks[index].interval_ticks = 1000 / sched_tasks[index].rate_hz;
		//The shortest period is 1, i.e. 1ms
		if (sched_tasks[index].interval_ticks < 1)
		{
			sched_tasks[index].interval_ticks = 1;
		}
	}
}
//This function is placed in the while(1) of the main function to constantly judge whether any thread should be executed
void Scheduler_Run(void)
{
	uint8_t index = 0;
	//Loop to determine whether all threads should execute

	for (index = 0; index < TASK_NUM; index++)
	{
		//Get the current time of the system, in MS
		uint32_t tnow = GetTimeMs();
		//If the current time minus the last execution time is greater than or equal to the execution cycle of the thread, the thread will be executed
		if (tnow - sched_tasks[index].last_run >= sched_tasks[index].interval_ticks)
		{

			//Update the execution time of the thread for the next judgment
			sched_tasks[index].last_run = tnow;
			//Thread functions are executed using function pointers
			sched_tasks[index].task_func();
		}
	}
}

/************************END OF FILE************/

The anonymous notes have been made very clear. Here are the brief supplement and transplantation instructions. Scheduler_ The Setup function is the scheduler initialization function, which needs to be called once before the while(1) of the main function. Scheduler_Run function is a scheduler running function, which needs to be called circularly in while(1) of main function. Its main content is to obtain the current time of the system and subtract the last execution time from the current time. If it is greater than or equal to the execution cycle of the thread, the corresponding thread will be executed. The execution of user tasks in the thread should not take too long, otherwise the thread will be blocked. The scheduler of anonymous flight control is soft real-time scheduling, rather than FreeRTOS style hard real-time scheduling. (hard real-time refers to the system executing a program. As long as the specified time runs out, it will jump out, no matter whether it is completed or not. Soft real-time has no hard time limit, and it can postpone its task for a period of time.) Scheduler_ The GetTimeMs() function invoked in Run is located at timer.. C file, as follows.
3.timer.c. Store timer initialization, timer interrupt and GetTimeMs() functions

#include "timer.h"
#include "usart.h"

static uint64_t TimeMs = 0;


//Timer 7 interrupt service program		    
void TIM7_IRQHandler(void)
{ 	
	if (TIM_GetITStatus(TIM7, TIM_IT_Update) != RESET)//Is the update interrupted
	{	 	
		TimeMs++;
		TIM_ClearITPendingBit(TIM7, TIM_IT_Update  );  //Clear TIM7 update interrupt flag     
	}	    
}


 
//General interrupt initialization timer
//Here, always choose twice as much as APB1, while APB1 is 36M
//arr: automatic reload value.
//psc: clock pre division frequency		 
void TIM7_Int_Init(u16 arr,u16 psc)
{	
	NVIC_InitTypeDef NVIC_InitStructure;
	TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;

	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM7, ENABLE);//TIM7 clock enable    
	
	//Timer TIM7 initialization
	TIM_TimeBaseStructure.TIM_Period = arr; //Sets the value of the auto reload register cycle of the load activity at the next update event	
	TIM_TimeBaseStructure.TIM_Prescaler =psc; //Sets the prescaled value used as the divisor of TIMx clock frequency
	TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //Set clock division: TDTS = Tck_tim
	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM up count mode
	TIM_TimeBaseInit(TIM7, &TIM_TimeBaseStructure); //Initializes the time base unit of TIMx according to the specified parameters
 
	TIM_ITConfig(TIM7,TIM_IT_Update,ENABLE ); //Enables the specified TIM7 interrupt and allows the update interrupt
   
	TIM_Cmd(TIM7,ENABLE);//Enable timer 7
	
	NVIC_InitStructure.NVIC_IRQChannel = TIM7_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0 ;//Preemption priority 0
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;		//Sub priority 1
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;			//IRQ channel enable
	NVIC_Init(&NVIC_InitStructure);	//Initializes the VIC register according to the specified parameters
	
}

uint32_t GetTimeMs(void)
{
	return TimeMs;
}


	 

4.main.c. Software and hardware initialization, call Scheduler_Run() to start the scheduler

#include "stm32f4xx.h"
#include "usart.h"
#include "delay.h"
#include "timer.h"
#include "Scheduler.h"


int main(void)
{
	
	uart_init(115200);
	delay_init(168);
	TIM7_Int_Init(10-1,8400-1);
	Scheduler_Setup();
  while(1){
    Scheduler_Run();
	}
}

If necessary, a complete project is provided here for reference.

https://download.csdn.net/download/qq_45296217/79248632

Keywords: C Single-Chip Microcomputer stm32

Added by zarp on Fri, 04 Feb 2022 15:34:07 +0200