diff --git a/arch/arm/src/stm32l4/stm32l4_tim_lowerhalf.c b/arch/arm/src/stm32l4/stm32l4_tim_lowerhalf.c index e7d0d72dbd0..f99b4b2a9d8 100644 --- a/arch/arm/src/stm32l4/stm32l4_tim_lowerhalf.c +++ b/arch/arm/src/stm32l4/stm32l4_tim_lowerhalf.c @@ -3,9 +3,11 @@ * * Copyright (C) 2015 Wail Khemir. All rights reserved. * Copyright (C) 2015 Omni Hoverboards Inc. All rights reserved. + * Copyright (C) 2016 Sebastien Lorquet All rights reserved. * Authors: Wail Khemir * Paul Alexander Patience * dev@ziggurat29.com + * Sebastien Lorquet * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -91,7 +93,8 @@ struct stm32l4_lowerhalf_s { FAR const struct timer_ops_s *ops; /* Lower half operations */ FAR struct stm32l4_tim_dev_s *tim; /* stm32 timer driver */ - tccb_t usrhandler; /* Current user interrupt handler */ + tccb_t callback; /* Current upper half interrupt callback */ + FAR void *arg; /* Argument passed to upper half callback */ const xcpt_t timhandler; /* Current timer interrupt handler */ bool started; /* True: Timer has been started */ const uint8_t resolution; /* Number of bits in the timer (16 or 32 bits) */ @@ -145,8 +148,8 @@ static int stm32l4_start(FAR struct timer_lowerhalf_s *lower); static int stm32l4_stop(FAR struct timer_lowerhalf_s *lower); static int stm32l4_settimeout(FAR struct timer_lowerhalf_s *lower, uint32_t timeout); -static tccb_t stm32l4_sethandler(FAR struct timer_lowerhalf_s *lower, - tccb_t handler); +static tccb_t stm32l4_setcallback(FAR struct timer_lowerhalf_s *lower, + tccb_t callback, FAR void *arg); /**************************************************************************** * Private Data @@ -155,110 +158,110 @@ static tccb_t stm32l4_sethandler(FAR struct timer_lowerhalf_s *lower, static const struct timer_ops_s g_timer_ops = { - .start = stm32l4_start, - .stop = stm32l4_stop, - .getstatus = NULL, - .settimeout = stm32l4_settimeout, - .sethandler = stm32l4_sethandler, - .ioctl = NULL, + .start = stm32l4_start, + .stop = stm32l4_stop, + .getstatus = NULL, + .settimeout = stm32l4_settimeout, + .setcallback = stm32l4_setcallback, + .ioctl = NULL, }; #ifdef CONFIG_STM32L4_TIM1 static struct stm32l4_lowerhalf_s g_tim1_lowerhalf = { - .ops = &g_timer_ops, - .timhandler = stm32l4_tim1_interrupt, - .resolution = STM32L4_TIM1_RES, + .ops = &g_timer_ops, + .timhandler = stm32l4_tim1_interrupt, + .resolution = STM32L4_TIM1_RES, }; #endif #ifdef CONFIG_STM32L4_TIM2 static struct stm32l4_lowerhalf_s g_tim2_lowerhalf = { - .ops = &g_timer_ops, - .timhandler = stm32l4_tim2_interrupt, - .resolution = STM32L4_TIM2_RES, + .ops = &g_timer_ops, + .timhandler = stm32l4_tim2_interrupt, + .resolution = STM32L4_TIM2_RES, }; #endif #ifdef CONFIG_STM32L4_TIM3 static struct stm32l4_lowerhalf_s g_tim3_lowerhalf = { - .ops = &g_timer_ops, - .timhandler = stm32l4_tim3_interrupt, - .resolution = STM32L4_TIM3_RES, + .ops = &g_timer_ops, + .timhandler = stm32l4_tim3_interrupt, + .resolution = STM32L4_TIM3_RES, }; #endif #ifdef CONFIG_STM32L4_TIM4 static struct stm32l4_lowerhalf_s g_tim4_lowerhalf = { - .ops = &g_timer_ops, - .timhandler = stm32l4_tim4_interrupt, - .resolution = STM32L4_TIM4_RES, + .ops = &g_timer_ops, + .timhandler = stm32l4_tim4_interrupt, + .resolution = STM32L4_TIM4_RES, }; #endif #ifdef CONFIG_STM32L4_TIM5 static struct stm32l4_lowerhalf_s g_tim5_lowerhalf = { - .ops = &g_timer_ops, - .timhandler = stm32l4_tim5_interrupt, - .resolution = STM32L4_TIM5_RES, + .ops = &g_timer_ops, + .timhandler = stm32l4_tim5_interrupt, + .resolution = STM32L4_TIM5_RES, }; #endif #ifdef CONFIG_STM32L4_TIM6 static struct stm32l4_lowerhalf_s g_tim6_lowerhalf = { - .ops = &g_timer_ops, - .timhandler = stm32l4_tim6_interrupt, - .resolution = STM32L4_TIM6_RES, + .ops = &g_timer_ops, + .timhandler = stm32l4_tim6_interrupt, + .resolution = STM32L4_TIM6_RES, }; #endif #ifdef CONFIG_STM32L4_TIM7 static struct stm32l4_lowerhalf_s g_tim7_lowerhalf = { - .ops = &g_timer_ops, - .timhandler = stm32l4_tim7_interrupt, - .resolution = STM32L4_TIM7_RES, + .ops = &g_timer_ops, + .timhandler = stm32l4_tim7_interrupt, + .resolution = STM32L4_TIM7_RES, }; #endif #ifdef CONFIG_STM32L4_TIM8 static struct stm32l4_lowerhalf_s g_tim8_lowerhalf = { - .ops = &g_timer_ops, - .timhandler = stm32l4_tim8_interrupt, - .resolution = STM32L4_TIM8_RES, + .ops = &g_timer_ops, + .timhandler = stm32l4_tim8_interrupt, + .resolution = STM32L4_TIM8_RES, }; #endif #ifdef CONFIG_STM32L4_TIM15 static struct stm32l4_lowerhalf_s g_tim15_lowerhalf = { - .ops = &g_timer_ops, - .timhandler = stm32l4_tim15_interrupt, - .resolution = STM32L4_TIM15_RES, + .ops = &g_timer_ops, + .timhandler = stm32l4_tim15_interrupt, + .resolution = STM32L4_TIM15_RES, }; #endif #ifdef CONFIG_STM32L4_TIM16 static struct stm32l4_lowerhalf_s g_tim16_lowerhalf = { - .ops = &g_timer_ops, - .timhandler = stm32l4_tim16_interrupt, - .resolution = STM32L4_TIM16_RES, + .ops = &g_timer_ops, + .timhandler = stm32l4_tim16_interrupt, + .resolution = STM32L4_TIM16_RES, }; #endif #ifdef CONFIG_STM32L4_TIM17 static struct stm32l4_lowerhalf_s g_tim17_lowerhalf = { - .ops = &g_timer_ops, - .timhandler = stm32l4_tim17_interrupt, - .resolution = STM32L4_TIM17_RES, + .ops = &g_timer_ops, + .timhandler = stm32l4_tim17_interrupt, + .resolution = STM32L4_TIM17_RES, }; #endif @@ -369,7 +372,7 @@ static int stm32l4_timer_handler(FAR struct stm32l4_lowerhalf_s *lower) STM32L4_TIM_ACKINT(lower->tim, 0); - if (lower->usrhandler(&next_interval_us)) + if (lower->callback(&next_interval_us, lower->arg)) { if (next_interval_us > 0) { @@ -407,7 +410,7 @@ static int stm32l4_start(FAR struct timer_lowerhalf_s *lower) { STM32L4_TIM_SETMODE(priv->tim, STM32L4_TIM_MODE_UP); - if (priv->usrhandler != NULL) + if (priv->callback != NULL) { STM32L4_TIM_SETISR(priv->tim, priv->timhandler, 0); STM32L4_TIM_ENABLEINT(priv->tim, 0); @@ -505,11 +508,12 @@ static int stm32l4_settimeout(FAR struct timer_lowerhalf_s *lower, * Call this user provided timeout handler. * * Input Parameters: - * lower - A pointer the publicly visible representation of the "lower-half" - * driver state structure. - * newhandler - The new timer expiration function pointer. If this - * function pointer is NULL, then the reset-on-expiration - * behavior is restored, + * lower - A pointer the publicly visible representation of the "lower-half" + * driver state structure. + * callback - The new timer expiration function pointer. If this + * function pointer is NULL, then the reset-on-expiration + * behavior is restored, + * arg - Argument that will be provided in the callback * * Returned Values: * The previous timer expiration function pointer or NULL is there was @@ -517,22 +521,18 @@ static int stm32l4_settimeout(FAR struct timer_lowerhalf_s *lower, * ****************************************************************************/ -static tccb_t stm32l4_sethandler(FAR struct timer_lowerhalf_s *lower, - tccb_t newhandler) +static void stm32l4_setcallback(FAR struct timer_lowerhalf_s *lower, + tccb_t callback, FAR void *arg) { FAR struct stm32l4_lowerhalf_s *priv = (FAR struct stm32l4_lowerhalf_s *)lower; - irqstate_t flags = enter_critical_section(); - /* Get the old handler return value */ + /* Save the new callback */ - tccb_t oldhandler = priv->usrhandler; + priv->callback = callback; + priv->arg = arg; - /* Save the new handler */ - - priv->usrhandler = newhandler; - - if (newhandler != NULL && priv->started) + if (callback != NULL && priv->started) { STM32L4_TIM_SETISR(priv->tim, priv->timhandler, 0); STM32L4_TIM_ENABLEINT(priv->tim, 0); @@ -544,7 +544,6 @@ static tccb_t stm32l4_sethandler(FAR struct timer_lowerhalf_s *lower, } leave_critical_section(flags); - return oldhandler; } /**************************************************************************** @@ -636,9 +635,9 @@ int stm32l4_timer_initialize(FAR const char *devpath, int timer) /* Initialize the elements of lower half state structure */ - lower->started = false; - lower->usrhandler = NULL; - lower->tim = stm32l4_tim_init(timer); + lower->started = false; + lower->callback = NULL; + lower->tim = stm32l4_tim_init(timer); if (lower->tim == NULL) { diff --git a/drivers/timers/timer.c b/drivers/timers/timer.c index 16c85fa5d73..ab71bb6ddbd 100644 --- a/drivers/timers/timer.c +++ b/drivers/timers/timer.c @@ -46,6 +46,7 @@ #include #include #include +#include #include #include #include @@ -66,11 +67,9 @@ struct timer_upperhalf_s { uint8_t crefs; /* The number of times the device has been opened */ -#ifdef HAVE_NOTIFICATION - uint8_t signal; /* The signal number to use in the notification */ + uint8_t signo; /* The signal number to use in the notification */ pid_t pid; /* The ID of the task/thread to receive the signal */ FAR void *arg; /* An argument to pass with the signal */ -#endif FAR char *path; /* Registration path */ /* The contained lower-half driver */ @@ -82,12 +81,7 @@ struct timer_upperhalf_s * Private Function Prototypes ****************************************************************************/ -#ifdef HAVE_NOTIFICATION - /* REVISIT: This function prototype is insufficient to support signaling */ - -static bool timer_notifier(FAR uint32_t *next_interval_us); -#endif - +static bool timer_notifier(FAR uint32_t *next_interval_us, FAR void *arg); static int timer_open(FAR struct file *filep); static int timer_close(FAR struct file *filep); static ssize_t timer_read(FAR struct file *filep, FAR char *buffer, @@ -131,15 +125,18 @@ static const struct file_operations g_timerops = * ************************************************************************************/ -#ifdef HAVE_NOTIFICATION -static bool timer_notifier(FAR uint32_t *next_interval_us) +static bool timer_notifier(FAR uint32_t *next_interval_us, FAR void *arg) { - FAR struct timer_upperhalf_s *upper = HOW?; + FAR struct timer_upperhalf_s *upper = (FAR struct timer_upperhalf_s *)arg; #ifdef CONFIG_CAN_PASS_STRUCTS union sigval value; #endif int ret; + DEBUGASSERT(upper != NULL); + + /* Signal the waiter.. if there is one */ + #ifdef CONFIG_CAN_PASS_STRUCTS value.sival_ptr = upper->arg; ret = sigqueue(upper->pid, upper->signo, value); @@ -149,7 +146,6 @@ static bool timer_notifier(FAR uint32_t *next_interval_us) return ret == OK; } -#endif /************************************************************************************ * Name: timer_open @@ -363,7 +359,6 @@ static int timer_ioctl(FAR struct file *filep, int cmd, unsigned long arg) } break; -#ifdef HAVE_NOTIFICATION /* cmd: TCIOC_NOTIFICATION * Description: Notify application via a signal when the timer expires. * Argument: signal number @@ -375,15 +370,15 @@ static int timer_ioctl(FAR struct file *filep, int cmd, unsigned long arg) case TCIOC_NOTIFICATION: { FAR struct timer_notify_s *notify = - (FAR struct timer_notify_s *)((uintptr_t)arg) + (FAR struct timer_notify_s *)((uintptr_t)arg); if (notify != NULL) { - upper->signo = notify->signal; - upper->get = notify->signal; - upper->arg = noify->arg; + upper->signo = notify->signo; + upper->pid = notify->pid; + upper->arg = notify->arg; - ret = timer_sethandler((FAR void *handle)upper, timer_notifier, NULL); + ret = timer_setcallback((FAR void *)upper, timer_notifier, upper); } else { @@ -391,7 +386,6 @@ static int timer_ioctl(FAR struct file *filep, int cmd, unsigned long arg) } } break; -#endif /* Any unrecognized IOCTL commands might be platform-specific ioctl commands */ @@ -548,7 +542,7 @@ void timer_unregister(FAR void *handle) } /**************************************************************************** - * Name: timer_sethandler + * Name: timer_setcallback * * Description: * This function can be called to add a callback into driver-related code @@ -556,21 +550,20 @@ void timer_unregister(FAR void *handle) * and may NOT be used by appliction code. * * Input parameters: - * handle - This is the handle that was returned by timer_register() - * newhandler - The new timer interrupt handler - * oldhandler - The previous timer interrupt handler (if any) + * handle - This is the handle that was returned by timer_register() + * newcallback - The new timer interrupt callback + * oldcallback - The previous timer interrupt callback (if any) + * arg - Argument to be provided with the callback * * Returned Value: * None * ****************************************************************************/ -int timer_sethandler(FAR void *handle, tccb_t newhandler, - FAR tccb_t *oldhandler) +int timer_setcallback(FAR void *handle, tccb_t newcallback, FAR void *arg) { FAR struct timer_upperhalf_s *upper; FAR struct timer_lowerhalf_s *lower; - tccb_t tmphandler; /* Recover the pointer to the upper-half driver state */ @@ -579,21 +572,13 @@ int timer_sethandler(FAR void *handle, tccb_t newhandler, lower = upper->lower; DEBUGASSERT(lower->ops != NULL); - /* Check if the lower half driver supports the sethandler method */ + /* Check if the lower half driver supports the setcallback method */ - if (lower->ops->sethandler != NULL) /* Optional */ + if (lower->ops->setcallback != NULL) /* Optional */ { /* Yes.. Defer the hander attachment to the lower half driver */ - tmphandler = lower->ops->sethandler(lower, newhandler); - - /* Return the oldhandler if a location to return it was provided */ - - if (oldhandler != NULL) - { - *oldhandler = tmphandler; - } - + lower->ops->setcallback(lower, newcallback, arg); return OK; } diff --git a/include/nuttx/timers/timer.h b/include/nuttx/timers/timer.h index eb2830bd560..a89369d5df7 100644 --- a/include/nuttx/timers/timer.h +++ b/include/nuttx/timers/timer.h @@ -52,11 +52,6 @@ /**************************************************************************** * Pre-processor Definitions ****************************************************************************/ -/* It would require some interface modifcations in order to support - * notifications. - */ - -#undef HAVE_NOTIFICATION /* IOCTL Commands ***********************************************************/ /* The timer driver uses a standard character driver framework. However, @@ -96,9 +91,7 @@ #define TCIOC_STOP _TCIOC(0x0002) #define TCIOC_GETSTATUS _TCIOC(0x0003) #define TCIOC_SETTIMEOUT _TCIOC(0x0004) -#ifdef HAVE_NOTIFICATION #define TCIOC_NOTIFICATION _TCIOC(0x0005) -#endif /* Bit Settings *************************************************************/ /* Bit settings for the struct timer_status_s flags field */ @@ -111,11 +104,11 @@ * Public Types ****************************************************************************/ -/* User function prototype. Returns true to reload the timer, and the +/* Upper half callback prototype. Returns true to reload the timer, and the * function can modify the next interval if desired. */ -typedef CODE bool (*tccb_t)(FAR uint32_t *next_interval_us); +typedef CODE bool (*tccb_t)(FAR uint32_t *next_interval_us, FAR void *arg); /* This is the type of the argument passed to the TCIOC_GETSTATUS ioctl and * and returned by the "lower half" getstatus() method. @@ -129,16 +122,14 @@ struct timer_status_s * (in microseconds) */ }; -#ifdef HAVE_NOTIFICATION /* This is the type of the argument passed to the TCIOC_NOTIFICATION ioctl */ struct timer_notify_s { FAR void *arg; /* An argument to pass with the signal */ pid_t pid; /* The ID of the task/thread to receive the signal */ - uint8_t signal; /* The signal number to use in the notification */ + uint8_t signo; /* The signal number to use in the notification */ }; -#endif /* This structure provides the "lower-half" driver operations available to * the "upper-half" driver. @@ -166,12 +157,13 @@ struct timer_ops_s CODE int (*settimeout)(FAR struct timer_lowerhalf_s *lower, uint32_t timeout); - /* Call this user provider timeout handler on timeout. - * NOTE: Providing handler==NULL disable. + /* Call the NuttX INTERNAL timeout callback on timeout. + * NOTE: Providing callback==NULL disable. + * NOT to call back into applications. */ - CODE tccb_t (*sethandler)(FAR struct timer_lowerhalf_s *lower, - CODE tccb_t handler); + CODE void (*setcallback)(FAR struct timer_lowerhalf_s *lower, + CODE tccb_t callback, FAR void *arg); /* Any ioctl commands that are not recognized by the "upper-half" driver * are forwarded to the lower half driver through this method. @@ -272,7 +264,7 @@ void timer_unregister(FAR void *handle); ****************************************************************************/ /**************************************************************************** - * Name: timer_sethandler + * Name: timer_setcallback * * Description: * This function can be called to add a callback into driver-related code @@ -280,9 +272,9 @@ void timer_unregister(FAR void *handle); * and may NOT be used by appliction code. * * Input parameters: - * handle - This is the handle that was returned by timer_register() - * newhandler - The new timer interrupt handler - * oldhandler - The previous timer interrupt handler (if any) + * handle - This is the handle that was returned by timer_register() + * callback - The new timer interrupt callback + * arg - Argument provided when the callback is called. * * Returned Value: * None @@ -290,8 +282,7 @@ void timer_unregister(FAR void *handle); ****************************************************************************/ #ifdef __KERNEL__ -int timer_sethandler(FAR void *handle, tccb_t newhandler, - FAR tccb_t *oldhandler); +int timer_setcallback(FAR void *handle, tccb_t callback, FAR void *arg); #endif /****************************************************************************