From 6d7a4d2ee7053488f625faccc8bd4dc4d25d6460 Mon Sep 17 00:00:00 2001 From: Chris Johns Date: Fri, 17 Jun 2016 15:05:41 +1000 Subject: Update the BSP howto. Closes #2590. --- bsp_howto/shared_memory_support.rst | 260 ++++++++++++++++++------------------ 1 file changed, 127 insertions(+), 133 deletions(-) (limited to 'bsp_howto/shared_memory_support.rst') diff --git a/bsp_howto/shared_memory_support.rst b/bsp_howto/shared_memory_support.rst index 21cfef9..f73588d 100644 --- a/bsp_howto/shared_memory_support.rst +++ b/bsp_howto/shared_memory_support.rst @@ -1,86 +1,85 @@ .. comment SPDX-License-Identifier: CC-BY-SA-4.0 +.. COMMENT: COPYRIGHT (c) 1988-2009. +.. COMMENT: On-Line Applications Research Corporation (OAR). +.. COMMENT: All rights reserved. + Shared Memory Support Driver ############################ -The Shared Memory Support Driver is responsible for providing glue -routines and configuration information required by the Shared -Memory Multiprocessor Communications Interface (MPCI). The -Shared Memory Support Driver tailors the portable Shared -Memory Driver to a particular target platform. +The Shared Memory Support Driver is responsible for providing glue routines and +configuration information required by the Shared Memory Multiprocessor +Communications Interface (MPCI). The Shared Memory Support Driver tailors the +portable Shared Memory Driver to a particular target platform. -This driver is only required in shared memory multiprocessing -systems that use the RTEMS mulitprocessing support. For more -information on RTEMS multiprocessing capabilities and the -MPCI, refer to the *Multiprocessing Manager* chapter -of the *RTEMS Application C User's Guide*. +This driver is only required in shared memory multiprocessing systems that use +the RTEMS mulitprocessing support. For more information on RTEMS +multiprocessing capabilities and the MPCI, refer to the *Multiprocessing +Manager* chapter of the *RTEMS Application C User's Guide*. Shared Memory Configuration Table ================================= -The Shared Memory Configuration Table is defined in the following -structure: -.. code:: c +The Shared Memory Configuration Table is defined in the following structure: + +.. code-block:: c typedef volatile uint32_t vol_u32; + typedef struct { - vol_u32 \*address; /* write here for interrupt \*/ - vol_u32 value; /* this value causes interrupt \*/ - vol_u32 length; /* for this length (0,1,2,4) \*/ + vol_u32 *address; /* write here for interrupt */ + vol_u32 value; /* this value causes interrupt */ + vol_u32 length; /* for this length (0,1,2,4) */ } Shm_Interrupt_information; + struct shm_config_info { - vol_u32 \*base; /* base address of SHM \*/ - vol_u32 length; /* length (in bytes) of SHM \*/ - vol_u32 format; /* SHM is big or little endian \*/ - vol_u32 (\*convert)(); /* neutral conversion routine \*/ - vol_u32 poll_intr; /* POLLED or INTR driven mode \*/ - void (\*cause_intr)( uint32_t ); - Shm_Interrupt_information Intr; /* cause intr information \*/ + vol_u32 *base; /* base address of SHM */ + vol_u32 length; /* length (in bytes) of SHM */ + vol_u32 format; /* SHM is big or little endian */ + vol_u32 (*convert)(); /* neutral conversion routine */ + vol_u32 poll_intr; /* POLLED or INTR driven mode */ + void (*cause_intr)( uint32_t ); + Shm_Interrupt_information Intr; /* cause intr information */ }; + typedef struct shm_config_info shm_config_table; where the fields are defined as follows: -*base* - is the base address of the shared memory buffer used to pass - messages between the nodes in the system. +``base`` + is the base address of the shared memory buffer used to pass messages + between the nodes in the system. -*length* - is the length (in bytes) of the shared memory buffer used to pass - messages between the nodes in the system. +``length`` + is the length (in bytes) of the shared memory buffer used to pass messages + between the nodes in the system. -*format* - is either SHM_BIG or SHM_LITTLE to indicate that the neutral format - of the shared memory area is big or little endian. The format - of the memory should be chosen to match most of the inter-node traffic. +``format`` + is either ``SHM_BIG`` or ``SHM_LITTLE`` to indicate that the neutral format + of the shared memory area is big or little endian. The format of the + memory should be chosen to match most of the inter-node traffic. -*convert* - is the address of a routine which converts from native format to - neutral format. Ideally, the neutral format is the same as the - native format so this routine is quite simple. +``convert`` + is the address of a routine which converts from native format to neutral + format. Ideally, the neutral format is the same as the native format so + this routine is quite simple. -*poll_intr* - is either INTR_MODE or POLLED_MODE to indicate how the node will be +``poll_intr``, ``cause_intr`` + is either ``INTR_MODE`` or ``POLLED_MODE`` to indicate how the node will be informed of incoming messages. -*cause_intr* - -*Intr* - +``Intr`` is the information required to cause an interrupt on a node. This structure contains the following fields: - *address* - - is the address to write at to cause an interrupt on that node. - For a polled node, this should be NULL. - - *value* + ``address`` + is the address to write at to cause an interrupt on that node. For a + polled node, this should be NULL. + ``value`` is the value to write to cause an interrupt. - *length* - + ``length`` is the length of the entity to write on the node to cause an interrupt. This can be 0 to indicate polled operation, 1 to write a byte, 2 to write a sixteen-bit entity, and 4 to write a thirty-two bit entity. @@ -91,158 +90,153 @@ Primitives Convert Address --------------- -The ``Shm_Convert_address`` is responsible for converting an address -of an entity in the shared memory area into the address that should be -used from this node. Most targets will simply return the address -passed to this routine. However, some target boards will have a special -window onto the shared memory. For example, some VMEbus boards have -special address windows to access addresses that are normally reserved -in the CPU's address space. -.. code:: c +The ``Shm_Convert_address`` is responsible for converting an address of an +entity in the shared memory area into the address that should be used from this +node. Most targets will simply return the address passed to this routine. +However, some target boards will have a special window onto the shared memory. +For example, some VMEbus boards have special address windows to access +addresses that are normally reserved in the CPU's address space. + +.. code-block:: c - void \*Shm_Convert_address( void \*address ) + void *Shm_Convert_address( void *address ) { - return the local address version of this bus address + return the local address version of this bus address } Get Configuration ----------------- -The ``Shm_Get_configuration`` routine is responsible for filling in the -Shared Memory Configuration Table passed to it. -.. code:: c +The ``Shm_Get_configuration`` routine is responsible for filling in the Shared +Memory Configuration Table passed to it. + +.. code-block:: c void Shm_Get_configuration( - uint32_t localnode, - shm_config_table \**shmcfg + uint32_t localnode, + shm_config_table **shmcfg ) { - fill in the Shared Memory Configuration Table + fill in the Shared Memory Configuration Table } Locking Primitives ------------------ -This is a collection of routines that are invoked by the portable -part of the Shared Memory Driver to manage locks in the shared -memory buffer area. Accesses to the shared memory must be -atomic. Two nodes in a multiprocessor system must not be manipulating -the shared data structures simultaneously. The locking primitives -are used to insure this. +This is a collection of routines that are invoked by the portable part of the +Shared Memory Driver to manage locks in the shared memory buffer area. +Accesses to the shared memory must be atomic. Two nodes in a multiprocessor +system must not be manipulating the shared data structures simultaneously. The +locking primitives are used to insure this. To avoid deadlock, local processor interrupts should be disabled the entire time the locked queue is locked. -The locking primitives operate on the lock``field`` of the ``Shm_Locked_queue_Control`` -data structure. This structure is defined as follows: -.. code:: c +The locking primitives operate on the lock ``field`` of the +``Shm_Locked_queue_Control`` data structure. This structure is defined as +follows: + +.. code-block:: c typedef struct { - vol_u32 lock; /* lock field for this queue \*/ - vol_u32 front; /* first envelope on queue \*/ - vol_u32 rear; /* last envelope on queue \*/ - vol_u32 owner; /* receiving (i.e. owning) node \*/ + vol_u32 lock; /* lock field for this queue */ + vol_u32 front; /* first envelope on queue */ + vol_u32 rear; /* last envelope on queue */ + vol_u32 owner; /* receiving (i.e. owning) node */ } Shm_Locked_queue_Control; where each field is defined as follows: -*lock* - is the lock field. Every node in the system must agree on how this - field will be used. Many processor families provide an atomic - "test and set" instruction that is used to manage this field. +``lock`` + is the lock field. Every node in the system must agree on how this field + will be used. Many processor families provide an atomic "test and set" + instruction that is used to manage this field. -*front* +``front`` is the index of the first message on this locked queue. -*rear* +``rear`` is the index of the last message on this locked queue. -*owner* +``owner`` is the node number of the node that currently has this structure locked. Initializing a Shared Lock ~~~~~~~~~~~~~~~~~~~~~~~~~~ -The ``Shm_Initialize_lock`` routine is responsible for -initializing the lock field. This routines usually is implemented -as follows: -.. code:: c +The ``Shm_Initialize_lock`` routine is responsible for initializing the lock +field. This routines usually is implemented as follows: + +.. code-block:: c void Shm_Initialize_lock( - Shm_Locked_queue_Control \*lq_cb + Shm_Locked_queue_Control *lq_cb ) { - lq_cb->lock = LQ_UNLOCKED; + lq_cb->lock = LQ_UNLOCKED; } Acquiring a Shared Lock ~~~~~~~~~~~~~~~~~~~~~~~ -The ``Shm_Lock`` routine is responsible for -acquiring the lock field. Interrupts should be -disabled while that lock is acquired. If the lock -is currently unavailble, then the locking routine -should delay a few microseconds to allow the other -node to release the lock. Doing this reduces bus contention +The ``Shm_Lock`` routine is responsible for acquiring the lock field. +Interrupts should be disabled while that lock is acquired. If the lock is +currently unavailble, then the locking routine should delay a few microseconds +to allow the other node to release the lock. Doing this reduces bus contention for the lock. This routines usually is implemented as follows: -.. code:: c + +.. code-block:: c void Shm_Lock( - Shm_Locked_queue_Control \*lq_cb + Shm_Locked_queue_Control *lq_cb ) { - disable processor interrupts - set Shm_isrstat to previous interrupt disable level - while ( TRUE ) { - atomically attempt to acquire the lock - if the lock was acquired - return - delay some small period of time - } + disable processor interrupts + set Shm_isrstat to previous interrupt disable level + + while ( TRUE ) { + atomically attempt to acquire the lock + if the lock was acquired + return + delay some small period of time + } } Releasing a Shared Lock ~~~~~~~~~~~~~~~~~~~~~~~ -The ``Shm_Unlock`` routine is responsible for -releasing the lock field and reenabling processor -interrupts. This routines usually is implemented as follows: -.. code:: c +The ``Shm_Unlock`` routine is responsible for releasing the lock field and +reenabling processor interrupts. This routines usually is implemented as +follows: + +.. code-block:: c void Shm_Unlock( - Shm_Locked_queue_Control \*lq_cb + Shm_Locked_queue_Control *lq_cb ) { - set the lock to the unlocked value - reenable processor interrupts to their level prior - to the lock being acquired. This value was saved - in the global variable Shm_isrstat + set the lock to the unlocked value + reenable processor interrupts to their level prior + to the lock being acquired. This value was saved + in the global variable Shm_isrstat } Installing the MPCI ISR ======================= -The ``Shm_setvec`` is invoked by the portable portion -of the shared memory to install the interrupt service routine -that is invoked when an incoming message is announced. Some -target boards support an interprocessor interrupt or mailbox -scheme and this is where the ISR for that interrupt would be -installed. +The ``Shm_setvec`` is invoked by the portable portion of the shared memory to +install the interrupt service routine that is invoked when an incoming message +is announced. Some target boards support an interprocessor interrupt or +mailbox scheme and this is where the ISR for that interrupt would be installed. On an interrupt driven node, this routine would be implemented as follows: -.. code:: c + +.. code-block:: c void Shm_setvec( void ) { - install the interprocessor communications ISR + install the interprocessor communications ISR } On a polled node, this routine would be empty. - -.. COMMENT: COPYRIGHT (c) 1988-2009. - -.. COMMENT: On-Line Applications Research Corporation (OAR). - -.. COMMENT: All rights reserved. - -- cgit v1.2.3