Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:24:54

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /**
0004  * @file
0005  *
0006  * @ingroup RTEMSTestSuitesValidation
0007  *
0008  * @brief This source file contains the implementation of CallWithinISRClear(),
0009  *   CallWithinISRGetVector(), CallWithinISR(), CallWithinISRRaise(),
0010  *   CallWithinISRSubmit(), and CallWithinISRWait().
0011  */
0012 
0013 /*
0014  * Copyright (C) 2021, 2022 embedded brains GmbH & Co. KG
0015  *
0016  * Redistribution and use in source and binary forms, with or without
0017  * modification, are permitted provided that the following conditions
0018  * are met:
0019  * 1. Redistributions of source code must retain the above copyright
0020  *    notice, this list of conditions and the following disclaimer.
0021  * 2. Redistributions in binary form must reproduce the above copyright
0022  *    notice, this list of conditions and the following disclaimer in the
0023  *    documentation and/or other materials provided with the distribution.
0024  *
0025  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0026  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0027  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0028  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0029  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0030  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0031  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0032  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0033  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0034  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0035  * POSSIBILITY OF SUCH DAMAGE.
0036  */
0037 
0038 #ifdef HAVE_CONFIG_H
0039 #include "config.h"
0040 #endif
0041 
0042 #include "tx-support.h"
0043 
0044 #include <rtems/sysinit.h>
0045 #include <rtems/score/chainimpl.h>
0046 
0047 #include <bsp.h>
0048 #include <bsp/irq-generic.h>
0049 
0050 /* Some target architectures need this variable for <tm27.h> */
0051 uint32_t Interrupt_nest;
0052 
0053 #define _RTEMS_TMTEST27
0054 
0055 #include <tm27.h>
0056 
0057 typedef struct {
0058   Chain_Control pending;
0059   RTEMS_INTERRUPT_LOCK_MEMBER( lock )
0060 } CallWithinISRContext;
0061 
0062 static CallWithinISRContext CallWithinISRInstance = {
0063 #if defined( RTEMS_SMP )
0064   .lock = RTEMS_INTERRUPT_LOCK_INITIALIZER( "CallWithinISR" ),
0065 #endif
0066   .pending = CHAIN_INITIALIZER_EMPTY( CallWithinISRInstance.pending )
0067 };
0068 
0069 void CallWithinISRRaise( void )
0070 {
0071   Cause_tm27_intr();
0072 }
0073 
0074 void CallWithinISRClear( void )
0075 {
0076   Clear_tm27_intr();
0077 }
0078 
0079 #ifdef TM27_USE_VECTOR_HANDLER
0080 static rtems_isr CallWithinISRHandler( rtems_vector_number arg )
0081 #else
0082 static void CallWithinISRHandler( void *arg )
0083 #endif
0084 {
0085   CallWithinISRContext *ctx;
0086 
0087   (void) arg;
0088   ctx = &CallWithinISRInstance;
0089 
0090   CallWithinISRClear();
0091 
0092   while ( true ) {
0093     rtems_interrupt_lock_context lock_context;
0094     CallWithinISRRequest        *request;
0095 
0096     rtems_interrupt_lock_acquire( &ctx->lock, &lock_context );
0097     request = (CallWithinISRRequest *)
0098       _Chain_Get_unprotected( &ctx->pending );
0099     rtems_interrupt_lock_release( &ctx->lock, &lock_context );
0100 
0101     if ( request == NULL ) {
0102       break;
0103     }
0104 
0105     ( *request->handler )( request->arg );
0106     _Atomic_Store_uint( &request->done, 1, ATOMIC_ORDER_RELEASE );
0107   }
0108 }
0109 
0110 void CallWithinISR( void ( *handler )( void * ), void *arg )
0111 {
0112   CallWithinISRRequest request;
0113 
0114   request.handler = handler;
0115   request.arg = arg;
0116   CallWithinISRSubmit( &request );
0117   CallWithinISRWait( &request );
0118 }
0119 
0120 void CallWithinISRSubmit( CallWithinISRRequest *request )
0121 {
0122   CallWithinISRContext        *ctx;
0123   rtems_interrupt_lock_context lock_context;
0124 
0125   ctx = &CallWithinISRInstance;
0126 
0127   rtems_interrupt_lock_acquire( &ctx->lock, &lock_context );
0128   _Atomic_Store_uint( &request->done, 0, ATOMIC_ORDER_RELAXED );
0129   _Chain_Initialize_node( &request->node );
0130   _Chain_Append_unprotected( &ctx->pending, &request->node );
0131   rtems_interrupt_lock_release( &ctx->lock, &lock_context );
0132 
0133   CallWithinISRRaise();
0134 }
0135 
0136 void CallWithinISRWait( const CallWithinISRRequest *request )
0137 {
0138   while ( _Atomic_Load_uint( &request->done, ATOMIC_ORDER_ACQUIRE ) == 0 ) {
0139     /* Wait */
0140   }
0141 }
0142 
0143 #if !defined( TM27_INTERRUPT_VECTOR_DEFAULT )
0144 static void CallWithinISRIsHandlerInstalled(
0145   void                   *arg,
0146   const char             *info,
0147   rtems_option            option,
0148   rtems_interrupt_handler handler,
0149   void                   *handler_arg
0150 )
0151 {
0152   (void) info;
0153   (void) option;
0154   (void) handler_arg;
0155 
0156   if ( handler == CallWithinISRHandler && handler_arg == NULL ) {
0157     *(bool *) arg = true;
0158   }
0159 }
0160 #endif
0161 
0162 rtems_vector_number CallWithinISRGetVector( void )
0163 {
0164 #if defined( TM27_INTERRUPT_VECTOR_DEFAULT )
0165   return TM27_INTERRUPT_VECTOR_DEFAULT;
0166 #else
0167   rtems_vector_number vector;
0168 
0169   for ( vector = 0; vector < BSP_INTERRUPT_VECTOR_COUNT; ++vector ) {
0170     bool installed;
0171 
0172     installed = false;
0173     (void) rtems_interrupt_handler_iterate(
0174       vector,
0175       CallWithinISRIsHandlerInstalled,
0176       &installed
0177     );
0178 
0179     if ( installed ) {
0180       return vector;
0181     }
0182   }
0183 
0184   return UINT32_MAX;
0185 #endif
0186 }
0187 
0188 rtems_vector_number GetSoftwareInterruptVector( void )
0189 {
0190 #if defined( TM27_INTERRUPT_VECTOR_ALTERNATIVE )
0191   return TM27_INTERRUPT_VECTOR_ALTERNATIVE;
0192 #else
0193   return UINT32_MAX;
0194 #endif
0195 }
0196 
0197 rtems_status_code RaiseSoftwareInterrupt( rtems_vector_number vector )
0198 {
0199 #if defined( TM27_INTERRUPT_VECTOR_ALTERNATIVE )
0200   if ( vector == TM27_INTERRUPT_VECTOR_ALTERNATIVE ) {
0201     return _TM27_Raise_alternative();
0202   }
0203 #endif
0204 
0205   return rtems_interrupt_raise( vector );
0206 }
0207 
0208 rtems_status_code ClearSoftwareInterrupt( rtems_vector_number vector )
0209 {
0210 #if defined( TM27_INTERRUPT_VECTOR_ALTERNATIVE )
0211   if ( vector == TM27_INTERRUPT_VECTOR_ALTERNATIVE ) {
0212     return _TM27_Clear_alternative();
0213   }
0214 #endif
0215 
0216   return rtems_interrupt_clear( vector );
0217 }
0218 
0219 static void CallWithinISRInitialize( void )
0220 {
0221   Install_tm27_vector( CallWithinISRHandler );
0222 }
0223 
0224 RTEMS_SYSINIT_ITEM(
0225   CallWithinISRInitialize,
0226   RTEMS_SYSINIT_DEVICE_DRIVERS,
0227   RTEMS_SYSINIT_ORDER_MIDDLE
0228 );