예제 #1
0
파일: init.c 프로젝트: lanzhongheng/rtems
/*
 *  Timer Service Routine
 *
 *  If we are in an ISR, then this is a normal clock tick.
 *  If we are not, then it is the test case.
 */
rtems_timer_service_routine test_unblock_task(
  rtems_id  timer,
  void     *arg
)
{
  bool              in_isr;
  rtems_status_code status;

  in_isr = rtems_interrupt_is_in_progress();
  status = rtems_task_is_suspended( blocked_task_id );
  if ( in_isr ) {
    status = rtems_timer_fire_after( timer, 1, test_unblock_task, NULL );
    directive_failed( status, "timer_fire_after failed" );
    return;
  }

  if ( (status != RTEMS_ALREADY_SUSPENDED) ) {
    status = rtems_timer_fire_after( timer, 1, test_unblock_task, NULL );
    directive_failed( status, "timer_fire_after failed" );
    return;
  }

  blocked_task_status = 2;
  _Thread_Disable_dispatch();
  status = rtems_task_resume( blocked_task_id );
  _Thread_Unnest_dispatch();
#if defined( RTEMS_SMP )
  directive_failed_with_level( status, "rtems_task_resume", 1 );
#else
  directive_failed( status, "rtems_task_resume" );
#endif
}
예제 #2
0
파일: init.c 프로젝트: lanzhongheng/rtems
void check_isr_in_progress_inline(void)
{
  bool in_isr;

  in_isr = rtems_interrupt_is_in_progress();
  isr_in_progress_inline = ( in_isr ) ? 1 : 2;
}
예제 #3
0
/* test bodies */
void test_interrupt_inline(void)
{
  rtems_interrupt_level level;
  rtems_attribute level_attribute, level_attribute_macro;
  bool                  in_isr;

  puts( "interrupt is in progress (use body)" );
  in_isr = rtems_interrupt_is_in_progress();
  if ( in_isr ) {
    puts( "interrupt reported to be is in progress (body)" );
    rtems_test_exit( 0 );
  }

  puts( "interrupt disable (use inline)" );
  rtems_interrupt_disable( level );

  puts( "interrupt flash (use inline)" );
  rtems_interrupt_flash( level );

  puts( "interrupt enable (use inline)" );
  rtems_interrupt_enable( level );

  puts( "interrupt level attribute (use inline)" );
  level_attribute = rtems_interrupt_level_attribute( level );
  level_attribute_macro = RTEMS_INTERRUPT_LEVEL(level);
  if ( level_attribute_macro == level_attribute ) {
    puts( "test case working.." );
  }
}
예제 #4
0
rtems_status_code rtems_io_register_driver(
  rtems_device_major_number         major,
  const rtems_driver_address_table *driver_table,
  rtems_device_major_number        *registered_major
)
{
  rtems_device_major_number major_limit = _IO_Number_of_drivers;

  if ( rtems_interrupt_is_in_progress() )
    return RTEMS_CALLED_FROM_ISR;

  if ( registered_major == NULL )
    return RTEMS_INVALID_ADDRESS;

  /* Set it to an invalid value */
  *registered_major = major_limit;

  if ( driver_table == NULL )
    return RTEMS_INVALID_ADDRESS;

  if ( rtems_io_is_empty_table( driver_table ) )
    return RTEMS_INVALID_ADDRESS;

  if ( major >= major_limit )
    return RTEMS_INVALID_NUMBER;

  _Thread_Disable_dispatch();

  if ( major == 0 ) {
    rtems_status_code sc = rtems_io_obtain_major_number( registered_major );

    if ( sc != RTEMS_SUCCESSFUL ) {
      _Thread_Enable_dispatch();
      return sc;
    }
    major = *registered_major;
  } else {
    rtems_driver_address_table *const table = _IO_Driver_address_table + major;

    if ( !rtems_io_is_empty_table( table ) ) {
      _Thread_Enable_dispatch();
      return RTEMS_RESOURCE_IN_USE;
    }

    *registered_major = major;
  }

  _IO_Driver_address_table [major] = *driver_table;

  _Thread_Enable_dispatch();

  return rtems_io_initialize( major, 0, NULL );
}
예제 #5
0
파일: init.c 프로젝트: lanzhongheng/rtems
rtems_timer_service_routine test_isr_in_progress(
  rtems_id  timer,
  void     *arg
)
{
  bool in_isr;

  check_isr_in_progress_inline();

  in_isr = rtems_interrupt_is_in_progress();
  isr_in_progress_body = ( in_isr ) ? 1 : 2;
}
예제 #6
0
/**
 * @brief Iterates over all installed interrupt handler of a vector.
 *
 * @ingroup bsp_interrupt
 *
 * @return In addition to the standard status codes this function returns
 * RTEMS_INTERNAL_ERROR if the BSP interrupt support is not initialized.
 *
 * @see rtems_interrupt_handler_iterate().
 */
static rtems_status_code bsp_interrupt_handler_iterate(
  rtems_vector_number vector,
  rtems_interrupt_per_handler_routine routine,
  void *arg
)
{
  rtems_status_code sc = RTEMS_SUCCESSFUL;
  bsp_interrupt_handler_entry *current = NULL;
  rtems_option options = 0;
  rtems_vector_number index = 0;

  /* Check parameters and system state */
  if (!bsp_interrupt_is_initialized()) {
    return RTEMS_INTERNAL_ERROR;
  } else if (!bsp_interrupt_is_valid_vector(vector)) {
    return RTEMS_INVALID_ID;
  } else if (rtems_interrupt_is_in_progress()) {
    return RTEMS_CALLED_FROM_ISR;
  }

  /* Lock */
  sc = bsp_interrupt_lock();
  if (sc != RTEMS_SUCCESSFUL) {
    return sc;
  }

  /* Interate */
  index = bsp_interrupt_handler_index(vector);
  current = &bsp_interrupt_handler_table [index];
  if (!bsp_interrupt_is_empty_handler_entry(current)) {
    do {
      options = bsp_interrupt_is_handler_unique(index) ?
        RTEMS_INTERRUPT_UNIQUE : RTEMS_INTERRUPT_SHARED;
      routine(arg, current->info, options, current->handler, current->arg);
      current = current->next;
    } while (current != NULL);
  }

  /* Unlock */
  sc = bsp_interrupt_unlock();
  if (sc != RTEMS_SUCCESSFUL) {
    return sc;
  }

  return RTEMS_SUCCESSFUL;
}
예제 #7
0
파일: init.c 프로젝트: lanzhongheng/rtems
void test_interrupt_inline(void)
{
  rtems_interrupt_level level;
  rtems_mode            level_mode_body;
  rtems_mode            level_mode_macro;
  bool                  in_isr;

  puts( "interrupt is in progress (use body)" );
  in_isr = rtems_interrupt_is_in_progress();
  if ( in_isr ) {
    puts( "interrupt reported to be is in progress (body)" );
    rtems_test_exit( 0 );
  }

  puts( "interrupt disable (use inline)" );
  _Thread_Disable_dispatch();
  rtems_interrupt_disable( level );
  _Thread_Enable_dispatch();

  puts( "interrupt flash (use inline)" );
  _Thread_Disable_dispatch();
  rtems_interrupt_flash( level );
  _Thread_Enable_dispatch();

  puts( "interrupt enable (use inline)" );
  _Thread_Disable_dispatch();
  rtems_interrupt_enable( level );
  _Thread_Enable_dispatch();

  puts( "interrupt level mode (use inline)" );
  level_mode_body = rtems_interrupt_level_body( level );
  level_mode_macro = RTEMS_INTERRUPT_LEVEL(level);
  if ( level_mode_macro == level_mode_body ) {
    puts( "test case working.." );
  }
}
예제 #8
0
파일: init.c 프로젝트: lanzhongheng/rtems
rtems_task Init(
  rtems_task_argument argument
)
{
  rtems_time_of_day     time;
  rtems_status_code     status;
  rtems_interrupt_level level;
  rtems_mode            level_mode_body;
  rtems_mode            level_mode_macro;
  bool                  in_isr;
  rtems_id              timer;
  int                   i;

  puts( "\n\n*** TEST 37 ***" );

  test_isr_level();
  test_isr_locks();
  test_interrupt_locks();

  build_time( &time, 12, 31, 1988, 9, 0, 0, 0 );
  status = rtems_clock_set( &time );
  directive_failed( status, "rtems_clock_set" );

  /*
   *  Timer used in multiple ways
   */
  status = rtems_timer_create( 1, &timer );
  directive_failed( status, "rtems_timer_create" );

  /*
   *  Test clock tick from outside ISR
   */
  status = rtems_clock_tick();
  directive_failed( status, "rtems_clock_tick" );
  puts( "clock_tick from task level" );

  /*
   *  Now do a dispatch directly out of a clock tick that is
   *  called from a task.  We need to create a task that will
   *  block so we have one to unblock.  Then we schedule a TSR
   *  to run in the clock tick but it has to be careful to
   *  make sure it is not called from an ISR and that the
   *  dispatching critical section is managed properly to
   *  make the dispatch happen.
   */

  blocked_task_status = -1;

  status = rtems_task_create(
    rtems_build_name( 'T', 'A', '1', ' ' ),
    1,
    RTEMS_MINIMUM_STACK_SIZE,
    RTEMS_DEFAULT_MODES,
    RTEMS_DEFAULT_ATTRIBUTES,
    &blocked_task_id
  );
  directive_failed( status, "rtems_task_create" );

  status = rtems_task_start( blocked_task_id, blocked_task, 0 );
  directive_failed( status, "rtems_task_start" );

  status = rtems_task_wake_after( 10 );
  directive_failed( status, "rtems_task_wake_after" );

  status = rtems_timer_fire_after( timer, 1, test_unblock_task, NULL );
  directive_failed( status, "timer_fire_after failed" );

  /* we expect to be preempted from this call */
  for ( i=0 ; i<100 && blocked_task_status != 3 ; i++ ) {
    status = rtems_clock_tick();
    directive_failed( status, "rtems_clock_tick" );
  }
  switch ( blocked_task_status ) {
     case -1:
       puts(
         "clock_tick with task preempt -- task blocked, timer did not fire"
       );
       rtems_test_exit(0);
       break;
     case 1:
       puts( "clock_tick with task preempt -- timer fired case 1" );
       rtems_test_exit(0);
       break;
     case 2:
       puts( "clock_tick with task preempt -- timer fired case 2" );
       rtems_test_exit(0);
       break;
     case 3:
       puts( "clock_tick from task level with preempt -- OK" );
       break;
  }

  /*
   *  Test interrupt inline versions
   */
  test_interrupt_inline();

  /*
   *  Test interrupt bodies
   */
  puts( "interrupt is in progress (use body)" );
  in_isr = rtems_interrupt_is_in_progress();
  if ( in_isr ) {
    puts( "interrupt reported to be is in progress (body)" );
    rtems_test_exit( 0 );
  }

  puts( "interrupt disable (use body)" );
  _Thread_Disable_dispatch();
  level = rtems_interrupt_disable();
  _Thread_Enable_dispatch();

  puts( "interrupt disable (use body)" );
  _Thread_Disable_dispatch();
  level = rtems_interrupt_disable();
  _Thread_Enable_dispatch();

  puts( "interrupt flash (use body)" );
  _Thread_Disable_dispatch();
  rtems_interrupt_flash( level );
  _Thread_Enable_dispatch();

  puts( "interrupt enable (use body)" );
  _Thread_Disable_dispatch();
  rtems_interrupt_enable( level );
  _Thread_Enable_dispatch();

  puts( "interrupt level mode (use body)" );
  level_mode_body = rtems_interrupt_level_body( level );
  level_mode_macro = RTEMS_INTERRUPT_LEVEL(level);
  if ( level_mode_macro == level_mode_body ) {
    puts("test seems to work");
  }

  /*
   * Test ISR in progress from actual ISR
   */
  isr_in_progress_body   = -1;
  isr_in_progress_inline = -1;

  status = rtems_timer_fire_after( timer, 10, test_isr_in_progress, NULL );
  directive_failed( status, "timer_fire_after failed" );

  status = rtems_task_wake_after( 100 );
  directive_failed( status, "wake_after failed" );

  check_isr_worked( "inline", isr_in_progress_body );

  check_isr_worked( "body", isr_in_progress_body );

  puts( "*** END OF TEST 37 ***" );
  rtems_test_exit( 0 );
}
예제 #9
0
void
BSP_exceptionHandler(BSP_Exception_frame* excPtr)
{
uint32_t	note;
BSP_ExceptionExtension	ext=0;
rtems_id		id=0;
int			recoverable = 0;
char			*fmt="Uhuuuh, Exception %d in unknown task???\n";
int			quiet=0;

 if (!quiet) printk("In BSP_exceptionHandler()\n");
   /* If we are in interrupt context, we are in trouble - skip the user
    * hook and panic
    */
    if (rtems_interrupt_is_in_progress()) {
      fmt="Aieeh, Exception %d in interrupt handler\n";
    } else if ( !_Thread_Executing) {
      fmt="Aieeh, Exception %d in initialization code\n";
    } else {
    /* retrieve the notepad which possibly holds an extention pointer */
    if (RTEMS_SUCCESSFUL==rtems_task_ident(RTEMS_SELF,RTEMS_LOCAL,&id) &&
#if 0
/* Must not use a notepad due to unknown initial value (notepad memory is allocated from the
 * workspace)!
 */
	        RTEMS_SUCCESSFUL==rtems_task_get_note(id, BSP_EXCEPTION_NOTEPAD, &note)
#else
	        RTEMS_SUCCESSFUL==rtems_task_variable_get(id, (void*)&BSP_exceptionExtension, (void**)&note)
#endif
         ) {
	   ext = (BSP_ExceptionExtension)note;
	   if (ext)
	       quiet=ext->quiet;
	   if (!quiet) {
	      printk("Task (Id 0x%08x) got ",id);
	   }
	   fmt="exception %d\n";
	}
    }

    if (ext && ext->lowlevelHook && ext->lowlevelHook(excPtr,ext,0)) {
		/* they did all the work and want us to do nothing! */
      printk("they did all the work and want us to do nothing!\n");
		return;
    }

    if (!quiet) {
       /* message about exception */
       printk(fmt, excPtr->_EXC_number);
       /* register dump */
       printk("\t Next PC or Address of fault = %x, ", excPtr->EXC_SRR0);
       printk("Mvme5500 Saved MSR = %x\n", excPtr->EXC_SRR1);
       printk("\t R0  = %08x", excPtr->GPR0);
       printk(" R1  = %08x", excPtr->GPR1);
       printk(" R2  = %08x", excPtr->GPR2);
       printk(" R3  = %08x\n", excPtr->GPR3);
       printk("\t R4  = %08x", excPtr->GPR4);
       printk(" R5  = %08x", excPtr->GPR5);
       printk(" R6  = %08x", excPtr->GPR6);
       printk(" R7  = %08x\n", excPtr->GPR7);
       printk("\t R8  = %08x", excPtr->GPR8);
       printk(" R9  = %08x", excPtr->GPR9);
       printk(" R10 = %08x", excPtr->GPR10);
       printk(" R11 = %08x\n", excPtr->GPR11);
       printk("\t R12 = %08x", excPtr->GPR12);
       printk(" R13 = %08x", excPtr->GPR13);
       printk(" R14 = %08x", excPtr->GPR14);
       printk(" R15 = %08x\n", excPtr->GPR15);
       printk("\t R16 = %08x", excPtr->GPR16);
       printk(" R17 = %08x", excPtr->GPR17);
       printk(" R18 = %08x", excPtr->GPR18);
       printk(" R19 = %08x\n", excPtr->GPR19);
       printk("\t R20 = %08x", excPtr->GPR20);
       printk(" R21 = %08x", excPtr->GPR21);
       printk(" R22 = %08x", excPtr->GPR22);
       printk(" R23 = %08x\n", excPtr->GPR23);
       printk("\t R24 = %08x", excPtr->GPR24);
       printk(" R25 = %08x", excPtr->GPR25);
       printk(" R26 = %08x", excPtr->GPR26);
       printk(" R27 = %08x\n", excPtr->GPR27);
       printk("\t R28 = %08x", excPtr->GPR28);
       printk(" R29 = %08x", excPtr->GPR29);
       printk(" R30 = %08x", excPtr->GPR30);
       printk(" R31 = %08x\n", excPtr->GPR31);
       printk("\t CR  = %08x\n", excPtr->EXC_CR);
       printk("\t CTR = %08x\n", excPtr->EXC_CTR);
       printk("\t XER = %08x\n", excPtr->EXC_XER);
       printk("\t LR  = %08x\n", excPtr->EXC_LR);

       BSP_printStackTrace(excPtr);
    }

    if (ASM_MACH_VECTOR == excPtr->_EXC_number) {
       /* ollah , we got a machine check - this could either
	* be a TEA, MCP or internal; let's see and provide more info
	*/
       if (!quiet)
	   printk("Machine check; reason:");
       if ( ! (excPtr->EXC_SRR1 & (SRR1_TEA_EXC | SRR1_MCP_EXC)) ) {
	   if (!quiet)
	       printk("SRR1\n");
       } else {
	   if (excPtr->EXC_SRR1 & (SRR1_TEA_EXC)) {
	      if (!quiet)
		 printk(" TEA");
	   }
	   if (excPtr->EXC_SRR1 & (SRR1_MCP_EXC)) {
	      unsigned long gerr;

	      if (!quiet) printk(" MCP\n");

	      /* it's MCP; gather info from the host bridge */
 	      gerr=_BSP_clear_hostbridge_errors(0,0);
              if (gerr&0x80000000) printk("GT64260 Parity error\n");
              if (gerr&0x40000000) printk("GT64260 SysErr\n");
	      if ((!quiet) && (!gerr)) printk("GT64260 host bridge seems OK\n");
	    }
       }
    } else if (ASM_DEC_VECTOR == excPtr->_EXC_number) {
		recoverable = 1;
    } else if (ASM_SYS_VECTOR == excPtr->_EXC_number) {
#ifdef TEST_RAW_EXCEPTION_CODE
		recoverable = 1;
#else
		recoverable = 0;
#endif
    }

    /* call them for a second time giving a chance to intercept
     * the task_suspend
     */
    if (ext && ext->lowlevelHook && ext->lowlevelHook(excPtr, ext, 1))
		return;

    if (!recoverable) {
		if (id) {
			/* if there's a highlevel hook, install it */
			if (ext && ext->highlevelHook) {
				excPtr->EXC_SRR0 = (uint32_t)ext->highlevelHook;
				excPtr->GPR3     = (uint32_t)ext;
				return;
			}
			if (excPtr->EXC_SRR1 & MSR_FP) {
				/* thread dispatching is _not_ disabled at this point; hence
				 * we must make sure we have the FPU enabled...
				 */
				_write_MSR( _read_MSR() | MSR_FP );
				__asm__ __volatile__("isync");
			}
			printk("unrecoverable exception!!! task %08x suspended\n",id);
			rtems_task_suspend(id);
		} else {
			printk("PANIC, rebooting...\n");
			bsp_reset();
		}
    }
}
예제 #10
0
파일: init.c 프로젝트: Avanznow/rtems
rtems_task Init(
  rtems_task_argument argument
)
{
  rtems_status_code         sc;
  rtems_device_major_number registered;
  rtems_device_major_number registered_not;
  rtems_device_major_number invalid_major = _IO_Number_of_drivers + 1;
  rtems_interrupt_level level;
  bool do_interrupt_context_test = true;

  TEST_BEGIN();

  /* Ensure that this test works as expected */
  test_interrupt_context_enter( level );
  do_interrupt_context_test = rtems_interrupt_is_in_progress();
  test_interrupt_context_leave( level );

  /*
   *  Register a driver with init == NULL and open != NULL
   */

  puts( "Init - rtems_io_register_driver - init == NULL, open != NULL OK" );
  sc = rtems_io_register_driver( 0, &test_driver, &registered );
  printf( "Init - Major slot returned = %d\n", (int) registered );
  directive_failed( sc, "rtems_io_register_driver" );

  puts( "Init - rtems_io_register_driver - init == NULL, open != NULL OK" );
  sc = rtems_io_register_driver( 0, &test_driver, &registered_not );
  printf( "Init - Major slot returned = %d\n", (int) registered_not );
  fatal_directive_status(
    sc,
    RTEMS_TOO_MANY,
    "rtems_io_register_driver too many"
  );

  puts( "Init - rtems_io_register_driver - used slot" );
  sc = rtems_io_register_driver( registered, &test_driver, &registered_not );
  fatal_directive_status(
    sc,
    RTEMS_RESOURCE_IN_USE,
    "rtems_io_register_driver slot in use"
  );

  puts( "Init - rtems_io_unregister_driver - used slot" );
  sc = rtems_io_unregister_driver( registered );
  directive_failed( sc, "rtems_io_unregister_driver" );

  puts( "Init - rtems_io_register_driver - free slot" );
  sc = rtems_io_register_driver( registered, &test_driver, &registered );
  directive_failed( sc, "rtems_io_register_driver" );

  puts( "Init - rtems_io_register_driver - called from interrupt context" );
  if ( do_interrupt_context_test ) {
    test_interrupt_context_enter( level );
    sc = rtems_io_register_driver( 0, NULL, NULL );
    test_interrupt_context_leave( level );
    fatal_directive_status(
      sc,
      RTEMS_CALLED_FROM_ISR,
      "rtems_io_register_driver"
    );
  }

  puts( "Init - rtems_io_register_driver - invalid registered major pointer" );
  sc = rtems_io_register_driver( 0, NULL, NULL );
  fatal_directive_status(
    sc,
    RTEMS_INVALID_ADDRESS,
    "rtems_io_register_driver"
  );

  puts( "Init - rtems_io_register_driver - invalid driver table pointer" );
  sc = rtems_io_register_driver( 0, NULL, &registered );
  fatal_directive_status(
    sc,
    RTEMS_INVALID_ADDRESS,
    "rtems_io_register_driver"
  );

  puts( "Init - rtems_io_register_driver - invalid empty driver table" );
  test_driver.open_entry = NULL;
  sc = rtems_io_register_driver( 0, &test_driver, &registered );
  test_driver.open_entry = test_open;
  fatal_directive_status(
    sc,
    RTEMS_INVALID_ADDRESS,
    "rtems_io_register_driver"
  );

  puts( "Init - rtems_io_register_driver - invalid major" );
  sc = rtems_io_register_driver( invalid_major, &test_driver, &registered );
  fatal_directive_status(
    sc,
    RTEMS_INVALID_NUMBER,
    "rtems_io_register_driver"
  );

  puts( "Init - rtems_io_unregister_driver - called from interrupt context" );
  if ( do_interrupt_context_test ) {
    test_interrupt_context_enter( level );
    sc = rtems_io_unregister_driver( 0 );
    test_interrupt_context_leave( level );
    fatal_directive_status(
      sc,
      RTEMS_CALLED_FROM_ISR,
      "rtems_io_unregister_driver"
    );
  }

  puts( "Init - rtems_io_unregister_driver - invalid major number" );
  sc = rtems_io_unregister_driver( invalid_major );
  fatal_directive_status(
    sc,
    RTEMS_UNSATISFIED,
    "rtems_io_unregister_driver"
  );

  TEST_END();
  rtems_test_exit( 0 );
}
예제 #11
0
/**
 * @brief Removes an interrupt handler.
 *
 * @ingroup bsp_interrupt
 *
 * @return In addition to the standard status codes this function returns
 * RTEMS_INTERNAL_ERROR if the BSP interrupt support is not initialized.
 *
 * @see rtems_interrupt_handler_remove().
 */
static rtems_status_code bsp_interrupt_handler_remove(
  rtems_vector_number vector,
  rtems_interrupt_handler handler,
  void *arg
)
{
  rtems_status_code sc = RTEMS_SUCCESSFUL;
  rtems_interrupt_level level;
  rtems_vector_number index = 0;
  bsp_interrupt_handler_entry *head = NULL;
  bsp_interrupt_handler_entry *current = NULL;
  bsp_interrupt_handler_entry *previous = NULL;
  bsp_interrupt_handler_entry *match = NULL;

  /* Check parameters and system state */
  if (!bsp_interrupt_is_initialized()) {
    return RTEMS_INTERNAL_ERROR;
  } else if (!bsp_interrupt_is_valid_vector(vector)) {
    return RTEMS_INVALID_ID;
  } else if (handler == NULL) {
    return RTEMS_INVALID_ADDRESS;
  } else if (rtems_interrupt_is_in_progress()) {
    return RTEMS_CALLED_FROM_ISR;
  }

  /* Lock */
  sc = bsp_interrupt_lock();
  if (sc != RTEMS_SUCCESSFUL) {
    return sc;
  }

  /* Get handler table index */
  index = bsp_interrupt_handler_index(vector);

  /* Get head entry of the handler list for current vector */
  head = &bsp_interrupt_handler_table [index];

  /* Search for a matching entry */
  current = head;
  do {
    if (current->handler == handler && current->arg == arg) {
      match = current;
      break;
    }
    previous = current;
    current = current->next;
  } while (current != NULL);

  /* Remove the matching entry */
  if (match != NULL) {
    if (match->next != NULL) {
      /*
       * The match has a successor.  A successor is always
       * allocated.  So replace the match with its successor
       * and free the successor entry.
       */
      current = match->next;

      rtems_interrupt_disable(level);
      *match = *current;
      rtems_interrupt_enable(level);

      bsp_interrupt_free_handler_entry(current);
    } else if (match == head) {
      /*
       * The match is the list head and has no successor.
       * The list head is stored in a static table so clear
       * this entry.  Since now the list is empty disable the
       * vector.
       */

      /* Disable the vector */
      sc = bsp_interrupt_vector_disable(vector);

      /* Clear entry */
      rtems_interrupt_disable(level);
      bsp_interrupt_clear_handler_entry(head);
      #ifdef BSP_INTERRUPT_USE_INDEX_TABLE
        bsp_interrupt_handler_index_table [vector] = 0;
      #endif
      rtems_interrupt_enable(level);

      /* Allow shared handlers */
      bsp_interrupt_set_handler_unique(index, false);

      /* Check status code */
      if (sc != RTEMS_SUCCESSFUL) {
        bsp_interrupt_unlock();
        return sc;
      }
    } else {
      /*
       * The match is the list tail and has a predecessor.
       * So terminate the predecessor and free the match.
       */
      rtems_interrupt_disable(level);
      previous->next = NULL;
      rtems_interrupt_enable(level);

      bsp_interrupt_free_handler_entry(match);
    }
  } else {
    /* No matching entry found */
    bsp_interrupt_unlock();
    return RTEMS_UNSATISFIED;
  }

  /* Unlock */
  sc = bsp_interrupt_unlock();
  if (sc != RTEMS_SUCCESSFUL) {
    return sc;
  }

  return RTEMS_SUCCESSFUL;
}
예제 #12
0
/**
 * @brief Installs an interrupt handler.
 *
 * @ingroup bsp_interrupt
 *
 * @return In addition to the standard status codes this function returns:
 * - If the BSP interrupt support is not initialized RTEMS_INTERNAL_ERROR will
 * be returned.
 * - If not enough memory for a new handler is available RTEMS_NO_MEMORY will
 * be returned
 *
 * @see rtems_interrupt_handler_install()
 */
static rtems_status_code bsp_interrupt_handler_install(
  rtems_vector_number vector,
  const char *info,
  rtems_option options,
  rtems_interrupt_handler handler,
  void *arg
)
{
  rtems_status_code sc = RTEMS_SUCCESSFUL;
  rtems_interrupt_level level;
  rtems_vector_number index = 0;
  bsp_interrupt_handler_entry *head = NULL;
  bsp_interrupt_handler_entry *tail = NULL;
  bsp_interrupt_handler_entry *current = NULL;
  bsp_interrupt_handler_entry *match = NULL;
  bool enable_vector = false;

  /* Check parameters and system state */
  if (!bsp_interrupt_is_initialized()) {
    return RTEMS_INTERNAL_ERROR;
  } else if (!bsp_interrupt_is_valid_vector(vector)) {
    return RTEMS_INVALID_ID;
  } else if (handler == NULL) {
    return RTEMS_INVALID_ADDRESS;
  } else if (rtems_interrupt_is_in_progress()) {
    return RTEMS_CALLED_FROM_ISR;
  }

  /* Lock */
  sc = bsp_interrupt_lock();
  if (sc != RTEMS_SUCCESSFUL) {
    return sc;
  }

  /* Get handler table index */
  index = bsp_interrupt_handler_index(vector);

  /* Get head entry of the handler list for current vector */
  head = &bsp_interrupt_handler_table [index];

  if (bsp_interrupt_is_empty_handler_entry(head)) {
    /*
     * No real handler installed yet.  So allocate a new index in
     * the handler table and fill the entry with life.
     */
    if (bsp_interrupt_allocate_handler_index(vector, &index)) {
      rtems_interrupt_disable(level);
      bsp_interrupt_handler_table [index].handler = handler;
      bsp_interrupt_handler_table [index].arg = arg;
      #ifdef BSP_INTERRUPT_USE_INDEX_TABLE
        bsp_interrupt_handler_index_table [vector] = index;
      #endif
      rtems_interrupt_enable(level);
      bsp_interrupt_handler_table [index].info = info;
    } else {
      /* Handler table is full */
      bsp_interrupt_unlock();
      return RTEMS_NO_MEMORY;
    }

    /* This is the first handler so enable the vector later */
    enable_vector = true;
  } else {
    /* Ensure that a unique handler remains unique */
    if (
      RTEMS_INTERRUPT_IS_UNIQUE(options)
        || bsp_interrupt_is_handler_unique(index)
    ) {
      /*
       * Tried to install a unique handler on a not empty
       * list or there is already a unique handler installed.
       */
      bsp_interrupt_unlock();
      return RTEMS_RESOURCE_IN_USE;
    }

    /*
     * Search for the list tail and check if the handler is already
     * installed.
     */
    current = head;
    do {
      if (current->handler == handler && current->arg == arg) {
        match = current;
      }
      tail = current;
      current = current->next;
    } while (current != NULL);

    /* Ensure the handler is not already installed */
    if (match != NULL) {
      /* The handler is already installed */
      bsp_interrupt_unlock();
      return RTEMS_TOO_MANY;
    }

    /* Allocate a new entry */
    current = bsp_interrupt_allocate_handler_entry();
    if (current == NULL) {
      /* Not enough memory */
      bsp_interrupt_unlock();
      return RTEMS_NO_MEMORY;
    }

    /* Set entry */
    current->handler = handler;
    current->arg = arg;
    current->info = info;
    current->next = NULL;

    /* Link to list tail */
    rtems_interrupt_disable(level);
    tail->next = current;
    rtems_interrupt_enable(level);
  }

  /* Make the handler unique if necessary */
  bsp_interrupt_set_handler_unique(index, RTEMS_INTERRUPT_IS_UNIQUE(options));

  /* Enable the vector if necessary */
  if (enable_vector) {
    sc = bsp_interrupt_vector_enable(vector);
    if (sc != RTEMS_SUCCESSFUL) {
      bsp_interrupt_unlock();
      return sc;
    }
  }

  /* Unlock */
  sc = bsp_interrupt_unlock();
  if (sc != RTEMS_SUCCESSFUL) {
    return sc;
  }

  return RTEMS_SUCCESSFUL;
}
예제 #13
0
rtems_status_code rtems_io_register_driver(
  rtems_device_major_number         major,
  const rtems_driver_address_table *driver_table,
  rtems_device_major_number        *registered_major
)
{
  rtems_device_major_number major_limit = _IO_Number_of_drivers;

  if ( rtems_interrupt_is_in_progress() )
    return RTEMS_CALLED_FROM_ISR;

  if ( registered_major == NULL )
    return RTEMS_INVALID_ADDRESS;

  /* Set it to an invalid value */
  *registered_major = major_limit;

  if ( driver_table == NULL )
    return RTEMS_INVALID_ADDRESS;

  if ( rtems_io_is_empty_table( driver_table ) )
    return RTEMS_INVALID_ADDRESS;

  if ( major >= major_limit )
    return RTEMS_INVALID_NUMBER;

  _Thread_Disable_dispatch();

  if ( major == 0 ) {
    rtems_status_code sc = rtems_io_obtain_major_number( registered_major );

    if ( sc != RTEMS_SUCCESSFUL ) {
      _Thread_Enable_dispatch();
      return sc;
    }
    major = *registered_major;
  } else {
    rtems_driver_address_table *const table = _IO_Driver_address_table + major;

    if ( !rtems_io_is_empty_table( table ) ) {
      _Thread_Enable_dispatch();
      return RTEMS_RESOURCE_IN_USE;
    }

    *registered_major = major;
  }

  _IO_Driver_address_table [major] = *driver_table;

  _Thread_Enable_dispatch();

  if ( _IO_All_drivers_initialized ) {
    /* Other drivers have already been initialized, we initialize
     * the driver directly.
     */
    return rtems_io_initialize( major, 0, NULL );
  } else {
    /* The driver will be initialized together with all other drivers
     * in a later stage by _IO_Initialize_all_drivers().
     */
    return RTEMS_SUCCESSFUL;
  }
}
예제 #14
0
void C_exception_handler(BSP_Exception_frame *excPtr)
{
  static int nest = 0;

  int recoverable = 0;
  rtems_id id = 0;
  int synch;
  unsigned n;
  rtems_status_code sc;

  /* Catch recursion */
  nest++;

  if (nest > 2) {
    /* maybe printk() or dereferencing excPtr caused an exception;
     * die silently...
     */
    while (1);
  }

  synch = (int) excPtr->_EXC_number >= 0;
  n = excPtr->_EXC_number & 0x7fff;

  printk("Exception handler called for exception %d (0x%x)\n", n, n);
  printk("\t Next PC or Address of fault = %08x\n", excPtr->EXC_SRR0);
  printk("\t Saved MSR = %08x\n", excPtr->EXC_SRR1);

  if (nest > 1) {
    printk("Recursion in the exception handler detected; I'll spin now...\n");
    while (1);
  }

  /* Try to find out more about the context where this happened */
  printk("\t Context: ");
  if (rtems_interrupt_is_in_progress()) {
    printk("ISR");
  } else if (!_Thread_Executing) {
    printk("Initialization (_Thread_Executing not available yet)");
  } else {
    if (RTEMS_SUCCESSFUL != (sc = rtems_task_ident(RTEMS_SELF, RTEMS_LOCAL, &id))) {
      printk("Unable to determine faulting task; rtems_task_ident() returned %u", sc);
      id = 0;
    } else {
      printk("Task ID 0x%08x", id);
    }
  }
  printk("\n");

  /* Dump registers */

  printk("\t R0  = %08x", GET_GPR(excPtr->GPR0));
  if (synch) {
    printk(" R1  = %08x", GET_GPR(excPtr->GPR1));
    printk(" R2  = %08x", GET_GPR(excPtr->GPR2));
  } else {
    printk("               ");
    printk("               ");
  }
  printk(" R3  = %08x\n", GET_GPR(excPtr->GPR3));
  printk("\t R4  = %08x", GET_GPR(excPtr->GPR4));
  printk(" R5  = %08x", GET_GPR(excPtr->GPR5));
  printk(" R6  = %08x", GET_GPR(excPtr->GPR6));
  printk(" R7  = %08x\n", GET_GPR(excPtr->GPR7));
  printk("\t R8  = %08x", GET_GPR(excPtr->GPR8));
  printk(" R9  = %08x", GET_GPR(excPtr->GPR9));
  printk(" R10 = %08x", GET_GPR(excPtr->GPR10));
  printk(" R11 = %08x\n", GET_GPR(excPtr->GPR11));
  printk("\t R12 = %08x", GET_GPR(excPtr->GPR12));
  if (synch) {
    printk(" R13 = %08x", GET_GPR(excPtr->GPR13));
    printk(" R14 = %08x", GET_GPR(excPtr->GPR14));
    printk(" R15 = %08x\n", GET_GPR(excPtr->GPR15));
    printk("\t R16 = %08x", GET_GPR(excPtr->GPR16));
    printk(" R17 = %08x", GET_GPR(excPtr->GPR17));
    printk(" R18 = %08x", GET_GPR(excPtr->GPR18));
    printk(" R19 = %08x\n", GET_GPR(excPtr->GPR19));
    printk("\t R20 = %08x", GET_GPR(excPtr->GPR20));
    printk(" R21 = %08x", GET_GPR(excPtr->GPR21));
    printk(" R22 = %08x", GET_GPR(excPtr->GPR22));
    printk(" R23 = %08x\n", GET_GPR(excPtr->GPR23));
    printk("\t R24 = %08x", GET_GPR(excPtr->GPR24));
    printk(" R25 = %08x", GET_GPR(excPtr->GPR25));
    printk(" R26 = %08x", GET_GPR(excPtr->GPR26));
    printk(" R27 = %08x\n", GET_GPR(excPtr->GPR27));
    printk("\t R28 = %08x", GET_GPR(excPtr->GPR28));
    printk(" R29 = %08x", GET_GPR(excPtr->GPR29));
    printk(" R30 = %08x", GET_GPR(excPtr->GPR30));
    printk(" R31 = %08x\n", GET_GPR(excPtr->GPR31));
  } else {
    printk("\n");
  }
  printk("\t CR  = %08x\n", excPtr->EXC_CR);
  printk("\t CTR = %08x\n", excPtr->EXC_CTR);
  printk("\t XER = %08x\n", excPtr->EXC_XER);
  printk("\t LR  = %08x\n", excPtr->EXC_LR);

  /* Would be great to print DAR but unfortunately,
   * that is not portable across different CPUs.
   * AFAIK on classic PPC DAR is SPR 19, on the
   * 405 we have DEAR = SPR 0x3d5 and booE says
   * DEAR = SPR 61 :-(
   */
  if (ppc_exc_get_DAR) {
    printk("\t DAR = %08x\n", ppc_exc_get_DAR());
  }

  BSP_printStackTrace(excPtr);

  if (excPtr->_EXC_number == ASM_DEC_VECTOR)
    recoverable = 1;
  if (excPtr->_EXC_number == ASM_SYS_VECTOR)
#ifdef TEST_RAW_EXCEPTION_CODE
    recoverable = 1;
#else
    recoverable = 0;
#endif
  if (!recoverable) {
    if (id) {
      printk("Suspending faulting task (0x%08x)\n", id);
      /* Unnest here because rtems_task_suspend() never returns */
      nest--;
      rtems_task_suspend(id);
    } else {
      printk("unrecoverable exception!!! Push reset button\n");
      while (1);
    }
  } else {
    nest--;
  }
}