Keil™, An ARM® Company

µVision® IDE & Debugger

This feature works with...
ARMC166C251C51Eval

SPI Communications Simulation

The µVision3 Debugger simulates SPI interface of 8051, 251, 166, and ARM microcontrollers in both master and slave mode. Typically, there is no dialog support for SPI simulation.

The µVision3 Debugger implements two virtual target registers (SPIxIN and SPIxOUT) for SPI communication. Simulating SPI devices can be complex.

The following debugger script implements SPI simulation for the Atmel AT250X0 SPI Memory.

/* 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 ();

Notes Note

Be sure to refer to the datasheet for the device you use to determine how to use SPI.