/******************************************************************************* Eurecom OpenAirInterface Copyright(c) 1999 - 2011 Eurecom This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, version 2, as published by the Free Software Foundation. This program is distributed in the hope it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. The full GNU General Public License is included in this distribution in the file called "COPYING". Contact Information Openair Admin: openair_admin@eurecom.fr Openair Tech : openair_tech@eurecom.fr Forums : http://forums.eurecom.fsr/openairinterface Address : Eurecom, 2229, route des crĂȘtes, 06560 Valbonne Sophia Antipolis, France *******************************************************************************/ /*! \file lte-softmodem.c * \brief main program to control HW and scheduling * \author R. Knopp, F. Kaltenberger * \date 2012 * \version 0.1 * \company Eurecom * \email: knopp@eurecom.fr,florian.kaltenberger@eurecom.fr * \note * \warning */ #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include <sys/ioctl.h> #include <sys/types.h> #include <sys/mman.h> #include <sys/stat.h> #include <fcntl.h> #include <sched.h> #include <signal.h> #include <execinfo.h> #include <getopt.h> #include <pthread.h> #include "rt_wrapper.h" #define TIMER_ONESHOT_MODE #define FRAME_PERIOD 10000000ULL #define DAQ_PERIOD 500000ULL #define LTE_SLOTS_PER_FRAME 20 #ifdef RTAI static SEM *mutex; //static CND *cond; static long int thread0; static long int thread1; //static long int sync_thread; #else #define OPENAIR_THREAD_STACK_SIZE 8192 #define OPENAIR_THREAD_PRIORITY 255 pthread_t thread0; //pthread_t thread1; pthread_attr_t attr_dlsch_threads; struct sched_param sched_param_dlsch; #endif int oai_exit = 0; struct timing_info_t { //unsigned int frame, hw_slot, last_slot, next_slot; RTIME time_min, time_max, time_avg, time_last, time_now; //unsigned int mbox0, mbox1, mbox2, mbox_target; unsigned int n_samples; } timing_info; void signal_handler(int sig) { void *array[10]; size_t size; if (sig==SIGSEGV) { // get void*'s for all entries on the stack size = backtrace(array, 10); // print out all the frames to stderr fprintf(stderr, "Error: signal %d:\n", sig); backtrace_symbols_fd(array, size, 2); exit(-1); } else { oai_exit=1; } } void exit_fun(const char* s) { void *array[10]; size_t size; printf("Exiting: %s\n",s); oai_exit=1; //rt_sleep_ns(FRAME_PERIOD); //exit (-1); } int frame=0,slot=0; /* This is the main eNB thread. It gets woken up by the kernel driver using the RTAI message mechanism (rt_send and rt_receive). */ static void *eNB_thread(void *arg) { #ifdef RTAI RT_TASK *task; RTIME now; #endif unsigned char last_slot, next_slot; RTIME time_in, time_diff; int ret; #ifdef RTAI task = rt_task_init_schmod(nam2num("TASK0"), 0, 0, 0, SCHED_FIFO, 0xF); printf("Started eNB thread (id %p)\n",task); #ifndef TIMER_ONESHOT_MODE now = rt_get_time(); ret = rt_task_make_periodic(task, now, nano2count(DAQ_PERIOD)); if (ret!=0) printf("Problem with periodic timer\n"); #endif #endif #ifdef HARD_RT rt_make_hard_real_time(); #endif mlockall(MCL_CURRENT | MCL_FUTURE); timing_info.time_min = 100000000ULL; timing_info.time_max = 0; timing_info.time_avg = 0; timing_info.n_samples = 0; while (!oai_exit) { time_in = rt_get_time_ns(); #ifdef TIMER_ONESHOT_MODE ret = rt_sleep_ns(DAQ_PERIOD); if (ret) printf("eNB Frame %d, time %llu: rt_sleep_ns returned %d\n",frame,time_in,ret); #else rt_task_wait_period(); #endif time_diff = rt_get_time_ns() - time_in; if (time_diff > timing_info.time_max) timing_info.time_max = time_diff; if (time_diff < timing_info.time_min) timing_info.time_min = time_diff; timing_info.time_avg = (timing_info.time_avg*timing_info.n_samples + time_diff)/(timing_info.n_samples+1); timing_info.n_samples++; last_slot = (slot)%LTE_SLOTS_PER_FRAME; if (last_slot <0) last_slot+=20; next_slot = (slot+3)%LTE_SLOTS_PER_FRAME; slot++; if (slot==20) { slot=0; frame++; } } printf("eNB_thread: finished, ran %d times.\n",frame); #ifdef HARD_RT rt_make_soft_real_time(); #endif // clean task #ifdef RTAI rt_task_delete(task); #endif printf("Task deleted. returning\n"); return 0; } int main(int argc, char **argv) { #ifdef RTAI RT_TASK *task; RTIME period; #else int error_code; #endif int i,j,aa; void *status; // to make a graceful exit when ctrl-c is pressed signal(SIGSEGV, signal_handler); signal(SIGINT, signal_handler); #ifndef RTAI check_clock(); #endif mlockall(MCL_CURRENT | MCL_FUTURE); #ifdef RTAI // make main thread LXRT soft realtime task = rt_task_init_schmod(nam2num("MYTASK"), 9, 0, 0, SCHED_FIFO, 0xF); // start realtime timer and scheduler #ifdef TIMER_ONESHOT_MODE rt_set_oneshot_mode(); start_rt_timer(0); printf("started RTAI timer in oneshot mode\n"); #else rt_set_periodic_mode(); period = start_rt_timer(nano2count(500000)); printf("started RTAI timer with period %llu ns\n",count2nano(period)); #endif printf("Init mutex\n"); //mutex = rt_get_adr(nam2num("MUTEX")); mutex = rt_sem_init(nam2num("MUTEX"), 1); if (mutex==0) { printf("Error init mutex\n"); exit(-1); } else printf("mutex=%p\n",mutex); #endif rt_sleep_ns(10*FRAME_PERIOD); #ifndef RTAI pthread_attr_init (&attr_dlsch_threads); pthread_attr_setstacksize(&attr_dlsch_threads,OPENAIR_THREAD_STACK_SIZE); //attr_dlsch_threads.priority = 1; sched_param_dlsch.sched_priority = sched_get_priority_max(SCHED_FIFO); //OPENAIR_THREAD_PRIORITY; pthread_attr_setschedparam (&attr_dlsch_threads, &sched_param_dlsch); pthread_attr_setschedpolicy (&attr_dlsch_threads, SCHED_FIFO); #endif #ifdef RTAI thread0 = rt_thread_create(eNB_thread, NULL, 100000000); #else error_code = pthread_create(&thread0, &attr_dlsch_threads, eNB_thread, NULL); if (error_code!= 0) { printf("[lte-softmodem.c] Could not allocate eNB_thread, error %d\n",error_code); return(error_code); } else { printf("[lte-softmodem.c] Allocate eNB_thread successful\n"); } #endif printf("eNB threads created\n"); // wait for end of program printf("TYPE <CTRL-C> TO TERMINATE\n"); //getchar(); while (oai_exit==0) { printf("eNB Frame %d, hw_slot %d (time %llu): period %llu, sleep time (avg/min/max/samples) %llu / %llu / %llu / %d, ratio %f\n",frame,slot,rt_get_time_ns(),DAQ_PERIOD,timing_info.time_avg,timing_info.time_min,timing_info.time_max,timing_info.n_samples,(double)timing_info.time_avg/DAQ_PERIOD); rt_sleep_ns(100*FRAME_PERIOD); } // stop threads #ifdef RTAI rt_thread_join(thread0); #else pthread_join(thread0,&status); #endif #ifdef RTAI stop_rt_timer(); #endif return 0; }