FreeRTOS是一个开源的实时操作系统。
使用的平台:秉火STM32 Cortex-M3内核开发板,Free RTOS v8.2.3。
多任务流水灯
.
├── Doc
│ └── readme.txt
├── FreeRTOS //OS依赖目录
│ ├── inc
│ │ ├── croutine.h
│ │ ├── ... //头文件
│ └── src
│ ├── croutine.c
│ ├── ... //源码文件
├── Libraries //库文件
├── Project //工程文件
└── User
├── led
│ ├── bsp_led.c
│ └── bsp_led.h
├── main.c //源码
├── stm32f10x_conf.h
├── stm32f10x_it.c
└── stm32f10x_it.h
创建多任务:
int main ( void )
{
xTaskCreate( vTaskStart, "Task Start", 512, NULL, 1, NULL );
vTaskStartScheduler();
}
void vTaskStart( void * pvParameters )
{
LED_Init ();
xTaskCreate( vTaskLed1, "Task Led1", 512, NULL, 1, NULL );
xTaskCreate( vTaskLed2, "Task Led2", 512, NULL, 1, NULL );
xTaskCreate( vTaskLed3, "Task Led3", 512, NULL, 1, NULL );
vTaskDelete( NULL );
}
void vTaskLed1( void * pvParameters )
{
while(1)
{
macLED1_ON ();
vTaskDelay( 1000 );
macLED1_OFF ();
vTaskDelay( 1000 );
}
}
上面依次对应主函数创建一个任务并开始调度,任务中又新建了三个任务,每个任务负责一个灯的开启和关闭。
任务管理-挂起与恢复
static void vTaskLed1( void * pvParameters )
{
TickType_t xLastWakeTime;
while(1)
{
macLED1_ON ();
vTaskDelayUntil(&xLastWakeTime, 200 / portTICK_RATE_MS);
macLED1_OFF ();
vTaskDelayUntil(&xLastWakeTime, 200 / portTICK_RATE_MS);
}
}
static void vTaskKey( void * pvParameters )
{
uint8_t ucKey1Press = 0, ucKey2Press = 0;
while(1)
{
if( Key_Scan ( macKEY1_GPIO_PORT, macKEY1_GPIO_PIN, 1, & ucKey1Press ) )
{
vTaskSuspend( xHandleTaskLed1 );
}
else if( Key_Scan ( macKEY2_GPIO_PORT, macKEY2_GPIO_PIN, 1, & ucKey2Press ))
{
vTaskResume( xHandleTaskLed1 );
}
vTaskDelay( 20 / portTICK_RATE_MS );
}
}
现象:开机闪烁,按下按键1将停止,按下按键2恢复。
消息队列
static xQueueHandle xQueue;
static void vTaskStart ( void * pvParameters );
static void vTaskSender ( void * pvParameters );
static void vTaskReceive( void * pvParameters );
static void vTaskStart( void * pvParameters )
{
LED_Init ();
USARTx_Config ();
printf("Test Queue");
xQueue = xQueueCreate(5, sizeof(uint32_t) );
if(xQueue != NULL)
{
xTaskCreate( vTaskSender, "Task Sender1", 512, ( void *)100, 1, NULL);
xTaskCreate( vTaskSender, "Task Sender2", 512, ( void *)200, 1, NULL);
xTaskCreate( vTaskReceive, "Task Receiver", 512, NULL, 2, NULL );
}
else
{
while(1);
}
vTaskDelete( NULL );
}
static void vTaskSender( void * pvParameters )
{
uint32_t lValueToSend;
portBASE_TYPE xStatus;
lValueToSend = ( uint32_t ) pvParameters;
while(1)
{
xStatus = xQueueSendToBack( xQueue, &lValueToSend, 0 );
if( xStatus != pdPASS )
{
printf("数据不能发送到数据队列\r\n");
}
taskYIELD();
}
}
static void vTaskReceive( void * pvParameters )
{
uint32_t lReceivedValue;
portBASE_TYPE xStatus;
while(1)
{
xStatus = xQueueReceive( xQueue, &lReceivedValue, portMAX_DELAY );
if(xStatus==pdPASS)
{
printf( "接收的数据是: %d\r\n", lReceivedValue );
}
else
{
printf("没有接收的消息.\r\n");
}
}
}
int main ( void )
{
xTaskCreate( vTaskStart, "Task Start", 512, NULL, 1, NULL );
vTaskStartScheduler();
}
输出结果:
二值信号量–同步数据读写
static SemaphoreHandle_t xSemaphore = NULL;
xSemaphore = xSemaphoreCreateBinary();
xSemaphoreGive( xSemaphore );
xSemaphoreTake( xSemaphore, portMAX_DELAY );
计数信号量
xSemaphore = xSemaphoreCreateCounting(5, 5);
static void vTaskKey1( void * pvParameters )
{
BaseType_t xResult;
uint8_t ucKey1Press = 0;
while(1)
{
if( Key_Scan ( macKEY1_GPIO_PORT, macKEY1_GPIO_PIN, 1, & ucKey1Press ) )
{
xResult = xSemaphoreTake( xSemaphore,0);
taskENTER_CRITICAL();
if ( xResult == pdPASS )
printf ( "\r\nKEY1被单击:成功申请到停车位。\r\n" );
else
printf ( "\r\nKEY1被单击:不好意思,现在停车场已满!\r\n" );
taskEXIT_CRITICAL();
}
vTaskDelay( 20 / portTICK_RATE_MS );
}
}
static void vTaskKey2( void * pvParameters )
{
BaseType_t xResult;
uint8_t ucKey2Press = 0;
while(1)
{
if( Key_Scan ( macKEY2_GPIO_PORT, macKEY2_GPIO_PIN, 1, & ucKey2Press ) )
{
xResult = xSemaphoreGive( xSemaphore );
taskENTER_CRITICAL();
if ( xResult == pdPASS )
printf ( "\r\nKEY2被单击:释放1个停车位。\r\n" );
else
printf ( "\r\nKEY2被单击:但已无车位可以释放!\r\n" );
taskEXIT_CRITICAL();
}
vTaskDelay( 20 / portTICK_RATE_MS );
}
}
运行结果:
计数信号量模拟停车场管理测试
KEY1被单击:成功申请到停车位。
KEY1被单击:成功申请到停车位。
KEY1被单击:成功申请到停车位。
KEY1被单击:成功申请到停车位。
KEY1被单击:成功申请到停车位。
KEY1被单击:不好意思,现在停车场已满!
KEY2被单击:释放1个停车位。
KEY2被单击:释放1个停车位。
KEY2被单击:释放1个停车位。
KEY2被单击:释放1个停车位。
KEY2被单击:释放1个停车位。
KEY2被单击:但已无车位可以释放!
互斥量–同步数据读写
static SemaphoreHandle_t xSemaphore = NULL;
xSemaphore = xSemaphoreCreateMutex();
xSemaphoreGive( xSemaphore );
xSemaphoreTake( xSemaphore, portMAX_DELAY );
事件标志组–按键组合
static EventGroupHandle_t xCreatedEventGroup = NULL;
xCreatedEventGroup = xEventGroupCreate();
xEventGroupSetBits(xCreatedEventGroup, 0x01);
xEventGroupClearBits(xCreatedEventGroup, 0x01);
xEventGroupSetBits(xCreatedEventGroup, 0x02);
xEventGroupClearBits(xCreatedEventGroup, 0x02);
xEventGroupWaitBits(xCreatedEventGroup,
0x03,
pdTRUE,
pdTRUE,
portMAX_DELAY);
运行现象:KEY1红灯,KEY2绿灯,KEY3蓝灯,按下KEY1或者KEY2红灯或者绿灯亮,同时按下后红灯、绿灯、蓝灯均亮起,松开后只剩下蓝灯。
软件定时器
static TimerHandle_t xTimers[3] = {NULL};
static void vTimerCallback( xTimerHandle pxTimer )
{
uint32_t ulTimerID;
ulTimerID = (uint32_t) pvTimerGetTimerID( pxTimer );
switch ( ulTimerID )
{
case 0:
macLED1_TOGGLE ();
break;
case 1:
macLED2_TOGGLE ();
break;
case 2:
macLED3_TOGGLE ();
break;
default:
break;
}
}
static void vTaskTmr( void * pvParameters )
{
uint8_t i;
for( i=0; i<3; i++ )
{
xTimers[i] = xTimerCreate("Timer",
(i+1)*1000/portTICK_RATE_MS,
pdTRUE,
(void * const)i,
vTimerCallback);
}
for( i=0; i<3; i++ )
{
xTimerStart(xTimers[i],
portMAX_DELAY);
}
vTaskDelete( NULL );
}
多内核对象测试
使用内核对象集合进行统一处理,具体实现方式在创建队列、互斥等对象后,将对象放入集合并在一个任务中统一处理:
static SemaphoreHandle_t xSemaphore = NULL;
static xQueueHandle xQueue1 = NULL;
static xQueueHandle xQueue2 = NULL;
static xQueueSetHandle xQueueSet = NULL;
static void vTaskStart( void * pvParameters )
{
......
xSemaphore = xSemaphoreCreateBinary();
xQueue1 = xQueueCreate( 10, sizeof(uint32_t) );
xQueue2 = xQueueCreate( 10, sizeof(uint32_t) );
xQueueSet = xQueueCreateSet( 1 );
xQueueAddToSet(xSemaphore, xQueueSet);
xQueueAddToSet(xQueue1, xQueueSet);
xQueueAddToSet(xQueue2, xQueueSet);
......
}
static void vTaskPend(void *pvParameters)
{
QueueSetMemberHandle_t xActivatedMember;
uint32_t ulQueueMsgValue;
uint8_t ucQueueMsgValue;
while(1)
{
xActivatedMember = xQueueSelectFromSet(xQueueSet, portMAX_DELAY);
if(xActivatedMember == xQueue1)
{
xQueueReceive(xActivatedMember, &ulQueueMsgValue, 0);
printf("接收到消息队列1接收到消息内容为 %d\r\n", ulQueueMsgValue);
}
else if(xActivatedMember == xQueue2)
{
xQueueReceive(xActivatedMember, &ucQueueMsgValue, 0);
printf("接收到消息队列2接收到消息内容为 %d\r\n", ucQueueMsgValue);
}
else if(xActivatedMember == xSemaphore)
{
if( xSemaphoreTake(xActivatedMember, 0) == pdPASS )
macLED1_TOGGLE();
}
}
}
任务间通信–IPC
static TaskHandle_t xHandleTaskWait = NULL;
static void vTaskWait( void * pvParameters )
{
BaseType_t xResult;
uint32_t ulNotifiedValue;
while(1)
{
xResult = xTaskNotifyWait(0x00000000,
0xFFFFFFFF,
&ulNotifiedValue,
portMAX_DELAY);
if(xResult == pdPASS)
{
printf("接收到的任务消息数据为: %d\r\n", ulNotifiedValue);
}
else
{
macLED1_TOGGLE();
}
}
}
static void vTaskPost( void * pvParameters )
{
uint32_t ucCount = 0;
while(1)
{
xTaskNotify(xHandleTaskWait,
ucCount++,
eSetValueWithOverwrite);
vTaskDelay( 2000 / portTICK_RATE_MS );
}
}
运行现象:
任务消息测试
接收到的任务消息数据为: 0
接收到的任务消息数据为: 1
接收到的任务消息数据为: 2
接收到的任务消息数据为: 3
接收到的任务消息数据为: 4
接收到的任务消息数据为: 5
接收到的任务消息数据为: 6
......
任务间通信–中断
通过按键中断获取信息,主要将发送放入中断处理函数当中:
void macEXTI_INT_FUNCTION (void)
{
static portBASE_TYPE xHigherPriorityTaskWoken;
static uint32_t ucCount = 0;
if(EXTI_GetITStatus(macEXTI_LINE) != RESET)
{
xTaskNotifyFromISR(xHandleTaskWait,
ucCount++,
eSetValueWithoutOverwrite,
&xHigherPriorityTaskWoken);
EXTI_ClearITPendingBit(macEXTI_LINE);
}
portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
}
内存管理
static void vTaskStart( void * pvParameters )
{
char * pMallocMem;
LED_Init ();
Key_Initial ();
USARTx_Config ();
printf ( "\r\n内存管理测试\r\n" );
pMallocMem = (char *)pvPortMalloc(50);
printf( "%s\r\n", ( char * ) pvParameters );
strcpy( pMallocMem, pvParameters );
printf( "%s\r\n", pMallocMem );
vPortFree(pMallocMem);
vTaskDelete( NULL );
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)