在ATmega328P上使用FreeRTOS

作者: shaoziyang
上传时间为: 2015-01-08 03:20 PM

AVR上的RTOS可能是种类最多的,有avrx、ucOS、FreeRTOS、ChibiRTOS、Atomthreads等等,还有很多国内高手写的小rtos,加起来起码有几十种吧。虽然现在很多已经停止开发,甚至网站也没有了,但是仍然是非常经典的。

下面先尝试移植FreeRTOS到ATmega328P Xplained Mini上。

首先需要安装FreeRTOS。目前FreeRTOS的最新稳定版本是8.1.2,8.2版本暂时还是beta状态,所以就选择了8.1.2版。FreeRTOS的下载是放在SourceForge上,但是一些原因现在SF经常下载不了。如果需要下载,可以通过SF的镜像,例如http://sourceforge.jp/

安装FreeRTOS后,就可以开始我们的移植了。为了速度更快一些,先以AS4为例,AS6下基本是一样的。先创建一个新项目,并在项目文件夹下创建FreeRTOS目录。这样项目就可以和FreeRTOS结合起来,方便使用相对目录管理。(这里因为可能会有多个例子,所有的例子会共用FreeRTOS的文件,所以例子程序中FreeRTOS的目录和项目文件的目录就平级了)

然后在将FreeRTOS的文件复制过来。FreeRTOS的源码很大,因为包括了很多架构的移植,以及100多兆的例程,为了节约空间,我在例子中删除了绝大部分的东西,只保留了AVR相关的部分。

1.jpg

下一步就是添加FreeRTOS的文件到项目中,具体的文件参考一下图片和例程。

2.jpg

然后在项目文件夹中新建一个文件,保存为FreeRTOSConfig.h,这就是项目文件对FreeRTOS的配置。可以从FreeRTOS的例程中复制一个过来,修改一下使用。主要就是定义configCPU_CLOCK_HZ(时钟频率)、configTICK_RATE_HZ(节拍频率)、configMAX_PRIORITIES(最大优先级)等。例程中时钟设置为8M,因为我将ATmega328P Xplained Mini改为了3.3V,所以开发板的时钟频率自动降低到8M。如果是5V供电,时钟还是16M。

3.jpg

在就是设置一下文件的搜索路径,需要将FreeRTOS文件的路径添加进来。此外还需要将当前目录也加进来,因为这是FreeRTOSConfig.h所在的目录。

5.jpg

在main.c中写一小段代码,进行简单的测试。

  1. /*
  2. 单个任务的使用。
  3. * 使用 xTaskCreate 创建任务
  4. * vTaskStartScheduler 启动调度器
  5. * 在任务中使用 vTaskDelay 进行延时
  6. */
  7. #include "FreeRTOS.h"
  8. #include "task.h"
  9. #include "cfg.h"
  10. #include "macromcu.h"
  11. void vTaskCode( void * pvParameters )
  12. {
  13. const portTickType xDelay = 100 / portTICK_RATE_MS;
  14. for( ;; )
  15. {
  16. vTaskDelay( xDelay );
  17. PININV(LED1);
  18. }
  19. }
  20. int main()
  21. {
  22. PINDIR(LED1, PIN_OUTPUT);
  23. xTaskCreate( vTaskCode, "TASK1", configMINIMAL_STACK_SIZE, NULL, 1, NULL );
  24. vTaskStartScheduler();
  25. while(1);
  26. return 0;
  27. }

复制代码

先编译测试一下,发现编译有错误。检查后发现是port.c文件的问题,TIMSK没有定义。这是因为FreeRTOS是以atmega323为例的,和atmega328有一些区别。先将TIMSK修改为TIMSK1,在检查一下port.c中,还有没有问题。果然又发现TIMER1中断的名称需要修改。新版本的AVRGCC使用了新的命名方式,于是也修改为TIMER1_COMPA_vect。这次编译可以通过了。

先在Proteus中仿真一下,发现RTOS没有跑起来。再次检查port.c,发现定时器中断允许位设置有问题,FreeRTOS中设置的是

  1. #define portCOMPARE_MATCH_A_INTERRUPT_ENABLE ( ( uint8_t ) 0x10 )

复制代码

但是在atmega328P中,OCIE1A在TIMSK1的bit1上。于是再进行修改:

  1. #define portCOMPARE_MATCH_A_INTERRUPT_ENABLE (1<<OCIE1A)//( ( uint8_t ) 0x10 )

复制代码

在编译仿真,LED开始闪了,说明RTOS开始运行了。如图:

4.gif

移植FreeRTOS时,虽然中间有一点波折,但是还算比较快,使用也很方便。

完整的AS4参考例程
freertos_demo.zip

全部评论 ()

创建讨论帖子

登录 后参与评论
系统提示