21 PTE简介 (Peripheral-Trigger-Engine)
外设触发引擎( Peripheral trigger engine,PTE )通过事件发布和任务订阅的方式实现外设之间的连接,而不需要MCU的任何干预。通过PTE连接通道,当外设发生事件时,可以自动触发外设的预定义任务。这种逻辑联系无需 CPU 干预、降低功耗、提升实时性,可以使用PTE实现外设的预定义的行为。
21.1 PTE功能描述
PTE功能包括事件发布和任务订阅。PTE事件发布器可以发布事件,PTE任务订阅器可以订阅事件并执行相应的任务。PTE可以发布的外设任务和监听事件类型是硬件预先定义的,软件只能使用预先定义的事件类型。
注意:部分外设的事件和任务和DMA相关,使用这些任务和事件必须配合DMA使用
21.1.1 特性
- 外设作为发布者/订阅者
- 外设作为发布者可以在设定的通道上发布事件。
- 外设作为订阅者可以根据设定通道上的事件执行对应任务。
- 支持多种连接选项,包括一对一、一对多、多对一、多对多。
- 外设可以触发DMA任务,DMA可以发布生成的事件。
- 支持最高16个发布和订阅通道。
- 16个通道可以任意作为一个分组,支持最大四个通道分组。
21.1.2 PTE外设通道连接特性
PTE外设喝PTE模块之间的连接模块称之为PTEC(Peripheral-Trigger-Engine Controller), 功能框图如下图所示:
PTE外设和PTE模块之间的连接功能框图
由该框图可以看出,外设的任务喝事件可以预先配置到任意一个或多个通道,PTEC根据通道配置,将外设的任务和事件连接起来,当注册到同一个通道的外设发生事件时,PTEC会自动触发外设的预定义任务。
例如: GPIOTE(GPIO Task Event)的按键检测事件和UART的DMA开始发送任务预先配置在一个通道0,GPIOTE模块检测到了一个按键按下的事件,发布给PTEC,PTEC根据通道配置,触发UART的DMA开始发送任务。中间无需CPU干预,提升了任务实时性。
21.1.3 PTE模块通道的使能和分组
PTE的外设连接功能框图如下所示:
PTE模块通道的使能和分组
根据图示,PTE的通道连接特性包括:
- PTE通道内部是一个总线矩阵。
- 每个外设的功能task和event可以通过PTEC配置到一个或多个通道。
- 每个PTE通道可以单独配置使能和关闭,外设通道功能使能前无法发布和订阅事件。
- PTE通道可以配置为分组,最多支持四个分组。
- PTE通道分组将多个通道组合为一组,监听一个通道的event触发分组内通道的多个任务。
21.1.4 PTE事件接收器
PTE事件接收器可以在对应的通道监听事件。PTE通道会监听所有配置到当前通道的事件。 PTE支持的发布事件如下:
typedef enum
{
PTE_EVENT_QDEC_CH0_STOP_CPL = 0, // QDEC channel 0 stop complete event
PTE_EVENT_QDEC_CH1_STOP_CPL,
PTE_EVENT_QDEC_CH2_STOP_CPL,
PTE_EVENT_DMA_CH0_STOP_CPL = 0, // DMA channel 0 stop complete event
PTE_EVENT_DMA_CH1_STOP_CPL,
PTE_EVENT_DMA_CH2_STOP_CPL,
PTE_EVENT_DMA_CH3_STOP_CPL,
PTE_EVENT_DMA_CH4_STOP_CPL,
PTE_EVENT_DMA_CH5_STOP_CPL,
PTE_EVENT_DMA_CH6_STOP_CPL,
PTE_EVENT_DMA_CH7_STOP_CPL,
PTE_EVENT_GPIOTE_CH0_INPUT_INT = 0, // GPIOTE channel 0 input interrupt event
PTE_EVENT_GPIOTE_CH1_INPUT_INT,
PTE_EVENT_GPIOTE_CH2_INPUT_INT,
PTE_EVENT_GPIOTE_CH3_INPUT_INT,
PTE_EVENT_GPIOTE_CH4_INPUT_INT,
PTE_EVENT_GPIOTE_CH5_INPUT_INT,
PTE_EVENT_GPIOTE_CH6_INPUT_INT,
PTE_EVENT_GPIOTE_CH7_INPUT_INT,
PTE_EVENT_TIMER_CH0_TIM0_TIM_UP = 0, // Timer 0 channel 0 timer up event
PTE_EVENT_TIMER_CH0_TIM1_TIM_UP,
PTE_EVENT_TIMER_CH0_TIM2_TIM_UP,
PTE_EVENT_TIMER_CH0_TIM3_TIM_UP,
PTE_EVENT_TIMER_CH1_TIM0_TIM_UP,
PTE_EVENT_TIMER_CH1_TIM1_TIM_UP,
PTE_EVENT_TIMER_CH1_TIM2_TIM_UP,
PTE_EVENT_TIMER_CH1_TIM3_TIM_UP,
PTE_EVENT_SPI_TX_END = 0, // SPI TX end event
PTE_EVENT_I2C_TX_CPL = 0, // I2C TX complete event
PTE_EVENT_ADC_DATA_CPL = 0, // ADC data complete event
PTE_EVENT_ADC_DMA_STOP_TX, // ADC stop transfer status flag in dma mode
PTE_EVENT_UART_TX_INT = 0, // UART TX interrupt event
PTE_EVENT_UART_RX_INT, // UART RX interrupt event
PTE_EVENT_PWM_CH0_PWM_STOP = 0, // PWM channel 0 PWM stop event
PTE_EVENT_PWM_CH0_FIFO_TRG, // PWM channel 0 FIFO trigger event
PTE_EVENT_PWM_CH0_PCM_STOP, // PWM channel 0 PCM stop event
PTE_EVENT_PWM_CH1_PWM_STOP,
PTE_EVENT_PWM_CH1_FIFO_TRG,
PTE_EVENT_PWM_CH1_PCM_STOP,
PTE_EVENT_PWM_CH2_PWM_STOP,
PTE_EVENT_PWM_CH2_FIFO_TRG,
PTE_EVENT_PWM_CH2_PCM_STOP,
PTE_EVENT_ASDM_RX_DATA = 0, // ASDM RX data event
}PTE_Event;这些支持的事件可配置到对应的PTE通道上报对应的外设事件。
21.1.5 PTE任务发布器
PTE任务发布器用于将任务发布到对应的外设,PTE监听到通道上的事件后会触发配置到当前通道的所有任务执行。PTE任务发布器支持以下任务:
typedef enum
{
PTE_TASK_QDEC_CH0_START = 0, // QDEC channel 0 start
PTE_TASK_QDEC_CH0_STOP, // QDEC channel 0 stop
PTE_TASK_QDEC_CH1_START,
PTE_TASK_QDEC_CH1_STOP,
PTE_TASK_QDEC_CH2_START,
PTE_TASK_QDEC_CH2_STOP,
PTE_TASK_GPIOTE_TOGGLE_CH0 = 0, // GPIOTE channel 0 toggle
PTE_TASK_GPIOTE_TOGGLE_CH1,
PTE_TASK_GPIOTE_TOGGLE_CH2,
PTE_TASK_GPIOTE_TOGGLE_CH3,
PTE_TASK_GPIOTE_TOGGLE_CH4,
PTE_TASK_GPIOTE_TOGGLE_CH5,
PTE_TASK_GPIOTE_TOGGLE_CH6,
PTE_TASK_GPIOTE_TOGGLE_CH7,
PTE_TASK_GPIOTE_HIGH_CH0, // GPIOTE channel 0 high
PTE_TASK_GPIOTE_HIGH_CH1,
PTE_TASK_GPIOTE_HIGH_CH2,
PTE_TASK_GPIOTE_HIGH_CH3,
PTE_TASK_GPIOTE_HIGH_CH4,
PTE_TASK_GPIOTE_HIGH_CH5,
PTE_TASK_GPIOTE_HIGH_CH6,
PTE_TASK_GPIOTE_HIGH_CH7,
PTE_TASK_GPIOTE_LOW_CH0, // GPIOTE channel 0 low
PTE_TASK_GPIOTE_LOW_CH1,
PTE_TASK_GPIOTE_LOW_CH2,
PTE_TASK_GPIOTE_LOW_CH3,
PTE_TASK_GPIOTE_LOW_CH4,
PTE_TASK_GPIOTE_LOW_CH5,
PTE_TASK_GPIOTE_LOW_CH6,
PTE_TASK_GPIOTE_LOW_CH7,
PTE_TASK_TIMER_CH0_TM0_START = 0, // TIMER channel 0 timer 0 start
PTE_TASK_TIMER_CH0_TM1_START,
PTE_TASK_TIMER_CH0_TM2_START,
PTE_TASK_TIMER_CH0_TM3_START,
PTE_TASK_TIMER_CH1_TM0_START,
PTE_TASK_TIMER_CH1_TM1_START,
PTE_TASK_TIMER_CH1_TM2_START,
PTE_TASK_TIMER_CH1_TM3_START,
PTE_TASK_TIMER_CH0_TM0_STOP, // TIMER channel 0 timer 0 stop
PTE_TASK_TIMER_CH0_TM1_STOP,
PTE_TASK_TIMER_CH0_TM2_STOP,
PTE_TASK_TIMER_CH0_TM3_STOP,
PTE_TASK_TIMER_CH1_TM0_STOP,
PTE_TASK_TIMER_CH1_TM1_STOP,
PTE_TASK_TIMER_CH1_TM2_STOP,
PTE_TASK_TIMER_CH1_TM3_STOP,
PTE_TASK_SPI_MASTER_DMA_TX_START = 0, // start spi master transfer in dma mode
PTE_TASK_SPI_MASTER_DMA_TX_STOP, //stop spi master transfer in dma mode
PTE_TASK_I2C_MASTER_DMA_TX = 0, //I2C start i2c master transfer in dma mode
PTE_TASK_ADC_START = 0, // ADC start to sample data
PTE_TASK_ADC_LOOP, // adc loop
PTE_TASK_ADC_DMA_STOP_TX, // adc stop transfer in dma mode
PTE_TASK_UART_DMA_TX_START = 0, // UART start transmiting data in dma mode
PTE_TASK_UART_DMA_TX_STOP, // UART stop transmiting data in dma mode
PTE_TASK_UART_DMA_RX_START, // UART start receiving data in dma mode
PTE_TASK_UART_DMA_RX_STOP, // UART stop receiving data in dma mode
PTE_TASK_PWM_CH0_IR_START = 0, // PWM channel 0 IR send start
PTE_TASK_PWM_CH0_ONE_PULSE, //PWM channel0 one pulse pwm
PTE_TASK_PWM_CH0_PWM_START, //PWM channel0 start pwm
PTE_TASK_PWM_CH0_PWM_DMA_START, //PWM channel0 start pwm in dma mode
PTE_TASK_PWM_CH0_PCM_START, //PWM channel0 start pcm
PTE_TASK_PWM_CH0_PWM_STOP, //PWM channel0 stop pwm
PTE_TASK_PWM_CH0_PCM_STOP, //PWM channel0 stop pcm
PTE_TASK_PWM_CH1_IR_START,
PTE_TASK_PWM_CH1_ONE_PULSE,
PTE_TASK_PWM_CH1_PWM_START,
PTE_TASK_PWM_CH1_PWM_DMA_START,
PTE_TASK_PWM_CH1_PCM_START,
PTE_TASK_PWM_CH1_PWM_STOP,
PTE_TASK_PWM_CH1_PCM_STOP,
PTE_TASK_PWM_CH2_IR_START,
PTE_TASK_PWM_CH2_ONE_PULSE,
PTE_TASK_PWM_CH2_PWM_START,
PTE_TASK_PWM_CH2_PWM_DMA_START,
PTE_TASK_PWM_CH2_PCM_START,
PTE_TASK_PWM_CH2_PWM_STOP,
PTE_TASK_PWM_CH2_PCM_STOP,
PTE_TASK_I2S_DMA_TX_START = 0, // I2S start sending data in dma mode
PTE_TASK_I2S_DMA_RX_START, // I2S start receiving data in dma mode
PTE_TASK_I2S_DMA_TX_STOP, // I2S stop sending data
PTE_TASK_I2S_DMA_RX_STOP, // I2S stop receiving data
PTE_TASK_ASDM_RX_START = 0, //ASDM start receiving data
PTE_TASK_ASDM_RX_STOP, //ASDM stop receiving data
}PTE_Task;21.2 使用方法
21.2.1 API介绍
配置使能对应的任务到指定的PTE通道,使用该接口配置pte通道触发后要执行的任务。
uint8_t PTE_ConfigTask(PTE_Module module, PTE_Task Task, PTE_Channel SetTaskChannel, uint8_t enable);配置使能对应的监听事件到指定的PTE通道,使用该接口配置pte通道触发事件源。
uint8_t PTE_ConfigEvent(PTE_Module module, PTE_Event Event, PTE_Channel SetEventChannel, uint8_t enable);触发对应的任务,使用该接口可以通过软件方式手动触发任务运行,可以测试任务触发情况或手动触发任务运行。
uint8_t PTE_TaskTrigger(PTE_Module module, PTE_Task Task);使能对应的PTE通道,使用该接口使能PTE通道。PTE必须使能通道有效
void PTE_ChxEnable(uint32_t items);关闭对应的PTE通道使能
void PTE_ChxDisable(uint32_t items);获取当前的通道使能状态
uint32_t PTE_ChxGetEnableState(void);使能PTE分组,调用该接口相当于一直向整个GROUP所有通道发送执行对应任务的信号。
void PTE_SetTaskChxGroupEN(PTEC_ChannelGroup SetChannelGroup)关闭PTE分组,关闭向整个GROUP发送所有通道的执行任务信号。
void PTE_SetTaskChxGroupDIS(PTEC_ChannelGroup SetChannelGroup)使能对分组对指定通道事件的订阅
void PTE_SetTaskSubChxGroupEn(PTEC_ChannelGroup SetChannelGroup,uint32_t SetSubChannel);关闭对分组对指定通道事件的订阅
void PTE_SetTaskSubChxGroupDis(PTEC_ChannelGroup SetChannelGroup,uint32_t SetSubChannel);设置多个PTE通道映射到某个PTE分组
void PTE_SetTaskChxGroup(PTEC_ChannelGroup SetChannelGroup,uint32_t SetChannel);21.2.3 使用示例
下面代码将以GPIOTE模块初始化一个IO检测这个IO的电平状态,触发另外三个GPIOTE模块翻转三个IO的电平状态这个应用场景为例,展示GPIOTE模块和PTE模块的使用。
GPIO 使用 CHANNEL1接收IO7触发事件,IO需要设置为输入模式,开启GPIO中断使能,外部IO上拉,设置中断模式为下降沿触发,使用GPIOTE的0 2 3三个通道映射GIO_GPIO_24、25、26三个IO,当GPIO7触发下降沿事件时,GPIOTE的0 2 3三个通道会翻转GIO_GPIO_24、25、26三个IO的电平状态。
void pte_gpiote_test(void)
{
SYSCTRL_ClearClkGate(SYSCTRL_ITEM_APB_GPIO0);
SYSCTRL_ClearClkGate(SYSCTRL_ITEM_APB_GPIO1);
SYSCTRL_ClearClkGate(SYSCTRL_ITEM_APB_GPIOTE);
PINCTRL_Pull(GIO_GPIO_7, PINCTRL_PULL_UP);
GIO_ConfigIntSource(GIO_GPIO_7, GIO_INT_EN_LOGIC_LOW_OR_FALLING_EDGE, GIO_INT_EDGE);
GPIOTE_Configuration(GPIOTE_CHANNEL_0,GPIOTE_CHANNEL_TASK, GIO_GPIO_24, 0);
GPIOTE_Configuration(GPIOTE_CHANNEL_2,GPIOTE_CHANNEL_TASK, GIO_GPIO_25, 0);
GPIOTE_Configuration(GPIOTE_CHANNEL_3,GPIOTE_CHANNEL_TASK, GIO_GPIO_26, 0);
GPIOTE_Configuration(GPIOTE_CHANNEL_1,GPIOTE_CHANNEL_EVENT, GIO_GPIO_7, 0);
PTE_ConfigTask(PTE_GPIOTE_MODULE, PTE_TASK_GPIOTE_TOGGLE_CH0, PTE_CHANNEL_0, 1);
PTE_ConfigTask(PTE_GPIOTE_MODULE, PTE_TASK_GPIOTE_TOGGLE_CH2, PTE_CHANNEL_0, 1);
PTE_ConfigTask(PTE_GPIOTE_MODULE, PTE_TASK_GPIOTE_TOGGLE_CH3, PTE_CHANNEL_0, 1);
PTE_ConfigEvent(PTE_GPIOTE_MODULE, PTE_EVENT_GPIOTE_CH1_INPUT_INT, PTE_CHANNEL_0, 1);
PTE_ChxEnable(1 << PTE_CHANNEL_0);
}
void main(void)
{
pte_gpiote_test();
while(1);
}使用该代码测试,按下GPIO7对应的按键,GPIO24、GPIO25和GPIO26会翻转状态,LED灯会亮起和熄灭。