stm32开发之threadx+modulex组合开发使用记录

前言

  1. 参考博客 论坛
  2. 官方资料: 微软
  3. 开发板核心芯片使用的是stm32f407zgtx,烧录工具使用的是jlink
  4. 模块的构建使用的是脚本进行构建
  5. 网上针对modulex的资料较少,这里做个记录

项目结构

在这里插入图片描述

逻辑框架

在这里插入图片描述

主程序代码

在这里插入图片描述

主函数

/** Copyright (c) 2024-2024,shchl** SPDX-License-Identifier: Apache-2.0** Change Logs:* Date           Author       Notes* 2024-4-4     shchl   first version*/
#include "includes.h"/*** @brief app 入口函数* @return*/
int main() {/*系统初始化*/System_Init();/*挂起hal tick*/HAL_SuspendTick();/*进入threadx 内核*/tx_kernel_enter();while (1) {printf("app run\r\n");HAL_Delay(1000);}return 0;
}

app_threadx

/** Copyright (c) 2024-2024,shchl** SPDX-License-Identifier: Apache-2.0** Change Logs:* Date           Author       Notes* 2024-4-4     shchl   first version*** tx_kernel_enter() 执行逻辑(关键)*   TX_PORT_SPECIFIC_PRE_INITIALIZATION----可扩展*    _tx_initialize_low_level() --- 设备层(寄存器)初始化*    _tx_initialize_high_level() --- tx os 内部相关初始化*   TX_INITIALIZE_KERNEL_ENTER_EXTENSION----可扩展*     tx_application_define(_tx_initialize_unused_memory);*   TX_PORT_SPECIFIC_PRE_SCHEDULER_INITIALIZATION ---可扩展**/#include "includes.h"#define APP_MAIN_STACK_SIZE 2048
#define APP_MEM_ALLOC_STATIC_ENABLE (0) /*静态内存分配使能*//*
*******************************************************************************************************
*                               外部引入变量
*******************************************************************************************************
*/
extern void app_component_init(void);/*
*******************************************************************************************************
*                               变量
*******************************************************************************************************
*//*
*********************************************************************************************************
*                                       静态全局变量
*********************************************************************************************************
*/
static TX_THREAD app_start_thread; /*应用启动线程*/
/*
*********************************************************************************************************
*                                      函数声明
*********************************************************************************************************
*/
static void app_start_entry(ULONG input);
/*
*********************************************************************************************************
*                                      内部函数
*********************************************************************************************************
*/static void app_start_entry(ULONG input) {/*恢复 HAL 时基*/HAL_ResumeTick();/*外设初始化*/bsp_Init();/*应用组件初始化*/app_component_init();while (1) {/* 需要周期性处理的程序,对应裸机工程调用的SysTick_ISR */bsp_ProPer1ms();tx_thread_sleep(1);}
}/*** @brief  应用组件定义初始化* @param  first_unused_memory : 指向第一个未使用的内存的指针* @retval None*/
VOID tx_application_define(VOID *first_unused_memory) {UINT stat;
#if APP_MEM_ALLOC_STATIC_ENABLE
#define TX_STATIC_MEM_SIZE (60*1024) /*静态内存字节数*//*内存池初始化*/static uint8_t mem_pool_area[TX_STATIC_MEM_SIZE];tx_mem_pool_static_init(mem_pool_area, TX_STATIC_MEM_SIZE);
#elseif (first_unused_memory) {tx_mem_pool_init(first_unused_memory);} else {// todo 未使用动态内存,后面禁止使用 app_malloc 函数}
#endifstat = tx_thread_create(&app_start_thread, "app start thread",app_start_entry, 0,app_malloc(APP_MAIN_STACK_SIZE), APP_MAIN_STACK_SIZE,2, 2,TX_NO_TIME_SLICE, TX_AUTO_START);if (stat != TX_SUCCESS) {/*错误处理: 线程创建失败*/Error_Handler();}}

日志

/** Copyright (c) 2024-2024,shchl** SPDX-License-Identifier: Apache-2.0** Change Logs:* Date           Author       Notes* 2024-4-4     shchl   first version*/
#include "includes.h"/*
*******************************************************************************************************
*                               外部引入变量
*******************************************************************************************************
*/
extern TX_MUTEX AppPrintfSemp;    /* 用于printf互斥 */
/*
*******************************************************************************************************
*                               变量
*******************************************************************************************************
*//*
*********************************************************************************************************
*                                       静态全局变量
*********************************************************************************************************
*/
static char buf_str[TX_LOG_BUF_SZ] = {0}; /* 特别注意,如果printf的变量较多,注意此局部变量的大小是否够用 */
/*
*********************************************************************************************************
*                                      函数声明
*********************************************************************************************************
*//*
*********************************************************************************************************
*                                      外部函数
*********************************************************************************************************
*/
void tx_log(const char *fmt, ...) {va_list v_args;va_start(v_args, fmt);int len = vsnprintf((char *) &buf_str[0],(size_t) sizeof(buf_str),(char const *) fmt,v_args);va_end(v_args);/* 互斥操作 */tx_mutex_get(&AppPrintfSemp, TX_WAIT_FOREVER);if (len > TX_LOG_BUF_SZ - 1) {len = TX_LOG_BUF_SZ - 1;}buf_str[len] = '\0';printf("%s", buf_str);tx_mutex_put(&AppPrintfSemp);}void tx_log_no_mutex(const char *fmt, ...) {va_list v_args;va_start(v_args, fmt);(void) vsnprintf((char *) &buf_str[0],(size_t) sizeof(buf_str),(char const *) fmt,v_args);va_end(v_args);/* 互斥操作 */printf("%s", buf_str);
}

内存管理

/** Copyright (c) 2024-2024,shchl** SPDX-License-Identifier: Apache-2.0** Change Logs:* Date           Author       Notes* 2024-4-9     shchl   first version*/
#include "includes.h"#define RAM_START              (0x20000000)   /*ram起始地址*/
#define RAM_SIZE               (128 * 1024)   /*总大小*/
#define RAM_END                (RAM_START + RAM_SIZE) /*结束地址*/#define STAND_C_LIB      0  /*使用c标准库提供的内存分配函数进行管理*/
#define TX_BYTE_POOL_MEM 1  /*使用threadx提供的字节池对象进行内存分配管理*/
#define MEM_MANAGER_MODE TX_BYTE_POOL_MEM
/*
*********************************************************************************************************
*                                       静态全局变量
*********************************************************************************************************
*/
static TX_BYTE_POOL g_byte_pool; /*全局字节池*/
static ULONG mem_size;  /*内存总大小(字节)*//*
*********************************************************************************************************
*                                      外部函数
*********************************************************************************************************
*/
/*** @brief 内存池初始化* @param start_addr 其实地址*/
void tx_mem_pool_init(void *start_addr) {
#if MEM_MANAGER_MODE == TX_BYTE_POOL_MEM// 地址对齐-保证4字节 内部已处理这里就不需要进行字节对齐处理了ULONG begin_align =(ULONG) start_addr;mem_size = (RAM_END - begin_align); /*动态内存总大小(字节)*//*通过threadx 提供的字节池对象进行管理动态内存空间*/if (tx_byte_pool_create(&g_byte_pool, "heap",start_addr, mem_size) != TX_SUCCESS) {/*错误处理*/Error_Handler();}#elif MEM_MANAGER_MODE == TX_BYTE_POOL_MEM
#endif
}void tx_mem_pool_static_init(void *start_addr, uint16_t byte_cnt){mem_size = byte_cnt; /*动态内存总大小(字节)*//*通过threadx 提供的字节池对象进行管理动态内存空间*/if (tx_byte_pool_create(&g_byte_pool, "heap",start_addr, mem_size) != TX_SUCCESS) {/*错误处理*/Error_Handler();}}/*** @brief 内存分配* @param size 分配大小(字节)* @return 指向分配内存的首地址*/
void *app_malloc(ULONG size) {
#if MEM_MANAGER_MODE == TX_BYTE_POOL_MEMstatic void *mem_ptr = NULL; /*这里要用全局静态变量,不能放在栈上面*/tx_byte_allocate(&g_byte_pool, (void **) &mem_ptr,size, TX_NO_WAIT);return mem_ptr;
#elsereturn malloc(size);
#endif}/*** @brief 释放内存* @param mem_ptr*/
void app_free(void *mem_ptr) {
#if MEM_MANAGER_MODE == TX_BYTE_POOL_MEMtx_byte_release(mem_ptr);
#elsefree(mem_ptr);
#endif}/*** @brief 重新分配内存空间* @param ptr 原始内存指向的指针* @param size 重新分配的大小* @return 新分配内存空间的首地址*  @note 需要用返回回去的指针覆盖原始指针,防止重新分配的内存首地址发生改变*/
void *app_realloc(void *ptr, ULONG size) {
#if MEM_MANAGER_MODE == TX_BYTE_POOL_MEMvoid *nw_ptr = app_malloc(size);memcpy(nw_ptr, ptr, size);app_free(ptr);return nw_ptr;#elsereturn realloc(ptr,size);
#endif}

模块管理

#include "includes.h"
#include "txm_module.h"#define APP_MODULE_MANAGER_STACK_SIZE                          4096U /*模块管理栈字节大小*/
#define APP_MODULE_MANAGER_THREAD_PRIORITY                     4     /*模块管理线程优先级*/
#define APP_MODULE_MANAGER_THREAD_PREEMPTION_THRESHOLD         APP_MODULE_MANAGER_THREAD_PRIORITY /*模块管理抢占阈值优先级*/#define MODULE_DATA_SIZE           (20*1024)  /* 供动态APP使用 */
#define OBJECT_MEM_SIZE            (32*1024)    /* 供动态APP的动态内存管理申请使用 */
enum {READY_FLAG, /*未启动*/STARTED_FLAG, /*已启动*/
};
/*** @brief 模块信息结构体*/
struct module_info_struct {uint8_t start_flag; /*启动标志位*/char *module_name; /*模块名*/uint32_t load_addr; /*加载地址地址*/TXM_MODULE_INSTANCE instance;  /* 模块实例 */
};
/*
*******************************************************************************************************
*                               外部引入变量
*******************************************************************************************************
*//*
*******************************************************************************************************
*                               变量
*******************************************************************************************************
*/
struct module_info_struct module_tbl[] = {{READY_FLAG, "app module 01", 0x08020000U},{READY_FLAG, "app module 02", 0x08040000U}
};
#define MODULE_TBL_SIZE (sizeof(module_tbl)/sizeof(module_tbl[0]))TX_QUEUE ResidentQueue;       /* 消息队列,用于主程序和动态APP通信 */
uint32_t MessageQueuesBuf[100];/*
*********************************************************************************************************
*                                       静态全局变量
*********************************************************************************************************
*/
static TX_THREAD module_manager_thread; /*模块管理线程*/
static ULONG memory_faults = 0;
static UCHAR *module_data_area;
static UCHAR *object_memory;/*
*********************************************************************************************************
*                                      函数声明
*********************************************************************************************************
*/
static void app_txm_module_info_out(TXM_MODULE_INSTANCE *instance, ULONG prop);static VOID module_fault_handler(TX_THREAD *thread, TXM_MODULE_INSTANCE *module);static void app_module_load(uint8_t idx);static void app_module_unload(uint8_t idx);static VOID module_manager_entry(ULONG thread_input);
/*
*********************************************************************************************************
*                                      外部函数
*********************************************************************************************************
*//*
*********************************************************************************************************
*	函 数 名: module_application_define
*	功能说明: 创建 模块管理任务线程
*	形    参: 无
*	返 回 值: 无
*********************************************************************************************************
*/
int module_application_define(void) {/*模块 分配内存空间*/object_memory = app_malloc(OBJECT_MEM_SIZE);module_data_area = app_malloc(MODULE_DATA_SIZE);/* 创建动态APP管理器任务  */if (tx_thread_create(&module_manager_thread, "Module Manager Thread",module_manager_entry, 0,app_malloc(APP_MODULE_MANAGER_STACK_SIZE), APP_MODULE_MANAGER_STACK_SIZE,APP_MODULE_MANAGER_THREAD_PRIORITY, APP_MODULE_MANAGER_THREAD_PREEMPTION_THRESHOLD,TX_NO_TIME_SLICE, TX_AUTO_START) != TX_SUCCESS) {Error_Handler();}/* 创建常驻消息队列 */if (tx_queue_create(&ResidentQueue, "Resident Queue",TX_1_ULONG, MessageQueuesBuf,16 * sizeof(ULONG)) != TX_SUCCESS) {Error_Handler();}return TX_SUCCESS;
}TX_THREAD_EXPORT_LV1(module_application_define); /*首先创建模块应用*//*
*********************************************************************************************************
*	函 数 名: module_manager_entry
*	功能说明: 动态加载管理任务。
*	形    参: 无
*	返 回 值: 无
*********************************************************************************************************
*/static VOID module_manager_entry(ULONG thread_input) {TX_PARAMETER_NOT_USED(thread_input);UINT status;uint8_t cmd;/* 初始化动态加载管理器,主要是给动态APP的数据空间使用  */status = txm_module_manager_initialize((VOID *) module_data_area, MODULE_DATA_SIZE);if (status != TX_SUCCESS) {Error_Handler();}/* 供动态APP使用的对象内存池,主要各种控制块申请 */status = txm_module_manager_object_pool_create(object_memory, OBJECT_MEM_SIZE);if (status != TX_SUCCESS) {Error_Handler();}/* 注册faults管理 */status = txm_module_manager_memory_fault_notify(module_fault_handler);if (status != TX_SUCCESS) {Error_Handler();}while (1) {if (comGetChar(COM1, &cmd))    /* 从串口读入一个字符(非阻塞方式) */{switch (cmd) {/* 加载APP1 */case '1':app_module_load(0);break;/* 卸载APP1 */case '2':app_module_unload(0);break;/* 加载APP2 */case '3':app_module_load(1);break;/* 卸载APP2 */case '4':app_module_unload(1);break;/* 打印任务执行情况 */case '5':app_task_info_out();break;default:break;}}tx_thread_sleep(1);}
}/*
*********************************************************************************************************
*	函 数 名: module_fault_handler
*	功能说明: 监测faults
*	形    参: ---
*	返 回 值: 无
*********************************************************************************************************
*/
static VOID module_fault_handler(TX_THREAD *thread, TXM_MODULE_INSTANCE *module) {tx_log("module_fault_handler: thread[%s],module[%s]\r\n", thread->tx_thread_name, module->txm_module_instance_name);/* 统计错误消息  */memory_faults++;
}/*** @brief 加载模块* @param idx 模块下标*/
static void app_module_load(uint8_t idx) {UINT status;ULONG module_properties;struct module_info_struct *module_inf;if (idx >= MODULE_TBL_SIZE) {tx_log("load idx(%d) out of bound\r\n", idx);return;}/*模块信息*/module_inf = &module_tbl[idx];if (module_inf->start_flag == STARTED_FLAG) {tx_log("module(%s) already started \r\n", module_inf->module_name);return;}/* 加载动态APP */status = txm_module_manager_in_place_load(&module_inf->instance,module_inf->module_name,(VOID *) module_inf->load_addr);if (status) {tx_log("txm_module_manager_in_place_load error:[%d]\r\n", status);return;}/* 获取动态APP属性 */status = txm_module_manager_properties_get(&module_inf->instance, &module_properties);if (status) {tx_log("txm_module_manager_properties_get error:[%d]\r\n", status);return;}/*模块信息打印*/app_txm_module_info_out(&module_inf->instance, module_properties);/* 启动动态APP */status = txm_module_manager_start(&module_inf->instance);tx_thread_sleep(1000);if (status != TX_SUCCESS) {tx_log("txm_module_manager_start error:[%d]\r\n", status);return;}/*更新信息*/module_inf->start_flag = STARTED_FLAG;tx_log("Module execution is started\n");}/*** @brief 卸载模块* @param idx 模块下标*/
static void app_module_unload(uint8_t idx) {UINT status;struct module_info_struct *module_inf;if (idx >= MODULE_TBL_SIZE) {tx_log("load idx(%d) out of bound\r\n", idx);return;}/*模块信息*/module_inf = &module_tbl[idx];if (module_inf->start_flag == STARTED_FLAG) { /*已经启动,才会卸载*//* 停止动态APP */status = txm_module_manager_stop(&module_inf->instance);if (status != TX_SUCCESS) {tx_log("==========================MODULE(%s) STOP ERR(%d)========================\r\n",module_inf->module_name, status);return;}/* 卸载动态APP */status = txm_module_manager_unload(&module_inf->instance);if (status != TX_SUCCESS) {tx_log("==========================MODULE(%s) UNLOAD ERR(%d)========================\r\n",module_inf->module_name, status);return;}tx_log("==========================MODULE(%s) UNLOAD OK========================\r\n", module_inf->module_name);} else {tx_log("==========================MODULE(%s) NOT STARTED========================\r\n", module_inf->module_name);}}static void app_txm_module_info_out(TXM_MODULE_INSTANCE *instance, ULONG prop) {tx_log("===============================app_txm_module_info_out================================\r\n");tx_log("------------------module build info------------------\r\n");tx_log("\t--Compiled for %s compiler\r\n",((prop >> 25) == 1) ? "CubeIDE (GNU)" : ((prop >> 24) == 1) ? "ARM KEIL" : "IAR EW");tx_log("\t--Shared/external memory access is %s\r\n", ((prop & 0x04) == 0) ? "Disabled" : "Enabled");tx_log("\t--MPU protection is %s\r\n", ((prop & 0x02) == 0) ? "Disabled" : "Enabled");tx_log("\t--%s mode execution is enabled for the module\r\n\r\n", ((prop & 0x01) == 0) ? "Privileged" : "User");tx_log("------------------module application info------------------\r\n");tx_log("\t--application id %#x;instance id:%#x;name:%s\r\n",instance->txm_module_instance_application_module_id,instance->txm_module_instance_id,instance->txm_module_instance_name);tx_log("\t--code section【start addr: %#x||end addr:%#x||size(bytes):%d】\r\n",instance->txm_module_instance_code_start,instance->txm_module_instance_code_end,instance->txm_module_instance_code_size);tx_log("\t--data section【start addr: %#x||end addr:%#x||size(bytes):%d】\r\n",instance->txm_module_instance_data_start,instance->txm_module_instance_data_end,instance->txm_module_instance_data_size);tx_log("\t--shared_memory 【addr:%#x||size(bytes): %d】\r\n",instance->txm_module_instance_shared_memory_address,instance->txm_module_instance_shared_memory_length);}

主程序和模块的通信

/** Copyright (c) 2024-2024,shchl** SPDX-License-Identifier: Apache-2.0** Change Logs:* Date           Author       Notes* 2024-4-13     shchl   first version*/
#include "includes.h"
#include "txm_module.h"#define App_Printf_ID1       (TXM_APPLICATION_REQUEST_ID_BASE)
#define App_Printf_ID2       (TXM_APPLICATION_REQUEST_ID_BASE + 1)UINT module_manager_application_request(ULONG request_id,ALIGN_TYPE param_1,ALIGN_TYPE param_2,ALIGN_TYPE param_3) {switch (request_id) {/* 执行函数printf */case App_Printf_ID1:printf("执行APP1的打印函数:%lu\r\n", param_1);return TX_SUCCESS;/* 执行函数printf */case App_Printf_ID2:printf("执行APP2的打印函数:%lu\r\n", param_1);return TX_SUCCESS;default:{printf("module_manager_application_request:%lu not available\r\n",request_id);return TX_NOT_AVAILABLE;}}}

cpu 任务状态线程(未使用到threadx的内部工具代码)

/** Copyright (c) 2024-2024,shchl** SPDX-License-Identifier: Apache-2.0** Change Logs:* Date           Author       Notes* 2024-4-4     shchl   first version*/
#include "includes.h"
/*
*******************************************************************************************************
*                               任务相关宏定义
*******************************************************************************************************
*/
#define APP_TASK_CPU_STAT_PRIO 30
#define APP_TASK_CPU_STAT_STK_SIZE 1024
/*
*******************************************************************************************************
*                               外部引入变量
*******************************************************************************************************
*/
#if defined(TX_EXECUTION_PROFILE_ENABLE)
extern EXECUTION_TIME _tx_execution_idle_time_total;
extern EXECUTION_TIME _tx_execution_thread_time_total;
extern EXECUTION_TIME _tx_execution_isr_time_total;
#endif/*
*******************************************************************************************************
*                               变量
*******************************************************************************************************
*/
__IO double OSCPUUsage;    /* CPU百分比 */
/*
*********************************************************************************************************
*                                       静态全局变量
*********************************************************************************************************
*/
static TX_THREAD cpu_stat_task_thread;
/*
*********************************************************************************************************
*                                      函数声明
*********************************************************************************************************
*/
static VOID task_cpu_stat_entry(ULONG input);
/*
*********************************************************************************************************
*                                      外部函数
*********************************************************************************************************
*/
/*** @brief cpu 状态任务* @param first_thread 第一个启动的任务线程首地址*/
int tx_task_cpu_stat_create() {tx_thread_create(&cpu_stat_task_thread,              /* 任务控制块地址 */"app_cpu_stat",               /* 任务名 */task_cpu_stat_entry,                  /* 启动任务函数地址 */0,                             /* 传递给任务的参数 */app_malloc(APP_TASK_CPU_STAT_STK_SIZE),            /* 堆栈基地址 */APP_TASK_CPU_STAT_STK_SIZE,    /* 堆栈空间大小 */APP_TASK_CPU_STAT_PRIO,        /* 任务优先级*/APP_TASK_CPU_STAT_PRIO,        /* 任务抢占阀值 */TX_NO_TIME_SLICE,               /* 不开启时间片 */TX_AUTO_START);                 /* 创建后立即启动 */return TX_SUCCESS;
}TX_THREAD_EXPORT(tx_task_cpu_stat_create);/*
*********************************************************************************************************
*	函 数 名: app_task_info_out
*	功能说明: 将ThreadX任务信息通过串口打印出来
*	形    参:无
*	返 回 值: 无
*********************************************************************************************************
*/void app_task_info_out(void) {TX_THREAD *p_tcb = _tx_thread_identify(); /* 定义一个任务控制块指针,并指向当前线程 *//* 打印标题 */tx_log("调用线程======[%s]\r\n", p_tcb->tx_thread_name);
#if defined(TX_EXECUTION_PROFILE_ENABLE)tx_log("CPU利用率 = %5.2f%%\r\n", OSCPUUsage);tx_log("任务执行时间 = %.9fs\r\n", (double) _tx_execution_thread_time_total / SystemCoreClock);tx_log("空闲执行时间 = %.9fs\r\n", (double) _tx_execution_idle_time_total / SystemCoreClock);tx_log("中断执行时间 = %.9fs\r\n", (double) _tx_execution_isr_time_total / SystemCoreClock);tx_log("系统总执行时间 = %.9fs\r\n", (double) (_tx_execution_thread_time_total + \_tx_execution_idle_time_total + \_tx_execution_isr_time_total) / SystemCoreClock);
#endiftx_log("===============================================================\r\n");tx_log(" 任务优先级 任务栈大小 当前使用栈  最大栈使用 状态   任务名\r\n");tx_log("   Prio     StackSize   CurStack    MaxStack   Taskname\r\n");/* 遍历任务控制列表TCB list),打印所有的任务的优先级和名称 */while (p_tcb != (TX_THREAD *) 0) {tx_log("   %2d        %5d      %5d       %5d    %5d      %s\r\n",p_tcb->tx_thread_priority,p_tcb->tx_thread_stack_size,(int) p_tcb->tx_thread_stack_end - (int) p_tcb->tx_thread_stack_ptr,(int) p_tcb->tx_thread_stack_end - (int) p_tcb->tx_thread_stack_highest_ptr,p_tcb->tx_thread_state,p_tcb->tx_thread_name);p_tcb = p_tcb->tx_thread_created_next;if (p_tcb == _tx_thread_identify()) break;}
}/*
*********************************************************************************************************
*                                      内部函数
*********************************************************************************************************
*/
static VOID task_cpu_stat_entry(ULONG input) {
#if defined(TX_EXECUTION_PROFILE_ENABLE)EXECUTION_TIME TolTime, IdleTime, deltaTolTime, deltaIdleTime;uint32_t uiCount = 0;(void) input;/* 计算CPU利用率 */IdleTime = _tx_execution_idle_time_total;TolTime = _tx_execution_thread_time_total + _tx_execution_isr_time_total + _tx_execution_idle_time_total;while (1) {/* CPU利用率统计 */uiCount++;if (uiCount == 20) {uiCount = 0;deltaIdleTime = _tx_execution_idle_time_total - IdleTime;deltaTolTime =_tx_execution_thread_time_total + _tx_execution_isr_time_total + _tx_execution_idle_time_total -TolTime;OSCPUUsage = (double) deltaIdleTime / deltaTolTime;OSCPUUsage = 100 - OSCPUUsage * 100;IdleTime = _tx_execution_idle_time_total;TolTime = _tx_execution_thread_time_total + _tx_execution_isr_time_total + _tx_execution_idle_time_total;}tx_thread_sleep(10);}
#elsewhile (1) {bsp_Idle();tx_thread_sleep(10);}#endif
}

模块脚本生成代码(根据实际情况进行调整)

生成txm静态库文件的脚本(注意代码中的路径)

/** Copyright (c) 2024-2024,shchl** SPDX-License-Identifier: Apache-2.0** Change Logs:* Date           Author       Notes* 2024-4-14     shchl          thread txm lib 脚本构建*/
#include "main.h"
#include <dirent.h>
#include <sys/stat.h>
/*** @brief txm 源文件构建命令*/
const char *tx_txm_lib_source_build_cmd ="arm-none-eabi-gcc -c -g ""-mcpu=cortex-m4 ""-mfloat-abi=hard ""-mfpu=vfpv4 ""-mthumb ""-fpic -fno-plt ""-mno-pic-data-is-text-relative ""-msingle-pic-base ";
const char *tx_txm_lib_script = "tx_txm_static_lib_build.bat";/*根据实际情况修改*/
static char *txm_inc_list ="\t-IE:\\code\\clion\\STM32_Project\\Middleware\\threadx_6_4\\common\\inc""\t-IE:\\code\\clion\\STM32_Project\\Middleware\\threadx_6_4\\common_modules\\inc""\t-IE:\\code\\clion\\STM32_Project\\Middleware\\threadx_6_4\\ports_module\\cortex_m4\\gnu\\inc ";
static char *txm_lib_src_dir = "E:\\code\\clion\\STM32_Project\\Middleware\\threadx_6_4\\common_modules\\module_lib\\src";
static char *txm_lib_port_file = "E:\\code\\clion\\STM32_Project\\Middleware\\threadx_6_4\\ports_module\\cortex_m4\\gnu\\module_lib\\src\\txm_module_thread_shell_entry.c";void build_txm_lib() {FILE *pSaveFile = fopen(tx_txm_lib_script, "w");if (pSaveFile) {DIR *pDir = opendir(txm_lib_src_dir);/*删除之前的静态库文件*/fputs("del txm.a\n",pSaveFile);if (pDir) {struct dirent *pDirent = readdir(pDir);while (pDirent) {/*判断是否是.c文件*/if (strstr(pDirent->d_name, ".c")) {fprintf(pSaveFile, "%s %s %s\\%s\n",tx_txm_lib_source_build_cmd,txm_inc_list,txm_lib_src_dir,pDirent->d_name);} else if (strstr(pDirent->d_name, ".") && pDirent->d_namlen == 1) {// 当前目录} else if (strstr(pDirent->d_name, "..") && pDirent->d_namlen == 2) {// 上一级目录} else {// 其他判断}pDirent = readdir(pDir);}/*单独添加接口编译源文件*/fprintf(pSaveFile, "%s %s %s\n",tx_txm_lib_source_build_cmd,txm_inc_list,txm_lib_port_file);/*构建静态库*/fputs("arm-none-eabi-ar -r  txm.a *.o\n",pSaveFile);/*删除.o文件*/fputs("del *.o\n",pSaveFile);}fclose(pSaveFile);}}

生成模块构建bin文件的脚本(注意对应的threadx的实际位置)

/** Copyright (c) 2024-2024,shchl** SPDX-License-Identifier: Apache-2.0** Change Logs:* Date           Author       Notes* 2024-4-14     shchl          生成模块应用脚本代码*/
#include "main.h"const char *tx_module_build_script = "tx_module_build.bat";/*指令格式*/
const char *common_del_cmd = "del *.o *.axf *.map"; /*通用删除指令*/
/*** @brief  编译指令 c文件编译成 目标文件*/
const char *module_compilar_to_obj_cmd ="arm-none-eabi-gcc -c -g ^\n""\t\t-mcpu=cortex-m4 ^\n""\t\t-mfloat-abi=hard ^\n""\t\t-mfpu=vfpv4 -fpie -fno-plt ^\n""\t\t-mno-pic-data-is-text-relative ^\n""\t\t-msingle-pic-base ";/*** @brief 链接文件+目标文件*/
const char *module_compilar_to_axf_cmd ="arm-none-eabi-ld -A cortex-m4 ^\n""\t\t-T %s %s ^\n""\t\t-e _txm_module_thread_shell_entry txm.a ^\n""\t\t-o   app_module.axf ^\n""\t\t-M > app_module.map ";
const char *module_compilar_to_bin_cmd ="\narm-none-eabi-objcopy  -O binary  app_module.axf  \"app_module.bin\" ""\narm-none-eabi-objcopy  -O ihex  app_module.axf  \"app_module.hex\" ";/*模块使用的头文件目录*/
const char *module_inc_dir ="^\n\t\t-IE:\\code\\clion\\STM32_Project\\Middleware\\threadx_6_4\\common\\inc ""^\n\t\t-IE:\\code\\clion\\STM32_Project\\Middleware\\threadx_6_4\\common_modules\\inc ""^\n\t\t-IE:\\code\\clion\\STM32_Project\\Middleware\\threadx_6_4\\ports_module\\cortex_m4\\gnu\\inc ";void build_app_module_bat() {char *link_file = " ..\\app_module.ld ";char *asm_file_list = "^\n\t\t..\\app_module_preamble.S ""^\n\t\t..\\app_module_setup.s ";char *source_c_file_list ="^\n\t\t..\\app_module.c """;char *obj_file_list = "\tapp_module_preamble.o ""\tapp_module_setup.o ""\tapp_module.o ";const char *cmd_asm_fmt = "%s %s\n"; /*汇编指令格式*/const char *cmd_source_fmt = "%s %s %s\n"; /*汇编指令格式*/FILE *pFile = fopen(tx_module_build_script, "w");fprintf(pFile, "del  *.bin  *.hex\n");/*清除*//*汇编文件构建目标文件*/fprintf(pFile, cmd_asm_fmt, module_compilar_to_obj_cmd, asm_file_list);/*源文件构建目标文件*/fprintf(pFile, cmd_source_fmt, module_compilar_to_obj_cmd, module_inc_dir, source_c_file_list);/*目标文件构建axf 文件*/fprintf(pFile, module_compilar_to_axf_cmd, link_file, obj_file_list);/*生成bin文件和map文件*/fprintf(pFile, "%s", module_compilar_to_bin_cmd);/*删除 构建中间文件*/fprintf(pFile, "\n%s\n", common_del_cmd);/*清除*/fclose(pFile);
}

主函数

/** Copyright (c) 2024-2024,shchl** SPDX-License-Identifier: Apache-2.0** Change Logs:* Date           Author       Notes* 2024-4-14     shchl   first version*/
#include "main.h"int main(void) {build_txm_lib();build_app_module_bat();return 0;
}

模块1

在这里插入图片描述
上述名称,可自行定义。

入口函数

#define TXM_MODULE#include "txm_module.h"/*
*********************************************************************************************************
*                                    宏定义
*********************************************************************************************************
*/
#define DEFAULT_STACK_SIZE        1024#define App_Printf_ID1       (TXM_APPLICATION_REQUEST_ID_BASE)
#define App_Printf_ID2       (TXM_APPLICATION_REQUEST_ID_BASE + 1)#define MODULE_THREAD_PRIO                         3
#define MODULE_THREAD_PREEMPTION_THRESHOLD         MODULE_THREAD_PRIOULONG      AppModuleStk[DEFAULT_STACK_SIZE/4];/* 相关控制块 */
TX_THREAD               *thread_0;
TX_QUEUE                *resident_queue;/* 函数 */
void thread_0_entry(ULONG thread_input);
void Error_Handler1(void);/*
*********************************************************************************************************
*	函 数 名: default_module_start
*	功能说明: 动态APP入口
*	形    参: ---
*	返 回 值: 无
*********************************************************************************************************
*/
void  demo_module_start(ULONG id)
{CHAR    *pointer;/* 从主程序申请相关控制块,不在APP里面申请,防止APP出问题了影响主程序 */txm_module_object_allocate((void*)&thread_0, sizeof(TX_THREAD));/* 创建任务 */tx_thread_create(thread_0,"module thread 1",thread_0_entry,0,&AppModuleStk[0],DEFAULT_STACK_SIZE,MODULE_THREAD_PRIO,MODULE_THREAD_PREEMPTION_THRESHOLD,TX_NO_TIME_SLICE,TX_AUTO_START);}/*
*********************************************************************************************************
*	函 数 名: thread_0_entry
*	功能说明: 动态APP里面的任务
*	形    参: ---
*	返 回 值: 无
*********************************************************************************************************
*/
void thread_0_entry(ULONG thread_input)
{/* 防止警告 */UINT num = 0;while(1){/* 调用主程序里面的串口打印 */num++;txm_module_application_request(App_Printf_ID1, num, 0, 0);tx_thread_sleep(1000);}
}/*
*********************************************************************************************************
*	函 数 名: thread_0_entry
*	功能说明: 执行出错
*	形    参: ---
*	返 回 值: 无
*********************************************************************************************************
*/
void Error_Handler1(void)
{tx_thread_sleep(TX_WAIT_FOREVER);
}

链接文件(参考官网对应的设备内核)

这里设置的启动地址为0x08020000为的第一个模块的地址

MEMORY
{FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 1024KRAM   (wx) : ORIGIN = 0x20000000, LENGTH = 128K
}SECTIONS
{__FLASH_segment_start__ = 0x08020000;__FLASH_segment_end__   = 0x08030000;__RAM_segment_start__   = 0x20000000;__RAM_segment_end__     = 0x20020000;__HEAPSIZE__ = 128;__preamble_load_start__ = __FLASH_segment_start__;.preamble __FLASH_segment_start__ : AT(__FLASH_segment_start__){__preamble_start__ = .;*(.preamble .preamble.*)}__preamble_end__ = __preamble_start__ + SIZEOF(.preamble);__dynsym_load_start__ =  ALIGN(__preamble_end__ , 4);.dynsym ALIGN(__dynsym_load_start__ , 4) : AT(ALIGN(__dynsym_load_start__ , 4)){. = ALIGN(4);KEEP (*(.dynsym))KEEP (*(.dynsym*)). = ALIGN(4);}__dynsym_end__ = __dynsym_load_start__ + SIZEOF(.dynsym);__dynstr_load_start__ =  ALIGN(__dynsym_end__ , 4);.dynstr ALIGN(__dynstr_load_start__ , 4) : AT(ALIGN(__dynstr_load_start__, 4)){. = ALIGN(4);KEEP (*(.dynstr))KEEP (*(.dynstr*)). = ALIGN(4);}__dynstr_end__ = __dynstr_load_start__ + SIZEOF(.dynstr);__reldyn_load_start__ =  ALIGN(__dynstr_end__ , 4);.rel.dyn ALIGN(__reldyn_load_start__ , 4) : AT(ALIGN(__reldyn_load_start__ , 4)){. = ALIGN(4);KEEP (*(.rel.dyn))KEEP (*(.rel.dyn*)). = ALIGN(4);}__reldyn_end__ = __reldyn_load_start__ + SIZEOF(.rel.dyn);__relplt_load_start__ =  ALIGN(__reldyn_end__ , 4);.rel.plt ALIGN(__relplt_load_start__ , 4) : AT(ALIGN(__relplt_load_start__ , 4)){. = ALIGN(4);KEEP (*(.rel.plt))KEEP (*(.rel.plt*)). = ALIGN(4);}__relplt_end__ = __relplt_load_start__ + SIZEOF(.rel.plt);__plt_load_start__ =  ALIGN(__relplt_end__ , 4);.plt ALIGN(__plt_load_start__ , 4) : AT(ALIGN(__plt_load_start__ , 4)){. = ALIGN(4);KEEP (*(.plt))KEEP (*(.plt*)). = ALIGN(4);}__plt_end__ = __plt_load_start__ + SIZEOF(.plt);__interp_load_start__ =  ALIGN(__plt_end__ , 4);.interp ALIGN(__interp_load_start__ , 4) : AT(ALIGN(__interp_load_start__ , 4)){. = ALIGN(4);KEEP (*(.interp))KEEP (*(.interp*)). = ALIGN(4);}__interp_end__ = __interp_load_start__ + SIZEOF(.interp);__hash_load_start__ =  ALIGN(__interp_end__ , 4);.hash ALIGN(__hash_load_start__ , 4) : AT(ALIGN(__hash_load_start__, 4)){. = ALIGN(4);KEEP (*(.hash))KEEP (*(.hash*)). = ALIGN(4);}__hash_end__ = __hash_load_start__ + SIZEOF(.hash);__text_load_start__ =  ALIGN(__hash_end__ , 4);.text ALIGN(__text_load_start__ , 4) : AT(ALIGN(__text_load_start__, 4)){__text_start__ = .;*(.text .text.* .glue_7t .glue_7 .gnu.linkonce.t.* .gcc_except_table  )}__text_end__ = __text_start__ + SIZEOF(.text);__dtors_load_start__ = ALIGN(__text_end__ , 4);.dtors ALIGN(__text_end__ , 4) : AT(ALIGN(__text_end__ , 4)){__dtors_start__ = .;KEEP (*(SORT(.dtors.*))) KEEP (*(.dtors))}__dtors_end__ = __dtors_start__ + SIZEOF(.dtors);__ctors_load_start__ = ALIGN(__dtors_end__ , 4);.ctors ALIGN(__dtors_end__ , 4) : AT(ALIGN(__dtors_end__ , 4)){__ctors_start__ = .;KEEP (*(SORT(.ctors.*))) KEEP (*(.ctors))}__ctors_end__ = __ctors_start__ + SIZEOF(.ctors);__got_load_start__ = ALIGN(__ctors_end__ , 4);.got ALIGN(__ctors_end__ , 4) : AT(ALIGN(__ctors_end__ , 4)){. = ALIGN(4);_sgot = .;KEEP (*(.got))KEEP (*(.got*)). = ALIGN(4);_egot = .;}__got_end__ =  __got_load_start__ + SIZEOF(.got);__rodata_load_start__ = ALIGN(__got_end__ , 4);.rodata ALIGN(__got_end__ , 4) : AT(ALIGN(__got_end__ , 4)){__rodata_start__ = .;*(.rodata .rodata.* .gnu.linkonce.r.*)}__rodata_end__ = __rodata_start__ + SIZEOF(.rodata);__code_size__ =  __rodata_end__ - __FLASH_segment_start__;__fast_load_start__ = ALIGN(__rodata_end__ , 4);__fast_load_end__ = __fast_load_start__ + SIZEOF(.fast);__new_got_start__ = ALIGN(__RAM_segment_start__ , 4);__new_got_end__ =  __new_got_start__ + SIZEOF(.got);.fast ALIGN(__new_got_end__ , 4) : AT(ALIGN(__rodata_end__ , 4)){__fast_start__ = .;*(.fast .fast.*)}__fast_end__ = __fast_start__ + SIZEOF(.fast);.fast_run ALIGN(__fast_end__ , 4) (NOLOAD) :{__fast_run_start__ = .;. = MAX(__fast_run_start__ + SIZEOF(.fast), .);}__fast_run_end__ = __fast_run_start__ + SIZEOF(.fast_run);__data_load_start__ = ALIGN(__fast_load_start__ + SIZEOF(.fast) , 4);.data ALIGN(__fast_run_end__ , 4) : AT(ALIGN(__fast_load_start__ + SIZEOF(.fast) , 4)){__data_start__ = .;*(.data .data.* .gnu.linkonce.d.*)}__data_end__ = __data_start__ + SIZEOF(.data);__data_load_end__ = __data_load_start__ + SIZEOF(.data);__FLASH_segment_used_end__ = ALIGN(__fast_load_start__ + SIZEOF(.fast) , 4) + SIZEOF(.data);.data_run ALIGN(__fast_run_end__ , 4) (NOLOAD) :{__data_run_start__ = .;. = MAX(__data_run_start__ + SIZEOF(.data), .);}__data_run_end__ = __data_run_start__ + SIZEOF(.data_run);__bss_load_start__ = ALIGN(__data_run_end__ , 4);.bss ALIGN(__data_run_end__ , 4) (NOLOAD) : AT(ALIGN(__data_run_end__ , 4)){__bss_start__ = .;*(.bss .bss.* .gnu.linkonce.b.*) *(COMMON)}__bss_end__ = __bss_start__ + SIZEOF(.bss);__non_init_load_start__ = ALIGN(__bss_end__ , 4);.non_init ALIGN(__bss_end__ , 4) (NOLOAD) : AT(ALIGN(__bss_end__ , 4)){__non_init_start__ = .;*(.non_init .non_init.*)}__non_init_end__ = __non_init_start__ + SIZEOF(.non_init);__heap_load_start__ = ALIGN(__non_init_end__ , 4);.heap ALIGN(__non_init_end__ , 4) (NOLOAD) : AT(ALIGN(__non_init_end__ , 4)){__heap_start__ = .;*(.heap). = ALIGN(MAX(__heap_start__ + __HEAPSIZE__ , .), 4);}__heap_end__ = __heap_start__ + SIZEOF(.heap);__data_size__ =  __heap_end__ - __RAM_segment_start__;
}

模块要求汇编文件(具体含义参考官方文档,这里主要注意入口函数名要对应模块文件中的入口函数)

    .text.align 4.syntax unified/* Define public symbols.  */.global __txm_module_preamble/* Define application-specific start/stop entry points for the module.  */.global demo_module_start/* Define common external refrences.  */.global _txm_module_thread_shell_entry.global _txm_module_callback_request_thread_entry__txm_module_preamble:.dc.l      0x4D4F4455                                       // Module ID.dc.l      0x6                                              // Module Major Version.dc.l      0x1                                              // Module Minor Version.dc.l      32                                               // Module Preamble Size in 32-bit words.dc.l      0x12345678                                       // Module ID (application defined).dc.l      0x02000004                                       // Module Properties where://   Bits 31-24: Compiler ID//           0 -> IAR//           1 -> ARM//           2 -> GNU//   Bits 23-3: Reserved//   Bit 2:  0 -> Disable shared/external memory access//           1 -> Enable shared/external memory access//   Bit 1:  0 -> No MPU protection//           1 -> MPU protection (must have user mode selected - bit 0 set)//   Bit 0:  0 -> Privileged mode execution//           1 -> User mode execution.dc.l      _txm_module_thread_shell_entry - . - 0           // Module Shell Entry Point.dc.l      demo_module_start - . - 0                        // Module Start Thread Entry Point.dc.l      0                                                // Module Stop Thread Entry Point .dc.l      1                                                // Module Start/Stop Thread Priority.dc.l      1024                                             // Module Start/Stop Thread Stack Size.dc.l      _txm_module_callback_request_thread_entry - . - 0 // Module Callback Thread Entry.dc.l      1                                                // Module Callback Thread Priority.dc.l      1024                                             // Module Callback Thread Stack Size.dc.l      __code_size__                                           // Module Code Size.dc.l      __data_size__                                           // Module Data Size.dc.l      0                                                // Reserved 0.dc.l      0                                                // Reserved 1.dc.l      0                                                // Reserved 2.dc.l      0                                                // Reserved 3.dc.l      0                                                // Reserved 4.dc.l      0                                                // Reserved 5.dc.l      0                                                // Reserved 6.dc.l      0                                                // Reserved 7.dc.l      0                                                // Reserved 8.dc.l      0                                                // Reserved 9.dc.l      0                                                // Reserved 10.dc.l      0                                                // Reserved 11.dc.l      0                                                // Reserved 12.dc.l      0                                                // Reserved 13.dc.l      0                                                // Reserved 14.dc.l      0                                                // Reserved 15

设置汇编文件 (这个直接使用的是threadx源码中提供的,主要做数据的拷贝和填充,共其他地方调用)

.text.align 4.syntax unified.global _gcc_setup.thumb_func
_gcc_setup:STMDB   sp!, {r3, r4, r5, r6, r7, lr}             // Store other preserved registersldr     r3, =__FLASH_segment_start__ldr     r4, =__RAM_segment_start__mov     r5,r0/* Copy GOT table. */ldr     r0, =__got_load_start__sub     r0,r0,r3add     r0,r0,r5ldr     r1, =__new_got_start__sub     r1,r1, r4add     r1,r1,r9ldr     r2, =__new_got_end__sub     r2,r2,r4add     r2,r2,r9new_got_setup:cmp     r1, r2          // See if there are more GOT entriesbeq     got_setup_done  // No, done with GOT setupldr     r6, [r0]        // Pickup current GOT entrycmp     r6, #0          // Is it 0?beq     address_built   // Yes, just skip the adjustmentcmp     r6, r4          // Is it in the code or data area?blt     flash_area      // If less than, it is a code addresssub     r6, r6, r4      // Compute offset of data areaadd     r6, r6, r9      // Build address based on the loaded data addressb       address_built   // Finished building address
flash_area:sub     r6, r6, r3      // Compute offset of code areaadd     r6, r6, r5      // Build address based on the loaded code address
address_built:str     r6, [r1]        // Store in new GOT tableadd     r0, r0, #4      // Move to next entryadd     r1, r1, #4      // b       new_got_setup   // Continue at the top of the loop
got_setup_done:/* Copy initialised sections into RAM if required. */ldr     r0, =__data_load_start__sub     r0,r0,r3add     r0,r0,r5ldr     r1, =__data_start__sub     r1,r1, r4add     r1,r1,r9ldr     r2, =__data_end__sub     r2,r2,r4add     r2,r2,r9bl      crt0_memory_copy/* Zero bss. */ldr     r0, =__bss_start__sub     r0,r0,r4add     r0,r0,r9ldr     r1, =__bss_end__sub     r1,r1,r4add     r1,r1,r9mov     r2, #0bl      crt0_memory_set/* Setup heap - not recommended for Threadx but here for compatibility reasons */ldr     r0, =__heap_start__sub     r0,r0,r4add     r0,r0,r9ldr     r1, =__heap_end__sub     r1,r1,r4add     r1,r1,r9sub     r1,r1,r0mov     r2, #0str     r2, [r0]add     r0, r0, #4str     r1, [r0]LDMIA   sp!, {r3, r4, r5, r6, r7, lr}       // Store other preserved registersbx      lr                                  // Return to caller.align 4/* Startup helper functions. */.thumb_func
crt0_memory_copy:cmp     r0, r1beq     memory_copy_donecmp     r2, r1beq     memory_copy_donesub     r2, r2, r1
memory_copy_loop:ldrb    r3, [r0]add     r0, r0, #1strb    r3, [r1]add     r1, r1, #1sub     r2, r2, #1cmp     r2, #0bne     memory_copy_loop
memory_copy_done:bx      lr.thumb_func
crt0_memory_set:cmp     r0, r1beq     memory_set_donestrb    r2, [r0]add     r0, r0, #1b       crt0_memory_set
memory_set_done:bx      lr/* Setup attibutes of heap section so it doesn't take up room in the elf file */.section .heap, "wa", %nobits

模块2

  1. 与模块1不同的是模块函数 和链接文件中的启动地址不同,其他均一样

入口函数

#define TXM_MODULE#include "txm_module.h"/*
*********************************************************************************************************
*                                    宏定义
*********************************************************************************************************
*/
#define DEFAULT_STACK_SIZE        1024#define App_Printf_ID1       (TXM_APPLICATION_REQUEST_ID_BASE)
#define App_Printf_ID2       (TXM_APPLICATION_REQUEST_ID_BASE + 1)#define MODULE_THREAD_PRIO                         3
#define MODULE_THREAD_PREEMPTION_THRESHOLD         MODULE_THREAD_PRIOULONG      AppModuleStk[DEFAULT_STACK_SIZE/4];/* 相关控制块 */
TX_THREAD               *thread_0;
TX_QUEUE                *resident_queue;/* 函数 */
void thread_0_entry(ULONG thread_input);
void Error_Handler1(void);/*
*********************************************************************************************************
*	函 数 名: default_module_start
*	功能说明: 动态APP入口
*	形    参: ---
*	返 回 值: 无
*********************************************************************************************************
*/
void  demo_module_start(ULONG id)
{CHAR    *pointer;/* 从主程序申请相关控制块,不在APP里面申请,防止APP出问题了影响主程序 */txm_module_object_allocate((void*)&thread_0, sizeof(TX_THREAD));/* 创建任务 */tx_thread_create(thread_0,"module thread 22",thread_0_entry,0,&AppModuleStk[0],DEFAULT_STACK_SIZE,MODULE_THREAD_PRIO,MODULE_THREAD_PREEMPTION_THRESHOLD,TX_NO_TIME_SLICE,TX_AUTO_START);}/*
*********************************************************************************************************
*	函 数 名: thread_0_entry
*	功能说明: 动态APP里面的任务
*	形    参: ---
*	返 回 值: 无
*********************************************************************************************************
*/
void thread_0_entry(ULONG thread_input)
{/* 防止警告 */UINT num = 0;while(1){/* 调用主程序里面的串口打印 */num++;txm_module_application_request(App_Printf_ID2, num, 0, 0);tx_thread_sleep(1000);}
}/*
*********************************************************************************************************
*	函 数 名: thread_0_entry
*	功能说明: 执行出错
*	形    参: ---
*	返 回 值: 无
*********************************************************************************************************
*/
void Error_Handler1(void)
{tx_thread_sleep(TX_WAIT_FOREVER);
}

链接文件

MEMORY
{FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 1024KRAM   (wx) : ORIGIN = 0x20000000, LENGTH = 128K
}SECTIONS
{__FLASH_segment_start__ = 0x08040000;__FLASH_segment_end__   = 0x08050000;__RAM_segment_start__   = 0x20000000;__RAM_segment_end__     = 0x20020000;__HEAPSIZE__ = 128;__preamble_load_start__ = __FLASH_segment_start__;.preamble __FLASH_segment_start__ : AT(__FLASH_segment_start__){__preamble_start__ = .;*(.preamble .preamble.*)}__preamble_end__ = __preamble_start__ + SIZEOF(.preamble);__dynsym_load_start__ =  ALIGN(__preamble_end__ , 4);.dynsym ALIGN(__dynsym_load_start__ , 4) : AT(ALIGN(__dynsym_load_start__ , 4)){. = ALIGN(4);KEEP (*(.dynsym))KEEP (*(.dynsym*)). = ALIGN(4);}__dynsym_end__ = __dynsym_load_start__ + SIZEOF(.dynsym);__dynstr_load_start__ =  ALIGN(__dynsym_end__ , 4);.dynstr ALIGN(__dynstr_load_start__ , 4) : AT(ALIGN(__dynstr_load_start__, 4)){. = ALIGN(4);KEEP (*(.dynstr))KEEP (*(.dynstr*)). = ALIGN(4);}__dynstr_end__ = __dynstr_load_start__ + SIZEOF(.dynstr);__reldyn_load_start__ =  ALIGN(__dynstr_end__ , 4);.rel.dyn ALIGN(__reldyn_load_start__ , 4) : AT(ALIGN(__reldyn_load_start__ , 4)){. = ALIGN(4);KEEP (*(.rel.dyn))KEEP (*(.rel.dyn*)). = ALIGN(4);}__reldyn_end__ = __reldyn_load_start__ + SIZEOF(.rel.dyn);__relplt_load_start__ =  ALIGN(__reldyn_end__ , 4);.rel.plt ALIGN(__relplt_load_start__ , 4) : AT(ALIGN(__relplt_load_start__ , 4)){. = ALIGN(4);KEEP (*(.rel.plt))KEEP (*(.rel.plt*)). = ALIGN(4);}__relplt_end__ = __relplt_load_start__ + SIZEOF(.rel.plt);__plt_load_start__ =  ALIGN(__relplt_end__ , 4);.plt ALIGN(__plt_load_start__ , 4) : AT(ALIGN(__plt_load_start__ , 4)){. = ALIGN(4);KEEP (*(.plt))KEEP (*(.plt*)). = ALIGN(4);}__plt_end__ = __plt_load_start__ + SIZEOF(.plt);__interp_load_start__ =  ALIGN(__plt_end__ , 4);.interp ALIGN(__interp_load_start__ , 4) : AT(ALIGN(__interp_load_start__ , 4)){. = ALIGN(4);KEEP (*(.interp))KEEP (*(.interp*)). = ALIGN(4);}__interp_end__ = __interp_load_start__ + SIZEOF(.interp);__hash_load_start__ =  ALIGN(__interp_end__ , 4);.hash ALIGN(__hash_load_start__ , 4) : AT(ALIGN(__hash_load_start__, 4)){. = ALIGN(4);KEEP (*(.hash))KEEP (*(.hash*)). = ALIGN(4);}__hash_end__ = __hash_load_start__ + SIZEOF(.hash);__text_load_start__ =  ALIGN(__hash_end__ , 4);.text ALIGN(__text_load_start__ , 4) : AT(ALIGN(__text_load_start__, 4)){__text_start__ = .;*(.text .text.* .glue_7t .glue_7 .gnu.linkonce.t.* .gcc_except_table  )}__text_end__ = __text_start__ + SIZEOF(.text);__dtors_load_start__ = ALIGN(__text_end__ , 4);.dtors ALIGN(__text_end__ , 4) : AT(ALIGN(__text_end__ , 4)){__dtors_start__ = .;KEEP (*(SORT(.dtors.*))) KEEP (*(.dtors))}__dtors_end__ = __dtors_start__ + SIZEOF(.dtors);__ctors_load_start__ = ALIGN(__dtors_end__ , 4);.ctors ALIGN(__dtors_end__ , 4) : AT(ALIGN(__dtors_end__ , 4)){__ctors_start__ = .;KEEP (*(SORT(.ctors.*))) KEEP (*(.ctors))}__ctors_end__ = __ctors_start__ + SIZEOF(.ctors);__got_load_start__ = ALIGN(__ctors_end__ , 4);.got ALIGN(__ctors_end__ , 4) : AT(ALIGN(__ctors_end__ , 4)){. = ALIGN(4);_sgot = .;KEEP (*(.got))KEEP (*(.got*)). = ALIGN(4);_egot = .;}__got_end__ =  __got_load_start__ + SIZEOF(.got);__rodata_load_start__ = ALIGN(__got_end__ , 4);.rodata ALIGN(__got_end__ , 4) : AT(ALIGN(__got_end__ , 4)){__rodata_start__ = .;*(.rodata .rodata.* .gnu.linkonce.r.*)}__rodata_end__ = __rodata_start__ + SIZEOF(.rodata);__code_size__ =  __rodata_end__ - __FLASH_segment_start__;__fast_load_start__ = ALIGN(__rodata_end__ , 4);__fast_load_end__ = __fast_load_start__ + SIZEOF(.fast);__new_got_start__ = ALIGN(__RAM_segment_start__ , 4);__new_got_end__ =  __new_got_start__ + SIZEOF(.got);.fast ALIGN(__new_got_end__ , 4) : AT(ALIGN(__rodata_end__ , 4)){__fast_start__ = .;*(.fast .fast.*)}__fast_end__ = __fast_start__ + SIZEOF(.fast);.fast_run ALIGN(__fast_end__ , 4) (NOLOAD) :{__fast_run_start__ = .;. = MAX(__fast_run_start__ + SIZEOF(.fast), .);}__fast_run_end__ = __fast_run_start__ + SIZEOF(.fast_run);__data_load_start__ = ALIGN(__fast_load_start__ + SIZEOF(.fast) , 4);.data ALIGN(__fast_run_end__ , 4) : AT(ALIGN(__fast_load_start__ + SIZEOF(.fast) , 4)){__data_start__ = .;*(.data .data.* .gnu.linkonce.d.*)}__data_end__ = __data_start__ + SIZEOF(.data);__data_load_end__ = __data_load_start__ + SIZEOF(.data);__FLASH_segment_used_end__ = ALIGN(__fast_load_start__ + SIZEOF(.fast) , 4) + SIZEOF(.data);.data_run ALIGN(__fast_run_end__ , 4) (NOLOAD) :{__data_run_start__ = .;. = MAX(__data_run_start__ + SIZEOF(.data), .);}__data_run_end__ = __data_run_start__ + SIZEOF(.data_run);__bss_load_start__ = ALIGN(__data_run_end__ , 4);.bss ALIGN(__data_run_end__ , 4) (NOLOAD) : AT(ALIGN(__data_run_end__ , 4)){__bss_start__ = .;*(.bss .bss.* .gnu.linkonce.b.*) *(COMMON)}__bss_end__ = __bss_start__ + SIZEOF(.bss);__non_init_load_start__ = ALIGN(__bss_end__ , 4);.non_init ALIGN(__bss_end__ , 4) (NOLOAD) : AT(ALIGN(__bss_end__ , 4)){__non_init_start__ = .;*(.non_init .non_init.*)}__non_init_end__ = __non_init_start__ + SIZEOF(.non_init);__heap_load_start__ = ALIGN(__non_init_end__ , 4);.heap ALIGN(__non_init_end__ , 4) (NOLOAD) : AT(ALIGN(__non_init_end__ , 4)){__heap_start__ = .;*(.heap). = ALIGN(MAX(__heap_start__ + __HEAPSIZE__ , .), 4);}__heap_end__ = __heap_start__ + SIZEOF(.heap);__data_size__ =  __heap_end__ - __RAM_segment_start__;
}

测试方式

  1. 主程序通过jlink直接下载烧录即可
  2. 模块应用,通过脚本生成bin文件,通过jflash进行对应的地址烧录,此步骤不能擦除主程序的存放的空间

烧录模块到对应的地址

在这里插入图片描述

测试结果(通过串口发送对应的命令。测试ok)

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/619231.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Web】VS Code 插件及快捷键

专栏文章索引&#xff1a;Web 有问题可私聊&#xff1a;QQ&#xff1a;3375119339 目录 一、安装步骤 二、插件 1.Chinese (Simplified) (简体中文) 2.open in browser 3.vscode-icons 4.Live Server 5.Live Server Preview 6.翻译(英汉词典) 三、快捷键 1.缩放代码…

【SERVERLESS】AWS Lambda上实操

通过Serverless的发展历程及带给我们的挑战&#xff0c;引出我们改如何改变思路&#xff0c;化繁为简&#xff0c;趋利避害&#xff0c;更好的利用其优势&#xff0c;来释放企业效能&#xff0c;为创造带来无限可能。 一 Serverless概述 无服务器计算近年来与云原生计算都是在…

如何解决电感啸叫

一、什么是电感噪声 电感器啸叫是指在20Hz-200Hz的当前激励频率下&#xff0c;电感器会发出人耳可以听到的吱吱声。这种现象在DC-DC的功率电感器中很常见。是什么引起电感啸叫以及如何解决&#xff1f; 二、电感啸叫的原因 电感啸叫声产生的主要的原因就是漆包线。我们都知道电…

【探讨】光场空间结构全维度非线性调控理论及应用

摘要&#xff1a;得益于数字全息与几何相位平面光学技术的逐渐成熟&#xff0c;空间结构光场调控及应用研究已在线性光学领域取得蓬勃发展。与之相比&#xff0c;以非线性光学为物理途径的相关研究虽能实现许多关键功能(如光场间信息交互)却仍处于起步阶段。笔者课题组在国家自…

C语言文件操作函数remove、rename、popen、fget

1.remove函数删除文件 remove 函数原型 : 删除指定的文件 ; #include <stdio.h> int remove(char *filename);参数&#xff1a; char *filename 是文件路径 ; 返回值&#xff1a;如果成功&#xff0c;则返回零。如果错误&#xff0c;则返回 -1&#xff0c;并设置 errn…

wpf下RTSP|RTMP播放器两种渲染模式实现

技术背景 在这篇blog之前&#xff0c;我提到了wpf下播放RTMP和RTSP渲染的两种方式&#xff0c;一种是通过控件模式&#xff0c;另外一种是直接原生RTSP、RTMP播放模块&#xff0c;回调rgb&#xff0c;然后在wpf下渲染&#xff0c;本文就两种方式做个说明。 技术实现 以大牛直…

双向链表的实现(详解)

目录 前言初始化双向链表的结构为双向链表的节点开辟空间头插尾插打印链表尾删头删查找指定位置之后的插入删除pos节点销毁双向链表 前言 链表的分类&#xff1a; 带头 不带头 单向 双向 循环 不循环 一共有 (2 * 2 * 2) 种链表 带头指的是&#xff1a;带有哨兵位节点 哨兵位&a…

webrtc中的Track,MediaChannel,MediaStream

文章目录 Track,MediaChannel,MediaStream的关系MediaStream的创建流程创建VideoChannel的堆栈创建VideoStream的堆栈 sdp中媒体参数信息的映射sdp中媒体信息参数设置体系参数设置流程参数映射体系 Track,MediaChannel,MediaStream的关系 Audio/Video track&#xff0c;MediaC…

Servlet实现常用功能及其他方法

getParameter 获取body或url中指定的key/value值 String classIdreq.getParameter("classId"); getQueryString 获取请求的所有查询参数key,values1 String queryStringreq.getQueryString(); from表单提交 前端通过from表单提交用户名和密码 <!DOCTYPE htm…

Java record类用法简介

参考资料 Java 16 新特性&#xff1a;record类新特性Record最全用法总结—动力节点总结Javaのレコードクラス从头学Java17-Stream API&#xff08;二&#xff09;结合Record、Optional 目录 一. 介绍二. 基本语法三. 各种特性示例3.1 准备3.2 创建&#xff0c;属性&#xff0c…

MySQL 社区版 安装总结

很早就安装过MySQL&#xff0c;没有遇到过什么问题&#xff0c;直接next就行了&#xff0c;这次在新电脑上安装却遇到了一些问题&#xff0c;记录一下。 安装的是MySQL社区版&#xff0c;下载地址是www.mysql.com&#xff0c;进入后选择DOWNLOAD页面&#xff0c;选择MySQL Com…

对常见FTP客户端/服务器的调查与分析

前言 主要是想看看常见的服务器和客户端是如何实现协议中要求的功能的&#xff0c;。 比如RF959要求的记录结构&#xff08;Record Structure&#xff09;、页结构&#xff08;Page Structure&#xff09;、Block Mode、Compress Mode&#xff0c;看起来就很抽象。 实测发现…