【M32】F103CBTx 移植 ThreadX

1.配置

取消 Pendable request for system service 和 System tick timer 选项
在这里插入图片描述
库函数时基源改为普通定时器
在这里插入图片描述
Project Manager 不生成 mian 入口函数
在这里插入图片描述

2.移植

下载 threadx 源码包:源码包

在这里插入图片描述

拷贝下面两个文件夹到项目
在这里插入图片描述
ports 选择对应的内核,M32F103CB 是 cortex-m3 内核,使用 keil 编译,拷贝 cortex_m3/keil 下的文件夹到 ports 中,将 example_build 中的 tx_initialize_low_level.s 拷贝出来,删除其他文件夹
在这里插入图片描述

keil 分组导入对应的文件,ThreadX/common 分组导入 common 路径下所有 C 文件;ThreadX/ports 分组导入 ports 路径下所有 S 文件以及 tx_initialize_low_level.s
在这里插入图片描述

3.适配

修改 tx_initialize_low_level.s,仅保留系统时钟信息、_tx_initialize_low_level 函数和 __tx_SysTickHandler 函数

;   在 _tx_initialize_low_level 中使用的外部函数
    IMPORT  _tx_thread_system_stack_ptr
    IMPORT  _tx_initialize_unused_memory
    IMPORT  __initial_sp
    IMPORT  __Vectors
;   在 __tx_SysTickHandler 中使用的外部函数   
    IMPORT  _tx_timer_interrupt
    
; 系统时钟信息
SYSTEM_CLOCK        EQU     72000000
SYSTICK_CYCLES      EQU     ((SYSTEM_CLOCK / 1000) -1)


    AREA ||.text||, CODE, READONLY
    
;   __initial_sp 取代 |Image\$\$ZI\$\$Limit|,__Vectors 取代 __tx_vectors
    
    EXPORT  _tx_initialize_low_level
_tx_initialize_low_level
    CPSID   i
    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
    MOV     r0, #0xE000E000                     ; Build address of NVIC registers
    LDR     r1, =__Vectors                      ; Pickup address of vector table
    STR     r1, [r0, #0xD08]                    ; Set vector table address
    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
    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
    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
    BX      lr

;   SysTick_Handler 取代 __tx_SysTickHandler
    EXPORT  SysTick_Handler
SysTick_Handler
    PUSH    {r0, lr}
    BL      _tx_timer_interrupt
    POP     {r0, lr}
    BX      LR


    ALIGN
    LTORG
    END

4.运行

创建 tx_application_define.c 文件,定义 tx_application_define 函数,实现 main 函数入口,循环打印内部温度

#include "tx_api.h"
#include <stdio.h>
#include "main.h"
#include "adc.h"
#include "dma.h"
#include "rtc.h"
#include "usart.h"
#include "usb_device.h"
#include "gpio.h"

#define DEMO_STACK_SIZE 1024
#define DEMO_BYTE_POOL_SIZE 2048

TX_THREAD thread_0;
TX_BYTE_POOL byte_pool_0;
UCHAR memory_area[DEMO_BYTE_POOL_SIZE];

#define AVMAX 10
struct
{
  uint16_t temp;
  uint16_t vref;
} AdcValue[AVMAX];
UINT status;
RTC_DateTypeDef sdatestructure;
RTC_TimeTypeDef stimestructure;

// 引入 main.c 中的时钟配置
extern void SystemClock_Config(void);

// 主函数入口
int main()
{
  HAL_Init();
  SystemClock_Config();
  // 挂起时基
  HAL_SuspendTick();
  tx_kernel_enter();
}

void thread_0_entry(ULONG thread_input);

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

void tx_application_define(void *first_unused_memory)
{

  CHAR *pointer = TX_NULL;

  /* Create a byte memory pool from which to allocate the thread stacks.  */
  tx_byte_pool_create(&byte_pool_0, "byte pool 0", memory_area, DEMO_BYTE_POOL_SIZE);

  /* Put system definition stuff in here, e.g. thread creates and other assorted
     create information.  */

  /* Allocate the stack for thread 0.  */
  tx_byte_allocate(&byte_pool_0, (VOID **)&pointer, DEMO_STACK_SIZE, TX_NO_WAIT);

  /* Create the main thread.  */
  tx_thread_create(&thread_0, "thread 0", thread_0_entry, 0,
                   pointer, DEMO_STACK_SIZE,
                   1, 1, TX_NO_TIME_SLICE, TX_AUTO_START);
}

/* Define the test threads.  */

void thread_0_entry(ULONG thread_input)
{
  // 恢复时基
  HAL_ResumeTick();
  MX_GPIO_Init();
  MX_DMA_Init();
  MX_USART1_UART_Init();
  MX_USB_DEVICE_Init();
  MX_RTC_Init();
  MX_ADC1_Init();
  HAL_ADCEx_Calibration_Start(&hadc1);
  HAL_ADC_Start_DMA(&hadc1, (uint32_t *)&AdcValue, sizeof(AdcValue) / sizeof(uint16_t));

  /* This thread simply sits in while-forever-sleep loop.  */
  while (1)
  {
    HAL_RTC_GetTime(&hrtc, &stimestructure, RTC_FORMAT_BIN);
    HAL_RTC_GetDate(&hrtc, &sdatestructure, RTC_FORMAT_BIN);

    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
    printf("%02d/%02d/%02d\r\n", 2000 + sdatestructure.Year, sdatestructure.Month, sdatestructure.Date);
    printf("%02d:%02d:%02d\r\n", stimestructure.Hours, stimestructure.Minutes, stimestructure.Seconds);

    int32_t temp = 0.0, vref = 0.0;
    for (uint8_t i = 0; i < AVMAX; i++)
    {
      temp += AdcValue[i].temp;
      vref += AdcValue[i].vref;
    }
    temp /= AVMAX;
    vref /= AVMAX;

    printf("MCU Temperature : %.5f\r\n", ((temp * 3300.0 / 4096 - 1410) / 4.2 + 25));
    printf("Vrefint value = %1.3fV \r\n", vref * 3.3f / 4096);

    HAL_GPIO_TogglePin(LED_TSF_GPIO_Port, LED_TSF_Pin);

    /* Sleep for 10 ticks.  */
    tx_thread_sleep(1000);
  }
}

在调度器开启之前,进行外设资源的初始化操作,可能会导致不可预测的错误,我在实际项目中出现了意外死机,频繁产生 HardFault…在放置在任务中进行初始化资源后,错误消失,具体原因尚未深究

注意:如果编译提示 __initial_sp 未定义,一定要勾选微库
在这里插入图片描述
在 startup_stm32f103xb.s 启动文件中,识别到微库的宏,才释放 __initial_sp

IF      :DEF:__MICROLIB           
  EXPORT  __initial_sp

5.运行

系统启动后,成功打印
在这里插入图片描述

参考

1.手把手教你移植ThreadX操作系统,基于在Keil MDK环境
2.stm32移植threadx rtos
3.关于Free-RTOS调度器启动前API调用造成中断关闭问题
4.【安富莱】ThreadX内核教程更新记录帖

交流

项目仓库:https://github.com/dissor/F1-Link.git

git clone https://github.com/dissor/F1-Link.git
cd F1-Link
git reset --hard bd3590d197ff7ad90462c88c7722282b983d482d

微信公众号:物联指北
B站:物联指北
千人企鹅群:658685162

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

西西洛

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值