Freertos 任务TASK(一) 任务创建

2023-05-16

任务的创建

Freertos 的任务创建难点
1)堆栈生长的方向
2)64字节的对齐
3)任务堆栈初始化

Freertos 的任务使用任务控制块来进行管理,是对任务的抽象。任务本身就是一段可执行的代码,存储在嵌入式设备的只读存储器上。为了让操作系统的调度器方便管理,把这段代码在逻辑上分割为一个任务。

Freertos 中对于任务控制块的定义

typedef struct tskTaskControlBlock       /* The old naming convention is used to prevent breaking kernel aware debuggers. */
{
    volatile StackType_t * pxTopOfStack; /*< Points to the location of the last item placed on the tasks stack.  THIS MUST BE THE FIRST MEMBER OF THE TCB STRUCT. */

    #if ( portUSING_MPU_WRAPPERS == 1 )
        xMPU_SETTINGS xMPUSettings; /*< The MPU settings are defined as part of the port layer.  THIS MUST BE THE SECOND MEMBER OF THE TCB STRUCT. */
    #endif

    ListItem_t xStateListItem;                  /*< The list that the state list item of a task is reference from denotes the state of that task (Ready, Blocked, Suspended ). */
    ListItem_t xEventListItem;                  /*< Used to reference a task from an event list. */
    UBaseType_t uxPriority;                     /*< The priority of the task.  0 is the lowest priority. */
    StackType_t * pxStack;                      /*< Points to the start of the stack. */
    char pcTaskName[ configMAX_TASK_NAME_LEN ]; /*< Descriptive name given to the task when created.  Facilitates debugging only. */ /*lint !e971 Unqualified char types are allowed for strings and single characters only. */

    #if ( ( portSTACK_GROWTH > 0 ) || ( configRECORD_STACK_HIGH_ADDRESS == 1 ) )
        StackType_t * pxEndOfStack; /*< Points to the highest valid address for the stack. */
    #endif

    #if ( portCRITICAL_NESTING_IN_TCB == 1 )
        UBaseType_t uxCriticalNesting; /*< Holds the critical section nesting depth for ports that do not maintain their own count in the port layer. */
    #endif

    #if ( configUSE_TRACE_FACILITY == 1 )
        UBaseType_t uxTCBNumber;  /*< Stores a number that increments each time a TCB is created.  It allows debuggers to determine when a task has been deleted and then recreated. */
        UBaseType_t uxTaskNumber; /*< Stores a number specifically for use by third party trace code. */
    #endif

    #if ( configUSE_MUTEXES == 1 )
        UBaseType_t uxBasePriority; /*< The priority last assigned to the task - used by the priority inheritance mechanism. */
        UBaseType_t uxMutexesHeld;
    #endif

    #if ( configUSE_APPLICATION_TASK_TAG == 1 )
        TaskHookFunction_t pxTaskTag;
    #endif

    #if ( configNUM_THREAD_LOCAL_STORAGE_POINTERS > 0 )
        void * pvThreadLocalStoragePointers[ configNUM_THREAD_LOCAL_STORAGE_POINTERS ];
    #endif

    #if ( configGENERATE_RUN_TIME_STATS == 1 )
        configRUN_TIME_COUNTER_TYPE ulRunTimeCounter; /*< Stores the amount of time the task has spent in the Running state. */
    #endif

    #if ( configUSE_NEWLIB_REENTRANT == 1 )

        /* Allocate a Newlib reent structure that is specific to this task.
         * Note Newlib support has been included by popular demand, but is not
         * used by the FreeRTOS maintainers themselves.  FreeRTOS is not
         * responsible for resulting newlib operation.  User must be familiar with
         * newlib and must provide system-wide implementations of the necessary
         * stubs. Be warned that (at the time of writing) the current newlib design
         * implements a system-wide malloc() that must be provided with locks.
         *
         * See the third party link http://www.nadler.com/embedded/newlibAndFreeRTOS.html
         * for additional information. */
        struct  _reent xNewLib_reent;
    #endif

    #if ( configUSE_TASK_NOTIFICATIONS == 1 )
        volatile uint32_t ulNotifiedValue[ configTASK_NOTIFICATION_ARRAY_ENTRIES ];
        volatile uint8_t ucNotifyState[ configTASK_NOTIFICATION_ARRAY_ENTRIES ];
    #endif

    /* See the comments in FreeRTOS.h with the definition of
     * tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE. */
    #if ( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 ) /*lint !e731 !e9029 Macro has been consolidated for readability reasons. */
        uint8_t ucStaticallyAllocated;                     /*< Set to pdTRUE if the task is a statically allocated to ensure no attempt is made to free the memory. */
    #endif

    #if ( INCLUDE_xTaskAbortDelay == 1 )
        uint8_t ucDelayAborted;
    #endif

    #if ( configUSE_POSIX_ERRNO == 1 )
        int iTaskErrno;
    #endif
} tskTCB;

很长的代码很多成员变量。这里讨论任务必须的部分
在这里插入图片描述
每个成员的含义代码中有详细的解释,需要强调的是pxStack代表的堆栈的起始地址,就是定义的时候。那个数组的首地址,代表堆栈空间通过他找到堆栈空间。
pxTopOfStack 表示栈顶,就是下一个写入栈的位置。

初始化

    TaskHandle_t xTaskCreateStatic( TaskFunction_t pxTaskCode,
                                    const char * const pcName, /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
                                    const uint32_t ulStackDepth,
                                    void * const pvParameters,
                                    UBaseType_t uxPriority,
                                    StackType_t * const puxStackBuffer,
                                    StaticTask_t * const pxTaskBuffer )
    {
        TCB_t * pxNewTCB;
        TaskHandle_t xReturn;

        configASSERT( puxStackBuffer != NULL );
        configASSERT( pxTaskBuffer != NULL );

        #if ( configASSERT_DEFINED == 1 )
            {
                /* Sanity check that the size of the structure used to declare a
                 * variable of type StaticTask_t equals the size of the real task
                 * structure. */
                volatile size_t xSize = sizeof( StaticTask_t );
                configASSERT( xSize == sizeof( TCB_t ) );
                ( void ) xSize; /* Prevent lint warning when configASSERT() is not used. */
            }
        #endif /* configASSERT_DEFINED */

        if( ( pxTaskBuffer != NULL ) && ( puxStackBuffer != NULL ) )
        {
            /* The memory used for the task's TCB and stack are passed into this
             * function - use them. */
            pxNewTCB = ( TCB_t * ) pxTaskBuffer; /*lint !e740 !e9087 Unusual cast is ok as the structures are designed to have the same alignment, and the size is checked by an assert. */
            pxNewTCB->pxStack = ( StackType_t * ) puxStackBuffer;

            #if ( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 ) /*lint !e731 !e9029 Macro has been consolidated for readability reasons. */
                {
                    /* Tasks can be created statically or dynamically, so note this
                     * task was created statically in case the task is later deleted. */
                    pxNewTCB->ucStaticallyAllocated = tskSTATICALLY_ALLOCATED_STACK_AND_TCB;
                }
            #endif /* tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE */

            prvInitialiseNewTask( pxTaskCode, pcName, ulStackDepth, pvParameters, uxPriority, &xReturn, pxNewTCB, NULL );
            prvAddNewTaskToReadyList( pxNewTCB );
        }
        else
        {
            xReturn = NULL;
        }

        return xReturn;
    }

#endif /* SUPPORT_STATIC_ALLOCATION */

请看下图
在这里插入图片描述

动态初始化和静态初始化,所谓动静是指栈空间的创建。
初始化的部分目前看还比较单纯,传入参数赋值到对应的TCB结构体中。
State list item 代表任务存在于各个状态列表里面的 。State list 在Readylist里面代表任务处于就绪态
重要的部分代码如下

/*-----------------------------------------------------------*/

static void prvInitialiseNewTask( TaskFunction_t pxTaskCode,
                                  const char * const pcName, /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
                                  const uint32_t ulStackDepth,
                                  void * const pvParameters,
                                  UBaseType_t uxPriority,
                                  TaskHandle_t * const pxCreatedTask,
                                  TCB_t * pxNewTCB,
                                  const MemoryRegion_t * const xRegions )
{
    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 ( tskSET_NEW_STACKS_TO_KNOWN_VALUE == 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 /* tskSET_NEW_STACKS_TO_KNOWN_VALUE */

    /* 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 !e9033 !e9078 MISRA exception.  Avoiding casts between pointers and integers is not practical.  Size differences accounted for using portPOINTER_SIZE_TYPE type.  Checked by assert(). */

            /* Check the alignment of the calculated top of stack is correct. */
            configASSERT( ( ( ( portPOINTER_SIZE_TYPE ) pxTopOfStack & ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) == 0UL ) );

            #if ( configRECORD_STACK_HIGH_ADDRESS == 1 )
                {
                    /* Also record the stack's high address, which may assist
                     * debugging. */
                    pxNewTCB->pxEndOfStack = pxTopOfStack;
                }
            #endif /* configRECORD_STACK_HIGH_ADDRESS */
        }
    #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. */
    if( pcName != NULL )
    {
        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 ] == ( char ) 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';
    }
    else
    {
        /* The task has not been given a name, so just ensure there is a NULL
         * terminator when it is read out. */
        pxNewTCB->pcTaskName[ 0 ] = 0x00;
    }

    /* This is used as an array index so must ensure it's not too large. */
    configASSERT( uxPriority < configMAX_PRIORITIES );

    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 = ( configRUN_TIME_COUNTER_TYPE ) 0;
        }
    #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 )
        {
            memset( ( void * ) &( pxNewTCB->pvThreadLocalStoragePointers[ 0 ] ), 0x00, sizeof( pxNewTCB->pvThreadLocalStoragePointers ) );
        }
    #endif

    #if ( configUSE_TASK_NOTIFICATIONS == 1 )
        {
            memset( ( void * ) &( pxNewTCB->ulNotifiedValue[ 0 ] ), 0x00, sizeof( pxNewTCB->ulNotifiedValue ) );
            memset( ( void * ) &( pxNewTCB->ucNotifyState[ 0 ] ), 0x00, sizeof( pxNewTCB->ucNotifyState ) );
        }
    #endif

    #if ( configUSE_NEWLIB_REENTRANT == 1 )
        {
            /* Initialise this task's Newlib reent structure.
             * See the third party link http://www.nadler.com/embedded/newlibAndFreeRTOS.html
             * for additional information. */
            _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 )
        {
            /* If the port has capability to detect stack overflow,
             * pass the stack end address to the stack initialization
             * function as well. */
            #if ( portHAS_STACK_OVERFLOW_CHECKING == 1 )
                {
                    #if ( portSTACK_GROWTH < 0 )
                        {
                            pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxNewTCB->pxStack, pxTaskCode, pvParameters, xRunPrivileged );
                        }
                    #else /* portSTACK_GROWTH */
                        {
                            pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxNewTCB->pxEndOfStack, pxTaskCode, pvParameters, xRunPrivileged );
                        }
                    #endif /* portSTACK_GROWTH */
                }
            #else /* portHAS_STACK_OVERFLOW_CHECKING */
                {
                    pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxTaskCode, pvParameters, xRunPrivileged );
                }
            #endif /* portHAS_STACK_OVERFLOW_CHECKING */
        }
    #else /* portUSING_MPU_WRAPPERS */
        {
            /* If the port has capability to detect stack overflow,
             * pass the stack end address to the stack initialization
             * function as well. */
            #if ( portHAS_STACK_OVERFLOW_CHECKING == 1 )
                {
                    #if ( portSTACK_GROWTH < 0 )
                        {
                            pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxNewTCB->pxStack, pxTaskCode, pvParameters );
                        }
                    #else /* portSTACK_GROWTH */
                        {
                            pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxNewTCB->pxEndOfStack, pxTaskCode, pvParameters );
                        }
                    #endif /* portSTACK_GROWTH */
                }
            #else /* portHAS_STACK_OVERFLOW_CHECKING */
                {
                    pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxTaskCode, pvParameters );
                }
            #endif /* portHAS_STACK_OVERFLOW_CHECKING */
        }
    #endif /* portUSING_MPU_WRAPPERS */

    if( 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();
    }
}

在这里插入图片描述
堆栈方向的理解

‘push’ 指令之后, sp (stack pointer)寄存器数值变大了,就是‘向上(高地址)长’;

反之,‘push’ 指令之后, sp (stack pointer)寄存器数值变小了,就是‘向下(低地址)长’。

上图标注了,不同的堆栈生长方向情况下,堆栈指针的初始化情况。

堆栈的初始化

模拟一次堆栈入栈,是个时候任务函数指针终于排上用场。被填入到PC寄存器对应的栈位。
下一次正常做上下文切换的入栈时,任务函数的地址就会推入PC指针,任务得以开始启动。

在这里插入图片描述

字节对齐

可以理解为,处理器数据总线的宽度,如果地址按照字节的单次变动小于宽度,那么指针不会移动。所以确保指针能有效移动,需要进行对齐。N*length 1>=1 就可以有效移动指针。

总结

任务的初始化,包含两部分
1.用户设定的各种数据进行装填,归总到TCB上
2.对任务内存空间初始化主要是栈的初始化
模拟一次任务的入栈是程序第一次得以运行的保证

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

Freertos 任务TASK(一) 任务创建 的相关文章

  • 为什么对于没有通过方法反射获取返回类型的 Task,Type.IsGenericType 返回 TRUE,而 typeof(Task).IsGenericTyp 返回 FALSE

    有人可以解释一下吗 根据文档是泛型类型 https learn microsoft com en us dotnet api system type isgenericparameter view netframework 4 7 2 指示
  • IRequestHandler 返回 void

    请看下面的代码 public class CreatePersonHandler IRequestHandler
  • 任务状态:等待激活 -DownloadStringTaskAsync -WP8

    任务的状态始终为 等待激活 任务的结果 我不明白为什么 谢谢你的帮助 UI 调用 GetDocLibs 方法 public class ServerFunctions public static List
  • 编辑 UI 的 task.Wait() 上出现死锁

    我试图在这里找到一些解决我的问题的方法 但没有结果 或者我只是没有得到正确的结果 所以如果有人可以帮助 解释我将非常感激 我正在使用 Win Form 为系统管理员开发一个工具 现在我需要在选定的后台运行的计算机上创建连续的 ping UI
  • Rails rake 任务是否提供对 ActiveRecord 模型的访问?

    我正在尝试创建自定义 rake 任务 但似乎我无权访问我的模型 我认为这是 Rails 任务中隐含的内容 我在 lib tasks test rake 中有以下代码 namespace test do task new task do pu
  • C++ freeRTOS任务,非静态成员函数的无效使用

    哪里有问题 void MyClass task void pvParameter while 1 this gt update void MyClass startTask xTaskCreate this gt task Task 204
  • 任务中重新抛出异常 (TPL) 丢失堆栈跟踪

    我有重新抛出异常的代码 当我后来从 task Exception 读取异常时 它的堆栈跟踪指向我重新抛出异常的位置 如我所料 第 n 行而不是第 m 行 为什么会这样呢 TPL 中的错误或更可能是我忽略的东西 当我解决方法时 我可以将异常包
  • 有没有正确的方法来取消异步任务?

    我遇到了如何正确取消异步任务的问题 这是一些草稿 我的入口点运行两个异步任务 第一个任务做了一些 长时间 的工作 第二个任务取消了它 入口点 private static void Main var ctc new Cancellation
  • 无论如何,Task.Factory.StartNew 在 UI 线程上调用

    我必须处理一个奇怪的问题 至少从我的角度来看是这样 我使用任务来等待变量获取特定值 然后再次在 ui 线程上运行 继续 部分 现在的问题是 在我调用 StartNew 之前 调用内部的 ManagedThreadId 是相同的 它会冻结我的
  • 什么时候应该将任务视为“长时间运行”?

    在处理任务时 经验法则似乎是线程池 通常由例如调用Task Run or Parallel Invoke 应该用于相对较短运营 当处理长时间运行的操作时 我们应该使用TaskCreationOptions LongRunning标志是为了
  • 并发任务更新复杂对象 JavaFX - swingworker 等效项?

    我想在后台运行一个任务 更新视图中的中间结果 我正在尝试实现 MVC JavaFX 应用程序 任务在模型中定义 我想将部分结果发送给主要威胁 以便在视图中显示它们 我使用 updateValue 来执行此操作 另外 我在控制器中定义了对象属
  • Flash Builder 中的 TODO 任务列表

    Flash Builder 支持任务列表吗 我正在测试 PHP 的 Flash Builder 我可以在 PHP 代码中看到我的 TODO 但在 AS 或 MXML 中看不到 我找到了这个插件 http www richinternet d
  • 使用VB.net创建计划任务[重复]

    这个问题在这里已经有答案了 如何使用 VB NET 创建计划任务 单击按钮时从 vb net 程序填充计划任务字段 我现在什么都没有 也不知道是否可能 您必须围绕本机 COM 接口创建包装器 如果你不想自己做 你可以使用这个库https t
  • 如何在组织模式下取消选中下一个循环/重复任务的复选框

    对于组织模式下的循环或重复任务 在该任务内 如果有多个复选框且全部标记为勾选 则在一般任务屏蔽为 完成 后 下一个循环周期的复选框仍显示为勾选 并且应该取消勾选 例如 TODO Cyclic monthly home 0 5 SCHEDUL
  • Task.IsCancelled 不起作用

    我有以下示例代码 static class Program static void Main var cts new CancellationTokenSource var task Task Factory StartNew gt try
  • 如何处理Task.Run异常

    我在捕获异常时遇到问题Task Run这是通过更改代码解决的 如下所示 我想知道这两种方式处理异常之间的区别 In the Outside方法我无法捕获异常 但是在Inside方法我可以 void Outside try Task Run
  • 哪些变量类型/大小在 STM32 微控制器上是原子的?

    以下是 STM32 微控制器上的数据类型 http www keil com support man docs armcc armcc chr1359125009502 htm http www keil com support man d
  • 如何取消等待中的任务?

    我正在处理这些 Windows 8 WinRT 任务 并且尝试使用下面的方法取消任务 并且它在某种程度上有效 CancelNotification 方法确实被调用 这使您认为任务已被取消 但在后台任务仍在运行 然后在完成后 任务的状态始终为
  • Gradle创建多项目Jar

    因此 从 Gradle 和 Android Studio 诞生之初起 我就一直在使用它们 然而 我发现自己用头撞墙的次数有时远远超过了它的价值 我花了一天半的时间试图解决我目前的困境 在我工作的地方 我们使用很多共享库项目 这意味着与 Gr
  • 适用于多应用项目的 Grunt 和 requirejs 优化器

    我在让 Grunt 对具有以下结构的项目执行 requirejs 优化时遇到问题 static js apps app js dash js news js many more app files build collections lib

随机推荐

  • 基于ROS的语音控制机器人(二):上位机的实现

    文章目录 目录 文章目录 前言 一 准备工作 1 python工作环境 2 ros环境 3 QT designer 二 界面程序设计 1 界面设计 2 ui文件转py文件 三 上位机程序编写 1 具体思路 2 具体实现 3 遇到的问题 1
  • "指定的文件格式无法识别或为不支持的二进制"

    次奥 xff0c 你没有正确设置启动项目 转载于 https www cnblogs com tupx p 3701598 html
  • Linux安装MySQL8.0.16

    1 下载安装包 https www mysql com 2 安装MySQL 将下载好的安装包上传到服务器 然后解压 tar xvf mysql 8 0 16 el7 x86 64 tar gz 然后将解压目录重命名为mysql 8 0 16
  • 硬件中断和软件中断的区别

    中断 中断指当出现需要时 xff0c CPU暂时停止当前程序的执行转而执行处理新情况的程序和执行过程 即在程序运行过程中 xff0c 系统出现了一个必须由CPU立即处理的情况 xff0c 此时 xff0c CPU暂时中止程序的执行转而处理这
  • 嵌入式C语言自我修养笔记1-ARM体系结构与编译运行

    目录 ARM 体系结构ARM 体系结构ARM 汇编指令ARM 寻址方式ARM 伪指令C 与汇编混合编程 程序编译链接与安装运行预处理过程编译过程链接过程程序安装apt get链接静态库动态链接共享库插件工作原理Linux 内核模块运行机制L
  • Renode应用:在RISC-V核上运行FreeRTOS

    本篇记录通过Renode在RISC V核上运行FreeRTOS demo的情况 本来不准备写这一篇 xff0c 但是发现近期工作学习密度实在太大 xff0c 上周工作的中间结果这周竟然完全想不起来了 xff0c 不得不又花了一些时间从头摸索
  • VideoStream流媒体(VOD视频点播)系统平台

    软件介绍 xff1a VideoStream是集流媒体视频服务和流媒体应用管理为一体的综合流媒体服务系统 xff0c 本产品通过宽带IP网络为教育系统 各类运营商 政府企业等用户提供音视频服务的应用 系统特点 xff1a 1 采用WEB端口
  • c语言实现模拟FTP服务器项目

    下载源码后 xff0c 直接可以在ubuntu中编译运行 xff1a FTP服务器程序功能 xff1a 客户端 xff1a 1 输入命令 xff1a help 查看FTP服务器所支持的所有命令 2 输入名 xff1a ls 查看服务器上可以
  • 基于ArUco的视觉定位

    参考如下 博客 基于ArUco的视觉定位 1 3 https www freesion com article 4265319144 基于ArUco的视觉定位 4 https www pianshen com article 2491452
  • 伺服电机和步进电机的区别

    硬件型号 xff1a 三菱伺服电机HG KR43J 系统版本 xff1a 电机系统 1 控制的方式不同 步进电机 xff1a 通过控制脉冲的个数控制转动角度的 xff0c 一个脉冲对应一个步距角 伺服电机 xff1a 通过控制脉冲时间的长短
  • ubutnu更换国内源后,更新一直出现404,Not Found的问题

    1 问题 题主系统是ubuntu16 04 64位系统 尝试更换国内各种源 连ubuntu官方源都尝试了 sudo vim etc apt sources list修改为 deb https mirrors tuna tsinghua ed
  • Python+Flask实现股价查询系统。Python绘制股票k线走势

    文章目录 一 实现效果图二 实现思路1 获取数据 2 可视化数据三 源码获取 一 实现效果图 打开默认显示半年线 xff0c 可以通过可视化类型选择可视化k线图 高低点等 xff08 目前只完成了初版 xff0c 当查询的股票数据返回为空时
  • Failed to fetch http://mirrors.tuna.tsinghua.edu.cn/ubuntu/pool/main/g/gcc-5/g++-5_5.4.0-6ubuntu1~16

    今天在ubutun中在安装redis过程中 xff0c 安装gcc时遇到了Failed to fetch http mirrors tuna tsinghua edu cn ubuntu pool main g gcc 5 g 43 43
  • 切换日语输入法找不到MicrosoftIME键盘选项了

    去微软官方下载一个 Microsoft IME office 2010后 xff0c 安装解决 转载于 https www cnblogs com tupx p 3816026 html
  • msgid 属性

    Android源码中的String xml文件 xff0c msgid这个属性是干嘛的 xff1f 全局资源 xff0c 方便引用 比如在布局的text和activity中用到 转载于 https www cnblogs com Ph on
  • 2017年09月23日普级组 数列

    Description 小S今天给你出了一道找规律题 xff0c 题目如下 xff1a 有如下的数列1 xff0c 11 xff0c 21 xff0c 1211 xff0c 111221 xff0c 312211 xff0c 小S问你这个数
  • python 机器学习实战:信用卡欺诈异常值检测

    今晚又实战了一个小案例 xff0c 把它总结出来 xff1a 有些人利用信用卡进行诈骗等活动 xff0c 如何根据用户的行为 xff0c 来判断该用户的信用卡账单涉嫌欺诈呢 xff1f 数据集见及链接 xff1a 在这个数据集中 xff0c
  • Virtual Serial Port Driver 虚拟串口工具软件 使用介绍

    一般来说 xff0c 电脑的外部设备可以用过各种端口和电脑连接 常见的有USB xff0c VGA xff0c DVI等等 在工业领域或者是软件开发领域 xff0c 我们常常需要用简单低成本快捷的方式 xff0c 完成电脑和设备的连接 那么
  • Freertos 源码分析 队列queue

    队列queue xff08 零 xff09 队列的基础概念和形态 xff08 一 xff09 Freertos 队列 queue c FreeRTOS Kernel 10 4 6 include queue h Freertos队列模块包含
  • Freertos 任务TASK(一) 任务创建

    任务的创建 Freertos 的任务创建难点 1 xff09 堆栈生长的方向 2 xff09 64字节的对齐 3 xff09 任务堆栈初始化 Freertos 的任务使用任务控制块来进行管理 xff0c 是对任务的抽象 任务本身就是一段可执