threadx系统_STM32F103C8基于CubeMX+ MDK来移植ThreadX系统

目录

写在前面

STM32CubeMX

CubeMX中选择该芯片

 时钟配置

 系统配置

中断配置

 引脚配置

 生成工程

工程目录

验证

下载源码

 系统移植

在mdk中添加相应的文件

 移植编译

error:SysTick_Handler重复定义

 error:cannot all be FIRST/LAST

系统节拍修改

 系统运行


写在前面

ThreadX 是由 Express Logic 公司开发的实时操作系统。该公司已被微软收购,并且已经开源,就这点来说微软这波开源操作有点狠,有点打压其它RTOS全家桶的意思,有点针对亚马逊的FreeRTOS和国内的RTT,而且其全家桶一旦推广起来,对其他RTOS和中间件几乎是毁灭性打击。

为什么这么说呢?

首先,ThreadX几乎是小型RTOS的巅峰之作,不管你之前用的那个OS,如果有精力建议还是学习下。62亿电子设备采用,是其它RTOS无法逾越的高山。而且还拥有大量的不同行业的认证。

虽然ThreadX很强大,但是本次例程结束后将会开始RTT的移植,做为中国人,必须支持国产。

闲话少说,开坛讲法。

STM32CubeMX

本次使用的CubeMX版本为6.4.0,MCU为ST的STM32F103C8T6,flash为64K,ram为20K,。

CubeMX中选择该芯片

不贴图了,大家应该都会。

 时钟配置

选择外部时钟

 系统配置

1、采用swd的串行调试;

2、由于ThreadX需要使用Systick,因此hal库的时基选择为TIM1;

中断配置

同样由于ThreadX需要使用PendSV_Handler,应该此处将该中断去掉;

 引脚配置

PA0作为呼吸灯

配置串口为9600

 生成工程

设置工程名和路径,选择MDK,完成相关配置,点击生成工程

工程目录

其中有些文件是git需要的文件以及从正点原子拿过来的keilkill文件。至此,CubeMX操作完成。

验证

工程生成后在移植前最好在mdk编译一遍,确保工程是没问题的,我是写了个呼吸灯和串口的程序。

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_USART1_UART_Init();
  /* USER CODE BEGIN 2 */
	/* Enter the ThreadX kernel.  */
    tx_kernel_enter();
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
		HAL_Delay(500);
		HAL_GPIO_WritePin(GPIOA,GPIO_PIN_0,GPIO_PIN_RESET);
		HAL_Delay(500);
		HAL_GPIO_WritePin(GPIOA,GPIO_PIN_0,GPIO_PIN_SET);
		HAL_UART_Transmit(&huart1,TxBuf,sizeof(TxBuf),100);
  }
  /* USER CODE END 3 */
}

下载源码

 首先到github上下载threadx的源码,建议使用git,下载zip的话非常慢,而且容易失败,点击链接threadx下载。下载后目录如下,我们移植需要以下2个文件夹的内容

1:源码; 

2:启动文件,启动文件内内容较多,选择的mcu为m3内核,使用mdk软件,因此需要的是threadx-master\ports\cortex_m33\keil下的文件

 将上述2个文件夹复制到工程目录中,我放在了Drivers目录中

 

 系统移植

在mdk中添加相应的文件

添加Source下在所有文件

 添加port下的文件

1、文件 tx_initialize_low_level.s 在路径 ThreadX\ports\cortex_m3\ ac5 \example_build
应该添加ThreadX\ports\cortex_m3\ keil \example_build路径下的也是ok的
2、其它文件在路径 ThreadX\ports\cortex_m3\ keil \src,如果添加 ac5 的会报 Invalid line start错误,打开两个文件后会看到,原来是文件最前面的说明的注释文档的注释方式有所区别导致的,可能跟keil在编译汇编文件时对注释方法和其他有所区别。

 最终的工程结构如下

 移植编译

移植完成后我们先来编译下,发现error:

error:SysTick_Handler重复定义

此时找到文件Core\Src\stm32f1xx_it.c 将里面的SysTick_Handler整个注释掉。

systick明明选择了TIM1,不知道为什么还会重复定义,有知道的可以留言告诉我。

 error:cannot all be FIRST/LAST

居然只有几个碰到类似问题。看了下http://www.amobbs.com/thread-3308421-1-1.html 即

stm32f10系列移植threadx - uCOS & uCGUI & emWin & embOS & TouchGFX & ThreadX - 硬汉嵌入式论坛 - Powered by Discuz!

发现是startup文件的问题,原来文件tx_initialize_low_level.s接管了xxx.S启动文件已经实现的功能。从ThreadX的角度来说,他们保证了自己发布新软件包的独立性,直接面向内核出,不需要再面向各个厂家单独出一个系列,否则工作量就超级大,各大厂家加起来有几千个上万的启动文件。要他们专门去做适配,基本做不到的。所以他们接管xxxx.S启动文件,但他们接管的文件仅写了几个重要的中断向量表入口。这就给让移植的人非常不方便。所以我们做的例子不接管XXX.S启动文件了,方便大家移植,直接将里面修正后的代码覆盖当前tx_initialize_low_level.s中的代码即可。ThreadX的MDK AC5版底层移植修正版

下面的代码跟链接中的一样

;/**************************************************************************/
;/*                                                                        */
;/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
;/*                                                                        */
;/*       This software is licensed under the Microsoft Software License   */
;/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
;/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
;/*       and in the root directory of this software.                      */
;/*                                                                        */
;/**************************************************************************/
;
;
;/**************************************************************************/
;/**************************************************************************/
;/**                                                                       */
;/** ThreadX Component                                                     */
;/**                                                                       */
;/**   Initialize                                                          */
;/**                                                                       */
;/**************************************************************************/
;/**************************************************************************/
;
;#define TX_SOURCE_CODE
;
;
;/* Include necessary system files.  */
;
;#include "tx_api.h"
;#include "tx_initialize.h"
;#include "tx_thread.h"
;#include "tx_timer.h"
;
;
    IMPORT  _tx_thread_system_stack_ptr
    IMPORT  _tx_initialize_unused_memory
    IMPORT  _tx_thread_context_save
    IMPORT  _tx_thread_context_restore
    IMPORT  _tx_timer_interrupt
    IMPORT  __main
        IMPORT        __Vectors
        IMPORT        __initial_sp  
                
;
;
SYSTEM_CLOCK        EQU     400000000
SYSTICK_CYCLES      EQU     ((SYSTEM_CLOCK / 1000) -1)
;
;     
;
;
    AREA ||.text||, CODE, READONLY
        PRESERVE8

;/**************************************************************************/
;/*                                                                        */
;/*  FUNCTION                                               RELEASE        */
;/*                                                                        */
;/*    _tx_initialize_low_level                          Cortex-M7/AC5     */
;/*                                                           6.0.1        */
;/*  AUTHOR                                                                */
;/*                                                                        */
;/*    William E. Lamie, Microsoft Corporation                             */
;/*                                                                        */
;/*  DESCRIPTION                                                           */
;/*                                                                        */
;/*    This function is responsible for any low-level processor            */
;/*    initialization, including setting up interrupt vectors, setting     */
;/*    up a periodic timer interrupt source, saving the system stack       */
;/*    pointer for use in ISR processing later, and finding the first      */
;/*    available RAM memory address for tx_application_define.             */
;/*                                                                        */
;/*  INPUT                                                                 */
;/*                                                                        */
;/*    None                                                                */
;/*                                                                        */
;/*  OUTPUT                                                                */
;/*                                                                        */
;/*    None                                                                */
;/*                                                                        */
;/*  CALLS                                                                 */
;/*                                                                        */
;/*    None                                                                */
;/*                                                                        */
;/*  CALLED BY                                                             */
;/*                                                                        */
;/*    _tx_initialize_kernel_enter           ThreadX entry function        */
;/*                                                                        */
;/*  RELEASE HISTORY                                                       */
;/*                                                                        */
;/*    DATE              NAME                      DESCRIPTION             */
;/*                                                                        */
;/*  06-30-2020     William E. Lamie         Initial Version 6.0.1         */
;/*                                                                        */
;/**************************************************************************/
;VOID   _tx_initialize_low_level(VOID)
;{
    EXPORT  _tx_initialize_low_level
_tx_initialize_low_level
;
;    /* Disable interrupts during ThreadX initialization.  */
;
    CPSID   i
;
;    /* Set base of available memory to end of non-initialised RAM area.  */
;     
    LDR     r0, =_tx_initialize_unused_memory       ; Build address of unused memory pointer
    LDR     r1, =__initial_sp                       ; Build first free address
    ADD     r1, r1, #4                              ; 
    STR     r1, [r0]                                ; Setup first unused memory pointer
;
;    /* Setup Vector Table Offset Register.  */
;    
    MOV     r0, #0xE000E000                         ; Build address of NVIC registers
    LDR     r1, =__Vectors                          ; Pickup address of vector table
    STR     r1, [r0, #0xD08]                        ; Set vector table address   
;
;    /* Enable the cycle count register.  */
;
;    LDR     r0, =0xE0001000                         ; Build address of DWT register
;    LDR     r1, [r0]                                ; Pickup the current value
;    ORR     r1, r1, #1                              ; Set the CYCCNTENA bit
;    STR     r1, [r0]                                ; Enable the cycle count register 
;
;    /* Set system stack pointer from vector value.  */
;
    LDR     r0, =_tx_thread_system_stack_ptr        ; Build address of system stack pointer
    LDR     r1, =__Vectors                          ; Pickup address of vector table
    LDR     r1, [r1]                                ; Pickup reset stack pointer
    STR     r1, [r0]                                ; Save system stack pointer
;
;    /* Configure SysTick.  */
;
    MOV     r0, #0xE000E000                         ; Build address of NVIC registers
    LDR     r1, =SYSTICK_CYCLES
    STR     r1, [r0, #0x14]                         ; Setup SysTick Reload Value
    MOV     r1, #0x7                                ; Build SysTick Control Enable Value
    STR     r1, [r0, #0x10]                         ; Setup SysTick Control
;
;    /* Configure handler priorities.  */
;
    LDR     r1, =0x00000000                         ; Rsrv, UsgF, BusF, MemM
    STR     r1, [r0, #0xD18]                        ; Setup System Handlers 4-7 Priority Registers

    LDR     r1, =0xFF000000                         ; SVCl, Rsrv, Rsrv, Rsrv
    STR     r1, [r0, #0xD1C]                        ; Setup System Handlers 8-11 Priority Registers
                                                    ; Note: SVC must be lowest priority, which is 0xFF

    LDR     r1, =0x40FF0000                         ; SysT, PnSV, Rsrv, DbgM
    STR     r1, [r0, #0xD20]                        ; Setup System Handlers 12-15 Priority Registers
                                                    ; Note: PnSV must be lowest priority, which is 0xFF
;
;    /* Return to caller.  */
;    
    BX      lr 
;}     
;
;
;/* Define shells for each of the unused vectors.  */
;
    EXPORT  __tx_BadHandler
__tx_BadHandler 
    B       __tx_BadHandler

    EXPORT  __tx_SVCallHandler
__tx_SVCallHandler
    B       __tx_SVCallHandler 

    EXPORT  __tx_IntHandler
__tx_IntHandler
; VOID InterruptHandler (VOID)
; {

    PUSH    {r0, lr}
;    /* Do interrupt handler work here */
;    /* .... */
        POP     {r0, lr}
    BX      LR
; }

    EXPORT  __tx_SysTickHandler
        EXPORT  SysTick_Handler
__tx_SysTickHandler
SysTick_Handler
; VOID TimerInterruptHandler (VOID)
; {
;
    PUSH    {r0, lr}
;        BL      _tx_execution_isr_enter            
        BL      _tx_timer_interrupt
;        BL      _tx_execution_isr_exit
    POP     {r0, lr}
    BX      LR
; }

    EXPORT  __tx_NMIHandler 
__tx_NMIHandler
    B       __tx_NMIHandler

    EXPORT  __tx_DBGHandler
__tx_DBGHandler
    B       __tx_DBGHandler

    ALIGN
    LTORG
    END


系统节拍修改

修改tx_initialize_low_level.s中的系统节拍,mcu为72M,系统节拍设置为1000,即1ms,重新编译,0error,0警告,编译完成。

SYSTEM_CLOCK        EQU     72000000
SYSTICK_CYCLES      EQU     ((SYSTEM_CLOCK / 1000) -1)

 系统运行

编译完成之后,我们还需要写一个示例程序,来让系统跑起来,这部分比较简单,可以参考\Drivers\ThreadX\ports\cortex_m3\keil\example_build文件夹里的sample_threadx.c的例程,我这里直接放源码了,编译下载后呼吸灯正常,串口发送数据正常。移植完成

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

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "tx_api.h"
#include "SEGGER_RTT.h"
/* USER CODE END Includes */

#define DEMO_STACK_SIZE         1000
#define DEMO_QUEUE_SIZE         10

TX_THREAD               thread_0;
UCHAR                   thread_0_stack[DEMO_STACK_SIZE];
void    thread_0_entry(ULONG thread_input);

VOID tx_application_define(void  *first_unused_memory)
{
	/* Create the main thread.  */
    tx_thread_create(&thread_0, "thread 0", thread_0_entry, 0,  
            thread_0_stack, DEMO_STACK_SIZE, 
            1, 1, TX_NO_TIME_SLICE, TX_AUTO_START);
}

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_USART1_UART_Init();
  /* USER CODE BEGIN 2 */
	/* Enter the ThreadX kernel.  */
    tx_kernel_enter();
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
  }
}

/* USER CODE BEGIN 4 */
void    thread_0_entry(ULONG thread_input)
{

	//UINT    status = 8;

	/* This thread simply sits in while-forever-sleep loop.  */
	while(1)
	{			
		tx_thread_sleep(500);
		HAL_GPIO_WritePin(GPIOA,GPIO_PIN_0,GPIO_PIN_RESET);
		tx_thread_sleep(500);
		HAL_GPIO_WritePin(GPIOA,GPIO_PIN_0,GPIO_PIN_SET);
		HAL_UART_Transmit(&huart1,TxBuf,sizeof(TxBuf),100);		
  }
}

  • 4
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值