嵌入式学习(3)-FreeRTOS的创建任务过程

2023-05-16

创建任务过程理解

  • xTaskCreate()分析
  • prvInitialiseNewTask()函数分析
  • vListInitialiseItem()函数分析
  • prvAddNewTaskToReadyList()函数分析
  • prvAddTaskToReadyList()函数分析
  • pxPortInitialiseStack()函数分析

xTaskCreate()分析

BaseType_t xTaskCreate(	TaskFunction_t pxTaskCode,
							const char * const pcName,
							const uint16_t usStackDepth,
							void * const pvParameters,
							UBaseType_t uxPriority,
							TaskHandle_t * const pxCreatedTask ) 
	{
	TCB_t *pxNewTCB;
	BaseType_t xReturn;
		#if( portSTACK_GROWTH > 0 )
		{
			pxNewTCB = ( TCB_t * ) pvPortMalloc( sizeof( TCB_t ) );
			if( pxNewTCB != NULL )
			{
				pxNewTCB->pxStack = ( StackType_t * ) pvPortMalloc( ( ( ( size_t ) usStackDepth ) * sizeof( StackType_t ) ) );
				if( pxNewTCB->pxStack == NULL )
				{
					vPortFree( pxNewTCB );
					pxNewTCB = NULL;
				}
			}
		}
		#else 
		{
		StackType_t *pxStack;
			pxStack = ( StackType_t * ) pvPortMalloc( ( ( ( size_t ) usStackDepth ) * sizeof( StackType_t ) ) ); 
			if( pxStack != NULL )
			{
				/* Allocate space for the TCB. */
				pxNewTCB = ( TCB_t * ) pvPortMalloc( sizeof( TCB_t ) ); /*lint !e961 MISRA exception as the casts are only redundant for some paths. */

				if( pxNewTCB != NULL )
				{
					/* Store the stack location in the TCB. */
					pxNewTCB->pxStack = pxStack;
				}
				else
				{
					/* The stack cannot be used as the TCB was not created.  Free
					it again. */
					vPortFree( pxStack );
				}
			}
			else
			{
				pxNewTCB = NULL;
			}
		}
		#endif /* portSTACK_GROWTH */

		if( pxNewTCB != NULL )
		{
			#if( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 )
			{
				/* Tasks can be created statically or dynamically, so note this
				task was created dynamically in case it is later deleted. */
				pxNewTCB->ucStaticallyAllocated = tskDYNAMICALLY_ALLOCATED_STACK_AND_TCB;
			}
			#endif /* configSUPPORT_STATIC_ALLOCATION */

			prvInitialiseNewTask( pxTaskCode, pcName, ( uint32_t ) usStackDepth, pvParameters, uxPriority, pxCreatedTask, pxNewTCB, NULL );
			prvAddNewTaskToReadyList( pxNewTCB );
			xReturn = pdPASS;
		}
		else
		{
			xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY;
		}

		return xReturn;
	}

首先判断堆栈增长方向,通过堆栈增长方向来设置堆栈。
然后给任务快申请内存,申请成功就初始化堆栈字段pxStack 。
再标记一下这是使用动态创建任务函数。
然后初始化任务。
将新创建的任务加入到就绪列表中。

prvInitialiseNewTask()函数分析

static void prvInitialiseNewTask( 	TaskFunction_t pxTaskCode,
									const char * const pcName,
									const uint32_t ulStackDepth,
									void * const pvParameters,
									UBaseType_t uxPriority,
									TaskHandle_t * const pxCreatedTask,
									TCB_t *pxNewTCB,
									const MemoryRegion_t * const xRegions ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
{
StackType_t *pxTopOfStack;
UBaseType_t x;

	#if( portUSING_MPU_WRAPPERS == 1 )
		/* Should the task be created in privileged mode? */
		BaseType_t xRunPrivileged;
		if( ( uxPriority & portPRIVILEGE_BIT ) != 0U )
		{
			xRunPrivileged = pdTRUE;
		}
		else
		{
			xRunPrivileged = pdFALSE;
		}
		uxPriority &= ~portPRIVILEGE_BIT;
	#endif /* portUSING_MPU_WRAPPERS == 1 */

	/* Avoid dependency on memset() if it is not required. */
	#if( ( configCHECK_FOR_STACK_OVERFLOW > 1 ) || ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) )
	{
		/* Fill the stack with a known value to assist debugging. */
		( void ) memset( pxNewTCB->pxStack, ( int ) tskSTACK_FILL_BYTE, ( size_t ) ulStackDepth * sizeof( StackType_t ) );
	}
	#endif /* ( ( configCHECK_FOR_STACK_OVERFLOW > 1 ) || ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) ) ) */

	/* Calculate the top of stack address.  This depends on whether the stack
	grows from high memory to low (as per the 80x86) or vice versa.
	portSTACK_GROWTH is used to make the result positive or negative as required
	by the port. */
	#if( portSTACK_GROWTH < 0 )
	{
		pxTopOfStack = pxNewTCB->pxStack + ( ulStackDepth - ( uint32_t ) 1 );
		pxTopOfStack = ( StackType_t * ) ( ( ( portPOINTER_SIZE_TYPE ) pxTopOfStack ) & ( ~( ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) ) ); /*lint !e923 MISRA exception.  Avoiding casts between pointers and integers is not practical.  Size differences accounted for using portPOINTER_SIZE_TYPE type. */

		/* Check the alignment of the calculated top of stack is correct. */
		configASSERT( ( ( ( portPOINTER_SIZE_TYPE ) pxTopOfStack & ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) == 0UL ) );
	}
	#else /* portSTACK_GROWTH */
	{
		pxTopOfStack = pxNewTCB->pxStack;

		/* Check the alignment of the stack buffer is correct. */
		configASSERT( ( ( ( portPOINTER_SIZE_TYPE ) pxNewTCB->pxStack & ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) == 0UL ) );

		/* The other extreme of the stack space is required if stack checking is
		performed. */
		pxNewTCB->pxEndOfStack = pxNewTCB->pxStack + ( ulStackDepth - ( uint32_t ) 1 );
	}
	#endif /* portSTACK_GROWTH */

	/* Store the task name in the TCB. */
	for( x = ( UBaseType_t ) 0; x < ( UBaseType_t ) configMAX_TASK_NAME_LEN; x++ )
	{
		pxNewTCB->pcTaskName[ x ] = pcName[ x ];

		/* Don't copy all configMAX_TASK_NAME_LEN if the string is shorter than
		configMAX_TASK_NAME_LEN characters just in case the memory after the
		string is not accessible (extremely unlikely). */
		if( pcName[ x ] == 0x00 )
		{
			break;
		}
		else
		{
			mtCOVERAGE_TEST_MARKER();
		}
	}

	/* Ensure the name string is terminated in the case that the string length
	was greater or equal to configMAX_TASK_NAME_LEN. */
	pxNewTCB->pcTaskName[ configMAX_TASK_NAME_LEN - 1 ] = '\0';

	/* This is used as an array index so must ensure it's not too large.  First
	remove the privilege bit if one is present. */
	if( uxPriority >= ( UBaseType_t ) configMAX_PRIORITIES )
	{
		uxPriority = ( UBaseType_t ) configMAX_PRIORITIES - ( UBaseType_t ) 1U;
	}
	else
	{
		mtCOVERAGE_TEST_MARKER();
	}

	pxNewTCB->uxPriority = uxPriority;
	#if ( configUSE_MUTEXES == 1 )
	{
		pxNewTCB->uxBasePriority = uxPriority;
		pxNewTCB->uxMutexesHeld = 0;
	}
	#endif /* configUSE_MUTEXES */

	vListInitialiseItem( &( pxNewTCB->xStateListItem ) );
	vListInitialiseItem( &( pxNewTCB->xEventListItem ) );

	/* Set the pxNewTCB as a link back from the ListItem_t.  This is so we can get
	back to	the containing TCB from a generic item in a list. */
	listSET_LIST_ITEM_OWNER( &( pxNewTCB->xStateListItem ), pxNewTCB );

	/* Event lists are always in priority order. */
	listSET_LIST_ITEM_VALUE( &( pxNewTCB->xEventListItem ), ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) uxPriority ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
	listSET_LIST_ITEM_OWNER( &( pxNewTCB->xEventListItem ), pxNewTCB );

	#if ( portCRITICAL_NESTING_IN_TCB == 1 )
	{
		pxNewTCB->uxCriticalNesting = ( UBaseType_t ) 0U;
	}
	#endif /* portCRITICAL_NESTING_IN_TCB */

	#if ( configUSE_APPLICATION_TASK_TAG == 1 )
	{
		pxNewTCB->pxTaskTag = NULL;
	}
	#endif /* configUSE_APPLICATION_TASK_TAG */

	#if ( configGENERATE_RUN_TIME_STATS == 1 )
	{
		pxNewTCB->ulRunTimeCounter = 0UL;
	}
	#endif /* configGENERATE_RUN_TIME_STATS */

	#if ( portUSING_MPU_WRAPPERS == 1 )
	{
		vPortStoreTaskMPUSettings( &( pxNewTCB->xMPUSettings ), xRegions, pxNewTCB->pxStack, ulStackDepth );
	}
	#else
	{
		/* Avoid compiler warning about unreferenced parameter. */
		( void ) xRegions;
	}
	#endif

	#if( configNUM_THREAD_LOCAL_STORAGE_POINTERS != 0 )
	{
		for( x = 0; x < ( UBaseType_t ) configNUM_THREAD_LOCAL_STORAGE_POINTERS; x++ )
		{
			pxNewTCB->pvThreadLocalStoragePointers[ x ] = NULL;
		}
	}
	#endif

	#if ( configUSE_TASK_NOTIFICATIONS == 1 )
	{
		pxNewTCB->ulNotifiedValue = 0;
		pxNewTCB->ucNotifyState = taskNOT_WAITING_NOTIFICATION;
	}
	#endif

	#if ( configUSE_NEWLIB_REENTRANT == 1 )
	{
		/* Initialise this task's Newlib reent structure. */
		_REENT_INIT_PTR( ( &( pxNewTCB->xNewLib_reent ) ) );
	}
	#endif

	#if( INCLUDE_xTaskAbortDelay == 1 )
	{
		pxNewTCB->ucDelayAborted = pdFALSE;
	}
	#endif

	/* Initialize the TCB stack to look as if the task was already running,
	but had been interrupted by the scheduler.  The return address is set
	to the start of the task function. Once the stack has been initialised
	the	top of stack variable is updated. */
	#if( portUSING_MPU_WRAPPERS == 1 )
	{
		pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxTaskCode, pvParameters, xRunPrivileged );
	}
	#else /* portUSING_MPU_WRAPPERS */
	{
		pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxTaskCode, pvParameters );
	}
	#endif /* portUSING_MPU_WRAPPERS */

	if( ( void * ) pxCreatedTask != NULL )
	{
		/* Pass the handle out in an anonymous way.  The handle can be used to
		change the created task's priority, delete the created task, etc.*/
		*pxCreatedTask = ( TaskHandle_t ) pxNewTCB;
	}
	else
	{
		mtCOVERAGE_TEST_MARKER();
	}
}

这段代码比较长,一点一点分析,首先

#if( ( configCHECK_FOR_STACK_OVERFLOW > 1 ) || ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) )
	{
		/* Fill the stack with a known value to assist debugging. */
		( void ) memset( pxNewTCB->pxStack, ( int ) tskSTACK_FILL_BYTE, ( size_t ) ulStackDepth * sizeof( StackType_t ) );
	}

这里是判断是否使能了堆栈溢出检测功能和追踪功能,如果使能了,就用0XA5U来填充堆栈。tskSTACK_FILL_BYTE的值为0xA5U.
然后根据堆栈增长方向,计算栈顶的地址。
然后将任务的名字的字符串保存起来,添加结束符’\0’。
判断当前任务的优先级是否超过了FreeRTOS系统的最大优先级。超过了就将优先级设置为最大优先级减一。
初始化任务控制块的优先级字段uxPriority。
如果使能了互斥信号量,就初始化相应的字段。
使用vListInitialiseItem()函数初始化列表项。
设置状态列表项和事件列表项为当前任务的控制块。
后面有一些条件编译,根据自己使用情况来开启,这里是在开启后进行了一些初始化字段。
后面初始化了任务堆栈,使用pxPortInitialiseStack()。
最后生成任务句柄,可以看出,任务句柄就是任务控制块。

vListInitialiseItem()函数分析

void vListInitialiseItem( ListItem_t * const pxItem )
{
	/* Make sure the list item is not recorded as being on a list. */
	pxItem->pvContainer = NULL;

	/* Write known values into the list item if
	configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */
	listSET_FIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem );
	listSET_SECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem );
}

这里的函数都没有实现,说明这里只是将列表进行了初始化,对pvContainer 给了0。

prvAddNewTaskToReadyList()函数分析

static void prvAddNewTaskToReadyList( TCB_t *pxNewTCB )
{
	/* Ensure interrupts don't access the task lists while the lists are being
	updated. */
	taskENTER_CRITICAL();
	{
		uxCurrentNumberOfTasks++;
		if( pxCurrentTCB == NULL )
		{
			/* There are no other tasks, or all the other tasks are in
			the suspended state - make this the current task. */
			pxCurrentTCB = pxNewTCB;

			if( uxCurrentNumberOfTasks == ( UBaseType_t ) 1 )
			{
				/* This is the first task to be created so do the preliminary
				initialisation required.  We will not recover if this call
				fails, but we will report the failure. */
				prvInitialiseTaskLists();
			}
			else
			{
				mtCOVERAGE_TEST_MARKER();
			}
		}
		else
		{
			/* If the scheduler is not already running, make this task the
			current task if it is the highest priority task to be created
			so far. */
			if( xSchedulerRunning == pdFALSE )
			{
				if( pxCurrentTCB->uxPriority <= pxNewTCB->uxPriority )
				{
					pxCurrentTCB = pxNewTCB;
				}
				else
				{
					mtCOVERAGE_TEST_MARKER();
				}
			}
			else
			{
				mtCOVERAGE_TEST_MARKER();
			}
		}

		uxTaskNumber++;

		#if ( configUSE_TRACE_FACILITY == 1 )
		{
			/* Add a counter into the TCB for tracing only. */
			pxNewTCB->uxTCBNumber = uxTaskNumber;
		}
		#endif /* configUSE_TRACE_FACILITY */
		traceTASK_CREATE( pxNewTCB );

		prvAddTaskToReadyList( pxNewTCB );

		portSETUP_TCB( pxNewTCB );
	}
	taskEXIT_CRITICAL();

	if( xSchedulerRunning != pdFALSE )
	{
		/* If the created task is of a higher priority than the current task
		then it should run now. */
		if( pxCurrentTCB->uxPriority < pxNewTCB->uxPriority )
		{
			taskYIELD_IF_USING_PREEMPTION();
		}
		else
		{
			mtCOVERAGE_TEST_MARKER();
		}
	}
	else
	{
		mtCOVERAGE_TEST_MARKER();
	}
}

先进入临界区。uxCurrentNumberOfTasks()函数用来记录任务数量。
如果任务控制块为空,说明当前没有任务,或者其他任务都处于挂起态,那就将此做为当前任务。初始化任务列表。
如果当前有任务,那就判断当前是否开启任务调度。如果当前调度任务还未运行,那就判断优先级,将pxCurrentTCB设置为高优先级任务的任务控制块。
任务数量加一。
traceTASK_CREATE( pxNewTCB );函数未实现
添加任务到就绪列表中,
退出临界区。
如果当前任务调度器已经开启。而且新任务的优先级最高,那就进行一次任务切换。

prvAddTaskToReadyList()函数分析

#define prvAddTaskToReadyList( pxTCB )																\
	traceMOVED_TASK_TO_READY_STATE( pxTCB );														\
	taskRECORD_READY_PRIORITY( ( pxTCB )->uxPriority );												\
	vListInsertEnd( &( pxReadyTasksLists[ ( pxTCB )->uxPriority ] ), &( ( pxTCB )->xStateListItem ) ); \
	tracePOST_MOVED_TASK_TO_READY_STATE( pxTCB )

添加任务到就绪列表函数是一个宏,其中traceMOVED_TASK_TO_READY_STATE( pxTCB ); 未实现
taskRECORD_READY_PRIORITY函数用于硬件设置优先级。
在就将任务添加到就绪列表结尾。

pxPortInitialiseStack()函数分析

StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )
{
	/* Simulate the stack frame as it would be created by a context switch
	interrupt. */
	pxTopOfStack--; /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */
	*pxTopOfStack = portINITIAL_XPSR;	/* xPSR */
	pxTopOfStack--;
	*pxTopOfStack = ( ( StackType_t ) pxCode ) & portSTART_ADDRESS_MASK;	/* PC */
	pxTopOfStack--;
	*pxTopOfStack = ( StackType_t ) prvTaskExitError;	/* LR */

	pxTopOfStack -= 5;	/* R12, R3, R2 and R1. */
	*pxTopOfStack = ( StackType_t ) pvParameters;	/* R0 */
	pxTopOfStack -= 8;	/* R11, R10, R9, R8, R7, R6, R5 and R4. */

	return pxTopOfStack;
}

在任务初始化函数里会对任务的堆栈初始化,首先将寄存器xPSRd的值设置为portINITIAL_XPSR,然后将PC的值设置为pxCode ,然后将LR的值设置为prvTaskExitError。跳过R12,R3,R2,R1.将R0设置为pvParameters。跳过八个寄存器。这里的寄存器顺序是芯片内设置好的。最后的堆栈如图所示。
在这里插入图片描述

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

嵌入式学习(3)-FreeRTOS的创建任务过程 的相关文章

  • composer.lock是干什么的?底层原理是什么?

    composer lock文件是Composer工具在安装依赖包时生成的一个锁文件 它记录了当前应用程序所依赖的所有PHP库及其版本号 xff0c 以及所有依赖库所依赖的其他库及其版本号等信息 在运行composer install命令时
  • PHP的Zend引擎是干什么的?底层原理是什么?

    PHP的Zend引擎是PHP解释器的核心组件 xff0c 负责将PHP代码转换为可执行的指令集 xff0c 并执行这些指令 Zend引擎是PHP的默认执行引擎 xff0c 被广泛使用 Zend引擎的底层原理可以分为以下几个关键步骤 xff1
  • PHP解释器是干什么的?底层原理是什么?

    PHP解释器是用于解释执行PHP代码的软件程序 它负责将编写的PHP代码转换为可执行的机器指令 xff0c 并执行这些指令以实现代码的功能 PHP解释器的底层原理可以分为以下几个步骤 xff1a 词法分析 xff08 Lexical Ana
  • PHP代码的底层是什么?底层原理是什么?

    PHP代码的底层是由计算机可执行的机器码 xff08 二进制指令 xff09 组成 底层原理是将PHP代码经过编译和解释执行的过程转化为机器码 底层原理可以分为以下几个步骤 xff1a 词法分析 xff08 Lexical Analysis
  • Jetson Xavier NX 的SD卡系统镜像制作

    Jetson Xavier NX 的SD卡系统镜像制作 一 SD卡系统查看二 系统镜像制作三 系统镜像烧录 一 SD卡系统查看 现有的SD卡的内存为128G xff0c 其中64G内存并未分配 span class token commen
  • 嵌入式Linux下使用crond服务

    参考 xff1a https www linuxidc com Linux 2014 02 97369 htm http www linuxidc com Linux 2014 02 97360 htm https blog csdn ne
  • 关于Flexsns Sky 卡80%,以及乱码的解决问题

    一直被 flexsns sky 这个应用折磨好久了 xff0c 刚开始的时候安装成功 但是打开界面一直卡在80 那里 xff0c ucenter 里面的设置也是对的 官网也是挂的 xff01 于是百思不得解 接下来 我来说说我的解决办法把
  • Ubuntu18.04运行ORB-SLAM3(Demo+本地Realsense D415运行)

    ORB SLAM3论文地址 xff1a https arxiv org abs 2007 11898 代码地址 xff1a https github com UZ SLAMLab ORB SLAM3 一 安装库 根据ORB SLAM3源代码
  • ROS中的坐标与坐标系转换

    ROS中的TF 官网建议新工作直接使用tf2 xff0c 因为它有一个更清洁的界面 xff0c 和更好的使用体验 xff08 自ROS Hydro以来 xff0c tf第一代已被 弃用 xff0c 转而支持tf2 xff09 TF介绍 TF
  • 激光雷达与相机融合(二)-----基于openCV的YOLO目标检测

    代码解析 1 加载模型 span class token comment load image from file span cv span class token operator span Mat img span class toke
  • 线程优先权Thread Priority概念总结

    全文参考 WIN32多线程设计 一书 为什么会有线程优先权 xff1a 为什么CPU处理线程时会按优先级执行 xff1f 想象在忙碌的一天中 xff0c 有很多事情待做但时间又不够 xff0c 其中有很多紧急的事情 比如当晚的英语在线测试
  • 将ros cv_bridge关联到自己安装的Opencv版本

    有时候需要同时使用较高版本的openCV 但一般默认安装的ros系统的cv bridge包关联的Opencv版本都较低 xff0c 这时候就需要将cv bridge关联到自己安装的高版本OpenCV 成功方法为第三条 xff0c 前两条为遇
  • chmod +x 与chmod 777的区别

    chmod 43 x 是将文件状态改为可执行 xff0c 而chmod 777 是改变文件读写权限 在linux中使用man命令查看chmod的大纲我们可以得出以下有用的信息 xff1a chmod OPTION MODE MODE FIL
  • WIndowsServer2012 DHCP服务器配置

    DHCP服务器配置 WIndowsServer2012 DHCP服务器配置服务器配置保留IP设置作用域选项 客户机设置 WIndowsServer2012 DHCP服务器配置 服务器配置 1 首先打开服务器管理器 xff0c 点击工具 xf
  • JavaScript设计模式:四、发布订阅模式

    JavaScript设计模式 xff1a 四 发布订阅模式 文章目录 JavaScript设计模式 xff1a 四 发布订阅模式一 概述1 观察者模式2 发布订阅模式3 观察者模式是不是发布订阅模式 一 概述 观察者模式 xff1a 观察者
  • FreeRTOS教程——二值信号量(四)

    二值信号量 信号量简介 目的 xff1a 共享资源访问 与任务同步 信号量类型 xff1a 二值信号量 计数型信号量 互斥信号量 递归互斥信号量 本质上是一种只包含一个项数的队列 二值信号量 0 和 1 xff0c 一种内核机制 内核同步
  • Bug:Warning: [antd: ***] overlay is deprecated. Please use menu instead.以及解决方案

    Ant Design Pro umi4Bug记录 xff1a Bug xff1a Warning antd overlay is deprecated Please use menu instead 解决方案 xff1a yarn add
  • 前端初学者的Ant Design Pro V6总结(上)

    前端初学者的Ant Design Pro V6总结 xff08 上 xff09 一 UI组件开发流程 61 gt 通用 xff08 异步 xff09 函数useEmotionCss 定义CSSuseModel获取全局状态useCallbac
  • 关于C语言在VS2017上开头格式

    span class token macro property span class token directive keyword include span span class token string lt stdio h gt sp
  • Java中Long和long的区别

    Java中Long和long的区别 Java的数据类型分为两种 xff1a 1 基本类型 xff1a byte 8 short 16 int 32 long 64 float 32 double 64 char 16 boolean 1 2

随机推荐

  • Windows 10 下如何彻底关闭 Hyper-V 服务

    CMD运行bcdedit set hypervisorlaunchtype off 恢复使用 xff1a bcdedit set hypervisorlaunchtype auto
  • 从百度运维实践谈“基于机器学习的智能运维”

    清华大学计算机系副教授裴丹于运维自动化专场发表了题为 基于机器学习的智能运维 的演讲 xff0c 上篇参看 科研角度谈 如何实现基于机器学习的智能运维 文章 xff0c 此为下篇 从百度运维实践谈基于机器学习的智能运维 以下为演讲实录 xf
  • python通过udp传输图片

    首先要了解UDP的工作模式 对于服务器 xff0c 首先绑定IP和端口 xff0c 本机测试的时候可以使用127 0 0 1是本机的专有IP xff0c 端口号 大于1024的是自定义的 xff0c 所以用大于1024的端口号 xff0c
  • D435i跑通ORB-SLAM2

    这篇文章主要记录我的实现过程 根据官方安装文档 xff0c 并参考以下两篇博客 xff0c 可以比较顺利的实现 xff1a Realsense D435i 在ubuntu上安装SDK与ROS Wrapper 运行ORB SLAM2 RTAB
  • 通俗理解滑模变结构控制(1)

    这里写自定义目录标题 1 什么是滑模变结构控制2 滑模变结构的一些基本知识3 滑模控制器设计4 滑模控制器例子 1 什么是滑模变结构控制 在开始介绍滑模变结构控制之前 xff0c 最好先学习一些线性控制的基础 xff0c 知道什么是李亚普诺
  • 终端滑模(Terminal滑模)理解

    一 什么是终端滑模 在前面所介绍的滑模控制中 xff0c 我们是选取了一个线性的滑模面s xff0c 使系统达到滑模面后 xff0c 误差逐渐收敛到0 xff0c 收敛的速度可以通过调节滑模面的参数来实现 后来人们为了使滑模控制有更好的性能
  • PX4环境git submodule update --init --recursive失败的解决办法

    最近开始搭建PX4环境 xff0c 搭建是需要从github下载工程 xff0c 然后使用语句git submodule update init recursive更新工程子模块 xff0c 但往往由于网络原因这一步需要很久 xff0c 甚
  • 变结构滑模控制抖振处理(1)------动态滑模法

    1 什么是动态滑模 从前面一些关于滑模的介绍 xff0c 我们知道 xff0c 在设计滑模控制器时 xff0c 避不开的问题就是抖振 至于抖振的产生 xff0c 很大程度上是由于一般滑模控制器的控制律u是一个不连续的函数 xff0c u中往
  • 四旋翼双环PID控制

    在我上篇博客 四旋翼无人机Matlab建模 中 xff0c 我建立了四旋翼的模型 xff0c 并在simulink中搭建了仿真 xff0c 但并没有设计控制器 本章便针对四旋翼设计最常见的串级PID控制器 xff0c 本篇文章主要从两个部分
  • PX4代码解析(1)

    前言 做pixhawk飞控有一段时间了 xff0c 但在学习过程中遇到许多困难 xff0c 目前网上找不到比较完整的PX4学习笔记 xff0c 我打算结合自己理解 xff0c 写写自己对PX4源码的理解 xff0c 不一定对 xff0c 只
  • PX4代码解析(2)

    前言 在大致了解PX4代码架构后 xff0c 我们需要了解PX4的通信机制 在PX4代码架构中 xff0c 每通信总线主要分为两个部分 xff0c 一是内部通信总线uORB 即PX4内部进程通信采用的协议 xff0c 例如PX4内部姿态控制
  • px4代码解析(3)

    前言 在使用PX4飞控时 xff0c 我们难免要对其进行二次开发 xff0c 例如修改控制算法 xff0c 添加新的传感器 xff0c 这时需要在代码中定义属于自己的消息 本节主要分享一下如何在PX4代码中添加自己的消息 一 消息添加与配置
  • 七月在线NLP千元课程笔记

    xfeff xfeff NLP七月在线 照着PDF的内容解释 第一课 NLP基础知识 Python基础知识7分钟 正则表达式验证工具 https regexr com v1 基本字符 匹配除了换行符外所有字符 d匹配所有数字 能找到所有数字
  • PX4代码解析(4)

    一 引言 PX4程序是基于实时操作系统 xff08 Real time operating system RTOS xff09 的上层应用程序 xff0c PX4飞控程序的很多重要模块都是在Nuttx操作系统的调度下运行的 因此 xff0c
  • PX4代码解析(5)

    一 前言 我所讨论的PX4代码是基于v1 11版本 xff0c 该版本与之前的版本有不少不同 xff0c 其中一个比较大的区别在于新版本大部分用到了C 43 43 中模板 xff0c 使得代码没有以前那么容易理解 xff0c 因此我在后面介
  • gcc与Makefile

    一 gcc命令 在linux开发编程过程中 xff0c 需要对完成的代码进行编译运行 xff0c 这时我们便需要用到gcc命令 xff0c 下面我介绍gcc的安装与使用 1 安装 在ubuntu系统下终端中输入下面的命令 sudo apt
  • 大疆嵌入式工程师面试

    昨天刚刚经历了大疆嵌入式第一轮面试 xff0c 面试官是个大佬 xff0c 感觉很不错 xff0c 但大疆面试问的很深 xff0c 自己有些答得不是很好 xff0c 记录一下 一面 xff08 8 16号 xff0c 35min左右 xff
  • PX4代码解析(6)

    一 前言 上一节介绍了PX4姿态估计调用函数的流程 xff0c 这一节分享一下我对PX4姿态解算的解读 首先 xff0c 要理解PX4姿态解算的程序 xff0c 要先从传感器的特性入手 xff0c 这里主要介绍的传感器有加速度计 xff0c
  • 嵌入式学习(2)-FreeRTOS--任务调度器开启过程分析

    FreeRTOS 开启任务调度器过程分析 vTaskStartScheduler xff1b 代码分析其中一些汇编的寄存器操作还不是特别清楚 xff0c 还需要进一步去学习 vTaskStartScheduler xff1b 代码分析 sp
  • 嵌入式学习(3)-FreeRTOS的创建任务过程

    创建任务过程理解 xTaskCreate xff08 xff09 分析prvInitialiseNewTask xff08 xff09 函数分析vListInitialiseItem xff08 xff09 函数分析prvAddNewTas