FreeRTOS【17】常用功能使用

1.开发背景

       基于 FreeRTOS 熟悉使用其他 API 接口

2.开发需求

        无

3.开发环境

        window10 + MDK + STM32F429 + FreeRTOS10.3.1

4.常用功能

4.1 获取系统时间

void xPortSysTickHandler( void )
{
	/* The SysTick runs at the lowest interrupt priority, so when this interrupt
	executes all interrupts must be unmasked.  There is therefore no need to
	save and then restore the interrupt mask value as its value is already
	known - therefore the slightly faster vPortRaiseBASEPRI() function is used
	in place of portSET_INTERRUPT_MASK_FROM_ISR(). */
	vPortRaiseBASEPRI();
	{
		/* Increment the RTOS tick. */
		if( xTaskIncrementTick() != pdFALSE )
		{
			/* A context switch is required.  Context switching is performed in
			the PendSV interrupt.  Pend the PendSV interrupt. */
			portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;
		}
	}
	vPortClearBASEPRIFromISR();
}
BaseType_t xTaskIncrementTick( void )
{
TCB_t * pxTCB;
TickType_t xItemValue;
BaseType_t xSwitchRequired = pdFALSE;

	/* Called by the portable layer each time a tick interrupt occurs.
	Increments the tick then checks to see if the new tick value will cause any
	tasks to be unblocked. */
	traceTASK_INCREMENT_TICK( xTickCount );
	if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE )
	{
		/* Minor optimisation.  The tick count cannot change in this
		block. */
		const TickType_t xConstTickCount = xTickCount + ( TickType_t ) 1;

		/* Increment the RTOS tick, switching the delayed and overflowed
		delayed lists if it wraps to 0. */
		xTickCount = xConstTickCount;

		if( xConstTickCount == ( TickType_t ) 0U ) /*lint !e774 'if' does not always evaluate to false as it is looking for an overflow. */
		{
			taskSWITCH_DELAYED_LISTS();
		}
		else
		{
			mtCOVERAGE_TEST_MARKER();
		}
/* pxDelayedTaskList and pxOverflowDelayedTaskList are switched when the tick
count overflows. */
#define taskSWITCH_DELAYED_LISTS()																	\
{																									\
	List_t *pxTemp;																					\
																									\
	/* The delayed tasks list should be empty when the lists are switched. */						\
	configASSERT( ( listLIST_IS_EMPTY( pxDelayedTaskList ) ) );										\
																									\
	pxTemp = pxDelayedTaskList;																		\
	pxDelayedTaskList = pxOverflowDelayedTaskList;													\
	pxOverflowDelayedTaskList = pxTemp;																\
	xNumOfOverflows++;																				\
	prvResetNextTaskUnblockTime();																	\
}

        上述是部分源码,可以看出 xPortSysTickHandler 中断调用 xTaskIncrementTick,进而实现每次中断 xTickCount 递增,并且当 xConstTickCount  递增到 0 时(计数器16位或者24位)会触发xNumOfOverflows溢出计数递增。

        所以可以使用 xTaskGetTickCount 获取局部变量或者使用 vTaskSetTimeOutState 获取全部计数。

TickType_t xTaskGetTickCount( void )
{
TickType_t xTicks;

	/* Critical section required if running on a 16 bit processor. */
	portTICK_TYPE_ENTER_CRITICAL();
	{
		xTicks = xTickCount;
	}
	portTICK_TYPE_EXIT_CRITICAL();

	return xTicks;
}
void vTaskSetTimeOutState( TimeOut_t * const pxTimeOut )
{
	configASSERT( pxTimeOut );
	taskENTER_CRITICAL();
	{
		pxTimeOut->xOverflowCount = xNumOfOverflows;
		pxTimeOut->xTimeOnEntering = xTickCount;
	}
	taskEXIT_CRITICAL();
}

4.2 待续~

好的,下面我来演示如何使用FreeRTOS和HAL库来实现一个常用功能,例如LED闪烁。 首先,我们需要在CubeMX中配置我们的硬件和FreeRTOS。选择我们的开发板和我们要控制的LED引脚,然后选择FreeRTOS并配置任务。在这个例子中,我们只需要一个任务,让它每隔一秒钟切换LED的状态。 接下来在main.c文件中编写代码。首先,我们需要包含FreeRTOS和HAL库的头文件: ```c #include "FreeRTOS.h" #include "task.h" #include "main.h" #include "stm32f4xx_hal.h" ``` 然后定义LED的GPIO端口和引脚: ```c #define LED_GPIO_PORT GPIOA #define LED_GPIO_PIN GPIO_PIN_5 ``` 接着,我们编写LED初始化函数: ```c void LED_Init(void) { GPIO_InitTypeDef GPIO_InitStruct = {0}; __HAL_RCC_GPIOA_CLK_ENABLE(); GPIO_InitStruct.Pin = LED_GPIO_PIN; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; HAL_GPIO_Init(LED_GPIO_PORT, &GPIO_InitStruct); } ``` 然后,我们编写任务函数,让它每隔一秒钟切换LED的状态: ```c void LED_Task(void *params) { while (1) { HAL_GPIO_TogglePin(LED_GPIO_PORT, LED_GPIO_PIN); vTaskDelay(pdMS_TO_TICKS(1000)); } } ``` 最后,在main函数中创建任务并启动FreeRTOS调度器: ```c int main(void) { HAL_Init(); LED_Init(); xTaskCreate(LED_Task, "LED Task", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY + 1, NULL); vTaskStartScheduler(); while (1); } ``` 现在,我们的LED闪烁程序已经完成了!当我们启动程序时,LED会每隔一秒钟闪烁一次。 需要注意的是,这个例子中使用FreeRTOS的延时函数vTaskDelay(),这个函数可以暂停任务并等待指定的时间,单位是毫秒。pdMS_TO_TICKS()是一个宏,用于将毫秒转换为FreeRTOS的时钟滴答周期。 希望这个例子可以帮助您理解如何使用FreeRTOS和HAL库实现常用功能
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值