ERTEC200P-2作为应用处理器,既可以单独使用,通过GPIO扩展实现基本的IO功能。也可以配合外部主机(例如单片机)实现更复杂的应用。ERTEC200P-2与外部主机接口的示意图如下。常用的接口包括UART,SPI,XHIF接口。从通讯速率来看,UART最低,XHIF最高。所以如果在主机和200P之间有大量的周期数据交换(例如伺服驱动器),建议使用XHIF。
评估板支持两种方式的主机接口:SPI和XHIF。由于UART和SPI属于常见的外设,使用起来比较简单,可以参考对应的代码,所以这里不做过多介绍。接下来重点介绍一下XHIF。
4.1 XHIF接口说明
外部的处理器可以使用XHIF以静态存储的方式访问芯片内部的地址空间。XHIF可以通过AHB总线访问EMC,APB… 等片上资源。一般情况下,可以把EMC(SDRAM)配置为XHIF访问地址空间,这样就可以通过XHIF与主机共享SDRAM中的数据。由于主机和200P会同时访问相同的片上资源,因此XHIF会通过插入等待或就绪(WAIT/RDY)信号控制读写访问的周期,因此在配合XHIF的CPU选型时,一定选则支持WAIT/RDY信号的CPU。
首先,XHIF必须在芯片复位时通过CONFIG引脚使能和配置,因此需要在对应的配置管脚上添加上拉、下拉电阻使能和配置主机接口。
当前评估板的配置是:XHIF=on,16位模式,XHIF_XRD和XHIF_XWR分开,XHIF_XRD高有效。模式的选择需要和主机的外设一致。需要注意的是,XHIF_XRDY是开漏输出,因此需要根据其有效方式添加上拉、下拉电阻。一般情况下XHIF_XRDY低有效加下拉电阻、高有效加上拉电阻。参考设计板采用的模式为高有效加上拉电阻。如果主机为其他型号单片机可以参考如下时序:
读操作,XHIF_XRDY时序:
接下来需要初始化XHIF,在200P用户程序中指定SDRAM中的一个区域用于XHIF访问,
static PNIO_UINT16 xhif_mem[XHIF_SIZE_WORD] __attribute__((section(".xhif_mi_cyclic_in_buf")));
段".xhif_mi_cyclic_in_buf"是在target.ld文件中定义的(注意:主机接口的起始地址必须对齐到0x100000)。这样xhif_mem的起始地址就被编译器分配到0x21000000。
接下来初始XHIF寄存器,由于评估板已经将XHIF_PAGE[0-2]固定配置为011b
因此单片机访问的是PAGE3。当然,自己设计电路时可以任意选择PAGE。XHIF初始化函数为:
static void xhifInit(void)
在该函数中,首先使能REMAP REG32(0x4000F030) = 0x01; REMAP之后SDRAM会被重新映射到0x00000000,这样0x21000000起始的数据与0x01000000起始的数据是一致的。通过实验表明,只有访问REMAP之后的数据才能保证XHIF的数据更新(具体原因不明,芯片手册中也没写)。通过XHIF_0_P3_OF寄存器配置页面3(PAGE3)的起始地址。例如:
REG32(U_HOSTIF__XHIF_0_P3_OF) = (PNIO_UINT32)xhif_mem;
这样,200P通过读写0x01000000起始的数据,就可以实现与单片机共享数据。
单片机STM32F407通过FSMC访问XHIF,具体配置如下下图,注意Wait信号的使能。其中读写时间要与200P数据手册保持一致。
这里FSMC使用片选信号NE1, 起始地址为0x60000000。单片机读写0x60000000相当于读写200P 0x21000000。200P的用户程序通过访问0x01000000也可以读写0x21000000。这样就实现了在两个处理器之间共享程序。
在示例程序中,XHIF前32个WORD(64 bytes)用于存放输出数据,后32个WORD (64 bytes)用于存放输入数据。需要注意的是,尽管当前XHIF为16位模式,在单片机写操作时,必须对齐32位才能生效。举了例子:uint16_t xhif_buffer_out_data[32]映射到主机接口,如果依次执行以下程序:
xhif_buffer_out_data[0] = 0x0001;
xhif_buffer_out_data[1] = 0x0002;
xhif_buffer_out_data[2] = 0x0003;
如果执行完第三行,其实0x0003并没有写入到SDRAM,0x0001和0x0002会被写入到SDRAM。如果再执行:xhif_buffer_out_data[3] = 0x0004; 0x0003 0x0004才会被写入到SDRAM。因此在开发时一定要注意写操作对齐的问题。
在200P上,示例程序在通讯结束回调函数(PnUsr_cbf_IoDatXch)中通过调用IODataToXHIF 将周期输出数据缓存 OutData[2][1] (对应64bytes output) 拷贝到xhif_mem_remap [0 - 63] (xhif_mem_remap 类型是byte[]);并且将xhif_mem_remap [64 - 127] 拷贝到周期输入数据缓存InData [1][1] (对应64bytes input)。
这样,在407上,单片机程序就可以从xhif_buffer[ 0 – 31 ] (xhif_buffer 类型是 short[]) 读取输出数据,更新到外设的输出上(GPIO 或者 DAC);或者读取外设(GPIO或ADC)的输入值写入到xhif_buffer[ 32 – 63]。举例来说:在接收到EXIT0(连接在200P的同步输出SYNC上)中断后,中断服务程序将数据从xhif_buffer读出,然后将xhif_data[0] bit 0-7 (OutData [2][1][0]) 设置为GPIOG的输出。
for(tmpIdx = 0 ; tmpIdx < 32 ; tmpIdx++)
{
xhif_data[tmpIdx] = xhif_buffer[tmpIdx];
delay_clk(5);
}
set_reg = xhif_data[0];
set_reg <<= 8;
set_reg &= 0x0000ff00;
GPIOG->ODR = set_reg;
从原理图上看:
LED分别对应 GPIOG8 – GPIOG15,因此PLC通过写入slot 2 sub 1 字节0,即可设置LED的输出。
同理, 在接收到EXIT0中断后,中断服务程序读取GPIOC的DI输入,将输入值写入到xhif_buffer[32] (对应InData [1][1][0])
input_reg = GPIOC->IDR;
input_reg &= 0xff;
xhif_data[32] = input_reg;
for(tmpIdx = 32 ; tmpIdx < 64 ; tmpIdx++)
{
xhif_buffer[tmpIdx] = xhif_data[tmpIdx];
delay_clk(5);
}
从原理图上看:
拨码开关分别对应 GPIOC0 – GPIOC7,因此拨码开关的拨码值,可以通过slot 1 sub 1 字节0由PLC读取。这样,通过XHIF共享数据,实现了主机外围设备与200P的数据交互。
下一篇:XHIF接口实验