⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sma_priority_driver.c

📁 sharp的arm920t 7A400的评估板附带光盘Sharp KEVLH7A400 v0.3b Welcome to the SHARP KEV7A400 Evaluation board
💻 C
📖 第 1 页 / 共 2 页
字号:
/**********************************************************************
 *	$Workfile:   SMA_priority_driver.c  $
 *	$Revision:   1.4  $
 *	$Author:   KovitzP  $
 *	$Date:   Jun 06 2002 08:37:28  $
 *
 *	Project: Useful functions for SOC devices.
 *
 *	Description:
 *   This module contains functions for parsing status bits with
 *   constant latency and software assignable priorities.
 *   Provided functions are:
 *   priority_init_handlers()--create priority encoding environment
 *   priority_install_handler()--associate a status bit with a 
 *                               priority and a handler function
 *   priority_remove_handler()--de-associate a status bit with a 
 *                              prioirty and a handler function
 *   priority_get_priority()--return the priority of a status bit
 *   priority_get_handler()--return the handler function pointer for a 
 *                           status bit
 *
 *   Also,the following macro (see priority_driver.h) assists in
 *   making parser functions.
 *   MAKE_DISPATCHER8()
 *   MAKE_DISPATCHER16()
 *   MAKE_DISPATCHER24()
 *   MAKE_DISPATCHER32()
 *
 * Purpose and Algorithm:
 *   Many peripherals report status based on a single status register
 *   that can be up to 32 bits wide. Interrupt handlers often have
 *   to parse these bits to figure out the appropriate response
 *   to a particular interrupt. The traditional parser looks like
 *   this:
 *
 *   status = read_status_register();
 *   if (status && _BIT(0))
 *   {
 *      handle_bit_0()
 *   }
 *   else if (status & _BIT(1) )
 *   {
 *      handle_bit_1();
 *   }
 *     .....
 *   else if (status & _BIT(31) )
 *   {
 *      handle_bit_31();
 *   }
 *
 *   There are a two main problems with this structure. First,
 *   this is a linear search algorithm. Figuring out which bit is
 *   set is an O(N) operation. Latency in handling a particular
 *   condition is proportional to the place in the parsing loop.
 *
 *   Second, the priority of a particular status bit is fixed in
 *   the handler function and cannot change at run-time. Figuring
 *   out the priority of a particular status bit requires reading
 *   the entire code section of the parser.
 *
 *   The functions in this module attempt to address both problems.
 *   The family of functions provided here support the following
 *   algorith for parsing status bits:
 *
 *   1 status = read_status_register();
 *   2 priority = priority_encode[status];
 *   3 handler_list[priority]();
 *
 *   To understand this algorithm, start with line 3.  The priority
 *   of any condition is a number {0,1,2,..). The lower the number,
 *   the higher the priority. Each condition that can set a status bit 
 *   is assigned a priority. Each condition that can set a status bit
 *   has an associated handler function. The pointers to the  handler
 *   functions are stored in the handler_list[] array. Handler function
 *   pointers are sorted by the priority number of their associated
 *   status bits.
 *
 *   The purpose of line 2 is to convert any combination of set bits
 *   into the single, highest priority. Notice that line 2 seems to
 *   ignore the fact that the status register bits have individual
 *   identities. Rather, the status register is treated as an integer
 *   array index. 
 *
 *   For example, if the status register contents contains bits 1 and 3 
 *   set, then the integer value in the status  variable is 9.
 *   If the condition that set bit 1 is higher priority than the
 *   condition that set bit 3, then priority_encode[9] will contain
 *   the priority number that corresponds to the condition that
 *   set bit 1 (9 is 0b1001, i.e. bits 3 and 1 set). This makes the
 *   priority search algorithm O(1) instead of O(N).
 *
 *   There are two complications. First, the number of entries in the 
 *   priority_encode[] array grows as 2^(number of status bits). For
 *   a 32-bit status register, the priority_encode[] array would be
 *   too large to be practical. To get around this complication, these
 *   functions divide the status register into 8-bit sections. For a
 *   32-bit status register, the parsing algorithm looks like this:
 *
 *   10 status = read_status_register();
 *   11 priority0 = priority_encode0[status & _BITMASK(8)];
 *   12 priority1 = priority_encode1[ (status >> 8 ) & _BITMASK(8)];
 *   13 priority2 = priority_encode2[ (status >> 16) & _BITMASK(8)];
 *   14 priority3 = priority_encode3[ (status >> 24) & _BITMASK(8)];
 *   15 if (priority0 < priority1)
 *   16    priority4 = priority0;
 *   17 else
 *   18    priority4 = prioirty1
 *   19 if (priority2 < priority3)
 *   20    priority5 = priority2;
 *   21 else
 *   22    priority5 = prioirty3;
 *   23 if (priority4 < priority5)
 *   24    priority = priority4;
 *   25 else
 *   26    priority = prioirty5
 *   27 handler_list[priority]();
 *   
 *   For 32 possible status bits, the above algorithm is much
 *   faster than the worst case linear search latency. Also, the 
 *   parsing latency is the same no matter what the priority. The cost
 *   is a table of 33 function pointers and 4 256-entry priority encode
 *   tables. As an added benefit, priorities are assignable at run-
 *   time rather than at compile time.
 *
 *   Some details: The functions in this module use priority numbers
 *   {0,1,2,3,...,number of status bits - 1, number of status bits).
 *   Since the priority numbers start with 0, there would seem to be
 *   an extra priority value. The highest legal priority number is
 *   number of status bits - 1. The number of status bits prioirty
 *   number is called illegal_prioirty. When the priority_encode[]
 *   array is created, all elements are initialized to contain the 
 *   value illegal_priority. The element handler_list[illegal_priority]
 *   contains a pointer to a function for handling unhandled status
 *   bits. The illegal_priority handler should, at a minimum, disable
 *   the source that asserts the illegal status bit so that the
 *   unhandled status won't happen again.
 * 
 *	Revision History:
 *	$Log:   //smaicnt2/pvcs/VM/CHIPS/archives/SOC/Source/SMA_priority_driver.c-arc  $
 * 
 *    Rev 1.4   Jun 06 2002 08:37:28   KovitzP
 * Added missing line breaks and added note to 2nd revision 1.0
 * in the Revision History.
 * 
 *    Rev 1.3   Jun 05 2002 19:59:12   MaysR
 * Corrected error in structure initialization.  Was initializing 
 * unused handler to zero instead of unhandled function address.
 * 
 *    Rev 1.2   Mar 28 2002 14:18:22   lij
 * Add SHARP Legal Header
 * 
 *    Rev 1.1   07 Mar 2002 09:26:50   kovitzp
 * repaired a bug in priority_init_driver() that was causing writes to 
 * address 0 if any of the priority_encode arrays pointers were 
 * NULL.
 * 
 *    Rev 1.0   Jan 31 2002 10:48:14   SuryanG
 * Initial revision. (Renamed to SMA_priority_driver.c).
 * 
 *    Rev 1.2   Jan 31 2002 10:10:50   KovitzP
 * Added default handler argument so that inadvertant source
 * triggers after a source handler is removed will not cause a
 * problem.
 * 
 *    Rev 1.1   Jan 03 2002 16:10:14   KovitzP
 * Corrected typos in rebuild_priority_encode()
 * 
 *    Rev 1.0   Dec 28 2001 13:26:02   KovitzP
 * Initial revision.
 *
 * SHARP MICROELECTRONICS OF THE AMERICAS MAKES NO REPRESENTATION
 * OR WARRANTIES WITH RESPECT TO THE PERFORMANCE OF THIS SOFTWARE,
 * AND SPECIFICALLY DISCLAIMS ANY RESPONSIBILITY FOR ANY DAMAGES, 
 * SPECIAL OR CONSEQUENTIAL, CONNECTED WITH THE USE OF THIS SOFTWARE.
 *
 * SHARP MICROELECTRONICS OF THE AMERICAS PROVIDES THIS SOFTWARE SOLELY 
 * FOR THE PURPOSE OF SOFTWARE DEVELOPMENT INCORPORATING THE USE OF A 
 * SHARP MICROCONTROLLER OR SYSTEM-ON-CHIP PRODUCT. USE OF THIS SOURCE
 * FILE IMPLIES ACCEPTANCE OF THESE CONDITIONS.
 *
 *	COPYRIGHT (C) 2001 SHARP MICROELECTRONICS OF THE AMERICAS, INC.
 *		CAMAS, WA
 *********************************************************************/
#include "SMA_priority_driver.h"

/**********************************************************************
*
* Function: priority_init_driver
*
* Purpose:
*  Initialize the IRQ dispatcher and handler function arrays to a known
*  state so that handlers may be subsequently installed. Set up the
*  IRQ exception vector so that any IRQ exception will vector to
*  the LH7A400_IRQ_handler fuction.
*
* Processing:
*  Associate each source with no handler function handlers[source]=0 
*  and with illegal priority priorities[source] = ILLEGAL_PRIORITY. 
*  Make all priority encode tables priority_encode0...
*  3[all combinations] = nsources (illegal priority).
*
* Parameters:
*  prio: a pointer to a PRIORITY_DATA structure initalized as follows:
*        nsources         contains the number of status bits to parse
*        priorities       points to an array of INT_8 with nsources + 1
*                         elements
*        priority_encode3 is NULL if nsources <= 24 else points to an
*                         array of INT_8 containing 2^(nsources - 24)
*                         elements
*        priority_encode2 is NULL if nsources <= 16 else points to an
*                         array of INT_8 containing 8 elements if
*                         nsources > 24 else points to an array of
*                         INT_8 containing 2^(nsources - 16) elements
*        priority_encode1 is NULL if nsources <= 8 else points to an
*                         array of INT_8 containing 8 elements if
*                         nsources > 16 else points to an array of
*                         INT_8 containing 2^(nsources - 8) elements
*        priority_encode0 points to an array of INT_8 containing 8 
*                         elements if nsources > 8 else points to an
*                         array of INT_8 containing 2^(nsources) 
*                         elements.
*        handlers         points to an array of nsources + 1 pointers
*                         to functions that take no arguments and
*                         that return nothing.
*  fp:   a pointer to the default handler
*
* Outputs:
*  all arrays in the prio structure initialized to the no handlers
*  installed state.
*
* Returns: Nothing
*
* Notes:
*  You must call this function before installing any IRQ handlers and
*  before enabling IRQ interrupts.
*
**********************************************************************/
void priority_init_driver(PRIORITY_DATA * const prio,
                          void (*fp)(void))
{
   INT_32 i;
   INT_32 nsources0, nsources1, nsources2, nsources3;

   /* divide the sources into groups of 8 */
   nsources3 = prio->nsources - 24;
   nsources2 = 8;
   nsources1 = 8;
   nsources0 = 8;
   if (nsources3 <= 0)
   {
      nsources3 = 0;
      nsources2 = prio->nsources - 16;
      if (nsources2 <= 0 )
      {
         nsources2 = 0;
         nsources1 = prio->nsources - 8;
         if (nsources1 <= 0 )
         {
            nsources1 = 0;
            nsources0 = prio->nsources;
         }
      }
   }
   
   for (i = 0; i < prio->nsources; i++)
   {
      prio->priorities[i] = prio->nsources; // an illegal priority
      prio->handlers[i] = fp;
   }
   prio->priorities[prio->nsources] = prio->nsources;
   prio->handlers[prio->nsources] = fp;
   
   if (nsources3 > 0)
   {
       prio->priority_encode3[0] = prio->nsources;
   }
   
   for (i = 1; i < _BIT(nsources3); i++)
   {
      prio->priority_encode3[i] = prio->nsources; // illegal priority
   }   

   if (nsources2 > 0)
   {
       prio->priority_encode2[0] = prio->nsources;
   }

   for (i = 1; i < _BIT(nsources2); i++)
   {
      prio->priority_encode2[i] = prio->nsources; // illegal priority
   }   

   if (nsources1 > 0)
   {
       prio->priority_encode1[0] = prio->nsources;
   }

   for (i = 1; i < _BIT(nsources1); i++)
   {
      prio->priority_encode1[i] = prio->nsources; // illegal priority
   }   

   if (nsources0 > 0)
   {
       prio->priority_encode0[0] = prio->nsources;
   }

   for (i = 1; i < _BIT(nsources0); i++)
   {
      prio->priority_encode0[i] = prio->nsources; // illegal priority
   }   

}


/**********************************************************************
*
* Function: rebuild_priority_encode
*
* Purpose:
*  Assign values to the priority_encode arrays so that a dispatcher
*  can call the highest priority handler function. This function is
*  usually called after assigned a new priority to a source in the
*  prio->priorities array; this function makes the 
*  prio->priority_encodex[] arrays reflect what is stored in the
*  prio->priorities[] array.
*
* Processing:
*  This function uses the following algorithm: for each priority
*  encode array index, look at the index as a binary number. For
*  each bit in that index that is equal to one, check the priority of
*  the associated interrupt source. Assign to the priority encode array
*  at the index location the highest priority of all the sources
*  that correspond to a bit of the index being set. Note that if
*  the source has no handler associated with it, its priority will be
*  ILLEGAL_PRIORITY==prio->nsources. prio->nsources is always
*  a higher number (lower priority) than any valid priority.
*
* Parameters: 
*  prio: a constant pointer to the PRIORITY_DATA structure containing
*        the priority encode arrays. 
*
* Outputs: None
*
* Returns: Nothing
*
* Notes:
*  The structure pointed to by prio must be initialized by the
*  priority_init_driver() function before this function is called.
*
**********************************************************************/
static void rebuild_priority_encode(PRIORITY_DATA * const prio)
{
   UNS_32 i,j,source,mask,not_masked;
   INT_32 nsources0, nsources1, nsources2, nsources3;

   /* divide the sources into groups of 8 */
   nsources3 = prio->nsources - 24;
   nsources2 = 8;
   nsources1 = 8;
   nsources0 = 8;
   if (nsources3 <= 0)
   {
      nsources3 = 0;
      nsources2 = prio->nsources - 16;
      if (nsources2 <= 0 )
      {
         nsources2 = 0;
         nsources1 = prio->nsources - 8;
         if (nsources1 <= 0 )
         {
            nsources1 = 0;
            nsources0 = prio->nsources;
         }
      }
   }
   
   for (i = 1; i < _BIT(nsources0); i++)
   {
      for (source = 0; source < nsources0; source ++)
      {
         mask = 1 << source;
         prio->priority_encode0[mask] = prio->priorities[source];
         if ( (mask & i) == mask)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -