Keil Logo

SPI Simulation

A Serial Peripheral Interface (SPI) allows you to connect devices on board level. The µVision3 Debugger simulates SPI interface of several microcontrollers in both master and slave mode.

Virtual Simulation Registers (VTREG)

For simulation of SPI communication, the µVision3 Debugger implements the following virtual simulation registers (VTREG)

VTREG Description
SPIxIN Is the SPI input register gets the data that are currently received.
SPIxOUT Is the SPI output register that holds the data that are currently transmitted.

The VTREG naming conventions SPIx vary from device to device. Several devices provide more than one SPI interface and therefore the VTREG names may be prefixed with SPI0 or SPI1. You may use the command DIR VTREG to check the virtual simulation register names of the SPI interface of the device you have selected.

SPI Simulation Examples

µVison Download file AT25 SPI EEPROM Simulation for NXP LPC2000 provides an example for simulating an AT25 SPI EEPROM.

The following debug script includes debugger signal functions that simulate an Atmel AT250X0 SPI memory device. This device is simulated using a simple state machine implemented with switch statements.

/* 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 %u\n", (unsigned) st);

  switch (st)  {
    case 0:  /* Get OPCode */
      opcode = SPI_OUT & 0x0007;
      printf ("AT250X0: OPCODE %u\n", (unsigned) opcode);

    switch (opcode)
      {
      case 1: /* WRSR */
        return (0);

      case 2: /* Write */
        printf ("AT250X0: WRITE OPCODE Detected\n");
        spi_at250x0_address = (SPI_OUT & 0x08) << 5;
        return (3);

      case 3: /* Read */
        printf ("AT250X0: READ OPCODE Detected\n");
        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 Detected\n", spi_at250x0_address);
    return (2);

  case 2:  /* Read */
    printf ("AT250X0: Read %2.2X from address %4.4X\n", '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 Detected\n", spi_at250x0_address);
    return (4);

  case 4:  /* Write */
    if (spi_at250x0_status & 0x02)
      {
      printf ("AT250X0: Write %2.2X to address %4.4X\n", 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 Detected\n");

  if ((PORT1 & 0x01) == 0)
    {
    printf ("Calling AT250X0 Routines\n");
    spi_at250x0_state = spi_at250x0 (spi_at250x0_state);

    if (spi_at250x0_status & 0x01)
      swatch (0.000100);
      spi_at250x0_status &= ~0x01;
    }
  else
    {
    printf ("Resetting AT250X0 Routines\n");
    spi_at250x0_state = 0;
    }
  }
}

/*-----------------------------------------------
Enable the signal function for SPI writes.
-----------------------------------------------*/
spi_watcher ();
  Arm logo
Important information

This site uses cookies to store information on your computer. By continuing to use our site, you consent to our cookies.

Change Settings

Privacy Policy Update

Arm’s Privacy Policy has been updated. By continuing to use our site, you consent to Arm’s Privacy Policy. Please review our Privacy Policy to learn more about our collection, use and transfers
of your data.