GCC Code Coverage Report


Directory: ../../
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 47.7% 72 / 0 / 151
Functions: 57.1% 4 / 0 / 7
Branches: 29.5% 13 / 0 / 44

app/rev2/flash_appa.c
Line Branch Exec Source
1 /*******************************************************************************
2 * *
3 * FILE: *
4 * flash_logger.c *
5 * *
6 * DESCRIPTION: *
7 * Contains all flash special functions for APPA *
8 * application. *
9 * *
10 * CRITICALITY: *
11 * FQ - Flight Qualified *
12 * *
13 * COPYRIGHT: *
14 * Copyright (c) 2025 Sun Devil Rocketry. *
15 * All rights reserved. *
16 * *
17 * This software is licensed under terms that can be found in the LICENSE *
18 * file in the root directory of this software component. *
19 * If no LICENSE file comes with this software, it is covered under the *
20 * BSD-3-Clause. *
21 * *
22 * https://opensource.org/license/bsd-3-clause *
23 * *
24 *******************************************************************************/
25
26 /*------------------------------------------------------------------------------
27 Standard Includes
28 ------------------------------------------------------------------------------*/
29 #include <stdlib.h>
30 #include "main.h"
31 #include "usb.h"
32 #include "string.h"
33 #include "led.h"
34 #include "imu.h"
35 #include "buzzer.h"
36
37 /*------------------------------------------------------------------------------
38 Instantiations
39 ------------------------------------------------------------------------------*/
40 uint8_t sensor_frame_size = 0;
41 uint8_t num_preset_frames = 1;
42
43 extern IMU_OFFSET imu_offset;
44 extern BARO_PRESET baro_preset;
45 extern SENSOR_DATA sensor_data;
46 extern PRESET_DATA preset_data;
47 extern CONFIG_SETTINGS_TYPE config_settings;
48 extern float feedback;
49
50 /*------------------------------------------------------------------------------
51 Local Procedures
52 ------------------------------------------------------------------------------*/
53 static void set_default_configs
54 (
55 void
56 );
57
58
59 /*******************************************************************************
60 * *
61 * PROCEDURE: *
62 * store_frame *
63 * *
64 * DESCRIPTION: *
65 * Store a frame of flight computer data in flash *
66 * *
67 *******************************************************************************/
68 ✗ FLASH_STATUS store_frame
69 (
70 HFLASH_BUFFER* pflash_handle,
71 uint32_t time,
72 uint32_t* address
73 )
74 ✗ {
75 /*------------------------------------------------------------------------------
76 Local variables
77 ------------------------------------------------------------------------------*/
78 ✗ FLASH_STATUS flash_status; /* Flash API status code */
79
80 /*------------------------------------------------------------------------------
81 Initialize sensor data
82 ------------------------------------------------------------------------------*/
83 ✗ if ( !sensor_frame_size )
84 {
85 ✗ sensor_frame_size_init();
86 ✗ *address = sensor_frame_size * num_preset_frames;
87 }
88
89 ✗ uint8_t buffer[sensor_frame_size]; /* Sensor data in byte form */
90 ✗ flash_status = get_sensor_frame( buffer, time );
91
92 /* Skip logging if error detected */
93 ✗ if( flash_status != FLASH_OK )
94 {
95 return flash_status;
96 }
97
98 /*------------------------------------------------------------------------------
99 Store Data
100 ------------------------------------------------------------------------------*/
101 /* Set buffer pointer */
102 ✗ pflash_handle->pbuffer = &buffer[0];
103 ✗ pflash_handle->num_bytes = sensor_frame_size;
104 ✗ pflash_handle->address = *address;
105
106 /* Write to flash */
107 ✗ flash_status = flash_write( pflash_handle );
108
109 /* Update the address pointer */
110 ✗ *address = pflash_handle->address + pflash_handle->num_bytes;
111
112 /* Return status code */
113 ✗ return flash_status;
114
115 } /* store_frame */
116
117
118 /*******************************************************************************
119 * *
120 * PROCEDURE: *
121 * read_preset *
122 * *
123 * DESCRIPTION: *
124 * Read configuration data from the flash memory *
125 * *
126 *******************************************************************************/
127 2 FLASH_STATUS read_preset
128 (
129 HFLASH_BUFFER* pflash_handle,
130 uint32_t* address
131 )
132 {
133 2 uint8_t buffer[ sizeof( PRESET_DATA ) + 2 ]; /* Sensor data in byte form */
134 2 memset(buffer, 0, sizeof( PRESET_DATA ) + 2 );
135 2 pflash_handle->pbuffer = &buffer[0];
136 2 pflash_handle->address = 0;
137 2 pflash_handle->num_bytes = sizeof( PRESET_DATA ) + 2;
138 // Look for save bit
139 while (1){ /* could change to a for loop i < PRESET_WRITE_REPEATS */
140
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 10698 times.
10698 while( flash_is_flash_busy() == FLASH_BUSY )
141 {
142 ✗ led_set_color(LED_YELLOW);
143 }
144
145 10698 FLASH_STATUS flash_status = flash_read( pflash_handle, sizeof( PRESET_DATA ) + 2 );
146
1/2
✓ Branch 0 taken 10698 times.
✗ Branch 1 not taken.
10698 if (flash_status != FLASH_OK)
147 {
148 return FLASH_FAIL;
149 }
150
1/2
✓ Branch 0 taken 10698 times.
✗ Branch 1 not taken.
10698 if (pflash_handle->pbuffer[0] == 1){
151 break;
152 }
153 10698 pflash_handle->address += sizeof( PRESET_DATA ) + 2;
154
2/2
✓ Branch 0 taken 10696 times.
✓ Branch 1 taken 2 times.
10698 if (pflash_handle->address + (sizeof( PRESET_DATA ) + 2) > FLASH_MAX_ADDR) {
155 // save_bit not found, proceed with default settings
156 2 *address = 0;
157 2 set_default_configs();
158 2 write_preset( pflash_handle, address );
159 2 return FLASH_PRESET_NOT_FOUND;
160 }
161 }
162
163 ✗ memcpy(&preset_data, &(buffer)[2], sizeof(PRESET_DATA));
164
165 ✗ config_settings = preset_data.config_settings;
166 ✗ imu_offset = preset_data.imu_offset;
167 ✗ baro_preset = preset_data.baro_preset;
168
169 ✗ *address = 0;
170
171 ✗ return FLASH_OK;
172
173 } /* read_preset */
174
175
176 /*******************************************************************************
177 * *
178 * PROCEDURE: *
179 * write_preset *
180 * *
181 * DESCRIPTION: *
182 * Store PID data and offsets in flash. 34 bytes. *
183 * *
184 *******************************************************************************/
185 3 FLASH_STATUS write_preset
186 (
187 HFLASH_BUFFER* pflash_handle,
188 uint32_t* address
189 )
190 {
191 /*------------------------------------------------------------------------------
192 Init
193 ------------------------------------------------------------------------------*/
194
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 time.
3 if (!sensor_frame_size)
195 {
196 2 sensor_frame_size_init();
197 }
198
199 /*------------------------------------------------------------------------------
200 Local variables
201 ------------------------------------------------------------------------------*/
202 3 uint8_t buffer[ sizeof( PRESET_DATA) + 2 ]; /* Sensor data in byte form */
203 3 FLASH_STATUS flash_status; /* Flash API status code */
204 3 memset( &buffer, 0, sizeof( PRESET_DATA) + 2 );
205
206 /*------------------------------------------------------------------------------
207 Store Data
208 ------------------------------------------------------------------------------*/
209 /*
210 Erase old preset data by erasing the first 4KB sector
211 */
212 3 flash_status = flash_block_erase( FLASH_BLOCK_0, FLASH_BLOCK_4K );
213
214
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
3 while( flash_is_flash_busy() == FLASH_BUSY )
215 {
216 ✗ led_set_color(LED_YELLOW);
217 }
218
219 2 uint8_t save_bit = 1;
220
221 /* Put data into buffer for flash write */
222 2 memcpy( &buffer[0], &save_bit, sizeof( uint8_t ) );
223 2 memcpy( &buffer[2], &preset_data, sizeof( PRESET_DATA ) );
224
225 /* Write to flash */
226 2 pflash_handle->address = 0;
227 2 pflash_handle->pbuffer = &buffer[0];
228 2 pflash_handle->num_bytes = sizeof( PRESET_DATA ) + 2;
229 2 flash_status = flash_write( pflash_handle );
230
231 /* Update the address */
232 2 *address = ( sensor_frame_size * num_preset_frames );
233
234 /* Return status code */
235 2 return flash_status;
236
237 } /* write_preset */
238
239
240 /*******************************************************************************
241 * *
242 * PROCEDURE: *
243 * flash_erase_preserve_preset *
244 * *
245 * DESCRIPTION: *
246 * Erases flash while saving the stored preset values. *
247 * *
248 *******************************************************************************/
249 ✗ FLASH_STATUS flash_erase_preserve_preset
250 (
251 HFLASH_BUFFER* pflash_handle,
252 uint32_t* address
253 )
254 {
255
256 ✗ if (!sensor_frame_size)
257 {
258 ✗ sensor_frame_size_init();
259 }
260
261 /* Read the presets */
262 ✗ *address = 0;
263 ✗ FLASH_STATUS status = read_preset( pflash_handle, address );
264 ✗ if ( status != FLASH_OK )
265 {
266 return status;
267 }
268
269 /* Erase flash */
270 ✗ status = flash_erase( pflash_handle );
271 ✗ if ( status != FLASH_OK )
272 {
273 return status;
274 }
275
276 /* Write the presets back */
277 ✗ *address = 0;
278 ✗ status = write_preset( pflash_handle, address );
279 ✗ return status;
280
281 } /* flash_erase_preserve_preset */
282
283
284 /*******************************************************************************
285 * *
286 * PROCEDURE: *
287 * get_sensor_frame *
288 * *
289 * DESCRIPTION: *
290 * Gets the contents of a sensor frame based on config data. *
291 * *
292 *******************************************************************************/
293 ✗ FLASH_STATUS get_sensor_frame
294 (
295 uint8_t* buffer, /* o: sensor frame buffer */
296 uint32_t time /* i: frame timestamp */
297 )
298 {
299 /* Local Variables */
300 ✗ uint8_t idx = 0; /* current index in the buffer */
301
302 /* Clear the allocated memory */
303 ✗ memset(buffer, 0, sensor_frame_size);
304 ✗ buffer[0] = 1; /* save bit */
305 ✗ buffer[1] = get_fc_state();
306 ✗ memcpy( &buffer[2], &time, sizeof( uint32_t ) );
307 ✗ idx = 6;
308
309 ✗ if ( preset_data.config_settings.enabled_data & STORE_CONV )
310 {
311 ✗ memcpy( &buffer[idx],
312 &sensor_data.imu_converted,
313 sizeof( IMU_CONVERTED ));
314 ✗ idx += sizeof( IMU_CONVERTED );
315 ✗ memcpy( &buffer[idx], &sensor_data.baro_pressure, sizeof(float));
316 ✗ idx += 4;
317 ✗ memcpy( &buffer[idx], &sensor_data.baro_temp, sizeof(float));
318 ✗ idx += 4;
319 }
320
321 ✗ if ( preset_data.config_settings.enabled_data & STORE_STATE_ESTIM )
322 {
323 ✗ memcpy( &buffer[idx],
324 &sensor_data.state_estimate,
325 sizeof( STATE_ESTIMATION ));
326 ✗ idx += sizeof( STATE_ESTIMATION );
327 ✗ memcpy( &buffer[idx], &sensor_data.baro_alt, sizeof(float));
328 ✗ idx += 4;
329 }
330
331 ✗ if ( preset_data.config_settings.enabled_data & STORE_GPS )
332 {
333 ✗ memcpy( &buffer[idx], &sensor_data.gps_altitude_ft, sizeof(float));
334 ✗ idx += 4;
335 ✗ memcpy( &buffer[idx], &sensor_data.gps_speed_kmh, sizeof(float));
336 ✗ idx += 4;
337 ✗ memcpy( &buffer[idx], &sensor_data.gps_utc_time, sizeof(float));
338 ✗ idx += 4;
339 ✗ memcpy( &buffer[idx], &sensor_data.gps_dec_longitude, sizeof(float));
340 ✗ idx += 4;
341 ✗ memcpy( &buffer[idx], &sensor_data.gps_dec_latitude, sizeof(float));
342 ✗ idx += 4;
343 ✗ memcpy( &buffer[idx], &sensor_data.gps_ns, sizeof(char));
344 ✗ idx++;
345 ✗ memcpy( &buffer[idx], &sensor_data.gps_ew, sizeof(char));
346 ✗ idx++;
347 ✗ memcpy( &buffer[idx], &sensor_data.gps_gll_status, sizeof(char));
348 ✗ idx++;
349 ✗ memcpy( &buffer[idx], &sensor_data.gps_rmc_status, sizeof(char));
350 ✗ idx++;
351 }
352
353 ✗ if ( preset_data.config_settings.enabled_data & STORE_CANARD_DATA )
354 {
355 ✗ memcpy( &buffer[idx], &feedback, sizeof(float));
356 ✗ idx += 4;
357 }
358
359 /* Validity check: Verify the allocated size matches the final index*/
360 ✗ if (sensor_frame_size == idx)
361 {
362 return FLASH_OK;
363 }
364 else
365 {
366 ✗ return FLASH_SENSOR_RETRIEVE_ERROR;
367 }
368
369 }
370
371
372 /*******************************************************************************
373 * *
374 * PROCEDURE: *
375 * sensor_frame_size_init *
376 * *
377 * DESCRIPTION: *
378 * Calculates the size of a sensor frame from configs. *
379 * *
380 *******************************************************************************/
381 2 void sensor_frame_size_init
382 (
383 void
384 )
385 {
386 /* Local Variables */
387 2 uint8_t size = 0; /* value to return; size of buffer */
388
389 /* Allocate the required memory */
390 2 size += 6; /* space for save bit, FC state, and time. */
391
392
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if ( preset_data.config_settings.enabled_data & STORE_CONV )
393 {
394 2 size += sizeof( IMU_CONVERTED );
395 2 size += 2 * sizeof( float ); /* baro raw data */
396 }
397
398
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if ( preset_data.config_settings.enabled_data & STORE_STATE_ESTIM )
399 {
400 2 size += sizeof( STATE_ESTIMATION );
401 2 size += sizeof( float ); /* baro alt */
402 }
403
404
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if ( preset_data.config_settings.enabled_data & STORE_GPS )
405 {
406 2 size += 5 * sizeof( float );
407 2 size += 4 * sizeof( char );
408 }
409
410
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if ( preset_data.config_settings.enabled_data & STORE_CANARD_DATA )
411 {
412 2 size += 1 * sizeof( float ); /* feedback */
413 }
414
415 2 sensor_frame_size = size;
416 2 num_preset_frames = 1;
417
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 while ( size < sizeof( PRESET_DATA ) + 2 )
418 {
419 ✗ size += sensor_frame_size;
420 ✗ num_preset_frames++;
421 }
422
423 2 }
424
425
426 /*******************************************************************************
427 * *
428 * PROCEDURE: *
429 * set_default_configs *
430 * *
431 * DESCRIPTION: *
432 * Sets the configuration struct to default values (save bit not found) *
433 * *
434 *******************************************************************************/
435 2 static void set_default_configs
436 (
437 void
438 )
439 {
440 2 led_set_color( LED_CYAN );
441 2 buzzer_multi_beeps( 500, 500, 3 );
442 2 preset_data.config_settings.enabled_features = 0x00000041; /* dual deploy, accel LD */
443 2 preset_data.config_settings.enabled_data = 0xFFFFFFFF; /* all data enabled */
444 2 preset_data.config_settings.sensor_calibration_samples = 1000; /* unitless */
445 2 preset_data.config_settings.launch_detect_timeout = 30000; /* unit: ms */
446 2 preset_data.config_settings.launch_detect_accel_threshold = 2; /* unit: g */
447 2 preset_data.config_settings.launch_detect_accel_samples = 5; /* unitless */
448 2 preset_data.config_settings.launch_detect_baro_threshold = 300; /* unit: Pa */
449 2 preset_data.config_settings.launch_detect_baro_samples = 5; /* unitless */
450 2 preset_data.config_settings.control_delay_after_launch = 4000; /* unit: ms */
451 2 preset_data.config_settings.roll_control_constant_p = 0.0f; /* active control disabled */
452 2 preset_data.config_settings.roll_control_constant_i = 0.0f; /* active control disabled */
453 2 preset_data.config_settings.roll_control_constant_d = 0.0f; /* active control disabled */
454 2 preset_data.config_settings.pitch_yaw_control_constant_p = 0.0f; /* active control disabled */
455 2 preset_data.config_settings.pitch_yaw_control_constant_i = 0.0f; /* active control disabled */
456 2 preset_data.config_settings.pitch_yaw_control_constant_d = 0.0f; /* active control disabled */
457 2 preset_data.config_settings.control_max_deflection_angle = 0; /* active control disabled */
458 2 preset_data.config_settings.flash_rate_limit = 0; /* unit: Hz */
459 2 }
460