Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
81 changes: 62 additions & 19 deletions arch/arm/src/common/stm32/stm32_tickless_m3m4_v1.c
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,15 @@ static inline void stm32_tickless_ackint(int channel)
stm32_putreg16(STM32_BTIM_SR_OFFSET, ~(1 << channel));
}

/****************************************************************************
* Name: stm32_tickless_trigint
****************************************************************************/

static inline void stm32_tickless_trigint(int channel)
{
stm32_putreg16(STM32_ATIM_EGR_OFFSET, 1 << channel);
}

/****************************************************************************
* Name: stm32_tickless_getint
****************************************************************************/
Expand Down Expand Up @@ -835,15 +844,9 @@ int up_timer_cancel(struct timespec *ts)
(unsigned long)period, (unsigned long)count);

#ifndef HAVE_32BIT_TICKLESS
if (count > period)
{
/* Handle rollover */

period += UINT16_MAX;
}
else if (count == period)
if ((int16_t)(period - count) <= 0)
#else
if (count >= period)
if ((int32_t)(period - count) <= 0)
#endif
{
/* No time remaining */
Expand All @@ -861,8 +864,13 @@ int up_timer_cancel(struct timespec *ts)
* usecs = (ticks * USEC_PER_SEC) / frequency;
*/

usec = (((uint64_t)(period - count)) * USEC_PER_SEC) /
#ifndef HAVE_32BIT_TICKLESS
usec = (((uint64_t)(uint16_t)(period - count)) * USEC_PER_SEC) /
g_tickless.frequency;
#else
usec = (((uint64_t)(uint32_t)(period - count)) * USEC_PER_SEC) /
g_tickless.frequency;
#endif

/* Return the time remaining in the correct form */

Expand Down Expand Up @@ -929,18 +937,35 @@ int up_timer_start(const struct timespec *ts)

/* Express the delay in microseconds */

usec = ts->tv_sec * USEC_PER_SEC +
(ts->tv_nsec / NSEC_PER_USEC);
if (ts->tv_sec < 0 || (ts->tv_sec == 0 && ts->tv_nsec <= 0))
{
period = 0;
}
else
{
usec = ts->tv_sec * USEC_PER_SEC +
(ts->tv_nsec / NSEC_PER_USEC);

/* Get the timer counter frequency and determine the number of counts need
* to achieve the requested delay.
*
* frequency = ticks / second
* ticks = seconds * frequency
* = (usecs * frequency) / USEC_PER_SEC;
*/
/* Get the timer counter frequency and determine the number of counts
* need to achieve the requested delay.
*
* frequency = ticks / second
* ticks = seconds * frequency
* = (usecs * frequency) / USEC_PER_SEC;
*/

period = (usec * (uint64_t)g_tickless.frequency) / USEC_PER_SEC;
}

if (period == 0)
{
stm32_tickless_enableint(g_tickless.channel);
stm32_tickless_trigint(g_tickless.channel);
g_tickless.pending = true;
leave_critical_section(flags);
return OK;
}

period = (usec * (uint64_t)g_tickless.frequency) / USEC_PER_SEC;
count = STM32_TIM_GETCOUNTER(g_tickless.tch);

tmrinfo("usec=%llu period=%08llx\n", usec, period);
Expand Down Expand Up @@ -968,6 +993,24 @@ int up_timer_start(const struct timespec *ts)
stm32_tickless_enableint(g_tickless.channel);

g_tickless.pending = true;

/* Check if the counter already reached or passed the compare target
* while we were configuring the registers.
*/

#ifdef HAVE_32BIT_TICKLESS
if ((uint32_t)(STM32_TIM_GETCOUNTER(g_tickless.tch) - count) >=
(uint32_t)period)
#else
if ((uint16_t)(STM32_TIM_GETCOUNTER(g_tickless.tch) - (uint16_t)count) >=
(uint16_t)period)
#endif
{
/* Target time already elapsed; force the interrupt immediately */

stm32_tickless_trigint(g_tickless.channel);
}

leave_critical_section(flags);
return OK;
}
Expand Down
84 changes: 64 additions & 20 deletions arch/arm/src/stm32f7/stm32_tickless.c
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,15 @@ static inline void stm32_tickless_ackint(int channel)
stm32_putreg16(STM32_BTIM_SR_OFFSET, ~(1 << channel));
}

/****************************************************************************
* Name: stm32_tickless_trigint
****************************************************************************/

static inline void stm32_tickless_trigint(int channel)
{
stm32_putreg16(STM32_GTIM_EGR_OFFSET, 1 << channel);
}

/****************************************************************************
* Name: stm32_tickless_getint
****************************************************************************/
Expand Down Expand Up @@ -379,9 +388,9 @@ static int stm32_tickless_handler(int irq, void *context, void *arg)
return OK;
}

#ifdef CONFIG_SCHED_TICKLESS_ALARM
/****************************************************************************
* Name: stm32_get_counter
*
****************************************************************************/

static uint64_t stm32_get_counter(void)
Expand All @@ -394,6 +403,7 @@ static uint64_t stm32_get_counter(void)
STM32_TIM_GETCOUNTER(g_tickless.tch);
#endif
}
#endif

/****************************************************************************
* Public Functions
Expand Down Expand Up @@ -877,15 +887,9 @@ int up_timer_cancel(struct timespec *ts)
(unsigned long)period, (unsigned long)count);

#ifndef HAVE_32BIT_TICKLESS
if (count > period)
{
/* Handle rollover */

period += UINT16_MAX;
}
else if (count == period)
if ((int16_t)(period - count) <= 0)
#else
if (count >= period)
if ((int32_t)(period - count) <= 0)
#endif
{
/* No time remaining */
Expand All @@ -903,8 +907,13 @@ int up_timer_cancel(struct timespec *ts)
* usecs = (ticks * USEC_PER_SEC) / frequency;
*/

usec = (((uint64_t)(period - count)) * USEC_PER_SEC) /
#ifndef HAVE_32BIT_TICKLESS
usec = (((uint64_t)(uint16_t)(period - count)) * USEC_PER_SEC) /
g_tickless.frequency;
#else
usec = (((uint64_t)(uint32_t)(period - count)) * USEC_PER_SEC) /
g_tickless.frequency;
#endif

/* Return the time remaining in the correct form */

Expand Down Expand Up @@ -973,18 +982,35 @@ int up_timer_start(const struct timespec *ts)

/* Express the delay in microseconds */

usec = ts->tv_sec * USEC_PER_SEC +
(ts->tv_nsec / NSEC_PER_USEC);
if (ts->tv_sec < 0 || (ts->tv_sec == 0 && ts->tv_nsec <= 0))
{
period = 0;
}
else
{
usec = ts->tv_sec * USEC_PER_SEC +
(ts->tv_nsec / NSEC_PER_USEC);

/* Get the timer counter frequency and determine the number of counts need
* to achieve the requested delay.
*
* frequency = ticks / second
* ticks = seconds * frequency
* = (usecs * frequency) / USEC_PER_SEC;
*/
/* Get the timer counter frequency and determine the number of counts
* need to achieve the requested delay.
*
* frequency = ticks / second
* ticks = seconds * frequency
* = (usecs * frequency) / USEC_PER_SEC;
*/

period = (usec * (uint64_t)g_tickless.frequency) / USEC_PER_SEC;
}

if (period == 0)
{
stm32_tickless_enableint(g_tickless.channel);
stm32_tickless_trigint(g_tickless.channel);
g_tickless.pending = true;
leave_critical_section(flags);
return OK;
}

period = (usec * (uint64_t)g_tickless.frequency) / USEC_PER_SEC;
count = STM32_TIM_GETCOUNTER(g_tickless.tch);

tmrinfo("usec=%llu period=%08llx\n", usec, period);
Expand Down Expand Up @@ -1012,6 +1038,24 @@ int up_timer_start(const struct timespec *ts)
stm32_tickless_enableint(g_tickless.channel);

g_tickless.pending = true;

/* Check if the counter already reached or passed the compare target
* while we were configuring the registers.
*/

#ifdef HAVE_32BIT_TICKLESS
if ((uint32_t)(STM32_TIM_GETCOUNTER(g_tickless.tch) - count) >=
(uint32_t)period)
#else
if ((uint16_t)(STM32_TIM_GETCOUNTER(g_tickless.tch) - (uint16_t)count) >=
(uint16_t)period)
#endif
{
/* Target time already elapsed; force the interrupt immediately */

stm32_tickless_trigint(g_tickless.channel);
}

leave_critical_section(flags);
return OK;
}
Expand Down
84 changes: 64 additions & 20 deletions arch/arm/src/stm32h7/stm32_tickless.c
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,15 @@ static inline void stm32_tickless_ackint(int channel)
stm32_putreg16(STM32_BTIM_SR_OFFSET, ~(1 << channel));
}

/****************************************************************************
* Name: stm32_tickless_trigint
****************************************************************************/

static inline void stm32_tickless_trigint(int channel)
{
stm32_putreg16(STM32_GTIM_EGR_OFFSET, 1 << channel);
}

/****************************************************************************
* Name: stm32_tickless_getint
****************************************************************************/
Expand Down Expand Up @@ -366,9 +375,9 @@ static int stm32_tickless_handler(int irq, void *context, void *arg)
return OK;
}

#ifdef CONFIG_SCHED_TICKLESS_ALARM
/****************************************************************************
* Name: stm32_get_counter
*
****************************************************************************/

static uint64_t stm32_get_counter(void)
Expand All @@ -381,6 +390,7 @@ static uint64_t stm32_get_counter(void)
STM32_TIM_GETCOUNTER(g_tickless.tch);
#endif
}
#endif

/****************************************************************************
* Public Functions
Expand Down Expand Up @@ -851,15 +861,9 @@ int up_timer_cancel(struct timespec *ts)
(unsigned long)period, (unsigned long)count);

#ifndef HAVE_32BIT_TICKLESS
if (count > period)
{
/* Handle rollover */

period += UINT16_MAX;
}
else if (count == period)
if ((int16_t)(period - count) <= 0)
#else
if (count >= period)
if ((int32_t)(period - count) <= 0)
#endif
{
/* No time remaining */
Expand All @@ -877,8 +881,13 @@ int up_timer_cancel(struct timespec *ts)
* usecs = (ticks * USEC_PER_SEC) / frequency;
*/

usec = (((uint64_t)(period - count)) * USEC_PER_SEC) /
#ifndef HAVE_32BIT_TICKLESS
usec = (((uint64_t)(uint16_t)(period - count)) * USEC_PER_SEC) /
g_tickless.frequency;
#else
usec = (((uint64_t)(uint32_t)(period - count)) * USEC_PER_SEC) /
g_tickless.frequency;
#endif

/* Return the time remaining in the correct form */

Expand Down Expand Up @@ -947,18 +956,35 @@ int up_timer_start(const struct timespec *ts)

/* Express the delay in microseconds */

usec = ts->tv_sec * USEC_PER_SEC +
(ts->tv_nsec / NSEC_PER_USEC);
if (ts->tv_sec < 0 || (ts->tv_sec == 0 && ts->tv_nsec <= 0))
{
period = 0;
}
else
{
usec = ts->tv_sec * USEC_PER_SEC +
(ts->tv_nsec / NSEC_PER_USEC);

/* Get the timer counter frequency and determine the number of counts need
* to achieve the requested delay.
*
* frequency = ticks / second
* ticks = seconds * frequency
* = (usecs * frequency) / USEC_PER_SEC;
*/
/* Get the timer counter frequency and determine the number of counts
* need to achieve the requested delay.
*
* frequency = ticks / second
* ticks = seconds * frequency
* = (usecs * frequency) / USEC_PER_SEC;
*/

period = (usec * (uint64_t)g_tickless.frequency) / USEC_PER_SEC;
}

if (period == 0)
{
stm32_tickless_enableint(g_tickless.channel);
stm32_tickless_trigint(g_tickless.channel);
g_tickless.pending = true;
leave_critical_section(flags);
return OK;
}

period = (usec * (uint64_t)g_tickless.frequency) / USEC_PER_SEC;
count = STM32_TIM_GETCOUNTER(g_tickless.tch);

tmrinfo("usec=%llu period=%08llx\n", usec, period);
Expand Down Expand Up @@ -986,6 +1012,24 @@ int up_timer_start(const struct timespec *ts)
stm32_tickless_enableint(g_tickless.channel);

g_tickless.pending = true;

/* Check if the counter already reached or passed the compare target
* while we were configuring the registers.
*/

#ifdef HAVE_32BIT_TICKLESS
if ((uint32_t)(STM32_TIM_GETCOUNTER(g_tickless.tch) - count) >=
(uint32_t)period)
#else
if ((uint16_t)(STM32_TIM_GETCOUNTER(g_tickless.tch) - (uint16_t)count) >=
(uint16_t)period)
#endif
{
/* Target time already elapsed; force the interrupt immediately */

stm32_tickless_trigint(g_tickless.channel);
}

leave_critical_section(flags);
return OK;
}
Expand Down
Loading
Loading