Contiki-Inga 3.x
rtimer-arch.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2012, Texas Instruments Incorporated - http://www.ti.com/
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  * notice, this list of conditions and the following disclaimer in the
12  * documentation and/or other materials provided with the distribution.
13  *
14  * 3. Neither the name of the copyright holder nor the names of its
15  * contributors may be used to endorse or promote products derived
16  * from this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
21  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
22  * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
23  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
27  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
29  * OF THE POSSIBILITY OF SUCH DAMAGE.
30  */
31 /**
32  * \addtogroup cc2538-rtimer
33  * @{
34  *
35  * \file
36  * Implementation of the arch-specific rtimer functions for the cc2538
37  *
38  */
39 #include "contiki.h"
40 #include "sys/energest.h"
41 #include "sys/rtimer.h"
42 #include "dev/nvic.h"
43 #include "dev/smwdthrosc.h"
44 #include "cpu.h"
45 #include "lpm.h"
46 
47 #include <stdint.h>
48 /*---------------------------------------------------------------------------*/
49 static volatile rtimer_clock_t next_trigger;
50 /*---------------------------------------------------------------------------*/
51 /**
52  * \brief We don't need to explicitly initialise anything but this
53  * routine is required by the API.
54  *
55  * The Sleep Timer starts ticking automatically as soon as the device
56  * turns on. We don't need to turn on interrupts before the first call
57  * to rtimer_arch_schedule()
58  */
59 void
61 {
62  return;
63 }
64 /*---------------------------------------------------------------------------*/
65 /**
66  * \brief Schedules an rtimer task to be triggered at time t
67  * \param t The time when the task will need executed. This is an absolute
68  * time, in other words the task will be executed AT time \e t,
69  * not IN \e t ticks
70  */
71 void
72 rtimer_arch_schedule(rtimer_clock_t t)
73 {
74  rtimer_clock_t now;
75 
76  /* STLOAD must be 1 */
77  while((REG(SMWDTHROSC_STLOAD) & SMWDTHROSC_STLOAD_STLOAD) != 1);
78 
80 
81  now = RTIMER_NOW();
82 
83  /*
84  * New value must be 5 ticks in the future. The ST may tick once while we're
85  * writing the registers. We play it safe here and we add a bit of leeway
86  */
87  if((int32_t)(t - now) < 7) {
88  t = now + 7;
89  }
90 
91  /* ST0 latches ST[1:3] and must be written last */
92  REG(SMWDTHROSC_ST3) = (t >> 24) & 0x000000FF;
93  REG(SMWDTHROSC_ST2) = (t >> 16) & 0x000000FF;
94  REG(SMWDTHROSC_ST1) = (t >> 8) & 0x000000FF;
95  REG(SMWDTHROSC_ST0) = t & 0x000000FF;
96 
98 
99  /* Store the value. The LPM module will query us for it */
100  next_trigger = t;
101 
103 }
104 /*---------------------------------------------------------------------------*/
105 rtimer_clock_t
107 {
108  return next_trigger;
109 }
110 /*---------------------------------------------------------------------------*/
111 /**
112  * \brief Returns the current real-time clock time
113  * \return The current rtimer time in ticks
114  */
115 rtimer_clock_t
117 {
118  rtimer_clock_t rv;
119 
120  /* SMWDTHROSC_ST0 latches ST[1:3] and must be read first */
121  rv = REG(SMWDTHROSC_ST0);
122  rv |= (REG(SMWDTHROSC_ST1) << 8);
123  rv |= (REG(SMWDTHROSC_ST2) << 16);
124  rv |= (REG(SMWDTHROSC_ST3) << 24);
125 
126  return rv;
127 }
128 /*---------------------------------------------------------------------------*/
129 /**
130  * \brief The rtimer ISR
131  *
132  * Interrupts are only turned on when we have an rtimer task to schedule
133  * Once the interrupt fires, the task is called and then interrupts no
134  * longer get acknowledged until the next task needs scheduled.
135  */
136 void
137 rtimer_isr()
138 {
139  /*
140  * If we were in PM1+, call the wake-up sequence first. This will make sure
141  * that the 32MHz OSC is selected as the clock source. We need to do this
142  * before calling the next rtimer_task, since the task may need the RF.
143  */
144  lpm_exit();
145 
146  ENERGEST_ON(ENERGEST_TYPE_IRQ);
147 
148  next_trigger = 0;
149 
152 
153  rtimer_run_next();
154 
155  ENERGEST_OFF(ENERGEST_TYPE_IRQ);
156 }
157 /*---------------------------------------------------------------------------*/
158 /** @} */