Back to home page

LXR

 
 

    


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

0001 /*
0002  * SPDX-License-Identifier: BSD-2-Clause
0003  *
0004  * Copyright (C) 2022 German Aerospace Center (DLR)
0005  *
0006  * Redistribution and use in source and binary forms, with or without
0007  * modification, are permitted provided that the following conditions
0008  * are met:
0009  * 1. Redistributions of source code must retain the above copyright
0010  *    notice, this list of conditions and the following disclaimer.
0011  * 2. Redistributions in binary form must reproduce the above copyright
0012  *    notice, this list of conditions and the following disclaimer in the
0013  *    documentation and/or other materials provided with the distribution.
0014  *
0015  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0016  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0017  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0018  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0019  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0020  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0021  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0022  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0023  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0024  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0025  * POSSIBILITY OF SUCH DAMAGE.
0026  */
0027 
0028 #ifdef HAVE_CONFIG_H
0029 #include "config.h"
0030 #endif
0031 
0032 #include <errno.h>
0033 #include <rtems/test.h>
0034 #include <rtems/test-info.h>
0035 #include <rtems/timespec.h>
0036 #include <rtems/rtems/event.h>
0037 #define _KERNEL
0038 #include <sys/timepps.h>
0039 
0040 const char rtems_test_name[] = "SPPPS 1";
0041 
0042 #define PPS_EVENT RTEMS_EVENT_0
0043 #define TASK_WAITING RTEMS_EVENT_1
0044 #define PPS_EVENT_RECEIVED RTEMS_EVENT_2
0045 
0046 struct test_pps_device {
0047   struct pps_state pps;
0048   rtems_id task_waiting;
0049   int wokenup;
0050 };
0051 
0052 typedef struct {
0053   rtems_id main_task;
0054   struct test_pps_device *pps_dev;
0055 } test_context;
0056 
0057 T_TEST_CASE( WaitPPSEventDefaultHandler )
0058 {
0059   int status;
0060   struct test_pps_device pps_dev;
0061   struct pps_fetch_args fetch;
0062 
0063   memset( &pps_dev, 0, sizeof( pps_dev ) );
0064   pps_dev.task_waiting = RTEMS_INVALID_ID;
0065 
0066   pps_dev.pps.ppscap = PPS_CAPTUREBOTH;
0067   pps_init_abi( &pps_dev.pps );
0068   pps_dev.pps.ppsparam.mode = PPS_CAPTUREASSERT;
0069 
0070   /* If no timeout is requested, pps_fetch() doesn't call the default handler */
0071   memset( &fetch, 0, sizeof( fetch ) );
0072   status = pps_ioctl( PPS_IOC_FETCH, (caddr_t)&fetch, &pps_dev.pps );
0073   T_eq_int( status, 0 );
0074 
0075   fetch.timeout.tv_sec = 1;
0076   status = pps_ioctl( PPS_IOC_FETCH, (caddr_t)&fetch, &pps_dev.pps );
0077   T_eq_int( status, ETIMEDOUT );
0078 }
0079 
0080 static void fake_wakeup(struct pps_state *pps)
0081 {
0082   struct test_pps_device *pps_dev;
0083 
0084   pps_dev = RTEMS_CONTAINER_OF( pps, struct test_pps_device, pps );
0085   pps_dev->wokenup++;
0086 }
0087 
0088 T_TEST_CASE( PPSEventEarlyReturns )
0089 {
0090   struct test_pps_device pps_dev;
0091 
0092   memset( &pps_dev, 0, sizeof( pps_dev ) );
0093   pps_dev.task_waiting = RTEMS_INVALID_ID;
0094 
0095   pps_dev.pps.ppscap = PPS_CAPTUREBOTH;
0096   pps_init_abi( &pps_dev.pps );
0097   pps_dev.pps.wakeup = fake_wakeup;
0098   pps_dev.pps.ppsparam.mode = PPS_CAPTUREASSERT;
0099 
0100   pps_capture( &pps_dev.pps );
0101   /* Trigger event with a different event than the one previously selected */
0102   pps_event( &pps_dev.pps, PPS_CAPTURECLEAR );
0103   T_eq_int( pps_dev.wokenup, 0 );
0104 
0105   pps_dev.pps.ppsparam.mode = PPS_CAPTURECLEAR;
0106 
0107   /* Wait th_generation to be updated */
0108   rtems_task_wake_after( 2 );
0109   pps_event( &pps_dev.pps, PPS_CAPTURECLEAR );
0110   T_eq_int( pps_dev.wokenup, 0 );
0111 
0112   /* Save current timecounter in pps_state object */
0113   pps_capture( &pps_dev.pps );
0114   pps_event( &pps_dev.pps, PPS_CAPTURECLEAR );
0115   T_eq_int( pps_dev.wokenup, 0 );
0116 
0117   pps_capture( &pps_dev.pps );
0118   pps_event( &pps_dev.pps, PPS_CAPTURECLEAR );
0119   T_eq_int( pps_dev.wokenup, 1 );
0120 }
0121 
0122 static void wakeup(struct pps_state *pps)
0123 {
0124   struct test_pps_device *pps_dev;
0125 
0126   pps_dev = RTEMS_CONTAINER_OF( pps, struct test_pps_device, pps );
0127   if (pps_dev->task_waiting != RTEMS_INVALID_ID)
0128     rtems_event_send( pps_dev->task_waiting, PPS_EVENT );
0129 }
0130 
0131 static int wait(struct pps_state *pps, struct timespec timeout)
0132 {
0133   rtems_status_code sc;
0134   rtems_event_set out;
0135   uint32_t timeoutticks;
0136   struct test_pps_device *pps_dev;
0137 
0138   pps_dev = RTEMS_CONTAINER_OF( pps, struct test_pps_device, pps );
0139   pps_dev->task_waiting = rtems_task_self();
0140 
0141   timeoutticks = rtems_timespec_to_ticks(&timeout);
0142   sc = rtems_event_receive( PPS_EVENT, RTEMS_DEFAULT_OPTIONS, timeoutticks, &out );
0143   return rtems_status_code_to_errno(sc);
0144 }
0145 
0146 static void pps_task(rtems_task_argument arg)
0147 {
0148   int status;
0149   rtems_status_code sc;
0150   struct pps_fetch_args fetch;
0151   test_context *ctx;
0152 
0153   ctx = (test_context *) arg;
0154 
0155   fetch.tsformat = PPS_TSFMT_TSPEC;
0156   fetch.timeout.tv_sec = 1;
0157   fetch.timeout.tv_nsec = 0;
0158 
0159   sc = rtems_event_send( ctx->main_task, TASK_WAITING );
0160   T_rsc_success( sc );
0161   status = pps_ioctl( PPS_IOC_FETCH, (caddr_t)&fetch, &ctx->pps_dev->pps );
0162   T_eq_int( status, 0 );
0163   sc = rtems_event_send( ctx->main_task, PPS_EVENT_RECEIVED );
0164   T_rsc_success( sc );
0165 
0166   rtems_task_exit();
0167 }
0168 
0169 T_TEST_CASE( WakeupTaskWithPPSEvent )
0170 {
0171   int status;
0172   rtems_status_code sc;
0173   struct test_pps_device pps_dev;
0174   struct pps_kcbind_args kcbind;
0175   test_context ctx;
0176   rtems_id pps_task_id;
0177   rtems_task_priority pps_task_prio = 1;
0178   rtems_event_set out;
0179 
0180   memset( &pps_dev, 0, sizeof( pps_dev ) );
0181   pps_dev.task_waiting = RTEMS_INVALID_ID;
0182   ctx.pps_dev = &pps_dev;
0183   ctx.main_task = rtems_task_self();
0184 
0185   pps_dev.pps.ppscap = PPS_CAPTUREBOTH;
0186   pps_init_abi( &pps_dev.pps );
0187   pps_dev.pps.wait = wait;
0188   pps_dev.pps.wakeup = wakeup;
0189   pps_dev.pps.ppsparam.mode = PPS_CAPTUREASSERT;
0190 
0191   kcbind.kernel_consumer = PPS_KC_HARDPPS;
0192   kcbind.edge = PPS_CAPTUREASSERT;
0193   kcbind.tsformat = PPS_TSFMT_TSPEC;
0194   status = pps_ioctl( PPS_IOC_KCBIND, (caddr_t)&kcbind, &pps_dev.pps );
0195   T_eq_int( status, 0 );
0196 
0197   /* Save current timecounter in pps_state object */
0198   pps_capture( &pps_dev.pps );
0199   pps_event( &pps_dev.pps, PPS_CAPTUREASSERT );
0200 
0201   sc = rtems_task_create(
0202     rtems_build_name('P', 'P', 'S', 'E'),
0203     pps_task_prio,
0204     RTEMS_MINIMUM_STACK_SIZE,
0205     RTEMS_DEFAULT_MODES,
0206     RTEMS_DEFAULT_ATTRIBUTES,
0207     &pps_task_id
0208   );
0209   T_rsc_success( sc );
0210   sc = rtems_task_start( pps_task_id, pps_task, (rtems_task_argument) &ctx );
0211   T_rsc_success( sc );
0212 
0213   sc = rtems_event_receive( TASK_WAITING, RTEMS_DEFAULT_OPTIONS, RTEMS_MILLISECONDS_TO_TICKS(100), &out );
0214   T_rsc_success( sc );
0215 
0216   /* Capture event and send wake-up */
0217   pps_capture( &pps_dev.pps );
0218   pps_event( &pps_dev.pps, PPS_CAPTUREASSERT );
0219 
0220   sc = rtems_event_receive( PPS_EVENT_RECEIVED, RTEMS_DEFAULT_OPTIONS, RTEMS_MILLISECONDS_TO_TICKS(100), &out );
0221   T_rsc_success( sc );
0222 }
0223 
0224 static rtems_task Init( rtems_task_argument argument )
0225 {
0226   rtems_test_run( argument, TEST_STATE );
0227 }
0228 
0229 #define CONFIGURE_APPLICATION_NEEDS_SIMPLE_CONSOLE_DRIVER
0230 #define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
0231 
0232 #define CONFIGURE_MAXIMUM_TASKS 2
0233 
0234 #define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION
0235 
0236 #define CONFIGURE_RTEMS_INIT_TASKS_TABLE
0237 
0238 #define CONFIGURE_INIT
0239 
0240 #include <rtems/confdefs.h>