一、GPIO
GPAPUD寄存器
在所选GPIO端口A引脚上配置内部上拉电阻。每个GPIO引脚对应这个寄存器中的一个位。
0启用指定引脚的内部上拉。GPIO12-GPIO31(默认复位后是禁用)
1禁用指定引脚的内部上拉。GPIO0-GPIO11(默认复位后是启用)。
CAN例程里面:
GpioCtrlRegs.GPAPUD.bit.GPIO30 = 0; // Enable pull-up for GPIO30 (CANRXA)
GpioCtrlRegs.GPAPUD.bit.GPIO31 = 0; // Enable pull-up for GPIO31 (CANTXA)
GPAQSEL1寄存器
GPAQSEL2寄存器
每个GPIO的这类寄存器有如下四种状态:
00:只与系统时钟SYSCLKOUT同步
01或者10:此模式中,当与系统时钟同步后,输入信号在输入值改变前需要满足一定数量的时钟周期的宽度要求。
11:不同步,此模式用于不同步外设
CAN例程里面:
GpioCtrlRegs.GPAQSEL2.bit.GPIO30 = 3; // Asynch qual for GPIO30 (CANRXA)
GPAMUX1、GPAMUX2、GPBMUX1、GPBMUX2寄存器
共58个GPIO,每个GPAMUXx.GPIOy寄存器有如下4种状态,
00:通用的输入输出口
01:外设选择1
10:外设选择2
11:外设选择3
注意:上面所示的寄存器不是F28035的,F28035只有44个GPIO。
CAN例程里面:
GpioCtrlRegs.GPAMUX2.bit.GPIO30 = 1; // Configure GPIO30 for CANRXA operation
GpioCtrlRegs.GPAMUX2.bit.GPIO31 = 1; // Configure GPIO31 for CANTXA operation
GPADIR寄存器
当指定引脚在相应的GPAMUX1或GPAMUX2寄存器中配置为GPIO时,控制GPIO口A引脚的方向。
0配置GPIO引脚为输入。(默认)
1配置GPIO引脚为输出。GPADAT输出锁存器当前的值在引脚上驱动。
在将引脚从输入更改为输出之前,要初始化GPADAT锁存器,请使用GPASET、GPACLEAR和GPATOGGLE寄存器。
GPBDIR寄存器
1)使用GPADAT/GPBDAT寄存器对GPIO引脚进行输出。
void Gpio_example1(void)
{
// Example 1:
// Toggle I/Os using DATA registers
for(;;)
{
GpioDataRegs.GPADAT.all =0xAAAAAAAA;
GpioDataRegs.GPBDAT.all =0x0000000A;
delay_loop();
GpioDataRegs.GPADAT.all =0x55555555;
GpioDataRegs.GPBDAT.all =0x00000005;
delay_loop();
}
}
GPADAT寄存器
每个bit对应一个GPIO A引脚(GPIO0-GPIO31),如图65所示。
读取0表示引脚当前的状态是低的,与引脚配置的模式无关。
如果在适当的GPAMUX1/2和GPADIR寄存器中将引脚配置为GPIO输出,写入0将强制输出为0;否则,该值被锁存但不用于驱动引脚。
1读1表示引脚当前处于高状态,与引脚配置的模式无关。
写入1将强制输出1,如果该引脚在适当的GPAMUX1/2和GPADIR寄存器中配置为GPIO输出;否则,该值被锁存但不用于驱动引脚。
GPBDAT寄存器
2)使用GPASET/GPBSET和GPACLEAR/GPBCLEAR寄存器
void Gpio_example2(void)
{
// Example 2:
// Toggle I/Os using SET/CLEAR registers
for(;;)
{
GpioDataRegs.GPASET.all =0xAAAAAAAA;
GpioDataRegs.GPACLEAR.all =0x55555555;
GpioDataRegs.GPBSET.all =0x0000000A;
GpioDataRegs.GPBCLEAR.all =0x00000005;
delay_loop();
GpioDataRegs.GPACLEAR.all =0xAAAAAAAA;
GpioDataRegs.GPASET.all =0x55555555;
GpioDataRegs.GPBCLEAR.all =0x0000000A;
GpioDataRegs.GPBSET.all =0x00000005;
delay_loop();
}
}
GPASET、GPACLEAR、GPATOGGLE寄存器
如图68所示,每个GPIO端口A引脚(GPIO0-GPIO31)对应该寄存器中的一个位。
0忽略对0的写操作。这个寄存器总是读回0。
写入1强制各自的输出数据锁存到高。
如果引脚被配置为GPIO输出,那么它将被高电平驱动。
如果引脚未配置为GPIO输出,则锁存器设置为高电平,但引脚不被驱动。
如图68所示,每个GPIO端口A引脚(GPIO0-GPIO31)对应该寄存器中的一个位。
0忽略对0的写操作。这个寄存器总是读回0。
写入1强制各自的输出数据锁存到低。
如果引脚被配置为GPIO输出,那么它将被驱动为低电平。
如果引脚没有配置为GPIO输出,那么锁存器会被清除,但引脚不会被驱动。
如图68所示,每个GPIO端口A引脚(GPIO0-GPIO31)对应该寄存器中的一个位。
0忽略对0的写操作。这个寄存器总是读回0。
写入1强制各自的输出数据锁存器从其当前状态切换。如果引脚被配置为GPIO输出,那么它将被驱动到与当前状态相反的方向。如果引脚未配置为GPIO输出,则闩锁被切换,但引脚未被驱动。
二、PIE 配置和控制寄存器
PIE向量表(参见表109)由一个256 x 16的SARAM块组成,如果没有使用PIE块,它也可以用作RAM(仅在数据空间中)。重置时,PIE向量表的内容未定义。
CPU为INT1到INT12修复中断优先级。PIE控制每组8个中断的优先级。例如,如果INT1.1和INT8.1同时发生,两个中断都由PIE块同时呈现给CPU, CPU首先服务INT1.1。如果INT1.1和INT1.8同时出现,则先将INT1.1发送给CPU,然后再将INT1.8发送给CPU。中断优先级在中断处理的矢量获取部分执行。
当PIE被启用时,TRAP #1到TRAP #12或INTR INT1到INTR INT12指令将程序控制传递给与PIE组中第一个向量对应的中断服务例程。例如:TRAP #1从INT1.1获取向量,TRAP #2从INT2.1获取向量,以此类推。类似地,如果设置了相应的中断标志,则OR IFR, #16位操作将导致从INTR1.1到INTR12.1位置获取向量。所有其他TRAP、INTR、OR IFR、#16位操作都从相应的表位置获取向量。矢量表受EALLOW保护。
在表108中96个可能的MUXed中断中,目前使用了43个中断。剩余的中断为将来的设备保留。如果在PIEIFRx级别启用了这些保留中断,则可以将它们用作软件中断,前提是组内没有任何中断被外设使用。否则,在修改PIEIFR时,由于意外地清除了外设的标志,来自外设的中断可能会丢失。
总的来说,当保留中断可以用作软件中断时,有两种安全的情况:
1. 组内没有外设在断言中断。
2. 没有为该组分配外围中断。例如,PIE组11和12没有任何外设连接到它们。
连接到PIE模块的外设和外部中断分组如表108所示。表中的每一行显示了被复用到一个特定CPU中断的8个中断。整个PIE向量表,包括MUXed和非MUXed中断,如表109所示。
(1) 在96 个可能的中断中,有一些是不使用的。这些中断是为以后的器件所保留的。如果它们在PIEIFRx 级被启用并且这个组中的中断没有
一个被外设使用,这些中断可被用作软件中断。否则,在意外地清除它们的标志同时修改PIEIFR 的情况下,来自外设的中断也许会丢
失。总的来说,在两个安全情况下,被保留的中断可被用作软件中断:
• 组内没有外设使中断有效。
• 没有外设中断被分配给组(例如,PIE 组7)
PIECTRL寄存器
PIEVECT:这些位表示从PIE向量表中获取向量的地址。地址的最低有效位被忽略,只显示地址的1到15位。您可以读取矢量值来确定哪个中断生成了矢量获取。
例如:如果PIECTRL = 0x0D27,则获取地址0x0D26(非法操作)的向量。
ENPIE:启用从PIE矢量表中获取矢量。
注意:即使启用了重置向量,也不会从PIE中获取。这个向量总是从引导ROM中获取。
0:如果该位设置为0,则关闭PIE块,并从boot ROM的CPU矢量表中获取向量,即使关闭了PIE块,所有的PIE块寄存器(PIEACK, PIEIFR, PIEIER)都可以被访问。
1:当ENPIE设置为1时,除reset外的所有向量都从PIE向量表中获取。重置向量总是从引导ROM中获取。
CAN例程里面:
// Disable the PIE
PieCtrlRegs.PIECTRL.bit.ENPIE = 0;
PIEIERx寄存器
有12个PIEIER寄存器,一个用于PIE模块(INT1-INT12)使用的每个CPU中断。
这些寄存器位分别在一个组中启用中断,并且行为非常像核心中断6启用寄存器。将位设置为1就可以为各自的中断提供服务。将位设置为0将禁用中断服务。X = 1到12。INTx表示CPU INT1 ~ INT12
CAN例程里面:
// Clear all PIEIER registers:
PieCtrlRegs.PIEIER1.all = 0;
PieCtrlRegs.PIEIER2.all = 0;
PieCtrlRegs.PIEIER3.all = 0;
PieCtrlRegs.PIEIER4.all = 0;
PieCtrlRegs.PIEIER5.all = 0;
PieCtrlRegs.PIEIER6.all = 0;
PieCtrlRegs.PIEIER7.all = 0;
PieCtrlRegs.PIEIER8.all = 0;
PieCtrlRegs.PIEIER9.all = 0;
PieCtrlRegs.PIEIER10.all = 0;
PieCtrlRegs.PIEIER11.all = 0;
PieCtrlRegs.PIEIER12.all = 0;
PIEIFRx寄存器
这些寄存器位指示当前中断是否处于活动状态。它们的行为非常像CPU中断标志寄存器。当中断处于活动状态时,设置相应的寄存器位。当中断被处理或通过向寄存器位写入0来清除该位。也可以读取这个寄存器来确定哪些中断是活动的或挂起的。X = 1到12。INTx表示CPU INT1到INT12,在中断处理的中断向量提取部分,PIEIFR寄存器位被清除。硬件对PIEIFR寄存器的访问优先于CPU。
CAN例程里面:
// Clear all PIEIFR registers:
PieCtrlRegs.PIEIFR1.all = 0;
PieCtrlRegs.PIEIFR2.all = 0;
PieCtrlRegs.PIEIFR3.all = 0;
PieCtrlRegs.PIEIFR4.all = 0;
PieCtrlRegs.PIEIFR5.all = 0;
PieCtrlRegs.PIEIFR6.all = 0;
PieCtrlRegs.PIEIFR7.all = 0;
PieCtrlRegs.PIEIFR8.all = 0;
PieCtrlRegs.PIEIFR9.all = 0;
PieCtrlRegs.PIEIFR10.all = 0;
PieCtrlRegs.PIEIFR11.all = 0;
PieCtrlRegs.PIEIFR12.all = 0;
InitPieVectTable();
//这个函数的作用:
用指向shell中断服务例程(ISR)的指针初始化PIE向量表。
这将填充整个表,即使本例中没有使用中断。这对于调试非常有用
//这个函数初始化PIE向量表到一个已知的状态。
//该函数必须在启动后执行。
不要写前3个32位位置(这些位置由Boot ROM用Boot变量初始化)。
.....
......
EINT DINT ERTM DRTM EALLOW EDIS ESTOP0的理解 - 平凡的笨蛋 - 博客园 (cnblogs.com)
一、DSP的EALLOW和EDIS指令
在看DSP初始化程序的时候,经常会看到
void DisableDog(void)
{
EALLOW;
SysCtrlRegs.WDCR= 0x0068;
EDIS;
}
EALLOW与EDIS究竟有什么含义呢?
在.h文件中会发现,这两条其实是汇编指令
#define EALLOW asm(" EALLOW")
#define EDIS asm(" EDIS")
原来TI的DSP为了提高安全性能,将很多关键寄存器作了保护处理。通过状态寄存器1(ST1)的位6设置与复位,来决定是否允许DSP指令对关键寄存器进行操作。这些关键寄存器包括:器件仿真寄存器、FLASH寄存器、CSM寄存器、PIE矢量表、系统控制寄存器、GPIOMux寄存器等等。
DSP由于在上电复位之后,状态寄存器基本上都是清零,而这样的状态下正是上述特殊寄存器禁止改写的状态。为了能够对这些特殊寄存器进行初始化,所以在对上述特殊寄存器进行改写之前,一定要执行汇编指令asm(“EALLOW”)或者宏定义EALLOW来设置状态寄存器1的C6位,在设置完寄存器之后,一定要注意执行汇编指令asm(“EDIS”)或者宏定义EDIS来清除状态寄存器1的C6位,来防止杂散代码或指针破坏寄存器内容。
DSP中的I/O/Z的Z表示高阻态。
void InitGpio(void)
{
EALLOW;
// Each GPIO pin can be:
// a) a GPIO input/output
// b) peripheral function 1
// c) peripheral function 2
// d) peripheral function 3
//GPIO17 input -- DCDC Off control
GpioCtrlRegs.GPAPUD.bit.GPIO17 = DISABLE_PULL_UP;
GpioCtrlRegs.GPACTRL.bit.QUALPRD2 = 1; // Qual period = SYSCLKOUT/2
GpioCtrlRegs.GPAQSEL2.bit.GPIO17 = 2; // 6 samples
GpioCtrlRegs.GPAMUX2.bit.GPIO17 = USED_AS_GPIO;
GpioCtrlRegs.GPADIR.bit.GPIO17 = GPIO_AS_INPUT;
//GPIO18 output -- ORING_OFF
GpioCtrlRegs.GPAPUD.bit.GPIO18 = DISABLE_PULL_UP;
GpioCtrlRegs.GPAMUX2.bit.GPIO18 = USED_AS_GPIO;
GpioCtrlRegs.GPADIR.bit.GPIO18 = GPIO_AS_OUTPUT;
GpioDataRegs.GPACLEAR.bit.GPIO18 = 1;
// GPIO19 input -- present
GpioCtrlRegs.GPAPUD.bit.GPIO19 = DISABLE_PULL_UP;
GpioCtrlRegs.GPAMUX2.bit.GPIO19 = USED_AS_GPIO;
GpioCtrlRegs.GPADIR.bit.GPIO19 = GPIO_AS_INPUT;
GpioCtrlRegs.GPACTRL.bit.QUALPRD2 = 1; // Qual period = SYSCLKOUT/2
GpioCtrlRegs.GPAQSEL2.bit.GPIO19 = 2; // 6 samples
//GPIO20 output -- Led
GpioCtrlRegs.GPAPUD.bit.GPIO20 = DISABLE_PULL_UP;
GpioCtrlRegs.GPAMUX2.bit.GPIO20 = USED_AS_GPIO;
GpioCtrlRegs.GPADIR.bit.GPIO20 = GPIO_AS_OUTPUT;
GpioDataRegs.GPACLEAR.bit.GPIO20 = 1;
//GPIO21 output -- Led
GpioCtrlRegs.GPAPUD.bit.GPIO21 = DISABLE_PULL_UP;
GpioCtrlRegs.GPAMUX2.bit.GPIO21 = USED_AS_GPIO;
GpioCtrlRegs.GPADIR.bit.GPIO21 = GPIO_AS_OUTPUT;
GpioDataRegs.GPACLEAR.bit.GPIO21 = 1;
// GPIO22 output -- EEPROM Disable
GpioCtrlRegs.GPAPUD.bit.GPIO22 = DISABLE_PULL_UP;
GpioCtrlRegs.GPAMUX2.bit.GPIO22 = USED_AS_GPIO;
GpioCtrlRegs.GPADIR.bit.GPIO22 = GPIO_AS_OUTPUT;
GpioDataRegs.GPASET.bit.GPIO22 = 1;
//GPIO23 input -- Test mode switch
GpioCtrlRegs.GPAPUD.bit.GPIO23 = ENABLE_PULL_UP;
GpioCtrlRegs.GPAMUX2.bit.GPIO23 = USED_AS_GPIO;
GpioCtrlRegs.GPADIR.bit.GPIO23 = GPIO_AS_INPUT;
GpioCtrlRegs.GPACTRL.bit.QUALPRD2 = 1; // Qual period = SYSCLKOUT/2
GpioCtrlRegs.GPAQSEL2.bit.GPIO23 = 2; // 6 samples
EDIS;
}
GPACTRL寄存器
当使用3个或6个采样窗口配置输入限制时,GPxCTRL寄存器指定输入引脚的采样周期。
采样周期是相对于syclkout周期的确认样本之间的时间量。
样本的数量在GPxQSELn寄存器中指定。
GPIO作为输入引脚,采样周期设置为系统时钟周期的2倍,这样采久点,可以过滤一下干扰。
注意:如下语句:即便失能了GPIO的内部上拉,而且外面也没有接上拉的话,那么作为输出引脚的话,GPASET设置为1,也照样可以输出高电平。
D100MUX = 0;//GPIO功能
D100DIR = 1;//输出
D100PUD=1;