精华内容
下载资源
问答
  • matter网络基础之—Thread

    千次阅读 2021-07-01 16:35:26
    Thread协议栈支持 IPv6 地址并提供与其他 IP 网络的低成本桥接,Thread协议栈针对低功耗/电池供电的操作和无线设备到设备通信进行了优化。 Thread协议栈为需要基于IP网络互联和家庭和商业应用而设计,并且可以

    matter网络基础之—Thread

    前文我们讲过,matter目前有两个分支,matter over Thread和matter over Wi-Fi。 matter over Thread本质上就是运行在Thread协议上的matter应用层协议。matter over Thread产品需要两个认证:CSA联盟的matter认证和Thread联盟的Thread产品认证。学习Thread协议对我matter产品开发是非常有意义的。

    什么是 Thread?
    Thread是专门为物联网设计的一种短距离、低功耗、支持IPv6的无线网状网络组网协议。Thread协议栈是建立在现有的IEEE和IETF标准集之上的一个开放标准,而不是一个全新的标准。

    Thread协议栈的结构如下图:
    在这里插入图片描述
    Thread协议栈支持 IPv6 地址并提供与其他 IP 网络的低成本桥接,Thread协议栈针对低功耗/电池供电的操作和无线设备到设备通信进行了优化。 Thread协议栈为需要基于IP网络互联和家庭和商业应用而设计,并且可以在堆栈上使用各种应用层。

    Thread协议栈的主要特性包括:
    • 易于部署和维护 — 安装、启动和操作相对简单。产品安装码(Product installation codes)确保经过授权的产品可以加入网络之中。简单的建网和入网协议允许系统自我配置和修复路由错误。
    • 通信安全 — Thread 网络中的设备都必须通过身份验证,并且所有的通信都经过了加密
    • 稳定可靠 — 具有自愈能力的网状网络,无单点故障,并且采用扩频技术以提高抗干扰能力
    • 低功耗 — Thread 低功耗设备可以进入休眠并使用电池供电,通常使用一块电池能工作数年
    • 规模可扩展 — Thread 网络的规模可以扩展达数百个设备

    OpenThread:
    由谷歌发布是的OpenThread的开放源代码实现Thread。谷歌发布OpenThread,旨在让开发者更广泛地使用谷歌 Nest产品中使用的网络技术,以加快互联家庭和商业建筑产品的开发。

    OpenThread为家庭和商业建筑应用定义了一种基于IPv6的,可靠的、安全和低功耗的无线设备到设备通信协议。OpenThread实现了Thread 1.1.1 规格中定义的所有功能以及Thread 1.2 规格的部分功能。

    Thread网络结构:
    全功能Thread设备(Full Thread Device)总是打开它的射频收发器,它订阅所有Router的多播地址,并维护 IPv6 地址映射。FTD 有三种类型:
    路由器, REED–可以升级为Router, 全功能终端设备(Full End Device)–无法升级为 Router

    最小功能Thread设备(Minimal Thread Device)不会订阅多播地址,并且它会将它的所有消息发送给它的父节点。MTD 有两种类型:
    最小功能终端设备(Minimal End Device)–始终打开自身的收发器,无需从父节点中轮询消息
    休眠终端设备(Sleepy End Device)–通常会关闭自身的收发器(睡眠),偶然会打开收发器(唤醒)以从父节点中轮询消息

    Thread家庭网络构架:
    在这里插入图片描述
    Thread设备类型:

    1. 边界路由器:是一种可以在Thread网络和其他网络(Wi-Fi,以太网,蓝牙等)之间转发信息的设备。它还为Thread网络提供服务,包括路由服务和离网服务 (一个 Thread 网络中可以有多个Border Router)。

    2. 领导者(Leader):是一个特殊的Router,在 Thread 网络分区中,Leader管理己经分配了Router ID的注册表,并接受符合升级为路由器条件的REED请求成为路由器。 Leader决定哪些REED应该是路由器,Leader 和网络中的Router一样,也可以有子节点。 Leader 还使用 CoAP分配和管理路由器地址。 Leader 中包含的所有信息都存在于其它Router中。如果Leader出现故障或失去与网络的连接,其它的Router会被推举为Leader,这个过程不需要用户的干预。

    3. 路由器:Thread路由器为网络设备提供路由服务。Thread路由器还为试图加入网络的设备提供加入和安全服务。Thread路由器不能休眠(Sleep),但是可以降级成为REED。

    4. 可以升级为Router的终端设备(Router Eligible End Device):REEDs可以成为Router或Leader,但是不能成为边界路由器。Thread会尝试将 Router 的数量保持在16-23之间。如果一个REED作为End Device加入,并且网络中的Router数量低于 16,那么它将自动升级为 Router。

    5. 终端设备: 终端设备无法升级为 Router。可以是全功能的终端设备(FED)或最小功能的终端设备(MED)。MED不需要和父节点精确的同步通信。

    6. 休眠终端设备(Sleepy end devices):只和自己的父亲路由节点通信的终端设备,不能转发消息给其它设备。

    Thread商业网络构架:
    在这里插入图片描述

    Thread的商业网络通过域和域唯一地址配置。

    1. Thread域(Thread Domain model):域支持多个Thread网络之间或Thread网络和非Thread的IPv6网络之间无缝集成和通信。Thread域的主要优势在于,设备在一定程度上可以灵活地加入公共Thread域中的任何Thread网段,从而在网络规模或数据量扩大时减少了主动网络规划或主动重新配置网络的需要。
    2. 骨干边界路由器(Backbone Border Router):BBR是商业应用范围的一种边界路由器,它促进多个Thread网段中的域同步,并允许在Thread域范围内进出不同Thread网段的多播消息传输。作为大型Thread域的组成部分的Thread网络必须至少有一个主要的骨干边界路由器,可以有多个次要的骨干边界路由器以实现故障安全机制。骨干边界路由器通过骨干链路(Backbone Link)相互通信。
    3. 骨干链路(Backbone Link):由骨干边界路由器连接的非Thread的IPv6链路。骨干边界路由器通过Thread骨干连接协议(TBLP)和其它的骨干边界路由器进行同步。
    4. 域唯一地址(Domain Unique Address):当设备成为Thread域的一部分时,设备的域唯一地址在设备的生命周期内永远不变。这有助于设备在同一个域的不同Thread网络中迁移,并确保各自的骨干边界路由器方便的跨越多个Thread网络路由。

    设备限制:
    单个 Thread 网络所支持的设备类型数量是有限制的。
    在这里插入图片描述
    Thread会尝试将Router的数量保持在16-23 之间。如果一个REED作为End Device 加入,并且网络中的 Router 数量低于16,那么它将自动升级为 Router。

    IPv6地址:
    Thread协议栈的设备支持在RFC4219((https://tools.ietf.org/html/rfc4291)中定义的IPv6地址构架。Thread设备支持唯一的本地地址(ULA-Unique Local Address),域模型中的域唯一地址(DUA-Domain Unique Address),Thread设备根据设备提供的资源支持一个或多个全局单播地址

    IPv6地址的高位64比特代表网络地址,其它的表示网络中的特殊地址。也就是说一个网络中的所有设备拥有相同的N个高比特位。这前面的N个高比特也叫做前缀(Prefix),"/64"表示这是一个具有64比特前缀的地址。加入网络中的设备被分配一个64比特前缀,设备在网络中使终使用这个前缀。前缀也是一个唯一的本地单播地址(https://tools.ietf.org/html/rfc4193: Unique Local IPv6 Unicast Addresses)。Thread网络也许有一个或多个边界路由器,这些边界路由器有些没有用来产生唯一的本地地址或全局单播地址的64比特前缀。这些设备使用它自己的EUI-64地址获取接口标识符–在RFC4944第6章有详细介绍(https://tools.ietf.org/html/rfc4944: Transmission of IPv6 Packets over IEEE 802.15.4 Networks)。这些设备会支持由EUI-64作为接口标识符而配置的本地连接IPv6地址。配置使用RFC4862(https://tools.ietf.org/html/rfc4862: IPv6 Stateless Address Autoconfiguration)中定义的知名的本地连接前缀FE80::0/64

    Thread设备还支持合适的多播地址。包括本地连接的所有节点多播(link-local all node multicast),本地连接的所有路由器多播(link local all router multicast),被请求的节点多播(solicited node multicast),本地网状多播(mesh local multicast)。如果域模型中存在骨干边界路由器,设备还可以支持更大范围的多播地址。

    每一个加入网络的Thread设备会依据IEEE 802.15.4-2006规格分配一个2字节的短地址。对于路由器来说,这个地址是使用地址范围中的高比特位分配的。孩子节点使用父节点的高比特位后再分配合适的低比特位形成自己的地址。这可以保证Thread网络中的其它设备能够很容易的理解孩子节点的路由位置。
    单播(Unicast):
    在一个单个的发送者和一个接受者之间通过网络进行的通信。

    常见的单播类型如下
    在这里插入图片描述
    在这里插入图片描述

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    多播(Multicast):
    多播用于一次将信息传达给多个设备。Thread 网络中保留了特定的地址,以提供给不同分组的设备在多播时使用。
    在这里插入图片描述

    任播(Anycast)
    当目的地的 RLOC 未知时,可以使用任播将数据路由到 Thread 接口。ALOC(Anycast Locator)标识 Thread 分区内多个接口的位置。ALOC 的后 16 位,称为 ALOC16,其格式为 0xfcXX,表示 ALOC 的类型。
    Thread 定义了以下 ALOC16 值
    在这里插入图片描述

    Thread应用层:
    Thread协议栈是负责在Thread网络中不同设备之间传输消息的无线网状网协议。Thread协议栈没有标准化的应用层规范(matter是一个通用的应用层规范,与Thread互补),Thread提供了基本的应用服务。

    1. UDP消息
      UDP提供一个以16位(bit)的端口号和IPv6地址发送消息的方法,UDP比 TCP更简单,并且连接开销更少(例如,UDP 不需要keep-alive消息)。 所以UDP 实现了更快、更高的消息吞吐量,并降低了应用程序的整体功耗。 UDP使用的代码空间比TCP更少,这为应用程序留下了更多可用Flash空间。
    2. 多播消息
      Thread支持广播消息,也就是说Thread可以将相同的消息发给Thread网络中的多个节点。多播以标准的IPv6地址,使用Thread协议栈内置的方法让节点和邻居节点(neighbor nodes),路由节点(Routers)以及整个Thread网络通信。
    3. 应用层使用IP服务
      Thread允许应用层使用UDP和CoAP与因特网进行交互通信。
      在这里插入图片描述

    IP协议栈基础:

    1. CoAP(Constrained Application Protocol)-受限应用协议是一种专门的传输协议,用于资源受限的物联网设备和低功耗网络。CoAP 提供应用程序endpoint之间的请求/应答模型,支持内置的服务和资源发现,并包含互联网的关键概念,例如统一资源定位符URL。 在Thread网络中,CoAP用于配置设备的mesh-local地址和组播地址。 此外,CoAP 还用于管理消息,例如在活跃的Thread路由器上获取和设置诊断信息以及其他网络数据。

    2. DTLS(Datagram Transport Layer Security)即数据包传输层安全性协议。TCP之上的应用可以用TLS来保证安全,但是TLS不能用来保证UDP的安全。Datagram TLS试图在现存的TLS协议架构上提出扩展,使之支持UDP,即成为TLS的一个支持数据报传输的版本。

    3. 距离向量路由协议(distance vector routing protocol)是为小型网络环境设计的。路由协议中的两大分类之一,这类协议采用距离向量(distance-vector,缩写为DV)算法来决定报文交换的路径。

    4. 6LoWPAN(IPv6 Over Low Power Wireless Personal Networks):是一种基于IPv6的低速无线个域网标准,6LoWPAN的主要目标是在IEEE 802.15.4的连接上面传输和接收IPv6数据包,可用于构建无线传感器网络。 在以太网链路中,具有 IPv6 最大传输单元 (MTU)-1280字节大的数据包可以作为一帧通过链路发送。为了适应无线传输的802.15.4帧尺寸,6LoWPAN做了很多折中处理。在802.15.4的网络中,6LoWPAN充当IPv6网络层和802.15.4链路层之间的适配层。 它通过在发送方对IPv6数据包进行分段并在接收方重组来解决传输IPv6 最大传输单元的问题。
      6LoWPAN还提供了一种压缩机制,减少通过无线信号发送的IPv6报头大小,从而减少传输开销。 通过无线信号发送的比特越少,设备消耗的能量就越少。 Thread 充分利用这些机制在 802.15.4 网络上高效传输数据包。RFC 4944 (https://tools.ietf.org/html/rfc4944) 和 RFC 6282 (https://tools.ietf.org/html/rfc6282) 详细的描述了完成报头压缩和报文分割的方法。

    5. ICMPv6: IPv6版本的因特网控制报文协议,在RFC 4443里面定义(https://tools.ietf.org/html/rfc4443)。

    6. UDP: Thread协议栈支持用户数据报文协议,在RFC 768 (https://tools.ietf.org/html/rfc768: User Datagram Protocol)中定义。

    Thread的系统构架:
    在这里插入图片描述
    Spinel 是一种通用管理协议,用于使主机设备能够与协处理器进行通信并对其进行管理。 Spinel 最初旨在支持基于线程的 NCP,现在采用分层方法设计,使其在未来可以轻松适应其他网络技术。它与 RCP 和 NCP 设计一起使用。

    Thread 1.2:
    Thread 1.2 进一步优化可扩展性、能效以及对大规模网络应用程序的支持;进一步增强基本规范,以优化功耗、延迟和节点密度。Thread 1.2 为蓝牙设备提供可选支持,增强其基于 IPv6 的大型多域网络功能并简化调试。

    用蓝牙控制Thread设备:
    蓝牙可以和手机直接连接而无需设置网络,因此可以使用智能手机轻松控制Thread网络。

    Thread 设备,可能配备有“双无线电”,即同时拥有蓝牙和 Thread。双无线电设备可以与蓝牙设备“对话”并成为 Thread网络的一部分,提供 Thread 网络的所有功能,包括使用安全和完全加密的低功耗无线信号在所有连接的智能设备之间自动高效地路由数据。

    另外,智能手机或平板电脑等双无线电设备可以充当互联网的网关,例如为 Thread 网络上的设备下载新的固件更新,或者要快速发送当前所有设备的状态给维护工程师时。
    在这里插入图片描述

    参考资料:
    https://www.threadgroup.org/
    https://openthread.io/
    https://github.com/openthread/openthread
    https://openthread.google.cn/

    CSDN博客仅作为本人工作学习之余的笔记使用,无任何商业目的,如果侵犯了你的隐私或权益,请随时联系作者,本人将及时删除相关内容。

    展开全文
  • 关注+星标公众号,不错过精彩内容作者 | strongerHuang微信公众号|嵌入式专栏目前市面上的开源协议有很多种,比如:GPL、BSD、MIT、Mozilla、Apache 和 ...

    关注+星标公众,不错过精彩内容

    作者 | strongerHuang

    微信公众号 | 嵌入式专栏

    目前市面上的开源协议有很多种,比如:GPL、BSD、MIT、Mozilla、Apache 和 LGPL等。

    选择RTOS,通常会考虑开源、市场占有率、配套资料和例程,以及配套组件等,市面上使用率较多的开源RTOS,这里主要推荐:µC/OS、RT-Thread、FreeRTOS、ThreadX等大家熟悉的RTOS。

    随着µC/OSThreadX的开源,现在供大家选择学习的RTOS越来越多了。

    下面讲讲µC/OS、FreeRTOS、RT-Thread、ThreadX开源协议的具体内容。

    嵌入式专栏

    1

    µC/OS开源许可

    µC/OS使用Apache 2.0开源许可。

    µC及相关组件以允许的开源Apache 2.0许可模式提供,在这种开源模型下,寻求使用组件的开发人员可以免费下载和使用该软件。

    地址:

    https://weston-embedded.com/micrium-licensing

    Apache 协议在为开发人员提供版权及专利许可的同时,允许用户拥有修改代码及再发布的自由。

    嵌入式专栏

    2

    RT-Thread 开源许可

    RT-Thread 遵循 GPL V2 + 开源许可协议。

    RT-Thread 系统完全开源,3.1.0 及以前的版本遵循 GPL V2 + 开源许可协议。从 3.1.0 以后的版本遵循 Apache License 2.0 开源许可协议,可以免费在商业产品中使用,并且不需要公开私有代码。

    地址:

    https://www.rt-thread.org/document/site/tutorial/quick-start/introduction/introduction/

    GPL 开源协议的主要特点:

    嵌入式专栏

    3

    FreeRTOS开源协议

    FreeRTOS使用MIT开源协议。

    包括但不限于以下权利:使用,复制,修改,合并,发布,分发,再许可和/或出售。

    地址:

    https://www.freertos.org/a00114.html

    免费和商业版协议差异:

    嵌入式专栏

    4

    ThreadX开源协议

    ThreadX遵循“简单”的开源协议。

    ThreadX的协议由微软“自定义”,包含的款项比较多,对共享、删除、修改、分发等都有约定。

    地址:

    https://github.com/azure-rtos/threadx/blob/master/LICENSE.txt

    最后:

    开源协议由很多,具体开源协议代表什么含义,可以参看我的之前分享的内容:开源协议是什么?开源等于免费吗?如何选择开源协议?

    ------------ END ------------

    后台回复『RTOS』『嵌入式软件基础知识』阅读更多相关文章。

    欢迎关注我的公众号回复“加群”按规则加入技术交流群,回复“1024”查看更多内容。

    欢迎关注我的视频号:

    点击“阅读原文”查看更多分享,欢迎点分享、收藏、点赞、在看。

    展开全文
  • 在前一篇博文中我们已经介绍了在RT-Thread OS 下实现了IEEE1599/PTP 协议。但是这只是第一步,如何在控制系统中使用这一同步时钟呢?我们来讨论一下这个问题。

            在前一篇博文中我们已经介绍了在RT-Thread OS 下实现了IEEE1599/PTP 协议。但是这只是第一步,如何在控制系统中使用这一同步时钟呢?我们来讨论一下这个问题

    同步时钟源

            实现了本机语主时钟设备同步以后,PTP 硬件将提供一个同步信号出来,它就是PPS(pulse-per-second),提醒的是,不要被它的名称所混淆。它并非一定是个秒信号,它的频率是可编程的。基于Phy 的1588硬件可以输出多路高速(10M)的PPS。但是对于STM32 而言,PPS 速率的最高频率只能是32.768KHz.

     硬件PPS

    通过PPS 控制寄存器 (ETH_MACPPSCR)设置。最高为

    0001:二进制翻转为 2 Hz,数字翻转为 1 Hz。

    0010:二进制翻转为 4 Hz,数字翻转为 2 Hz。

    0011:二进制翻转为 8 Hz,数字翻转为 4 Hz。

    0100:二进制翻转为 16 Hz,数字翻转为 8 Hz。

     .. 1111:二进制翻转为 32.768 KHz,数字翻转为 16.384 KHz

    PPS 是芯片的一个GPIO 输出信号,要使用STM32Cube来配置,STM32H7 是PG8 或者PB5.

    TIM 触发ITR4

            对于应用程序而言,可以通过一个TIM 对PPS 计数,实现内部时钟。STM 在芯片的内部实现了这种机制。 PPS 可以产生ITR4触发信号触发TIM2 或者TIM3(STM32H7)计数。

    软件同步方案

    软件方案如下图所示:

            设置ETH_MAC 产生一个最高频率为32.768的ITR4,TIM2 设置为从模式。在应用程序中通过TIM2 的中断产生一个周期性的中断。最高频率做到30.5us有这个中断程序维持一个软时钟来实现软件组件之间的时间同步。

    虽然30us 的延时有点长,但是对于一般的控制系统来讲也能够满足要求了.

            如果使用DDP83640外部Phy,它包括一个高度可配置的时钟输出信号,其与内置的IEEE 1588时钟谐振。注意到谐振意味着频率相同而相位则不必相同。这个时钟的标称频率是250 MHz的整除结果,例如250 MHz/N,其中N为从2到255的整数。如果e PTP_COC 中写入0x8019 这里的N=0x19 =25,那么可以输出10MHz的同步时钟!当然这需要带有DP83640 PHY 的开发板。只能暂时放一边,

    RT-Thread 实现

            在RT-Thread 中,实现TIM2 计数器。具体步骤如下

    1 开通HWTIMER ,在RT-Thread Studio 在配置。如果没有实现添加,需要在RT-Thread.h 中添加

    #define BSP_USING_HWTIMER

    2 在Board.h 中添加

    #define BSP_USING_TIM

    #ifdef BSP_USING_TIM

     #define BSP_USING_TIM2

    3 使用STM32 配置TIM2PPS 。并且在stm32h7xx_hal_conf.h 中去掉

    #define HAL_TIM_MODULE_ENABLED

    的括号

    4 Drivers/include/config/time_comfig.h 修改为

    #define TIM2_CONFIG                                        \

        {                                                       \

           .tim_handle.Instance     = TIM2,                    \

           .tim_irqn                = TIM2_IRQn,  \

           .name                    = "timer2",                \

    }

    5 art pi 中的 drv_hwtimer.c 替换原来的drv_hwtimer.c

    6 修改drv_hwtimer.c 程序中的init,使TIM2 支持从模式的配置

    static void timer_init(struct rt_hwtimer_device *timer, rt_uint32_t state)
    {
        uint32_t prescaler_value = 0;
        uint32_t pclk1_doubler, pclk2_doubler;
        TIM_HandleTypeDef *tim = RT_NULL;
        TIM_ClockConfigTypeDef sClockSourceConfig = {0};
        TIM_SlaveConfigTypeDef sSlaveConfig = {0};
        struct stm32_hwtimer *tim_device = RT_NULL;
    
        RT_ASSERT(timer != RT_NULL);
        if (state)
        {
            tim = (TIM_HandleTypeDef *)timer->parent.user_data;
            tim_device = (struct stm32_hwtimer *)timer;
            pclkx_doubler_get(&pclk1_doubler, &pclk2_doubler);
            if (tim->Instance == TIM2){
                printf("tim2\n");
            tim->Init.Prescaler = 0;
            tim->Init.CounterMode = TIM_COUNTERMODE_DOWN;
            tim->Init.Period = 8;
            tim->Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
            tim->Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
            if (HAL_TIM_Base_Init(tim) != HAL_OK)
            {
              Error_Handler();
            }
    
            sSlaveConfig.SlaveMode = TIM_SLAVEMODE_EXTERNAL1;
            sSlaveConfig.InputTrigger = TIM_TS_ITR4;
            sSlaveConfig.TriggerPolarity = TIM_TRIGGERPOLARITY_RISING;
              sSlaveConfig.TriggerPrescaler = TIM_TRIGGERPRESCALER_DIV1;
              sSlaveConfig.TriggerFilter = 0x0;                         // 滤波:本例中不需要任何滤波
            if (HAL_TIM_SlaveConfigSynchro(tim, &sSlaveConfig) != HAL_OK)
            {
              Error_Handler();
            }
    
            /* set the TIMx priority */
            HAL_NVIC_SetPriority(tim_device->tim_irqn, 3, 0);
            /* enable the TIMx global Interrupt */
             HAL_NVIC_EnableIRQ(tim_device->tim_irqn);
             /* clear update flag */
             __HAL_TIM_CLEAR_FLAG(tim, TIM_FLAG_UPDATE);
           /* enable update request source */
          __HAL_TIM_URS_ENABLE(tim);
            } else{
    
            /* time init */
            prescaler_value = (uint32_t)(HAL_RCC_GetPCLK1Freq() * pclk1_doubler / 10000) - 1;
            tim->Init.Period            = 10000 - 1;
            tim->Init.Prescaler         = prescaler_value;
            tim->Init.ClockDivision     = TIM_CLOCKDIVISION_DIV1;
            if (timer->info->cntmode == HWTIMER_CNTMODE_UP)
            {
                tim->Init.CounterMode   = TIM_COUNTERMODE_UP;
            }
            else
            {
                tim->Init.CounterMode   = TIM_COUNTERMODE_DOWN;
            }
            tim->Init.RepetitionCounter = 0;
            tim->Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
            if (HAL_TIM_Base_Init(tim) != HAL_OK)
            {
                LOG_E("%s init failed", tim_device->name);
                return;
            }
            else
            {
    
                /* set the TIMx priority */
                HAL_NVIC_SetPriority(tim_device->tim_irqn, 3, 0);
    
                /* enable the TIMx global Interrupt */
                HAL_NVIC_EnableIRQ(tim_device->tim_irqn);
    
                /* clear update flag */
                __HAL_TIM_CLEAR_FLAG(tim, TIM_FLAG_UPDATE);
                /* enable update request source */
                __HAL_TIM_URS_ENABLE(tim);
                LOG_D("%s init success", tim_device->name);
            }
            }
        }
    }
    

    另一处的修改,TIM2 不需要修改prescale ,让它保持为0

    static rt_err_t timer_ctrl(rt_hwtimer_t *timer, rt_uint32_t cmd, void *arg)
    {
        TIM_HandleTypeDef *tim = RT_NULL;
        rt_err_t result = RT_EOK;
        uint32_t pclk1_doubler, pclk2_doubler;
    
        RT_ASSERT(timer != RT_NULL);
        RT_ASSERT(arg != RT_NULL);
    
        tim = (TIM_HandleTypeDef *)timer->parent.user_data;
    
        switch (cmd)
        {
        case HWTIMER_CTRL_FREQ_SET:
        {
            rt_uint32_t freq;
            rt_uint16_t val;
    
            /* set timer frequence */
            freq = *((rt_uint32_t *)arg);
    
            pclkx_doubler_get(&pclk1_doubler, &pclk2_doubler);
            if (tim->Instance != TIM2 ){  //By yao
              val = HAL_RCC_GetPCLK1Freq() * pclk1_doubler / freq;
              __HAL_TIM_SET_PRESCALER(tim, val - 1);
            /* Update frequency value */
            tim->Instance->EGR |= TIM_EVENTSOURCE_UPDATE;
            }
        }
        break;
        default:
        {
            result = -RT_ENOSYS;
        }
        break;
        }
    
        return result;
    }

    7 编译时发现找不到下面这两个文件

    rt_err_t rt_device_hwtimer_register(rt_hwtimer_t *timer, const char *name, void *user_data);

    void rt_device_hwtimer_isr(rt_hwtimer_t *timer);

            在这里卡壳了蛮长的时间,结果发现,在rtthread->components->drivers中没有hwtimer目录。而在art pi 中却是存在的。可是目录中明明有hwtimer 的目录。也许是因为一开始没有选配HWTIMER,然后再RT-Thread.h添加后,不会导入hwtimer 目录了(我觉得这是RT-Thread Studio 的一个BUG! 如果你再后来去点击第一个蓝色的RT-thread Settings 的图标去设置的话,会导致你添加再Application 目录下的应用程序目录被隐藏,删掉了也无法从新添加,烦死人!!)网络上建议点击项目资源管理器边框右上方的向下小箭头中的“过滤器和定制”设置可以解决这个问题。

    8 主程序添加一个hwtimer_sample

    #define HWTIMER_DEV_NAME   "timer2"
    int SoftTimer=4096;
    rt_tick_t last_time,current_time;
    static rt_err_t timeout_cb(rt_device_t dev, rt_size_t size)
    {  SoftTimer--;
    if (SoftTimer==0){
       current_time= rt_tick_get();
        rt_kprintf("tick is :%d(ms)!\n", current_time-last_time);
        last_time=current_time;
        SoftTimer=4096;
    };
        return 0;
    }
    
    static int hwtimer_sample(int argc, char *argv[])
    {
        rt_err_t ret = RT_EOK;
        rt_hwtimerval_t timeout_s;
        rt_device_t hw_dev = RT_NULL;
        rt_hwtimer_mode_t mode;
    
    
        hw_dev = rt_device_find(HWTIMER_DEV_NAME);
        if (hw_dev == RT_NULL)
        {
            rt_kprintf("hwtimer sample run failed! can't find %s device!\n", HWTIMER_DEV_NAME);
            return RT_ERROR;
        }
    
    
        ret = rt_device_open(hw_dev, RT_DEVICE_OFLAG_RDWR);
        if (ret != RT_EOK)
        {
            rt_kprintf("open %s device failed!\n", HWTIMER_DEV_NAME);
            return ret;
        }
    
    
        rt_device_set_rx_indicate(hw_dev, timeout_cb);
    
    
        mode = HWTIMER_MODE_PERIOD;
        ret = rt_device_control(hw_dev, HWTIMER_CTRL_MODE_SET, &mode);
        if (ret != RT_EOK)
        {
            rt_kprintf("set mode failed! ret is :%d\n", ret);
            return ret;
        }
    
    
        timeout_s.sec = 0;
        timeout_s.usec = 8;
    
       if (rt_device_write(hw_dev, 0, &timeout_s, sizeof(timeout_s)) != sizeof(timeout_s))
        {
            rt_kprintf("set timeout value failed\n");
            return RT_ERROR;
        }
    
    
        rt_thread_mdelay(3500);
    
    
        rt_device_read(hw_dev, 0, &timeout_s, sizeof(timeout_s));
        rt_kprintf("Read: Sec = %d, Usec = %d\n", timeout_s.sec, timeout_s.usec);
    
        return ret;
    }
    
    MSH_CMD_EXPORT(hwtimer_sample, hwtimer sample);

    运行 hwtimer_sample 命令时,输出

     显然达到目的了

    实现时间触发网络协议

    有了同步的软件时钟,实现时间触发网络就接近一步了。可以考虑使用PTP SYNC 帧作为时间触发网络的同步帧。我们另文深入探讨

    结束语

          STM32H 能够实现IEEE1588/PTP 协议,唯一的缺点是PPS频率太低了。如果能够输出一个高频信号,比如10MHz 就完美了。

        

    展开全文
  • 1 使用rtt 自带的例程, 自有协议下载固件 添加软件包 ota_downloader , 启动http_ota/ymodem_ota 例程后, 在控制台输入 ymodem_ota , 通过 x-shell 等 支持ymodem 工具, 点击发送, 就可以下载固件到设备上(设备开启 ...

    1 使用rtt 自带的例程,测试下载固件

    添加软件包 ota_downloader , 启动http_ota/ymodem_ota 例程后, 在控制台输入 ymodem_ota ,
    通过 x-shell 等 支持ymodem 工具, 点击发送, 就可以下载固件到设备上(设备开启 rtt bootloader fal 软件包, 并定义好分区信息).

    参考链接: https://www.rt-thread.org/document/site/application-note/system/rtboot/an0028-rtboot/

    但是如果我们需要使用自有协议下载固件, 就需要了解一下下载流程

    2 下载流程

    通过查看源代码, 我们会发现几个关键信息 , 1 接收分区 recv_partition, 2 开始传输回调函数, 3 传输回调函数
    传输流程如下

    在这里插入图片描述

    参考链接: https://blog.csdn.net/lijing198997/article/details/29839505

    值得注意的是, x-shell 是支持发送文件大小的, 部分终端软件不支持发送文件大小

    3 模拟实现流程

    根据上述流程, 我们只需要实现, 开始接收函数, 和数据传输函数即可
    参考提供的源代码
    定义如下几个参数变量
    3.0 变量参数

    static size_t update_file_total_size, update_file_cur_size; // 定义固件的大小, 和已传输的大小
    static const struct fal_partition * dl_part = RT_NULL; // 需要传输到的分区句柄 
    

    , 开始 接收函数需要实现的内容如下
    3.1 , 文件名, 指定文件分区
    3.2 文件大小

    eg : int start_tran(uint8_t *name, uint8_t len)
    {
     1 获取固件名 // 非必须
     file_name = xxx; 
     2 获取固件大小 // 必须
     update_file_total_size = xxx; // 自有协议实现
     3 重置已传输的大小参数// 必须
     update_file_cur_size = 0; 
     4 开启传输标志位/ 信号量// 可选
     5 查找, 判断大小, 和擦除分区
         /* Get download partition information and erase download partition data */
        if ((dl_part = fal_partition_find(recv_partition)) == RT_NULL)
        {
            LOG_E("Firmware download failed! Partition (%s) find error!", recv_partition);
            return 0;
        }
    
        if (update_file_total_size > dl_part->len)
        {
            LOG_E("Firmware is too large! File size (%d), '%s' partition size (%d)", update_file_total_size, recv_partition, dl_part->len);
            return 0;
        }
    
        LOG_I("Start erase. Size (%d)", update_file_total_size);
    
        /* erase DL section */
        if (fal_partition_erase(dl_part, 0, update_file_total_size) < 0)
        {
            LOG_E("Firmware download failed! Partition (%s) erase error!", dl_part->name);
            return 0;
        }
    
    

    数据传输函数内容如下
    3.3 数据本体, 帧头,和校验, 帧头和校验按照自己的通信协议即可

    eg: int data_write(uint8_t *buf,size_t len)
    {
    1 获取数据本体内容
        /* write data of application to DL partition  */
        if (fal_partition_write(dl_part, update_file_cur_size, buf, len) < 0)
        {
            LOG_E("Firmware download failed! Partition (%s) write data error!", dl_part->name);
            return RYM_CODE_CAN;
        }
    
        update_file_cur_size += len;
    }
    

    在完成上述操作后, 固件就可以按照自有协议传输, 传输完成后, 再自行定义一个传输完成的标志, 然后进入重启状态, boot 会根据下载分区的数据内容, 自行搬运固件到程序区

         复位重启
            /* wait some time for terminal response finish */
            rt_thread_delay(rt_tick_from_millisecond(200));
    
            /* Reset the device, Start new firmware */
            extern void rt_hw_cpu_reset(void);
            rt_hw_cpu_reset();
            /* wait some time for terminal response finish */
            rt_thread_delay(rt_tick_from_millisecond(200));
    

    以上参考的源代码, 均可在rtt 官网上提供的软件包可以找到

    展开全文
  • IEEE1588/PTP协议对于实时通信非常重要。可惜RT-Thread OS 没有支持IEEE1588/PTP 协议。尝试做一个。貌似简单,其实不易
  • 教程更新中:ThreadX USBX协议栈教程更新记录贴,前5章发布(2021-10-11) - uCOS & uCGUI & emWin & embOS & TouchGFX & ThreadX - 硬汉嵌入式论坛 - Powered by Discuz!...tid=108546 ...
  • 第5章 ThreadX NetXDUO网络协议栈介绍 本章节介绍 ThreadX NetXDUO网络协议栈,让大家对NetXDUO有一个整体的了解。 5.1 初学者重要提示 5.2 Express Logic公司介绍 5.3 ThreadX NetXDUO简介 5.4 ThreadX ...
  • 教程更新中:ThreadX USBX协议栈教程更新记录贴,前5章发布(2021-10-11) - uCOS & uCGUI & emWin & embOS & TouchGFX & ThreadX - 硬汉嵌入式论坛 - Powered by Discuz!...tid=108546 ...
  • 1.使用RT-Thread Studio写TCP传输程序时用stm32f407+lan8720做TCP客户端,PC机做TCP服务器传输数据。 发现: 客户端和服务器正常连接时拔掉网线打印link down,可以检测到网线被拔掉了。 运行过程中断开TCP...
  • matter协议

    千次阅读 2021-09-21 12:19:28
    其中Thread是专门为物联网设计的一种短距离、低功耗、支持IPv6的无线网状网络组网协议。以实现设备间的互操作性架构目标,Matter规范设备和控制器(基于 IPv6的网络(Thread或Wi-Fi))的应用层。 应用层可以...
  • 教程更新中:ThreadX USBX协议栈教程更新记录贴,前5章发布(2021-10-11) - uCOS & uCGUI & emWin & embOS & TouchGFX & ThreadX - 硬汉嵌入式论坛 - Powered by Discuz!...tid=108546 ...
  • 从事Zigbee行业的应该都知道今年Zgibee联盟已经改名为CSA联盟,并推出一个全新的,定位于解决IOT碎片化的统一协议,即Matter协议。 Matter协议的由来: Matter协议的前身CHIP(Connected Home Over IP),该CHIP...
  • 第6章 ThreadX NetXDUO网络协议栈移植到STM32H7 本章教程为大家讲解NetXDUO的移植。 目录 第6章 ThreadX NetXDUO网络协议栈移植到STM32H7 6.1 初学者重要提示 6.2 第1步,准备一个工程模板 6.3 第2步,添加...
  • 参与开源项目贡献,或者使用开源项目的代码,一定要注意查看项目所遵循的开源许可协议,许可协议决定你贡献的代码将被如何规范的使用,也决定你要如何规范的使用开源项目的代码。目前世界上的开源许可证...
  • RT-Thread的网络协议栈基于lwip,TCP、UDP等网络功能,可以快捷的搭建并验证 RT-Thread有libmodbus软件包,可以实现Modbus主从机功能。 本次目标是实现Modbus-TCP从机,也就是TCP服务端。 准备 NUCLEO-F767ZI ...
  • C++ thread函数使用

    2021-05-21 03:57:20
    #include #include using namespace std;int shared_value = 0;void change_value (int n){for (int i = 0; i < n;...}}int main (){thread t[100];for (int i = 0; i < 100; i++){t[i] = t...
  • RTThread uart注册与安装

    2021-05-11 20:37:37
    /* 设备句柄 */ static char str[] = "hello RT-Thread2!\r\n"; /* 需要发送的数据 */ static int uart2_sample(void) { rt_err_t ret2 = RT_EOK; rt_size_t send_len = 0; /* 查找系统中的串口设备 */ serial2 =...
  • Dubbo协议一览

    2021-04-18 11:52:01
    Dubbo协议一览Dubbo协议报文关于全局请求id 在Dubbo里头,对多个协议进行了支持。如:DubboProtocol、GRpcProtocol、RmiProtocol、HessianProtocol、HttpProtocol、WebService、ThriftProtocol等多种协议。本文...
  • 教程更新中:ThreadX USBX协议栈教程更新记录贴,前5章发布(2021-10-11) - uCOS & uCGUI & emWin & embOS & TouchGFX & ThreadX - 硬汉嵌入式论坛 - Powered by Discuz!...tid=108546 ...
  • nrf52空中升级

    2021-12-08 20:54:35
    更多Settings信息 协议栈:升级包的时候回用到它的版本号,可在通过命令行的命令(nrfutil pkg generate --help)查看、在线文档、官方论坛搜索,也可以在SDK的协议栈版本的doc信息中查看(SDK\components\softdevice\s...
  • 第5章 ThreadX NetXDUO网络协议栈介绍 本章节介绍 ThreadX NetXDUO网络协议栈,让大家对NetXDUO有一个整体的了解。 目录 第5章 ThreadX NetXDUO网络协议栈介绍 5.1 初学者重要提示 5.2 Express Logic公司介绍 ...
  • 1.前言 RT-Thread这一个操作系统获得很多工程师的...主要要用的有两个一个是RT-Thread Studio,这个是IDE,另外一个是RT-Thread env 工具,用于图形化进行配置,然后还有一个RT-Thread本身,也就是MCU用的操作系统 ..
  • 本文由RT-Thread论坛用户@出出啊原创发布:https://club.rt-thread.org/ask/article/3011.html 前言 很久之前就开始整理下面的优化项列表了,但是有很多问题研究不深,一时不敢冒失推出。 前不久,有人在论坛上提问...
  • 实时游戏,在异步IO机制引入之前,常常是面对海量客户端连接的策略 LoT物联网,谷歌提出的Thread协议就是基于UDP的 移动通信领域,比如4G移动网络 6. 问题总结 6.1 怎样才算一个连接? 是为了在客户端和服务端维护...
  • UDP 是User Datagram Protocol的简称, 中文名是用户数据报协议,是OSI(Open System Interconnection,开放式系统互联) 参考模型中一种无连接的传输层协议,提供面向事务的简单不可靠信息传送服务,IETF RFC 768是...
  • 初识matter(Connected Home over IP)协议

    千次阅读 2021-06-17 12:26:36
    Matter是 CSA连接标准联盟(原Zigbee 联盟)新推出的一个应用层协议。是一种新的、基于IP的连接标准,Matter的商标所有权是隶属于CSA联盟的。 Matter原来叫Connected Home over IP (CHIP)项目,2021年5月12日正式更名...
  • 教程更新中:ThreadX USBX协议栈教程更新记录贴,前5章发布(2021-10-11) - uCOS & uCGUI & emWin & embOS & TouchGFX & ThreadX - 硬汉嵌入式论坛 - Powered by Discuz!...tid=108546 ...
  • 本章节介绍 ThreadX 操作系统,让大家对 ThreadX 有一个整体的了解。 目录 第3章 ThreadX操作系统介绍 3.1 初学者重要提示 3.2 Express Logic公司介绍 3.2.1 FileX文件系统 3.2.2 NetX网络协议栈 3.2.3 USBX...
  • 项目信息项目名称:龙芯2K上的RT-Thread系统学生姓名:李志锐学校:聊城大学方案描述:该项目要求首先实现RT-Thread项目到龙芯2K平台上的MMU移植,并实现GMAC及SATA...
  • RT-Thread是一个嵌入式实时多线程操作系统,系统完全开源,它不仅仅是一个实时内核,还具备丰富的中间层组件,包括如文件系统、图形库等较为完整的中间件组件,具备低功耗、安全、通信协议支持和云端连接能力的软件...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 156,524
精华内容 62,609
关键字:

thread协议