谷动谷力

 找回密码
 立即注册
查看: 1274|回复: 0
打印 上一主题 下一主题
收起左侧

灵动微课堂 |使用MM32F3270基于Azure RTOS信号量的应用

[复制链接]
跳转到指定楼层
楼主
发表于 2022-12-15 23:46:18 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
灵动微课堂 |使用MM32F3270基于Azure RTOS信号量的应用


简 介
Azure RTOS ThreadX 是 Microsoft 提供的高级工业级实时操作系统 (RTOS)。它是专门为深度嵌入式实时 IoT 应用程序设计的。Azure RTOS ThreadX 提供高级计划、通信、同步、计时器、内存管理和中断管理功能。此外,Azure RTOS ThreadX 具有许多高级功能,包括 picokernel™ 体系结构、preemption-threshold™ 计划、event-chaining™、执行分析、性能指标和系统事件跟踪。Azure RTOS ThreadX 非常易于使用,适用于要求极其苛刻的嵌入式应用程序。Azure RTOS ThreadX 在各种产品(包括消费者设备、医疗电子设备和工业控制设备)上的部署次数已达数十亿次。
具体的介绍和用户指南可以参考:
https://docs.microsoft.com/zh-cn/azure/rtos/threadx/
在前文描述移植基本内核的基础上,该应用手册描述了如何基于MM32F3270系列MCU结合Azure RTOS ThreadX应用Counting Semaphores的使用,引导用户理解Azure RTOS ThreadX信号量功能。
表 1 适用系列型号
系列
芯片型号
开发板
MM32F3270
MM32F3273G9P
EVB-F3270

1
移植应用的准备
1.1  硬件开发板的准备
该移植过程中应用的开发板为MM32的EVB-F3270,板载MM32F3273G9P。
EVB-F3270 (MM32F3273G9P) 的简要参数:
Arm Cortex-M3 内核
板载 MM32F3273G9P(LQFP144)
USB Host / Device、SPI、I2C
4 x Key、4 x LED
I2S Speaker
TF-Card
Ethernet PHY

1.2  软件的准备
库函数和例程(Lib Samples)
该移植过程中应用的 Firmware 分别为 MM32F3270 库函数和例程,下载地址:
https://www.mindmotion.com.cn/products/mm32mcu/mm32f/mm32f_mainstream/mm32f3270/
Azure RTOS ThreadX(源码)
ThreadX 的源代码已经开放,我们可以从 ThreadX 公共源代码存储库获取 Azure RTOS ThreadX,网址为:
https://github.com/azure-rtos/threadx/
具体的商用使用条件参考Azure的许可证说明:
https://www.microsoft.com/en-us/legal/intellectualproperty/tech-licensing/programs?msclkid=f7ab4ff3afa011ec90a79366a52034fa&activetab=pivot1:primaryr11
Microsoft publishes the Azure RTOS source code to GitHub. No license is required to install and use the software for internal development, testing, and evaluation purposes. A license is required to distribute or sell components and devices unless using Azure RTOS licensed hardware.
Azure RTOS 何时需要许可证?
Microsoft 将 Azure RTOS 源代码发布到 GitHub。安装和使用该软件进行内部开发、测试和评估无需许可证。分发或销售组件和设备需要许可证,除非使用 Azure RTOS 许可的硬件。
ThreadX 安装
可以通过将 GitHub 存储库克隆到本地计算机来安装 ThreadX。下面是用于在 PC 上创建 ThreadX 存储库的克隆的典型语法。
shell复制
或者,也可以使用 GitHub 主页上的“下载”按钮来下载存储库的副本。
下载后的仓库代码目录列表如下:
Azure RTOS ThreadX(源码)支持的开发环境
ThreadX 内核提供好了各种主流硬件平台和软件平台的移植文件,以Cortex_M3为例,可以支持以下六种开发环境:
本次移植过程使用Azure RTOS原有的sample_threadx.c文件为例,稍作修改,演示信号量的功能与应用。
2
Threadx 信号量的应用
该章节介绍信号量的相关知识,演示程序可在MM32F3273G9P的EVB-F3270上运行。
此示例在文件 main_semaphore_demo.c 中实现,旨在说明如何在嵌入式多线程环境中使用信号量,实现任务之间的同步和资源共享机制。
2.1  信号量
2.1.1  统计信号量
ThreadX 提供 32 位计数信号灯,其值范围在 0 到 4,294,967,295 之间。计数信号灯有两个操作:tx_semaphore_get 和 tx_semaphore_put 。执行获取操作会将信号灯数量减一,如果信号灯为 0,获取操作不会成功。获取操作的逆操作是放置操作,该操作会将信号灯数量加一。
每个计数信号灯都是一个公用资源,ThreadX 对如何使用计数信号灯没有任何限制。
计数信号灯通常用于互相排斥,也可将计数信号灯用作事件通知的方法。
2.1.2  互相排斥
互相排斥用于控制线程对某些应用程序区域(也称为关键部分或应用程序资源)的访问 。将信号灯用于互相排斥时,信号灯的“当前计数”表示允许访问的线程总数。在大多数情况下,用于互相排斥的计数信号灯的初始值为 1,这意味着每次只有一个线程可以访问关联的资源。只有 0 或 1 值的计数信号灯通常称为二进制信号灯。
如果使用二进制信号灯,用户必须阻止同一个线程对其已拥有的信号灯执行获取操作。第二个获取操作将失败,并且可能导致调用线程无限期挂起和资源永久不可用。
2.1.3  事件通知
还可以采用生成者-使用者的方式,将计数信号灯用作事件通知。使用者尝试获取计数信号灯,而生成者则在有可用的信息时增加信号灯。此类信号灯的初始值通常为 0,此值不会在生成者为使用者准备好信息之前增加。用于事件通知的信号灯也可能从使用 tx_semaphore_ceiling_put 服务调用中获益。此服务确保信号灯计数值永远不会超过调用中提供的值。
2.1.4  创建计数信号灯
计数信号灯由应用程序线程在初始化期间或运行时创建。信号灯的初始计数在创建过程中指定。应用程序中计数信号灯的数量没有限制。
2.1.5  线程挂起
尝试对当前计数为 0 的信号灯执行获取操作时,应用程序线程可能会挂起。
执行放置操作后,才会执行挂起线程的获取操作并恢复该线程。如果同一计数信号灯上挂起多个线程,这些线程将按照挂起的顺序 (FIFO) 恢复。
不过,如果应用程序在取消线程挂起的信号灯放置调用之前调用 tx_semaphore_prioritize,还可以恢复优先级。信号灯设置优先级服务将优先级最高的线程放于挂起列表的前面,同时让所有其他挂起的线程采用相同的 FIFO 顺序。
2.1.6  信号灯放置通知
某些应用程序可能会发现,在放置信号灯时收到通知十分有利。ThreadX 通过 tx_semaphore_put_notify 服务提供此功能。此服务将提供的应用程序通知函数注册到指定的信号灯。只要放置了信号灯,ThreadX 就会调用此应用程序通知函数。应用程序通知函数内的确切处理由应用程序决定;但这通常包括恢复相应的线程以处理新信号灯放置事件。
2.1.7  运行时信号灯性能信息
ThreadX 提供可选的运行时信号灯性能信息。如果 ThreadX 库和应用程序是在定义 TX_SEMAPHORE_ENABLE_PERFORMANCE_INFO 的情况下生成的,ThreadX 会累积以下信息。
整个系统的总数:
信号灯放置数
信号灯获取数
信号灯获取挂起数
信号灯获取超时数
每个信号灯的总数:
信号灯放置数
信号灯获取数
信号灯获取挂起数
信号灯获取超时数
此信息在运行时通过tx_semaphore_performance_info_get和 tx_semaphore_performance_system_info_get 服务提供。信号灯性能信息在确定应用程序是否正常运行时非常有用。此信息对于优化应用程序也很有用。例如,“信号灯获取超时数”相对较高可能表明其他线程占用资源的时间太长。

2.2  Azure Threadx 信号量的相关函数
tx_semaphore_create 创建计数信号灯UINT tx_semaphore_create(
    TX_SEMAPHORE *semaphore_ptr,
    CHAR *name_ptr,
    ULONG initial_count);

函数说明
此服务创建用于线程间同步的计数信号灯。初始信号灯计数指定为输入参数。
参数
semaphore_ptr:指向信号灯控制块的指针。
name_ptr:指向信号灯名称的指针。
initial_count:指定此信号灯的初始计数。合法值的范围为 0x00000000 至 0xFFFFFFFF。
返回值
TX_SUCCESS:(0X00) 成功创建信号灯。
TX_SEMAPHORE_ERROR:(0x0C) 信号灯指针无效。指针为 NULL 或已创建信号灯。
NX_CALLER_ERROR:(0x13) 此服务的调用方无效。
示例
TX_SEMAPHORE my_semaphore;
UINT status;

/* Create a counting semaphore whose initial value is 1.
This is typically the technique used to make a binary
semaphore. Binary semaphores are used to provide
protection over a common resource. */
status = tx_semaphore_create(&my_semaphore,
    "my_semaphore_name", 1);

/* If status equals TX_SUCCESS, my_semaphore is ready for
use. */

另请参阅
tx_semaphore_ceiling_put
tx_semaphore_delete
tx_semaphore_get
tx_semaphore_info_get
tx_semaphore_performance_info_get
tx_semaphore_performance_system_info_get
tx_semaphore_prioritize
tx_semaphore_put
tx_semaphore_put_notify
具体函数的中文说明可以参考:
https://docs.microsoft.com/zh-cn/azure/rtos/threadx/chapter4
具体函数的英文说明可以参考:
https://docs.microsoft.com/en-us/azure/rtos/threadx/threadx-smp/chapter4

2.3  信号量的应用演示
2.3.1  工程目录的建立
打开目标工程文件夹“MM32F3270Project”:
移除原有样例.c 文件sample_threadx.c:
参考sample_threadx.c建立main_semaphore_demo.c文件,并添加hardware目录中的led.c、key.c到工程项目中。
注意:
需要在delay.c中配置USE_SYSTICK_DELAY 为 0。
#define USE_SYSTICK_DELAY 0

3
Threadx 的信号量应用
创建如下几个任务:
LED1闪烁指示当前系统运行。
K2键按下,发送信号量同步信号。
任务接收到消息后,串口打印。

3.1  代码实现
下载调试默认会运行到main()函数,如下为全部实现的代码。
Demo演示代码
/* This is a small demo of the high-performance ThreadX kernel.  It includes examples of six
   threads of different priorities, using a message queue, semaphore, and an event flags group.  */

#include "tx_api.h"
#include "delay.h"
#include "led.h"
#include "key.h"
#include "uart.h"


#define DEMO_STACK_SIZE         1024

#define THREAD0_PRIORITY 1
#define THREAD0_PREEMPTION_THRESHOLD 1
#define THREAD1_PRIORITY 2
#define THREAD1_PREEMPTION_THRESHOLD 2

#define THREAD5_PRIORITY 4
#define THREAD5_PREEMPTION_THRESHOLD 4



//#define THREAD5_PREEMPTION_THRESHOLD_NEW 0


/* Define the ThreadX object control blocks...  */
TX_THREAD               thread_0;
TX_THREAD               thread_1;

TX_THREAD               thread_5;

TX_SEMAPHORE Semaphore;

/* Define the counters used in the demo application...  */
ULONG                   thread_0_counter;
ULONG                   thread_1_counter;

ULONG                   thread_5_counter;


/* Define the thread stacks.  */
UCHAR                   thread_0_stack[DEMO_STACK_SIZE];
UCHAR                   thread_1_stack[DEMO_STACK_SIZE];

UCHAR                   thread_5_stack[DEMO_STACK_SIZE];

/* Define thread prototypes.  */

void    thread_0_entry(ULONG thread_input);
void    thread_1_entry(ULONG thread_input);

void    thread_5_entry(ULONG thread_input);


volatile unsigned int bootloop;

/* Define main entry point.  */



int main()
{
    DELAY_Init();//can not use systick
    LED_Init();
    KEY_Init();
    CONSOLE_Init(115200);
    printf("!!! Start !!!\r\n");

    /* Enter the ThreadX kernel.  */
    tx_kernel_enter();
}


/* Define what the initial system looks like.  */

void tx_application_define(void* first_unused_memory)
{
        /* Create thread 0.  */
        tx_thread_create(
        &thread_0,
        "thread 0",
        thread_0_entry,
        0,
        thread_0_stack,
        DEMO_STACK_SIZE,
        THREAD0_PRIORITY,
        THREAD0_PREEMPTION_THRESHOLD,
        TX_NO_TIME_SLICE,
        TX_AUTO_START);

        /* Create thread 1.  */
        tx_thread_create(
        &thread_1,
        "thread 1",
        thread_1_entry,
        0,
        thread_1_stack,
        DEMO_STACK_SIZE,
        THREAD1_PRIORITY,
        THREAD1_PREEMPTION_THRESHOLD,
        TX_NO_TIME_SLICE,
        TX_AUTO_START);


        /* Create thread 5. */
        tx_thread_create(
        &thread_5,
        "thread 5",
        thread_5_entry,
        5,
        thread_5_stack,
        DEMO_STACK_SIZE,
        THREAD5_PRIORITY,
        THREAD5_PREEMPTION_THRESHOLD,
        TX_NO_TIME_SLICE,
        TX_AUTO_START);

        /* Create a semaphore for signal synchronization */
        tx_semaphore_create(&Semaphore, "Semaphore", 0);

}


/* Define the test threads.  */

void thread_0_entry(ULONG thread_input)
{
    /* This thread simply controls LED flashing to indicate that the system is running  */
    while(1)
    {
        /* Increment the thread counter.  */
        thread_0_counter++;

        LED1_TOGGLE();

        /* Sleep for 200 ticks.  */
        tx_thread_sleep(200);

    }
}

void thread_1_entry(ULONG thread_input)
{
        UINT status;
        /* This thread simply successfully receives the semaphore and starts to print information  */   
    while(1)
    {
        /* Increment the thread counter.  */
        thread_1_counter++;               
        status = tx_semaphore_get(&Semaphore, TX_WAIT_FOREVER);
        if(status == TX_SUCCESS)
        {
        /* Receive the semaphore */
            printf("Synchronization semaphore received\r\n");
        }            
    }
}


void thread_5_entry(ULONG thread_input)
{  
    UCHAR t = 0;
    /* This thread simply scan button is pressed to send the semaphore.  */
    while(1)
    {   
        /* Increment the thread counter.  */
        thread_5_counter++;

        t = KEY_Scan(0);
        if(KEY1_PRES == t)
                {
            LED1_TOGGLE();
        }
        else if(KEY2_PRES == t) {
            LED2_TOGGLE();
            /* K2 is pressed to send a semaphore */
            tx_semaphore_put(&Semaphore);   
        }
        else if(KEY3_PRES == t) {
            LED3_TOGGLE();
        }
        else if(KEY4_PRES == t) {
            LED4_TOGGLE();
        }
        else {
            tx_thread_sleep(10);
        }
    }
}

3.2  下载与调试
运行程序,板载LED1闪烁。观察串口调试助手,按下K2键,串口打印信息:
创建信号量初始值为 0,用于信号同步。任务5执行按键扫描,当K2按下时通过tx_semaphore_put发送信号量,对计数值执行加1操作。任务1通过tx_semaphore_get用于信号量接收,对计数值执行减1操作,实际运行情况是K2键每按下一次,串口打印一条信息,Demo演示成功。

4
小结
Azure RTOS 使用信号量能够方便地实现任务之间的同步和资源共享机制,结合MM32F3270的强大性能,可以实现Azure RTOS广泛的应用场景。


+10
回复

使用道具 举报

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

本版积分规则

QQ|Archiver|手机版|深圳市光明谷科技有限公司|光明谷商城|Sunshine Silicon Corpporation ( 粤ICP备14060730号|Sitemap

GMT+8, 2024-5-6 12:19 , Processed in 0.081598 second(s), 43 queries .

Powered by Discuz! X3.2 Licensed

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表