csr8670--sink工程的大致工作流程分析(以speaker为例)一
今天是14号 15号更新,说明,刚开始看程序有点复杂 没办法,必须看代码
建议首先先把ADK3.5.1中的例程tutorials看完,对学习很有帮助
1.csr中的消息机制
1.1 adk3.5.1中的led的例子
- csr8670中是以消息机制进行任务调度的,根据消息调用相应的回调函数进行处理,如下面这个例子所示:在主函数中,首先设置PIO为输出并且设置为低电平,然后调用了messagesend函数和messageloop函数
- TaskData :这个结构体是最重要的,可以看出定义了一个函数指针,其参数有三个
</pre><pre class="prettyprint" name="code" style="white-space: nowrap; word-wrap: break-word; box-sizing: border-box; position: relative; overflow-y: hidden; overflow-x: auto; margin-top: 0px; margin-bottom: 1.1em; font-family: 'Source Code Pro', monospace; padding: 5px 5px 5px 60px; font-size: 14px; line-height: 1.45; word-break: break-all; color: rgb(51, 51, 51); border: 1px solid rgba(128, 128, 128, 0.0745098); border-radius: 0px; background-color: rgba(128, 128, 128, 0.0470588);"><code class="hljs d has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">typedef</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">struct</span> TaskData { <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> (*handler)(Task, MessageId, Message); } TaskData;</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li></li></ul>
- messagesend:这个函数能够向某个任务发送消息
- messageloop:开始任务调度,不会返回
static void led_controller1( Task t, MessageId id, Message payload ) {PioSet32( LED1, (PioGet32() ^ LED1) );MessageSendLater( t, 0, 0, DELAY1 ); } static void led_controller2( Task t, MessageId id, Message payload ) {PioSet32( LED2, (PioGet32() ^ LED2) );MessageSendLater( t, 0, 0, DELAY2 ); } static TaskData led_controller1_task = { led_controller1 };//实例化了一个任务,并初始化了其参数,即回调函数 static TaskData led_controller2_task = { led_controller2 };int main(void) {PioSetDir32(0xFF, 0xFF); /* Set all PIO to be output */PioSet32(0xFF, 0); /* Set all PIO off (0) */MessageSend( &led_controller1_task, 0 , 0 );//第一个参数为发送给哪个任务MessageSend( &led_controller2_task, 0 , 0 );MessageLoop();//开始任务调度return 0; }
1.2 hsTaskData结构体
csr中是以消息机制来进行任务的处理的,其中最大的任务为theSink,其结构体如下
/* Sink application data */
typedef struct
{/* Main task */TaskData task;//最重要的任务,指向最高层的回到函数,即main函数里边的app_handler/* Config variables */ButtonsTaskData *theButtonsTask;//按键的任务,这些是最高层任务之下的任务,之所以定义在最高层里面,应该是想让最高层具有知道所有事件运行情况的能力LedTaskData *theLEDTask;//led显示的任务,同上runtime_block1_t *rundata;//运行时的数据,目前还不了解config_block1_t *conf1;//解下来的7个block以后会分析config_block2_t *conf2;config_block3_t *conf3;config_block4_t *conf4;config_block5_t *conf5;config_block6_t *conf6;config_block7_t *conf7;ConfigTone_t gConfigTones;volume_levels_t *volume_levels; /* current operating volume levels for a2dp/usb/wired modes */power_table *user_power_table; /* pointer to user power table if available in ps */hfp_common_plugin_params_t hfp_plugin_params;HFP_features_type HFP_supp_features;feature_config_type features;bdaddr local_bd_addr; /* Local BD Address of the sink device available in ps *//* Runtime variables *//*下面这些运行时的变量都是在动态的生成或者释放的,每一个和button一样都是一个任务*/Task codec_task ;Sink routed_audio;uint16 NoOfReconnectionAttempts;profile_data_t profile_data[MAX_MULTIPOINT_CONNECTIONS];a2dp_data *a2dp_link_data;
#ifdef ENABLE_AVRCPavrcp_data *avrcp_link_data;
#endif tp_bdaddr *confirmation_addr;inquiry_data_t inquiry;#ifdef ENABLE_PBAPpbapc_data_t pbapc_data;
#endif
#ifdef ENABLE_USBusb_info *usb;
#endif
#ifdef ENABLE_PEERbdaddr remote_peer_ag_bd_addr;
#endifuser_eq_bank_t *PEQ;/*! Runtime flags*//*word 1*/unsigned PowerOffIsEnabled:1; /*自行百度结构体的用法,这样写应该是为了节省空间*/unsigned SinkInitialising:1;unsigned VolumeOrientationIsInverted:1; /*whether or not the vol buttons are inverted*/unsigned NetworkIsPresent:1;unsigned inquiry_scan_enabled:1;unsigned page_scan_enabled:1 ;unsigned csr_speech_recognition_is_active:1 ;unsigned csr_speech_recognition_tuning_active:1 ; unsigned panic_reconnect:1; unsigned last_outgoing_ag:2 ; /* which AG made the last outgoing call */unsigned audio_prompts_enabled:1;unsigned confirmation:1;unsigned debug_keys_enabled:1;unsigned RepeatCallerIDFlag:1;unsigned mute_all_outputs:1;/*word 2*/unsigned audio_prompt_language:4; unsigned num_audio_prompt_languages:4;unsigned MultipointEnable:1;unsigned powerup_no_connection:1; /* bit to indicate device has powered and no connections yet */unsigned paging_in_progress:1; /* bit to indicate that device is curretly paging whilst in connectable state */unsigned audioAmpPowerPin:1; /* bit to indicate logic state of audio amplifier power pin */unsigned battery_state:3;unsigned gVolButtonsInverted:1; /*! whether or not the volume button operation is currently inverted*/ /*word 3*/unsigned FailAudioNegotiation:1;unsigned RenegotiateSco:1; unsigned lbipmEnable:1; /* enable Low Battery Intelligent Power Management feature */unsigned buttons_locked:1; /* Flag to indicate if button locking is enabled */unsigned HeldCallIndex:4; /* which call to route in the case of multiple held calls */ unsigned inquiry_tx:8;/*word 4*/unsigned MissedCallIndicated:8;unsigned gEventQueuedOnConnection:8 ;/*word 5*/unsigned mute_states:3;unsigned pbap_access:1; /* Link Policy expedites PBAP access */unsigned dfu_access:1; /* Link Policy expedites DFU data transfer */unsigned hfp_profiles:3;unsigned ssr_enabled:1;unsigned VoiceRecognitionIsActive:2;unsigned PartyModeEnabled:1;
#ifdef ENABLE_PEER unsigned remote_peer_audio_conn_status:3; /* Flag to indicate which Audio sources are connected to the remote peer */unsigned tws_qual_enable_peer_open:1; /* Flag to indicate App to trigger opening of Peer media channel */
#elseunsigned unused4:4;
#endif/* word 6 */unsigned gated_audio:8; /* Bitmask indicating which audio sources are prevented from being routed */unsigned linkLossReminderTime:8;/* word 7 */peer_states_t peer;
#if defined(ENABLE_PEER) && defined( ENABLE_PEER_BATTERY_LEVEL)uint16 peer_battery_level;
#endif
} hsTaskData;
2.sink工程的流程分析
2.1 sink的初始化和工具
- 如下图所示,描述了之前提到过的csr的开发流程,即pc工具和开发环境配合使用,所以在程序中需要读取这些配置的参数等数据
2.2 speaker流程分析
- 第一步:init函数,对sink工程进行单步调试发现,工程首先进入的入口函数是init函数,而不是main函数,下面都是大致的分析,对整个流程有个初步的认识即可
/* Time critical initialisation */
#ifdef HOSTED_TEST_ENVIRONMENT
void _sink_init(void)
#else
void _init(void)
#endif
{/* Set the application task */theSink.task.handler = app_handler; /*这个就是上面提及的最重要的任务的回调函数,如果其他任务想让这个任务的事件触发,则向它发送消息,第一个参数为这个任务的TASK*//* set flag to indicate that configuration is being read, use to prevent use of variablesprior to completion of initialisation */theSink.SinkInitialising = TRUE;/*将sink的正在初始化标志置位*//* Read in any PIOs required */configManagerPioMap();/*根据配置文件获取PIO的设置和映射关系*//* Time critical USB setup */usbTimeCriticalInit();/*目前没有用到*/
}
- 第二步:mian函数,看函数注释说sink引用程序从这里开始,突然发现上面的init函数前面包含了一个下划线,这个带下划线的函数我们应该是单步不到的,应该是系统自动上电执行的,超出我们单步调试的范围,应该是系统内部的函数,目前不是很了解。
<pre name="code" class="cpp">/* The Sink Application starts here...*/ #ifdef HOSTED_TEST_ENVIRONMENT int sink_main(void) #else int main(void) #endif {DEBUG (("Main [%s]\n",__TIME__));/* Initialise the Upgrade lib */sinkUpgradeInit(&theSink.task);/*这个和更新有关,暂不考虑*//* check and update as necessary the software version pskey, this is used for ensuring maximumcompatibility with the sinkg configuration tool */configManagerSetVersionNo();/*版本相关*//* Initialise memory required early */configManagerInitMemory();/*这个函数里面开辟了runtime_block1_t 这个结构体,初始化为0*//* initialise memory for the led manager */LedManagerMemoryInit();/*开辟了LedTaskData结构体的空间,初始化为0*//* Initialise device state */AuthResetConfirmationFlags();/*不懂?*//*the internal regs must be latched on (smps and LDO)*/PioSetPowerPin ( TRUE ) ;/*不懂?*/switch (BootGetMode() )/*配置工具可以设置系统的启动模式*/{ #ifdef CVC_PRODTESTcase BOOTMODE_CVC_PRODTEST:/*run the cvc prod test code and dont start the applicaiton */cvcProductionTestEnter() ;break ; #endifcase BOOTMODE_DFU:/*do nothing special for the DFU boot mode,This mode expects to have the appropriate host interfface enabledDon't start the application *//* Initializing only the system components required for flashing the led pattern in the DFU mode*/configManagerInit(FALSE);LEDManagerIndicateEvent(EventUsrEnterDFUMode);break ;case BOOTMODE_DEFAULT:case BOOTMODE_CUSTOM:case BOOTMODE_USB_LOW_POWER:case BOOTMODE_ALT_FSTAB:default:{/* Initialise the Connection lib */sinkConnectionInit();/*初始化连接库,从这里开始,可以把整个连接库从初始化调用到完成分析一下*/#ifdef TEST_HARNESStest_init();#endif}break ;}/* Make sure the mute states are correctly set up */VolumeSetInitialMuteState();/*静音模式初始化*//* Start the message scheduler loop */MessageLoop();/*开始任务调度*//* Never get here...*/return 0; }
- 第三步:连接库的具体初始化过程
- 2.3.1.sinkConnectionInit函数,注意这个函数使用static修饰
<pre name="code" class="cpp">static void sinkConnectionInit(void) {/* read the lengths key into a temporary malloc to get pdl length *//*给pdl分配空间*/lengths_config_type * lengths_key = PanicUnlessMalloc(sizeof(lengths_config_type));/* The number of paired devices can be restricted using pskey user 40, a number between 1 and 8 is allowed *//*读取pdl*/ConfigRetrieve(CONFIG_LENGTHS, lengths_key , sizeof(lengths_config_type) );DEBUG (("PDLSize[%d]\n" , lengths_key->pdl_size ));/* Initialise the Connection Library with the options *//*具体的初始化函数,注意(0001)第一个参数为最上层的任务,第三个参数为pdl的个数*/ConnectionInitEx2(&theSink.task , NULL, lengths_key->pdl_size );/* free the malloc'd memory */free(lengths_key);/*这里需要关注一下,这种malloc,free的模式在工程中很常见,都是先分配空间,使用之后再释放,在哪里看的目的好像是说减少栈内存的使用*/ }
- 2.3.2.看源代码可知ConnectionInitEx2–>ConnectionInitEx3,所以接下来是ConnectionInitEx3这个函数,参数前三个对应
<pre name="code" class="cpp">void ConnectionInitEx3(Task theAppTask, const msg_filter *msgFilter , uint16 TdlNumberOfDevices , uint16 options) {/*注意这里面又有了一个theCm,自己可以分析一下,怎样和最重要的任务产生关系*/theCm.msgFilter = (msgFilter == NULL) ? &defaultMsgFilter : msgFilter;/* Initialise the Connection Library Task, all upstream messages sent byBluestack will be handled by this task *//*这也是个任务,初始化其回调函数*/theCm.task.handler = connectionBluestackHandler;/* If a task is already registered to receive BlueStack prims then we panic! */if (MessageBlueStackTask(connectionGetCmTask())){CL_DEBUG(("ERROR - task already registered\n"));}/* Init the resource locks */initLocks();/* Init the sm_init_msg types.*/theCm.smState.sm_init_msg = sm_init_set_none;/* Store the application task *//*在这一步,将最终要的任务,赋值给这个任务的结构体,这样这个任务就可以向最重要任务发消息*/theCm.theAppTask = theAppTask;/*set the number of devices to the requested value if in the range 1 to 8*/theCm.smState.TdlNumberOfDevices = DEFAULT_NO_DEVICES_TO_MANAGE ;if ((TdlNumberOfDevices >= MIN_NO_DEVICES_TO_MANAGE) && (TdlNumberOfDevices <= MAX_NO_DEVICES_TO_MANAGE)){theCm.smState.TdlNumberOfDevices = TdlNumberOfDevices ;}/* Process options *//* Enable SC */if (options & CONNLIB_OPTIONS_SC_ENABLE)theCm.flags |= CONNECTION_FLAG_SC_ENABLE;/* Enable SC only mode. It implies SC must be turned on as well */if (options & CONNLIB_OPTIONS_SCOM_ENABLE)theCm.flags |= (CONNECTION_FLAG_SCOM_ENABLE | CONNECTION_FLAG_SC_ENABLE);/* Start the initialisation process */MessageSend(connectionGetCmTask(), CL_INTERNAL_INIT_REQ, NO_PAYLOAD);/*这里发送消息给&theCm.task,也即上面赋值过的回调函数connectionBluestackHandler,第二个代表连接内部初始化请求此数值为1,第三个参数延时时间*/ }
- 2.3.3 现在走进connectionBluestackHandler这个函数看怎样处理这个消息
<pre name="code" class="cpp">/**************************************************************************** NAMEconnectionBluestackHandlerDESCRIPTIONThis is the main task handler for all messages sent to the ConnectionLibrary task.RETURNSvoid */ void connectionBluestackHandler(Task task, MessageId id, Message message) {/* Get access to the Connection Library instance state *//*获取这个传递过来的任务*/connectionState *theCm = (connectionState *)task;connectionStates state = theCm->state;PRINT(("connectionBluestackHandler - Id = 0x%x\n",id));/* Handle Bluestack primitives seperately */switch (id){case MESSAGE_BLUESTACK_DM_PRIM:/*8004*/connectionBluestackHandlerDm(theCm, (DM_UPRIM_T *)message);break;#ifndef CL_EXCLUDE_RFCOMMcase MESSAGE_BLUESTACK_RFCOMM_PRIM:/*8006*/connectionBluestackHandlerRfcomm(theCm, (RFCOMM_UPRIM_T *)message);break; #endif#if !defined(CL_EXCLUDE_L2CAP) || !defined(DISABLE_BLE)case MESSAGE_BLUESTACK_L2CAP_PRIM:/*8005*/connectionBluestackHandlerL2cap(theCm, (L2CA_UPRIM_T *)message);break; #endif#ifndef CL_EXCLUDE_SDPcase MESSAGE_BLUESTACK_SDP_PRIM:/*8007*/connectionBluestackHandlerSdp(theCm, (SDS_UPRIM_T *)message);break; #endifcase MESSAGE_BLUESTACK_UDP_PRIM:/*8015*/case MESSAGE_BLUESTACK_TCP_PRIM:/*8014*/handleUnexpected(connectionUnhandledMessage, theCm->state, id);break;#ifndef CL_EXCLUDE_SDP/* CL_SDP_CLOSE_SEARCH_CFM Primitive arrived as a result of an internalcall to close SDP search, can't avoid so ignoreHandled as a special case to allow the compiler to generate bettercode for the previous switch statements. */case CL_SDP_CLOSE_SEARCH_CFM:break; #endif/* Everything else must be internal connection library primitives */default:/*可知1会进入这里*/{switch (state)/*然会根据任务的状态判断,我们可以回过头去看看这个任务的状态在什么时间被赋值了,发现没有处理过所以为0,会进入connectionUninitialised这个值也为0*/{case connectionReady:connectionBluestackHandlerReady(theCm, id, message);break;case connectionUninitialised:connectionBluestackHandlerUninitialised(theCm, id, message);/*注意传递过去的参数*/break;case connectionInitialising:connectionBluestackHandlerInitialising(theCm, id, message);break;case connectionTestMode:connectionBluestackHandlerTestMode(theCm, id, message);break;}}} }
- 2.3.4 connectionBluestackHandlerUninitialised函数
<pre name="code" class="cpp">static void connectionBluestackHandlerUninitialised(connectionState *theCm, MessageId id, Message message) {/* Depending upon the message id...*//*由前面可以知道此时相等*/if (id == CL_INTERNAL_INIT_REQ){PRINT(("CL_INTERNAL_INIT_REQ\n"));connectionHandleInternalInit(connectionInit);/*执行这个函数,注意参数为0*/}else{/* Prims we are not handling - Not panicing the app in DEBUG Mode. Just Print this INFO and ignore it.*/CL_DEBUG_INFO(("Ignored Unexpected Message - Code 0x%x State 0x%x MsgId 0x%x\n", connectionUnexpectedCmPrim, theCm->state, id))} }
- 2.3.5 connectionHandleInternalInit函数
<pre name="code" class="cpp">void connectionHandleInternalInit(connectionInitState state) {/* If we're ready to run, change state */ if(state == connectionInitComplete){theCm.state = connectionReady;}else if (theCm.state != connectionInitialising)/*这个成立,此时状态为未初始化*/{theCm.state = connectionInitialising;/*改变状态*//* Start a Timer to notify the Client if the initialisation fails *//*等待一段时间发送CL_INTERNAL_INIT_TIMEOUT_IND这个消息此数值为0,还是向connectionBluestackHandler发送的,注意第三个参数,这个是个时间,很重要下面会分析到*/MessageSendLater(&theCm.task, CL_INTERNAL_INIT_TIMEOUT_IND, NO_PAYLOAD, (uint32) INIT_TIMEOUT);}/* Check to see if all objects have been initialised */if(state == connectionInitComplete){/* Initialise auth requirements to unknown */theCm.smState.authentication_requirements = AUTH_REQ_UNKNOWN;/* Some DM stuff can be initialised only after the DM register has happened so do it here */connectionDmInfoInit();/* Let the application we're ready to go */connectionSendInitCfm(theCm.theAppTask, success, theCm.infoState.version);}else{/* Depending upon the previous object initialised, initialise the next one */switch(state){case connectionInit:/*此时会调用这个函数*/connectionDmInit(); /*这个是个初始化,做什么的不了解*/break;case connectionInitDm: #ifndef CL_EXCLUDE_RFCOMMconnectionRfcInit(); #elseconnectionL2capInit(); #endifbreak;#ifndef CL_EXCLUDE_RFCOMMcase connectionInitRfc:connectionL2capInit();break; #endifcase connectionInitL2cap:connectionUdpInit();break;case connectionInitUdp:connectionTcpInit();break;case connectionInitTcp:connectionSdpInit(&theCm.sdpState);break;case connectionInitSdp: connectionVersionInit();break;case connectionInitVer:connectionSmInit(theCm.infoState.version,&theCm.smState,theCm.flags);break;case connectionInitSm:theCm.smState.noDevices = connectionAuthInit();break;case connectionInitComplete:/* We're ready! */ default:break;}} }
- 2.3.6 接下来第二次进入connectionBluestackHandler这个函数,只不过此时的状态已经更改为theCm.state = connectionInitialising;所以进入的函数为
case connectionInitialising:
connectionBluestackHandlerInitialising(theCm, id, message);
break; - 2.3.7 connectionBluestackHandlerInitialising函数分析,此时的id为CL_INTERNAL_INIT_TIMEOUT_IND
<pre name="code" class="cpp">static void connectionBluestackHandlerInitialising(connectionState *theCm, MessageId id, Message message) {/* Depending upon the message id...*/switch (id){case CL_INTERNAL_INIT_CFM:PRINT(("CL_INTERNAL_INIT_CFM\n"));connectionHandleInternalInit(((CL_INTERNAL_INIT_CFM_T*)message)->state);break;case CL_INTERNAL_INIT_TIMEOUT_IND:/*所以会执行下面的语句*/PRINT(("CL_INTERNAL_INIT_TIMEOUT_IND\n"));(void)MessageCancelFirst(&theCm->task, CL_INTERNAL_INIT_CFM);SET_CM_STATE(connectionUninitialised);connectionSendInitCfm(theCm->theAppTask, fail, bluetooth_unknown);/*这个函数是个重点,关注它的第一个参数为最重要的那个任务*/break;case CL_INTERNAL_SM_INIT_REQ:PRINT(("CL_INTERNAL_SM_INIT_REQ\n"));handleSecurityInitReq(&theCm->infoState, (CL_INTERNAL_SM_INIT_REQ_T *)message);break;case CL_INTERNAL_DM_READ_LOCAL_VERSION_REQ:PRINT(("CL_INTERNAL_DM_READ_LOCAL_VERSION_REQ\n"));connectionHandleReadLocalVersionRequest(&theCm->infoState, (CL_INTERNAL_DM_READ_LOCAL_VERSION_REQ_T *)message);break;case CL_INTERNAL_DM_SET_BT_VERSION_REQ:PRINT(("CL_INTERNAL_DM_SET_BT_VERSION_REQ\n"));connectionHandleSetBtVersionReq(&theCm->infoState, (CL_INTERNAL_DM_SET_BT_VERSION_REQ_T *)message);break;default:/* Prims we are not handling - for now panic the app */handleUnexpected(connectionUnhandledMessage, theCm->state, id);break;} }
- 2.3.8 回不去了 好像分析有误^0^………………..接着看connectionSendInitCfm函数
<pre name="code" class="cpp">void connectionSendInitCfm(Task task, connection_lib_status status, cl_dm_bt_version version) { MAKE_CL_MESSAGE(CL_INIT_CFM);message->status = status;//这里这个是failmessage->version = version;//版本的话没有bluetooth_unknown/*这个函数是重点,这个task是最重要的任务,所以会往上面返回一个没有初始化成功的标志*/MessageSend(task, CL_INIT_CFM, message);/* Cancel initialisation timeout */if(status == success)(void) MessageCancelFirst(connectionGetCmTask(), CL_INTERNAL_INIT_TIMEOUT_IND); }
汗啊,分析了一遍结果发现到头来初始化失败了啊!!
莫急,有没有注意到我上面说的那个时间很重要的参数,没错就是在这里,当这个时间到之后,确实会发送初始化失败,但是如果底层初始化成功的话这个消息将被取消,不会发往上面,其实程序看到这里的话,应该知道当状态变为初始化完成时,会向上面发送成功的标志,应该说流程大致有个印象,对于具体的其状态是怎样切换成初始化完成的,这个有待后面研究,目前我也不是很懂。
3.几个需要重要关注的地方
- 结构体的理解是个重点
- 连接库初始化的过程中状态的切换是个重点:这个没有解决!!!
百度文档搜索到一篇不错的文档:
注:参考文档,百度文档的对sink流程的分析–CSR ADK sink理解
csr8670--sink工程的大致工作流程分析(以speaker为例)一相关推荐
- 【转载】csr8670--sink工程的大致工作流程分析(以speaker为例)二
csr8670--sink工程的大致工作流程分析(以speaker为例)二 1.编解码任务的初始化 继续接着流程一分析: 1.1 当连接初始化完成之后,如下所示会调用编解码的初始化任务:这个编解码的任 ...
- csr8670--sink工程的大致工作流程分析(以speaker为例)二
1.编解码任务的初始化 继续接着流程一分析: 1.1 当连接初始化完成之后,如下所示会调用编解码的初始化任务:这个编解码的任务作用是什么? <code class="hljs coff ...
- 16.U-boot的工作流程分析-2440
16.U-boot的工作流程分析-2440 分析的流程: 程序入口 第一阶段程序分析 第二阶段程序分析 2440开发板: 1.uboot的入口: 要看uboot工程的入口,首先打开顶层目录的Makef ...
- K8S架构设计及工作流程分析
Kubernetes架构设计 核心组件 api server 功能 controller manager 负责维护集群的状态 scheduler 负责资源的调度按照预定的调度策略将Pod调度到相应的机 ...
- kafka的基本概念和工作流程分析
为什么需要消息队列 周末无聊刷着手机,某宝网APP突然蹦出来一条消息"为了回馈老客户,女朋友买一送一,活动仅限今天!".买一送一还有这种好事,那我可不能错过!忍不住立马点了去.于是 ...
- 【SemiDrive源码分析】【X9芯片启动流程】14 - freertos_safetyos目录Cortex-R5 SafetyOS/RTOS工作流程分析
[SemiDrive源码分析][X9芯片启动流程]14 - freertos_safetyos目录Cortex-R5 SafetyOS/RTOS工作流程分析 一.SafetyOS 工作流程分析 1. ...
- 你想要的系列:网络请求框架OkHttp3全解系列 - (二)OkHttp的工作流程分析
Okhttp系列文章: 你想要的系列:网络请求框架OkHttp3全解系列 - (一)OkHttp的基本使用 你想要的系列:网络请求框架OkHttp3全解系列 - (二)OkHttp的工作流程分析 你想 ...
- Zygote工作流程分析
Zygote 接收客户端创建进程的请求,使用JNI调用linux fork函数创建进程. Zygote是在Init进程中作为Service被启动的.Zygote进程的主体是:ZygoteInit. Z ...
- Android 7.0 WifiMonitor工作流程分析
2019独角兽企业重金招聘Python工程师标准>>> 在wifi启动扫描的分析过程中,出现了多次WifiMonitor的操作,在此分析一下这个函数是如何工作的. 在Android的 ...
最新文章
- Deepmind最新研究:从图表示学习看算法推理
- 学网络好帮手:路由器模拟软件RouteSim3.31
- 基于ASP.Net Core开发的一套通用后台框架
- Lombok介绍、附比较好用的几种注释推荐
- iOS逆向工程(简单利用dumpdecrypted给ipa砸壳)
- 消息队列面试 - 如何保证消息不被重复消费?或者说,如何保证消息消费的幂等性?
- 双系统的电脑中如何完美系统其中一个操作系统
- VS Code 的 Java 七月更新,新的重构特性
- java实验总结_java第一次实验总结第三周总结
- RabbitMq的基本认识和配置(一)
- Failed to connect to d.line-scdn.net port 443: Operation timed out
- 2020.10.1--PS--画笔色彩模式、画笔预设、自定义画笔
- orc识别 语音识别 云真机 内网穿透快速调研
- 老男孩教育教育46期 LIHAO
- java自习_java自习重点及自测
- PHP高性能编程-提高PHP速度-加速PHP执行-PHP性能优化实践
- 篮球英文术语翻译与解释 (以A至E为限)
- 珞珈一号01星(luojia1-01)的夜间灯光影像数据处理流程
- 微软裁员方式曝光:鼓励自愿退休 减少合同工
- Python安装方法
热门文章
- php微信公众点歌台,PHP实现微信公众平台音乐点播功能
- 微信小程序 - 音乐播放器源码
- echarts上加横线标线_Echarts地图添加引导线效果(labelLine)
- Oracle日志挖掘技术logminer
- 解决sublime text2字体显示模糊问题
- Facebook背后的软件
- Java最牛教材!阿里技术官整合的四大主流中间件笔记
- Ubuntu 系统备份为ISO
- vue 项目中 自动生成 二维码
- npm install安装失败,报错记录之The operation was rejected by your operating system. node-sass无法安装,且禁用淘宝镜像