串行外设接口 (SPI) 允许在板级连接设备。µVision 调试器在主从模式下模拟多个微控制器的SPI接口。
虚拟仿真寄存器 (VTREG)
以下 VTREG 用于模拟 SPI 通信:
VTREG | 描述 |
SPIxIN | 是SPI输入寄存器,获取当前接收到的数据。 |
SPIxOUT | 是保存当前传输数据的 SPI 输出寄存器。 |
SPIx 的 VTREG 命名约定因器件而异。一些设备提供了不止一个 SPI 接口。因此,VTREG 名称可能以 SPI0 或 SPI1 为前缀。使用命令 DIR VTREG检查 SPI 接口的虚拟仿真寄存器名称。
SPI仿真示例
以下脚本定义了调试器信号函数,这些函数使用带有switch语句的简单状态机模拟 Atmel AT250X0 SPI 存储设备。
/* Define the state and address for the AT250x0.*/
define char spi_at250x0_state
define int spi_at250x0_address
define char spi_at250x0_status
/* MAP the memory area to use for the SPI RAM. */
map X:0x700000,X:0x70FFFF READ WRITE
/*-----------------------------------------------
This function implements the state matching for
the AT250x0.
State Transition
-------------------------------------------------
0: WREN -> 0
0: WRDI -> 0
0: RDSR -> 0
0: Read -> 1: Get Address LSB -> 2: Read Byte <-
0: Write -> 3: Get Address LSB -> 4: Write Byte -> 5 <-
1: Get Addr LSB -> 2
2: Read Byte(s) -> 2
3: Get Addr LSB -> 4
4: Write Byte -> 5
-----------------------------------------------*/
func char spi_at250x0 (char st) {
unsigned char opcode;
printf ("AT250X0: STATE %un", (unsigned) st);
switch (st) {
case 0: /* Get OPCode */
opcode = SPI_OUT & 0x0007;
printf ("AT250X0: OPCODE %un", (unsigned) opcode);
switch (opcode)
{
case 1: /* WRSR */
return (0);
case 2: /* Write */
printf ("AT250X0: WRITE OPCODE Detectedn");
spi_at250x0_address = (SPI_OUT & 0x08) << 5;
return (3);
case 3: /* Read */
printf ("AT250X0: READ OPCODE Detectedn");
spi_at250x0_address = (SPI_OUT & 0x08) << 5;
return (1);
case 4: /* WRDI */
spi_at250x0_status &= ~0x02; /* Clear Write Enable Bit */
return (0);
case 5: /* RDSR */
SPI_IN = spi_at250x0_status;
return (5);
case 6: /* WREN */
spi_at250x0_status |= 0x02; /* Set Write Enable Bit */
return (0);
}
return (0);
case 1: /* Get Address LSB for READ */
spi_at250x0_address |= (SPI_OUT & 0xFF);
printf ("AT250X0: Address %4.4X Detectedn", spi_at250x0_address);
return (2);
case 2: /* Read */
printf ("AT250X0: Read %2.2X from address %4.4Xn", 'A', spi_at250x0_address);
SPI_IN = _rbyte(X:0x700000 + spi_at250x0_address);
spi_at250x0_address = (spi_at250x0_address + 1) % 512;
return (2);
case 3: /* Get Address LSB for WRITE */
spi_at250x0_address |= (SPI_OUT & 0xFF);
printf ("AT250X0: Address %4.4X Detectedn", spi_at250x0_address);
return (4);
case 4: /* Write */
if (spi_at250x0_status & 0x02)
{
printf ("AT250X0: Write %2.2X to address %4.4Xn", SPI_OUT, spi_at250x0_address);
_wbyte(X:0x700000 + spi_at250x0_address, SPI_OUT);
spi_at250x0_status |= 0x01;
}
return (5);
case 5: /* Instruction End */
return (5);
}
return (0);
}
/*
* This signal function watches the AT89S8252 SPI port for writes. If there
* is an SPI port output and if P1.0 is LO (AT250X0 chip select) then interpret
* the SPI output data and run the state machine.
*/
signal void spi_watcher (void) {
spi_at250x0_state = 0;
while (1) {
wwatch (SPI_OUT);
printf ("SPI_OUT Detectedn");
if ((PORT1 & 0x01) == 0)
{
printf ("Calling AT250X0 Routinesn");
spi_at250x0_state = spi_at250x0 (spi_at250x0_state);
if (spi_at250x0_status & 0x01)
swatch (0.000100);
spi_at250x0_status &= ~0x01;
}
else
{
printf ("Resetting AT250X0 Routinesn");
spi_at250x0_state = 0;
}
}
}
/*-----------------------------------------------
Enable the signal function for SPI writes.
-----------------------------------------------*/
spi_watcher ();