【05】FreeRTOS的中断管理

news2024/11/17 1:53:48

目录

1.什么是中断

2.中断优先级分组

2.1中断优先级分组-介绍

2.2中断优先级分组-配置

2.3中断优先级分组-特点

3.中断相关寄存器

3.1寄存器地址

3.2在FreeRTOS中配置PendSV和Systick中断优先级

3.3中断相关寄存器

4.FreeRTOS中断管理实验

4.1修改freertos_demo.c

4.2移除工程中exti.c文件

4.3实现定时器功能

 4.4实现关闭和开启中断功能

5.总结


1.什么是中断

        简介:让CPU打断正常运行的程序,转而去处理紧急的事件(程序,ISR中断服务函数),就叫中断。

中断执行机制,可简单概括为三步:

1,中断请求:外设产生中断请求(GPIO外部中断、定时器中断等);

2,响应中断:CPU停止执行当前程序,转而去执行中断处理程序(ISR);

3,退出中断:执行完毕,返回被打断的程序处,继续往下执行。(打断哪个点,就返回哪个点继续执行

举例说明:小明在看视频的时候突然肚子疼,必须要上厕所,打断看视频的任务,去上厕所, 暂停视频播放,上完厕所后,继续从暂停处继续观看视频。

2.中断优先级分组

2.1中断优先级分组-介绍

        ARM Cortex-M 使用了 8 位宽的寄存器来配置中断的优先等级(最大{\color{Red} 2^{8}},256个优先级,0~255),这个寄存器就是中断优先级配置寄存器。但STM32,只用了中断优先级配置寄存器的高4位 [7 : 4],所以STM32提供了最大16级的中断优先等级。

 STM32 的中断优先级可以分为抢占优先级子优先级

抢占优先级: 抢占优先级高的中断可以打断正在执行但抢占优先级低的中断

子优先级:当同时发生具有相同抢占优先级的两个中断时,子优先级数值小的优先执行(例如有两个中断int1、int2,抢占优先级都为2,而子优先级int1为1,int2为0。假设int1正在执行,触发了int2,int2并不会抢占int1,因为抢占优先级相同,int2会在int1执行完后被执行。

注意:中断优先级数值越小越优先

2.2中断优先级分组-配置

        一共有 5 种分配方式,对应着中断优先级分组的 5 个组,FreeRTOS为了方便管理使用的是优先级分组4,全部用于抢占优先级。

优先级分组抢占优先级子优先级优先级配置寄存器高 4 位
NVIC_PriorityGroup_00 级抢占优先级0-15 级子优先级

0bit 用于抢占优先级

4bit 用于子优先级

NVIC_PriorityGroup_1 0-1 级抢占优先级0-7 级子优先级 

1bit 用于抢占优先级

3bit 用于子优先级

NVIC_PriorityGroup_20-3 级抢占优先级0-3 级子优先级

2bit 用于抢占优先级

2bit 用于子优先级

NVIC_PriorityGroup_3 0-7 级抢占优先级0-1 级子优先级

3bit 用于抢占优先级

1bit 用于子优先级

NVIC_PriorityGroup_40-15 级抢占优先级 0 级子优先级

4bit 用于抢占优先级

0bit 用于子优先级

通过调用函数HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4)即可完成设置(在HAL_Init中设置)  

FreeRTOS官网关于中断说明:FreeRTOS官网中断说明地址

2.3中断优先级分组-特点

1、低于configMAX_SYSCALL_INTERRUPT_PRIORITY优先级的中断里才允许调用FreeRTOS 的API函数(在代码中configMAX_SYSCALL_INTERRUPT_PRIORITY设置的是5,所以能被FreeRTOS操作的中断优先级是5~15

2、建议将所有优先级位指定为抢占优先级位,方便FreeRTOS管理(调用函数HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4)

3、中断优先级数值越小越优先,任务优先级数值越大越优先

3.中断相关寄存器

3.1寄存器地址

三个系统中断优先级配置寄存器,分别为 SHPR1、 SHPR2、 SHPR3。

SHPR1寄存器首地址:0xE000ED18

SHPR2寄存器首地址:0xE000ED1C

SHPR3寄存器首地址:0xE000ED20

        表中一个地址是8个位,一个寄存器是32位。如果想设置PendSV的优先级,则需要从SHPR3首地址偏移16位;如果想设置SysTick的优先级,则SHPR3首地址偏移24位。

表出自:《Cortex M3权威指南(中文)》第286页

         注意:SysTick和PendSV的优先级设置,嘀嗒定时器Systick给系统提供心跳节拍,任务切换、调度都是在PendingSV中实现。

3.2在FreeRTOS中配置PendSV和Systick中断优先级

以下程序中SHPR3寄存器设置PendSV和SysTick的优先级。

 其中oxe00ed20是寄存器SHPR3的首地址。

PendSV的首地址等于变量configKERNEL_INTERRUPT_PRIORITY左移16位,同理,Systick的首地址等于configKERNEL_INTERRUPT_PRIORITY左移24位。

 configKERNEL_INTERRUPT_PRIORITY为变量configLIBRARY_LOWEST_INTERRUPT_PRIORITY左移8-configPRIO_BITS位(其中configPRIO_BITS宏定义为4,configLIBRARY_LOWEST_INTERRUPT_PRIORITY宏定义为15),即将15左移4位,STM32优先级配置低4位并没有用到,左移4位到高四位。

         经过以上配置将PendSV和Systick设置优先级位15。

PendSV和SysTick设置最低优先级

设置最低:保证系统任务切换不会阻塞系统其他中断的响应(中断可以打断任务,任务不能打断中断,因为中断是较为紧急的事情)

3.3中断相关寄存器

 三个中断屏蔽寄存器,分别为 PRIMASK、 FAULTMASK 和BASEPRI 

FreeRTOS所使用的中断管理就是利用的BASEPRI这个寄存器。

BASEPRI:屏蔽优先级低于某一个阈值的中断,当设置为0时,则不关闭任何中断。

比如: BASEPRI设置为0x50,代表中断优先级在5~15内的均被屏蔽,0~4的中断优先级正常执行。

关中断程序示例(中断优先级在5 ~ 15的全部被关闭):

#define portDISABLE_INTERRUPTS() 		vPortRaiseBASEPRI()
static portFORCE_INLINE void vPortRaiseBASEPRI( void ) 
{ 
	uint32_t ulNewBASEPRI = configMAX_SYSCALL_INTERRUPT_PRIORITY; 
	__asm 
	{
		msr basepri, ulNewBASEPRI 
		dsb 
		isb
	} 
}
#define configMAX_SYSCALL_INTERRUPT_PRIORITY            ( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )
#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY        5      /* FreeRTOS可管理的最高中断优先级 */ 

        以上程序中变量 configMAX_SYSCALL_INTERRUPT_PRIORITY为0x50,赋值给变量ulNewBASEPRI ,使用汇编语言将ulNewBASEPRI 赋值给basepri寄存器。

 当BASEPRI设置为0x50时:

在中断服务函数中调度FreeRTOS的API函数需注意:

1、中断服务函数的优先级需在FreeRTOS所管理的范围内;

2、在中断服务函数里边需调用FreeRTOS的API函数,必须使用带“FromISR”后缀的函数 ;

3、优先级分组必须设置为组4,全部设置成抢占优先级。

开中断程序示例(BASEPRI:屏蔽优先级低于某一个阈值的中断,当设置为0时,则不关闭任何中断): 

#define portENABLE_INTERRUPTS()		 vPortSetBASEPRI( 0 )
static portFORCE_INLINE void vPortSetBASEPRI( uint32_t ulBASEPRI ) 
{ 
	__asm
	{
		msr basepri, ulBASEPRI
	} 
}

         以上程序将寄存器basepri设置成0。

4.FreeRTOS中断管理实验

1、实验目的:学会使用FreeRTOS的中断管理! 本实验会使用两个定时器,一个优先级为4,一个优先级为6,注意:系统所管理的优先级范围:5~15, 现象:两个定时器每1s,打印一段字符串,当关中断时,停止打印,开中断时持续打印。(优先级为6的定时器,在关闭中断时会停止打印,而优先级为4的定时器,不在5~15内,不受影响

2、实验设计:将设计2个任务:start_task、task1

2个任务的功能如下:

start_task:用来创建task1任务;

task1:中断测试任务,任务中将调用关中断和开中断函数来体现对中断的管理作用。

本次实验基于本系列文章【04】FreeRTOS的任务挂起与恢复   工程文件实现。

4.1修改freertos_demo.c

        删除上一节中用到的任务2、任务3相关代码,并删除任务1中的数字打印和LED翻转,删除完如下所示

#include "freertos_demo.h"
#include "usart.h"
#include "led.h"
#include "lcd.h"
#include "key.h"
/*FreeRTOS*********************************************************************************************/
#include "FreeRTOS.h"
#include "task.h"

/******************************************************************************************************/
/*FreeRTOS配置*/

/* START_TASK 任务 配置
 * 包括: 任务句柄 任务优先级 堆栈大小 创建任务
 */
#define START_TASK_PRIO         1
#define START_TASK_STACK_SIZE   128
TaskHandle_t    start_task_handler;
void start_task( void * pvParameters );

/* TASK1 任务 配置
 * 包括: 任务句柄 任务优先级 堆栈大小 创建任务
 */
#define TASK1_PRIO         2
#define TASK1_STACK_SIZE   128
TaskHandle_t    task1_handler;
void task1( void * pvParameters );
/******************************************************************************************************/


/**
 * @brief       FreeRTOS例程入口函数
 * @param       无
 * @retval      无
 */
void freertos_demo(void)
{    
    xTaskCreate((TaskFunction_t         )   start_task,
                (char *                 )   "start_task",
                (configSTACK_DEPTH_TYPE )   START_TASK_STACK_SIZE,
                (void *                 )   NULL,
                (UBaseType_t            )   START_TASK_PRIO,
                (TaskHandle_t *         )   &start_task_handler );
    vTaskStartScheduler();
}


void start_task( void * pvParameters )
{
	taskENTER_CRITICAL();                              /*进入临界区*/
    xTaskCreate((TaskFunction_t         )   task1,
                (char *                 )   "task1",
                (configSTACK_DEPTH_TYPE )   TASK1_STACK_SIZE,
                (void *                 )   NULL,
                (UBaseType_t            )   TASK1_PRIO,
                (TaskHandle_t *         )   &task1_handler );
    vTaskDelete(NULL);
	taskEXIT_CRITICAL();                              /*退出临界区*/
}

/* 任务一,实现每5000ms关闭和开启中断 */
void task1( void * pvParameters )
{
	uint32_t task1_num=0;
    while(1)
    {
        vTaskDelay(500);
    }
}

4.2移除工程中exti.c文件

        移除以下文件,并且在main.c文件中删除相关调用程序。

#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "led.h"
#include "key.h"
#include "lcd.h"
#include "sdram.h"
#include "malloc.h"
#include "freertos_demo.h"
 
int main(void)
{
    
    HAL_Init();                     //初始化HAL库   
    Stm32_Clock_Init(360,25,2,8);   //设置时钟,180Mhz
    delay_init(180);                //初始化延时函数
    uart_init(115200);              //初始化USART
    LED_Init();
	KEY_Init();

	freertos_demo();
}

4.3实现定时器功能

timer.c原始程序如下所示:

#include "timer.h"
#include "led.h"


TIM_HandleTypeDef TIM3_Handler;      //定时器句柄 

//通用定时器3中断初始化
//arr:自动重装值。
//psc:时钟预分频数
//定时器溢出时间计算方法:Tout=((arr+1)*(psc+1))/Ft us.
//Ft=定时器工作频率,单位:Mhz
//这里使用的是定时器3!(定时器3挂在APB1上,时钟为HCLK/2)
void TIM3_Init(u16 arr,u16 psc)
{  
    TIM3_Handler.Instance=TIM3;                          //通用定时器3
    TIM3_Handler.Init.Prescaler=psc;                     //分频系数
    TIM3_Handler.Init.CounterMode=TIM_COUNTERMODE_UP;    //向上计数器
    TIM3_Handler.Init.Period=arr;                        //自动装载值
    TIM3_Handler.Init.ClockDivision=TIM_CLOCKDIVISION_DIV1;//时钟分频因子
    HAL_TIM_Base_Init(&TIM3_Handler);
    
    HAL_TIM_Base_Start_IT(&TIM3_Handler); //使能定时器3和定时器3更新中断:TIM_IT_UPDATE   
}


//定时器底册驱动,开启时钟,设置中断优先级
//此函数会被HAL_TIM_Base_Init()函数调用
void HAL_TIM_Base_MspInit(TIM_HandleTypeDef *htim)
{
    if(htim->Instance==TIM3)
	{
		__HAL_RCC_TIM3_CLK_ENABLE();            //使能TIM3时钟
		HAL_NVIC_SetPriority(TIM3_IRQn,1,3);    //设置中断优先级,抢占优先级1,子优先级3
		HAL_NVIC_EnableIRQ(TIM3_IRQn);          //开启ITM3中断   
	}
}


//定时器3中断服务函数
void TIM3_IRQHandler(void)
{
    HAL_TIM_IRQHandler(&TIM3_Handler);
}


//回调函数,定时器中断服务函数调用
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
    if(htim==(&TIM3_Handler))
    {
        LED1=!LED1;        //LED1反转
    }
}

由于timer.c中已经实现了定时器3的程序,定时器3为通用定时器,此处选用TIM3和TIM4都为通用定时器(2022正点原子FreeRTOS教程中选用的是TIM6和TIM7基本定时器,此处有所不同)。timer.c修改完如下所示( 在中断回调函数中不建议使用printf()函数进行打印,耗时较长,此处为了方便演示):

#include "timer.h"
#include "led.h"


TIM_HandleTypeDef TIM3_Handler;      //定时器3句柄 
TIM_HandleTypeDef TIM4_Handler;      //定时器4句柄 
//通用定时器3,4中断初始化
//arr:自动重装值。
//psc:时钟预分频数
//定时器溢出时间计算方法:Tout=((arr+1)*(psc+1))/Ft us.
//Ft=定时器工作频率,单位:Mhz
//这里使用的是定时器3!(定时器3挂在APB1上,时钟为HCLK/2)
void TIM3_Init(u16 arr,u16 psc)
{  
    TIM3_Handler.Instance=TIM3;                          //通用定时器3
    TIM3_Handler.Init.Prescaler=psc;                     //分频系数
    TIM3_Handler.Init.CounterMode=TIM_COUNTERMODE_UP;    //向上计数器
    TIM3_Handler.Init.Period=arr;                        //自动装载值
    TIM3_Handler.Init.ClockDivision=TIM_CLOCKDIVISION_DIV1;//时钟分频因子
    HAL_TIM_Base_Init(&TIM3_Handler);
    
    HAL_TIM_Base_Start_IT(&TIM3_Handler); //使能定时器3和定时器3更新中断:TIM_IT_UPDATE   
}
void TIM4_Init(u16 arr,u16 psc)
{  
    TIM4_Handler.Instance=TIM4;                          //通用定时器4
    TIM4_Handler.Init.Prescaler=psc;                     //分频系数
    TIM4_Handler.Init.CounterMode=TIM_COUNTERMODE_UP;    //向上计数器
    TIM4_Handler.Init.Period=arr;                        //自动装载值
    TIM4_Handler.Init.ClockDivision=TIM_CLOCKDIVISION_DIV1;//时钟分频因子
    HAL_TIM_Base_Init(&TIM4_Handler);
    
    HAL_TIM_Base_Start_IT(&TIM4_Handler); //使能定时器4和定时器4更新中断:TIM_IT_UPDATE   
}


//定时器底册驱动,开启时钟,设置中断优先级
//此函数会被HAL_TIM_Base_Init()函数调用
void HAL_TIM_Base_MspInit(TIM_HandleTypeDef *htim)
{
    if(htim->Instance==TIM3)
	{
		__HAL_RCC_TIM3_CLK_ENABLE();            //使能TIM3时钟
		HAL_NVIC_SetPriority(TIM3_IRQn,6,0);    //设置中断优先级,抢占优先级6,子优先级0
		HAL_NVIC_EnableIRQ(TIM3_IRQn);          //开启ITM3中断   
	}
	if (htim->Instance==TIM4)
	{
		__HAL_RCC_TIM4_CLK_ENABLE();            //使能TIM4时钟
		HAL_NVIC_SetPriority(TIM4_IRQn,4,0);    //设置中断优先级,抢占优先级4,子优先级0
		HAL_NVIC_EnableIRQ(TIM4_IRQn);          //开启ITM4中断   
	}
}


//定时器3中断服务函数
void TIM3_IRQHandler(void)
{
    HAL_TIM_IRQHandler(&TIM3_Handler);
}
//定时器4中断服务函数
void TIM4_IRQHandler(void)
{
    HAL_TIM_IRQHandler(&TIM4_Handler);
}

//回调函数,定时器中断服务函数调用
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
    if(htim==(&TIM3_Handler))
    {
		printf("TIM3优先级为6正在运行!\r\n");
    }
	else if (htim==(&TIM4_Handler))
	{
		printf("TIM4优先级为4正在运行!!!\r\n");
	}
}

在timer.h中声明timer4的初始化函数,修改完如下所示:

#ifndef _TIMER_H
#define _TIMER_H
#include "sys.h"
	
extern TIM_HandleTypeDef TIM3_Handler;      //定时器句柄 

void TIM3_Init(u16 arr,u16 psc);
void TIM4_Init(u16 arr,u16 psc);
#endif

在main.c中调用TIM3和TIM4的初始化函数,并添加头文件,修改完如下所示:

#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "led.h"
#include "key.h"
#include "lcd.h"
#include "sdram.h"
#include "malloc.h"
#include "freertos_demo.h"

#include "timer.h"

int main(void)
{
    
    HAL_Init();                     //初始化HAL库   
    Stm32_Clock_Init(360,25,2,8);   //设置时钟,180Mhz
    delay_init(180);                //初始化延时函数
    uart_init(115200);              //初始化USART
    LED_Init();
	KEY_Init();
	TIM3_Init(10000-1,9000-1);      //定时器1s中断一次
	TIM4_Init(10000-1,9000-1);
	freertos_demo();
}

现象:

以上程序可以实现每隔1s,进入TIM3和TIM4,并打印。 

 4.4实现关闭和开启中断功能

在task1中关闭中断后延时5s使用的是死延时delay_ms(),并不使用vTaskDelay()函数,因为vTaskDelay()函数退出临界区时调用了开启中断函数portENABLE_INTERRUPTS(),因为刚刚关闭了中断,并不能调用开启中断函数。

freertos_demo.c部分程序修改如下(需要在一开始引用delay.h头文件):

#include "delay.h"
/* 任务一,实现每5000ms关闭和开启中断 */
void task1( void * pvParameters )
{
	uint32_t task1_num=0;
    while(1)
    {
		
		if(++task1_num==5)
		{
			task1_num=0;
			printf("关中断!!\r\n");
			portDISABLE_INTERRUPTS();
			delay_ms(5000);
			printf("开中断!!!\r\n");
			portENABLE_INTERRUPTS();
		}
        vTaskDelay(1000);
    }
}

现象:

在串口中每隔一秒进入TIM3和TIM4中断,进入5次,关闭中断;在串口中每隔1s进入TIM4中断, 开启中断;重复以上两步骤。

5.总结

 

 

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

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

相关文章

2023.1.30作业-【尝试移植TF-A】

1、解压源码&#xff0c;进入目录如图一 2、解压源码包 3、进入解压后的目录&#xff0c;打入官方补丁 4、查看SD卡的分区&#xff0c;发现正常无需重新分区 5、导入编译工具查看是否正常导入 6、添加设备树等相关文件 7、修改上层目录下的 Makefile.sdk中添加 stm32mp157a-fsm…

chatGPT模型简介

ChatGPT的工作原理 chatGPT 是一款由 OpenAI 开发的聊天机器人模型&#xff0c;它能够模拟人类的语言行为&#xff0c;与用户进行自然的交互。它的名称来源于它所使用的技术—— GPT-3架构&#xff0c;即生成式语言模型的第3代。 chatGPT的核心技术是 GPT-3 架构。它通过使用大…

vue 自动生成swagger接口请求文件

前端: vue-element-admin 后端: .net core (6.0) 找了很多自动生成的代码的&#xff0c;感觉不太行&#xff0c;可能是我不太懂。所以自己根据swagger.json去生成了js请求文件。 后端很简单&#xff0c;就不说了&#xff0c;只要能访问到swagger的地址就可以&#xff0c;主要…

【My Electronic Notes系列——低频功率放大器】

目录 序言&#xff1a; &#x1f3c6;&#x1f3c6;人生在世&#xff0c;成功并非易事&#xff0c;他需要破茧而出的决心&#xff0c;他需要永不放弃的信念&#xff0c;他需要水滴石穿的坚持&#xff0c;他需要自强不息的勇气&#xff0c;他需要无畏无惧的凛然。要想成功&…

【自学Docker】Docker rename命令

Docker rename命令 大纲 docker rename命令教程 docker rename 命令可以用于重命名一个 Docker容器。docker rename命令后面的 CONTAINER 可以是容器Id&#xff0c;或者是容器名。 docker rename语法 haicoder(www.haicoder.net)# docker rename CONTAINER NEW_NAME案例 重…

【Kubernetes 企业项目实战】05、基于云原生分布式存储 Ceph 实现 K8s 数据持久化(下)

目录 一、K8s 对接 ceph rbd 实现数据持久化 1.1 k8s 安装 ceph 1.2 创建 pod 挂载 ceph rbd 二、基于 ceph rbd 生成 pv 2.1 创建 ceph-secret 2.2 创建 ceph 的 secret 2.3 创建 pool 池 2.4 创建 pv 2.5 创建 pvc 2.6 测试 pod 挂载 pvc 2.7 注意事项 1&#xf…

软考高项—第一章信息系统项目管理基础

项目特点 1、临时性&#xff1a;有明确的开始时间和结束时间 2、独特的产品、可交付成果 3、逐步完善&#xff1a;项目团队从开始的粗略计划到详细计划&#xff0c;在到完成项目 4、资源约束&#xff1a;每个项目都需要各种资源保证&#xff0c;资源是有限的 5、目的性&#x…

C语言重点复习大纲

目录数据存储(3星)判断大小端写一个函数判断大小端截断与整形提升数组和指针(5星)几个特殊的指针数组传参字符串数组库函数的实现(4星)atoi与itoamemcpy与memmove内存重叠自定义类型(4星)内存对齐结构体&#xff0c;联合体&#xff0c;枚举位段编译链接(3星)编译和链接的过程条…

循环队列实现---kfifo

循环队列 概述 在优化系统性能时&#xff0c;我们通常需要分析一个单线程程序各模块的功能和性能&#xff0c;然后将这些模块拆分到多个线程中并行执行。而多个线程之间需要加入缓存以实现线程间的通信。如图1所示&#xff1a; 图1&#xff1a;多线程缓存为方便进程间通信&am…

Python【xpath】实战下

项目要求&#xff1a;获取某二手租房平台关于房源信息的简介和价格代码&#xff1a;python编写&#xff0c;实现需要准备的第三方库&#xff1a;requests &#xff0c;lxml&#xff0c; time代码分析&#xff1a;导入需要使用的第三方库&#xff1a;import requests import tim…

java ssm校园快递代领系统的设计与实现idea maven

近几年随着国民经济的不断发展&#xff0c;电子商务行业的不断创新。作为物流业一个重要分支的校园快递代领逐渐兴起&#xff0c;各种快递公司层出不穷。校园快递代领在不断向前发展的同时也存在一些无法避免的小问题&#xff0c;例如许多小型的快递公司在信息处理和管理上存在…

基于微信小程序的民宿短租系统小程序

文末联系获取源码 开发语言&#xff1a;Java 框架&#xff1a;ssm JDK版本&#xff1a;JDK1.8 服务器&#xff1a;tomcat7 数据库&#xff1a;mysql 5.7/8.0 数据库工具&#xff1a;Navicat11 开发软件&#xff1a;eclipse/myeclipse/idea Maven包&#xff1a;Maven3.3.9 浏览器…

Spring Boot Actuator详解

Actuator简介 什么是Spring Boot Actuator&#xff1f; Spring Boot Actuator 模块提供了生产级别的功能&#xff0c;比如健康检查&#xff0c;审计&#xff0c;指标收集&#xff0c;HTTP跟踪等&#xff0c;帮助我们监控和管理Spring Boot应用。这个模块是一个采集应用内部信…

react知识点整理

1、react hooks是用来做什么的? 加入hooks,让react函数组件更加的灵活 hooks之前,React存在很多问题: 1、组件间服用状态逻辑难2、复杂组件变的难以理解,高阶组件和函数组件的嵌套过深3、class组件的this问题4、难以记忆的生命周期hooks有: useState()useEffects()useR…

从头开始创建一个OData SAP Gateway Service

可能用到的事务代码&#xff1a;/IWFND/IWF_ACTIVATE – Activate / Deactivate SAP GatewaySEGW – SAP Gateway Service Builder/IWFND/MAINT_SERVICE – Activate and Maintain Services/IWFND/EXPLORER – Service Explorer/IWFND/GW_CLIENT – SAP Gateway Client/IWFND/S…

Android | 输入系统(IMS)

前言 一般情况下很多同学对于点击事件的认识都只存在于从 Activity 开始的&#xff0c;然后从 Window 中进行分发&#xff0c;甚至有些人可能也只知道 onTouchEvent 和 dispatchTouchEvetn 这几个方法&#xff0c;对于 View 层的了解都不属性。 自从对于应用层面的分发过程了…

logging日志模块详解

说到日志&#xff0c;无论是写框架代码还是业务代码都离不开日志的记录&#xff0c;其能给我们定位问题带来极大的帮助。 记录日志最简单的方式是在你想要记录的地方加上一句print。我相信无论是新手还是老鸟都经常这么干&#xff0c;在简单的代码或者小型项目中这么干一点问题…

这样吃才能有效补脑

核桃长得像大脑&#xff0c;还含有Ω-3&#xff0c;一直被认为补脑效果很好。但是现代科学研究发现&#xff0c;Ω-3并不是核桃专有的&#xff0c;很多坚果都有&#xff0c;所以核桃在补脑这方面并没有什么特殊功效。补脑其实就是维持大脑的正常工作&#xff0c;还要延缓大脑认…

SAP ADM100-Unit4 数据库工作原理:监控数据库

概览 除了执行数据备份之外,还需要对数据库进行大量的周期性检查。 课程目标 对数据库计划额外的周期性检查。 1、数据库定期监控 除了日常监控数据库备份外,还有大量的其他检查不得不定期执行。有的检查可以通过DBA Cockpit Planning Calendar来计划。 例如: 当存取数…

Mac电脑使用:查看本机已连接Wi-Fi密码的方法

前言 在使用Mac电脑的时候&#xff0c;电脑自身所连接成功的Wi-Fi一般都不显示密码&#xff0c;这是苹果出于安全考量的保护措施&#xff0c;但是有时候遇到新的设备想要连接已经连过的Wi-Fi&#xff0c;由于时间太久忘记Wi-Fi密码&#xff0c;这就需要查看一下电脑连接的Wi-Fi…