STM32用CUBEMx生成工程, 不使用CMSIS, 自己移植freertos

news2024/12/23 22:25:54

目录

完整工程代码:

零. 参考

一. 外围配置

二, 放进来freertos源代码

三.修改makefile

四. 解决修改函数重定义报错

五. 让Freertos的systick工作起来

六. 验证


完整工程代码:

​​​​​​https://download.csdn.net/download/u011493332/87821404

零. 参考

正在入门freertos, 网上教程还是以正宗的freertos的API为主, CMSIS又分了V1,V2, 看起来有点混乱, 干脆自己移植一个原版freertos, 省心

文章参考野火的教程:

FreeRTOS 内核实现与应用开发实战指南
—基于野火 STM32 全系列(M3/4/7)开发板

第13章 移植 FreeRTOS 到 STM32

他这个教程里非要修改人家freertos原始的目录结构, 我不想改人家原始目录结构

他的教程是Keil的,  我环境是GCC工具链的

一. 外围配置

1. 点一个灯

2. systick用定时器

 3. 

SWD RCC

二, 放进来freertos源代码

freertos源代码压缩包的目录结构, 用到的是Source文件夹

 在生成的工程里, 新建一个目录, 名字随意, 我这里是freertos_z, 把Source文件夹放进来, 新建一个config文件夹跟Source文件夹同级,  其实这个中间件文件夹应该放纯源码, config属于是用户文件, 按cubemx的文件管理习惯, 应该放在main.h旁边更好, 介意的话就那么做, 改改makefile就行

这时候, Souce文件夹里的portable文件夹里有很多文件, 是针对各种编译器的, 我们当前的工程是用GCC工具链的,  所以删掉那些无关的,  其实删不删都行,  makefile里面指定留着的就可以了

删之后, 只留了memMang和GCC/Arm_CM3,  因为我当前是一个STM32103RC的板子.   别的板子根据实际内核选择保留

添加config文件.   我这里用了一个以前cubemx生成的config文件

/* USER CODE BEGIN Header */
/*
 * FreeRTOS Kernel V10.0.1
 * Copyright (C) 2017 Amazon.com, Inc. or its affiliates.  All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of
 * this software and associated documentation files (the "Software"), to deal in
 * the Software without restriction, including without limitation the rights to
 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
 * the Software, and to permit persons to whom the Software is furnished to do so,
 * subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * http://www.FreeRTOS.org
 * http://aws.amazon.com/freertos
 *
 * 1 tab == 4 spaces!
 */
/* USER CODE END Header */

#ifndef FREERTOS_CONFIG_H
#define FREERTOS_CONFIG_H

/*-----------------------------------------------------------
 * Application specific definitions.
 *
 * These definitions should be adjusted for your particular hardware and
 * application requirements.
 *
 * These parameters and more are described within the 'configuration' section of the
 * FreeRTOS API documentation available on the FreeRTOS.org web site.
 *
 * See http://www.freertos.org/a00110.html
 *----------------------------------------------------------*/

/* USER CODE BEGIN Includes */
/* Section where include file can be added */
/* USER CODE END Includes */

/* Ensure definitions are only used by the compiler, and not by the assembler. */
#if defined(__ICCARM__) || defined(__CC_ARM) || defined(__GNUC__)
  #include <stdint.h>
  extern uint32_t SystemCoreClock;
#endif
#define configUSE_PREEMPTION                     1
#define configSUPPORT_STATIC_ALLOCATION          1
#define configSUPPORT_DYNAMIC_ALLOCATION         1
#define configUSE_IDLE_HOOK                      0
#define configUSE_TICK_HOOK                      0
#define configCPU_CLOCK_HZ                       ( SystemCoreClock )
#define configTICK_RATE_HZ                       ((TickType_t)1000)
#define configMAX_PRIORITIES                     ( 56 )
#define configMINIMAL_STACK_SIZE                 ((uint16_t)128)
#define configTOTAL_HEAP_SIZE                    ((size_t)1024*4)
#define configMAX_TASK_NAME_LEN                  ( 16 )
#define configUSE_TRACE_FACILITY                 1
#define configUSE_16_BIT_TICKS                   0
#define configUSE_MUTEXES                        1
#define configQUEUE_REGISTRY_SIZE                8
#define configUSE_RECURSIVE_MUTEXES              1
#define configUSE_COUNTING_SEMAPHORES            1
#define configUSE_PORT_OPTIMISED_TASK_SELECTION  0

/* Co-routine definitions. */
#define configUSE_CO_ROUTINES                    0
#define configMAX_CO_ROUTINE_PRIORITIES          ( 2 )

/* Software timer definitions. */
#define configUSE_TIMERS                         1
#define configTIMER_TASK_PRIORITY                ( 2 )
#define configTIMER_QUEUE_LENGTH                 10
#define configTIMER_TASK_STACK_DEPTH             256

/* Set the following definitions to 1 to include the API function, or zero
to exclude the API function. */
#define INCLUDE_vTaskPrioritySet            1
#define INCLUDE_uxTaskPriorityGet           1
#define INCLUDE_vTaskDelete                 1
#define INCLUDE_vTaskCleanUpResources       0
#define INCLUDE_vTaskSuspend                1
#define INCLUDE_vTaskDelayUntil             1
#define INCLUDE_vTaskDelay                  1
#define INCLUDE_xTaskGetSchedulerState      1
#define INCLUDE_xTimerPendFunctionCall      1
#define INCLUDE_xQueueGetMutexHolder        1
#define INCLUDE_uxTaskGetStackHighWaterMark 1
#define INCLUDE_eTaskGetState               1

/*
 * The CMSIS-RTOS V2 FreeRTOS wrapper is dependent on the heap implementation used
 * by the application thus the correct define need to be enabled below
 */
#define USE_FreeRTOS_HEAP_4

/* Cortex-M specific definitions. */
#ifdef __NVIC_PRIO_BITS
 /* __BVIC_PRIO_BITS will be specified when CMSIS is being used. */
 #define configPRIO_BITS         __NVIC_PRIO_BITS
#else
 #define configPRIO_BITS         4
#endif

/* The lowest interrupt priority that can be used in a call to a "set priority"
function. */
#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY   15

/* The highest interrupt priority that can be used by any interrupt service
routine that makes calls to interrupt safe FreeRTOS API functions.  DO NOT CALL
INTERRUPT SAFE FREERTOS API FUNCTIONS FROM ANY INTERRUPT THAT HAS A HIGHER
PRIORITY THAN THIS! (higher priorities are lower numeric values. */
#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 5

/* Interrupt priorities used by the kernel port layer itself.  These are generic
to all Cortex-M ports, and do not rely on any particular library functions. */
#define configKERNEL_INTERRUPT_PRIORITY 		( configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )
/* !!!! configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to zero !!!!
See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html. */
#define configMAX_SYSCALL_INTERRUPT_PRIORITY 	( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )

/* Normal assert() semantics without relying on the provision of an assert.h
header file. */
/* USER CODE BEGIN 1 */
#define configASSERT( x ) if ((x) == 0) {taskDISABLE_INTERRUPTS(); for( ;; );}
/* USER CODE END 1 */

/* Definitions that map the FreeRTOS port interrupt handlers to their CMSIS
standard names. */
#define vPortSVCHandler    SVC_Handler
#define xPortPendSVHandler PendSV_Handler

/* IMPORTANT: This define is commented when used with STM32Cube firmware, when the timebase source is SysTick,
              to prevent overwriting SysTick_Handler defined within STM32Cube HAL */

#define xPortSysTickHandler SysTick_Handler

/* USER CODE BEGIN Defines */
/* Section where parameter definitions can be added (for instance, to override default ones in FreeRTOS.h) */
/* USER CODE END Defines */

#endif /* FREERTOS_CONFIG_H */

三.修改makefile

添加参与编译的c文件, 和.h文件路径

...

######################################
# source
######################################
# C sources
C_SOURCES =  \
Core/src/app.c \
Core/Src/main.c \
Middlewares/Third_Party/freertos_z/Source/croutine.c \
Middlewares/Third_Party/freertos_z/Source/event_groups.c \
Middlewares/Third_Party/freertos_z/Source/list.c \
Middlewares/Third_Party/freertos_z/Source/queue.c \
Middlewares/Third_Party/freertos_z/Source/stream_buffer.c \
Middlewares/Third_Party/freertos_z/Source/tasks.c \
Middlewares/Third_Party/freertos_z/Source/timers.c \
Middlewares/Third_Party/freertos_z/Source/portable/MemMang/heap_4.c \
Middlewares/Third_Party/freertos_z/Source/portable/GCC/ARM_CM3/port.c \

...

...


# C includes
C_INCLUDES =  \
-ICore/Inc \
-IMiddlewares/Third_Party/freertos_z/Source/include \
-IMiddlewares/Third_Party/freertos_z/Source/portable/GCC/ARM_CM3 \
-IMiddlewares/Third_Party/freertos_z/config \
-IDrivers/STM32F1xx_HAL_Driver/Inc/Legacy \
-IDrivers/STM32F1xx_HAL_Driver/Inc \
-IDrivers/CMSIS/Device/ST/STM32F1xx/Include \
-IDrivers/CMSIS/Include


...

路径以实际文件位置为准

四. 解决修改函数重定义报错

这个时候, 可以尝试编译一次, 不过必然报错, 如果makefile里文件路径都对的话, 最后会留下3个报错, 3个都是函数重复定义

因为freertos使用了3个自己的中断处理函数, cubemx默认也自动生成他们, 就是FreeRTOSConfig.h最后几行这几个宏

freertos把原来cubemx的中断函数重新定义了一个名字, 以此来实现可移植, 同时也在平台的port.c里重新定义了他们三个.  

这里不能简单的把stm32f1xx_it.c里的三个中断删了,  那样用cubemx重新生成工程时候他们还会出来,   所以这里应该在cubemx里面设置, 取消他们的生成

 取消掉之后, 用cubemx重新生成工程代码, 这时, 中断.c里面这3个函数没有了.   编译系统将会去编译port.c里面的三个中断函数,  到这里, 严格说, 就已经是移植完成状态.  但是还差系统systick的设置

五. 让Freertos的systick工作起来

一开始, 我们设置了systick使用tim2,   这样生成两段代码,  一是Core\Src\stm32f1xx_it.c里面

 

还有 main.c里面的回调函数

这里只要修改回调函数就可以了, 让tim2中断发生时候, 更新freertos的systick, 同时屏蔽hal的systick. 再一次同时, 还要不让cubemx的自动生成干扰我们的修改, 修改后如下, 内容参考了野火的教程

 

 代码

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
  /* USER CODE BEGIN Callback 0 */
#if 0
  /* USER CODE END Callback 0 */
  if (htim->Instance == TIM2) {
    HAL_IncTick();
  }
  /* USER CODE BEGIN Callback 1 */
#endif

    if (htim->Instance == TIM2) {
#if (INCLUDE_xTaskGetSchedulerState == 1 )
	if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) {
#endif /* INCLUDE_xTaskGetSchedulerState */
		xPortSysTickHandler();
#if (INCLUDE_xTaskGetSchedulerState == 1 )
	}
#endif /* INCLUDE_xTaskGetSchedulerState */
    }
  /* USER CODE END Callback 1 */
}

到这里移植全部完成

剩下的就是验证了

六. 验证

我添加里app.c和app.h, 代码都在app.c里写, main.c只调用app.c里一个函数

app.c: 

#include "app.h"
/* FreeRTOS 头文件 */
#include "FreeRTOS.h"
#include "task.h"
#include <stdio.h>

/**************************** 任务句柄 ********************************/
/*
 * 任务句柄是一个指针,用于指向一个任务,当任务创建好之后,它就具有了一个任务句柄
 * 以后我们要想操作这个任务都需要通过这个任务句柄,如果是自身的任务操作自己,那么
 * 这个句柄可以为 NULL。
 */
/* 创建任务句柄 */
static TaskHandle_t AppTaskCreate_Handle;
/* LED 任务句柄 */
static TaskHandle_t LED_Task_Handle;

/******************************* 内核对象句柄 **************************/
/*
* 信号量,消息队列,事件标志组,软件定时器这些都属于内核的对象,要想使用这些内核
* 对象,必须先创建,创建成功之后会返回一个相应的句柄。实际上就是一个指针,后续我
* 们就可以通过这个句柄操作这些内核对象。
*
*
内核对象说白了就是一种全局的数据结构,通过这些数据结构我们可以实现任务间的通信,
* 任务间的事件同步等各种功能。至于这些功能的实现我们是通过调用这些内核对象的函数
* 来完成的
*
*/

/************************** 全局变量声明 *******************************/
/*
 * 当我们在写应用程序的时候,可能需要用到一些全局变量。
 */
/* AppTaskCreate 任务任务堆栈 */
static StackType_t AppTaskCreate_Stack[128];
/* LED 任务堆栈 */
static StackType_t LED_Task_Stack[128];

/* AppTaskCreate 任务控制块 */
static StaticTask_t AppTaskCreate_TCB;
/* AppTaskCreate 任务控制块 */
static StaticTask_t LED_Task_TCB;

/* 空闲任务任务堆栈 */
static StackType_t Idle_Task_Stack[configMINIMAL_STACK_SIZE];
/* 定时器任务堆栈 */
static StackType_t Timer_Task_Stack[configTIMER_TASK_STACK_DEPTH];

/* 空闲任务控制块 */
static StaticTask_t Idle_Task_TCB;
/* 定时器任务控制块 */
static StaticTask_t Timer_Task_TCB;

/*
*************************************************************************
* 函数声明
*************************************************************************
*/
static void AppTaskCreate(void); /* 用于创建任务 */

static void LED_Task(void *pvParameters); /* LED_Task 任务实现 */

/**
 * 使用了静态分配内存,以下这两个函数是由用户实现,函数在 task.c 文件中有引用
 *当且仅当 configSUPPORT_STATIC_ALLOCATION 这个宏定义为 1 的时候才有效
 */
void vApplicationGetTimerTaskMemory(StaticTask_t **ppxTimerTaskTCBBuffer,
				    StackType_t **ppxTimerTaskStackBuffer,
				    uint32_t *pulTimerTaskStackSize);

void vApplicationGetIdleTaskMemory(StaticTask_t **ppxIdleTaskTCBBuffer,
				   StackType_t **ppxIdleTaskStackBuffer,
				   uint32_t *pulIdleTaskStackSize);

/***********************************************************************
 * @ 函数名 : AppTaskCreate
 * @ 功能说明: 为了方便管理,所有的任务创建函数都放在这个函数里面
 * @ 参数 : 无
 * @ 返回值 : 无
 ***************************************************************/
static void AppTaskCreate(void)
{
	taskENTER_CRITICAL(); // 进入临界区

	/* 创建 LED_Task 任务 */
	LED_Task_Handle = xTaskCreateStatic((TaskFunction_t)LED_Task,	    // 任务函数
					    (const char *)"LED_Task",	    // 任务名称
					    (uint32_t)128,		    // 任务堆栈大小
					    (void *)NULL,		    // 传递给任务函数的参数
					    (UBaseType_t)4,		    // 任务优先级
					    (StackType_t *)LED_Task_Stack,  // 任务堆栈
					    (StaticTask_t *)&LED_Task_TCB); // 任务控制块

	if (NULL != LED_Task_Handle) /* 创建成功 */
		printf("LED_Task create success\n");
	else
		printf("LED_Task create failed\n");

	vTaskDelete(AppTaskCreate_Handle); // 删除 AppTaskCreate 任务

	taskEXIT_CRITICAL(); // 退出临界区
}

/**************************************************************
 * @ 函数名 : LED_Task
 * @ 功能说明: LED_Task 任务主体
 * @ 参数 :
 * @ 返回值 : 无
 ********************************************************************/
static void LED_Task(void *parameter)
{
	while (1) {
		vTaskDelay(500);
		HAL_GPIO_WritePin(LED2_GPIO_Port, LED2_Pin, GPIO_PIN_RESET);

		vTaskDelay(500);
		HAL_GPIO_WritePin(LED2_GPIO_Port, LED2_Pin, GPIO_PIN_SET);
	}
}

/**
**********************************************************************
* @brief 获取空闲任务的任务堆栈和任务控制块内存
* ppxTimerTaskTCBBuffer : 任务控制块内存
* ppxTimerTaskStackBuffer : 任务堆栈内存
* pulTimerTaskStackSize : 任务堆栈大小
* @author fire
* @version V1.0
* @date 2018-xx-xx
**********************************************************************
*/
void vApplicationGetIdleTaskMemory(StaticTask_t **ppxIdleTaskTCBBuffer,
				   StackType_t **ppxIdleTaskStackBuffer,
				   uint32_t *pulIdleTaskStackSize)
{
	*ppxIdleTaskTCBBuffer = &Idle_Task_TCB;		  /* 任务控制块内存 */
	*ppxIdleTaskStackBuffer = Idle_Task_Stack;	  /* 任务堆栈内存 */
	*pulIdleTaskStackSize = configMINIMAL_STACK_SIZE; /* 任务堆栈大小 */
}

/**
*********************************************************************
* @brief 获取定时器任务的任务堆栈和任务控制块内存
* ppxTimerTaskTCBBuffer : 任务控制块内存
* ppxTimerTaskStackBuffer : 任务堆栈内存
* pulTimerTaskStackSize : 任务堆栈大小
* @author fire
* @version V1.0
* @date 2018-xx-xx
**********************************************************************
*/
void vApplicationGetTimerTaskMemory(StaticTask_t **ppxTimerTaskTCBBuffer,
				    StackType_t **ppxTimerTaskStackBuffer,
				    uint32_t *pulTimerTaskStackSize)
{
	*ppxTimerTaskTCBBuffer = &Timer_Task_TCB;	       /* 任务控制块内存 */
	*ppxTimerTaskStackBuffer = Timer_Task_Stack;	       /* 任务堆栈内存 */
	*pulTimerTaskStackSize = configTIMER_TASK_STACK_DEPTH; /* 任务堆栈大小 */
}

void app_initial(void)
{
	// vTaskStartScheduler();
}

extern UART_HandleTypeDef huart1;

void app_start(void)
{

	HAL_UART_Transmit(&huart1, (uint8_t *)"TEST\r\n", 16, 100);
	printf("app start\r\n");
	/* 创建 AppTaskCreate 任务 */
	AppTaskCreate_Handle = xTaskCreateStatic((TaskFunction_t)AppTaskCreate,
						 (const char *)"AppTaskCreate", // 任务名称
						 (uint32_t)128,			// 任务堆栈大小
						 (void *)NULL,			// 传递给任务函数的参数
						 (UBaseType_t)3,		// 任务优先级
						 (StackType_t *)AppTaskCreate_Stack,
						 (StaticTask_t *)&AppTaskCreate_TCB);

	if (NULL != AppTaskCreate_Handle) /* 创建成功 */
		vTaskStartScheduler();	  /* 启动任务,开启调度 */

	while (1)
		; /* 正常不会执行到这里 */
}

也是参考野火的代码.   删了他代码里的bsp初始化,  因为cubemx已经帮我们完成了

完毕!

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

虚拟机磁盘扩容及重新分区方法

创建虚拟机的时候&#xff0c;如果分配的磁盘过小&#xff0c;在后续的使用时可能需要进行扩容&#xff0c;在扩容后你会发现好像磁盘并没有变大&#xff0c;这时候就需要进行重新分区 一、虚拟机扩容 在将需要扩容的虚拟机关机后&#xff0c;点击VMware的菜单栏中的虚拟机&…

面试:前端安全之XSS及CSRF

一、概念&#xff1a; XSS攻击全称跨站脚本攻击(Cross Site Scripting); CSRF&#xff08;Cross-site request forgery&#xff09;跨站请求伪造&#xff0c;也被称为“One Click Attack”或者Session Riding&#xff0c;通常缩写为CSRF或者XSRF;是一种挟制用户在当前已登录的…

合同管理系统对企业的重要性,不仅能降本增效,还能规避风险

企业管理合同有哪些通病 企业在管理合同会经常遇到在约定条款时存在空泛、笼统的情况&#xff0c;导致在实际操作时产生争议&#xff0c;没有系统化进行操作规范&#xff0c;由于签订合同的时候可能存在一些法律问题&#xff0c;如未经授权签署的合同、涉及侵犯他人权益的条款…

港联证券|北向资金为何大量买入?哪些股容易受到青睐?

北向资金由于流动情况透明且披露及时&#xff0c;一直备受投资者们的关注。那么北向资金为何大量买入&#xff1f;哪些股容易受到青睐&#xff1f;港联证券也为大家准备了相关内容&#xff0c;以供参考。 北向资金为何大量买入&#xff1f; 1、中国经济增长预期较好。这为北向…

Prettier Eslint Stylelint Husky lint-staged

关于代码格式的讨论数不胜数&#xff0c;个人认为没有绝对的对与错&#xff0c;代码只要始终遵守可读性&#xff0c;可拓展性强这两点我认为就是优秀的代码。 如果是个人项目那就没有什么问题&#xff0c;但是如果涉及到多人开发&#xff0c;就不可避免的遇到代码风格迥异&…

uni-app 中如何实现触底加载功能

&#x1f468;&#x1f3fb;‍&#x1f4bb; 热爱摄影的程序员 &#x1f468;&#x1f3fb;‍&#x1f3a8; 喜欢编码的设计师 &#x1f9d5;&#x1f3fb; 擅长设计的剪辑师 &#x1f9d1;&#x1f3fb;‍&#x1f3eb; 一位高冷无情的编码爱好者 大家好&#xff0c;我是全栈 …

队列与C++中的std::queue详解(多图超详细)

文章目录 队列&#xff08;Queue&#xff09;什么是队列队列的基本操作和应用1. 入队2. 出队3. 入队出队的复杂度和应用 类模板std::queue形参T和Container成员函数1. 元素访问2. 容量3. 队列的修改 用法示例 队列&#xff08;Queue&#xff09; 什么是队列 队列就是一种线性…

单模光纤三维模场分布动画的MATLAB实现

利用MATLAB的动画功能&#xff0c;我们可以把上一篇中绘制的三维分布图变为动画 clear close all clcV 2.4000; U 1.6453; W 1.7473;Npoint 501; Rx 5; Ry 5; x linspace(-Rx,Rx,Npoint); y linspace(-Ry,Ry,Npoint); [X Y] meshgrid(x,y); R sqrt(X.^2Y.^2);E1 …

Android自定义View:超过最大高度时支持滚动并且解决滑动冲突的TextView

VerticalScrollTextView&#xff1a;超过最大高度时支持滚动并且解决滑动冲突的TextView 正如标题所说&#xff0c;这个自定义TextView在它的行数超过最大行数或是高度超过最大高度限制时&#xff0c;会将TextView设置为可纵向滑动的状态&#xff0c;如果没有超过限制&#xf…

python 的APScheduler配置的定时任务会被Miss掉

背景 python 的APScheduler配置的定时任务会被Miss掉&#xff0c;经常在控制台收到一些Miss的告警信息&#xff0c;就觉得是任务太多导致的&#xff0c;为了定位到具体的原因&#xff0c;看了一些源码&#xff0c;了解到了定时任务的6大模块的协同工作模式。异常信息及来源 异…

01.GATK人种系变异最佳实践SnakeMake流程:WorkFlow简介

<~生~信~交~流~与~合~作~请~关~注~公~众~号生信探索> 学习的第一个GATK找变异流程&#xff0c;人的种系变异的短序列变异&#xff0c;包括SNP和INDEL。写了一个SnakeMake分析流程&#xff0c;从fastq文件到最后的vep注释后的VCF文件&#xff0c;关于VCF的介绍可以参考上一…

Windows 安装 GCC

文章目录 GCC 是什么&#xff1f;GCC 和 gcc 什么关系&#xff1f;Windows 安装 GCC选型下载安装配置环境变量验证 参考文献 GCC 是什么&#xff1f; GCC&#xff08;GNU Compiler Collection&#xff09;是一个开源的编译器套件&#xff0c;由 GNU 项目开发和维护。 GNU 编译…

悠可集团再获金鼠标3项大奖,自研营销工具助推全渠道数字营销

5月19日,第14届金鼠标数字营销大赛评选结果揭晓,悠可集团斩获3项大奖,其中悠可集团被评为“年度数字营销杰出代理商”,悠可DTC团队自主研发的智能广告投放引擎Turbo Media及点正科技申报的KOL优先自动化工具均荣获“年度最佳数字营销工具”奖项。 据主办方介绍,本届金鼠标数字营…

java基础 - jvm 堆、栈、方法区 java 内存模型

一、 概览 在进入主题前&#xff0c;我们先了解一些相关的知识&#xff0c;方面后面对运行时数据区进行分类。 进程中&#xff0c;有很多数据是多线程之间共享的&#xff0c;线程在执行时&#xff0c;会先从主存中读取数据&#xff0c;然后复制一份到高速缓存中&#xff0c;当…

【Docker容器】Docker安装Kibana详细步骤(看完这一篇就够啦!)

前言 安装Kibana的版本一定要跟ElaticSearch的版本是一样的&#xff0c;这样才不会容易出问题。 安装ElasticSearch请点击以下链接前去学习。 【Docker容器】Docker安装ElasticSearch详细步骤(看这一篇就够啦&#xff01;) 安装 1.访问镜像官网 https://hub.docker.com/ 搜索…

Java的内存模型(Java Memory Mode,JMM)

并发编程模型的两个关键问题 线程之间如何通信及线程之间如何同步。 线程之间如何通信&#xff1a;共享内存&#xff0c;消息传递线程之间如何同步通信是指线程之间以何种机制来 交换信息同步是指程序中用于控制不同线程间 操作发生相对顺序 的机制在共享内存的并发模型里&a…

【PHP图片托管】免费CFimagehost图床源码搭建私人图床 - 无需数据库

文章目录 1.前言2. CFImagehost网站搭建2.1 CFImagehost下载和安装2.2 CFImagehost网页测试2.3 cpolar的安装和注册 3.本地网页发布3.1 Cpolar临时数据隧道3.2 Cpolar稳定隧道&#xff08;云端设置&#xff09;3.3.Cpolar稳定隧道&#xff08;本地设置&#xff09; 4.公网访问测…

C#入门:编写运行第一个Windows窗体应用程序Helloworld_WinForm

下载及安装Visual Studio的链接&#xff0c;具体见C#入门&#xff1a;编写运行第一个C#程序Helloworld 目录 下载.NET桌面开发组件创建新项目添加控件编辑程序运行查看效果补充 下载.NET桌面开发组件 Visual Studio中需下载安装.NET桌面开发组件。 创建新项目 创建项目&…

【2】Jmeter获取token,模拟多用户并发及token存储文本文件

按以下步骤来&#xff0c;以下各种处理程序的放置位置很重要&#xff01;&#xff01;不然会出现各种问题&#xff1a; 1、setup线程组 前置获取token的接口&#xff08;login&#xff0c;以下都用login表示获取token接口&#xff09;请求&#xff0c;获取类似token等后续需要…

10 个对 Android 开发者有用的 Kotlin 扩展函数 #2

10 个对 Android 开发者有用的 Kotlin 扩展函数 #2 通过出色的 Kotlin 扩展提高您的工作效率 EditText 通过EditText的“text”属性&#xff0c;您可以快速获取EditText中的文本。但是&#xff0c;这个文本是“可编辑”的&#xff0c;因此每次都需要将其转换为字符串才能获…