迅维网

查看: 1416|回复: 0
打印 上一主题 下一主题

【NUCLEO-F412ZG试用体验】跑个RTOS

[复制链接]
跳转到指定楼层
1#
发表于 2016-12-19 13:59:51 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式 来自: 山东 来自 山东

马上注册,获取阅读精华内容及下载权限

您需要 登录 才可以下载或查看,没有帐号?注册

x
又是一周过去了,这周使用F412跑个RTOS,性能绝对杠杠的,不过这次改成了标准库,整个软件工程的结构也进行了调整。1MB的flash可以做很多事情。只不过有一点遗憾,就是这个flash的SECTOR太大,用来模拟eeprom有点浪费,也浪费内存。从最开始玩了一下uCOS,对实时操作系统也有一个简单的入门,不过当时虽然听说有FreeRTOS这么一个轻便的实时内核,但是由于编程能力有限,再加上思维上的错误,导致刚接触就退缩了。后来出于好奇,再次开始捣鼓这个实时内核,不过这次有点不同,主要是思维上的转变,开始不再深入内核源码,而是直接使接口函数,把它当个工具来用,后来熟悉了,遇到问题了再稍微深入源码看一下。前期还是要多看一些资料。
   FreeRTOS的移植要比uCOS简单,重点就在FreeRTOSConfig.h这个文件中进行配置,对内核进行裁剪。
   既然有了内核,那么就应该好好利用内核提供的接口函数。内核固然很好,但是过分依赖于内核,会导我们的代码过分依赖于内核,降低了可移植性。所以需要尽量做一些封装,先对信号量做一些封装,这也是学了一下lwip协议栈。
先定义一下信号量类型。
  • typedef struct{
  •     int count;//初始值为0,表示当前已被占用信号量的个数。
  •     void *sem;//信号量。
  • }os_sem_t;

[color=rgb(51, 102, 153) !important]复制代码

下面是信号量的两个操作函数。
  • int os_sem_get(os_sem_t*sem,int count);//获取信号量,count是创建信号量时的信号量总数,这个必须确定,这个地方做的不太好。
  • int os_sem_del(os_sem_t*sem);//用完之后需要释放信号量

[color=rgb(51, 102, 153) !important]复制代码

接下来是这两个函数的具体实现,os_sem_get在获取信号量时,如果不存在,则会创建,这也是其参数count的作用。os_sem_del在释放信号量时,如果信号量已全部释放,则会自动释放信号量暂用的内存空间。
  • int os_sem_get(os_sem_t*sem,int count)
  • {
  •     BaseType_t xResult;
  •     if(sem->sem==NULL)
  •     {
  •         sem->count=0;
  •         sem->sem = pvPortMalloc(sizeof(SemaphoreHandle_t));//首次使用,需要创建
  •         if(sem->sem==NULL)
  •             return -1;
  •         sem->sem = xSemaphoreCreateCounting(count, count);
  • }
  •     if(sem->sem==NULL)
  •         return -2;
  •     xResult = xSemaphoreTake(sem->sem, portMAX_DELAY);
  •     if(xResult!=pdTRUE)
  •         return -3;
  •     sem->count++;
  •     return 0;
  • }
  • <blockquote>int os_sem_del(os_sem_t*sem)

[color=rgb(51, 102, 153) !important]复制代码

接下来就使用这两个函数把printf函数封装成线程安全的print函数。关键就是调用printf之前先获取信号量,获取成功后再执行printf,执行完后要释放信号量,不然下次就无法再次执行printf。这里再插一句,由于printf这里是重映射到串口,所以,应该建立一个二值信号量,保证串口的发送函数顺序不会出错。所以这里再次对这个信号量进行封装,如下,注意应该首先建立一个com_tx_sem信号量。
  • #define com_get_sem()   os_sem_get(&com_tx_sem, 1)
  • #define com_del_sem()   os_sem_del(&com_tx_sem)

[color=rgb(51, 102, 153) !important]复制代码

下面对printf进行封装。printf是一个参数个数可变的函数,暂时也就是仿照网上的方法,使用,printf内部的具体实现没有深入了解。封装之后就可以使用了。
  • int os_print(const char *fmt, ...)
  • {
  •     int res = -1;
  •     com_get_sem();
  •     va_list args;   //定义va_list类型变量,用来存储单个参数
  •     va_start(args, fmt);    //使用args指向可变参数的第一个参数
  •     res = printf(fmt, args); //直接传给printf
  •     va_end(args);   //结束可变参数的获取
  •     com_del_sem();
  •     return res;
  • }

[color=rgb(51, 102, 153) !important]复制代码

虽然互斥信号量可以解决优先级反转的问题,但是这需要暂时提升低优先级任务的优先级,在学习FreeRTOS的时候了解到,可以使用守护任务,对于共享资源,使用一个任务进行操作,其他任务通过这个任务间接的使用共享资源,这样就不会有优先级反转的问题了,这样的结构确实挺好。
这里就是使用一个任务来打印字符,另外建立两个任务,向这个任务发送数据,通过这个任务把数据打印到串口终端上。任务之前的数据传送是通过os_printstr函数向队列中发送数据。再专门建立一个任务来处理队列中的数据。先贴个效果图。


                               
登录/注册后看高清大图


接下来看一下处理数据的具体实现,又是贴代码,见谅了。
  • int os_printstr(const char *str)
  • {
  •     portBASE_TYPE xStatus;
  •     int ret=-1;
  •     if(pxPrintQueue==NULL)
  •     {
  •         pxPrintQueue = xQueueCreate(5, sizeof(int));
  •     }
  •     xStatus=xQueueSendToBack(pxPrintQueue, &str, portMAX_DELAY);
  •     if(xStatus!=pdPASS)
  •     {
  •         ret = os_print("Could not send to printstr queue.\r\n");
  •     }
  •     return ret;
  • }
  • void vTaskPrint(void *pvParameter)
  • {
  •     portBASE_TYPE xStatus;
  •     char *str = NULL;
  •     os_print("print task startup!\r\n");
  •     while(1)
  •     {
  •         if(pxPrintQueue!=NULL)
  •         {
  •             xStatus = xQueueReceive(pxPrintQueue, &str, portMAX_DELAY);
  •             if(xStatus==pdPASS)
  •                 os_print(str);
  •             else
  •                 os_print("Could not receive from printstr queue.\r\n");
  •         }
  •         vTaskDelay(10);
  •     }
  • }


[color=rgb(51, 102, 153) !important]复制代码

接下来是向队列中发送数据的任务。这个就很简单了,使用xTaskCreate建立两个任务,仅仅传入参数不一样。

  • void vTaskPrintDemo(void *pvParameter)
  • {
  •     while(1)
  •     {
  •         os_printstr((const char *)pvParameter);
  •         vTaskDelay(1000);
  •     }
  • }

[color=rgb(51, 102, 153) !important]复制代码



您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表
附近
店铺
微信扫码查看附近店铺
维修
报价
扫码查看手机版报价
信号元
件查询
点位图


芯片搜索

快速回复