Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
R
RIOT
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Container Registry
Model registry
Operate
Environments
Monitor
Incidents
Service Desk
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
cm-projects
RIOT
Commits
c8f00d0a
Commit
c8f00d0a
authored
9 years ago
by
Thomas Eichinger
Browse files
Options
Downloads
Plain Diff
Merge pull request #4089 from dkm/pr/timer
Reworking timer in lm4f120, fix #4077
parents
315ae0ee
96444d63
No related branches found
Branches containing commit
No related tags found
No related merge requests found
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
boards/ek-lm4f120xl/include/periph_conf.h
+12
-5
12 additions, 5 deletions
boards/ek-lm4f120xl/include/periph_conf.h
cpu/lm4f120/periph/timer.c
+291
-58
291 additions, 58 deletions
cpu/lm4f120/periph/timer.c
with
303 additions
and
63 deletions
boards/ek-lm4f120xl/include/periph_conf.h
+
12
−
5
View file @
c8f00d0a
...
@@ -42,19 +42,26 @@ extern "C" {
...
@@ -42,19 +42,26 @@ extern "C" {
*/
*/
#define TIMER_NUMOF (2U)
#define TIMER_NUMOF (2U)
#define TIMER_0_EN 1
#define TIMER_0_EN 1
#define TIMER_1_EN
0
#define TIMER_1_EN
1
#define TIMER_IRQ_PRIO 1
#define TIMER_IRQ_PRIO 1
/* Timer 0 configuration */
/* Timer 0 configuration
*
* WTIMER0 is a 32/64bits timer.
* We use timer_a as TIMER_0
*/
#define TIMER_0_CHANNELS 1
#define TIMER_0_CHANNELS 1
#define TIMER_0_PRESCALER (39U)
#define TIMER_0_MAX_VALUE (0xffffffff)
#define TIMER_0_MAX_VALUE (0xffffffff)
#define TIMER_0_ISR isr_wtimer0a
#define TIMER_0_ISR isr_wtimer0a
#define TIMER_0_IRQ_CHAN Timer0A_IRQn
#define TIMER_0_IRQ_CHAN Timer0A_IRQn
/* Timer 1 configuration */
/* Timer 1 configuration
*
* WTIMER1 is a 32/64bits timer.
* We use timer_a as TIMER_1
*/
#define TIMER_1_CHANNELS 1
#define TIMER_1_CHANNELS 1
#define TIMER_1_PRESCALER (39U)
#define TIMER_1_MAX_VALUE (0xffffffff)
#define TIMER_1_MAX_VALUE (0xffffffff)
#define TIMER_1_ISR isr_wtimer1a
#define TIMER_1_ISR isr_wtimer1a
#define TIMER_1_IRQ_CHAN Timer1A_IRQn
#define TIMER_1_IRQ_CHAN Timer1A_IRQn
...
...
This diff is collapsed.
Click to expand it.
cpu/lm4f120/periph/timer.c
+
291
−
58
View file @
c8f00d0a
/*
/*
* Copyright (C) 2015 Rakendra Thapa <rakendrathapa@gmail.com
* Copyright (C) 2015 Rakendra Thapa <rakendrathapa@gmail.com
* 2015 Marc Poulhiès <dkm@kataplop.net>
*
*
* This file is subject to the terms and conditions of the GNU Lesser General
* This file is subject to the terms and conditions of the GNU Lesser General
* Public License v2.1. See the file LICENSE in the top level directory for more
* Public License v2.1. See the file LICENSE in the top level directory for more
...
@@ -14,6 +15,7 @@
...
@@ -14,6 +15,7 @@
* @brief Implementation of the low-level timer driver for the LM4F120
* @brief Implementation of the low-level timer driver for the LM4F120
*
*
* @author Rakendra Thapa <rakendrathapa@gmail.com>
* @author Rakendra Thapa <rakendrathapa@gmail.com>
* Marc Poulhiès <dkm@kataplop.net>
*/
*/
#include
<stdint.h>
#include
<stdint.h>
...
@@ -27,132 +29,363 @@
...
@@ -27,132 +29,363 @@
#define ENABLE_DEBUG (0)
#define ENABLE_DEBUG (0)
#include
"debug.h"
#include
"debug.h"
/* guard file in case no timers are defined */
/* guard file in case no timers are defined */
#if TIMER_
0_EN
#if TIMER_
NUMOF
/**
/**
* @brief Struct holding the configuration data
* @brief Struct holding the configuration data
* @{
* @{
*/
*/
typedef
struct
{
typedef
struct
{
void
(
*
cb
)(
int
);
/**< timeout callback */
void
(
*
cb
)(
int
);
/**< timeout callback */
unsigned
int
divisor
;
/**< software clock divisor */
}
timer_conf_t
;
}
timer_conf_t
;
static
timer_conf_t
config
[
TIMER_NUMOF
];
static
timer_conf_t
config
[
TIMER_NUMOF
];
/**@}*/
/**@}*/
#include
"hw_timer.h"
/* Missing from driverlib */
static
inline
unsigned
long
PRIV_TimerPrescaleSnapshotGet
(
unsigned
long
ulbase
,
unsigned
long
ultimer
)
{
return
((
ultimer
==
TIMER_A
)
?
HWREG
(
ulbase
+
TIMER_O_TAPS
)
:
HWREG
(
ulbase
+
TIMER_O_TBPS
));
}
static
inline
unsigned
long
long
_scaled_to_ll_value
(
unsigned
int
uncorrected
,
unsigned
int
divisor
)
{
const
unsigned
long
long
scaledv
=
(
unsigned
long
long
)
uncorrected
*
divisor
;
return
scaledv
;
}
static
inline
unsigned
int
_llvalue_to_scaled_value
(
unsigned
long
long
corrected
,
unsigned
int
divisor
)
{
const
unsigned
long
long
scaledv
=
corrected
/
divisor
;
return
scaledv
;
}
int
timer_init
(
tim_t
dev
,
unsigned
int
us_per_tick
,
void
(
*
callback
)(
int
))
int
timer_init
(
tim_t
dev
,
unsigned
int
us_per_tick
,
void
(
*
callback
)(
int
))
{
{
if
(
dev
==
TIMER_0
)
{
if
(
dev
>=
TIMER_NUMOF
){
config
[
dev
].
cb
=
callback
;
/* User Function */
return
-
1
;
ROM_SysCtlPeripheralEnable
(
SYSCTL_PERIPH_WTIMER0
);
/* Activate Timer0 */
}
WTIMER0_CTL_R
&=
~
0x00000001
;
/* Disable timer0A during setup */
WTIMER0_CFG_R
=
TIMER_CFG_16_BIT
;
config
[
dev
].
cb
=
callback
;
/* User Function */
WTIMER0_TAMR_R
=
TIMER_TAMR_TAMR_PERIOD
;
/* Configure for periodic mode */
config
[
dev
].
divisor
=
us_per_tick
*
ROM_SysCtlClockGet
()
/
1000000
;
WTIMER0_TAPR_R
=
TIMER_0_PRESCALER
;
/* 1us timer0A */
WTIMER0_ICR_R
=
0x00000001
;
/* clear timer0A timeout flag */
unsigned
int
sysctl_timer
;
WTIMER0_IMR_R
|=
0x00000001
;
/* arm timeout interrupt */
unsigned
int
timer_base
;
ROM_IntPrioritySet
(
INT_WTIMER0A
,
32
);
unsigned
int
timer_side
=
TIMER_A
;
timer_irq_enable
(
dev
);
unsigned
int
timer_cfg
=
TIMER_CFG_SPLIT_PAIR
|
TIMER_CFG_A_PERIODIC_UP
|
TIMER_TAMR_TAMIE
;
timer_start
(
dev
);
unsigned
int
timer_max_val
;
DEBUG
(
"startTimeout Value=0x%lx
\n
"
,
ROM_TimerValueGet
(
WTIMER0_BASE
,
TIMER_A
));
unsigned
int
timer_intbit
=
TIMER_TIMA_TIMEOUT
|
TIMER_TIMA_MATCH
;
return
1
;
}
switch
(
dev
){
return
-
1
;
#if TIMER_0_EN
case
TIMER_0
:
sysctl_timer
=
SYSCTL_PERIPH_WTIMER0
;
timer_base
=
WTIMER0_BASE
;
timer_max_val
=
TIMER_0_MAX_VALUE
;
break
;
#endif
#if TIMER_1_EN
case
TIMER_1
:
sysctl_timer
=
SYSCTL_PERIPH_WTIMER1
;
timer_base
=
WTIMER1_BASE
;
timer_max_val
=
TIMER_1_MAX_VALUE
;
break
;
#endif
default:
return
-
1
;
/* unreachable */
}
ROM_SysCtlPeripheralEnable
(
sysctl_timer
);
ROM_TimerDisable
(
timer_base
,
timer_side
);
ROM_TimerConfigure
(
timer_base
,
timer_cfg
);
unsigned
long
long
lltimer_val_max
=
_scaled_to_ll_value
(
timer_max_val
,
config
[
dev
].
divisor
);
ROM_TimerPrescaleSet
(
timer_base
,
timer_side
,
lltimer_val_max
>>
32
);
ROM_TimerLoadSet
(
timer_base
,
timer_side
,
lltimer_val_max
&
0xFFFFFFFF
);
ROM_TimerIntClear
(
timer_base
,
timer_intbit
);
ROM_TimerIntEnable
(
timer_base
,
timer_intbit
);
timer_irq_enable
(
dev
);
timer_start
(
dev
);
return
0
;
}
}
int
timer_set
(
tim_t
dev
,
int
channel
,
unsigned
int
timeout
)
int
timer_set
(
tim_t
dev
,
int
channel
,
unsigned
int
timeout
)
{
{
if
(
dev
==
TIMER_0
)
{
unsigned
int
corrected_now
;
unsigned
int
now
=
timer_read
(
dev
)
;
int
retval
;
DEBUG
(
"timer_set now=0x%x
\n
"
,
now
);
DEBUG
(
"timer_set timeout=0x%x
\n
"
,
timeout
);
if
(
dev
>=
TIMER_NUMOF
){
return
timer_set_absolute
(
dev
,
channel
,
now
+
timeout
)
;
return
-
1
;
}
}
return
-
1
;
corrected_now
=
timer_read
(
dev
);
retval
=
timer_set_absolute
(
dev
,
channel
,
corrected_now
+
timeout
);
return
retval
;
}
}
int
timer_set_absolute
(
tim_t
dev
,
int
channel
,
unsigned
int
value
)
int
timer_set_absolute
(
tim_t
dev
,
int
channel
,
unsigned
int
value
)
{
{
if
(
dev
==
TIMER_0
)
{
unsigned
int
timer_base
;
WTIMER0_TAILR_R
=
0x00000000
|
value
;
/* period; Reload value */
unsigned
int
timer_side
=
TIMER_A
;
DEBUG
(
"Setting timer absolute value=0x%x
\n
"
,
value
);
unsigned
long
long
scaledv
;
return
1
;
if
(
dev
>=
TIMER_NUMOF
){
return
-
1
;
}
switch
(
dev
){
#if TIMER_0_EN
case
TIMER_0
:
timer_base
=
WTIMER0_BASE
;
break
;
#endif
#if TIMER_1_EN
case
TIMER_1
:
timer_base
=
WTIMER1_BASE
;
break
;
#endif
default:
return
-
1
;
/* unreachable */
break
;
}
ROM_TimerDisable
(
timer_base
,
timer_side
);
scaledv
=
_scaled_to_ll_value
(
value
,
config
[
dev
].
divisor
);
if
(
scaledv
>>
32
){
ROM_TimerPrescaleMatchSet
(
timer_base
,
timer_side
,
scaledv
>>
32
);
}
}
return
-
1
;
else
{
ROM_TimerPrescaleMatchSet
(
timer_base
,
timer_side
,
0
);
}
ROM_TimerMatchSet
(
timer_base
,
timer_side
,
(
unsigned
long
)
(
scaledv
&
0xFFFFFFFF
));
ROM_TimerEnable
(
timer_base
,
timer_side
);
return
1
;
}
}
int
timer_clear
(
tim_t
dev
,
int
channel
)
int
timer_clear
(
tim_t
dev
,
int
channel
)
{
{
if
(
dev
==
TIMER_0
){
unsigned
int
timer_intbit
=
TIMER_TIMA_TIMEOUT
;
WTIMER0_ICR_R
=
TIMER_ICR_TATOCINT
;
unsigned
int
timer_base
;
return
1
;
if
(
dev
>=
TIMER_NUMOF
){
return
-
1
;
}
}
return
-
1
;
switch
(
dev
){
#if TIMER_0_EN
case
TIMER_0
:
timer_base
=
WTIMER0_BASE
;
break
;
#endif
#if TIMER_1_EN
case
TIMER_1
:
timer_base
=
WTIMER1_BASE
;
break
;
#endif
default:
return
-
1
;
/* unreachable */
break
;
}
ROM_TimerIntClear
(
timer_base
,
timer_intbit
);
return
1
;
}
}
unsigned
int
timer_read
(
tim_t
dev
)
unsigned
int
timer_read
(
tim_t
dev
)
{
{
if
(
dev
==
TIMER_0
)
{
unsigned
int
timer_base
;
unsigned
int
currTimer0Val
=
0
;
unsigned
int
timer_side
=
TIMER_A
;
unsigned
int
loadTimer0Val
=
0
;
unsigned
long
long
high_bits
,
high_bits_dup
;
currTimer0Val
=
(
unsigned
int
)
ROM_TimerValueGet
(
WTIMER0_BASE
,
TIMER_A
);
unsigned
long
long
low_bits
;
loadTimer0Val
=
(
unsigned
int
)
ROM_TimerLoadGet
(
WTIMER0_BASE
,
TIMER_A
);
unsigned
long
long
total
;
DEBUG
(
"WTIMER0_TAILR_R=0x%lx
\t
currTimer0Val=0x%x
\t
loadTimer0Val=0x%x
\n
"
,
WTIMER0_TAILR_R
,
currTimer0Val
,
loadTimer0Val
);
unsigned
int
scaled_value
;
return
(
loadTimer0Val
-
currTimer0Val
);
if
(
dev
>=
TIMER_NUMOF
){
return
-
1
;
}
}
return
0
;
switch
(
dev
){
#if TIMER_0_EN
case
TIMER_0
:
timer_base
=
WTIMER0_BASE
;
break
;
#endif
#if TIMER_1_EN
case
TIMER_1
:
timer_base
=
WTIMER1_BASE
;
break
;
#endif
default:
return
-
1
;
/* unreachable */
break
;
}
/* handle overflow happening between the 2 register reads */
do
{
high_bits
=
((
unsigned
long
long
)
PRIV_TimerPrescaleSnapshotGet
(
timer_base
,
timer_side
))
<<
32
;
low_bits
=
(
unsigned
long
long
)
ROM_TimerValueGet
(
timer_base
,
timer_side
);
high_bits_dup
=
((
unsigned
long
long
)
PRIV_TimerPrescaleSnapshotGet
(
timer_base
,
timer_side
))
<<
32
;
}
while
(
high_bits
!=
high_bits_dup
);
total
=
high_bits
+
low_bits
;
DEBUG
(
"Combined %lx:%lx
\n
"
,
(
unsigned
long
)
(
total
>>
32
),
(
unsigned
long
)
(
total
&
0xFFFFFFFF
));
scaled_value
=
_llvalue_to_scaled_value
(
total
,
config
[
dev
].
divisor
);
return
scaled_value
;
}
}
void
timer_start
(
tim_t
dev
)
void
timer_start
(
tim_t
dev
)
{
{
if
(
dev
==
TIMER_0
)
{
unsigned
int
timer_base
;
ROM_TimerEnable
(
WTIMER0_BASE
,
TIMER_A
);
unsigned
int
timer_side
=
TIMER_A
;
if
(
dev
>=
TIMER_NUMOF
){
return
;
}
switch
(
dev
){
#if TIMER_0_EN
case
TIMER_0
:
timer_base
=
WTIMER0_BASE
;
break
;
#endif
#if TIMER_1_EN
case
TIMER_1
:
timer_base
=
WTIMER1_BASE
;
break
;
#endif
default:
return
;
/* unreachable */
}
}
ROM_TimerEnable
(
timer_base
,
timer_side
);
}
}
void
timer_stop
(
tim_t
dev
)
void
timer_stop
(
tim_t
dev
)
{
{
if
(
dev
==
TIMER_0
)
{
unsigned
int
timer_base
;
ROM_TimerDisable
(
WTIMER0_BASE
,
TIMER_A
);
unsigned
int
timer_side
=
TIMER_A
;
if
(
dev
>=
TIMER_NUMOF
){
return
;
}
switch
(
dev
){
#if TIMER_0_EN
case
TIMER_0
:
timer_base
=
WTIMER0_BASE
;
break
;
#endif
#if TIMER_1_EN
case
TIMER_1
:
timer_base
=
WTIMER1_BASE
;
break
;
#endif
default:
return
;
/* unreachable */
}
}
ROM_TimerDisable
(
timer_base
,
timer_side
);
}
}
void
timer_irq_enable
(
tim_t
dev
)
void
timer_irq_enable
(
tim_t
dev
)
{
{
if
(
dev
==
TIMER_0
)
{
unsigned
int
timer_intbase
;
ROM_IntEnable
(
INT_WTIMER0A
);
ROM_TimerIntEnable
(
WTIMER0_BASE
,
TIMER_TIMA_TIMEOUT
);
if
(
dev
>=
TIMER_NUMOF
){
return
;
}
switch
(
dev
){
#if TIMER_0_EN
case
TIMER_0
:
timer_intbase
=
INT_WTIMER0A
;
break
;
#endif
#if TIMER_1_EN
case
TIMER_1
:
timer_intbase
=
INT_WTIMER1A
;
break
;
#endif
default:
return
;
/* unreachable */
}
}
ROM_IntPrioritySet
(
timer_intbase
,
32
);
ROM_IntEnable
(
timer_intbase
);
}
}
void
timer_irq_disable
(
tim_t
dev
)
void
timer_irq_disable
(
tim_t
dev
)
{
{
if
(
dev
==
TIMER_0
)
{
unsigned
int
timer_base
;
ROM_IntDisable
(
INT_WTIMER0A
);
unsigned
int
timer_intbit
=
TIMER_TIMA_TIMEOUT
;
unsigned
int
timer_intbase
;
if
(
dev
>=
TIMER_NUMOF
){
return
;
}
switch
(
dev
){
#if TIMER_0_EN
case
TIMER_0
:
timer_base
=
WTIMER0_BASE
;
timer_intbase
=
INT_WTIMER0A
;
break
;
#endif
#if TIMER_1_EN
case
TIMER_1
:
timer_base
=
WTIMER1_BASE
;
timer_intbase
=
INT_WTIMER1A
;
break
;
#endif
default:
return
;
/* unreachable */
}
}
ROM_IntEnable
(
timer_intbase
);
ROM_TimerIntDisable
(
timer_base
,
timer_intbit
);
}
}
#if TIMER_0_EN
#if TIMER_0_EN
void
isr_timer0a
(
void
)
void
isr_
w
timer0a
(
void
)
{
{
TIMER0_ICR_R
=
TIMER_ICR_TATOCINT
;
/* Clears both IT */
ROM_TimerIntClear
(
WTIMER0_BASE
,
TIMER_TIMA_TIMEOUT
|
TIMER_TIMA_MATCH
);
config
[
TIMER_0
].
cb
(
0
);
config
[
TIMER_0
].
cb
(
0
);
if
(
sched_context_switch_request
){
if
(
sched_context_switch_request
){
thread_yield
();
thread_yield
();
}
}
}
}
void
isr_wtimer0a
(
void
)
#endif
/* TIMER_0_EN */
#if TIMER_1_EN
void
isr_wtimer1a
(
void
)
{
{
WTIMER0_ICR_R
=
TIMER_ICR_TATOCINT
;
ROM_TimerIntClear
(
WTIMER1_BASE
,
TIMER_TIMA_TIMEOUT
|
TIMER_TIMA_MATCH
)
;
config
[
TIMER_
0
].
cb
(
0
);
config
[
TIMER_
1
].
cb
(
0
);
if
(
sched_context_switch_request
){
if
(
sched_context_switch_request
){
thread_yield
();
thread_yield
();
}
}
}
}
#endif
/* TIMER_
0
_EN */
#endif
/* TIMER_
1
_EN */
#endif
/* TIMER_
0_EN
*/
#endif
/* TIMER_
NUMOF
*/
/** @} */
/** @} */
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment