STM32F4-DISCO 学习之FreeRTOS的移植[无需30分钟]

/ 0评 / 0

FreeRTOS应该是我见过最好移植的RTOS系统了,不会像uCos一样可能要修改一些库文件,危险性比较大.要下载FreeRTOS的最新源码可以到这个地址:https://sourceforge.net/projects/freertos/files/latest/download?source=files 当然,作为新手做实验可以下载我这个版本的,当然,为了方便上传,几百MB的DEMO已经去掉了,要完整还是去官网下载哈.下载地址:FreeRTOSV8.2.3
对了,做这个实验,用F407做简单演示,虽然我有F429,但是没现成比较干净的工程,所以,先这么干.移植很简单,把FreeRTOSV8.2.3FreeRTOSSourceportableRVDS目录下ARM_CM4F的port.c和portmacro.h,复制出来.再把内存管理算法FreeRTOSV8.2.3FreeRTOSSourceportableMemMang目录下heap_2.c复制出来,再把FreeRTOSV8.2.3FreeRTOSSource下的list.c,queue.c,tasks.c复制出来,这都是功能,当然还有timers.c这些也都是功能.但是暂时用不上.最后把FreeRTOSV8.2.3FreeRTOSSourceinclude所有文件复制出来,对了,还有一个比较重要的,可裁剪配置项.FreeRTOSConfig.h,这个文件本来应该人为创建,但是有官方参考:FreeRTOSConfig (<-使劲戳)
网上不少参考说要修改startup文件,新版已经不用了.只要到stm32f4xx_it.c删掉冲突的中断函数就可以了.再把刚才复制到的文件,引用到项目里面,就可以了.目前目录规模:
├─Application
│ └─main
├─Drivers
├─RTOS
│ ├─Include
│ └─Source
└─STM32_FWLib
├─CMSIS
│ └─startup
└─FWLib
├─inc
└─src
工程规模:
QQ截圖20151118202928
至此,编译,即可得到跑RTOS的工程.这个不用我们自己SysTick初始化哦,我们加入一个LED一闪一闪亮晶晶的程序.首先要声明一个队列,xQueueHandle类型的变量.当然,之前假定你已经初始化了LED的IO哦,程序如下:

static xQueueHandle xQueue = NULL;
/* 发送任务与接收任务之间传送的数据 */
#define mainQUEUE_SEND_PARAMETER			( 0x1111UL )
#define mainQUEUE_RECEIVE_PARAMETER			( 0x22UL )
/* 向队列发送数据的频率。利用portTICK_RATE_MS将200ms转换为ticks数目*/
#define mainQUEUE_SEND_FREQUENCY_MS			( 2000 / portTICK_RATE_MS )
#define mainQUEUE_RECEIVE_TASK_PRIORITY		( tskIDLE_PRIORITY + 2 )
#define	mainQUEUE_SEND_TASK_PRIORITY		( tskIDLE_PRIORITY + 1 )
static void prvQueueReceiveTask( void *pvParameters )
{
  unsigned long ulReceivedValue;
	/* 参数检查 */
	configASSERT( ( ( unsigned long ) pvParameters ) == mainQUEUE_RECEIVE_PARAMETER );
	for( ;; )
	{
		/* 等待数据到达队列 - 如果在FreeRTOSConfig.h中将INCLUDE_vTaskSuspend置1。
		   该任务将永远阻塞*/
		xQueueReceive( xQueue, &ulReceivedValue, portMAX_DELAY );
		/*  如果队列中有数据,将其读出并检查其值是否正确 */
		if( ulReceivedValue == 100UL )
		{
			taskENTER_CRITICAL();
			GPIO_ToggleBits(GPIOD,GPIO_Pin_12);
			taskEXIT_CRITICAL();
			ulReceivedValue = 0U;
		}
	}
}
static void prvQueueSendTask( void *pvParameters )
{
  portTickType xNextWakeTime;
  const unsigned long ulValueToSend = 100UL;
	/* 参数检查 */
	configASSERT( ( ( unsigned long ) pvParameters ) == mainQUEUE_SEND_PARAMETER );
	/* 初始化xNextWakeTime(只做一次). */
	xNextWakeTime = xTaskGetTickCount();
	for( ;; )
	{
		/* 将任务置于阻塞状态200ms,此时该任务不占用任何CPU时间此处使用
		   vTaskDelayUntil API函数可以保证任务被阻塞的时间恒定为200ms左右*/
		vTaskDelayUntil( &xNextWakeTime, mainQUEUE_SEND_FREQUENCY_MS );
		/* 将数据发送至队列 - 队列接收任务开启并切换LED显示。由于发送数据时,队列为空,
		   所以阻塞时间可以设置为0。*/
		xQueueSend( xQueue, &ulValueToSend, 0U );
	}
}
void LED_Toggle( void )
{
	/* 创建队列*/
	xQueue = xQueueCreate( 1, sizeof( unsigned long ) );
	if( xQueue != NULL )
	{
		/* 创建任务 */
		xTaskCreate( prvQueueReceiveTask,							/* 执行任务的函数 */
					( const char * ) "Rx", 										/* 任务名称,主要用于调试 */
					configMINIMAL_STACK_SIZE, 						/* 分配给任务的堆栈大小 */
					( void * ) mainQUEUE_RECEIVE_PARAMETER, /* 传递给任务的参数 */
					mainQUEUE_RECEIVE_TASK_PRIORITY, 		/* 分内给任务的句柄 */
					NULL );																	/* 任务句柄,此处设置为NULL */
		xTaskCreate( prvQueueSendTask, ( const char * ) "TX", configMINIMAL_STACK_SIZE, ( void * ) mainQUEUE_SEND_PARAMETER, mainQUEUE_SEND_TASK_PRIORITY, NULL );
		/* 启动任务调度器 */
		vTaskStartScheduler();
	}
	/* 在调度器正常运行时,程序不会执行到此处。如果程序运行到这里,则说明
	   FreeRTOS分配给空闲任务和定时器任务的堆空间不足
	*/
	for( ;; );
}

如此,我们有了RTOS,就可以干好多事情了.

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注