GCC Code Coverage Report


Directory: /home/runner/work/Flight-Computer-Firmware/Flight-Computer-Firmware/app/rev2/
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 100.0% 151 / 0 / 151
Functions: 100.0% 7 / 0 / 7
Branches: 77.3% 34 / 0 / 44

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 1 FLASH_STATUS store_frame
69 (
70 HFLASH_BUFFER* pflash_handle,
71 uint32_t time,
72 uint32_t* address
73 )
74 1 {
75 /*------------------------------------------------------------------------------
76 Local variables
77 ------------------------------------------------------------------------------*/
78 1 FLASH_STATUS flash_status; /* Flash API status code */
79
80 /*------------------------------------------------------------------------------
81 Initialize sensor data
82 ------------------------------------------------------------------------------*/
83
1/2
✓ Branch 0 taken 1 time.
✗ Branch 1 not taken.
1 if ( !sensor_frame_size )
84 {
85 1 sensor_frame_size_init();
86 1 *address = sensor_frame_size * num_preset_frames;
87 }
88
89 1 uint8_t buffer[sensor_frame_size]; /* Sensor data in byte form */
90 1 flash_status = get_sensor_frame( buffer, time );
91
92 /* Skip logging if error detected */
93
1/2
✓ Branch 0 taken 1 time.
✗ Branch 1 not taken.
1 if( flash_status != FLASH_OK )
94 {
95 return flash_status;
96 }
97
98 /*------------------------------------------------------------------------------
99 Store Data
100 ------------------------------------------------------------------------------*/
101 /* Set buffer pointer */
102 1 pflash_handle->pbuffer = &buffer[0];
103 1 pflash_handle->num_bytes = sensor_frame_size;
104 1 pflash_handle->address = *address;
105
106 /* Write to flash */
107 1 flash_status = flash_write( pflash_handle );
108
109 /* Update the address pointer */
110 1 *address = pflash_handle->address + pflash_handle->num_bytes;
111
112 /* Return status code */
113 1 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 4 FLASH_STATUS read_preset
128 (
129 HFLASH_BUFFER* pflash_handle,
130 uint32_t* address
131 )
132 {
133 4 uint8_t buffer[ sizeof( PRESET_DATA ) + 2 ]; /* Sensor data in byte form */
134 4 memset(buffer, 0, sizeof( PRESET_DATA ) + 2 );
135 4 pflash_handle->pbuffer = &buffer[0];
136 4 pflash_handle->address = 0;
137 4 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
2/2
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 5352 times.
5356 while( flash_is_flash_busy() == FLASH_BUSY )
141 {
142 4 led_set_color(LED_YELLOW);
143 }
144
145 5352 FLASH_STATUS flash_status = flash_read( pflash_handle, sizeof( PRESET_DATA ) + 2 );
146
2/2
✓ Branch 0 taken 5351 times.
✓ Branch 1 taken 1 time.
5352 if (flash_status != FLASH_OK)
147 {
148 return FLASH_FAIL;
149 }
150
2/2
✓ Branch 0 taken 5349 times.
✓ Branch 1 taken 2 times.
5351 if (pflash_handle->pbuffer[0] == 1){
151 break;
152 }
153 5349 pflash_handle->address += sizeof( PRESET_DATA ) + 2;
154
2/2
✓ Branch 0 taken 5348 times.
✓ Branch 1 taken 1 time.
5349 if (pflash_handle->address + (sizeof( PRESET_DATA ) + 2) > FLASH_MAX_ADDR) {
155 // save_bit not found, proceed with default settings
156 1 *address = 0;
157 1 set_default_configs();
158 1 write_preset( pflash_handle, address );
159 1 return FLASH_PRESET_NOT_FOUND;
160 }
161 }
162
163 2 memcpy(&preset_data, &(buffer)[2], sizeof(PRESET_DATA));
164
165 2 config_settings = preset_data.config_settings;
166 2 imu_offset = preset_data.imu_offset;
167 2 baro_preset = preset_data.baro_preset;
168
169 2 *address = 0;
170
171 2 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
2/2
✓ Branch 2 taken 1 time.
✓ Branch 3 taken 3 times.
4 while( flash_is_flash_busy() == FLASH_BUSY )
215 {
216 1 led_set_color(LED_YELLOW);
217 }
218
219 3 uint8_t save_bit = 1;
220
221 /* Put data into buffer for flash write */
222 3 memcpy( &buffer[0], &save_bit, sizeof( uint8_t ) );
223 3 memcpy( &buffer[2], &preset_data, sizeof( PRESET_DATA ) );
224
225 /* Write to flash */
226 3 pflash_handle->address = 0;
227 3 pflash_handle->pbuffer = &buffer[0];
228 3 pflash_handle->num_bytes = sizeof( PRESET_DATA ) + 2;
229 3 flash_status = flash_write( pflash_handle );
230
231 /* Update the address */
232 3 *address = ( sensor_frame_size * num_preset_frames );
233
234 /* Return status code */
235 3 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 1 FLASH_STATUS flash_erase_preserve_preset
250 (
251 HFLASH_BUFFER* pflash_handle,
252 uint32_t* address
253 )
254 {
255
256
1/2
✓ Branch 0 taken 1 time.
✗ Branch 1 not taken.
1 if (!sensor_frame_size)
257 {
258 1 sensor_frame_size_init();
259 }
260
261 /* Read the presets */
262 1 *address = 0;
263 1 FLASH_STATUS status = read_preset( pflash_handle, address );
264
1/2
✓ Branch 0 taken 1 time.
✗ Branch 1 not taken.
1 if ( status != FLASH_OK )
265 {
266 return status;
267 }
268
269 /* Erase flash */
270 1 status = flash_erase( pflash_handle );
271
1/2
✓ Branch 0 taken 1 time.
✗ Branch 1 not taken.
1 if ( status != FLASH_OK )
272 {
273 return status;
274 }
275
276 /* Write the presets back */
277 1 *address = 0;
278 1 status = write_preset( pflash_handle, address );
279 1 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 3 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 3 uint8_t idx = 0; /* current index in the buffer */
301
302 /* Clear the allocated memory */
303 3 memset(buffer, 0, sensor_frame_size);
304 3 buffer[0] = 1; /* save bit */
305 3 buffer[1] = get_fc_state();
306
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 memcpy( &buffer[2], &time, sizeof( uint32_t ) );
307 3 idx = 6;
308
309
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if ( preset_data.config_settings.enabled_data & STORE_CONV )
310 {
311 3 memcpy( &buffer[idx],
312 &sensor_data.imu_converted,
313 sizeof( IMU_CONVERTED ));
314 3 idx += sizeof( IMU_CONVERTED );
315 3 memcpy( &buffer[idx], &sensor_data.baro_pressure, sizeof(float));
316 3 idx += 4;
317 3 memcpy( &buffer[idx], &sensor_data.baro_temp, sizeof(float));
318 3 idx += 4;
319 }
320
321
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if ( preset_data.config_settings.enabled_data & STORE_STATE_ESTIM )
322 {
323 3 memcpy( &buffer[idx],
324 &sensor_data.state_estimate,
325 sizeof( STATE_ESTIMATION ));
326 3 idx += sizeof( STATE_ESTIMATION );
327 3 memcpy( &buffer[idx], &sensor_data.baro_alt, sizeof(float));
328 3 idx += 4;
329 }
330
331
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if ( preset_data.config_settings.enabled_data & STORE_GPS )
332 {
333 3 memcpy( &buffer[idx], &sensor_data.gps_altitude_ft, sizeof(float));
334 3 idx += 4;
335 3 memcpy( &buffer[idx], &sensor_data.gps_speed_kmh, sizeof(float));
336 3 idx += 4;
337 3 memcpy( &buffer[idx], &sensor_data.gps_utc_time, sizeof(float));
338 3 idx += 4;
339 3 memcpy( &buffer[idx], &sensor_data.gps_dec_longitude, sizeof(float));
340 3 idx += 4;
341 3 memcpy( &buffer[idx], &sensor_data.gps_dec_latitude, sizeof(float));
342 3 idx += 4;
343 3 memcpy( &buffer[idx], &sensor_data.gps_ns, sizeof(char));
344 3 idx++;
345 3 memcpy( &buffer[idx], &sensor_data.gps_ew, sizeof(char));
346 3 idx++;
347 3 memcpy( &buffer[idx], &sensor_data.gps_gll_status, sizeof(char));
348 3 idx++;
349 3 memcpy( &buffer[idx], &sensor_data.gps_rmc_status, sizeof(char));
350 3 idx++;
351 }
352
353
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if ( preset_data.config_settings.enabled_data & STORE_CANARD_DATA )
354 {
355 3 memcpy( &buffer[idx], &feedback, sizeof(float));
356 3 idx += 4;
357 }
358
359 /* Validity check: Verify the allocated size matches the final index*/
360
2/2
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 2 times.
3 if (sensor_frame_size == idx)
361 {
362 return FLASH_OK;
363 }
364 else
365 {
366 1 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 5 void sensor_frame_size_init
382 (
383 void
384 )
385 {
386 /* Local Variables */
387 5 uint8_t size = 0; /* value to return; size of buffer */
388
389 /* Allocate the required memory */
390 5 size += 6; /* space for save bit, FC state, and time. */
391
392
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 1 time.
5 if ( preset_data.config_settings.enabled_data & STORE_CONV )
393 {
394 4 size += sizeof( IMU_CONVERTED );
395 4 size += 2 * sizeof( float ); /* baro raw data */
396 }
397
398
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 1 time.
5 if ( preset_data.config_settings.enabled_data & STORE_STATE_ESTIM )
399 {
400 4 size += sizeof( STATE_ESTIMATION );
401 4 size += sizeof( float ); /* baro alt */
402 }
403
404
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 1 time.
5 if ( preset_data.config_settings.enabled_data & STORE_GPS )
405 {
406 4 size += 5 * sizeof( float );
407 4 size += 4 * sizeof( char );
408 }
409
410
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 1 time.
5 if ( preset_data.config_settings.enabled_data & STORE_CANARD_DATA )
411 {
412 4 size += 1 * sizeof( float ); /* feedback */
413 }
414
415 5 sensor_frame_size = size;
416 5 num_preset_frames = 1;
417
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 5 times.
21 while ( size < sizeof( PRESET_DATA ) + 2 )
418 {
419 16 size += sensor_frame_size;
420 16 num_preset_frames++;
421 }
422
423 5 }
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 1 static void set_default_configs
436 (
437 void
438 )
439 {
440 1 led_set_color( LED_CYAN );
441 1 buzzer_multi_beeps( 500, 500, 3 );
442 1 preset_data.config_settings.enabled_features = 0x00000041; /* dual deploy, accel LD */
443 1 preset_data.config_settings.enabled_data = 0xFFFFFFFF; /* all data enabled */
444 1 preset_data.config_settings.sensor_calibration_samples = 1000; /* unitless */
445 1 preset_data.config_settings.launch_detect_timeout = 30000; /* unit: ms */
446 1 preset_data.config_settings.launch_detect_accel_threshold = 2; /* unit: g */
447 1 preset_data.config_settings.launch_detect_accel_samples = 5; /* unitless */
448 1 preset_data.config_settings.launch_detect_baro_threshold = 300; /* unit: Pa */
449 1 preset_data.config_settings.launch_detect_baro_samples = 5; /* unitless */
450 1 preset_data.config_settings.control_delay_after_launch = 4000; /* unit: ms */
451 1 preset_data.config_settings.roll_control_constant_p = 0.0f; /* active control disabled */
452 1 preset_data.config_settings.roll_control_constant_i = 0.0f; /* active control disabled */
453 1 preset_data.config_settings.roll_control_constant_d = 0.0f; /* active control disabled */
454 1 preset_data.config_settings.pitch_yaw_control_constant_p = 0.0f; /* active control disabled */
455 1 preset_data.config_settings.pitch_yaw_control_constant_i = 0.0f; /* active control disabled */
456 1 preset_data.config_settings.pitch_yaw_control_constant_d = 0.0f; /* active control disabled */
457 1 preset_data.config_settings.control_max_deflection_angle = 0; /* active control disabled */
458 1 preset_data.config_settings.flash_rate_limit = 0; /* unit: Hz */
459 1 }
460