-
Notifications
You must be signed in to change notification settings - Fork 3
ORCAASAT Dev Guide
This development guide outlines the software architecture and directories. It provides examples and templates to serve as a starting point during feature development. Since the core goal of the OBC firmware is reliability, all software must remain consistent with the information in this document.
Template for periodic task Template for asynchronous task
These templates would include appropriate watchdog calls to enable correct functionality.
Flight and test configurations are used when it is impractical during testing to set a certain parameter as it should be set in flight. An example of this is a task execution frequency. We may only want to log telemetry every 3 minutes in flight, but this low frequency makes testing a task during development impractical since the task would be executed so infrequently.
This is where #FLIGHT_CONFIG
and #TEST_CONFIG
come in. Whenever you are defining something that should have different flight and testing values, you should set it up using the following snippet:
#ifdef FLIGHT_CONFIG
uint32_t timeout_delay_s = 30000;
#endif
#ifdef TEST_CONFIG
uint32_t timeout_delay_s = 10;
#endif
It's verbose, but will ensure that we don't set up any parameters incorrectly when we flash the flight firmware.
You can set the flight vs. test config using the TODO: environment variable picker screenshot
Use the types that have the bit size in the type name. These can be included with #include 'sys_common.h'
.
It's important to use these because the bit size is important in embedded systems. It makes you think about what you're doing and how much memory you actually need. It also helps prevent errors because you will always know the size you're dealing with since it's not obfuscated.
#include `sys_common.h`
uint32_t foo;
int16_t bar;
int foo;
short bar;
Think of header files as the user-facing interface to your API. Therefore, try to only include or declare items in the header file that will be of use outside the context of the .c file.
Functions that will be called all over the place: put in header
Functions that are only used internally: don't put in header
Global variables must be declared in the header file using the keyword extern
. In the .c
file, define or initialize the variable. More info: https://www.cprogramming.com/declare_vs_define.html
To access the variable, simply include the header file with the extern
declaration, and refer to the variable by name like usual.
If you don't do this, you may get multiple definition errors or create multiple copies of the same variable.
extern uint32_t foo;
uint32_t foo = 234;
Globals should be initialized in an init()
function, or they may be initialized at the top of the .c
file.
The hardwaredefs file is used to map HALCoGEN-created peripheral names to our own names. This allows us to give a GPIO pin a descriptive name in our code, and then to easily change which port/pin it is connected to. This is useful for supporting different board revisions with #defines, instead of changing things deep in our code.
Please see sfu_hardwaredefs.h
for example usage.
Guidance
When dealing with peripherals, create a descriptive name in hardwaredefs.h
and assign it to the peripheral there. Use the descriptive name in your code, not the name that comes from HALCoGEN. Be sure to #include "sfu_hwdefs.h"
#include "sys_common.h"
- gives you access to the integral types.
Use a function with the suffix noMutex
Functions tagged noMutex
are for use inside other functions that are themselves wrapped in a mutex or when mutexes are not available. There are two cases where this may happen:
- a function executing before the scheduler is started (uncommon)
- a function within something else that itself takes the mutex (common in low-level code)