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;
extern void SystemClock_Config(void);
int main()
{
HAL_Init();
SystemClock_Config();
HAL_SuspendTick();
tx_kernel_enter();
}
void thread_0_entry(ULONG thread_input);
void tx_application_define(void *first_unused_memory)
{
CHAR *pointer = TX_NULL;
tx_byte_pool_create(&byte_pool_0, "byte pool 0", memory_area, DEMO_BYTE_POOL_SIZE);
tx_byte_allocate(&byte_pool_0, (VOID **)&pointer, DEMO_STACK_SIZE, TX_NO_WAIT);
tx_thread_create(&thread_0, "thread 0", thread_0_entry, 0,
pointer, DEMO_STACK_SIZE,
1, 1, TX_NO_TIME_SLICE, TX_AUTO_START);
}
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));
while (1)
{
HAL_RTC_GetTime(&hrtc, &stimestructure, RTC_FORMAT_BIN);
HAL_RTC_GetDate(&hrtc, &sdatestructure, RTC_FORMAT_BIN);
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);
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
|