QQ登录

只需一步,快速开始

新浪微博账号登陆

只需一步,快速开始

热搜: eclipse ecos stm32 ecos源码 如何获取ecos ecos源代码 code goAhead redboot
搜索
发新帖

26

主题

1

听众

617

积分

高级工程师

Rank: 4Rank: 4

该用户从未签到

最后登录
2015-11-9
威望
0
金钱
532
贡献
0
注册时间
2013-10-12
积分
617
帖子
70
主题
26
精华
3
UID
495
发表于 2013-11-18 19:19:18 |显示全部楼层
更多
本帖最后由 zoomdy 于 2013-11-18 19:30 编辑

本文阐述eCos在Cortex-M架构中的中断响应过程。eCos是开源免版税的抢占式实时操作系统。其最大亮点是可配置,与其配套的图形化配置工具提供组件管理、选项配置、自动化单元测试等。官网http://ecos.sourceware.org,中文专业论坛http://www.52ecos.net

ecos <at> zoomdy <dot> org
http://blog.csdn.net/zoomdy/article/details/16807263

使能和屏蔽中断
Cortex-M有三个特殊功能寄存器与中断使能和屏蔽有关,分别是primask、faultmask、basepri,设置primask可以屏蔽除了硬ault异常和NMI异常之外的所有异常和中断,设置faultmask可以屏蔽除了NMI异常之外的所有异常和中断,设置basepri可以屏蔽优先级等于或低于当前basepri值的所有异常和中断,但basepri为0时表示使能所有异常和中断。

eCos使用basepri控制中断使能和屏蔽。在整个eCos运行期间,包括初始化、中断处理过程,primask和faultmask寄存器都处于默认状态,即清除状态,在整个运行期间硬fault异常总是使能的。进入初始化例程后,用法fault、总线fault、存储器管理fault被使能且优先级设置为0。eCos在初始化早期将basepri设置成优先级低于0(优先级数值大于0)的最高有效优先级,最高有效优先级定义为宏CYGNUM_HAL_CORTEXM_PRIORITY_MAX,
  1. CYGNUM_HAL_CORTEXM_PRIORITY_MAX = 1<<(8-CYGNUM_HAL_CORTEXM_PRIORITY_LEVEL_BITS)
复制代码
CYGNUM_HAL_CORTEXM_PRIORITY_LEVEL_BITS与Cortex-M核心的配置有关,不同的Cortex-M变种使用不同的数值,例如Kinetis和STM32为4,LPC17xx为5。

屏蔽中断
eCos将basepri设置为CYGNUM_HAL_CORTEXM_PRIORITY_MAX来屏蔽中断。
  1. // hal/cortexm/arch/<version>/include/hal_intr.h:239  
  2. # define HAL_DISABLE_INTERRUPTS(__old)          \  
  3.     __asm__ volatile (                          \  
  4.         "mrs    %0, basepri             \n"     \  
  5.         "mov    r1,%1                   \n"     \  
  6.         "msr    basepri,r1              \n"     \  
  7.         : "=&r" (__old)                         \  
  8.         :  "r" (CYGNUM_HAL_CORTEXM_PRIORITY_MAX)\  
  9.         : "r1"                                  \  
  10.         );  
  11. #endif
复制代码
(4)将原来的basepri复制到__old,供下次恢复basepri值。

(6)将CYGNUM_HAL_CORTEXM_PRIORITY_MAX复制给basepri,屏蔽所有优先级等于或低于CYGNUM_HAL_CORTEXM_PRIORITY_MAX的中断。

使能中断
eCos将basepri设置为0来使能中断。
  1. // hal/cortexm/arch/<version>/include/hal_intr.h:260  
  2. # define HAL_ENABLE_INTERRUPTS()                \  
  3.     __asm__ volatile (                          \  
  4.         "mov    r1,#0                   \n"     \  
  5.         "msr    basepri,r1              \n"     \  
  6.         :                                       \  
  7.         :                                       \  
  8.         : "r1"                                  \  
  9.         );  
  10. #endif
复制代码
(5)将pasepri设置为0,使能所有中断。

中断优先级
eCos将basepri设置为CYGNUM_HAL_CORTEXM_PRIORITY_MAX来屏蔽中断,这意味着所有中断优先级都不能高于CYGNUM_HAL_CORTEXM_PRIORITY_MAX,否则HAL_DISABLE_INTERRUPTS宏将不能正常工作,为了将中断优先级等于低于CYGNUM_HAL_CORTEXM_PRIORITY_MAX,在设置中断优先级时,eCos对优先级数值做了修改。
  1. // hal/cortexm/arch/<version>/src/hal_misc.c:502  
  2. __externC void hal_interrupt_set_level( cyg_uint32 vector, cyg_uint32 level )  
  3. {  
  4.     cyg_uint32 l = (level)+CYGNUM_HAL_CORTEXM_PRIORITY_MAX;  
  5.     if( l > 0xFF ) l = 0xFF; /* clamp to 0xFF */  
  6.     ......  
  7. }
复制代码
(3)将优先级数值加上CYGNUM_HAL_CORTEXM_PRIORITY_MAX,这将保证中断优先级等于或低于CYGNUM_HAL_CORTEXM_PRIORITY_MAX。

(4)如果超过0xFF,那么设置为0xFF,避免高字节截断引起优先级紊乱,0xFF是Cortex-M最低优先级。

中断响应
eCos将中断处理分成两部分:ISR和DSR。中断响应的过程也就分成了两种,一种是ISR没有要求执行DSR或者调度器被加锁的情况,这种情况下执行ISR后立即返回被中断线程;另一种是ISR要求执行DSR并且调度器未加锁的情况,这种情况下执行ISR后接着执行DSR,在DSR中可能将某些线程从等待状态切换到就绪状态并执行线程调度,DSR执行完成后可能返回当前线程,也可能返回刚刚被列入就绪队列的更高优先级的线程。

eCos在Cortex-M架构下的中断响应过程如下图所示,下图的响应过程是要求执行DSR的过程。


图中S为Cyg_Scheduler的缩写,I为Cyg_Interrupt的缩写,S::unlock()意为Cyg_Scheduler::unlock()。

中断响应过程涉及4个运行状态Thread、ISR、PendSV、SVC,Thread使用PSP堆栈,ISR、PendSV、SVC均使用MSP堆栈,包括7个步骤,1次中断向量响应,1次PendSV响应,2次SVC响应。

{1}中断产生,当前线程执行过程被打断,CPU进入中断异常向量开始中断响应,eCos将所有中断包括SysTick的中断向量设置为hal_default_interrupt_vsr,因此首先进入hal_default_interrupt_vsr函数,该函数读取中断号后调用hal_deliver_interrupt对中断进行分发,hal_deliver_interrupt函数调用对应的ISR,并根据需要挂起一个PendSV请求。

{2}中断向量返回后通过Cortex-M的咬尾中断机制直接进入PendSV向量,PendSV构造一个假的异常堆栈,通过这个假的异常堆栈在线程环境下调用hal_interrupt_end函数,从PendSV返回后,因为假的异常堆栈的存在并不返回当前线程被中断的代码处继续执行,而是返回到hal_interrupt_end函数,此外假的异常堆栈将hal_interrupt_end函数的返回点设置为hal_interrupt_end_done。看起来就像是在当前线程被中断处调用了hal_interrupt_end_done,然后hal_interrupt_end_done调用了hal_interrupt_end函数一样。

{3}返回到线程环境后开始执行hal_interrupt_end,依次调用interrupt_end、Cyg_Scheduler::unlock、Cyg_Scheduler::unlock_inner、Cyg_Scheduler::call_pending_DSRs、Cyg_Interrupt::call_pending_DSRs,eCos希望在专用的中断堆栈环境下执行DSR,因此通过swi指令进入SVC系统调用向量,在SVC环境下调用DSR,SVC使用的MSP堆栈,eCos将MSP用作专用的中断和异常堆栈。

{4}CPU执行到swi指令后进入SVC系统调用向量,这次系统调用将调用hal_call_dsrs_vsr函数,hal_call_dsrs_vsr直接跳转到cyg_interrupt_call_pending_DSRs,cyg_interrupt_call_pending_DSRs调用Cyg_Interrupt::call_pending_DSRs_inner来调用DSR。

{5}SVC系统调用向量返回当前线程后,最终返回到hal_interrupt_end_done。前面是通过假的异常堆栈帧在当前线程中断点插入对hal_interrupt_end的调用,hal_interrupt_end_done的作用是撤销假堆栈帧恢复当前线程的被中断点运行环境,通过swi指令进入SVC系统调用来恢复线程堆栈。

{6}CPU执行到swi指令后进入sVC系统调用向量,这次系统调用将调用hal_interrupt_end_vsr,hal_interrupt_end_vsr的作用是撤销假堆栈恢复当前线程堆栈指针,然后返回。

{7}终于,中断响应完成,返回到线程被中断点继续执行,需要注意的是{5}和{6}之间会进行调度,如果调度了更高优先级的线程,当返回到这里的时候已经过去比较长的时间了。

接下来依据中断响应过程的调用次序,详细讲述各函数。

hal_default_interrupt_vsr
在HAL的初始化过程,所有中断向量服务例程包括SysTick的向量服务例程均被设置成hal_default_interrupt_vsr,因此产生中断后首先进入的就是向量服务例程hal_default_interrupt_vsr。
  1. hal/cortexm/arch/<version>/src/vectors.S:212  
  2.         .type   hal_default_interrupt_vsr, %function  
  3. hal_default_interrupt_vsr:  
  4.   
  5.         push    {lr}                    // Save return link  
  6.         sub     sp,#4                   // Realign SP to 8 bytes  
  7.   
  8.         mrs     r0,ipsr                 // R0 = arg0 = vector number  
  9.         sub     r0,#15                  // Adjust to interrupt range  
  10.   
  11.         bl      hal_deliver_interrupt  
  12.   
  13.         add     sp,#4                   // pop alignment padding  
  14.         pop     {pc}                    // Pop LR and return  
复制代码
(5)向量服务例程首先保存当前的lr寄存器值到堆栈,因为后面马上要使用bl指令调用函数,bl指令将会修改lr寄存器。

(6)堆栈按8字节对齐。

(8)读取当前中断号。

(9)对中断号进行修正,ipsr中存储的实际上是向量编号,这里实际需要的是中断编号,减掉15而不是16的原因是eCos将SysTick也作为中断来处理,SysTick的异常编号为15,对应中断编号0。

(11)调用hal_deliver_interrupt函数分发中断服务例程。

(13)重新修正堆栈指针。

(14)将lr寄存器弹出到pc,等价于mov pc, lr,从中断返回,如果没有DSR需要执行,立即返回被中断线程,如果需要执行DSR,那么执行咬尾中断,进入PendSVC异常服务例程。

hal_deliver_interrupt
VSR读取当前中断号后调用中断分发函数,中断分发函数根据中断号调用对应的ISR。
  1. // hal/cortexm/arch/<version>/src/hal_misc.c:371  
  2. void hal_deliver_interrupt( cyg_uint32 vector )  
  3. {  
  4.     register cyg_uint32 isr_result;  
  5.     register cyg_isr *isr;  
  6.     cyg_bool pendsvc = false;  
  7.   
  8.     isr = (cyg_isr *)hal_interrupt_handlers[vector];  
  9.   
  10.     // Call the ISR  
  11.     isr_result = isr( vector, hal_interrupt_data[vector] );  
  12.   
  13.     // If the ISR has returned the CALL_DSR bit, post the DSR and set  
  14.     // the pendable SVC exception pending.  
  15.     if( isr_result & CYG_ISR_CALL_DSR )  
  16.     {  
  17.         cyg_interrupt_post_dsr( hal_interrupt_objects[vector] );  
  18.   
  19.         // Post the pendable SVC to call interrupt_end(). But only if  
  20.         // the scheduler lock is currently zero. If it is non zero  
  21.         // then interrupt_end will do nothing useful, so avoid calling  
  22.         // it.  
  23.         if( cyg_scheduler_sched_lock == 0 )  
  24.             pendsvc = true;  
  25.     }  
  26.   
  27.     // Post the pendable SVC if required.  
  28.     if( pendsvc )  
  29.     {  
  30.         cyg_uint32 icsr;  
  31.         HAL_READ_UINT32( CYGARC_REG_NVIC_BASE+CYGARC_REG_NVIC_ICSR, icsr );  
  32.         icsr |= CYGARC_REG_NVIC_ICSR_PENDSVSET;  
  33.         HAL_WRITE_UINT32( CYGARC_REG_NVIC_BASE+CYGARC_REG_NVIC_ICSR, icsr );  
  34.     }  
  35. }
复制代码
(2)中断号作为中断分发函数的入参传入。

(8)以中断号作为索引读取ISR函数指针,ISR函数指针是在驱动程序通过调用cyg_drv_interrupt_attach来设置的。

(11)调用ISR,ISR入参为中断向量号以及用户数据,多个中断源可能会使用相同的ISR,根据中断向量号或用户数据可以判断到底是哪一个中断。

(15)判断ISR返回值,看是否需要调用DSR。

(17)如果需要调用DSR,那么调用cyg_interrupt_post_dsr将当前中断对应的DSR追加到DSR列表。

(23)判断当前线程是否对调度器进行加锁,如果未加锁,那么允许执行DSR。

(28-34)如果需要执行DSR,那么将ICSR寄存器PENDSVSET置位,这将挂起一个PendSV请求,因为PendSV的优先级被初始化为最低优先级,因此不会对当前中断处理进行抢占,只有中断向量服务函数返回后才会执行PendSV。

疑问:(31-33)读取ICSR寄存器修改后写回,这个过程没有进行关中断保护,如果在(31)读取ICSR后产生了更高优先级的中断,那么将会抢占当前中断处理进入嵌套中断处理流程执行更高优先级的中断服务例程,当高优先级中断服务例程返回后,ICSR寄存器的值与icsr临时变量存储的值还保持一致吗?

hal_pendable_svc_vsr
eCos中ISR的优先级要绝对高于DSR且不可配置,DSR仅在ISR执行完成后执行,如果产生了嵌套中断,那么要等所有ISR全部执行完成后再执行DSR。Cortex-M的中断控制器与核心紧密结合,只有执行了hal_default_interrupt_vsr最后一条指令(pop {pc})后,中断处理才算完成。当前中断处理完成后,要么返回被中断线程,要么开始进入低优先级的中断服务例程。eCos为了保证ISR的优先级绝对高于DSR,且在ISR完成后有机会调用DSR,使用了Cortex-M的PendSV机制,在PendSV处理DSR相关请求。PendSV优先级被设置成最低优先级,如果当前有ISR正在执行,由于PendSV的优先级最低,不可能抢占ISR,因此可以保证ISR优先级绝对高于DSR,即使当前中断同样是最低优先级,由于Cortex-M不支持同优先级的抢占,因此也会保证在ISR执行完后再处理DSR。

中断向量服务例程完成后,通过Cortex-M的咬尾中断机制进入PendSV向量服务例程。
  1. // hal/cortexm/arch/<v>/src/vectors.S:257  
  2.         .type   hal_pendable_svc_vsr, %function  
  3. hal_pendable_svc_vsr:  
  4.   
  5.         mrs     r12,psp                 // R12 = thread's PSP  
  6.         sub     r0,r12,#HAL_SAVEDREG_AUTO_FRAME_SIZE            // Make space for frame  
  7.         msr     psp,r0                  // Put it back  
  8.   
  9.         ldr     r3,=0x01000000          // R3 = PSR = thumb bit set  
  10.         ldr     r2,=hal_interrupt_end   // R2 = PC = interrupt end entry point  
  11.         ldr     r1,=hal_interrupt_end_done // R1 = LR = restore code  
  12.         stmfd   r12!,{r0-r3}            // Save fake R12, LR, PC, PSR  
  13.         stmfd   r12!,{r0-r3}            // Save fake R0-R3  
  14.   
  15.         bx      lr                      // Return to hal_interrupt_end
复制代码
(5)读取线程堆栈寄存器,eCos中线程使用PSP为堆栈,PendSV使用MSP最为堆栈,因此通过MRS指令读取PSP寄存器。

(6)为后面的假异常堆栈帧预留空间。

(7)将修改后的堆栈写回PSP寄存器。

(9-13)构造假异常堆栈帧,假异常堆栈帧的PSR=0x01000000,PC=hal_interrupt_end,LR=hal_interrupt_end_done,其他寄存器值的内容无关紧要,但是必须按照Cortex-M异常响应时自动压栈的次序压入。

(15)从PendSV返回,Cortex-M执行到这条语句时,将自动从PSP堆栈中恢复R0-R3,R12,LR,PC,PSR,因此当返回后,PC=hal_interrupt_end,LR=hal_interrupt_end_done,也就是说并不是返回当前线程的被中断点,而是返回到了hal_interrupt_end函数,而且从hal_interrupt_end返回后还不是线程被中断点,而是返回hal_interrupt_end_done。eCos通过构造假异常堆栈帧的手段在线程环境环境下调用部分中断处理相关代码。

hal_interrupt_end
hal_interrupt_end的主要作用是调用interrupt_end函数,interrupt_end属于eCos内核的中断处理内容。
  1. // hal/cortexm/arch/<v>/src/hal_misc.c:430  
  2. __externC void hal_interrupt_end( void )  
  3. {  
  4. #ifdef CYGFUN_HAL_COMMON_KERNEL_SUPPORT  
  5.     cyg_scheduler_sched_lock++;  
  6. #endif  
  7.   
  8.    interrupt_end(0,0,0);  
  9. }
复制代码
(5)调度器锁进行加锁,在interrupt_end将对调度器解锁,这里的加锁是为了与interrupt_end中的解锁配套。cyg_scheduler_sched_lock是Cyg_Scheduler_SchedLock::sched_lock的符号别名,在kernel/<version>/include/smp.hxx:414定义二者的别名关系。

(8)调用interrupt_end,interrupt_end是属于内核中断处理的内容,interrupt_end函数的关键是调用Cyg_Scheduler::unlock函数,Cyg_Scheduler::unlock调用Cyg_Scheduler::unlock_inner,Cyg_Scheduler::unlock_inner调用Cyg_Interrupt::call_pending_DSRs,Cyg_Interrupt::call_pending_DSRs最终调用DSR。

Cyg_Interrupt::call_pending_DSRs是通过HAL宏来调用DSR的,因为eCos需要在中断堆栈中调用DSR,而堆栈切换是与硬件息息相关的,因此必须通过HAL宏来实现,该宏为HAL_INTERRUPT_STACK_CALL_PENDING_DSRS,在Cortex-M架构中,该宏定义如下
  1. // hal/cortexm/arch/<v>/include/hal_intr.h:303  
  2. #define HAL_INTERRUPT_STACK_CALL_PENDING_DSRS()         \  
  3. {                                                       \  
  4.     __asm__ volatile (                                  \  
  5.         "ldr     r3,=hal_call_dsrs_vsr          \n"     \  
  6.         "swi 0                                  \n"     \  
  7.         :                                               \  
  8.         :                                               \  
  9.         : "r3"                                          \  
  10.         );                                              \  
  11. }
复制代码
(5)将SVC系统调用服务需要调用的函数指针通过R3传入,R0-R2参数不使用。

(6)使用swi指令触发系统调用服务。

hal_default_svc_vsr
eCos中断响应过程包括了2次SVC系统调用服务,因此eCos定义了一个通用的SVC向量服务例程来根据传入的参数调用响应的函数,当执行到swi指令时将进入SVC向量服务例程响应SVC系统调用服务。
  1. // hal/cortexm/arch/<v>/src/vectors.S:348  
  2.         .type   hal_default_svc_vsr, %function  
  3. hal_default_svc_vsr:  
  4.   
  5.         mrs     r12,psp  
  6.         ldmfd   r12,{r0-r3}  
  7.         bx      r3                      // Jump to routine in R3
复制代码
(5-6)从PSP堆栈取参数。R0-R3是在进入SVC向量服务例程时由Cortex-M自动压入PSP堆栈的。

(7)R3存储的是被调用函数指针,跳转到该函数。

hal_call_dsrs_vsr
  1. // hal/cortexm/arch/<v>/src/vectors.S:326  
  2.         .type   hal_call_dsrs_vsr, %function  
  3. hal_call_dsrs_vsr:  
  4.         .extern cyg_interrupt_call_pending_DSRs  
  5.         b       cyg_interrupt_call_pending_DSRs
复制代码
(5)直接跳转到cyg_interrupt_call_pending_DSRs,cyg_interrupt_call_pending_DSRs在kernel/<version>/src/intr/intr.cxx:233中定义,cyg_interrupt_call_pending_DSRs的作用是调用DSR。

hal_interrupt_end_done
DSR调用完成后,从SVC向量服务例程返回到线程环境,然后沿着函数调用路径退回到hal_interrupt_end,从hal_interrupt_end返回时返回到hal_interrupt_end_done,这个返回过程是在构造假异常堆栈帧时设定的。
  1. // hal/cortexm/arch/<v>/src/vectors.S:289  
  2.         .type   hal_interrupt_end_done, %function  
  3. hal_interrupt_end_done:  
  4.         ldr  r3,=hal_interrupt_end_vsr  
  5.         swi  0
复制代码
(4)将hal_interrupt_end_vsr函数地址保存到R3,SVC系统调用将通过R3调用hal_interrupt_end_vsr。

(5)触发SVC系统调用。

hal_interrupt_end_vsr
hal_interrupt_end_vsr的作用是撤销假异常堆栈帧,恢复线程在中断自动压栈后的状态。
  1. // hal/cortexm/arch/<v>/src/vectors.S:306  
  2.         .type   hal_interrupt_end_vsr, %function  
  3. hal_interrupt_end_vsr:  
  4.         mrs     r12,psp                 // R12 = thread's PSP  
  5.         add     r12,#HAL_SAVEDREG_AUTO_FRAME_SIZE                 // Skip our saved state  
  6.         msr     psp,r12                 // Restore thread's PSP  
  7.   
  8.         bx      lr                      // And return
复制代码
(4)读取线程堆栈PSP。

(5)跳过伪造的异常堆栈帧,恢复到发生中断并自动压栈后的状态。

(6)重新保存回PSP寄存器。

(8)从SVC返回,返回时恢复的寄存器是发生中断时压入堆栈的的寄存器值,即返回线程被中断处,到此为止中断响应完成。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册会员 新浪微博账号登陆

回复

使用道具 举报

84

主题

16

听众

2901

积分

超级版主

Rank: 8Rank: 8Rank: 8Rank: 8

该用户从未签到

最后登录
2015-5-31
威望
0
金钱
2389
贡献
0
注册时间
2012-5-1
积分
2901
帖子
492
主题
84
精华
4
UID
2
发表于 2013-11-18 21:38:52 |显示全部楼层
又看到大作了,必须顶一个!
回复

使用道具 举报

84

主题

16

听众

2901

积分

超级版主

Rank: 8Rank: 8Rank: 8Rank: 8

该用户从未签到

最后登录
2015-5-31
威望
0
金钱
2389
贡献
0
注册时间
2012-5-1
积分
2901
帖子
492
主题
84
精华
4
UID
2
发表于 2013-11-18 21:39:47 |显示全部楼层
这两天在移植SDIO接口WIFI驱动,正好在用HAL_DISABLE_INTERRUPTS和HAL_ENABLE_INTERRUPTS两个宏呢!
回复

使用道具 举报

23

主题

2

听众

898

积分

高级工程师

Rank: 4Rank: 4

  • TA的每日心情
    难过
    2013-9-3 21:37
  • 签到天数: 31 天

    [LV.5]常住居民I

    最后登录
    2014-7-16
    威望
    0
    金钱
    821
    贡献
    0
    注册时间
    2013-5-8
    积分
    898
    帖子
    77
    主题
    23
    精华
    0
    UID
    295
    发表于 2013-11-18 21:50:33 |显示全部楼层
    能把ECOS中断分析的这么详细 真是大牛之作了
    回复

    使用道具 举报

    26

    主题

    1

    听众

    617

    积分

    高级工程师

    Rank: 4Rank: 4

    该用户从未签到

    最后登录
    2015-11-9
    威望
    0
    金钱
    532
    贡献
    0
    注册时间
    2013-10-12
    积分
    617
    帖子
    70
    主题
    26
    精华
    3
    UID
    495
    发表于 2013-11-23 11:19:32 |显示全部楼层
    reille 发表于 2013-11-18 21:39
    这两天在移植SDIO接口WIFI驱动,正好在用HAL_DISABLE_INTERRUPTS和HAL_ENABLE_INTERRUPTS两个宏呢! ...

    原来还有SDIO的WIFI,这个可以考虑啊,SDIO的通信有没有标准的?还是各个厂家各有一套通信协议?
    回复

    使用道具 举报

    84

    主题

    16

    听众

    2901

    积分

    超级版主

    Rank: 8Rank: 8Rank: 8Rank: 8

    该用户从未签到

    最后登录
    2015-5-31
    威望
    0
    金钱
    2389
    贡献
    0
    注册时间
    2012-5-1
    积分
    2901
    帖子
    492
    主题
    84
    精华
    4
    UID
    2
    发表于 2013-11-23 13:30:30 |显示全部楼层
    zoomdy 发表于 2013-11-23 11:19
    原来还有SDIO的WIFI,这个可以考虑啊,SDIO的通信有没有标准的?还是各个厂家各有一套通信协议 ...

    SDIO接口通信,有MMC、SD和SDIO 3种通信协议标准,用于MMC卡、SD卡以及SDIO设备的通信!
    回复

    使用道具 举报

    0

    主题

    0

    听众

    22

    积分

    实习生

    Rank: 1

    该用户从未签到

    最后登录
    2013-12-27
    威望
    0
    金钱
    15
    贡献
    0
    注册时间
    2013-12-26
    积分
    22
    帖子
    7
    主题
    0
    精华
    0
    UID
    608
    发表于 2013-12-26 20:23:33 |显示全部楼层
    duoxie
    QQQQQQQQQQQQQQQQQQ
    回复

    使用道具 举报

    0

    主题

    0

    听众

    28

    积分

    实习生

    Rank: 1

    该用户从未签到

    最后登录
    2015-2-4
    威望
    0
    金钱
    19
    贡献
    0
    注册时间
    2015-2-2
    积分
    28
    帖子
    9
    主题
    0
    精华
    0
    UID
    1411
    发表于 2015-2-3 11:22:18 |显示全部楼层
    写得不错,感谢分享。
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 注册会员 新浪微博账号登陆

    无觅相关文章插件

    申请友链|手机版|关于本站|站点帮助|eCos技术网 ( 粤ICP备12094833号-1 )   

    GMT+8, 2016-8-6 04:21 , Processed in 0.199153 second(s), 39 queries .

    Powered by Discuz!2.5 X2.5

    © 2001-2012 Comsenz Inc.

    回顶部