diff --git a/.hgsubstate b/.hgsubstate --- a/.hgsubstate +++ b/.hgsubstate @@ -1,2 +1,2 @@ 3081d1f9bb20b2b64a192585337a292a9804e0c5 LFR_basic-parameters -ce0c2f17257170a8529605f68687c18f23973087 header/lfr_common_headers +084fd0db5e4139a1096789935e32ef498192f395 header/lfr_common_headers diff --git a/header/fsw_init.h b/header/fsw_init.h --- a/header/fsw_init.h +++ b/header/fsw_init.h @@ -18,6 +18,8 @@ extern rtems_name Task_name[20]; /* array of task names */ extern rtems_id Task_id[20]; /* array of task ids */ +extern rtems_name timecode_timer_name; +extern rtems_id timecode_timer_id; extern unsigned char pa_bia_status_info; // RTEMS TASKS @@ -29,6 +31,7 @@ int create_all_tasks( void ); int start_all_tasks( void ); // rtems_status_code create_message_queues( void ); +rtems_status_code create_timecode_timer( void ); rtems_status_code get_message_queue_id_send( rtems_id *queue_id ); rtems_status_code get_message_queue_id_recv( rtems_id *queue_id ); rtems_status_code get_message_queue_id_prc0( rtems_id *queue_id ); diff --git a/header/fsw_spacewire.h b/header/fsw_spacewire.h --- a/header/fsw_spacewire.h +++ b/header/fsw_spacewire.h @@ -15,6 +15,8 @@ extern spw_stats spacewire_stats; extern spw_stats spacewire_stats_backup; +extern rtems_name timecode_timer_name; +extern rtems_id timecode_timer_id; // RTEMS TASK rtems_task spiq_task( rtems_task_argument argument ); @@ -31,6 +33,7 @@ void spacewire_set_NP( unsigned char val void spacewire_set_RE( unsigned char val, unsigned int regAddr ); // RMAP Enable void spacewire_compute_stats_offsets( void ); void spacewire_update_statistics( void ); +void increase_an_unsigned_char_counter( unsigned char *counter ); void init_header_cwf( Header_TM_LFR_SCIENCE_CWF_t *header ); void init_header_swf( Header_TM_LFR_SCIENCE_SWF_t *header ); @@ -43,6 +46,9 @@ void spw_send_asm_f1( ring_node *ring_no void spw_send_asm_f2( ring_node *ring_node_to_send, Header_TM_LFR_SCIENCE_ASM_t *header ); void spw_send_k_dump( ring_node *ring_node_to_send ); +rtems_timer_service_routine timecode_timer_routine( rtems_id timer_id, void *user_data ); +unsigned int check_timecode_and_previous_timecode_coherency(unsigned char currentTimecodeCtr); +unsigned int check_timecode_and_internal_time_coherency(unsigned char timecode, unsigned char internalTime); void timecode_irq_handler( void *pDev, void *regs, int minor, unsigned int tc ); void (*grspw_timecode_callback) ( void *pDev, void *regs, int minor, unsigned int tc ); diff --git a/src/fsw_globals.c b/src/fsw_globals.c --- a/src/fsw_globals.c +++ b/src/fsw_globals.c @@ -26,6 +26,8 @@ rtems_name misc_name[5]; rtems_name Task_name[20]; /* array of task names */ rtems_id Task_id[20]; /* array of task ids */ +rtems_name timecode_timer_name; +rtems_id timecode_timer_id; int fdSPW = 0; int fdUART = 0; unsigned char lfrCurrentMode; diff --git a/src/fsw_init.c b/src/fsw_init.c --- a/src/fsw_init.c +++ b/src/fsw_init.c @@ -35,7 +35,7 @@ #define CONFIGURE_INIT_TASK_ATTRIBUTES (RTEMS_DEFAULT_ATTRIBUTES | RTEMS_FLOATING_POINT) #define CONFIGURE_MAXIMUM_DRIVERS 16 #define CONFIGURE_MAXIMUM_PERIODS 5 -#define CONFIGURE_MAXIMUM_TIMERS 5 // STAT (1s), send SWF (0.3s), send CWF3 (1s) +#define CONFIGURE_MAXIMUM_TIMERS 5 // [spiq] [wtdg] [spacewire_reset_link] #define CONFIGURE_MAXIMUM_MESSAGE_QUEUES 5 #ifdef PRINT_STACK_REPORT #define CONFIGURE_STACK_CHECKER_ENABLED @@ -160,6 +160,12 @@ rtems_task Init( rtems_task_argument ign create_names(); // create all names + status = create_timecode_timer(); // create the timer used by timecode_irq_handler + if (status != RTEMS_SUCCESSFUL) + { + PRINTF1("in INIT *** ERR in create_timer_timecode, code %d", status) + } + status = create_message_queues(); // create message queues if (status != RTEMS_SUCCESSFUL) { @@ -317,6 +323,8 @@ void create_names( void ) // create all misc_name[QUEUE_PRC0] = rtems_build_name( 'Q', '_', 'P', '0' ); misc_name[QUEUE_PRC1] = rtems_build_name( 'Q', '_', 'P', '1' ); misc_name[QUEUE_PRC2] = rtems_build_name( 'Q', '_', 'P', '2' ); + + timecode_timer_name = rtems_build_name( 'S', 'P', 'T', 'C' ); } int create_all_tasks( void ) // create all tasks which run in the software @@ -750,6 +758,24 @@ rtems_status_code create_message_queues( return ret; } +rtems_status_code create_timecode_timer( void ) +{ + rtems_status_code status; + + status = rtems_timer_create( timecode_timer_name, &timecode_timer_id ); + + if ( status != RTEMS_SUCCESSFUL ) + { + PRINTF1("in create_timer_timecode *** ERR creating SPTC timer, %d\n", status) + } + else + { + PRINTF("in create_timer_timecode *** OK creating SPTC timer\n") + } + + return status; +} + rtems_status_code get_message_queue_id_send( rtems_id *queue_id ) { rtems_status_code status; diff --git a/src/fsw_misc.c b/src/fsw_misc.c --- a/src/fsw_misc.c +++ b/src/fsw_misc.c @@ -342,7 +342,7 @@ rtems_task dumb_task( rtems_task_argumen unsigned int fine_time = 0; rtems_event_set event_out; - char *DumbMessages[13] = {"in DUMB *** default", // RTEMS_EVENT_0 + char *DumbMessages[14] = {"in DUMB *** default", // RTEMS_EVENT_0 "in DUMB *** timecode_irq_handler", // RTEMS_EVENT_1 "in DUMB *** f3 buffer changed", // RTEMS_EVENT_2 "in DUMB *** in SMIQ *** Error sending event to AVF0", // RTEMS_EVENT_3 @@ -354,7 +354,8 @@ rtems_task dumb_task( rtems_task_argumen "tick", // RTEMS_EVENT_9 "VHDL ERR *** waveform picker", // RTEMS_EVENT_10 "VHDL ERR *** unexpected ready matrix values", // RTEMS_EVENT_11 - "WATCHDOG timer" // RTEMS_EVENT_12 + "WATCHDOG timer", // RTEMS_EVENT_12 + "TIMECODE timer" // RTEMS_EVENT_13 }; BOOT_PRINTF("in DUMB *** \n") @@ -362,7 +363,7 @@ rtems_task dumb_task( rtems_task_argumen while(1){ rtems_event_receive(RTEMS_EVENT_0 | RTEMS_EVENT_1 | RTEMS_EVENT_2 | RTEMS_EVENT_3 | RTEMS_EVENT_4 | RTEMS_EVENT_5 | RTEMS_EVENT_6 | RTEMS_EVENT_7 - | RTEMS_EVENT_8 | RTEMS_EVENT_9 | RTEMS_EVENT_12, + | RTEMS_EVENT_8 | RTEMS_EVENT_9 | RTEMS_EVENT_12 | RTEMS_EVENT_13, RTEMS_WAIT | RTEMS_EVENT_ANY, RTEMS_NO_TIMEOUT, &event_out); // wait for an RTEMS_EVENT intEventOut = (unsigned int) event_out; for ( i=0; i<32; i++) @@ -375,6 +376,10 @@ rtems_task dumb_task( rtems_task_argumen { PRINTF1("%s\n", DumbMessages[12]) } + if (i==13) + { + PRINTF1("%s\n", DumbMessages[13]) + } } } } diff --git a/src/fsw_spacewire.c b/src/fsw_spacewire.c --- a/src/fsw_spacewire.c +++ b/src/fsw_spacewire.c @@ -22,6 +22,9 @@ Header_TM_LFR_SCIENCE_CWF_t headerCWF; Header_TM_LFR_SCIENCE_SWF_t headerSWF; Header_TM_LFR_SCIENCE_ASM_t headerASM; +unsigned char previousTimecodeCtr = 0; +unsigned int *grspwPtr = (unsigned int *) (REGS_ADDR_GRSPW + APB_OFFSET_GRSPW_TIME_REGISTER); + //*********** // RTEMS TASK rtems_task spiq_task(rtems_task_argument unused) @@ -658,41 +661,146 @@ void spacewire_update_statistics( void ) housekeeping_packet.hk_lfr_dpu_spw_rx_too_big = (unsigned char) spacewire_stats.rx_truncated; } -void timecode_irq_handler( void *pDev, void *regs, int minor, unsigned int tc ) +void increase_unsigned_char_counter( unsigned char *counter ) { - // a valid timecode has been received, write it in the HK report - unsigned int *grspwPtr; - unsigned char timecodeCtr; - unsigned char updateTimeCtr; + // update the number of valid timecodes that have been received + if (*counter == 255) + { + *counter = 0; + } + else + { + *counter = *counter + 1; + } +} - grspwPtr = (unsigned int *) (REGS_ADDR_GRSPW + APB_OFFSET_GRSPW_TIME_REGISTER); +rtems_timer_service_routine timecode_timer_routine( rtems_id timer_id, void *user_data ) +{ + + unsigned char currentTimecodeCtr; + + currentTimecodeCtr = (unsigned char) (grspwPtr[0] & TIMECODE_MASK); - housekeeping_packet.hk_lfr_dpu_spw_last_timc = (unsigned char) (grspwPtr[0] & 0xff); // [1111 1111] - timecodeCtr = (unsigned char) (grspwPtr[0] & 0x3f); // [0011 1111] - updateTimeCtr = time_management_regs->coarse_time_load & 0x3f; // [0011 1111] + if (currentTimecodeCtr == previousTimecodeCtr) + { + //************************ + // HK_LFR_TIMECODE_MISSING + // the timecode value has not changed, no valid timecode has been received, the timecode is MISSING + increase_unsigned_char_counter( &housekeeping_packet.hk_lfr_timecode_missing ); + } + else if (currentTimecodeCtr == (previousTimecodeCtr+1)) + { + // the timecode value has changed and the value is valid, this is unexpected because + // the timer should not have fired, the timecode_irq_handler should have been raised + } + else + { + //************************ + // HK_LFR_TIMECODE_INVALID + // the timecode value has changed and the value is not valid, no tickout has been generated + // this is why the timer has fired + increase_unsigned_char_counter( &housekeeping_packet.hk_lfr_timecode_invalid ); + } - // update the number of valid timecodes that have been received - if (housekeeping_packet.hk_lfr_dpu_spw_tick_out_cnt == 255) + rtems_event_send( Task_id[TASKID_DUMB], RTEMS_EVENT_13 ); +} + +unsigned int check_timecode_and_previous_timecode_coherency(unsigned char currentTimecodeCtr) +{ + unsigned char ret; + + ret = LFR_DEFAULT; + + if (currentTimecodeCtr == 0) { - housekeeping_packet.hk_lfr_dpu_spw_tick_out_cnt = 0; + if (previousTimecodeCtr == 63) + { + ret = LFR_SUCCESSFUL; + } + else + { + ret = LFR_DEFAULT; + } } else { - housekeeping_packet.hk_lfr_dpu_spw_tick_out_cnt = housekeeping_packet.hk_lfr_dpu_spw_tick_out_cnt + 1; - } - - // check the value of the timecode with respect to the last TC_LFR_UPDATE_TIME => SSS-CP-FS-370 - if (timecodeCtr != updateTimeCtr) - { - if (housekeeping_packet.hk_lfr_time_timecode_ctr == 255) + if (currentTimecodeCtr == (previousTimecodeCtr +1)) { - housekeeping_packet.hk_lfr_time_timecode_ctr = 0; + ret = LFR_SUCCESSFUL; } else { - housekeeping_packet.hk_lfr_time_timecode_ctr = housekeeping_packet.hk_lfr_time_timecode_ctr + 1; + ret = LFR_DEFAULT; } } + + return ret; +} + +unsigned int check_timecode_and_internal_time_coherency(unsigned char timecode, unsigned char internalTime) +{ + unsigned int ret; + + ret = LFR_DEFAULT; + + if (timecode == internalTime) + { + ret = LFR_SUCCESSFUL; + } + else + { + ret = LFR_DEFAULT; + } + + return ret; +} + +void timecode_irq_handler( void *pDev, void *regs, int minor, unsigned int tc ) +{ + // a tickout has been emitted, perform actions on the incoming timecode + + unsigned char incomingTimecode; + unsigned char updateTime; + unsigned char internalTime; + rtems_status_code status; + + incomingTimecode = (unsigned char) (grspwPtr[0] & TIMECODE_MASK); + updateTime = time_management_regs->coarse_time_load & TIMECODE_MASK; + internalTime = time_management_regs->coarse_time & TIMECODE_MASK; + + housekeeping_packet.hk_lfr_dpu_spw_last_timc = incomingTimecode; + + // update the number of tickout that have been generated + increase_unsigned_char_counter( &housekeeping_packet.hk_lfr_dpu_spw_tick_out_cnt ); + + //************************** + // HK_LFR_TIMECODE_ERRONEOUS + // MISSING and INVALID are handled by the timecode_timer_routine service routine + if (check_timecode_and_previous_timecode_coherency( incomingTimecode ) == LFR_DEFAULT) + { + // this is unexpected but a tickout has been raised and the timecode is erroneous + increase_unsigned_char_counter( &housekeeping_packet.hk_lfr_timecode_erroneous ); + } + + //************************ + // HK_LFR_TIME_TIMECODE_IT + // check the coherency between the SpaceWire timecode and the Internal Time + if (check_timecode_and_internal_time_coherency( incomingTimecode, internalTime ) == LFR_DEFAULT) + { + increase_unsigned_char_counter( &housekeeping_packet.hk_lfr_time_timecode_it ); + } + + //******************** + // HK_LFR_TIMECODE_CTR + // check the value of the timecode with respect to the last TC_LFR_UPDATE_TIME => SSS-CP-FS-370 + if (incomingTimecode != updateTime) + { + increase_unsigned_char_counter( &housekeeping_packet.hk_lfr_time_timecode_ctr ); + } + + // launch the timecode timer to detect missing or invalid timecodes + previousTimecodeCtr = incomingTimecode; // update the previousTimecodeCtr value + status = rtems_timer_fire_after( timecode_timer_id, TIMECODE_TIMER_TIMEOUT, timecode_timer_routine, NULL ); } void init_header_cwf( Header_TM_LFR_SCIENCE_CWF_t *header )