精华内容
下载资源
问答
  • 执行任务队列

    2019-02-26 16:55:00
    线程的 JavaScript 一段一段地执行,前面的执行完了,再执行后面的,试想一个,如果前一个任务需要执行很久,比如接口请求、I/O 操作,此时后面的任务只能干巴巴地等待么?干等不仅浪费了资源,而且页面的交互程度...
    单线程的 JavaScript 一段一段地执行,前面的执行完了,再执行后面的,试想一个,如果前一个任务需要执行很久,比如接口请求、I/O 操作,此时后面的任务只能干巴巴地等待么?干等不仅浪费了资源,而且页面的交互程度也很差。JavaScript 意识到了这个问题,他们将任务分成了同步任务和异步任务,对于二者有不同的处理。
     
    JavaScript 在运行时会将变量存放在堆(heap)和栈(stack)中,堆中通常存放着一些对象,而变量及对象的指针则存放在栈中。JavaScript 在执行时,同步任务会排好队,在主线程上按照顺序执行,前面的执行完了再执行后面的,排队的地方叫执行栈(execution context stack)。JavaScript 对异步任务不会停下来等待,而是将其挂起,继续执行执行栈中的同步任务,当异步任务有返回结果时,异步任务会加入与执行栈不一样的队列,即任务队列(task queue),所以任务队列中存放的是异步任务执行完成后的结果,通常是回调函数。
     
    当执行栈的同步任务已经执行完成,此时主线程闲下来,它便会去查看任务队列是否有任务,如果有,主线程会将最先进入任务队列的任务加入到执行栈中执行,执行栈中的任务执行完了之后,主线程便又去任务队列中查看是否有任务可执行。主线程去任务队列读取任务到执行栈中去执行,这个过程是循环往复的,这便是 Event Loop,事件循环。
     
    网上有张流传甚广的图对这一过程进行了总结,在图中我们可以看到,JavaScript 在运行时产生了堆和栈,ajax、setTimeout 等异步任务被挂起,异步任务的返回结果加入任务队列,主线程会循环往复地读取任务队列中的任务,加入执行栈中执行。
    为了更好的理解 JavaScript 的执行机制,我们来看个小例子。
    1 console.log(1)
    2 setTimeout(function() {
    3     console.log(2)
    4 }, 300)
    5 console.log(3)
    输出的结果是 1,3,2。setTimeout 是一个定时器,延迟 300 毫秒执行,所以 300 毫秒后,打印 2 的回调函数才会进入任务队列,等到执行栈中的代码执行完成后,也就是打印出 1 和 3 后,打印出 2 的回调函数才进入执行栈执行。
     
    如果将 setTimeout 的第二个参数设置为 0,它表示主线程空闲之后尽早执行它的回调,HTML5 规定 setTimeout 的第二个参数不得小于 4 毫秒。
    1 setTimeout(function() {
    2     console.log(1)
    3 }, 0)
    4 console.log(2)
    5 
    6 //  2,1

    对于 setTimeout 还有一个需要注意的是,它的延迟时间并不是等待多少毫秒后就一定会执行,始终是要等待主线程已经空闲了才会去读取它,如果执行栈中的任务需要很长时间才能执行完,那任务队列中的任务只能等待。我们可以通过一个例子来体验一下。

     1 var enterTime = Date.now()
     2 
     3 function sleep(time) {
     4   for(var temp = Date.now(); Date.now() - temp <= time;);
     5 }
     6 
     7 setTimeout(function() {
     8     var exeTime = Date.now()
     9     console.log(exeTime - enterTime)
    10 }, 300)
    11 
    12 sleep(1000)    // 睡眠 1 秒

    我们定义了一个 sleep 函数,设置了 1 秒的执行时间,所以 setTimeout 要等待的时间肯定大于 1 秒,而不是 300 毫秒后就执行了。上述代码的执行结果是 1000 左右,值不固定,可以复制代码到控制台执行看看。

    转载于:https://www.cnblogs.com/wangtao-/p/10438490.html

    展开全文
  • CC2640R2F BLE5.0 蓝牙协议GAPRole 任务

    千次阅读 2017-08-03 10:24:44
    GAPRole 任务 GAP层始终处于下面4种角色之一运行: Broadcaster(广播者):设备发送不可连接的广播。Observer(观察者):设备扫描广播但无法启动连接。Peripheral(外围设备):该设备是可连接的广播,并在单一...
    公司主页 文档归类 淘宝

    GAPRole 任务

    GAP层始终处于下面4种角色之一运行:

    • Broadcaster(广播者):设备发送不可连接的广播。
    • Observer(观察者):设备扫描广播但无法启动连接。
    • Peripheral(外围设备):该设备是可连接的广播,并在单一链路层连接中作为从设备运行。
    • Central(中央设备):设备扫描广告并启动连接,并在单个或多个链路层连接中作为主服务器运行。蓝牙低功耗中央协议栈支持多达三个并发连接。

    蓝牙核心规范5.0版允许多角色,这是由蓝牙低功耗协议栈所支持的某些组合。也就是说一个设备可以同时作为中央和外围设备,这其实就是蓝牙组网的基础。

    注意:一般Broadcaster和Observer作为一组设备使用,Peripheral和Central作为一组设备使用。比如一个温度计,它作为broadcaster每隔1S 发送一次温度值,然后一个显示器作为observer不断的接收广播并显示,但是不连接,只显示温度值。或者peripheral作为一个计步器,手机作为一个central,他们之间需要建立连接之后再进行数据传输。

    下面我们以peripheral Role和central Role来进行说明

    peripheral Role

    外设GAPRole任务在peripheral.c和peripheral.h中定义。有关完整的API外设角色API,请参阅BLE Stack API参考,包括命令,可配置参数,事件和回调。使用此模块的步骤如下:

    1. 初始化GAPRole参数,这部分代码在simple_peripheral.c的SimpleBLEPeripheral_init中能够找到。
    	   // Setup the GAP Peripheral Role Profile
    	
    	   {
    	
    	    uint8_t initialAdvertEnable = TRUE;
    	
    	    uint16_t advertOffTime = 0;
    	
    	    uint8_t enableUpdateRequest = DEFAULT_ENABLE_UPDATE_REQUEST;
    	    uint16_t desiredMinInterval = DEFAULT_DESIRED_MIN_CONN_INTERVAL;
    	    uint16_t desiredMaxInterval = DEFAULT_DESIRED_MAX_CONN_INTERVAL;
    	    uint16_t desiredSlaveLatency = DEFAULT_DESIRED_SLAVE_LATENCY;
    	    uint16_t desiredConnTimeout = DEFAULT_DESIRED_CONN_TIMEOUT;
    	
    	    // Set the GAP Role Parameters
    	
    	    GAPRole_setParameter(GAPROLE_ADVERT_ENABLED, sizeof(uint8_t),&initialAdvertEnable);
    	    GAPRole_setParameter(GAPROLE_ADVERT_OFF_TIME, sizeof(uint16_t), &advertOffTime); 
    		GAPRole_setParameter(GAPROLE_SCAN_RSP_DATA,sizeof(scanRspData), scanRspData);
    	    GAPRole_setParameter(GAPROLE_ADVERT_DATA, sizeof(advertData), advertData); 
            GAPRole_setParameter(GAPROLE_PARAM_UPDATE_ENABLE,sizeof(uint8_t), &enableUpdateRequest);
    	    GAPRole_setParameter(GAPROLE_MIN_CONN_INTERVAL,sizeof(uint16_t), &desiredMinInterval);
    	    GAPRole_setParameter(GAPROLE_MAX_CONN_INTERVAL,sizeof(uint16_t), &desiredMaxInterval);
    	    GAPRole_setParameter(GAPROLE_SLAVE_LATENCY, sizeof(uint16_t), &desiredSlaveLatency);
    	    GAPRole_setParameter(GAPROLE_TIMEOUT_MULTIPLIER,sizeof(uint16_t), &desiredConnTimeout);
    	    }

    上述代码使能了广播,设置了广播关闭时间,这里advertOffTime是0,就是一直进行广播。设置广播响应数据,设置广播数据,设置参数更新请求,设置广播连接间隔,设置广播从机延迟,设置连接超时。

    1. 初始化GAPRole任务并将应用程序回调函数传递给GAPRole。这也应该在simple_peripheral.c的SimpleBLEPeripheral_init中能够找到。其目的是当设备状态改变的时候进行响应,设备一旦改变都会通过这个回调函数改变event。然后SimpleBLEPeripheral_taskFxn里面一直在检测event事件的状态,发现状态改变则进行一些任务处理。
    	`VOID  GAPRole_StartDevice (&SimpleBLEPeripheral_gapRoleCBs );`
    1. 回调函数注册并初始化之后我们就能在应用程序接收GAPRole命令了,下面是使用GAPRole_terminateConnection()的程序上下文示意图。

    上图中可以看出应用程序直接调用GAPRole层API GAPRole_TerminateConnection(),GAPRole负责和协议栈通讯,然后接收到协议栈返回的状态之后又通过回调函数发送给应用程序,应用程序接收到状态之后再进行自己的逻辑处理。
    注意:返回值仅指示终止连接的尝试是否成功启动。连接终止实际是异步返回,并通过上面注册的回调传递给应用程序。

    1. GAPRole任务处理从协议栈传递给它的大多数GAP相关事件。GAPRole任务还将一些事件转发到应用程序(例如上面的GAPROLE_WAITING)。当链接终止时,GAPRole会自动重新启动广播。以下代码片段可以在peripheral.c中找到
    		  case GAP_LINK_TERMINATED_EVENT:
    		    {
    		      //.......
    		      //.......
    		      //.......
    		
    		      // If device was advertising when connection dropped
    		      if (gapRole_AdvNonConnEnabled)
    		      {
    		        // Continue advertising.
    		        gapRole_state = GAPROLE_ADVERTISING_NONCONN;
    		      }
    		      // Else go to WAITING state.
    		      else
    		      {
    		        if(pPkt->reason == LL_SUPERVISION_TIMEOUT_TERM)
    		        {
    		          gapRole_state = GAPROLE_WAITING_AFTER_TIMEOUT;
    		        }
    		        else
    		        {
    		          gapRole_state = GAPROLE_WAITING;
    		        }
    		
    		        // Start advertising, if enabled.
    		        gapRole_setEvent(START_ADVERTISING_EVT);
    		      }
    		    }
    		    break;

    central Role

    GAPRole中心任务在central.c和central.h中定义。有关完整的中央角色API,请参阅BLE Stack API参考,包括命令,可配置参数,事件和回调。有关实现中央GAPRole的示例,请参阅simple_central示例项目。使用此模块的步骤如下。

    1. 初始化GAPRole参数。这种初始化应该在应用程序初始化函数中出现(例如in SimpleBLECentral_init)。也可以在此初始化功能中设置GAP参数。
    		// Setup Central Profile 
    		{ 
    		   uint8_t  scanRes  =  DEFAULT_MAX_SCAN_RES ; 
    		
    		   GAPCentralRole_SetParameter (GAPCENTRALROLE_MAX_SCAN_RES ,
    		   sizeofuint8_t ), &scanRes ); 
    		}

    相比较peripheral Role,central Role的参数设置就很少了,只需要设置最大扫描响应数量。在程序中设置的8,也就是最多能接收8个外围设备的广播响应。

    1. 启动GAPRole任务。这涉及将应用程序回调函数的函数指针传递给Central GAPRole。这也应该在应用程序初始化函数中出现。和peripheral Role类似,协议栈返回一些事件,GAPRole在通过回调函数异步返回给应用程序。
    	`VOID  GAPCentralRole_StartDevice (&SimpleBLECentral_roleCB );`
    1. 从应用程序发送GAPRole命令。下图是使用GAPCentralRole_StartDiscovery()的应用程序上下文。

    上图中可以看出应用程序直接调用GAPRole层API CAPCrentralRole_StartDiscovery(),GAPRole负责和协议栈通讯,然后接收到协议栈返回的状态之后又通过回调函数发送给应用程序,应用程序接收到状态之后再进行自己的逻辑处理。
    注意:返回值仅指示是否启动了设备发现的尝试。发现的实际设备以GAP_DEVICE_INFO_EVENT异步方式返回,并通过上面注册的回调传递给应用程序。

    请注意,在扫描期间,如蓝牙核心规范版本5.0所定义,单个广播/扫描响应将返回为GAP_DEVICE_INFO_EVENT。默认情况下,重复的报告被过滤,以便每个唯一地址和数据对只有一个事件返回给应用程序。这可以通过TGAP_FILTER_ADV_REPORTS配置。扫描完成后,发现的报告将作为GAP_DEVICE_DISCOVERY_EVENT返回给应用程序。

    可以使用GAPCENTRALROLE_MAX_SCAN_RES参数设置在一次扫描期间可以发现的最大扫描响应量。如果在充斥着广播的环境中,这可能会对堆的使用产生重大影响,从而潜在地破坏堆栈。因此,对于在扫描期间发现最大扫描响应量的情况,必须对应用程序进行配置。

    在最坏的情况下,在扫描期间发现最大数量的广告/扫描响应(n),所有这些都具有最大数据大小,其中应用程序一直在处理它,使得它不处理任何堆栈的消息,堆可以增长:(8 + 87 * n个字节)。例如,如果 GAPCENTRALROLE_MAX_SCAN_RES设置为10,则必须至少有878字节可用于从堆分配。这包括一个完全填充的GAP_DEVICE_DISCOVERY_EVENT。如果此分配失败,则会尝试分配错误状态的GAP_DEVICE_DISCOVERY_EVENT。因此,为了使系统在上述情况下保持运行,堆必须具有至少分配(8 + 79 * n个字节)的空间。

    加入我们

    文章所有代码、工具、文档开源。加入我们QQ群 591679055获取更多支持,共同研究CC2640R2F&BLE5.0。

    CC2640R2F&BLE5.0-乐控畅联© Copyright 2017, 成都乐控畅联科技有限公司.

    展开全文
  • 1、首先,由于Javascript是线程这个本质才会有下来的一系列下文。 2、堆、、队列:  堆:堆是在程序运行时,而不是在程序编译时,动态申请某个大小的内存空间,即动态分配内存。  :简言之:‘使用堆的...

    1、首先,由于Javascript是单线程这个本质才会有接下来的一系列下文。

    2、堆、栈、队列:

          堆:堆是在程序运行时,而不是在程序编译时,动态申请某个大小的内存空间,即动态分配内存。

          栈:简言之:‘使用堆的一种方法’(先进后出)。

          队列:是一种先进先出的线性数据结构。

    区别:

    •     空间分配: 堆:一般由程序员释放,如果程序员不释放就会在结束时由OS回收;栈:一般由操作系统自动分配释放;
    •     缓存方式: 堆:存放在二级缓存中,生命周期一般是由虚拟机的垃圾回收算法决定的;栈:存放在一级缓存中,被调用时处于存储空间,调用完立即释放。
    •     操作数据:堆栈(先进后出),队列(先进先出);

    3、EventLoop(事件循环)

          由于js是单线程的所以js所有任务分为两种:同步任务和异步任务。

          同步任务:在主线程上排队执行的任务,只有前一个任务执行完毕,才能执行后一个任务;

          异步任务:异步任务指的是,不进入主线程、而进入"任务队列"(task queue)的任务,只有"任务队列"通知主线程,某个异步任务可以执行了,该任务才会进入主线程执行。

         事件循环:就是同步任务进入主线程,异步任务加入到任务队列中。等主线程的任务执行完就去执行任务队列中的任务,这个过程会不断重复。(如下图所示)

    4、宏任务和微任务

          任务队列又分为宏任务和微任务,宏任务队列可以有多个、微任务队列只有一个。

          EventLoop执行步骤:我们代码开始执行都是从script(全局任务)开始,所以,一旦我们的全局任务(属于宏任务)执行完,就马上执行完整个微任务队列。

          宏任务:script(全局任务), setTimeout, setInterval, setImmediate, I/O, UI rendering;

          微任务:process.nextTick, Promise, Object.observer, MutationObserver;

    5、最后给大家附一张我认为特别有价值的图帮助大家加深理解

       

    展开全文
  • 这部分API函数能够为任务分配和收回消息缓冲区,发送命令消息给以外一个任务并且接收应答。 3.2 osal_msg_allocate ( ) 概述: 当一个任务调用这个函数时,将为消息分配缓冲区,函数会将消息加入缓冲区,并调用...
    3.信息管理API
    3.1 概述
    这部分API提供了任务或处理单元与不同的处理环境之间的数据交换。这部分API函数能够为任务分配和收回消息缓冲区,发送命令消息给以外一个任务并且接收应答。
    3.2 osal_msg_allocate ( )
    概述:
    当一个任务调用这个函数时,将为消息分配缓冲区,函数会将消息加入缓冲区,并调用osal_msg_send()将消息发送到另一个任务。
    原型:
    byte *osal_msg_allocate( uint16 len )
    参数:
           len :消息的长度
    返回值:
           指向消息缓冲区的指针,当分配失败时返回NULL
     
    3.3 osal_msg_deallocate( )
    概述:
             用于收回缓冲区
    原型:
             byte osal_msg_deallocate( byte *msg_ptr )
    参数:
        Msg_ptr : 指向将要收回的缓冲区的指针
    返回值:RETURN VALUE DESCRIPTION
    ZSUCCESS                                           回收成功
    INVALID_MSG_POINTER              错误的指针
    MSG_BUFFER_NOT_AVAIL          缓冲区在队列中
     
    3.4 osal_msg_send( )
    概述:
    任务调用这个函数以实现发送指令或数据给另一个任务或处理单元。目标任务的标识必须是一个有效的系统任务,当调用osal_create_task ( )启动一个任务时,将会分配任务标识。
    osal_msg_send()也将在目标任务的事件列表中设置SYS_EVENT_MSG
    原型:
             byte osal_msg_send( byte destination_task, byte *msg_ptr )
    参数:
        destination_task :目标任务的标识
        msg_ptr : 指向消息缓冲区的指针
    返回值:
        ZSUCCESS                                           消息发送成功
    INVALID_MSG_POINTER              无效指针
    INVALID_TASK                                 目标任务无效
     
     
     
    3.5 osal_msg_receive( )
    概述:
             任务调用这个函数来接收消息。消息处理完毕后,发送消息的任务必须调用osal_msg_deallocate()收回缓冲区。
    原型:
             byte *osal_msg_receive( byte task_id )
    参数:
        task_id :消息发送者的任务标识
    返回值:
        指向消息所存放的缓冲区指针,如果没有收到消息将返回NULL。
     
    4.任务同步API
    4.1概述
    这个API使能一个任务等待一个事件的发生和返回控制而不是一直等待。在这个API中的函数可以用来为任务设置事件,立刻通知任务有事件被设置。
     
    4.2 osal_set_event( )
    概述:
             函数用来设置一个任务的事件标志
    原型:
             byte osal_set_event( byte task_id, UINT16 event_flag )
    参数:
        task_id :任务标识
    event_flag :2个字节,每个位特指一个事件。只有一个系统事件,其他事件在接收任务中定义。
    返回值:
        ZSUCCESS                                  成功设置
    INVALID_TASK                       无效任务
     
     
    5.定时器管理API
    5.1概述
    这个API允许内部任务(Z-Stack)以及应用层任务使用定时器。函数提供了启动和停止定时器的功能,定时器最小增量为1MS。
     
    5.2 osal_start_timer( )
    概述:
             启动定时器函数。当定时器到点时,the given event bit will be set。事件将在任务中设置,要指明具体任务,调用osal_start_timerEx()
    原型:
        byte osal_start_timer(UINT16 event_id, UINT16 timeout_value);
    参数:
        event_id : 用户定义的event bit. 当定时器到点时,事件将通知任务。
             timeout_value :定时值(ms)
    返回值:
        ZSUCCESS Timer                      成功开启
    NO_TIMER_AVAILABLE      无法开启
     
    5.3 osal_start_timerEx( )
    概述:
             功能与osal_start_timer()相近,这个函数允许调用者为另一个任务启动定时器
    原型:
        byte osal_start_timerEx( byte taskID, UINT16 event_id, UINT16
    timeout_value);
    参数:
        略
    返回值:
        ZSUCCESS Timer                      成功开启
    NO_TIMER_AVAILABLE      无法开启
     
     
    5.4 osal_stop_timer( )
    概述:
             停止正在运行的定时器,停止外部事件调用osal_stop_timerEx()
    原型:
        byte osal_stop_timer( UINT16 event_id );
    参数:
        event_id :将要结束的目标事件(该事件是启动定时器的事件)
    返回值:
        ZSUCCESS Timer                               成功停止
    INVALID_EVENT_ID                       无效事件
     
    5.5 osal_stop_timerEx( )
    概述:
             结束外部事件的定时器
    原型:
             byte osal_stop_timerEx( byte task_id, UINT16 event_id );
    参数:
        略
    返回值
             ZSUCCESS Timer                               成功停止
    INVALID_EVENT_ID                       无效事件
     
    5.6 osal_GetSystemClock( )
    概述:
             读取系统时间
    原型:
             uint32 osal_GetSystemClock( void );
    参数:
        无
    返回值:
        系统时间(ms)
     
    6.中断管理API
    6.1概述:
    这个API实现任务与外部中断的接口,函数允许任务关联每一个具体的中断程序,可以开关中断。在中断服务程序内,其他任务可以设置事件。
     
    6.2 osal_int_enable( )
    概述:
             函数用于使能中断。
    原型:
             byte osal_int_enable( byte interrupt_id )
    参数:
        interrupt_id :目标中断
    返回值:
        ZSUCCESS Interrupt                          成功使能
    INVALID_INTERRUPT_ID             无效中断
     
    6.3 osal_int_disable( )
    概述:
             关闭中断
    原型:
             byte osal_int_disable( byte interrupt_id )
    参数:
        略
    返回值:
        ZSUCCESS Interrupt                          成功关闭
    INVALID_INTERRUPT_ID             无效中断
     
     
    7.任务管理API
    7.1概述
    这个API用于在OSAL中增加和管理任务。每一个任务由任务初始化函数和时间处理函数组成。
    OSAL calls osalInitTasks() [application supplied] to initialize the tasks and OSAL uses a task table (const pTaskEventHandlerFn tasksArr[]) to call the event processor for each task (also application supplied).
     
     
     
     
     
    建立task table 的例子:
    const pTaskEventHandlerFn tasksArr[] =
    {
    macEventLoop,            //我的理解是已经建立好的事件队列
    nwk_event_loop,
    Hal_ProcessEvent,
    MT_ProcessEvent,
    APS_event_loop,
    ZDApp_event_loop,
    };
    //任务数
    const uint8 tasksCnt = sizeof( tasksArr ) / sizeof( tasksArr[0] );
     
    建立任务的例子:
    void osalInitTasks( void )
    {
    uint8 taskID = 0;
    tasksEvents = (uint16 *)osal_mem_alloc( sizeof( uint16 ) * tasksCnt);
    osal_memset( tasksEvents, 0, (sizeof( uint16 ) * tasksCnt));
    macTaskInit( taskID++ );
    nwk_init( taskID++ );
    Hal_Init( taskID++ );
    MT_TaskInit( taskID++ );
    APS_Init( taskID++ );
    ZDApp_Init( taskID++ );
    }
     
    7.2 osal_init_system()
    概述:
             该函数初始化OSAL系统。必须用在任何一个使用OSAL的地方。
    原型:
             byte osal_init_system( void )
    参数:
        无
    返回值:
        ZSUCCESS                        成功
     
    7.3 osal_start_system()
    概述:
    这个函数是系统任务的主循环函数,在循环里面将遍历所有的任务事件,为触发事件的任务调用任务事件处理函数。当事件处理完之后,将返回主循环。如果没有事件,函数将把处理器转到睡眠模式。
    原型:
           void osal_start_system( void )
    参数:
           无
    返回值:
           无
     
    7.4 osal_self()
    概述:不在支持,不推荐
     
    7.5 osalTaskAdd ()
    概述:不在支持,不推荐  可以参考7.1 任务初始化。
     
    8.内存管理API
    8.1概述
    简单的内存分配系统,支持动态分配内存。
     
    8.2 osal_mem_alloc()
    概述:
             如果成功的话,该函数将分配内存并返回指针。
    原型:
             void *osal_mem_alloc( uint16 size );
    参数:
        size – 想分配的内存空间的字节数
    返回值:
        返回一个void指针指向新分配的缓冲区。如果没有足够的空间将返回NULL。
     
    8.3 osal_mem_free()
    概述:
             释放内存空间
    原型:
    void osal_mem_free( void *ptr );
    参数:
        Ptr :指向将要释放的空间,改空间必须是分配过的。
    返回值:
        无
     
     
    9.电源管理API
    9.1概述
    这个部分阐述了OSAL的电源管理系统。系统提为应用或者任务提供了通知OSAL的方式,包括何时可以安全关闭,接收设备和其他设备,以及何时将处理器处于睡眠模式。
     
    有两类控制电源管理的函数。第一个,osal_pwrmgr_device(),设置设备级别模式(节点或不节点)。其次是osal_pwrmgr_task_state( PWRMGR_HOLD ),每个任务可以通过调用它函数hold off the power manager,如果一个任务“Holds” the power manager 后就需要调用osal_pwrmgr_task_state( PWRMGR_CONSERVE )允许电源管理来保存电源管理模式。
     
    默认当任务建立时,每个任务的电源管理状态被设置成PWRMGR_CONSERVE。如果任务不想实行断电保护(没有变化),不需要调用 osal_pwrmgr_task_state().电源管理将在进入电源保护状态之前察看设备模式和所有任务共有的电源状态。
     
    9.2 osal_pwrmgr_device()
    概述:
             函数在上电或电源需求变更时调用(例如电源支持协调器)。这一函数设置了大体的设备电源管理的开/关状态。该函数应当从中央控制实体(如ZDO)被调用。
    原型:
             void osal_pwrmgr_state( byte pwrmgr_device );
    参数:
        pwrmgr_device :更改或设置节电模式
             PWRMGR_ALWAYS_ON                                   无节电
    PWRMGR_BATTERY                                         开节电
    返回值:
             无
     
    9.3 osal_pwrmgr_task_state()
    概述:
             任务调用这个函数决定是否让OSAL保存电源状态。默认当任务创建时,它自己的电源状态设置成保存,如果任务总是想保存电源状态,就不需要调用这个函数。
    原型:
             byte osal_pwrmgr_task_state( byte task_id, byte state );
    参数:
        State – 变更的电源状态
        PWRMGR_CONSERVE                              打开节电,初始化默认
    PWRMGR_HOLD                                       关闭节电
    返回值:
             ZSUCCESS                                                    成功
    INVALID_TASK                                          无效任务ID
     
     
    10.非易失性(NV)内存管理
    10.1概述
    这部分阐述了OSAL的非易失性内存管理系统。系统为 应用 提供了一种永久储存信息的方式。协议栈也使用它来保存一些协议必要的项目。非易失性函数用来读写用户定义的项目包括任意的数据类型例如结构体和数组。用户可以读写这个项目,或者项目里的单一元素通过设置适当的长度。
    每部分NV有一个ID,有些被占用了,以下是分块表。
     
     
     
    0x0000 Reserved
    0x0001 – 0x0020 OSAL
    0x0021 – 0x0040 NWK
    0x0041 – 0x0060 APS
    0x0061 – 0x0080 Security
    0x0081 – 0x00A0 ZDO
    0x00A1 – 0x0200 Reserved
    0x0201 – 0x0FFF Application
    0x1000 -0xFFFF Reserved
    在使用API时有一些重要的注意点:
    1.       。。。例如,最好的写NV的时间是关闭接收之后
    2.       尽量减少NV的写频率,耗费时间和电源,对于flash有擦写次数的限制。
    3.       如果一个或多个NV项目的结构发生变化,特别是当从一个升级版本的z-stack到另一个,有必要擦除和重新初始化NV内存。否则,在NV项目上的读和写操作的改变将失败或产生错误的结果。
     
    10.2 osal_nv_item_init()
    概述:
             初始化一个NV项目。这个函数检查一个NV项目的存在与否。如果不存在,它将被建立和初始化随着数据一起传给函数,这个函数必须在调用osal_nv_read() or osal_nv_write()之前被调用
    原型:
             byte osal_nv_item_init( uint16 id, uint16 len, void *buf );
    参数:
        Id :用户定义的项目ID
        Len :项目的大小
        Buf :指向项目初始化的数据。如果没有初始化的数据,设置为NULL
    返回值:
        ZSUCCESS                                           成功
    NV_ITEM_UNINIT                            成功但是项目之前不存在
    NV_OPER_FAILED                           操作失败
     
    10.3 osal_nv_read()
    概述:
             从NV中读数据,可以读取整个项目,或是项目中有索引指定的元素,数据复制到*buf
    原型:
             byte osal_nv_read( uint16 id, uint16 offset, uint16 len, void *buf );
    参数:
             Id :用户定义的项目ID
             Offset :Memory offset into item in bytes.
             Len :项目长度
             Buf :数据保存缓冲区指针
    返回值:
             ZSUCCESS Success
    NV_ITEM_UNINIT Item is not initialized
    NV_OPER_FAILED Operation failed
     
    10.4 osal_nv_write()
    概述:
             写数据到NV
    原型:
             byte osal_nv_write( uint16 id, uint16 offset, uint16 len, void *buf );
    参数:
        Id : 用户定义的ID
        Offset :Memory offset into item in bytes.
             Len :项目长度
             Buf :写数据
    返回值:
             ZSUCCESS                                                    成功
    NV_ITEM_UNINIT                                     项目没有初始化
    NV_OPER_FAILED                                     操作失败
     
    10.5 osal_offsetof()
    概述:
             这个宏计算出一个单元内结构的内存偏移量。他对NV API函数涌来计算偏移量参数很有用。
    原型:
             osal_offsetof(type, member)
    参数:
        Type :结构类型
        Member :结构成员
    展开全文
  • 所有来自 TaskManager 的工作单元(子任务)都通过它来互相连接。你的流式传输数据流都要经过网络,所以它对 Flink 作业的性能表现(包括吞吐量和延迟指标)至关重要。与通过 Akka 使用 RPC 的 TaskManager 和 ...
  • 系统使用采用CAS+shiro点登录系统实现用户认证 使用ECharts根据后台查询数据生成图表 使用POI实现了商城盈利状况的Excel表格导出。 商品的详情页使用Thymeleaf完成页面静态化,减少页面数据展示延迟 项目中使用...
  • 5.3、路由详述: 5.3.1、路由基本原理: ...路由是L3网际层最重要的任务,对收发的报文,合法的不合法的,广播组播播的,都要做出相应的处理。 在接收端,linux内核中对IP报文的处理入口是ip_rcv函数,在检测I
  • 它连接所有TaskManagers的各个工作单元(子任务)。 这是流式传输数据流经的地方,因此,它对于Flink作业的性能(吞吐量和观察到的延迟)至关重要。 与通过Akka使用RPC的TaskManagers和JobManagers之间的协调通道相比,...
  • 相对《简单多线程拷贝文件示例》扩展了任务队列。 主要核心在于将单个大文件分成多份(比如100),形成一个任务,并将任务用链表链接起来,形成一个队列(FIFO)或者(无非是顺序不同)。 相对第一版来说,...
  • 摘要:针对某些MCU结构的嵌入式Internet服务器性能价格比低且灵活性差的问题,提出了一种双MCU结构的嵌入式Internet入服务器(DMCUEIAS)。它使嵌入式Internet的用户交互和设备控制分离,用户通过Internet不仅...
  • 司来说,开展MCU的性能测试成了不可能的任务。因此,探索一种 合理有效的测试方法对于解决MCU性能测试存在的问题是非常有意 义的。 该方法具体需求有两个,一是要实现一个符合H.323协议的软件 终端,并且其配置参数...
  • 这是一个全新的交替射频技术,它允许蓝牙协议针对任一任务动态地选择正确的射频。  从双向电话交流到流式立体声音频再到照片交换和手机壁纸,消费者可以更加方便地使用无线数据通讯,这些要部分归功于蓝牙...
  • 简单原则少ROM,少RAM,任务完成就让出CPU,调度器描述: 1、按... 5、任务用独立大小由用户自定义; 6、调度器无需初始化,代码为单个C文件,结构简单,代码尺寸小; 7、调度器加3个任务代码尺寸:Code=142...
  • 上海爱数面试

    千次阅读 2020-07-03 00:51:21
    关联容器:map重映射表,set重集合,multimap多重映射表,multiset多重集合 容器适配器:queue队列,stack 2.线程池 T1:创建线程的时间 T2:执行任务需要的时间 T3:销毁线程的时间 T1 + T3 >> T2,...
  • 问题描述:for循环中,异步调用后端接口无效(同时执行所有任务,导致页面卡死) 提示:循环不能是异步的,for循环是同步任务,内部的异步任务会在for循环执行完成后执行 解决方法:循环中使用递归。使用递归函数...
  • 因为js是线程语言,所以只有一个主线程来执行代码。 那么遇到异步任务的时候,js是如何实现非阻塞,或事件循环的(event loop)? 浏览器环境下js引擎的事件循环机制 js顺序执行代码,遇到同步代码,将代码推入...
  • 多线程有几种实现方案,分别是哪几种???三种。继承Thread类实现Runnable接口:Java不支持类的多重继承,但允许你调用多个接口。所以如果你要继承其他类,当然是调用...别把它和内存搞混,每个线程都拥有单独的...
  • 别把它和内存搞混,每个线程都拥有单独的内存用来存储本地数据。 2、实现多线程的方式有哪些? 继承Thread类:Java继承,不推荐; 实现Runnable接口:Thread类也是继承Runnable接口,推荐; 实现Callab
  • libco协程库,附VS工程

    2018-07-02 16:28:13
    可选的共享模式,单机轻松入千万连接(New); 完善简洁的协程编程接口 类pthread接口设计,通过co_create、co_resume等简单清晰接口即可完成协程的创建与恢复; __thread的协程私有变量、协程间通信的协程信号量co...
  • LWIP是一款开源的嵌入式网络协议,支持的功能很多,而且能在多任务环境下和单任务裸机环境下跑,今天说说他的移植过程,芯片为STM32,网卡为ENC28J60,无操作系统 首先下载LWIP的源代码,我下载的是1.4.1的源码,下载后...
  • pthread

    2016-12-07 22:54:00
    Linux系统下的多线程遵循POSIX线程接口,称为...与vxworks上任务的概念类似,都是调度的最小单元,都有共享的堆、、代码区、全局变量等。 2. 创建线程 int pthread_create(pthread_t * thread, pthread...
  • pthread 编程基础

    2016-05-21 18:10:00
    Linux系统下的多线程遵循POSIX线程接口,称为pthread。...与vxworks上任务的概念类似,都是调度的最小单元,都有共享的堆、、代码区、全局变量等。 2.创建线程 intpthread_create(pthread_t*thread, pthread...
  • 牛客网-错题

    2020-10-21 22:53:09
    多线程:多线程是指程序中包含多个执行流,即在一个程序中可以同时运行多个不同的线程来执行不同的任务,也就是说允许单个程序创建多个并行执行的线程来完成各自的任务。 Linux操作命令 将a下所有目录和文件复制到...
  • 在看这本书之前,我们要先明白一个问题。线程和进程之间的关系?...别把它和内存搞混,每个线程都拥有单独的内存用来存储本地数据。查看jdk源码 发现这里Thread实现了Runnable接口,他们之间具有多态关系,
  • 第12章 基于FreeRTOS的LwIP协议移植 12.1 概述 12.2 FreeRTOS下以太网驱动程序的移植 12.3 LwIP程序移植 12.3.1 以太网接口文件ethernetif.c的移植 12.3.2 操作系统模拟层文件sys_arch.c的移植 第13章 工业通信...
  • pthread编程基础

    2015-12-29 10:24:19
    Linux系统下的多线程遵循POSIX线程接口,称为pthread。编写Linux下的多线程程序,需要使用头文件pthread.h,连接...与vxworks上任务的概念类似,都是调度的最小单元,都有共享的堆、、代码区、全局变量等。
  • Linux 多线程编程基础

    2017-03-06 11:03:13
    Linux系统下的多线程遵循POSIX线程接口,称为...与vxworks上任务的概念类似,都是调度的最小单元,都有共享的堆、、代码区、全局变量等。   2. 创建线程 int pthread_create(pthread_t * thread, pthread_
  • pthread相关资料整理(1)

    2015-07-20 15:08:31
    1.  pthread线程概念 Linux系统下的多线程遵循POSIX线程接口,...与vxworks上任务的概念类似,都是调度的最小单元,都有共享的堆、、代码区、全局变量等。   2.  创建线程 int pthread_create(pthread_t

空空如也

空空如也

1 2 3 4 5 ... 8
收藏数 143
精华内容 57
关键字:

任务栈接单