【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 是专门为嵌入式应用程序设计的高性能实时内核。 </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™ 体系结构</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™)</li>
<li>优先级继承</li>
<li>事件链接 (Event-chaining™)</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> </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**) &pointer,
TX_APP_STACK_SIZE, TX_NO_WAIT) != TX_SUCCESS)
{
return TX_POOL_ERROR;
}
/* Create tx app thread.*/
if (tx_thread_create(&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(&tx_app_thread2,
"tx2 app thread",
tx_app_thread_entry2,
0,
&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(&tx_app_thread3,
"tx3 app thread",
tx_app_thread_entry3,
0,
&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> </p>
<p>效果:</p>
<p>c9859e6dc3349299b8edda6b05f3b47f<br />
</p>
<p> </p>
<div style="text-align: center;"></div>
<p>工程:</p>
<div></div>
页:
[1]