Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:23:03

0001 /**
0002  * @file
0003  *
0004  * @ingroup RTEMSBSPsARMLPC176X
0005  *
0006  * @brief Timer controller for the mbed lpc1768 board.
0007  */
0008 
0009 /*
0010  * Copyright (c) 2014 Taller Technologies.
0011  *
0012  * @author  Boretto Martin    (martin.boretto@tallertechnologies.com)
0013  * @author  Diaz Marcos (marcos.diaz@tallertechnologies.com)
0014  * @author  Lenarduzzi Federico  (federico.lenarduzzi@tallertechnologies.com)
0015  * @author  Daniel Chicco  (daniel.chicco@tallertechnologies.com)
0016  *
0017  * The license and distribution terms for this file may be
0018  * found in the file LICENSE in this distribution or at
0019  * http://www.rtems.org/license/LICENSE.
0020  */
0021 
0022 #include <stdio.h>
0023 #include <rtems/status-checks.h>
0024 #include <bsp.h>
0025 #include <bsp/irq.h>
0026 #include <bsp/io.h>
0027 #include <bsp/timer.h>
0028 
0029 /**
0030  * @brief Represents all the timers.
0031  */
0032 const lpc176x_timer timers[ LPC176X_TIMER_COUNT ] =
0033 {
0034   {
0035     .device = (lpc176x_timer_device *) LPC176X_TMR0_BASE_ADDR,
0036     .module = LPC176X_MODULE_TIMER_0,
0037     .pinselcap = LPC176X_TIMER0_CAPTURE_PORTS,
0038     .pinselemat = LPC176X_TIMER0_EMATCH_PORTS,
0039   },
0040   {
0041     .device = (lpc176x_timer_device *) LPC176X_TMR1_BASE_ADDR,
0042     .module = LPC176X_MODULE_TIMER_1,
0043     .pinselcap = LPC176X_TIMER1_CAPTURE_PORTS,
0044     .pinselemat = LPC176X_TIMER1_EMATCH_PORTS,
0045   },
0046   {
0047     .device = (lpc176x_timer_device *) LPC176X_TMR2_BASE_ADDR,
0048     .module = LPC176X_MODULE_TIMER_2,
0049     .pinselcap = LPC176X_TIMER2_CAPTURE_PORTS,
0050     .pinselemat = LPC176X_TIMER2_EMATCH_PORTS,
0051   },
0052   {
0053     .device = (lpc176x_timer_device *) LPC176X_TMR3_BASE_ADDR,
0054     .module = LPC176X_MODULE_TIMER_3,
0055     .pinselcap = LPC176X_TIMER3_CAPTURE_PORTS,
0056     .pinselemat = LPC176X_TIMER3_EMATCH_PORTS,
0057   }
0058 };
0059 
0060 /**
0061  * @brief Represents all the functions according to the timers.
0062  */
0063 lpc176x_timer_functions functions_vector[ LPC176X_TIMER_COUNT ] =
0064 {
0065   {
0066     .funct_vector = NULL
0067   },
0068   {
0069     .funct_vector = NULL
0070   },
0071   {
0072     .funct_vector = NULL
0073   },
0074   {
0075     .funct_vector = NULL
0076   }
0077 };
0078 
0079 /**
0080  * @brief Calls the corresponding interrupt function and pass the timer
0081  *        as parameter.
0082  *
0083  * @param  timer The specific device.
0084  * @param  interruptnumber Interrupt number.
0085  */
0086 static inline void lpc176x_call_desired_isr(
0087   const lpc176x_timer_number number,
0088   const lpc176x_isr_function interruptfunction
0089 )
0090 {
0091   if ( ( *functions_vector[ number ].funct_vector )[ interruptfunction ] !=
0092        NULL ) {
0093     ( *functions_vector[ number ].funct_vector )[ interruptfunction ]( number );
0094   }
0095 
0096   /* else implies that the function vector points NULL. Also,
0097      there is nothing to do. */
0098 }
0099 
0100 /**
0101  * @brief Gets true if the selected interrupt is pending
0102  *
0103  * @param number: the number of the timer.
0104  * @param interrupt: the interrupt we are checking for.
0105  * @return TRUE if the interrupt is pending.
0106  */
0107 static inline bool lpc176x_timer_interrupt_is_pending(
0108   const lpc176x_timer_number tnumber,
0109   const lpc176x_isr_function function
0110 )
0111 {
0112   assert( ( tnumber < LPC176X_TIMER_COUNT )
0113     && ( function < LPC176X_ISR_FUNCTIONS_COUNT ) );
0114 
0115   return ( timers[ tnumber ].device->IR &
0116            LPC176X_TIMER_INTERRUPT_SOURCE_BIT( function ) );
0117 }
0118 
0119 /**
0120  * @brief Resets interrupt status for the selected interrupt
0121  *
0122  * @param tnumber: the number of the timer
0123  * @param interrupt: the interrupt we are resetting
0124  */
0125 static inline void lpc176x_timer_reset_interrupt(
0126   const lpc176x_timer_number tnumber,
0127   const lpc176x_isr_function function
0128 )
0129 {
0130   assert( ( tnumber < LPC176X_TIMER_COUNT )
0131     && ( function < LPC176X_ISR_FUNCTIONS_COUNT ) );
0132   timers[ tnumber ].device->IR =
0133     LPC176X_TIMER_INTERRUPT_SOURCE_BIT( function );
0134 }
0135 
0136 inline rtems_status_code lpc176x_timer_reset(
0137   const lpc176x_timer_number tnumber )
0138 {
0139   rtems_status_code status_code = RTEMS_INVALID_NUMBER;
0140 
0141   if ( tnumber < LPC176X_TIMER_COUNT ) {
0142     timers[ tnumber ].device->TCR = LPC176X_TIMER_RESET;
0143     status_code = RTEMS_SUCCESSFUL;
0144   }
0145 
0146   /* else implies that the timer number is invalid. Also,
0147      an invalid number is returned. */
0148 
0149   return status_code;
0150 }
0151 
0152 inline rtems_status_code lpc176x_timer_set_mode(
0153   const lpc176x_timer_number tnumber,
0154   const lpc176x_timer_mode   mode
0155 )
0156 {
0157   rtems_status_code status_code = RTEMS_INVALID_NUMBER;
0158 
0159   if ( tnumber < LPC176X_TIMER_COUNT ) {
0160     timers[ tnumber ].device->CTCR = mode;
0161     status_code = RTEMS_SUCCESSFUL;
0162   }
0163 
0164   /* else implies that the timer number is invalid. Also,
0165      an invalid number is returned. */
0166 
0167   return status_code;
0168 }
0169 
0170 inline rtems_status_code lpc176x_timer_start(
0171   const lpc176x_timer_number tnumber )
0172 {
0173   rtems_status_code status_code = RTEMS_INVALID_NUMBER;
0174 
0175   if ( tnumber < LPC176X_TIMER_COUNT ) {
0176     timers[ tnumber ].device->TCR = LPC176X_TIMER_START;
0177     status_code = RTEMS_SUCCESSFUL;
0178   }
0179 
0180   /* else implies that the timer number is invalid. Also,
0181      an invalid number is returned. */
0182 
0183   return status_code;
0184 }
0185 
0186 inline rtems_status_code lpc176x_timer_is_started(
0187   const lpc176x_timer_number tnumber,
0188   bool                      *is_started
0189 )
0190 {
0191   rtems_status_code status_code = RTEMS_INVALID_NUMBER;
0192 
0193   if ( tnumber < LPC176X_TIMER_COUNT ) {
0194     *is_started = ( timers[ tnumber ].device->TCR & LPC176X_TIMER_START ) ==
0195                   LPC176X_TIMER_START;
0196     status_code = RTEMS_SUCCESSFUL;
0197   }
0198 
0199   /* else implies that the timer number is invalid. Also,
0200      an invalid number is returned. */
0201 
0202   return status_code;
0203 }
0204 
0205 inline rtems_status_code lpc176x_timer_set_resolution(
0206   const lpc176x_timer_number tnumber,
0207   const lpc176x_microseconds resolution
0208 )
0209 {
0210   rtems_status_code status_code = RTEMS_INVALID_NUMBER;
0211 
0212   if ( tnumber < LPC176X_TIMER_COUNT ) {
0213     timers[ tnumber ].device->PR = ( LPC176X_CCLK /
0214                                      LPC176X_TIMER_PRESCALER_DIVISOR ) *
0215                                    resolution;
0216     status_code = RTEMS_SUCCESSFUL;
0217   }
0218 
0219   /* else implies that the timer number is invalid. Also,
0220      an invalid number is returned. */
0221 
0222   return status_code;
0223 }
0224 
0225 rtems_status_code lpc176x_timer_match_config(
0226   const lpc176x_timer_number   tnumber,
0227   const lpc176x_match_port     match_port,
0228   const lpc176x_match_function function,
0229   const uint32_t               match_value
0230 )
0231 {
0232   rtems_status_code status_code = RTEMS_INVALID_NUMBER;
0233 
0234   if ( ( tnumber < LPC176X_TIMER_COUNT )
0235        && ( match_port < LPC176X_EMATCH_PORTS_COUNT )
0236        && ( function < LPC176X_TIMER_MATCH_FUNCTION_COUNT ) ) {
0237     timers[ tnumber ].device->MCR =
0238       LPC176X_SET_MCR( timers[ tnumber ].device->MCR,
0239         match_port, function );
0240     timers[ tnumber ].device->MR[ match_port ] = match_value;
0241     status_code = RTEMS_SUCCESSFUL;
0242   }
0243 
0244   /* else implies that the timer number, or a match port or a function
0245       is invalid. Also, an invalid number is returned. */
0246 
0247   return status_code;
0248 }
0249 
0250 inline rtems_status_code lpc176x_timer_capture_config(
0251   const lpc176x_timer_number     tnumber,
0252   const lpc176x_capture_port     capture_port,
0253   const lpc176x_capture_function function
0254 )
0255 {
0256   rtems_status_code status_code = RTEMS_INVALID_NUMBER;
0257 
0258   if ( ( tnumber < LPC176X_TIMER_COUNT )
0259        && ( capture_port < LPC176X_CAPTURE_PORTS_COUNT )
0260        && ( function < LPC176X_TIMER_CAPTURE_FUNCTION_COUNT ) ) {
0261     timers[ tnumber ].device->CCR =
0262       LPC176X_SET_CCR( timers[ tnumber ].device->CCR,
0263         capture_port, function );
0264     lpc176x_pin_select( timers[ tnumber ].pinselcap[ capture_port ],
0265       LPC176X_PIN_FUNCTION_11 );
0266   }
0267 
0268   /* else implies that the timer number or the capture port is invalid. Also,
0269      an invalid number is returned. */
0270 
0271   return status_code;
0272 }
0273 
0274 inline rtems_status_code lpc176x_timer_external_match_config(
0275   const lpc176x_timer_number       number,
0276   const lpc176x_match_port         match_port,
0277   const lpc176x_ext_match_function function
0278 )
0279 {
0280   rtems_status_code status_code = RTEMS_INVALID_NUMBER;
0281 
0282   if ( ( number < LPC176X_TIMER_COUNT )
0283        && ( match_port < LPC176X_EMATCH_PORTS_COUNT ) ) {
0284     timers[ number ].device->EMR =
0285       LPC176X_SET_EMR( timers[ number ].device->EMR,
0286         match_port, function );
0287     lpc176x_pin_select( timers[ number ].pinselemat[ match_port ],
0288       LPC176X_PIN_FUNCTION_11 );
0289     status_code = RTEMS_SUCCESSFUL;
0290   }
0291 
0292   /* else implies that the timer number or the match port is invalid. Also,
0293      an invalid number is returned. */
0294 
0295   return status_code;
0296 }
0297 
0298 inline uint32_t lpc176x_timer_get_capvalue(
0299   const lpc176x_timer_number number,
0300   const lpc176x_capture_port capture_port
0301 )
0302 {
0303   assert( ( number < LPC176X_TIMER_COUNT )
0304     && ( capture_port < LPC176X_CAPTURE_PORTS_COUNT ) );
0305 
0306   return timers[ number ].device->CR[ capture_port ];
0307 }
0308 
0309 inline uint32_t lpc176x_timer_get_timer_value(
0310   const lpc176x_timer_number tnumber )
0311 {
0312   assert( tnumber < LPC176X_TIMER_COUNT );
0313 
0314   return timers[ tnumber ].device->TC;
0315 }
0316 
0317 inline rtems_status_code lpc176x_timer_set_timer_value(
0318   const lpc176x_timer_number tnumber,
0319   const uint32_t             timer_value
0320 )
0321 {
0322   rtems_status_code status_code = RTEMS_INVALID_NUMBER;
0323 
0324   if ( tnumber < LPC176X_TIMER_COUNT ) {
0325     timers[ tnumber ].device->TC = timer_value;
0326     status_code = RTEMS_SUCCESSFUL;
0327   }
0328 
0329   /* else implies that the timer number is invalid. Also,
0330      an invalid number is returned. */
0331 
0332   return status_code;
0333 }
0334 
0335 void lpc176x_timer_isr( void *arg )
0336 {
0337   const lpc176x_timer_number tnumber = (lpc176x_timer_number) arg;
0338 
0339   if ( tnumber < LPC176X_TIMER_COUNT ) {
0340     lpc176x_isr_function i;
0341 
0342     for ( i = 0; i < LPC176X_ISR_FUNCTIONS_COUNT; ++i ) {
0343       if ( lpc176x_timer_interrupt_is_pending( tnumber, i ) ) {
0344         lpc176x_call_desired_isr( tnumber, i );
0345         lpc176x_timer_reset_interrupt( tnumber, i );
0346       }
0347 
0348       /* else implies that the current timer is not pending. Also,
0349          there is nothing to do. */
0350     }
0351   }
0352 
0353   /* else implies that the timer number is not valid. Also,
0354      there is nothing to do. */
0355 }
0356 
0357 rtems_status_code lpc176x_timer_init( const lpc176x_timer_number tnumber )
0358 {
0359   rtems_status_code status_code = RTEMS_INVALID_NUMBER;
0360 
0361   if ( tnumber < LPC176X_TIMER_COUNT ) {
0362     status_code = lpc176x_module_enable( timers[ tnumber ].module,
0363       LPC176X_MODULE_PCLK_DEFAULT );
0364     RTEMS_CHECK_SC( status_code, "Enabling the timer module." );
0365 
0366     status_code = lpc176x_timer_reset( tnumber );
0367     status_code = lpc176x_timer_set_mode( tnumber,
0368       LPC176X_TIMER_MODE_TIMER );
0369     status_code = lpc176x_timer_set_resolution( tnumber,
0370       LPC176X_TIMER_DEFAULT_RESOLUTION );
0371 
0372     timers[ tnumber ].device->MCR = LPC176X_TIMER_CLEAR_FUNCTION;
0373     timers[ tnumber ].device->CCR = LPC176X_TIMER_CLEAR_FUNCTION;
0374     timers[ tnumber ].device->EMR = LPC176X_TIMER_CLEAR_FUNCTION;
0375   }
0376 
0377   /* else implies that the timer number is not valid. Also,
0378      an invalid number is returned. */
0379 
0380   return status_code;
0381 }
0382 
0383 rtems_status_code lpc176x_timer_init_with_interrupt(
0384   const lpc176x_timer_number            tnumber,
0385   const lpc176x_isr_funct_vector *const vector
0386 )
0387 {
0388   rtems_status_code status_code = RTEMS_INVALID_NUMBER;
0389 
0390   char isrname[ LPC176X_ISR_NAME_STRING_SIZE ];
0391 
0392   snprintf( isrname, LPC176X_ISR_NAME_STRING_SIZE, "TimerIsr%d", tnumber );
0393 
0394   if ( tnumber < LPC176X_TIMER_COUNT && vector != NULL ) {
0395     functions_vector[ tnumber ].funct_vector = vector;
0396 
0397     status_code = lpc176x_timer_init( tnumber );
0398     status_code = rtems_interrupt_handler_install(
0399       LPC176X_TIMER_VECTOR_NUMBER( tnumber ),
0400       isrname,
0401       RTEMS_INTERRUPT_UNIQUE,
0402       lpc176x_timer_isr,
0403       (void *) tnumber );
0404   }
0405 
0406   return status_code;
0407 }