FreeRTOS任务管理与控制

2023-05-16

Task.c文件:

全局变量:

 static xList pxReadyTasksLists[configMAX_PRIORITIES ];

static xListxDelayedTaskList1;       
PRIVILEGED_DATA static xListxDelayedTaskList2;      

< Delayed tasks (two lists are used - one fordelays that have overflowed the current tick count.

PRIVILEGED_DATA static xListxPendingReadyList;      

 任务已经就绪,但是调度被禁止,暂时放到pending列表

 

 PRIVILEGED_DATA static xListxSuspendedTaskList;     

 

任务控制块结构:

typedef struct tskTaskControlBlock
{


 volatileportSTACK_TYPE *pxTopOfStack; 

 

 

 

 #if ( portUSING_MPU_WRAPPERS == 1 )
       xMPU_SETTINGSxMPUSettings;    


 #endif 
 
 xListItem   xGenericListItem; 
 xListItem    xEventListItem;  
 unsignedportBASE_TYPE uxPriority;
 portSTACK_TYPE   *pxStack;   


 signedchar    pcTaskName[configMAX_TASK_NAME_LEN ];

 

 #if ( portSTACK_GROWTH > 0)
  portSTACK_TYPE*pxEndOfStack;   
 #endif

 #if ( portCRITICAL_NESTING_IN_TCB == 1 )
  unsigned portBASE_TYPEuxCriticalNesting;
 #endif

 #if ( configUSE_TRACE_FACILITY == 1 )
  unsignedportBASE_TYPE uxTCBNumber; 


 #endif

 #if ( configUSE_MUTEXES == 1 )
  unsigned portBASE_TYPEuxBasePriority; 


 #endif

 #if ( configUSE_APPLICATION_TASK_TAG == 1)
  pdTASK_HOOK_CODEpxTaskTag;
 #endif

 #if ( configGENERATE_RUN_TIME_STATS == 1)
  unsigned longulRunTimeCounter;  


 #endif

} tskTCB;

 

 

任务函数API:

 

主要分为以下几个:

任务创建:xTaskCreate()

删除:vTaskDelete()

优先级设置:vTaskPrioritySet()

任务挂起:vTaskSuspend()

任务唤醒:vTaskResume()

从中断函数唤醒:xTaskResumeFromISR()

禁止调度:vTaskSuspendAll()

允许调度:xTaskResumeAll()

 

一:任务创建。

signed portBASE_TYPE xTaskGenericCreate( pdTASK_CODE pxTaskCode,const signed char * const pcName, unsigned short usStackDepth, void*pvParameters, unsigned portBASE_TYPE uxPriority, xTaskHandle*pxCreatedTask, portSTACK_TYPE *puxStackBuffer, const xMemoryRegion* const xRegions )。

代码体概述:

1:分配TCB和任务堆栈  

 tskTCB * pxNewTCB; 

pxNewTCB = prvAllocateTCBAndStack( usStackDepth, puxStackBuffer);:

2:栈顶指针赋值: pxTopOfStack =pxNewTCB->pxStack + ( usStackDepth - 1 );

3:初始化变量:名称,优先级,那两个列表项:xGenericItem,xEventItem

 
  prvInitialiseTCBVariables(pxNewTCB, pcName, uxPriority, xRegions, usStackDepth );

       初始化列表项

       vListInitialiseItem( &(pxTCB->xGenericListItem ) );
       vListInitialiseItem( &(pxTCB->xEventListItem ) );

      设置所有者,以便通过xGenericListItem,xEventListItem找到盖TCB,及找到该任务。

      
     listSET_LIST_ITEM_OWNER( &(pxTCB->xGenericListItem ), pxTCB );

    
    listSET_LIST_ITEM_VALUE( &(pxTCB->xEventListItem ), configMAX_PRIORITIES -(               portTickType)    uxPriority );
      listSET_LIST_ITEM_OWNER( &(pxTCB->xEventListItem ), pxTCB );

4:判断是否是第一个任务

 if( uxCurrentNumberOfTasks == ( unsignedportBASE_TYPE ) 1 )
   {
    
    pxCurrentTCB=  pxNewTCB;

    

   如果是第一个任务,就初始化上面那些全局变量链表。
    prvInitialiseTaskLists();
   }
   else
   {
    
    if(xSchedulerRunning == pdFALSE )
    {
     if(pxCurrentTCB->uxPriority <=uxPriority )
     {
      pxCurrentTCB= pxNewTCB;
     }
    }
   }
 5:加入就绪链表

   uxTaskNumber++;

   prvAddTaskToReadyQueue(pxNewTCB );

下面列出函数体:

     while( (pxTCB = ( tskTCB * ) listGET_OWNER_OF_HEAD_ENTRY( pxDelayedTaskList) ) !=    NULL)      \
                            \
  if( xTickCount <listGET_LIST_ITEM_VALUE( &(pxTCB->xGenericListItem ) ))         \
                            
   break;                         

                            
  vListRemove( &(pxTCB->xGenericListItem ));                
                   
  if(pxTCB->xEventListItem.pvContainer)                  
                            
   vListRemove(&( pxTCB->xEventListItem ));                
           

   if(pxTCB->uxPriority >uxTopReadyPriority)                
                             
    uxTopReadyPriority=pxTCB->uxPriority;                 

                          
   vListInsertEnd( ( xList * )&( pxReadyTasksLists[pxTCB->uxPriority ] ), &(pxTCB-  >xGenericListItem ));                 
                  
     

 6:看看是否发生调度。

 if( xSchedulerRunning != pdFALSE )
  {
   

   如果系统已经在跑,而且这个新建立的任务优先级高,就发生调度。
   if(pxCurrentTCB->uxPriority < uxPriority)
   {
    portYIELD_WITHIN_API();//牵涉到任务调度,会在----FreeRTOS调度----详细介绍。
   }
  }

 

 

 

 

 

二:任务删除

freertos的任务删除分两步完成,

第一步在vTaskDelete中完成,FreeRTOS先把要删除的任务从就绪任务链表和事件等待链表中删除,然后把此任务添加到任务删除链表(即那个xTasksWaitingTermination), 若删除的任务是当前运行任务,系统就执行任务调度函数.

第2步 则是在idle任务中完成,idle任务运行时,检查xTasksWaitingTermination链表,如果有任务在这个表上,释放该任务占用的内存空间,并把该任务从任务删除链表中删除。

void vTaskDelete( xTaskHandle pxTaskToDelete )

{

    tskTCB*pxTCB;

 

       taskENTER_CRITICAL();

       {

           

           if( pxTaskToDelete == pxCurrentTCB )

           {

               pxTaskToDelete = NULL;

           }

 

           

           pxTCB = prvGetTCBFromHandle( pxTaskToDelete );

 

           traceTASK_DELETE( pxTCB );

 

           

           vListRemove( &(pxTCB->xGenericListItem ) );

 

                         

           if( pxTCB->xEventListItem.pvContainer )

           {//如果是,则把它从事件等待链表中删除

               vListRemove( &(pxTCB->xEventListItem ) );

           }

         //插入等待删除链表

           vListInsertEnd( ( xList * )&xTasksWaitingTermination, &(pxTCB->xGenericListItem ) );

          //增加uxTasksDeleted计 数

           ++uxTasksDeleted;

       }

       taskEXIT_CRITICAL();

 

       

       if( xSchedulerRunning != pdFALSE )

       {

           if( ( void * ) pxTaskToDelete == NULL )

           {

               taskYIELD();//调度会在FreeRTOS调度章节中介绍。

           }

       }

}

 

Idle任务。

static portTASK_FUNCTION( prvIdleTask, pvParameters)

{

 

( void ) pvParameters;

 

for( ;; )

{

 

prvCheckTasksWaitingTermination();

…………………………….

这里prvCheckTasksWaitingTermination()就是干这第2步的工作:每次调用它删除一个任务

static void prvCheckTasksWaitingTermination( void)

{

#if ( INCLUDE_vTaskDelete == 1 )

{

portBASE_TYPE xListIsEmpty;

 

 

if( uxTasksDeleted > ( unsignedportBASE_TYPE ) 0 )

{//禁止调度

vTaskSuspendAll();

xListIsEmpty = listLIST_IS_EMPTY(&xTasksWaitingTermination);             //打开调度

xTaskResumeAll();

 

if( !xListIsEmpty )

{

tskTCB *pxTCB;

//关中断

portENTER_CRITICAL();

{

pxTCB = ( tskTCB * ) listGET_OWNER_OF_HEAD_ENTRY( (( xList * ) &xTasksWaitingTermination ) );

vListRemove( &(pxTCB->xGenericListItem ) );

--uxCurrentNumberOfTasks;

--uxTasksDeleted;

}

portEXIT_CRITICAL();

//释放内存,删除tcb

prvDeleteTCB( pxTCB );

}

}

}

#endif

}

 

三:禁止调度,打开调度

调度器的禁止和打开

这是一种同步机制,比关中断要温和点。禁止调度由vTaskSuspendAll实现,打开调度由xTaskResumeAll实现。

void vTaskSuspendAll( void )

{

portENTER_CRITICAL();

++uxSchedulerSuspended;

portEXIT_CRITICAL();

}

这个很简单,系统维护一个计数uxSchedulerSuspended,当它大于0时候表示禁止调度,等于0则打开调度(允许调度)。

signed portBASE_TYPE xTaskResumeAll( void )

{

register tskTCB *pxTCB;

signed portBASE_TYPE xAlreadyYielded = pdFALSE;

 

 

在禁止调度器件,如果ISR导致一个任务就绪,这个任务会放在xPendingReadyList中,一旦调度允许,必须把所有的xPendingzList中的任务移动到theappropriate ready list中。

portENTER_CRITICAL();

{//将计数减一

--uxSchedulerSuspended;

//如果等于0,则允许调度

if( uxSchedulerSuspended == ( unsignedportBASE_TYPE ) pdFALSE )

{

if( uxCurrentNumberOfTasks > (unsigned portBASE_TYPE ) 0 )

{

portBASE_TYPE xYieldRequired = pdFALSE;

 

 

while( ( pxTCB = ( tskTCB * )listGET_OWNER_OF_HEAD_ENTRY(  ( ( xList * )&xPendingReadyList ) ) ) != NULL )

{

vListRemove( &(pxTCB->xEventListItem ) );

vListRemove( &(pxTCB->xGenericListItem ) );

prvAddTaskToReadyQueue( pxTCB );

 

 

if( pxTCB->uxPriority>= pxCurrentTCB->uxPriority )

{

xYieldRequired = pdTRUE;

}

}

 

 

if( uxMissedTicks > ( unsignedportBASE_TYPE ) 0 )

{

while( uxMissedTicks > ( unsignedportBASE_TYPE ) 0 )

{

vTaskIncrementTick();

--uxMissedTicks;

}

 

 

#if configUSE_PREEMPTION == 1

{

xYieldRequired = pdTRUE;

}

#endif

}

 

if( ( xYieldRequired == pdTRUE ) || ( xMissedYield== pdTRUE ) )

{

xAlreadyYielded = pdTRUE;

xMissedYield = pdFALSE;

taskYIELD();  //又一次发生任务调度函数调用,任务调度章节会详细介绍。

}

}

}

}

portEXIT_CRITICAL();

 

return xAlreadyYielded;

}

 

 

四:任务的挂起与唤醒。

freertos的任务挂起与ucosii也不大一样。它把 所有挂起的任务加到xSuspendedTaskList中,而且一旦调用vTaskSuspend()函数挂起一个任务,该任务就将从所有它原先连入的链表中删除(包括就绪表,延时表和它等待的事件链表),也就是说,和ucosii不同,一旦一个任务被挂起,它将取消先前它的延 时和对事件的等待。ucosii中是不同的,在ucosii里 面一个任务被挂起仅仅是把任务的状态或上一个OS_STAT_SUSPEND并从就绪表中删除,如果先前这个任务正在等待某事件,则并不取消等待。

//如果传进来的pxTaskToSuspend==NULL,则表示挂起当前任务

void vTaskSuspend( xTaskHandle pxTaskToSuspend)

{

tskTCB *pxTCB;

 

taskENTER_CRITICAL();

{

 

if( pxTaskToSuspend == pxCurrentTCB )

{

pxTaskToSuspend = NULL;

}

 

 

pxTCB = prvGetTCBFromHandle( pxTaskToSuspend );

 

traceTASK_SUSPEND( pxTaskToSuspend );

 

 

vListRemove( &(pxTCB->xGenericListItem ) );

 

 

if(pxTCB->xEventListItem.pvContainer )

{

vListRemove( &(pxTCB->xEventListItem ) );

}

//插到xSuspendedTaskList

vListInsertEnd( ( xList * )&xSuspendedTaskList, &(pxTCB->xGenericListItem ) );

}

taskEXIT_CRITICAL();

 

 

if( ( void * ) pxTaskToSuspend == NULL )

{

taskYIELD();///又是调度。

}

}

 

相反的唤醒就是把任务从xSuspendedTaskList中删除,加到对应的就绪链表中(根据任务的优先级),然后如果唤醒的任务优先级高于当前任务优先级,则调度。

void vTaskResume( xTaskHandle pxTaskToResume )

{

tskTCB *pxTCB;

 

 

pxTCB = ( tskTCB * ) pxTaskToResume;

 

 

if( pxTCB != NULL )

{

taskENTER_CRITICAL();

{

if( prvIsTaskSuspended( pxTCB ) == pdTRUE )

{

traceTASK_RESUME( pxTCB );

 

 

vListRemove(  &(pxTCB->xGenericListItem ) );

prvAddTaskToReadyQueue( pxTCB );

 

 

if( pxTCB->uxPriority>= pxCurrentTCB->uxPriority )

{

 

taskYIELD();  调度。。。。。。。。

}

}

}

taskEXIT_CRITICAL();

}

}

 从中断函数唤醒:

 portBASE_TYPE xTaskResumeFromISR(xTaskHandle pxTaskToResume )
 {
 portBASE_TYPE xYieldRequired = pdFALSE;
 tskTCB *pxTCB;

  pxTCB = (tskTCB * ) pxTaskToResume;

  if(xTaskIsTaskSuspended( pxTCB ) == pdTRUE )
  {
   traceTASK_RESUME_FROM_ISR(pxTCB );

   if(uxSchedulerSuspended == ( unsigned portBASE_TYPE ) pdFALSE )
   {
    xYieldRequired= ( pxTCB->uxPriority >=pxCurrentTCB->uxPriority );
    vListRemove( &( pxTCB->xGenericListItem ));
    prvAddTaskToReadyQueue(pxTCB );
   }
   else
   {
    
    vListInsertEnd(( xList * ) &( xPendingReadyList ),&( pxTCB->xEventListItem ) );
   }
  }

  returnxYieldRequired;
 }

#endif

 

上面两种唤醒不大一样:

任务重唤醒:可以直接进行任务调度(如果唤醒的优先级比正在运行的优先级高)。

中断唤醒:最多可以把被唤醒的任务加入到就绪表或者pendinglist中,返回可以进行调度标志变量。

五:设置优先级

 unsigned portBASE_TYPEuxTaskPriorityGet( xTaskHandle pxTask )
 {
 tskTCB *pxTCB;
 unsigned portBASE_TYPE uxReturn;

  portENTER_CRITICAL();
  {
   
   pxTCB =prvGetTCBFromHandle( pxTask );
   uxReturn =pxTCB->uxPriority;
  }
  portEXIT_CRITICAL();

  returnuxReturn;
 }

#endif

#if ( INCLUDE_vTaskPrioritySet == 1 )

 void vTaskPrioritySet(xTaskHandle pxTask, unsigned portBASE_TYPE uxNewPriority )
 {
 tskTCB *pxTCB;
 unsigned portBASE_TYPE uxCurrentPriority,xYieldRequired = pdFALSE;

  
  if( uxNewPriority>= configMAX_PRIORITIES )
  {
   uxNewPriority= configMAX_PRIORITIES - 1;
  }

  portENTER_CRITICAL();
  {
   if( pxTask ==pxCurrentTCB )
   {
    pxTask= NULL;
   }

   
   pxTCB =prvGetTCBFromHandle( pxTask );

   traceTASK_PRIORITY_SET(pxTask, uxNewPriority );

   #if (configUSE_MUTEXES == 1 )
   {
    uxCurrentPriority= pxTCB->uxBasePriority;
   }
   #else
   {
    uxCurrentPriority= pxTCB->uxPriority;
   }
   #endif

   if(uxCurrentPriority != uxNewPriority )
   {
    
    if(uxNewPriority > uxCurrentPriority )
    {
     if(pxTask != NULL )
     {
      
      xYieldRequired= pdTRUE;
     }
    }
    elseif( pxTask == NULL )
    {
     
     xYieldRequired= pdTRUE;
    }

 

    #if( configUSE_MUTEXES == 1 )
    {
     
     if(pxTCB->uxBasePriority ==pxTCB->uxPriority )
     {
      pxTCB->uxPriority= uxNewPriority;
     }

     
     pxTCB->uxBasePriority= uxNewPriority;
    }
    #else
    {
     pxTCB->uxPriority= uxNewPriority;
    }
    #endif

    listSET_LIST_ITEM_VALUE(&( pxTCB->xEventListItem ), (configMAX_PRIORITIES - ( portTickType ) uxNewPriority ) );

    
    if(listIS_CONTAINED_WITHIN( &( pxReadyTasksLists[uxCurrentPriority ] ), &(pxTCB->xGenericListItem ) ) )
    {
     
     vListRemove(&( pxTCB->xGenericListItem ));
     prvAddTaskToReadyQueue(pxTCB );
    }

    if(xYieldRequired == pdTRUE )
    {
     portYIELD_WITHIN_API();
    }
   }
  }
  portEXIT_CRITICAL();
 }

#endif

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

FreeRTOS任务管理与控制 的相关文章

  • STM32F103移植FreeRTOS必须搞明白的系列知识---3(堆栈)

    STM32F103移植FreeRTOS必须搞明白的系列知识 1 Cortex CM3中断优先级 STM32F103移植FreeRTOS必须搞明白的系列知识 2 FreeRTOS任务优先级 STM32F103移植FreeRTOS必须搞明白的系
  • FreeRTOS学习笔记(3、信号量、互斥量的使用)

    FreeRTOS学习笔记 3 信号量 互斥量的使用 前言 往期学习笔记链接 学习工程 信号量 semaphore 两种信号量的对比 信号量的使用 1 创建信号量 2 give 3 take 4 删除信号量 使用计数型信号量实现同步功能 使用
  • freertos---软定时器

    一 软件定时器介绍 freeRTOS软件定时器的时基是基于系统时钟节拍实现的 可以创建很多个 在硬件定时器资源不充足的情况下非常有用 软件定时器一般用作周期性地执行函数 在创建软件定时器时指定软件定时器的回调函数 在回调函数中实现相应的功能
  • 【FreeRTOS】队列的使用

    作者主页 凉开水白菜 作者简介 共同学习 互相监督 热于分享 多加讨论 一起进步 专栏资料 https pan baidu com s 1nc1rfyLiMyw6ZhxiZ1Cumg pwd free 点赞 收藏 再看 养成习惯 订阅的粉丝
  • FreeRTOS学习笔记<中断>

    中断概念 Cortex M的NVIC最多支持240个IRQ 中断请求 1个不可屏蔽中断 NMI 1个Systick 滴答定时器 定时器中断和多个系统异常 Cortex M处理器有多个用于管中断和异常的可编程寄存器 这些寄存器大多数都在 NV
  • FreeRTOS+CubeMX系列第一篇——初识FreeRTOS

    文章目录 一 关于FreeRTOS 二 FreeRTOS的特点 三 如何在CubeMX上配置FreeRTOS 四 FreeRTOS文档资料 五 同系列博客 一 关于FreeRTOS 1 什么是FreeRTOS FreeRTOS是一个迷你的实
  • FreeRTOS基础五:软件定时器

    软件定时器简介 软件定时器的作用 在指定的时间到来时执行指定的函数 或者以某个频率周期性地执行某个函数 被执行的函数叫做软件定时器回调函数 软件定时器由FreeRTOS内核实现 不需要硬件支持 软件定时器只有在软件定时器回调函数被调用时才需
  • freertos————互斥锁

    线程安全 多线程程序处于一个多变的环境 可访问的全局变量和堆数据随时可能被其他的线程改变 多个线程同时访问一个共享数据 可能造成严重的后果 出现问题的是之前移植了一个freemodbus的从站 多个任务访问全局变量保持寄存器区 导致最后读出
  • FreeRTOS之事件

    FreeRTOS之事件 声明 本人按照正点原子的FreeRTOS例程进行学习的 欢迎各位大佬指责和批评 谢谢 一 事件定义 事件 事件集 与高数上的集合意义差不多 事件啊 其实是实现任务间通信的机制 主要用于实现多任务间的同步 但是事件类型
  • FreeRTOS死机原因

    1 中断回调函数中没有使用中断级API xxFromISR 函数 xSemaphoreGiveFromISR uart busy HighterTask 正确 xSemaphoreGive uart busy 错误 2 比configMAX
  • FreeRTOS学习---“定时器”篇

    总目录 FreeRTOS学习 任务 篇 FreeRTOS学习 消息队列 篇 FreeRTOS学习 信号量 篇 FreeRTOS学习 事件组 篇 FreeRTOS学习 定时器 篇 FreeRTOS提供了一种软件定时器 用来快速实现一些周期性的
  • RT-Thread记录(五、RT-Thread 临界区保护与FreeRTOS的比较)

    本文聊聊临界区 以及RT Thread对临界区的处理 通过源码分析一下 RT Thread 对临界区保护的实现以及与 FreeRTOS 处理的不同 目录 前言 一 临界区 1 1 什么是临界区 1 2 RTOS中的临界区 二 RT Thre
  • 【FreeRTOS 事件】任务通知事件

    普通任务通知事件创建创建及运行 参阅安富莱电子demo define BIT 0 1 lt lt 0 define BIT 1 1 lt lt 1 static TaskHandle t xHandleTaskUserIF NULL sta
  • STM32 Freertos 添加 外部sram heap_5.c

    1 添加外部SRAM 初始化 2 添加heap 5 c 3 初始化heap 5 c 外部堆栈 Define the start address and size of the two RAM regions not used by the
  • FreeRTOS多任务调度器基础

    Cortex M4中SysTick调度器核心 Cortex M4中的中断管理 Cortex M4中影子栈指针 Cortex M4中SVC和PendSV异常 1 Cortex M4中SysTick调度器核心 systick每一次中断都会触发内
  • FreeRTOSConfig.h 配置优化及深入

    本篇目标 基于上一篇的移植freertos stm32f4 freertos 上 修改 FreeRTOSConfig h 文件的相关配置来优化辅助 FreeRtos 的使用 并且建立一些基本功能 信号量 消息地列等 的简单应用位于 stm3
  • 当一个任务写入变量而其他任务读取该变量时,我们是否需要信号量?

    我正在研究 freeRtos 并且我有一个名为 x 的变量 现在 每秒只有一个任务正在写入该变量 而其他任务正在读取该变量值 我需要用互斥锁来保护变量吗 如果变量为 32 位或更小 并且其值是独立的并且不与任何其他变量一起解释 则不需要互斥
  • FreeRTOS 匈牙利表示法 [重复]

    这个问题在这里已经有答案了 我是 RTOS 和 C 编程的新手 而且我仍在习惯 C 的良好实践 因此 我打开了一个使用 FreeRTOS 的项目 我注意到操作系统文件使用匈牙利表示法 我知道一点符号 但面临一些新的 标准 FreeRTOS
  • GNU Arm Cortex m4 上的 C++ 异常处理程序与 freertos

    2016 年 12 月更新现在还有一个关于此行为的最小示例 https community nxp com message 862676 https community nxp com message 862676 我正在使用带有 free
  • 小型 ARM 微控制器的 RTOS 内核之间的可量化差异 [关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 有许多不同的 RTOS 可用于微控制器 我专门寻找支持 ARM Cortex M 处理器的 RTOS 另外 我对闭源解决方案不感兴趣 试图从网站

随机推荐

  • 程序员也是会浪漫的->打造浪漫的Android表白程序

    一年前 xff0c 看到过有个牛人用HTML5绘制了浪漫的爱心表白动画 xff0c 后来又在华超的这篇文章上看到大神用Android写出了相同的效果 xff0c 于是也动手写了一下 xff0c 并加了一些功能 xff0c 感谢大神的指引 写
  • 清浅时光,岁月静好——我的2016

    前言 时光在不经意中流逝 xff0c 翻开旧日的笔记 xff0c 字里行间充满着情深意境的交错 仿佛回到了那曾经经历过的风风雨雨 xff0c 坎坎坷坷中逝去 xff0c 旧时的回忆依旧 xff0c 只是少了几分忧郁 xff0c 几分繁华 x
  • Android登录注册功能封装

    我们都知道Android应用软件基本上都会用到登录注册功能 xff0c 那么对一个一个好的登录注册模块进行封装就势在必行了 这里给大家介绍一下我的第一个项目中所用到的登录注册功能的 xff0c 已经对其进行封装 xff0c 希望能对大家有帮
  • Kotlin 官方学习教程之扩展

    扩展 类似于 C 和 Gosu xff0c Kotlin 也提供了一种可以在不继承父类也不使用类似装饰器这样的设计模式的情况下对指定类进行扩展的功能 这是通过称为扩展名的特殊声明来实现的 Kotlin 支持函数扩展和属性扩展 函数扩展 要声
  • Kotlin 官方学习教程之密封类与泛型

    密封类 密封类用于表示受限类层次结构 xff0c 当值可以有一个有限集合的类型 xff0c 但不能有其他类型 它们在某种意义上是枚举类的扩展 xff1a 枚举类型的值集合也受到限制 xff0c 但每个枚举常量仅作为单个实例存在 xff0c
  • 致年轻时如此拼搏的你我

    离别总是伤人意 这一篇文章写在这个时候是有其特殊意义和价值 xff0c 起码对我来说是这样的 这个时候正是一年一度的毕业季 xff0c 而我最敬重的师兄即将要离校实习 xff0c 很幸运的是师兄收到了很不错的 offer xff0c 在这里
  • ubuntu系统下,下载安装Python程序的方法汇总(wget;apt-get;easy_install;pip)

    1 源码安装 xff1a 已知源码的地址 xff0c 例如 xff1a https www python org ftp python 3 6 1 Python 3 6 1 tgz 这是Python3 6 1的源码地址 xff0c 则可以使
  • 【C语言刷LeetCode】qsort库函数,刷题利器

    之前刷过一些leetcode算法题 xff0c 挺痛苦的 xff0c 毕竟用的C语言 其中很大一部分题都是考察数组和字符串 刷题中得到一个经验 xff0c 遇见数组先考虑排序 xff0c 排序就选qsort 那现在就总结写qsort的几个不
  • 一文讲解ARM、STM32之间的关系以及STM单片机介绍

    一 什么是ARM ARM xff1a xff08 Advanced RISC Machines xff09 高级精简指令集微处理器 它有几层含义 xff1a 1 ARM是一个公司 xff0c 英国公司 只出售芯片的技术授权 2 ARM是全球
  • ESP8266串口WiFi模块基本使用方法和配置教程

    前言 ESP8266是一款超低功耗的UART WiFi 透传模块 拥有业内极富竞争力的封装尺寸和超低能耗技术 专为移动设备和物联网应用设计 可将用户的物理设备连接到Wi Fi 无线网络上 进行互联网或局域网通信 实现联网功能 由于本人一直从
  • linux 内存查看方法:meminfo\maps\smaps\status 文件解析

    linux 下面查看内存有多种渠道 xff0c 比如通过命令 ps top free 等 xff0c 比如通过 proc系统 xff0c 一般需要比较详细和精确地知道整机内存 某个进程内存的使用情况 xff0c 最好通过 proc 系统 x
  • 数值型模板参数

    本篇文章学习记录 xff1a 数值型模板参数 实现C 43 43 数组类模板 1 模板中的数值型参数 模板参数可以是数值型参数 也就是非类型参数 如下图所示 xff1a 我们可以像上面定义一个局部数组 xff0c 但是却不能这样定义 xff
  • 矩阵分解 (加法篇)

    转自简书 xff1a https www jianshu com p fc89d92bbc24 引言 分解的思想其实并不古老 xff0c 而且大家都熟悉的 xff0c 把复杂的分而治之 xff0c 然后再组合起来 分解有什么好处 xff1f
  • 矩阵分解 (乘法篇)

    引自简书 xff1a https www jianshu com p 0741789ffd06 引言 前面我们在矩阵分解 加法篇 里面分析的加法下的矩阵分解 这里我们来看看乘法下矩阵分解的要点 对角和三角矩阵 首先 xff0c 我们总结下
  • openwrt 编译 问题

    xfeff xfeff 问题一 xff1a OpenWrt can only be built on a case sensitive filesystem 原因是文件解压保存在windows的文件夹 xff0c 应该要解压到linux环境
  • stm32 RTC_WaitForSynchro()死循环

    1 RTC WaitForSynchro 死循环 xff0c 发现是没有执行RTC Configuration 增加函数 xff0c 但不知道对之后的时钟准确性有什么影响 Function Name RTC Configuration De
  • 用docker创建ubuntu VNC桌面

    docker ubuntu vnc desktop from xff1a http wiki ros org docker Tutorials GUI 1 image 地址 https github com fcwu docker ubun
  • Win10如何安装VC6

    这里我们不真的运行setup安装VC6 xff0c 因为在win10安装程序有很大的概率会被卡住 xff0c 就算安装成功也是各种问题 xff0c 包括你设置了兼容性 这里有一个不用安装也能直接运行的办法 xff0c 并且可以支持C 43
  • 在 VMware 虚拟机中安装 open-vm-tools

    什么是 open vm tools xff1f open vm tools 是 VMware Tools 的开源实施 xff0c 由一套虚拟化实用程序组成 xff0c 这些程序可增强虚拟机在 VMware 环境中的功能 xff0c 使管理更
  • FreeRTOS任务管理与控制

    Task c文件 xff1a 全局变量 xff1a static xList pxReadyTasksLists configMAX PRIORITIES static xListxDelayedTaskList1 PRIVILEGED D