Back to home page

LXR

 
 

    


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

0001 /*
0002  *  Simple test program to demonstrate priority inversion when blocking
0003  *
0004    -Ulf Ivraeus ------------- --- -- -  -   -
0005  *  Saab Ericsson Space AB
0006  *  phone:  +46 (0)31 735 4542
0007  *  e-mail: ulf.ivraeus@space.se
0008  *  ----------------------------- --- -- -  -   -
0009  *
0010  *  The license and distribution terms for this file may be
0011  *  found in the file LICENSE in this distribution or at
0012  *  http://www.rtems.org/license/LICENSE.
0013  */
0014 
0015 /********************************************************************
0016 
0017   Semaphore Ids:
0018     Sync Mutex Id   = 0x18010009
0019     Local Mutex Id  = 0x1801000a
0020     Remote Mutex Id = 0x1801000b
0021 
0022   Task Ids:
0023     TaMedium[0] Id  = 0x08010002
0024     TaMedium[1] Id  = 0x08010003
0025     TaMedium[2] Id  = 0x08010004
0026     TaHigh Id       = 0x08010005
0027     TaLow Id        = 0x08010006
0028     TaHwSim Id      = 0x08010007
0029 
0030 ********************************************************************/
0031 
0032 /********************************************************************/
0033 /* define this to use the RTEMS 4.5 scheme for object names */
0034 /* #define TEST_ON_RTEMS_45 */
0035 
0036 /* define this to print the Id of the calling task */
0037 /* #define TEST_ON_TASK_ID */
0038 
0039 /* define this if you are (1) on a ERC32 and (2) want a SW ISR trigger */
0040 #if defined(__sparc__)
0041 /* #define TEST_USE_ISR */
0042 #endif
0043 
0044 /* define this if you want the test to exit */
0045 #define TEST_EXIT_AFTER_ITERATIONS 10
0046 /********************************************************************/
0047 
0048 #define CONFIGURE_INIT
0049 
0050 #ifdef HAVE_CONFIG_H
0051 #include "config.h"
0052 #endif
0053 
0054 #include <bsp.h>
0055 #include <stdio.h>
0056 #include "tmacros.h"
0057 
0058 #include <rtems/score/threadimpl.h>
0059 
0060 const char rtems_test_name[] = "SP 35";
0061 
0062 #if defined(TEST_EXIT_AFTER_ITERATIONS)
0063 volatile uint32_t Iterations = 0;
0064 #endif
0065 
0066 const char *CallerName(void);
0067 
0068 /* Task entry point prototypes */
0069 rtems_task Init(rtems_task_argument ignored);
0070 rtems_task Medium_Exec(rtems_task_argument TaskArg);
0071 rtems_task Low_Exec(rtems_task_argument TaskArg);
0072 rtems_task High_Exec(rtems_task_argument TaskArg);
0073 rtems_task LocalHwSim_Exec(rtems_task_argument TaskArg);
0074 
0075 /* ISR that signals that HW has completed */
0076 rtems_isr  LocalHwIsr(/*in*/ rtems_vector_number   Vector);
0077 
0078 /* Test driver functions */
0079 void AccessLocalHw(void);
0080 void AccessRemoteHw(void);
0081 
0082 const char *CallerName(void)
0083 {
0084   static char buffer[32];
0085   Thread_Control *executing = _Thread_Get_executing();
0086 #if defined(TEST_PRINT_TASK_ID)
0087   sprintf( buffer, "0x%08x -- %d",
0088       rtems_task_self(), _Thread_Get_priority( executing ) );
0089 #else
0090   volatile union {
0091     uint32_t u;
0092     unsigned char c[4];
0093   } TempName;
0094 
0095   #if defined(TEST_ON_RTEMS_45)
0096     TempName.u = *(uint32_t *)executing->Object.name;
0097   #else
0098     TempName.u = (uint32_t) executing->Object.name.name_u32;
0099   #endif
0100   sprintf( buffer, "%c%c%c%c -- %" PRIdPriority_Control,
0101       TempName.c[0], TempName.c[1], TempName.c[2], TempName.c[3],
0102       _Thread_Get_priority( executing )
0103   );
0104 #endif
0105   return buffer;
0106 }
0107 
0108 #define NofMediumTask_C 3
0109 
0110 /* RTEMS identifiers */
0111 rtems_id  TaMedium[NofMediumTask_C]; /* Medium-prio tasks accessing */
0112                                      /*    the common local HW */
0113 rtems_id  TaHwSim;                   /* HW simulator */
0114 rtems_id  TaLow;                     /* Low-prio task accessing common */
0115                                      /*    remote HW */
0116 rtems_id  TaHigh;                    /* High-prio task accessing common */
0117                                      /*    remote HW */
0118 
0119 
0120 rtems_id  LocalHwSync_S;             /* Syncrhonize task to local HW */
0121 rtems_id  LocalHwAccess_R;           /* Execlusive access to the local HW */
0122 rtems_id  RemoteHwAccess_R;          /* Execlusive access to the remote HW */
0123 
0124 
0125 /* The following variable triggers simulated HW activity */
0126 volatile bool StartHw = false;
0127 
0128 rtems_task Medium_Exec(rtems_task_argument TaskArg)
0129 {
0130   printf("Medium_Exec (%" PRIdrtems_task_argument ") begins...\n", TaskArg);
0131 
0132   rtems_task_wake_after(50);
0133 
0134   while(1) {
0135     AccessLocalHw();
0136   }
0137 
0138   /* JRS - task does not get here */
0139 
0140   printf("Medium_Exec (%" PRIdrtems_task_argument ") ends...\n", TaskArg);
0141   while(1) {
0142     rtems_task_wake_after(10000);
0143   }
0144 }
0145 
0146 rtems_task High_Exec(rtems_task_argument TaskArg)
0147 {
0148   printf("High_Exec (%" PRIdrtems_task_argument ") begins...\n", TaskArg);
0149 
0150   /* Delay more than the Low-prio task so that Remote HW access resource is
0151    * taken before call to AccesRemoteHw.
0152    */
0153   rtems_task_wake_after(250);
0154 
0155   while(1) {
0156     AccessRemoteHw();
0157   }
0158 
0159   /* JRS - task does not get here */
0160 
0161   printf("High_Exec (%" PRIdrtems_task_argument ") ends...\n", TaskArg);
0162   while(1) {
0163     rtems_task_wake_after(10000);
0164   }
0165   /* task does not get here */
0166 }
0167 
0168 rtems_task Low_Exec(rtems_task_argument TaskArg)
0169 {
0170   printf("Low_Exec (%" PRIdrtems_task_argument ") begins...\n", TaskArg);
0171 
0172   /* Delay less than High-prio task so that we take the remote HW access
0173    * resource before it does it. However, delay longer than the mid-prio
0174    * tasks so that we know for certain that they have taken control over
0175    * the local HW access.
0176    */
0177   rtems_task_wake_after(100);
0178 
0179   while(1) {
0180     AccessRemoteHw();
0181   }
0182 
0183   /* JRS - task does not get here */
0184 
0185   printf("Low_Exec (%" PRIdrtems_task_argument ") ends...\n", TaskArg);
0186   while(1) {
0187     rtems_task_wake_after(10000);
0188   }
0189 }
0190 
0191 
0192 rtems_task LocalHwSim_Exec(rtems_task_argument TaskArg)
0193 {
0194 #if 0
0195   int ISRCount = 0;
0196 #endif
0197   printf("LocalHwSim_Exec begins...\n");
0198 
0199   while(1) {
0200     if (StartHw) {
0201       /* A test task has activated the HW, wait for a while and then
0202        * generate an interrupt
0203        */
0204       rtems_task_wake_after(100);
0205 
0206       StartHw = FALSE;
0207 #if defined(TEST_USE_ISR)
0208       __asm__ volatile ("ta 5");
0209       __asm__ volatile ("nop");
0210       __asm__ volatile ("nop");
0211 #else
0212       LocalHwIsr( 0x85 );
0213 #endif
0214     }
0215 
0216   }
0217 
0218   printf("LocalHwSim_Exec ends...\n");
0219   while(1) {
0220     rtems_task_wake_after(10000);
0221   }
0222 }
0223 
0224 
0225 rtems_isr  LocalHwIsr(/*in*/ rtems_vector_number   Vector)
0226 {
0227   rtems_status_code status;
0228 
0229   /* Signal synchroniztion semaphore to invoke waiting task */
0230   status = rtems_semaphore_release(LocalHwSync_S);
0231   if (status != RTEMS_SUCCESSFUL) {
0232     printf( "LocalHwISR release %d\n", status );
0233     while(1); /* Error */
0234   }
0235 
0236   return;
0237 }
0238 
0239 void AccessLocalHw(void)
0240 {
0241   rtems_status_code     Sts;
0242 
0243   printf("  AccessLocalHw called by %s\n", CallerName());
0244 
0245   /* Obtain exclusive access to local HW, Start HW, Wait for completion,
0246    * Release access
0247    */
0248 
0249   Sts = rtems_semaphore_obtain(LocalHwAccess_R, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
0250   directive_failed( Sts, "rtems_semaphore_obtain(LocalHwAccess_R...)" );
0251 
0252   StartHw = TRUE;
0253 
0254   Sts = rtems_semaphore_obtain(LocalHwSync_S, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
0255   directive_failed( Sts, "rtems_semaphore_obtain(LocalHwAccess_R...)" );
0256 
0257   Sts = rtems_semaphore_release(LocalHwAccess_R);
0258   directive_failed( Sts, "rtems_semaphore_release(LocalHwAccess_R)" );
0259 
0260   printf("  AccessLocalHw returns to %s\n", CallerName());
0261   #if defined(TEST_EXIT_AFTER_ITERATIONS)
0262     if ( ++Iterations == 10 ) {
0263       TEST_END();
0264       exit(0);
0265     }
0266   #endif
0267   return;
0268 }
0269 
0270 void AccessRemoteHw(void)
0271 {
0272   rtems_status_code     Sts;
0273 
0274   printf("AccessRemoteHw called by %s\n", CallerName());
0275 
0276   /* Obtain exclusive access to remote HW, Start HW, Wait for completion,
0277    * Release access
0278    */
0279 
0280   Sts = rtems_semaphore_obtain(RemoteHwAccess_R, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
0281   directive_failed( Sts, "rtems_semaphore_obtain(RemoteHwAccess_R...)" );
0282 
0283   /* Carry out the remote access via the Local HW interface */
0284   printf("AccessRemoteHw access local %s\n", CallerName());
0285   AccessLocalHw();
0286 
0287   Sts = rtems_semaphore_release(RemoteHwAccess_R);
0288   directive_failed( Sts, "rtems_semaphore_release(RemoreHwAccess_R" );
0289 
0290   printf("AccessRemoteHw returns to %s\n", CallerName());
0291   return;
0292 }
0293 
0294 /*************************************************************************/
0295 /**********************        INITIALIZATION        *********************/
0296 /*************************************************************************/
0297 
0298 /* The Init operation (the Init-task) */
0299 rtems_task Init(rtems_task_argument ignored)
0300 {
0301   rtems_status_code status;
0302 #if defined(TEST_USE_ISR)
0303   rtems_isr_entry   DummyIsr;
0304 #endif
0305   int i;
0306 
0307   TEST_BEGIN();
0308 
0309   /* Create synchronisation semaphore for LocalHwIsr -> Test Tasks */
0310   status = rtems_semaphore_create(
0311     rtems_build_name ('S', 'Y', 'N', 'C'),           /* name */
0312     0,                                               /* initial count = 0 */
0313     RTEMS_LOCAL                   |
0314     RTEMS_SIMPLE_BINARY_SEMAPHORE |
0315     RTEMS_NO_INHERIT_PRIORITY     |
0316     RTEMS_NO_PRIORITY_CEILING     |
0317     RTEMS_FIFO,
0318     0,
0319     &LocalHwSync_S);                                 /* *id */
0320   directive_failed( status, "rtems_semaphore_create (SYNC)" );
0321 
0322   printf( "Sync Mutex Id = 0x%08" PRIxrtems_id "\n", LocalHwSync_S );
0323 
0324   /* Create resource semaphore for exclusive access to the local HW */
0325   status = rtems_semaphore_create(
0326     rtems_build_name ('R', 'E', 'S', '1'), /* name             */
0327     1,                                     /* count            */
0328     RTEMS_PRIORITY         |
0329     RTEMS_BINARY_SEMAPHORE |
0330     RTEMS_INHERIT_PRIORITY |
0331     RTEMS_LOCAL,                           /* attribute_set    */
0332     1, /* insignificant */                 /* priority_ceiling */
0333     &LocalHwAccess_R);                     /* *id              */
0334   directive_failed( status, "rtems_semaphore_create (RES1)" );
0335 
0336   printf( "Local Mutex Id = 0x%08" PRIxrtems_id "\n", LocalHwAccess_R );
0337 
0338   /* Create resource semaphore for exclusive access to the remote HW */
0339   status = rtems_semaphore_create(
0340     rtems_build_name ('R', 'E', 'S', '2'), /* name             */
0341     1,                                     /* count            */
0342     RTEMS_PRIORITY         |
0343     RTEMS_BINARY_SEMAPHORE |
0344     RTEMS_INHERIT_PRIORITY |
0345     RTEMS_LOCAL,                           /* attribute_set    */
0346     1, /* insignificant */                 /* priority_ceiling */
0347     &RemoteHwAccess_R);                    /* *id              */
0348   directive_failed( status, "rtems_semaphore_create (RES2)" );
0349 
0350   printf( "Remote Mutex Id = 0x%08" PRIxrtems_id "\n", RemoteHwAccess_R );
0351 
0352 #if defined(TEST_USE_ISR)
0353   /* Install ISR for HW/SW synchronization, use ta 0x85 which is synchronous */
0354   status = rtems_interrupt_catch(LocalHwIsr, 0x85 + 0x100, &DummyIsr);
0355   directive_failed( status, "rtems_interrupt_catch" );
0356 #endif
0357 
0358 
0359   printf("Ending Init-task\n");
0360   /* Create and start all tasks in the test */
0361 
0362   /* -- Medium-prio Test Tasks --- */
0363   for (i = 0; i < NofMediumTask_C; i++) {
0364 #define MEDIUM_PRIORITY ((RTEMS_MAXIMUM_PRIORITY / 2u) + 1u)
0365     status = rtems_task_create(
0366       rtems_build_name('M','E','D','0'+i),               /* Name */
0367       MEDIUM_PRIORITY,                                   /* Priority */
0368       RTEMS_MINIMUM_STACK_SIZE*2,                        /* Stack size (8KB) */
0369       RTEMS_DEFAULT_MODES | RTEMS_NO_ASR,                /* Mode */
0370       RTEMS_DEFAULT_ATTRIBUTES | RTEMS_FLOATING_POINT,   /* Attributes */
0371       &TaMedium[i]);                                     /* Assigned ID */
0372     directive_failed( status, "rtems_task_create (MEDn)" );
0373 
0374     printf( "TaMedium[%d] Id = 0x%08" PRIxrtems_id "\n", i, TaMedium[i] );
0375     status = rtems_task_start(
0376       TaMedium[i],
0377       Medium_Exec,
0378       (rtems_task_argument) i
0379     );
0380     directive_failed( status, "rtems_task_start (MEDn)" );
0381   }
0382 
0383   /* -- High-prio Test Task --- */
0384 #define HIGH_PRIORITY ((RTEMS_MAXIMUM_PRIORITY / 2u))
0385   status = rtems_task_create(
0386     rtems_build_name('H','I','G','H'),                 /* Name */
0387     HIGH_PRIORITY,                                     /* Priority */
0388     RTEMS_MINIMUM_STACK_SIZE*2,                        /* Stack size (8KB) */
0389     RTEMS_DEFAULT_MODES | RTEMS_NO_ASR,                /* Mode */
0390     RTEMS_DEFAULT_ATTRIBUTES | RTEMS_FLOATING_POINT,   /* Attributes */
0391     &TaHigh);                                          /* Assigned ID */
0392   directive_failed( status, "rtems_task_create (HIGH)" );
0393 
0394   printf( "TaHigh Id = 0x%08" PRIxrtems_id "\n", TaHigh );
0395   status = rtems_task_start(TaHigh, High_Exec, 0);
0396   directive_failed( status, "rtems_task_start (HIGH)" );
0397 
0398   /* -- Low-prio Test Task --- */
0399 #define LOW_PRIORITY (RTEMS_MAXIMUM_PRIORITY - 1u)
0400   status = rtems_task_create(
0401     rtems_build_name('L','O','W',' '),                 /* Name */
0402     LOW_PRIORITY,                                      /* Priority */
0403     RTEMS_MINIMUM_STACK_SIZE*2,                        /* Stack size (8KB) */
0404     RTEMS_DEFAULT_MODES | RTEMS_NO_ASR,                /* Mode */
0405     RTEMS_DEFAULT_ATTRIBUTES | RTEMS_FLOATING_POINT,   /* Attributes */
0406     &TaLow);                                           /* Assigned ID */
0407   directive_failed( status, "rtems_task_create (LOW)" );
0408 
0409   printf( "TaLow Id = 0x%08" PRIxrtems_id "\n", TaLow );
0410   status = rtems_task_start(TaLow, Low_Exec, 0);
0411   directive_failed( status, "rtems_task_start (LOW)" );
0412 
0413   /* -- HW Simulator Task --- */
0414 #define HWTASK_PRIORITY (RTEMS_MAXIMUM_PRIORITY - 2u)
0415   status = rtems_task_create(
0416     rtems_build_name('H','W','S','M'),                 /* Name */
0417     HWTASK_PRIORITY,                                   /* Priority */
0418     RTEMS_MINIMUM_STACK_SIZE*2,                        /* Stack size (8KB) */
0419     RTEMS_DEFAULT_MODES | RTEMS_NO_ASR,                /* Mode */
0420     RTEMS_DEFAULT_ATTRIBUTES | RTEMS_FLOATING_POINT,   /* Attributes */
0421     &TaHwSim);                                         /* Assigned ID */
0422   directive_failed( status, "rtems_task_create (HWSM)" );
0423 
0424   printf( "TaHwSim Id = 0x%08" PRIxrtems_id "\n", TaHwSim );
0425 
0426   status = rtems_task_start(TaHwSim, LocalHwSim_Exec, 0);
0427   directive_failed( status, "rtems_task_start (HWSM)" );
0428 
0429   /* Destroy the Init task (and let the ready tasks start running) */
0430   rtems_task_exit();
0431 }
0432 
0433 /* configuration information */
0434 
0435 #define CONFIGURE_APPLICATION_NEEDS_SIMPLE_CONSOLE_DRIVER
0436 #define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
0437 
0438 #define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION
0439 
0440 #define CONFIGURE_RTEMS_INIT_TASKS_TABLE
0441 
0442 #define CONFIGURE_EXTRA_TASK_STACKS (RTEMS_MINIMUM_STACK_SIZE * 3)
0443 
0444 #define CONFIGURE_MAXIMUM_TASKS 10
0445 #define CONFIGURE_MAXIMUM_SEMAPHORES 10
0446 
0447 #include <rtems/confdefs.h>
0448 
0449 /* end of file */