aboutsummaryrefslogtreecommitdiff
path: root/src/drivers/boards/px4cannode-v1/bootloader/src/timer.c
blob: 6f2014063283919c39fc669d17cdf8a99d36eb2c (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
#include <nuttx/config.h>

#include "board_config.h"

#include <sys/types.h>
#include <stdint.h>
#include <string.h>

#include <nuttx/arch.h>
#include <arch/irq.h>

#include "bl_macros.h"
#include "timer.h"
#include "nvic.h"

#include <arch/board/board.h>



typedef enum {
        OneShot         = modeOneShot,
        Repeating       = modeRepeating,
        Timeout         = modeTimeout,

        modeMsk         = 0x3 ,
        running         = modeStarted,
        inuse           = 0x80,

} bl_timer_ctl_t;

typedef struct {
  bl_timer_cb_t         usr;
  time_ms_t             count;
  time_ms_t             reload;
  bl_timer_ctl_t        ctl;
} bl_timer_t;

bl_timer_t timers[OPT_BL_NUMBER_TIMERS];

bl_timer_cb_t null_cb =
    {
       0,
       0
    };


static time_ms_t sys_tic;

time_ms_t timer_tic(void)
{
  return sys_tic;
}

void sched_process_timer(void)
{
  PROBE(1,true);
  PROBE(1,false);

  sys_tic++;
  time_ms_t ms_elapsed = (CONFIG_USEC_PER_TICK/1000);
  bl_timer_id t;
  for( t =  arraySize(timers)-1; (int8_t) t >= 0; t--) {
      if ((timers[t].ctl & (inuse|running)) == (inuse|running)) {
          if (timers[t].count != 0 && timers[t].count > ms_elapsed) {
              timers[t].count -= ms_elapsed;
          } else {
                  timers[t].count = 0;

                  switch(timers[t].ctl & ~(inuse|running)) {

                    case Timeout:
                       break;
                    case OneShot: {
                        bl_timer_cb_t user = timers[t].usr;
                        memset(&timers[t], 0, sizeof(timers[t]));
                        if (user.cb) {
                            user.cb(t, user.context);
                        }
                    }
                      break;
                    case Repeating:
                      timers[t].count = timers[t].reload;
                      if (timers[t].usr.cb) {
                          timers[t].usr.cb(t, timers[t].usr.context);
                      }
                      break;
                    default:
                       break;
                  }
              }
          }
      }
}

bl_timer_id timer_allocate(bl_timer_modes_t mode, time_ms_t msfromnow, bl_timer_cb_t *fc)
{
  bl_timer_id t;
  irqstate_t s = irqsave();

  for(t = arraySize(timers)-1; (int8_t)t >= 0; t--) {

      if ((timers[t].ctl & inuse) == 0 ) {

          timers[t].reload = msfromnow;
          timers[t].count = msfromnow;
          timers[t].usr = fc ? *fc : null_cb;
          timers[t].ctl = (mode & (modeMsk|running)) | (inuse);
          break;
      }
  }

  irqrestore(s);
  return t;
}


void timer_free(bl_timer_id id)
{
  DEBUGASSERT(id>=0 && id < arraySize(timers));
  irqstate_t s = irqsave();
  memset(&timers[id], 0, sizeof(timers[id]));
  irqrestore(s);
}

void timer_start(bl_timer_id id)
{
  DEBUGASSERT(id>=0 && id < arraySize(timers) && (timers[id].ctl & inuse));
  irqstate_t s = irqsave();
  timers[id].count = timers[id].reload;
  timers[id].ctl |= running;
  irqrestore(s);

}
void timer_stop(bl_timer_id id)
{
  DEBUGASSERT(id>=0 && id < arraySize(timers) && (timers[id].ctl & inuse));
  irqstate_t s = irqsave();
  timers[id].ctl &= ~running;
  irqrestore(s);

}

int timer_expired(bl_timer_id id)
{
  DEBUGASSERT(id>=0 && id < arraySize(timers) && (timers[id].ctl & inuse));
  irqstate_t s = irqsave();
  int rv = ((timers[id].ctl & running) && timers[id].count == 0);
  irqrestore(s);
  return rv;
}

time_ref_t timer_ref(bl_timer_id id)
{
  DEBUGASSERT(id>=0 && id < arraySize(timers) && (timers[id].ctl & inuse));
  return (time_ref_t) &timers[id].count;
}

void timer_restart(bl_timer_id id, time_ms_t ms)
{
  DEBUGASSERT(id>=0 && id < arraySize(timers) && (timers[id].ctl & inuse));
  irqstate_t s = irqsave();
  timers[id].count = timers[id].reload = ms;
  timers[id].ctl |= running;
  irqrestore(s);
}

__attribute__ ((visibility ("default")))
void timer_init(void)
{
/*  PROBE_INIT(7);
  PROBE(1,true);
  PROBE(2,true);
  PROBE(3,true);
  PROBE(1,false);
  PROBE(2,false);
  PROBE(3,false);
//  *((uint32_t *)0x40011010) = 0x100; // PROBE(3,true);
//  *((uint32_t *)0x40011014) = 0x100; // PROBE(3,false);
*/
  memset(timers,0,sizeof(timers));
}