zoukankan      html  css  js  c++  java
  • 如何理解nRF5芯片外设PPI

    PPI,英文全称Programmable Peripheral Interconnect,是Nordic独有的外设,其设计目的是让CPU处于idle模式下外设与外设之间也能完成相应通信,从而降低系统功耗。为此,很多人会把PPI类比成DMA,的确PPI和DMA两者在设计最终目的上有一定的相似性,但两者的功能和原理完全不相同。讲解PPI原理之前,先大概阐述一下Nordic芯片一个独特的设计理念。

    Nordic芯片每个外设都可以看做一个状态机,所以每个外设都有输入(task),输出(event)以及状态。比较常见的task比如启动外设,清0寄存器等,常见的event比如数据发送完毕,外设关闭等。实现上,每个task和event都是一个独立的32-bit寄存器,这跟传统的芯片不一样,传统的芯片都是用寄存器的某一个bit来启动,或者某一个bit来显示状态。换句话说,Nordic把传统芯片1bit要做的事情换成一个完整的32-bit寄存器来实现。这样做的好处是,每个task和event都是一个寄存器,他们都可以用一个独立而唯一的地址来标识,这就为PPI打下了坚实的基础。比如Timer模块的寄存器列表如下所示,里面就包含了各种task和event寄存器:

     

    再比如ADC模块的寄存器列表如下所示,里面也包含了各种task和event寄存器:

     

    现在开始讲PPI,首先PPI也是一个外设,因此PPI也有自己的寄存器定义,如下图所示,其主要用来配置PPI通道等。简言之,PPI就是一个数字逻辑系统,它可以通过某一个PPI通道把外设1的event跟外设2的task相连,这样一旦外设1的event置起(相关寄存器为1),将会自动触发外设2的task(将相关寄存器自动置1)。

     

    下面以一个实际例子来加深大家对PPI的理解,假设我们要实现如下功能:启动timer,定时10ms,10ms到后启动ADC模块。这里我们以两种方式来实现该例子要求:传统方式和PPI方式,大家仔细比较两者的区别,以理解PPI的积极作用。

    传统方式

    传统方式大致需要如下步骤:

    1. 初始化Timer模块和ADC模块——(CPU工作)
    2. 启动Timer——(CPU工作)
    3. 等待Timer中断——(CPU不工作)
    4. 10ms到,进入Timer timeout handler,启动ADC——(CPU工作)

    PPI方式

    PPI方式大致需要如下步骤:

    1. 初始化Timer模块,ADC模块,以及PPI模块,将Timer模块的timeout event和ADC模块的start task相连——(CPU工作)
    2. 启动Timer——(CPU工作)
    3. 等待Timer timeout,10ms到,PPI将自动启动ADC——(CPU不工作)

    通过比较传统方式和PPI方式,PPI方式可以少进入一次timeout handler,从而减少CPU工作时间,降低系统功耗。由于不需要进入timeout handler,因此启动ADC的操作就不存在被其他高优先级中断打断的可能,这是PPI带来的第二个好处:系统实时性更好。

    除了一个event对应一个task,PPI通过fork机制可以让一个event同时启动2个task,即把一个event同时和一个task以及task对应的fork相连,以实现一个event到来,2个task同时启动的目的。

    大家可以参考SDK自带例子(Keil5工程):

    SDK安装目录examplesperipheralppipca10040lankarm5_no_packs

    或者

    SDK安装目录examplesperipheralgpiotepca10040lankarm5_no_packs

    来进一步理解PPI的工作原理和编程注意事项。

    下面为一段PPI使用代码示例,它实现的功能是:当定时时间到,通过PPI自动去操作IO口

    err_code = nrf_drv_ppi_init();
    
    APP_ERROR_CHECK(err_code);
    
    err_code = nrf_drv_ppi_channel_alloc(&ppi_channel);
    
    APP_ERROR_CHECK(err_code);
    
    
    compare_evt_addr = nrf_drv_timer_event_address_get(&timer, NRF_TIMER_EVENT_COMPARE0);
    
    gpiote_task_addr = nrf_drv_gpiote_out_task_addr_get(GPIO_OUTPUT_PIN_NUMBER);
    
     
    err_code = nrf_drv_ppi_channel_assign(ppi_channel, compare_evt_addr, gpiote_task_addr);
    
    APP_ERROR_CHECK(err_code);
    
    err_code = nrf_drv_ppi_channel_enable(ppi_channel);
    
    APP_ERROR_CHECK(err_code);
  • 相关阅读:
    python爬虫----XPath
    定时爬取海丝财经网站新闻内容
    传染病传播模型(SIS)Matlab代码
    李航统计学习方法——算法3朴素贝叶斯法
    李航统计学习方法——算法2k近邻法
    文件从开头删除几个字符,整个磁盘的变化
    intel DSA spec 解读
    线上上课=大屏电视显示+nuc做机顶盒+手机做移动麦克风
    VPP/UPF/GTP
    超标量
  • 原文地址:https://www.cnblogs.com/iini/p/9348504.html
Copyright © 2011-2022 走看看