/* * Timer_init() * * ATTENTION: AS MC68349 has no built-in Timer, the following code doesn't work * in a MC68349. You can't use FIFO full mode for the moment, but * it should be easy to fix this by using an external timer * * Use TIMER 1 for TIMEOUT when using FIFO FULL mode in UART driver * Use TIMER 2 for timing test suites * * Geoffroy Montel * France Telecom - CNET/DSM/TAM/CAT * 4, rue du Clos Courtel * 35512 CESSON-SEVIGNE * FRANCE * * e-mail: g_montel@yahoo.com * * $Id$ */ /* * * Input parameters: NONE * * Output parameters: NONE * * NOTE: It is important that the timer start/stop overhead be * determined when porting or modifying this code. * * COPYRIGHT (c) 1989-1998. * On-Line Applications Research Corporation (OAR). * Copyright assigned to U.S. Government, 1994. * * The license and distribution terms for this file may be * found in the file LICENSE in this distribution or at * http://www.OARcorp.com/rtems/license.html. */ #include #include #include #include #include #define TIMER1_VECTOR 122 #define TIMER1_IRQ_LEVEL 5 #define TIMER1_INTERRUPT_ARBITRATION 5 #define TIMER2_VECTOR 123 #define TIMER2_IRQ_LEVEL 4 #define TIMER2_INTERRUPT_ARBITRATION 4 #define CLOCK_SPEED 25 /* in Mhz */ #define max(a,b) (((a)>(b)) ? (a) : (b)) void (*Restart_Fifo_Full_A_Timer)(); void (*Restart_Check_A_Timer)(); void (*Restart_Fifo_Full_B_Timer)(); void (*Restart_Check_B_Timer)(); int preload = 0; /****************************************************** Name: __Restart_Fifo_Full_Timer Input parameters: - Output parameters: - Description: when a character is received, sets the TIMER to raise an interrupt at TIMEOUT. It's necessary to prevent from not getting n-1 characters (with n the Uart Fifo size) *****************************************************/ void __Restart_Fifo_Full_Timer (void) { TSR1 |= m340_TO; TCR1 &= ~m340_CPE; WPREL11 = preload; TCR1 |= m340_CPE; } /****************************************************** Name: __Restart_Fifo_Full_Timer Input parameters: - Output parameters: - Description: when no character has been received recently, check now and then if whether a there's a character in the FIFO *****************************************************/ void __Restart_Check_Timer (void) { TSR1 |= m340_TO; TCR1 &= ~m340_CPE; WPREL11 = 0xFFFF; TCR1 |= m340_CPE; } /****************************************************** Name: __do_nothing Input parameters: - Output parameters: - Description: we always restart the fifo full timer with a call to Restart_*_Timer if we do not use FIFO full, Restart_*_Timer are set to do __do_nothing *****************************************************/ void __do_nothing (void) { } #define Fifo_Full_on_A (m340_uart_config[UART_CHANNEL_A].rx_mode==UART_FIFO_FULL && m340_uart_config[UART_CHANNEL_A].enable && m340_uart_config[UART_CHANNEL_A].mode==UART_INTERRUPTS) #define Fifo_Full_on_B (m340_uart_config[UART_CHANNEL_B].rx_mode==UART_FIFO_FULL && m340_uart_config[UART_CHANNEL_B].enable && m340_uart_config[UART_CHANNEL_B].mode==UART_INTERRUPTS) /****************************************************** Name: Fifo_Full_Timer_initialize Input parameters: - Output parameters: - Description: initialize Timer 1 for FIFO full mode *****************************************************/ void Fifo_Full_Timer_initialize (void) { float max_baud_rate; int prescaler_output_tap = -1; int nb_of_clock_ticks = 0; /* * USE TIMER 1 for UART FIFO FULL mode */ if ( Fifo_Full_on_A || Fifo_Full_on_B ) { /* Disable the timer */ TCR1 &= ~m340_SWR; /* Reset the interrupts */ TSR1 &= ~(m340_TO | m340_TG | m340_TC); /* Init the stop bit for normal operation, ignore FREEZE, user privileges, set interrupt arbitration */ TMCR1 = TIMER1_INTERRUPT_ARBITRATION; /* interrupt priority level and interrupt vector */ TIR1 = TIMER1_VECTOR | (TIMER1_IRQ_LEVEL << 8); /* compute prescaler */ if ( Fifo_Full_on_A && Fifo_Full_on_B) max_baud_rate = max(m340_uart_config[UART_CHANNEL_A].rx_baudrate, m340_uart_config[UART_CHANNEL_B].rx_baudrate); else if ( Fifo_Full_on_A ) max_baud_rate = m340_uart_config[UART_CHANNEL_A].rx_baudrate; else max_baud_rate = m340_uart_config[UART_CHANNEL_B].rx_baudrate; /* find out config */ nb_of_clock_ticks = (10/max_baud_rate)*(CLOCK_SPEED*1000000)*1.2; if (nb_of_clock_ticks < 0xFFFF) { preload = nb_of_clock_ticks; prescaler_output_tap = -1; } else if (nb_of_clock_ticks/2 < 0xFFFF) { preload = nb_of_clock_ticks/2; prescaler_output_tap = m340_Divide_by_2; } else if (nb_of_clock_ticks/4 < 0xFFFF) { preload = nb_of_clock_ticks/4; prescaler_output_tap = m340_Divide_by_4; } else if (nb_of_clock_ticks/8 < 0xFFFF) { preload = nb_of_clock_ticks/8; prescaler_output_tap = m340_Divide_by_16; } else if (nb_of_clock_ticks/16 < 0xFFFF) { preload = nb_of_clock_ticks/16; prescaler_output_tap = m340_Divide_by_16; } else if (nb_of_clock_ticks/32 < 0xFFFF) { preload = nb_of_clock_ticks/32; prescaler_output_tap = m340_Divide_by_32; } else if (nb_of_clock_ticks/64 < 0xFFFF) { preload = nb_of_clock_ticks/64; prescaler_output_tap = m340_Divide_by_64; } else if (nb_of_clock_ticks/128 < 0xFFFF) { preload = nb_of_clock_ticks/128; prescaler_output_tap = m340_Divide_by_128; } else if (nb_of_clock_ticks/256 < 0xFFFF) { preload = nb_of_clock_ticks/256; prescaler_output_tap = m340_Divide_by_256; } /* Input Capture/Output Compare (ICOC) */ TCR1 = m340_SWR | m340_TO_Enabled | m340_ICOC; if (prescaler_output_tap!=-1) TCR1 |= prescaler_output_tap | m340_PSE; /* install interrupt vector */ { rtems_isr_entry old_handler; rtems_status_code sc; extern void _Debug_ISR_Handler_Console(void); sc = rtems_interrupt_catch (InterruptHandler, TIMER1_VECTOR, &old_handler); /* uncomment this if you want to pass control to your own ISR handler it may be usefull to do so to check for performances with an oscilloscope */ /* { proc_ptr ignored; _CPU_ISR_install_raw_handler( TIMER1_VECTOR, _Debug_ISR_Handler_Console, &ignored ); } */ } } /* fifo full mode on a uart */ /* install routines */ Restart_Check_A_Timer = Fifo_Full_on_A ? __Restart_Check_Timer : __do_nothing; Restart_Fifo_Full_A_Timer = Fifo_Full_on_A ? __Restart_Fifo_Full_Timer : __do_nothing; Restart_Check_B_Timer = Fifo_Full_on_B ? __Restart_Check_Timer : __do_nothing; Restart_Fifo_Full_B_Timer = Fifo_Full_on_B ? __Restart_Fifo_Full_Timer : __do_nothing; /* start checking timer */ Restart_Check_A_Timer(); Restart_Check_B_Timer(); } /****************************************************** Name: Timer_initialize Input parameters: - Output parameters: - Description: init Timer for timing test suites *****************************************************/ void Timer_initialize (void) { /* Disable the timer */ TCR2 &= ~m340_SWR; /* Reset the interrupts */ TSR2 &= ~(m340_TO | m340_TG | m340_TC); /* Init the stop bit for normal operation, ignore FREEZE, user privileges, set interrupt arbitration */ TMCR1 = TIMER2_INTERRUPT_ARBITRATION; /* interrupt priority level and interrupt vector */ TIR1 = TIMER2_VECTOR | (TIMER2_IRQ_LEVEL << 8); /* Init the stop bit for normal operation, ignore FREEZE, user privileges, set interrupt arbitration */ TMCR2 = TIMER2_INTERRUPT_ARBITRATION; /* Preload register 1 */ WPREL21 = 0xFFFF; /* Input Capture/Output Compare (ICOC) */ TCR2 = m340_SWR | m340_ICOC | m340_PSE | m340_Divide_by_16 | m340_CPE; } /****************************************************** Name: Read_timer Input parameters: - Output parameters: - Description: Return timer value in microsecond units *****************************************************/ int Read_timer (void) { /* there's CLOCK_SPEED / 16 micro seconds between two timer register decrement */ return (((0xFFFF - TCNTR2) * CLOCK_SPEED) / 16); } /****************************************************** Name: Empty_function Input parameters: - Output parameters: - Description: Empty function call used in loops to measure basic cost of looping in Timing Test Suite. *****************************************************/ rtems_status_code Empty_function (void) { return RTEMS_SUCCESSFUL; } /****************************************************** Name: Set_find_average_overhead Input parameters: - Output parameters: - Description: - *****************************************************/ void Set_find_average_overhead(rtems_boolean find_flag) { }