正点原子[第二期]Linux之ARM(MX6U)裸机篇学习笔记-18讲 高精度延时定时器GPT

前言:

本文是根据哔哩哔哩网站上“正点原子[第二期]Linux之ARM(MX6U)裸机篇”视频的学习笔记,在这里会记录下正点原子 I.MX6ULL 开发板的配套视频教程所作的实验和学习笔记内容。本文大量引用了正点原子教学视频和链接中的内容。

引用:

正点原子IMX6U仓库 (GuangzhouXingyi) - Gitee.com

《【正点原子】I.MX6U嵌入式Linux驱动开发指南V1.5.2.pdf》

正点原子资料下载中心 — 正点原子资料下载中心 1.0.0 文档

正文:

本文是 “正点原子[第二期]Linux之ARM(MX6U)裸机篇--第18 讲” 的读书笔记。第87讲主要是介绍I.MX6U处理器的的GPT(通用目的定时器)来实现高精度延时。本节将参考正点原子的视频教程第18讲和配套的正点原子开发指南文档进行学习。

0. 概述

延时函数是很常见的API函数,在前面的实验中我们使用循环来实现延时函数,但是使用循环来实的延时函数不准确,误差会很大。虽然使用到延时函数的地方精度要求都不会很严格(要求严格的话就使用硬件定时器了),但是延时函数肯定是越精确越好,这样延时函数就可以使用在某些对时序要求严格的场合。本章我们就来学习一下如何使用硬件定时器来实现高精度延时。

1. 高精度延时简介

1.1 GPT定时器简介

学过STM32的同学应该知道,在使用STM32的时候可以使用 SYSTICK 来实现高精度延时。I.MX6U 没有 SYSTICK 定时器,但是I.MX6U有其他定时器啊,比如第十八章讲解的EPIT定时器。本章我们使用 I.MX6U 的 GPT (General Purpose Timer)来四坏心眼高精度延时,顺便学习一下GPT定时器,GPT定时器全程为 Gerernal Purpose Timer。

GPT定时器是一个32位向上定时器(也就是说从0x0000_0000向上递增计数),GPT定时器也可以跟一个值进行比较,当计数器值和这个值相等的话就发生比较事件,产生比较中断。GPT定时器有一个12位分频器,可以对GPT定时器的时钟源进行分频,GPT定时器特性如下:

  1. 一个可选时钟源的32位向上计数器
  2. 两个输入捕获通道,可以设置触发方式
  3. 三个比较输出通道,可以设置输出方式
  4. 可以生成捕获中断,比较中断和溢出中断
  5. 计数器可以运行在重新启动(restart)和(自由运行)free-run模式

GPT定时器的可选时钟源如下图所示

从上图中可以看出一共有五个时钟源,分别为:ipg_clk_24M,GPT_CLK(外部时钟),ipg_clk,ipg_clk_32k,ip_clk_higrfreq。本例程选择ipg_clk作为GPT的使用源,ipg_clk=66MHz。

GPT定时器的结构如下图所示:

其中各部分含义如下

序号描述
1此部分为GPT定时器的时钟源,前面已经说过了,本章例程选择ipg_clk作为GPT定时器的时钟源。ipg_clk=66MHz
2此部分为12位分频器,对时钟源进行分频处理,可设置0~4095,分别对应1~4096分频。
3经过分频的时钟源进入到GPT定时器内部的32位计数器。GPT定时器的计数器是32位向上计数器(即从0x00000000向上递增)
4,5这两部分是GPT的两路输入捕获通道,本章不讲解GPT的输入捕获
6此部分为输出比较寄存器,一共有三路输出比较,因此有三个输出比较寄存器,输出比较寄存器是32位的
7此部分为输出比较中断,三路输出比较中断,当计数器里面的值和比较寄存器里面的值相等就会触发输出比较中断。

GPT定时器有两种工作模式:重新启动(restart)模式和自由运行(free-run)模式,这两个工作模式区别如下:

  • 重新启动(restatr)模式:当GPTx_CR(x=1,2) 寄存器的FRR位清零的时候 GPT 工作在此模式。在此模式下,当计数值和比较寄存器中的值相等的话计数值就会清零,然后重新从0x00000000 开始向上计数,之后比较通道1才有此工作模式!向比较通道1的比较寄存器写入任何值都会复位GPT计数器。对于其他两路的比较通道(通道2和3),当比较事件发生以后不会复位计数器。
  • 自由运行(free-run)模式:当GPTx_CR(x=1,2) 寄存器的FRR位置1的时候GPT工作在此模式下,此模式下适用于所有三个比较通道,当比较事件发生以后不会复位计数器,而是继续计数,直到计数值为0xFFFFFFFF,然后重新回滚到 0x00000000。

接下来看一下GPT定时器比较重要的几个寄存器,第一个就是GPT的配置寄存器 GPTx_CR,此寄存器结构如下图:

bit位描述
SWR bit[15]复位GPT定时器,向此位写1就可以复位GPT定时器,当GPT复位完成以后此位会自动清零。
FRR bit[9]运行模式选择,当此位为0时比较通道1工作在重新启动模式。当此位为1的时候所有的三个比较通道均工作在自由运行模式(free-run)
CLK_SRC bit[8:6]GPT定时器的时钟源选择位,当为0的时候时钟源关闭,为1的时候选择ipg_clk作为时钟源,为 2 的时候选择 ipg_clk_highfreq 为时钟源;为 3 的时候选择外部时钟为时钟源;为 4 的时候选择 ipg_clk_32k 为时钟源;为 5 的时选择 ip_clk_24M 为时钟源。本章例程选择 ipg_clk 作为 GPT 定时器的时钟源,因此此位设置位 1(0b001)
ENMODE bit[1]GPT使能模式,此位为0的时候如果关闭GPT定时器,计数器寄存器保存定时器关闭时候的计数值,为1的时候如果关闭GPT定时器,计数器寄存器就会清零。
EN bit[0]GPT使能位,为1的时候使能GPT定时器,为0的时候关闭GPT定时器。

接下来看一下GPT定时器的分频寄存器GPTx_PR,此寄存器的结构如下图所示:

寄存器GPTx_PR我们用到的重要位就一个:PRESCALER (bit[11:0]),这就是12位分频值,可设置0~4095,分别对应1~4096分频。

接下来看一下GPT定时器的状态寄存器 GPTx_SR,此寄存器的结构如下图所示:

寄存器GPTx_SR重要位如下:

描述
ROV bit[5]回滚标志位,当计数值从 0xFFFFFFFF 回滚到 0x00000000 的时候此位置1
IF2~IF1 bit[4:3]输入捕获标志位,当输入捕获事件发生以后此位置1,一共有两路输入捕获通道。如果使用输入捕获中断的话需要再中断处理函数中清除此位。
OF3~OF1 bit[2:0]输出比较中断标志位,当输出比较中断事件发生以后此位置1,一共有三路输出比较通道。如果使用输出比较中断的话需要再中断处理函数中清除此位。

接下来看一下GPT定时器的计数寄存器GPTx_CNT,这个寄存器保存着GPT定时器的当前计数值,最后看一下GPT定时器的输出比较寄存器 GPTx_OCR ,每个输出比较通道对应一个输出比较寄存器,因此一个GPT定时器有三个OCR寄存器,它们的作用是相同的。以输出比较通道1为例,器输出比较寄存器为 GPTx_OCR1 ,这是一个32为寄存器,用于存放32位的比较值。当计数值和寄存器 GPTx_OCR1 中的值相等就会产生比较事件,如果省内了比较中断的话就会触发相应的中断。

关于 GPT 的寄存器就介绍到这里,关于这些寄存器详细的描述,请参考《I.MX6ULL 参考手册》第 1432 页的 30.6 小节。

1.2 定时器实现高精度延时的原理

高精度延时函数的实现肯定是要借助硬件定时器,前面说了本章实验使用GPT定时器来实现高精度延时。如果设置GPT定时器的时钟源为 ipg_clk=66MHz,设置66分频,那么进入GPT定时器的最终时钟频率就是 66MHz/66=1MHz,周期为 1us(微秒)。GTP的计数器每计一个数就表示“过去”了1us。如果10个计数就表示“过去”了10us。通过读取寄存器GPTx_CNT中的值就知道计数个数,比如现在要延时100us,那么进入延时函数以后记录下寄存器GPTx_CNT的值为200,当GPTx_CNT中的值为300的时候就表示100us过去了,也就是延时结束。GPTx_CNT是个32为寄存器,如果时钟为1MHz的话,GPTx_CNT最多可以实现

0xFFFFFFFF=4,294,967,295 us = 4294s = 72min。

也就是说72分钟以后 GPTx_CNT 寄存器就会回滚到 0x00000000,也就是溢出,所以在延时函数中需要处理溢出的情况。关于定时器实现高精度延时的原理就讲解到这里,原理韩式很简单的,高精度延时的实现步骤如下:

  1. 设置GPT1定时器
    首先设置GPT1_CR寄存器的 SWR(bit15) 位来复位寄存器 GPT1。复位完成以后设置寄存器 GPT1_CR 寄存器的 CLKSRC (bit8:6) ,选择 GPT1 的时钟源为 ipg_clk。设置定时器 GPT1的工作模式。
  2. 设置GPT1的分频值
    设置寄存器 GPT1_PR 寄存器的 PRESCALAR (bit:11:0)位,设置分频值。
  3. 设置GPT1的比较值
    如果要使用GPT1的输出比较中断,那么GPT1的输出比较寄存器 GPT1_OCR1 的值可以根据所需的中断时间来设置。本例程不使用比较输出中断,所以将  GPT1_COR1 设置为最大值,即: 0xFFFFFFFF。
  4. 使能 GPT1 定时器
    设置好GPT1定时器以后就可以使能了,设置GPT1_CR的EN(bit0)位为1来使能 GPT1定时器。
  5. 编写延时函数
    GPT1定时器已经开始运行了,可以根据前面介绍的高精度延时函数原理来编写延时函数,针对us 和 ms 延时分别编写两个延时函数。

1.3 硬件原理分析

 本实验用到的资源如下

  1. 一个LED灯:LED0
  2. 定时器GPT1

本实验通过高精度延时函数来控制LED0的闪烁,可以通过示波器来观察LED0的控制IE输出波形,通过波形的频率或者周期来判断延时函数的精度是否正常。

2. 高精度延时函数程序编写

基于GPT定时器的高精度延时函数程序源码如下,参考正点原子的示例程序:

bsp/bsp_dealy.c 

#include "bsp_delay.h"
#include "bsp_led.h"
#include "bsp_beep.h"
#include "bsp_int.h"void short_delay(volatile unsigned int n)
{while(n--){;}
}/* sleep 1ms */
void delay(volatile unsigned int m){while(m--){short_delay(0x7ff);}
}#include "bsp_delay.h"
#include "bsp_int.h"
#include "bsp_led.h"
#include "bsp_beep.h"/** @description 	: 延时初始化* @param  			: 无* @return 			: 无*/
void delay_init(void)
{/* GPT1_CR 清零 */GPT1->CR = 0;/* GPT1->CR 软件复位 */GPT1->CR |= (1 << 15);while(((GPT1->CR >> 15) & 0x01));GPT1->CR |= (1 << 6);		/* CLKSRC bit[8:6], 1 时钟源选择ipg_clk */GPT1->CR |= (1 << 1);		/* ENMODE bit[1], 1 reset mode *//* FRR bit[9], 0 reset mode *//* GPT1_PR 分频 */GPT1->PR &= ~(0xFFF << 0);GPT1->PR |= (65 << 0);		/* 66Mhz/66=1MHz *///GPT1->OCR[0] = 1000000/10;	/* GPT1输出比较通道1 */GPT1->OCR[0] = 0xFFFFFFFF;		/* GPT1输出比较通道1 */#if 0GPT1->IR &= ~(1 << 0);GPT1->IR |= (1 << 0);		/* 使能GPT1输出比较通道1中断 */GIC_EnableIRQ(GPT1_IRQn);system_irqhandler_register(GPT1_IRQn, gpt_system_irq_handler_t, NULL);gpt_irq_enable(GPT1);		/* GPT1 输出比较中断使能 */
#endifgpt_enable(GPT1);			/* GPT1 enable*/
}/** @description 	: 使能GPT输出比较通道1中断。* @param – base 	: GPT寄存器* @return 			: 无*/
void gpt_enable(GPT_Type *base)
{base->CR |= (1 << 0);
}/** @description 	: 使能GPT输出比较通道1中断。* @param – base 	: GPT寄存器* @return 			: 无*/
void gpt_disable(GPT_Type *base)
{base->CR &= ~(1 << 0);
}/** @description 	: 使能GPT输出比较通道1中断。* @param – base 	: GPT寄存器* @return 			: 无*/
void gpt_irq_enable(GPT_Type *base)
{base->IR |= (1 << 0);
}/** @description 	: 禁用GPT输出比较通道1中断。* @param – base 	: GPT寄存器* @return 			: 无*/
void gpt_irq_disable(GPT_Type *base)
{base->IR &= ~(1 << 0);
}/** @description 	: 清除中断标志位。* @param – base 	: GPT寄存器* @return 			: 无*/
void gpt_cleanIrqFlag(GPT_Type *base)
{base->SR |= (1 << 0);
}/** @description 	: 清除中断标志位。* @param – base 	: GPT寄存器* @return 			: 无*/
void gpt_restart_timer(GPT_Type *base, int value)
{base->CR &= ~(1 << 0);		/* 关闭GPT定时器 */base->OCR[0] = value;base->CR |= (1 << 0);		/* 启用GPT定时器 */
}/** @description 		: GPT中断处理函数。* @param – irq 		: 中断ID* @param – userparam 	: 用户注册参数* @return 				: 无*/
void gpt_system_irq_handler_t(IRQn_Type irq, void *userparam)
{static int led_state = 0;if(GPT1->SR & (1 << 0)){led_state = !led_state;led_switch(LED_0, led_state);beep_switch(led_state);//gpt_restart_timer(GPT1, 1000000/10);/* 清除中断标志位 */gpt_cleanIrqFlag(GPT1);}
}/** @description 		: 高精度延时函数微秒,基于GPT定时器* @param – us 			: 延时微秒数* @return 				: 无*/
void delay_us(int time_us)
{int oldvalue = 0;int newvalue = 0;int value = 0;while(1){newvalue = GPT1->CNT;if(newvalue != oldvalue){if(oldvalue <  newvalue){value += 0xFFFFFFFF - oldvalue + newvalue;}else{value += newvalue - oldvalue;}oldvalue = newvalue;if(value >= time_us)break;}}
}/** @description 		: 高精度延时函数毫秒,基于GPT定时器* @param – us 			: 延时毫秒数* @return 				: 无*/
void delay_ms(int time_ms)
{int i = 0;for(i=0; i<time_ms; i++){delay_us(1000);}
}

定义了 delay_us() 和 dalay_ms() 分别来实现微秒(us) 和 毫秒(ms)级别的延时。

3. 编译烧写SD卡验证实验结果

译修改主频后源码烧录SD卡验证本节的基于GPT定时器的高精度延时函数是否生效。预期烧录SD卡后正点原子I.MX6ULL ALPHA/Mini 开发板后,开发板按照指定的延时时间周期性的控制蜂鸣器的鸣叫和LED的闪亮。

我本地验证的结果是基于GPT定时器的高精度延时实验结果正常,开发板按照指定的延时时间周期性的控制蜂鸣器的鸣叫和LED的闪亮。

4. 总结和实验遇到的问题记录

4.1 问题1:高精度延时函数delay_us() 微秒延时函数的源码需要优化,减少不必要的指令和对寄存器的读取。

如图是3个版本的 dealy_us() 微秒延时延时函数的源码版本,第一个版本源码V1是我自己写的,V2 版本和 V3 版本是参考正点原子的示例源码和视频教程进行优化的两个版本,V3版本是我们最终需要的delay_us()实现微秒级延时函数的最终版本。

下面分析一下 V1,V2,V3版本的 delay_us() 函数优化了哪些?以及为什么需要做这样的优化。

  • V1->V2版本的优化,主要是减少了每次循环是对寄存器GPTx->CNT寄存器的读取次数。
    优化v1->v2:每次循环的时候只读一次寄存器GPT->CNT 的值,读取到中间变量newcnt 里面,这样可以减少读取寄存器次数,并且防止在运行过程中CPT->CNT计数器值发生了增长。
  • V2->V3的优化,主要是减少了每次循环时非必要的加减数学运算以及对oldcnt的更新。
    优化V2->V3:每次执行到循环的时候判断newcnt 是否等于oldcnt。因为CPU的执行速度要快于GPT定时器的主频,每次CPU再次执行循环的时候,很可能GPTx->CNT 计数器的值并没有修改。所以每次循环的时候先判断 newcnt 是否等于 oldcnt。

需要注意这里实现高精度延时函数时源码的写法,这里需要优化掉不必要的寄存器读取操作,和不必要的加减数学运算和更新。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/329997.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

前端 CSS 经典:元素倒影

前言&#xff1a;好看的元素倒影&#xff0c;可以通过-webkit-box-reflect 实现。但有兼容问题&#xff0c;必须是 webkit 内核的浏览器&#xff0c;不然没效果。但是好看啊。 效果图&#xff1a; 代码实现&#xff1a; <!DOCTYPE html> <html lang"en"&g…

VUE3好看的酒网站模板源码

文章目录 1.设计来源1.1 首页界面1.2 十大名酒界面1.3 名酒新闻界面1.4 联系我们界面1.5 在线留言界面 2.效果和结构2.1 动态效果2.2 代码结构 3.VUE框架系列源码4.源码下载 作者&#xff1a;xcLeigh 文章地址&#xff1a;https://blog.csdn.net/weixin_43151418/article/detai…

【C++初阶】—— 类和对象 (下)

&#x1f4dd;个人主页&#x1f339;&#xff1a;EterNity_TiMe_ ⏩收录专栏⏪&#xff1a;C “ 登神长阶 ” &#x1f339;&#x1f339;期待您的关注 &#x1f339;&#x1f339; 类和对象 1. 运算符重载运算符重载赋值运算符重载前置和后置重载 2. 成员函数的补充3. 初始化列…

Java中String类常用方法

写笔记记录自己的学习记录以及巩固细节 目录 1.String类的常用方法 1.1 字符串构造 1.2 String对象的比较 1.2.1 比较两个字符串是否相等 1.2.2 比较两个字符串的大小 1.3 字符串查找 1.4 字符串的转化 1.4.1 字符串转整数 1.4.2 字符串转数字 1.4.3 大小写的转换 1…

IT革命浪潮:技术革新如何改变我们的生活与工作

一、技术革新与行业应用 当前的IT行业正处于前所未有的技术革新阶段。其中&#xff0c;量子计算和虚拟现实是两项引人注目的技术。 量子计算&#xff1a;量子计算以其超越传统计算的潜力&#xff0c;正在逐步从理论走向实践。在材料科学、药物研发和气候模型等复杂计算领域&a…

利用kubeadm安装k8s集群 以及跟harbor私有仓库下载镜像

目录 环境准备 master&#xff08;2C/4G&#xff09; 192.168.88.3 docker、kubeadm、kubelet、kubectl、flannel node01&#xff08;2C/2G&#xff09; 192.168.88.4 docker、kubeadm、kubelet、kubectl、flannel node02&#xff08;…

Ansible自动化运维中的file文件模块模块应用详解

作者主页&#xff1a;点击&#xff01; Ansible专栏&#xff1a;点击&#xff01; 创作时间&#xff1a;2024年5月21日15点21分 &#x1f4af;趣站推荐&#x1f4af; 前些天发现了一个巨牛的&#x1f916;人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xf…

向npm发布自己写的vue组件,使用vite创建项目

向npm发布自己写的vue组件&#xff0c;使用vite创建项目 创建项目 pnpm create vite输入项目名称 由于我的组件是基于 ant-design-vue和vue的&#xff0c;需要解析.vue文件&#xff0c;我又安装了下面4个。 然后执行 pnpm i安装依赖 vite.config.ts import { defineC…

linux系统——ps命令的两种参数模式

ps命令后面接参数时&#xff0c;有“—”符号与无此符号&#xff0c;在具体实现功能上有很大区别 能够清晰表达进程之间层级关系

前端菜鸡,对于35+程序员失业这个事有点麻了

“经常看到30岁程序员失业的新闻&#xff0c;说实话&#xff0c;有点麻。目前程序员供求关系并未失衡&#xff0c;哪怕是最基础的前端或者后台、甚至事务型的岗位也是足够的。 事实上&#xff0c;现在一个开出的岗位要找到一位尽职尽责能顺利完成工作的程序员并不是一件那么容…

从零到一:手把手教你将项目部署上线-环境准备

部署步骤 引言1.Java环境配置2.ngnix安装好书推荐 引言 将自己的项目从本地开发环境顺利部署上线&#xff0c;是每个开发者必经的里程碑。今天&#xff0c;我们就从零开始&#xff0c;一步一步教你如何将手中的项目部署到线上&#xff0c;让全世界见证你的创造力。 首先&#x…

必应bing国内广告开户首充和开户费是多少?

微软必应Bing作为国内领先的搜索引擎之一&#xff0c;其广告平台凭借其精准的投放、高效的数据分析和广泛的用户覆盖&#xff0c;已成为众多企业的首选。 根据最新政策&#xff0c;2024年必应Bing国内广告开户预充值金额设定为1万元人民币起。这一调整旨在确保广告主在账户初始…

计算机操作系统总结(1)

1操作系统的概念&#xff08;定义&#xff09;功能和目标 (1)什么是操作系统&#xff1f; &#xff08;2&#xff09;操作系统的功能和目标—作为系统资源的管理者 &#xff08;3&#xff09;操作系统的功能和目标—向上层提供方便易用的服务 &#xff08;4&#xff09;操作系…

vue从入门到精通(四):MVVM模型

一,MVVM MVVM&#xff08;Model–view–viewmodel&#xff09;是一种软件架构模式。MVVM有助于将图形用户界面的开发与业务逻辑或后端逻辑&#xff08;数据模型&#xff09;的开发分离开来。详见MVVM 二,Vue中的MVVM Vue虽然没有完全遵循 MVVM 模型&#xff0c;但是 Vue 的设…

Xcode代码格式化SwiftFormat安装使用,以及不生效问题

官方仓库地址&#xff1a;GitHub - nicklockwood/SwiftFormat: A command-line tool and Xcode Extension for formatting Swift code 安装SwiftFormat 有两种安装方式&#xff0c;两种方式都可以&#xff0c;二选一即可&#xff1a; 第一种使用brew&#xff0c;如果已经使用…

启动docker报错:Failed to listen on Docker Socket for the API.

说明&#xff1a; 1、安装部署docker完成后&#xff0c;启动docker报错&#xff1a;Failed to listen on Docker Socket for the API&#xff0c;如下图所示&#xff1a; 2、将SocketGroupdocker更改成&#xff1a;SocketGrouproot即可 一、解决方法&#xff1a; 1、执行命令…

文件传输服务应用1——java集成smb2/3实现文件共享方案详细教程和windows共享服务使用配置

在实际项目开发过程中&#xff0c;读取网络资源或者局域网内主机的文件是必要的操作和需求。而FTP&#xff08;文件传输协议&#xff09;和SMB&#xff08;服务器消息块&#xff09;是两种最为常见的文件传输协议。它们各自在文件传输领域拥有独特的优势和特点&#xff0c;但同…

MySQL进阶 日志结尾以及8.0新特性

日志结尾 前面我们聊了mysql的undo日志,redo日志,binlog等等,也从一条update语句来分析了一下日志的执行思路以及版本控制是怎么回事,四大特性是怎么实现的等等 今天我们来说说最后一个错误日志 其实用处不大 因为对我们开发人员来说基本上是没有权限来查看错误日志的 一般…

vlan综合实验

一&#xff0c;实验拓扑&#xff1a; 二&#xff0c;实验需求&#xff1a; 1、pc1和pc3所在接口为access;属于vlan 2;P可以骄问pcepces不的一段;其中pc2可以访问pc4/pc5/pc6; 2、pc1/pc3与pc2/pc4/pc5/pc6不在同一网段; 3、所有pc通过DHCP获取Ip地址&#xff0c;且pc1/pc3可以…

BGP选路规则实验

实验拓扑及要求如下 注意&#xff1a; 在完成要求时&#xff0c;默认区域内IGP搭建完成&#xff0c;IBGP和EBGP的对等体关系建立完成 结果演示如下 IBGP内部搭建&#xff1a;使用OSPF IBGP与EBGP对等体建立 要求一&#xff1a;PreVal策略 PV属性默认值为0&#xff0c;规则是…