wiki:TBR/UserManual/SparcBSPStartup

Version 4 (modified by JoelSherrill, on Jan 15, 2008 at 8:51:50 AM) (diff)

Spelling, capitalization

SparcBSPStartup

The startup procedure for the SPARC Erc32 and Leon BSPs is complicated. Jiri Gaisler provided this explanation in response to a user's questions. See http://www.rtems.com/ml/rtems-users/2005/september/msg00024.html for the original.

  • The SPARC port of RTE<S generates binaries that do not perform any board initialisation, and that are linked to the beginning of the RAM. The idea behind this is to avoid having a separate bsp for every possible board around. Instead, a boot-prom builder (mkprom) is used to create a self-extracting prom image that initialises all board registers, loads the application to ram, and the starts it. The parameters to mkprom defines memory sizes, waitstates, frequency stack pointer and so on. So far so good...
  • When running on a (recent) ERC32 simulator, the RTEMS image is loaded into the emulated ram and started from there. The simulator detects that the start address is not 0 (SPARC reset vector) and perform the necessary board init routines that would have been make by mkprom on real hardware.
  • An issue with the 3-chip version of ERC32 is that the timer scaling register can not be read, only written (!). The RTEMS application can therefore not read the timer scaler to figure out which frequency the board is running at. To solve this, both the mkprom loader and the simulator writes a copy of the scaler value to trap entry 0x7e in the sparc trap table, because this trap can never occur anyway. The RTEMS application picks up the value from there and now knows the frequency and can generate proper timer events etc.
  • Possible cause of the problem: Fabrício could be running rdbmon debug monitor on his board, using it to download and start applications. rdbmon is an application on its own, and needs to insert its trap vectors into the RTEMS applications trap table. This is done by starting the application in user mode. The first priviledged instruction that occurs is a write to %tbr (trap base register). This instruction will trap and control is transfered to rdbmon. The monitor can read out the value of the new %tbr, insert its trap entries there, write the scaler value in 0x7e of the new trap table, and re-start the application is supervisor mode. What can not be done (and this is also mentioned in the leccs/rdbmon manual) is to single step through this procedure. What can also not be done is to use a custom loader that does not write 0x7e, or custom start up code that re-allocates the trap table.

Note that these issues are commented in start.S and spurious.c of the sparc/erc32 bsp.

start.S

/*
   This is a sad patch to make sure that we know where the
   MEC timer control register mirror is so we can stop the timers
   from an external debugger. It is needed because the control
   register is write-only. Trap 0x7C cannot occur in ERC32...


   We also use this location to store the last location of the
   usable RAM in order not to overwrite the remote debugger with
   the RTEMS work-space area.


 * /


	.global SYM(_ERC32_MEC_Timer_Control_Mirror), SYM(rdb_start), SYM(CLOCK_SPEED)
	.global SYM(Configuration)


SYM(rdb_start):
SYM(_ERC32_MEC_Timer_Control_Mirror):


  BAD_TRAP; BAD_TRAP;                           ! 7C - 7D undefined


SYM(CLOCK_SPEED):


  .word	0x0a, 0, 0, 0				! 7E (10 MHz default)

spurious.c

  for ( trap=0 ; trap<256 ; trap++ ) {


    /*
     *  Skip window overflow, underflow, and flush as well as software
     *  trap 0 which we will use as a shutdown. Also avoid trap 0x70 - 0x7f
     *  which cannot happen and where some of the space is used to pass
     *  paramaters to the program.
     */


     if (( trap == 5 || trap == 6 ) ||
     	(( trap >= 0x11 ) && ( trap <= 0x1f )) ||
     	(( trap >= 0x70 ) && ( trap <= 0x83 )))
      continue;


    set_vector( (rtems_isr_entry) bsp_spurious_handler,
         SPARC_SYNCHRONOUS_TRAP( trap ), 1 );
  }