dql2016 发表于 2023-10-29 18:13

【NUCLEO-H743ZI】8、stm32cubemx创建threadx工程体验

<p>ThreadX应该是目前最牛逼的开源RTOS之一了,开源链接:<a href="https://github.com/azure-rtos/threadx" target="_blank">https://github.com/azure-rtos/threadx</a>有了微软大厂的支持,发展前景比其它小众RTOS广阔,官方介绍<a href="https://learn.microsoft.com/zh-cn/azure/rtos/threadx/chapter1" target="_blank">https://learn.microsoft.com/zh-cn/azure/rtos/threadx/chapter1</a></p>

<p>STM32现在新出的芯片如U5就提供了ThreadX 内核、文件系统、图形库、USB协议栈、网络协议栈、加解密等全家桶的支持包,其它各个系列陆续支持ThreadX全家桶了,使用ThreadX全家桶相比之前开源大杂烩的方式更加方便,</p>

<div style="text-align: center;"></div>

<p>在STM32CubeMX中可以一键添加ThreadX的支持。STM32适配版开源链接:<a href="https://github.com/STMicroelectronics/x-cube-azrtos-h7" target="_blank">https://github.com/STMicroelectronics/x-cube-azrtos-h7</a></p>

<p>STM32官方对threadx的说明:<a href="https://wiki.stmicroelectronics.cn/stm32mcu/wiki/Introduction_to_THREADX" target="_blank">https://wiki.stmicroelectronics.cn/stm32mcu/wiki/Introduction_to_THREADX</a></p>

<p>摘自官方的介绍:</p>

<p>Azure RTOS ThreadX 是专门为嵌入式应用程序设计的高性能实时内核。&nbsp;</p>

<h2 id="threadx-unique-features">ThreadX 的独特功能</h2>

<p>与其他实时内核不同,ThreadX 功能多样。通过使用强大的 CISC、RISC 和 DSP 处理器的应用程序,可以轻松地在基于小型微控制器的应用程序之间扩展。</p>

<p>ThreadX 可基于其基础体系结构进行扩展。 因为 ThreadX 服务是作为 C 库实现的,所以只有应用程序实际使用的那些服务被引入了运行时映像。 因此,ThreadX 的实际大小完全由应用程序决定。 对于大多数应用程序,ThreadX 的指令映像的大小在 2 KB 至 15 KB 之间。</p>

<h3 id="picokernel-architecture">picokernel&trade; 体系结构</h3>

<p>ThreadX 服务没有像传统的微内核体系结构那样将内核函数相互层叠,而是直接将其插入核心。 由此产生了最快的上下文切换和服务呼叫性能。 我们将此非分层设计称为 picokernel 体系结构。</p>

<h3 id="ansi-c-source-code">ANSI C 源代码</h3>

<p>ThreadX 主要是在 ANSI C 中编写的。用户需要少量的汇编语言来定制内核,从而满足基础目标处理器的需求。 此设计使用户可以在很短的时间内(通常在几周内)将 ThreadX 移植到新的处理器系列!</p>

<h3 id="advanced-technology">高级技术</h3>

<p>下面是 ThreadX 高级技术的亮点。</p>

<ul>
        <li>简单的 picokernel 体系结构</li>
        <li>自动扩展(占用空间少)</li>
        <li>确定性处理</li>
        <li>快速实时性能</li>
        <li>抢先式和协作式计划</li>
        <li>灵活的线程优先级支持</li>
        <li>动态系统对象创建</li>
        <li>无限量的系统对象</li>
        <li>经过优化的中断处理</li>
        <li>抢占阈值 (Preemption-threshold&trade;)</li>
        <li>优先级继承</li>
        <li>事件链接 (Event-chaining&trade;)</li>
        <li>快速软件计时器</li>
        <li>运行时内存管理</li>
        <li>运行时性能监视</li>
        <li>运行时堆栈分析</li>
        <li>内置系统跟踪</li>
        <li>广泛的处理器支持</li>
        <li>广泛的开发工具支持</li>
        <li>字节顺序完全中性</li>
</ul>

<p>在之前配置好的工程基础上修改,首先在第三方软件包选项卡开启ThreadX支持,只勾选内核特性:</p>

<div style="text-align: center;"></div>

<p>然后就会看到ThreadX软件包了,修改ThreadX的内存池大小为10240,这是线程可以申请到的最大内存;勾选生成初始化代码,这样会创建一个默认线程:</p>

<div style="text-align: center;"></div>

<p><strong>将时钟节拍TX_TIMER_TICKS_PER_SECOND改为1000,即</strong>系统调度周期是<strong>1ms。</strong></p>

<div style="text-align: center;"></div>

<p>修改裸机的Timebase Source为TIM6,因为Systick被RTOS占用了,HAL库里面需要用到这个时钟。</p>

<div style="text-align: center;"></div>

<p>&nbsp;</p>

<p>生成的代码结构如下:</p>

<div style="text-align: center;"></div>

<p>在app_threadx.c中添加3个测试线程:分别是控制2个LED闪烁和串口打印数据</p>

<pre>
<code class="language-cpp">/* USER CODE BEGIN Header */
/**
******************************************************************************
* @File app_threadx.c
* @author MCD Application Team
* @brief ThreadX applicative file
******************************************************************************
* @attention *
* Copyright (c) 2020-2021 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */

/* Includes ------------------------------------------------------------------*/
#include "app_threadx.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */

#include "main.h"
#include "spi.h"
#include "usart.h"
#include "gpio.h"

/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */

/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/
TX_THREAD tx_app_thread;
/* USER CODE BEGIN PV */

TX_THREAD tx_app_thread2;
#defineAPP_CFG_TASK_USER_IF_STK_SIZE                  4096u
staticuint64_t    AppTaskStatStk;

TX_THREAD tx_app_thread3;
#defineAPP_CFG_TASK_USER2_STK_SIZE                  4096u
staticuint64_t    App2TaskStatStk;

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
/* USER CODE BEGIN PFP */

/* USER CODE END PFP */

/**
* @briefApplication ThreadX Initialization.
* @param memory_ptr: memory pointer
* @retval int
*/
UINT App_ThreadX_Init(VOID *memory_ptr)
{
UINT ret = TX_SUCCESS;
TX_BYTE_POOL *byte_pool = (TX_BYTE_POOL*)memory_ptr;
/* USER CODE BEGIN App_ThreadX_MEM_POOL */

/* USER CODE END App_ThreadX_MEM_POOL */
CHAR *pointer;

/* Allocate the stack for tx app thread*/
if (tx_byte_allocate(byte_pool, (VOID**) &amp;pointer,
                     TX_APP_STACK_SIZE, TX_NO_WAIT) != TX_SUCCESS)
{
    return TX_POOL_ERROR;
}
/* Create tx app thread.*/
if (tx_thread_create(&amp;tx_app_thread, "tx app thread", tx_app_thread_entry, 0, pointer,
                     TX_APP_STACK_SIZE, TX_APP_THREAD_PRIO, TX_APP_THREAD_PREEMPTION_THRESHOLD,
                     TX_APP_THREAD_TIME_SLICE, TX_APP_THREAD_AUTO_START) != TX_SUCCESS)
{
    return TX_THREAD_ERROR;
}

/* USER CODE BEGIN App_ThreadX_Init */

    if (tx_thread_create(&amp;tx_app_thread2,
    "tx2 app thread",
    tx_app_thread_entry2,
    0,
    &amp;AppTaskStatStk,                  
    APP_CFG_TASK_USER_IF_STK_SIZE,
    TX_APP_THREAD_PRIO+1,
    TX_APP_THREAD_PREEMPTION_THRESHOLD,                     
    TX_APP_THREAD_TIME_SLICE,
    TX_APP_THREAD_AUTO_START) != TX_SUCCESS)
    {
      return TX_THREAD_ERROR;
    }
   
    if (tx_thread_create(&amp;tx_app_thread3,
    "tx3 app thread",
    tx_app_thread_entry3,
    0,
    &amp;App2TaskStatStk,                  
    APP_CFG_TASK_USER2_STK_SIZE,
    TX_APP_THREAD_PRIO+1,
    TX_APP_THREAD_PREEMPTION_THRESHOLD,                     
    TX_APP_THREAD_TIME_SLICE,
    TX_APP_THREAD_AUTO_START) != TX_SUCCESS)
    {
      return TX_THREAD_ERROR;
    }
   
/* USER CODE END App_ThreadX_Init */

return ret;
}
/**
* @briefFunction implementing the tx_app_thread_entry thread.
* @paramthread_input: Hardcoded to 0.
* @retval None
*/
void tx_app_thread_entry(ULONG thread_input)
{
/* USER CODE BEGIN tx_app_thread_entry */
    while(1){
    HAL_GPIO_WritePin (LD2_GPIO_Port, LD2_Pin, GPIO_PIN_RESET);
tx_thread_sleep(100);
    HAL_GPIO_WritePin (LD2_GPIO_Port, LD2_Pin, GPIO_PIN_SET);
      tx_thread_sleep(100);
    }
/* USER CODE END tx_app_thread_entry */
}

/**
* @briefFunction that implements the kernel's initialization.
* @paramNone
* @retval None
*/
void MX_ThreadX_Init(void)
{
/* USER CODE BEGINBefore_Kernel_Start */

/* USER CODE ENDBefore_Kernel_Start */

tx_kernel_enter();

/* USER CODE BEGINKernel_Start_Error */

/* USER CODE ENDKernel_Start_Error */
}

/* USER CODE BEGIN 1 */

void tx_app_thread_entry2(ULONG thread_input)
{
    while(1)
    {
      HAL_GPIO_WritePin (LD3_GPIO_Port, LD3_Pin, GPIO_PIN_RESET);
      tx_thread_sleep(1000);
      HAL_GPIO_WritePin (LD3_GPIO_Port, LD3_Pin, GPIO_PIN_SET);
      tx_thread_sleep(1000);
    }
}

void tx_app_thread_entry3(ULONG thread_input)
{
    float a = 0;
    while(1)
    {
      printf("%u test a=%f\n",tx_time_get(),a);
      a+=1.3;
      tx_thread_sleep(1);
    }
}

/* USER CODE END 1 */
</code></pre>

<p>&nbsp;</p>

<p>效果:</p>

<p>c9859e6dc3349299b8edda6b05f3b47f<br />
&nbsp;</p>

<p>&nbsp;</p>

<div style="text-align: center;"></div>

<p>工程:</p>

<div></div>
页: [1]
查看完整版本: 【NUCLEO-H743ZI】8、stm32cubemx创建threadx工程体验