精华内容
下载资源
问答
  • 移植前的准备工作 ...下载TencentOS tiny 源码 TencentOS tiny的源码可从TencentOS tiny GitHub仓库地址https://github.com/Tencent/TencentOS-tiny下载,如果GitHub下载慢,也可以通过腾讯工蜂...
        

    移植前的准备工作

    1. 获取STM32的裸机工程模板

    STM32的裸机工程模板直接使用野火STM32开发板配套的固件库例程即可。可以从我github上获取https://github.com/jiejieTop/TencentOS-Demo

    下载TencentOS tiny 源码

    TencentOS tiny的源码可从TencentOS tiny GitHub仓库地址https://github.com/Tencent/TencentOS-tiny下载,如果GitHub下载慢,也可以通过腾讯工蜂开源仓下载,地址:https://git.code.tencent.com/Tencent_Open_Source/TencentOS-tiny ,大家在移植时并不需要把整个TencentOS tiny 源码放进工程文件中,否则工程的代码量太大。杰杰将在下文讲解如何将TencentOS tiny移植到工程中去,以及如何把TencentOS tiny源码中的核心部分单独提取出来,方便以后在不同的平台上移植。目前使用的是TencentOS tiny最新版本,由于TencentOS tiny在不断更新,如果以后TencentOS tiny更新到更高的版本,则以最新的版本为准。
    TencentOS tiny源码

    TencentOS tiny源码核心文件夹分析

    打开TencentOS tiny源码文件,可以看见里面有12个文件夹,下面先来了解主要文件夹及其子文件夹的作用,然后将TencentOS tiny源码的核心文件提取出来,添加到工程根目录下的文件夹中,因为工程只需要有用的源码文件,而不是全部的TencentOS tiny源码,所以可以避免工程过于庞大。

    一级目录 二 / 三级目录 说明(杰杰)
    arch arm TencentOS tiny适配的IP核架构(含M核中断、调度、tick相关代码),对我们的移植很重要
    arch risc-v TencentOS tiny适配的risc-v架构
    board TencentOS_tiny_EVB_MX TencentOS tiny 定制开发板demo,包含AT适配框架、MQTT协议、安全组件等
    component connectivity / loraWAN loRaWAN协议栈实现源码及适配层
    connectivity / Eclipse-Paho-MQTT MQTT协议栈实现源码及适配层
    connectivity / TencentCloud_SDK 腾讯云C-SDK实现源码及适配层
    fs 文件系统实现源码
    security mbedtls 安全协议源码
    utils 包含json相关源码
    devices TencentOS tiny适配的一些外设驱动(如串口wifi gprs 驱动等)
    doc TencentOS tiny相关技术文档及开发指南(建议多看这部分
    examples TencentOS tiny提供的功能示例
    kernel core TencentOS tiny内核源码(这部分是最重要的)
    hal TencentOS tiny驱动抽象层
    pm TencentOS tiny低功耗模块源码
    net at TencentOS tiny为串口类通信模组提供的AT框架实现层
    lora_module_wrapper TencentOS tiny为串口类LoraWAN模块提供的移植框架
    lwip Lwip协议实现源码及适配层
    sal_module_wrapper TencentOS tiny为串口类网络模块(wifi gprs)提供的socket移植框架
    tencent_firmware_module_wrapper TencentOS tiny提供的腾讯定制模组移植框架
    osal cmsis_os TencentOS tiny提供的cmsis os 适配
    platform hal TencentOS tiny适配的部分芯片的驱动实现源码
    vendor_bsp 芯片厂家提供的原厂bsp固件库,如STM32的HAL库
    test 存放TencentOS tiny提供的一些测试代码,含内核及上层模块示例及测试代码
    tools 存放TencentOS tiny提供的工具,小程序,配置工具等

    简单提一下我们的重点文件夹:

    • arch: TencentOS tiny是软件,单片机是硬件,为了使TencentOS tiny运行在单片机上面,TencentOS tiny和单片机必须关联在一起,那么如何关联呢?还是要通过代码来关联,这部分关联的文件叫接口文件,通常由汇编语言和C语言联合编写。这些接口文件都是跟硬件密切相关的,不同的硬件接口文件是不一样的,但都大同小异。TencentOS tinyarch\arm\arm-v6m目录中存放了cortex m0内核的单片机的接口文件,在arch\arm\arm-v7m目录中存放了cortex m3、m4m7内核的单片机的接口文件,以及一些通用的接口文件,基于这些内核的mcu都可以使用里面的接口文件。

    • kernelkernelTencentOS tiny内核核心源码,它的重要性我也不用多说,毕竟整个内核就是由这里面的文件组成,而其他文件夹都是基于内核的组件。

    提取TencentOS tiny内核源码

    将裸机工程源码重命名为hello-world,然后在裸机工程中新建一个TencentOS文件夹,接着将kernel文件夹、arch文件夹、添加到TencentOS文件夹下:

    除了TencentOS tiny的核心文件外,还需要移植一下其他文件,如关于TencentOS tiny系统的配置文件。这是一些可以被用户修改的文件,所以会放在具体的工程文件中。board就是TencentOS tiny为一些常用开发板开发的demo文件夹,其内有各个工程的配置文件,选一个与移植芯片最相机的开发板,找到它的配置文件tos_config.h,比如我们可以选择:TencentOS-tiny\board\STM32F103_SIM800A\TOS-CONFIG路径下的配置文件,把它拷贝到我们工程中的TencentOS文件夹下,当然你也可以把整个TOS-CONFIG目录拷贝过去,把其他无关的配置删掉就好了。

    这个配置文件很重要,后续在移植工程时,我们需要对这个配置文件进行修改,这样子可以裁剪TencentOS tiny的功能,得到最适合的工程配置。

    开始移植

    打开TencentOS-Demo\hello-world\Project\RVMDK(uv5)路径下的TencentOS.uvprojx文件。

    1. 根据下图的提示,新建3个工程分组,分别为tos/kernel、tos/arch、tos/config,这样可以见其名知其意,这些工程分组分别保存TencentOS tiny内核源码、接口文件、以及配置文件
    2. 根据下图将TencentOS-Demo\hello-world\TencentOS\kernel\core路径下的所有.c文件添加到tos/kernel工程分组中,也将\TencentOS-Demo\hello-world\TencentOS\kernel\pm目录下的所有.c文件添加到tos/kernel工程分组中:
    3. 同理将TencentOS-Demo\hello-world\TencentOS\arch\arm\arm-v7m\common路径下的 tos_cpu.c、tos_fault.c添加到tos/arch工程分组下,也将TencentOS-Demo\hello-world\TencentOS\arch\arm\arm-v7m\cortex-m3\armcc路径下的 port_s.S、port_c.c文件添加到tos/arch工程分组下
    4. 最后再将TencentOS-Demo\hello-world\TencentOS\TOS-CONFIG路径下的tos_config.h文件添加到tos/config工程分组中。

    需要注意的是,在tos/arch分组中添加的port_s.S文件,需要在添加时选择文件类型为“All files (*.*)”,添加(*.h)文件类型的时候也需要选择文件类型为“All files (*.*)”

    添加完成后的文件:

    指定头文件路径

    编译时需要为这些源文件指定头文件的路径,否则编译会报错。TencentOS tiny的源码中有很多头文件,必须将对应的路径添加到开发环境里。在添加TencentOS tiny源码时,一些其他的头文件夹也被复制到了工程目录中,所以这些文件夹的路径也要加到开发环境中。

    这些头文件的路径分别是:

    ..\..\TencentOS\arch\arm\arm-v7m\common\include
    ..\..\TencentOS\arch\arm\arm-v7m\cortex-m3\armcc
    ..\..\TencentOS\kernel\core\include
    ..\..\TencentOS\kernel\pm\include
    ..\..\TencentOS\TOS-CONFIG
    

    同时还要在配置中勾选支持C99模式:

    尝试编译

    如果你走到这一步,那么可以尝试编译一下,不过我测试时编译是没通过的,原因是缺少了部分头文件:

    不过这不影响,我们在配置文件tos_config.h中修改一下就好,添加两句话

    #include "stm32f10x.h"
    #include <stdio.h> // 或者 #include <stddef.h>
    

    如下图:

    修改中断函数

    注释PendSV_Handler()函数

    鉴于TencentOS tiny已经处理好PendSV与SysTick中断了,就不需要用户自己去处理,所以要在中断相关的源文件(stm32f10x_it.c文件)中注释(或者删除PendSV_Handler()函数。

    编写SysTick_Handler()函数

    SysTick中断服务函数是一个非常重要的函数,TencentOS tiny所有跟时间相关的事情都在里面处理,SysTick就是TencentOS tiny的一个心跳时钟,驱动着TencentOS tiny的运行,就像人的心跳一样,假如没有心跳,我们就相当于“挂掉”,同样的,TencentOS tiny没有了心跳,那么它就会卡死在某个地方,不能进行任务调度,不能运行任何的东西,因此我们需要实现一个TencentOS tiny的心跳时钟。代码如下:

    注意SysTick_Handler()中调用的都是TencentOS tiny中的函数,所以需要在stm32f10x_it.c文件中包含tos.h头文件。

    #include "tos.h"
    
    // SysTick_Handler()函数
    void SysTick_Handler(void)
    {
      if (tos_knl_is_running())
      {
        tos_knl_irq_enter();
        tos_tick_handler();
        tos_knl_irq_leave();
      }
    }
    

    编写main函数

    当你走到这一步,编译是不会出错了,此时我们已经完全移植好操作系统了,那么可以编写代码了,现在编写一个测试代码,在main.c文件中:

    #include "stm32f10x.h"
    #include "bsp_usart.h"
    #include "tos.h"
    
    
    k_task_t task;
    
    k_stack_t task_stack[1024];
    
    void test_task(void *Parameter)
    {
        while(1)
        {
            printf("hello world!\r\n");
            tos_task_delay(1000);
        }
    }
    
    /**
      * @brief  主函数
      * @author 杰杰
      * @retval 无
      */
    int main(void)
    {
        k_err_t err;
           
        /*初始化USART 配置模式为 115200 8-N-1,中断接收*/
        USART_Config();
    
        printf("Welcome to TencentOS tiny\r\n");
    
        tos_knl_init(); // TOS Tiny kernel initialize
                                            
        err = tos_task_create(&task, 
                              "task1", 
                              test_task,
                              NULL, 
                              2, 
                              task_stack,
                              1024,
                              20);
        if(err != K_ERR_NONE)
            printf("TencentOS Create task fail! code : %d \r\n",err);
        
        tos_knl_start(); // Start TOS Tiny
    
    }
    

    下载

    然后编译,下载到开发板上,就通过串口可以看到程序已经跑起来了:

    end

    至此,TencentOS tiny移植到stm32f1的过程全部完成!

    喜欢就关注我吧!

    欢迎关注我公众号

    相关代码可以在公众号后台获取。
    更多资料欢迎关注“物联网IoT开发”公众号!

    展开全文
  • TencentOS tiny】又有一个操作系统开源

    万次阅读 多人点赞 2019-09-18 18:51:58
    今日,腾讯宣布将开源 自主研发的轻量级物联网实时操作系统TencentOS tiny。相比市场上其它系统,腾讯TencentOS tiny在资源占用、设备成本、功耗管理以及安全稳定等层面极具竞争力。该系统的开源可大幅降低物联网...

    新闻

    今日,腾讯宣布将开源 自主研发轻量级物联网实时操作系统TencentOS tiny。相比市场上其它系统,腾讯TencentOS tiny在资源占用、设备成本、功耗管理以及安全稳定等层面极具竞争力。该系统的开源可大幅降低物联网应用开发成本,提升开发效率,同时支持一键上云,对接云端海量资源。

    源码已在github上开源:https://github.com/Tencent/TencentOS-tiny

    正题

    很荣幸,能亲眼见证TencentOS tiny的开源,也很荣幸能在一个多月前内测使用过它~

    不得不说,TencentOS tiny的内核确实是非常非常小巧,最少资源占用为RAM 0.6KB,ROM 1.8 KB。这是他们团队自主研发的RTOS,源码非常简单易懂,源码作者以非常清晰的逻辑实现了整个内核(还是非常佩服戴大神的,膜拜一下)。

    了解一下TencentOS tiny的框架
    TencentOS tiny的主体架构图
    TencentOS tiny主要由一个轻量级RTOS内核+多个物联网组件构成,,从下到上主要包括:

    CPU库 :TencentOS tiny支持的CPU IP核架构,当前主要支持ARM Cortex M0/3/4/7,还有现在很火的RISC-V,当然,腾讯物联网团队肯定也会支持更多种类更多IP核与开发板。

    驱动管理层 :包括BSP板级支持包,这些东西主要由MCU芯片厂家开发与维护,、HAL硬件抽象、Drivers设备驱动,这部分对于纯粹嵌入式开发者来说还是很重要的,肯定会越来越完善的!

    内核TencentOS tiny实时内核包括任务管理、实时调度、时间管理、中断管理、内存管理、异常处理、软件定时器、链表、消息队列、信号量、互斥锁、事件标志等模块,接下来我也将写一系列TencentOS tiny内核源码分析的文章,敬请期待吧!

    IoT协议栈TencentOS tiny提供lwip、AT Adapter、SAL层,支持不同的网络硬件,如以太网、串口WIFI、GPRS、NB-IoT、4G等通信模块。在TCP/IP网络协议栈上提供常用的物联网协议栈应用层,如COAP、MQTT,支撑终端业务快速接入腾讯云;

    安全框架TencentOS tiny为了确保物联网终端数据传输安全以及设备认证安全,提供了比较完整的安全解决方案。安全框架提供的DTLSTLS安全协议加固了COAPMQTT的传输层,可确保物联网终端在对接腾讯云时实现安全认证和数据加密;另外针对低资源的终端硬件,安全框架还提供与腾讯云IoTHub配套的密钥认证方案,确保资源受限设备也能在一定程度上实现设备安全认证;物联网安全是非常重要的,这些框架也是必须存在的。

    组件框架TencentOS tiny提供文件系统、KV存储、自组网、JS引擎、低功耗框架、设备框架、OTA、调试工具链等一系列组件,这部分我觉得还是很不错的,期待ing;

    开放API (规划开发中):TencentOS tiny将在协议中间件和框架层上提供开放API函数,这样子就能很方便使用中间组件的功能,我是最喜欢这种开发的,不造轮子,能直接使用。简单来说这个API能快速对接腾讯云,实现终端业务上云的需求,最大程度减少终端物联网产品开发周期,节省开发成本;

    示例应用TencentOS tiny提供的示例代码,模块测试代码等,方便用户参考使用。

    腾讯云物联网平台(图中最上层的部分):严格来说这部分不算TencentOS tiny的框架内容,这是接入平台层了,腾讯云的物联网平台都是提供多种语言的SDK包,当然在嵌入式设备上肯定使用C SDK的,不过总的来说都是很不错的。

    总的来说TencentOS tiny还是非常不错的,该有的功能都有,可以考虑使用一下这个操作系统~

    对于杰杰来说,作为嵌入式开发者,我是很看好物联网的,也一直在往这条路上缓缓前行,在万物互联的时代,说不定真的能在赚钱的同时还能为世界做出一丢丢贡献(如果没有那就算了)。

    据我所知,TencentOS tiny后续也将推出基于事件驱动模型的调度,用于某些单片机上不支持基于上下文调度的多任务。

    顺便再透露一下,我将接下来会写一系列TencentOS tiny内核分析的文章,全网首发哦!ps:得到源码作者的亲自指点,绝对干货!!!

    喜欢就关注我吧!

    图文教程:

    简单上手:

    深度源码分析:

    配套例程:

    视频教程:

    相关PPT资料:

    展开全文
  • TencentOS tiny 代码目录说明

    千次阅读 2019-09-23 22:38:29
    TencentOS tiny适配的IP核架构(含M核中断、调度、tick相关代码) board TencentOS_tiny_EVB_MX TencentOS tiny 定制开发板demo,包含AT适配框架、MQTT协议、安全组件等 component con...

     

    一级目录 二级目录 三级目录 说明
    arch arm   TencentOS tiny适配的IP核架构(含M核中断、调度、tick相关代码)
    board TencentOS_tiny_EVB_MX   TencentOS tiny 定制开发板demo,包含AT适配框架、MQTT协议、安全组件等
    component connectivity loraWAN loRaWAN协议栈实现源码及适配层
        Eclipse-Paho-MQTT MQTT协议栈实现源码及适配层
        TencentCloud_SDK 腾讯云C-SDK实现源码及适配层
      fs   文件系统实现源码
      security   mbedtls 安全协议源码
    devices     TencentOS tiny适配的一些外设驱动(如串口wifi gprs 驱动等)
    doc     TencentOS tiny相关技术文档及开发指南
    examples     TencentOS tiny提供的功能示例
    kernel core   TencentOS tiny内核源码
      hal   TencentOS tiny驱动抽象层
      pm   TencentOS tiny低功耗模块源码
    net at   TencentOS tiny为串口类通信模组提供的AT框架实现层
      lora_module_wrapper   TencentOS tiny为串口类LoraWAN模块提供的移植框架
      lwip   Lwip协议实现源码及适配层
      sal_module_wrapper   TencentOS tiny为串口类网络模块(wifi gprs)提供的socket移植框架
      tencent_firmware_module_wrapper   TencentOS tiny提供的腾讯定制模组移植框架
    osal cmsis_os   TencentOS tiny提供的cmsis os 适配
    platform hal   TencentOS tiny适配的部分芯片的驱动实现源码
      vendor_bsp   芯片厂家提供的原厂bsp固件库,如STM32的HAL库
    test     存放TencentOS tiny提供的一些测试代码,含内核及上层模块示例及测试代码
    tools     存放TencentOS tiny提供的工具,小程序,配置工具等
    展开全文
  • TencentOS tiny RTOS快速入门

    千次阅读 2020-09-15 00:16:24
    上节,我们介绍了TencentOS tiny,参考官方给出的移植教程亲自动手做了一遍,文章如下:天啊!鹅厂都开始做开发板了?网红腾讯物联网开发板终极开箱评测,让我们一睹为快!趁着最近有时...

    上节,我们介绍了TencentOS tiny,参考官方给出的移植教程亲自动手做了一遍,文章如下:

    天啊!鹅厂都开始做开发板了?网红腾讯物联网开发板终极开箱评测,让我们一睹为快!

    趁着最近有时间,这节,我撸了几个例程作为后面做项目参考的基本框架,当然也有一些是直接拿了官方文档的例程:

    一般来说,学习任何一个RTOS,本质是没有什么太大的区别的,通常在最简版nano上进行开发,关于TencentOS tiny,我个人认为,掌握以下基础组件的用法足矣,其它的一些组件,可以等需要使用的时候再参考文档学习应用即可。

    • TencentOS tiny多任务

    • TencentOS tiny RTOS软件定时器

    • TencentOS tiny RTOS任务间通信(互斥锁、信号量、事件、队列)

    在使用基本组件之前,我们需要配置tos_config.h文件:

    #ifndef _TOS_CONFIG_H_
    #define  _TOS_CONFIG_H_
    
    //#include "stm32l0xx.h" // 目标芯片头文件,用户需要根据情况更改
    #include "stm32l4xx_hal.h"
    
    #define TOS_CFG_TASK_PRIO_MAX           10u  // 配置TencentOS tiny默认支持的最大优先级数量
    
    #define TOS_CFG_ROUND_ROBIN_EN          0u  // 配置TencentOS tiny的内核是否开启时间片轮转
    
    #define TOS_CFG_OBJECT_VERIFY_EN           1u // 配置TencentOS tiny是否校验指针合法
    
    #define TOS_CFG_TASK_DYNAMIC_CREATE_EN  1u  // TencentOS tiny 动态任务创建功能宏
    
    #define TOS_CFG_EVENT_EN                1u  // TencentOS tiny 事件模块功能宏
    
    #define TOS_CFG_MMBLK_EN                1u  //配置TencentOS tiny是否开启内存块管理模块
    
    #define TOS_CFG_MMHEAP_EN               1u  //配置TencentOS tiny是否开启动态内存模块
    
    #define TOS_CFG_MMHEAP_DEFAULT_POOL_EN  1u  // TencentOS tiny 默认动态内存池功能宏
    
    #define TOS_CFG_MMHEAP_DEFAULT_POOL_SIZE        0x100 // 配置TencentOS tiny默认动态内存池大小
    
    #define TOS_CFG_MUTEX_EN                1u  // 配置TencentOS tiny是否开启互斥锁模块
    
    #define TOS_CFG_MESSAGE_QUEUE_EN        1u  // 配置TencentOS tiny是否开启消息队列模块
    
    #define TOS_CFG_MAIL_QUEUE_EN           1u  // 配置TencentOS tiny是否开启消息邮箱模块
    
    #define TOS_CFG_PRIORITY_MESSAGE_QUEUE_EN 1u // 配置TencentOS tiny是否开启优先级消息队列模块
    
    #define TOS_CFG_PRIORITY_MAIL_QUEUE_EN 1u  // 配置TencentOS tiny是否开启优先级消息邮箱模块
    
    #define TOS_CFG_TIMER_EN                1u  // 配置TencentOS tiny是否开启软件定时器模块
    
    #define TOS_CFG_PWR_MGR_EN              0u  // 配置TencentOS tiny是否开启外设电源管理模块
    
    #define TOS_CFG_TICKLESS_EN             0u  // 配置Tickless 低功耗模块开关
    
    #define TOS_CFG_SEM_EN                  1u  // 配置TencentOS tiny是否开启信号量模块
    
    #define TOS_CFG_TASK_STACK_DRAUGHT_DEPTH_DETACT_EN      1u // 配置TencentOS tiny是否开启任务栈深度检测
    
    #define TOS_CFG_FAULT_BACKTRACE_EN      0u  // 配置TencentOS tiny是否开启异常栈回溯功能
    
    #define TOS_CFG_IDLE_TASK_STK_SIZE      128u // 配置TencentOS tiny空闲任务栈大小
    
    #define TOS_CFG_CPU_TICK_PER_SECOND     1000u // 配置TencentOS tiny的tick频率
    
    #define TOS_CFG_CPU_CLOCK               (SystemCoreClock) // 配置TencentOS tiny CPU频率
    
    #define TOS_CFG_TIMER_AS_PROC           1u  // 配置是否将TIMER配置成函数模式
    
    #endif
    

    这样后面我们才能正常使用。

    1、TencentOS tiny多任务

    1.1 为什么要采用RTOS多任务?

    对于普通的项目来说,比如密码锁类项目,单独的一个传感器模块的开发,某些简单的仪器仪表等等,对于这类场景单一,业务需求也单一的项目来说,使用状态机或者事件驱动的方式就足以完成项目的基本功能了。

    但是如果开发一个巨量代码的工程项目,项目可能设计到传感器数据读取、无线数据上传与接收、数据传输、UI实时刷新、算法处理等等,功能诸多还需要相互配合的情况下,那么如果还在用裸机的思想去完成,那么开发者一般会面临以下两个问题:

    • 设计思路过于复杂,光怎么想程序的设计思路就得想好久了

    • 设计下来的各个功能,要考虑相互配合的问题,实时性可能得不到要求

    RTOS的多任务就可以解决对应的问题,它既能让项目开发起来思路清晰,方便易维护;同时RTOS也能保证整个产品运行的实时性,典型的程序设计架构,就可以按下面的方式来划分:

    1.2 TencentOS tiny RTOS多任务实践

    关于怎么创建多个任务,可以参考腾讯物联网终端操作系统开发指南.pdf文档,以下工程是我基于上一节的移植工程,在移植工程的基础上,由于官方给的OLED驱动例程是软件模拟驱动的,后来我将其改为I2C硬件驱动,所以,在STM32CubeMX上对OLED的I2C接口进行了配置:

    更改后重新生成软件工程,然后修改oled.c中关于写命令和写数据的接口为硬件I2C驱动:

    // IIC Write Command
    void Write_IIC_Command(unsigned char IIC_Command)
    {
        uint8_t buf[2] = {0};
        buf[0] = 0x00 ;
        buf[1] = IIC_Command ;
        HAL_I2C_Master_Transmit(&hi2c3, 0x78, buf, 2, HAL_TICK_FREQ_100HZ);
    }
    /**********************************************
    // IIC Write Data
    **********************************************/
    void Write_IIC_Data(unsigned char IIC_Data)
    {
        uint8_t buf[2] = {0};
        buf[0] = 0x40 ;
        buf[1] = IIC_Data ;
        HAL_I2C_Master_Transmit(&hi2c3, 0x78, buf, 2, HAL_TICK_FREQ_100HZ);
    }
    

    接下来,进入多任务程序编写,我们主要实现以下两个功能:

    • task1以1s的频率循环打印Hello TencentOS tiny

    • task2以100ms的频率循环翻转。

    main.c

    定义两个基本任务:

    //task1
    #define TASK1_STK_SIZE  256
    void task1(void *pdata);
    osThreadDef(task1, osPriorityNormal, 1, TASK1_STK_SIZE);
    
    void task1(void *pdata)
    {
        while(1)
        {
           printf("Hello TencentOS tiny\n");
           osDelay(1000);
        }
    }
    
    //task2
    #define TASK2_STK_SIZE  256
    void task2(void *pdata);
    osThreadDef(task2, osPriorityNormal, 1, TASK2_STK_SIZE);
    
    void task2(void *pdata)
    {
        while(1)
        {
           HAL_GPIO_TogglePin(DEBUG_LED_GPIO_Port, DEBUG_LED_Pin);
           osDelay(100);
        }
    }
    

    在main函数中:

    /**
      * @brief  The application entry point.
      * @retval int
      */
    int main(void)
    {
        /* USER CODE BEGIN 1 */
    
        /* USER CODE END 1 */
    
        /* MCU Configuration--------------------------------------------------------*/
    
        /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
        HAL_Init();
    
        /* USER CODE BEGIN Init */
    
        /* USER CODE END Init */
    
        /* Configure the system clock */
        SystemClock_Config();
    
        /* USER CODE BEGIN SysInit */
    
        /* USER CODE END SysInit */
    
        /* Initialize all configured peripherals */
        MX_GPIO_Init();
        MX_USART2_UART_Init();
        MX_I2C3_Init();
        /* USER CODE BEGIN 2 */
        OLED_Init();
        OLED_Clear();
        OLED_ShowString(0, 0, (uint8_t*)"TencentOS tiny", 16);
        OLED_ShowString(0, 2, (uint8_t*)"Bruce.yang", 16);
        //初始化内核
        osKernelInitialize();
        //创建并启动一个任务用于打印调试信息
        osThreadCreate(osThread(task1), NULL);
        //创建并启动一个任务用于以100ms的间隔翻转LED
        osThreadCreate(osThread(task2), NULL);
        //启动内核
        osKernelStart();
        /* USER CODE END 2 */
    
        /* Infinite loop */
        /* USER CODE BEGIN WHILE */
        while (1)
        {
            /* USER CODE END WHILE */
    
            /* USER CODE BEGIN 3 */
        }
    
        /* USER CODE END 3 */
    }
    

    编译后下载到EVB_MX+开发板后,运行结果如下:

    task1以1s的频率循环打印Hello TencentOS tiny,task2以100ms的频率循环翻转。

    1.3 总结

    概念性总结:

    • 多任务适合业务场景更加复杂的应用场景

    • 多任务适合对实时响应要求更高的场景

    使用总结:

    详情请参考腾讯物联网终端操作系统开发指南.pdf文档

    2、TencentOS tiny RTOS软件定时器

    2.1、为什么要采用RTOS软件定时器?

    软件定时器,顾名思义就是软件实现的定时器,它是和硬件定时器有本质区别的,软件定时器使用的是系统调度所依赖的嘀嗒定时器,也就是Systick来实现的,它主要解决一些不需要特别精准的定时触发场合,目前github仓库上有开源不少软件定时器的实例,比如multi_timer,TecentOS tiny也在自己的内核中集成了自己的一套软件定时器,实现原理其实也是差不多的。

    2.2、TencentOS tiny RTOS软件定时器实践

    关于怎么使用定时器,可以参考腾讯物联网终端操作系统开发指南.pdf文档,以下工程基于多任务例程修改,接下来,进入软件定时器程序编写,我们主要实现以下两个功能:

    • task1以1s的频率循环打印Hello TencentOS tiny

    • 软件定时器以500ms的频率翻转LED

    main.c

    /*定义一个定时器句柄*/
    k_timer_t os_tmr_handler;
    //创建一个任务
    #define TASK1_STK_SIZE  256
    void task1(void *pdata);
    osThreadDef(task1, osPriorityNormal, 1, TASK1_STK_SIZE);
    
    void task1(void *pdata)
    {
        while(1)
        {
           printf("Hello TencentOS tiny\n");
           osDelay(1000);
        }
    }
    
    //定时器回调函数
    void os_tmr_handler_callback(void *arg)
    {
       HAL_GPIO_TogglePin(DEBUG_LED_GPIO_Port, DEBUG_LED_Pin);
    }
    

    在main函数中:

    /**
      * @brief  The application entry point.
      * @retval int
      */
    int main(void)
    {
        /* USER CODE BEGIN 1 */
    
        /* USER CODE END 1 */
    
        /* MCU Configuration--------------------------------------------------------*/
    
        /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
        HAL_Init();
    
        /* USER CODE BEGIN Init */
    
        /* USER CODE END Init */
    
        /* Configure the system clock */
        SystemClock_Config();
    
        /* USER CODE BEGIN SysInit */
    
        /* USER CODE END SysInit */
    
        /* Initialize all configured peripherals */
        MX_GPIO_Init();
        MX_USART2_UART_Init();
        MX_I2C3_Init();
        /* USER CODE BEGIN 2 */
        OLED_Init();
        OLED_Clear();
        OLED_ShowString(0, 0, (uint8_t*)"TencentOS tiny", 16);
        OLED_ShowString(0, 2, (uint8_t*)"Bruce.yang", 16);
        //初始化内核
        osKernelInitialize();
        //创建一个以500ms周期运行的软件定时器
        tos_timer_create(&os_tmr_handler, 500, 500, os_tmr_handler_callback, K_NULL, TOS_OPT_TIMER_PERIODIC);
        //创建一个任务
        osThreadCreate(osThread(task1), NULL);
        //启动定时器
        tos_timer_start(&os_tmr_handler);
        //启动内核
        osKernelStart();
        /* USER CODE END 2 */
    
        /* Infinite loop */
        /* USER CODE BEGIN WHILE */
        while (1)
        {
            /* USER CODE END WHILE */
    
            /* USER CODE BEGIN 3 */
        }
    
        /* USER CODE END 3 */
    }
    

    编译后下载到EVB_MX+开发板后,运行结果如下:

    task1以1s的频率循环打印Hello TencentOS tiny,软件定时器以500ms的频率执行,此时LED会以500ms的速率循环翻转。

    2.3 总结

    概念性总结:

    • 软件定时器就是用"软件逻辑"实现的定时器

    • 软件定时器适合一些不需要特别精准的定时触发场合.

    使用总结:

    详情请参考腾讯物联网终端操作系统开发指南.pdf文档

    3、TencentOS tiny RTOS任务间通信

    3.1、TencentOS tiny RTOS互斥锁

    3.1.1 、为什么要采用RTOS互斥锁?

    互斥锁适用于实现临界区资源的互斥性访问,当有多个任务同时并行对一个数据操作时,就会存在不确定性,典型的案例就是全局变量,在不带操作系统的裸机功能开发中,我们通常会使用全局变量,让其在整个工程中通过外部引用的方式全局可见,这样我们就可以很方便的在任何一个地方对其进行读写操作,但如果在操作系统中却恰恰相反,这种奇怪的现象被称为不可重入,通常在操作系统里叫临界区资源,在字符串操作中,典型的不可重入函数是strtok,strtok函数内部有一个static变量,这种类型的变量可以被多次重入调用共同控制,其最终的结果依赖于它们的执行顺序,所以,使用互斥锁可以解决这种不确定性的问题,也就是说在任意时刻,只会有一个任务对其进行访问。

    3.1.2、TencentOS tiny RTOS互斥锁实践

    关于怎么使用互斥锁,可以参考腾讯物联网终端操作系统开发指南.pdf文档,以下工程基于多任务例程修改,接下来,进入互斥锁程序编写,我们主要实现三个任务同时执行一段代码:

    main.c

    k_mutex_t mutex;
    int number = 0 ;
    
    //task1
    #define TASK1_STK_SIZE  256
    void task1(void *pdata);
    osThreadDef(task1, osPriorityNormal, 1, TASK1_STK_SIZE);
    
    void count_sample_code(void)
    {
        tos_mutex_pend(&mutex);
        number=0;
        number+=1;
        number+=2;
        number+=3;
        tos_mutex_post(&mutex);
    }
    
    void task1(void *pdata)
    {
        while(1)
        {
            number = 0 ;
            osDelay(300);
            count_sample_code();
            printf("task1 number=%d\n",number);
            osDelay(100);
        }
    }
    
    //task2
    #define TASK2_STK_SIZE  256
    void task2(void *pdata);
    osThreadDef(task2, osPriorityNormal, 1, TASK2_STK_SIZE);
    void task2(void *pdata)
    {
        while(1)
        {
            osDelay(300);
            count_sample_code();
            printf("task2 number=%d\n",number);
            osDelay(200);
        }
    }
    
    //task3
    #define TASK3_STK_SIZE  256
    void task3(void *pdata);
    osThreadDef(task3, osPriorityNormal, 1, TASK3_STK_SIZE);
    void task3(void *pdata)
    {
        while(1)
        {
            osDelay(300);
            count_sample_code();
            printf("task3 number=%d\n",number);
            osDelay(300);
        }
    }
    

    在main函数中:

    /**
      * @brief  The application entry point.
      * @retval int
      */
    int main(void)
    {
        /* USER CODE BEGIN 1 */
    
        /* USER CODE END 1 */
    
        /* MCU Configuration--------------------------------------------------------*/
    
        /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
        HAL_Init();
    
        /* USER CODE BEGIN Init */
    
        /* USER CODE END Init */
    
        /* Configure the system clock */
        SystemClock_Config();
    
        /* USER CODE BEGIN SysInit */
    
        /* USER CODE END SysInit */
    
        /* Initialize all configured peripherals */
        MX_GPIO_Init();
        MX_USART2_UART_Init();
        MX_I2C3_Init();
        /* USER CODE BEGIN 2 */
        OLED_Init();
        OLED_Clear();
        OLED_ShowString(0, 2, (uint8_t*)"TencentOS tiny", 16);
        tos_mutex_create(&mutex);
        //初始化内核
        osKernelInitialize();
        //分别创建任务,用于验证互斥锁
        osThreadCreate(osThread(task1), NULL);
        osThreadCreate(osThread(task2), NULL);
        osThreadCreate(osThread(task3), NULL);
        //启动内核
        osKernelStart();
        /* USER CODE END 2 */
    
        /* Infinite loop */
        /* USER CODE BEGIN WHILE */
        while (1)
        {
            /* USER CODE END WHILE */
    
            /* USER CODE BEGIN 3 */
        }
    
        /* USER CODE END 3 */
    }
    

    编译后下载到EVB_MX+开发板后,运行结果如下:

    3.1.3、总结

    概念性总结:

    • 互斥锁在任意时刻,只会有一个任务对临界资源进行访问

    • 互斥锁用于实现临界区资源的互斥性访问

    使用总结:

    详情请参考腾讯物联网终端操作系统开发指南.pdf文档

    3.2、TencentOS tiny RTOS信号量

    3.2.1、为什么要采用RTOS信号量?

    信号量,俗话说就是信号的数量,它是一种任务间传递系统可用资源的机制;举一个生产者与消费者的问题;也就是说消费者在消费了一个资源之前需要等待资源释放,生产者生产资源以后要即时去通知其它的消费者,简单的说就是凡事都要有个先来后到,所以信号量最常用的地方就是实现任务间同步。

    3.2.2、TencentOS tiny RTOS信号量实践

    关于怎么使用信号量,可以参考腾讯物联网终端操作系统开发指南.pdf文档,以下工程基于多任务例程修改,接下来,进入信号量程序编写,我们主要实现生产者和消费者的问题,这段程序在参考文档里可以找到:

    main.c

    #define STK_SIZE_TASK_PRODUCER 512
    #define STK_SIZE_TASK_CONSUMER 512
    k_stack_t stack_task_producer[STK_SIZE_TASK_PRODUCER];
    
    k_stack_t stack_task_consumer[STK_SIZE_TASK_CONSUMER];
    k_task_t task_producer;
    k_task_t task_consumer;
    extern void entry_task_producer(void *arg);
    extern void entry_task_consumer(void *arg);
    k_mutex_t buffer_locker;
    k_sem_t full;
    k_sem_t empty;
    #define RESOURCE_COUNT_MAX 3
    struct resource_st
    {
        int cursor;
        uint32_t buffer[RESOURCE_COUNT_MAX];
    } resource = { 0, {0} };
    
    static void produce_item(int salt)
    {
        printf("produce item:\n");
        printf("%d", salt);
        resource.buffer[resource.cursor++] = salt;
        printf("\n");
    }
    void entry_task_producer(void *arg)
    {
        size_t salt = 0;
        k_err_t err;
    
        while (K_TRUE)
        {
            err = tos_sem_pend(&empty, TOS_TIME_FOREVER);
    
            if (err != K_ERR_NONE)
            {
                continue;
            }
    
            err = tos_mutex_pend(&buffer_locker);
    
            if (err != K_ERR_NONE)
            {
                continue;
            }
    
            produce_item(salt);
            tos_mutex_post(&buffer_locker);
            tos_sem_post(&full);
            tos_task_delay(1000);
            ++salt;
        }
    }
    static void consume_item(void)
    {
        printf("cosume item:\n");
        printf("%d\t", resource.buffer[--resource.cursor]);
        printf("\n");
    }
    void entry_task_consumer(void *arg)
    {
        k_err_t err;
    
        while (K_TRUE)
        {
            err = tos_sem_pend(&full, TOS_TIME_FOREVER);
    
            if (err != K_ERR_NONE)
            {
                continue;
            }
    
            tos_mutex_pend(&buffer_locker);
    
            if (err != K_ERR_NONE)
            {
                continue;
            }
    
            consume_item();
            tos_mutex_post(&buffer_locker);
            tos_sem_post(&empty);
            tos_task_delay(2000);
        }
    }
    

    main函数实现如下:

    int main(void)
    {
        /* USER CODE BEGIN 1 */
    
        /* USER CODE END 1 */
    
        /* MCU Configuration--------------------------------------------------------*/
    
        /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
        HAL_Init();
    
        /* USER CODE BEGIN Init */
    
        /* USER CODE END Init */
    
        /* Configure the system clock */
        SystemClock_Config();
    
        /* USER CODE BEGIN SysInit */
    
        /* USER CODE END SysInit */
    
        /* Initialize all configured peripherals */
        MX_GPIO_Init();
        MX_USART2_UART_Init();
        MX_I2C3_Init();
        /* USER CODE BEGIN 2 */
        OLED_Init();
        OLED_Clear();
        OLED_ShowString(0, 0, (uint8_t*)"TencentOS tiny", 16);
        OLED_ShowString(0, 2, (uint8_t*)"Bruce.yang", 16);
        //初始化内核
        osKernelInitialize();
        tos_mutex_create(&buffer_locker);
        tos_sem_create(&full, 0);
        tos_sem_create(&empty, RESOURCE_COUNT_MAX);
        (void)tos_task_create(&task_producer, "producer", entry_task_producer, NULL,
                              4, stack_task_producer, STK_SIZE_TASK_PRODUCER, 0);
    
        (void)tos_task_create(&task_consumer, "consumer", entry_task_consumer, NULL,
                              4, stack_task_consumer, STK_SIZE_TASK_CONSUMER, 0);
        //启动内核
        osKernelStart();
        /* USER CODE END 2 */
    
        /* Infinite loop */
        /* USER CODE BEGIN WHILE */
        while (1)
        {
            /* USER CODE END WHILE */
    
            /* USER CODE BEGIN 3 */
        }
    
        /* USER CODE END 3 */
    }
    

    编译后下载到EVB_MX+开发板后,运行结果如下:

    3.2.3、总结

    概念性总结:

    • 信号量可以用于实现任务间同步

    • 信号量最典型的应用就是处理生产者与消费者的问题

    使用总结:

    详情请参考腾讯物联网终端操作系统开发指南.pdf文档

    3.3、TencentOS tiny RTOS事件

    3.3.1、为什么要采用RTOS事件?

    事件,是RTOS任务间用来传递的一种信号的信息,它可以传递多个信息,事件和信号量的区别就是信号量只能传递0和1两个信息,而事件的类型通常用k_event_flag_t进行描述,它的本质是一个uint32_t数据类型,也就是说事件最多可以定义32个,使用事件可以很方便的实现任务间同步和信息传递,但是要注意的是事件达到的是一种类似通知的效果,本身是不带负载的。

    3.3.2、TencentOS tiny RTOS事件实践

    关于怎么使用事件,可以参考腾讯物联网终端操作系统开发指南.pdf文档,以下工程基于多任务例程修改,我们在多任务例程的基础上,移植了multi_button组件,这个组件的移植方法在之前写小熊派相关的文章中都有详细的方法,这里就不再多说了,参考文章如下:

    第1期 | MultiButton,一个小巧简单易用的事件驱动型按键驱动模块

    开源按键组件MultiButton支持菜单操作(事件驱动型)

    这里的button_ticks()我把它放在SysTick_Handler函数中进行处理,实现如下:

    /**
      * @brief This function handles System tick timer.
      */
    void SysTick_Handler(void)
    {
        /* USER CODE BEGIN SysTick_IRQn 0 */
        static uint8_t timer_ticks = 0 ;
        ++timer_ticks ;
         //5ms循环调用一次button_ticks();
        if(5 == timer_ticks)
        {
            timer_ticks = 0 ;
            button_ticks();
        }
    
        /* USER CODE END SysTick_IRQn 0 */
        HAL_IncTick();
    
        /* USER CODE BEGIN SysTick_IRQn 1 */
        if(tos_knl_is_running())
        {
            tos_knl_irq_enter();
            tos_tick_handler();
            tos_knl_irq_leave();
        }
    
        /* USER CODE END SysTick_IRQn 1 */
    }
    

    接下来进入事件程序的编写,我们主要实现以下两个功能:

    • 定义任务task1,用于初始化multi_button,通过按键回调发送事件

    • 定义任务task2,用于接收task1发送过来的事件,并进行处理

    main.c

    定义multi_button结构体变量以及事件相关的变量

    #include "multi_button.h"
    /*创建一个按键事件*/
    k_event_t key_event;
    //创建几个按键的事件标志
    const k_event_flag_t event_key1 = (k_event_flag_t)(1 << 0);
    const k_event_flag_t event_key2 = (k_event_flag_t)(1 << 1);
    const k_event_flag_t event_key3 = (k_event_flag_t)(1 << 2);
    const k_event_flag_t event_key4 = (k_event_flag_t)(1 << 3);
    const k_event_flag_t event_key5 = (k_event_flag_t)(1 << 4);
    //定义描述按键的结构体变量
    struct Button button1, button2, button3, button4;
    

    定义按键电平读取以及按键处理的函数:

    uint8_t key1_read_pin(void);
    uint8_t key2_read_pin(void);
    uint8_t key3_read_pin(void);
    uint8_t key4_read_pin(void);
    void key_handler(void* btn);
    
    uint8_t key1_read_pin(void)
    {
        return HAL_GPIO_ReadPin(KEY1_GPIO_Port, KEY1_Pin);
    }
    uint8_t key2_read_pin(void)
    {
        return HAL_GPIO_ReadPin(KEY2_GPIO_Port, KEY2_Pin);
    }
    uint8_t key3_read_pin(void)
    {
        return HAL_GPIO_ReadPin(KEY3_GPIO_Port, KEY3_Pin);
    }
    uint8_t key4_read_pin(void)
    {
        return HAL_GPIO_ReadPin(KEY4_GPIO_Port, KEY4_Pin);
    }
    //按键处理
    void key_handler(void* btn)
    {
        struct Button *button = btn ;
        if(btn == &button1)
        {
          if(button->event == PRESS_DOWN)
            tos_event_post(&key_event, event_key1);
          else if(button->event == PRESS_UP)
            tos_event_post(&key_event, event_key5);
        }
        else if(btn == &button2)
        {
          if(button->event == PRESS_DOWN)
            tos_event_post(&key_event, event_key2);
          else if(button->event == PRESS_UP)
            tos_event_post(&key_event, event_key5);
        }
        else if(btn == &button3)
        {
          if(button->event == PRESS_DOWN)
            tos_event_post(&key_event, event_key3);
          else if(button->event == PRESS_UP)
            tos_event_post(&key_event, event_key5);
        }
        else if(btn == &button4)
        {
          if(button->event == PRESS_DOWN)
            tos_event_post(&key_event, event_key4);
          else if(button->event == PRESS_UP)
            tos_event_post(&key_event, event_key5);
        }
    }
    

    在main函数中:

    /**
      * @brief  The application entry point.
      * @retval int
      */
    int main(void)
    {
        /* USER CODE BEGIN 1 */
    
        /* USER CODE END 1 */
    
        /* MCU Configuration--------------------------------------------------------*/
    
        /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
        HAL_Init();
    
        /* USER CODE BEGIN Init */
    
        /* USER CODE END Init */
    
        /* Configure the system clock */
        SystemClock_Config();
    
        /* USER CODE BEGIN SysInit */
    
        /* USER CODE END SysInit */
    
        /* Initialize all configured peripherals */
        MX_GPIO_Init();
        MX_USART2_UART_Init();
        MX_I2C3_Init();
        /* USER CODE BEGIN 2 */
        OLED_Init();
        OLED_Clear();
        OLED_ShowString(0, 0, (uint8_t*)"TencentOS tiny", 16);
        OLED_ShowString(0, 2, (uint8_t*)"Bruce.yang", 16);
        //初始化内核
        osKernelInitialize();
        //创建一个按键事件
        tos_event_create(&key_event, (k_event_flag_t)0u);
        //创建并启动一个任务用于通过按键发送事件
        osThreadCreate(osThread(task1), NULL);
        //创建并启动一个任务用于接收按键事件并执行相应的软件逻辑
        osThreadCreate(osThread(task2), NULL);
        //启动TencentOS tiny内核
        osKernelStart();
        /* USER CODE END 2 */
    
        /* Infinite loop */
        /* USER CODE BEGIN WHILE */
        while (1)
        {
            /* USER CODE END WHILE */
    
            /* USER CODE BEGIN 3 */
        }
    
        /* USER CODE END 3 */
    }
    

    编译后下载到EVB_MX+开发板后,运行结果如下:

    当分别按下四个按键后,task2接收到具体消息后执行不同的逻辑

    3.3.3 总结

    概念性总结:

    • 事件区别于信号量,信号量是0-1传递,而事件可以传递多个信息

    • 事件是用于RTOS任务间传递的一种没有信息负载的信号类信息

    使用总结:

    详情请参考腾讯物联网终端操作系统开发指南.pdf文档

    3.4、TencentOS tiny RTOS队列

    3.4.1、为什么要采用RTOS队列?

    队列也是任务间传递信息的一种方式,它和事件最本质的区别就是,事件传递没有负载,而队列的传递是包含数据负载的,在事件章节中,当我们按下按键的时候其中一个任务发出事件,另一个任务则接收事件,而接收的这个事件是非常单一的,除此之外并没有更多具体的新信息载体,而队列就是为了解决这个问题而诞生的,比如串口接收数据,当数据接收满了,此时我们就可以使用队列将接收满的数据通过队列的信息发出去,然后任务里进行接收处理。

    3.4.2、TencentOS tiny RTOS队列实践

    关于怎么使用队列,可以参考腾讯物联网终端操作系统开发指南.pdf文档,但该文档的API过老,可能不适合现在的版本,于是找来了一个新版的API,参考网友修改的,以下工程基于多任务例程修改:

    main.c

    #define STK_SIZE_TASK_RECEIVER      512
    #define STK_SIZE_TASK_SENDER        512
    
    #define PRIO_TASK_RECEIVER_HIGHER_PRIO      4
    #define PRIO_TASK_RECEIVER_LOWER_PRIO       (PRIO_TASK_RECEIVER_HIGHER_PRIO + 1)
    
    #define MESSAGE_MAX     10
    
    k_stack_t stack_task_receiver_higher_prio[STK_SIZE_TASK_RECEIVER];
    k_stack_t stack_task_receiver_lower_prio[STK_SIZE_TASK_RECEIVER];
    k_stack_t stack_task_sender[STK_SIZE_TASK_SENDER];
    
    uint8_t msg_pool[MESSAGE_MAX * sizeof(void *)];
    
    k_task_t task_receiver_higher_prio;
    k_task_t task_receiver_lower_prio;
    k_task_t task_sender;
    
    k_msg_q_t msg_q;
    
    void entry_task_receiver_higher_prio(void *arg)
    {
        k_err_t err;
        void *msg_received;
    
        while (K_TRUE)
        {
            err = tos_msg_q_pend(&msg_q, &msg_received, TOS_TIME_FOREVER);
    
            if (err == K_ERR_NONE)
            {
                printf("higher: msg incoming[%s]\n", (char *)msg_received);
            }
        }
    }
    
    void entry_task_receiver_lower_prio(void *arg)
    {
        k_err_t err;
        void *msg_received;
    
        while (K_TRUE)
        {
            err = tos_msg_q_pend(&msg_q, &msg_received, TOS_TIME_FOREVER);
    
            if (err == K_ERR_NONE)
            {
                printf("lower: msg incoming[%s]\n", (char *)msg_received);
            }
        }
    }
    
    void entry_task_sender(void *arg)
    {
        int i = 1;
        char *msg_to_one_receiver = "message for one receiver(with highest priority)";
        char *msg_to_all_receiver = "message for all receivers";
    
        while (K_TRUE)
        {
            if (i == 2)
            {
                printf("sender: send a message to one receiver, and shoud be the highest priority one\n");
                tos_msg_q_post(&msg_q, msg_to_one_receiver);
            }
    
            if (i == 3)
            {
                printf("sender: send a message to all recevier\n");
                tos_msg_q_post_all(&msg_q, msg_to_all_receiver);
            }
    
            if (i == 4)
            {
                printf("sender: send a message to one receiver, and shoud be the highest priority one\n");
                tos_msg_q_post(&msg_q, msg_to_one_receiver);
            }
    
            if (i == 5)
            {
                printf("sender: send a message to all recevier\n");
                tos_msg_q_post_all(&msg_q, msg_to_all_receiver);
            }
    
            tos_task_delay(1000);
            ++i;
        }
    }
    

    main函数实现:

    /**
      * @brief  The application entry point.
      * @retval int
      */
    int main(void)
    {
        /* USER CODE BEGIN 1 */
    
        /* USER CODE END 1 */
    
        /* MCU Configuration--------------------------------------------------------*/
    
        /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
        HAL_Init();
    
        /* USER CODE BEGIN Init */
    
        /* USER CODE END Init */
    
        /* Configure the system clock */
        SystemClock_Config();
    
        /* USER CODE BEGIN SysInit */
    
        /* USER CODE END SysInit */
    
        /* Initialize all configured peripherals */
        MX_GPIO_Init();
        MX_USART2_UART_Init();
        MX_I2C3_Init();
        /* USER CODE BEGIN 2 */
        OLED_Init();
        OLED_Clear();
        OLED_ShowString(0, 0, (uint8_t*)"TencentOS tiny", 16);
        OLED_ShowString(0, 2, (uint8_t*)"Bruce.yang", 16);
        //初始化内核
        osKernelInitialize();
        tos_msg_q_create(&msg_q, msg_pool, MESSAGE_MAX);
        (void)tos_task_create(&task_receiver_higher_prio, "receiver_higher_prio",
                              entry_task_receiver_higher_prio, NULL, PRIO_TASK_RECEIVER_HIGHER_PRIO,
                              stack_task_receiver_higher_prio, STK_SIZE_TASK_RECEIVER, 0);
        (void)tos_task_create(&task_receiver_lower_prio, "receiver_lower_prio",
                              entry_task_receiver_lower_prio, NULL, PRIO_TASK_RECEIVER_LOWER_PRIO,
                              stack_task_receiver_lower_prio, STK_SIZE_TASK_RECEIVER, 0);
        (void)tos_task_create(&task_sender, "sender", entry_task_sender, NULL,
                              4, stack_task_sender, STK_SIZE_TASK_SENDER, 0);
        //启动内核
        osKernelStart();
        /* USER CODE END 2 */
    
        /* Infinite loop */
        /* USER CODE BEGIN WHILE */
        while (1)
        {
            /* USER CODE END WHILE */
    
            /* USER CODE BEGIN 3 */
        }
    
        /* USER CODE END 3 */
    }
    

    编译后下载到EVB_MX+开发板后,运行结果如下:

    3.4.3、总结

    概念性总结:

    • 事件传递不带信息负载,而队列是带信息负载的

    • 队列除了可以告诉我们发生了什么事,还可以告诉我们发生这件事情的详细过程

    使用总结:

    详情请参考腾讯物联网终端操作系统开发指南.pdf文档

    4、总结

    关于TencentOS tiny还有非常多的组件可以学习,这里只是列出了最常用的几种,最后我们给本文做下简短的总结:

    • 多任务

    解决复杂需求、实时性问题。

    • 互斥锁

    解决不可重入,资源的竞争关系。

    • 信号量

    解决任务间同步问题,典型为生产者-消费者的问一体。

    • 事件

    解决任务间同步问题,相比信号量,事件可以传递多个,但不带负载。

    • 队列

    解决任务间传递带负载的问题。

    案例下载

    公众号后台回复:TencentOS tiny即可获取本节所有程序案例及参考文档下载链接。

    全文参考资料

    腾讯物联网终端操作系统SDK文档.pdf

    腾讯物联网终端操作系统开发指南.pdf

    TencentOS tiny技术讲解与开发实践PPT.pdf

    云加社区沙龙(腾讯物联网操作系统TencentOS tiny架构解析与实践).pdf

    公众号粉丝福利时刻

    这里我给大家申请到了福利,本公众号读者购买小熊派开发板可享受9折优惠,有需要购买小熊派以及腾讯物联网开发板的朋友,淘宝搜索即可,跟客服说你是公众号:嵌入式云IOT技术圈 的粉丝,立享9折优惠!

    往期精彩

    网红腾讯物联网开发板终极开箱评测,让我们一睹为快!

    STM32硬核DIY机械键盘|蓝牙USB双模|灯控

    一个超火超给力的STM32开源疫情监控项目

    一个超酷的开源uHand2.0机械手掌项目

    居民身份证阅读器产品开发学习心得(再谈标准-软件-协议)

    觉得本次分享的文章对您有帮助,随手点[在看]并转发分享,也是对我的支持。

    展开全文
  • 关于TencentOS tiny 基础内核实验 本次介绍的是关于TencentOS tiny 基础内核实验 ——hello_world实验 #Tiny EVB 板拿到以后会有两个途径学习 [Tencentos Tiny官网](https://gitee.com/TencentOS/TencentOS-tiny)和...
  • 腾讯Iot操作系统 TencentOS tiny 研究

    千次阅读 2019-11-03 16:28:31
    1 TencentOS tiny 系统简介 1.1 产品特性 腾讯物联网操作系统(TencentOS tiny)是腾讯面向物联网领域开发的实时操作系统,具有低功耗,低资源占用,模块化,可裁剪等特性。 TencentOS tiny 可以有效减少开发人员...
  • 移植前的准备工作 1. 获取STM32的裸机工程模板 STM32的裸机工程模板直接使用野火STM32开发板配套的固件库例程即可...下载TencentOS tiny 源码 TencentOS tiny的源码可从TencentOS tiny GitHub仓库地址https://github...
  • TencentOS tiny 是腾讯面向物联网领域开发的实时操作系统,具有低功耗,低资源占用,模块化,安全可靠等特点,可有效提升物联网终端产品开发效率。TencentOS tiny 提供精简的 RTOS 内核,内核组件可裁剪可配置,可...
  • nios上跑TencentOS Tiny 和 AliOS Things

    千次阅读 2019-10-02 11:31:05
    nios上跑TencentOS Tiny 和 AliOS Things nios上跑TencentOS Tiny 和 AliOS Things 终于实现了nios上跑TencentOS Tiny 和 AliOS Things,在MAX10的开发板上。 方法就是生成一个uCOS的项目,用里面的port.s,基本不用...
  • 我们描述了TencentOS tiny的队列实现,同时也点出了TencentOS tiny的队列是依赖于消息队列的,那么我们今天来看看消息队列的实现。 其实消息队列是TencentOS tiny的一个基础组件,作为队列的底...
  • 本工程使用stm32cubemx生成,并在此基础上移植腾讯TencentOS tiny,在野火挑战者平台上移植并成功运行,使用stm32cubemx将大大节省您的开发时间。
  • 物联网开发——TencentOS Tiny 简介

    千次阅读 2019-09-19 20:54:23
    TencentOS tiny是腾讯面向物联网领域开发的实时操作系统,具有低功耗,低资源占用,模块化,安全可靠等特点,可有效提升物联网终端产品开发效率。TencentOS tiny 提供精简的 RTOS 内核,内核组件可裁剪可配置,可...
  • 物联网终端操作系统 TencentOS Tiny

    千次阅读 2019-09-20 09:25:06
    TencentOS tiny 是腾讯面向物联网领域开发的实时操作系统,具有低功耗,低资源占用,模块化,安全可靠等特点,可有效提升物联网终端产品开发效率。TencentOS tiny 提供精简的 RTOS 内核,内核组件可裁剪可配置,可...
  • 手把手教你将MQTT客户端移植到stm32开发板上,使用TencentOS tiny官方开发板——TencentOS_tiny_EVB_MX_Plus开发板作为移植实验,使用wifi模块连接到云平台。
  • Cortex M23 移植TencentOS tiny准备源码和工具准备硬件、软件移植开始 准备源码和工具 TencentOS tiny的源码地址在这: TencentOS tiny. MDK软件下载在这:MDK5.28 已有MDK请忽略 项目需要的资料我已经上传 M251_...
  • 我们描述了TencentOS tiny的队列实现,同时也点出了TencentOS tiny的队列是依赖于消息队列的,那么我们今天来看看消息队列的实现。 其实消息队列是TencentOS tiny的一个基础组件,作为队列的底层。 所以在tos_config...
  • 9月18日,腾讯宣布开源自主研发的轻量级物联网实时操作系统 TencentOS tiny。据称,TencentOS tiny 的亮点体现在资源占用、设备成本、功耗管理以及安全稳定等层面。TencentOS tiny 整体架构从下到上主要包括:CPU 库...
  • TencentOS tiny内核是单地址空间的可抢占式实时内核,TencentOS tiny内核不提供进程模型,任务对应线程的概念,是最小的调度运行体,也是最小的资源持有单位。 任务的本质是一个拥有独立栈空间的可调度运行实体,...
  • 腾讯物联网操作系统(TencentOS tiny)是腾讯面向物联网领域开发的实时操作系统,具有低功耗,低资源占用,模块化,可裁剪等特性。TencentOS tiny 为物联网终端厂家提供一站式软件解决方案,方便各种物联网设备快速...
  • 前言公司前段时间发起了一个活动,免费给大家提供开发板,让大家基于 TencentOS tiny 采集数据,通过wifi、以太网、LoRaWAN、NB-IoT、2G、4G、BLE、或者网关...
  • TencentOS tiny入门(2) 内核的测试姿势

    千次阅读 2019-10-22 05:20:46
    文章目录1 前言2 TencentOS tiny内核功能3 TencentOS tiny内核测试3.1 C语言单元测试框架greatest简述3.1.1 greatest使用方法3.2 内核自动化测试3.2.1 内核测试用例3.2.1 MDK硬件平台实战3.2.2 MDK软件平台仿真3.2....
  • 国美金融贷款利用TencentOS tiny 实时内核包括任务管理、实时调度、时间管理、中断管理、内存管理、异常处理、软件定时器、链表、消息队列、信号量、互斥锁、事件标志等模块。 国美金融贷款的TencentOS tiny 为了...
  • 导语 |腾讯物联网终端操作系统(TencentOS tiny)是腾讯面向物联网领域自主研发的嵌入式实时操作系统,可助力物联网终端设备及业务快速接入腾讯云物联网平台。本文是对腾讯高级工程...
  • 本次沙龙邀请了多位腾讯技术专家,围绕腾讯开源与众多开发者进行探讨,深度揭秘了腾讯开源项目TencentOS tiny、TubeMQ、KonaJDK、TARS以及MedicalNet。本文是叶丰老师的演讲整理,编辑:涛涛。本文要点: TencentOS...
  • TencentOS tiny开发指南 ——概述

    千次阅读 2019-09-21 12:02:41
    TencentOS tiny是面向物联网(IOT)领域的操作系统,由一个实现精简的实时操作系统(RTOS)内核,以及丰富的物联网组件组成。 1.1 基础内核组件 系统管理 系统管理模块,主要提供了内核的初始化、内核运行启动,...
  • 9月18日,腾讯宣布将开源自主研发的轻量级物联网实时操作系统TencentOS tiny。相比市场上其它系统,腾讯TencentOS tiny在资源占用、设备成本、功耗管...
  • 导语 |近日,云+社区技术沙龙“腾讯开源技术”圆满落幕。本次沙龙邀请了多位腾讯技术专家,围绕腾讯开源与众多开发者进行探讨,...本文要点:TencentOS tiny开源项目简介TencentOS tiny loT解决方案TencentOS tiny...
  • 有的时候想灵活的操作模组进行一些自定义的频点和数据发送操作,这时候编写代码肯定是不方便的...这篇文章将使用 TencentOS tiny 定制开发板直接操作板载E53接口的LoRa模组,通过对其AT命令操作来实现一些自定义操作。
  • TencentOS tiny是一个支持多任务的操作系统,任务可以使用或等待CPU、使用内存空间等系统资源,并独立于其它任务运行,理论上任何数量的任务都可以共享同一个优先级,这样子处于就绪态的多个相同优先级任务将会以...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 497
精华内容 198
关键字:

TencentOSTiny