-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathstatus.c
335 lines (277 loc) · 12 KB
/
status.c
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
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
////////////////////////////////////////////////////////////////////////////////
/// @file
/// @brief Monitor Host status and annunciate FMU status.
////////////////////////////////////////////////////////////////////////////////
// *****************************************************************************
// ************************** System Include Files *****************************
// *****************************************************************************
// *****************************************************************************
// ************************** User Include Files *******************************
// *****************************************************************************
#include "status.h"
#include "fmucomm.h"
#include "coretime.h"
#include "adc.h"
#include "emc1412.h"
#include "can.h"
// *****************************************************************************
// ************************** Defines ******************************************
// *****************************************************************************
// The node type of the FMU. 0 = FMU, 1 = Servo-Node.
#define STATUS_FMU_NODE_TYPE 0
// *****************************************************************************
// ************************** Definitions **************************************
// *****************************************************************************
/// Structure defining space for storage of a serial number.
///
/// @note The tool used for programming the serial number has a minimum flash
/// size (0x200) for preserving flash memory (i.e. a flash row size).
/// The serial number is spare padded to this minimum required size to
/// interface with the tool.
///
typedef struct
{
uint32_t val;
uint8_t spare[ 508 ];
} STATUS_SERIAL_NUM_S;
/// The node type - value of '0' identifies node as a FMU node.
static const uint8_t status_node_type = 0;
static const uint8_t status_fw_rev_ver = 3; ///< Firmware revision version number.
static const uint8_t status_fw_min_ver = 2; ///< Firmware minor version number.
static const uint8_t status_fw_maj_ver = 1; ///< Firmware major version number.
static const uint8_t status_hw_rev_ver = 1; ///< Hardware revision version number.
static const uint8_t status_hw_min_ver = 0; ///< Hardware minor version number.
static const uint8_t status_hw_maj_ver = 1; ///< Hardware major version number.
/// The serial number - set during initial programming.
///
/// @note The serial number is set to the starting address of Program
/// memory.
///
static const STATUS_SERIAL_NUM_S __attribute__((space(prog), address(0x9D000000))) status_serial_num;
/// Data from Host Heartbeat Ethernet message.
static FMUCOMM_HOST_HEARTBEAT_PL status_host_hb_data;
// *****************************************************************************
// ************************** Function Prototypes ******************************
// *****************************************************************************
static void StatusLEDTask( void );
static void StatusFMUHbTask( void );
static void StatusFMUNodeTask( void );
static void StatusHostHbTask( void );
// *****************************************************************************
// ************************** Global Functions *********************************
// *****************************************************************************
void StatusTask( void )
{
StatusLEDTask();
StatusFMUHbTask();
StatusFMUNodeTask();
StatusHostHbTask();
}
// *****************************************************************************
// ************************** Static Functions *********************************
// *****************************************************************************
////////////////////////////////////////////////////////////////////////////////
/// @brief Status LED Task.
///
/// This periodic function blinks the heartbeat LED at a 0.5Hz rate.
////////////////////////////////////////////////////////////////////////////////
static void StatusLEDTask( void )
{
static uint32_t prevBlinkTime = 0;
// 1.0s elapsed since last blink ?
if( CoreTime32usGet() - prevBlinkTime > 1000000 )
{
// Toggle the LED state.
LATFINV = _LATF_LATF3_MASK;
// Latch the execution time for evaluation of next blink.
prevBlinkTime = CoreTime32usGet();
}
return;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief FMU Heartbeat Status Task.
///
/// The function sends the FMU Heartbeat Ethernet packet as a 1Hz rate.
////////////////////////////////////////////////////////////////////////////////
static void StatusFMUHbTask( void )
{
static enum
{
SM_TX,
SM_DELAY,
} statusPktState = SM_TX;
switch (statusPktState)
{
case SM_TX:
{
FMUCOMM_FMU_HEARTBEAT_PL fmu_heartbeat_pl;
bool setSuccess;
// Populate FMU Heartbeat Packet information.
fmu_heartbeat_pl.fwVersionRev = status_fw_rev_ver;
fmu_heartbeat_pl.fwVersionMin = status_fw_min_ver;
fmu_heartbeat_pl.fwVersionMaj = status_fw_maj_ver;
fmu_heartbeat_pl.hwVersionRev = status_hw_rev_ver;
fmu_heartbeat_pl.hwVersionMin = status_hw_min_ver;
fmu_heartbeat_pl.hwVersionMaj = status_hw_maj_ver;
fmu_heartbeat_pl.serialNum = status_serial_num.val;
fmu_heartbeat_pl.msUptime = CoreTime32msGet();
fmu_heartbeat_pl.inputVoltage = ADCVbattGet();
fmu_heartbeat_pl.boardTemp = EMC1412IntTempGet();
// Queue message for transmission.
setSuccess = FMUCommSet( FMUCOMM_TYPE_FMU_HEARTBEAT,
(uint8_t*) &fmu_heartbeat_pl,
sizeof( fmu_heartbeat_pl ) );
// Message successfully queued for transfer ?
//
// If queuing for transfer unsuccessful, the state machine is not
// updated and queuing will be attempted again.
//
if( setSuccess == true )
{
statusPktState++;
}
break;
}
case SM_DELAY:
{
static uint32_t prevExeTime = 0;
// Required time has elapsed ?
if( CoreTime32usGet() - prevExeTime > 1000000 )
{
// Increment by fixed transmission period time to eliminate
// drift.
prevExeTime += 1000000;
// Still identified that require time has elapsed ?
//
// Note: This could occur if processing inhibited this function's
// execution for an extended amount of time.
//
if( CoreTime32usGet() - prevExeTime > 1000000 )
{
// Update to the current time. Single or multiple timeouts
// have elapsed. Updating to the current time prevents
// repeated identifications of timeout having elapsed.
prevExeTime = CoreTime32usGet();
}
// Perform another task cycle.
statusPktState = SM_TX;
}
break;
}
}
return;
}
// Periodically send the Node Status and Node Version CAN messages.
////////////////////////////////////////////////////////////////////////////////
/// @brief FMU Node Status Task.
///
/// This function sends the FMU Node CAN messages (Node Status & Node Version)
/// at a 2Hz rate.
////////////////////////////////////////////////////////////////////////////////
static void StatusFMUNodeTask( void )
{
static uint32_t prevExeTime = 0;
static CAN_TX_NODE_STATUS_U node_status_msg = { { 0 } };
CAN_TX_NODE_VER_U node_ver_msg;
// Required time has elapsed ?
if( CoreTime32usGet() - prevExeTime > 500000 )
{
// Increment by fixed transmission period time to eliminate
// drift.
prevExeTime += 500000;
// Still identified that require time has elapsed ?
//
// Note: This could occur if processing inhibited this function's
// execution for an extended amount of time.
//
if( CoreTime32usGet() - prevExeTime > 500000 )
{
// Update to the current time. Single or multiple timeouts
// have elapsed. Updating to the current time prevents
// repeated identifications of timeout having elapsed.
prevExeTime = CoreTime32usGet();
}
// NODE STATUS MESSAGE -------------------------------------------------
// Reset detail not yet set ?
//
// Note: the status message is built once following reset since it is
// a static message and reset register bits need to be cleared to
// identify the next reset condition. reset_detail is checked to be
// zero to detect the first execution after reset as the hardware
// register stored to this variable is always non-zero.
//
if( node_status_msg.reset_detail == 0 )
{
// Build the message.
//
// Note: RCON register truncated to 16-bits since upper 16-bits is all
// spares.
node_status_msg.reset_detail = (uint16_t) RCON;
if( RCONbits.POR )
{
node_status_msg.reset_condition = 1;
}
else
if( RCONbits.BOR )
{
node_status_msg.reset_condition = 2;
}
else
if( RCONbits.SWR )
{
node_status_msg.reset_condition = 3;
}
else
{
node_status_msg.reset_condition = 4;
}
// Reset the RCON register BOR and POR bits so that the reset condition
// can be detected on the next reset.
RCONCLR = _RCON_BOR_MASK;
RCONCLR = _RCON_POR_MASK;
}
// Queue message for transmission.
//
// Note: destination ID set as zero b/c it is not applicable for the
// node status message which is a broadcast message.
//
CANTxSet( CAN_TX_MSG_NODE_STATUS,
0,
&node_status_msg.data_u32[ 0 ] );
// NODE VERSION MESSAGE ------------------------------------------------
// Build the message.
node_ver_msg.node_type = STATUS_FMU_NODE_TYPE;
node_ver_msg.rev_ver = status_fw_rev_ver;
node_ver_msg.min_ver = status_fw_min_ver;
node_ver_msg.maj_ver = status_fw_maj_ver;
node_ver_msg.serial_num = status_serial_num.val;
// Queue message for transmission.
//
// Note: destination ID set as zero b/c it is not applicable for the
// node version message which is a broadcast message.
//
CANTxSet( CAN_TX_MSG_NODE_VER,
0,
&node_ver_msg.data_u32[ 0 ] );
}
}
// Read the Host heartbeat message into module data.
////////////////////////////////////////////////////////////////////////////////
/// @brief Host Heartbeat Status Task.
///
/// This function buffers a received Host Heartbeat Ethernet message into
/// module data.
////////////////////////////////////////////////////////////////////////////////
static void StatusHostHbTask( void )
{
const FMUCOMM_RX_PKT* host_hb_pkt;
FMUCOMM_HOST_HEARTBEAT_PL* host_hb_pl;
host_hb_pkt = FMUCommGet( FMUCOMM_TYPE_HOST_HEARTBEAT );
// valid Host Heartbeat message received ?
if( host_hb_pkt->valid == true )
{
host_hb_pl = (FMUCOMM_HOST_HEARTBEAT_PL*) host_hb_pkt->pl_p;
// Copy message payload into module data.
status_host_hb_data = *host_hb_pl;
}
}