# Low level development guidelines
## Development environment
### Needed softwares
To being the low level development on STM32 boards you will need at least the follow softwares:
- STM32 Cube IDE
- STM32 Cube MX
There is currently no configurations to use VS Code or other IDE.
### Basic project setup
To setup a basic project you need to clone the following template project:
http://a-link-to-github
After that you will need to import the project inside STM32 Cube IDE by doing the following:
`File > Open Projects from File System`
And then browse to the cloned directory.
TODO: Explain how to choose the STM32 board
---
## Good practices
### Dynamic memory allocation
Please avoid dynamic memory allocation (so every memory allocation that can change of size or be freed after program initialization).
The reason is that dynamic memory allocation create fragmentation and embeded device has generally a very small amount of sram. Morever, you can have an out of memory error during runtime if you do dynamic allocation, but if you didn't, you can only have out of memory error during linkage or at the very begining of the program execution.
### Global constants
Do not forget to set a global variable constant if you do not plan to edit their value at runtime.
This allow the linker to put the variable in the FLASH without copying it in the SRAM at startup.
### Creating a driver
When you write a driver, keep in mind that one driver can be used for multiple hardware devices.
So do not use global variables to store one information about only one devices.
Additionally, when you create a driver, it's best to do generic code (so you mustn't hardcode values that are willing to change or that need to be customizable by the one we will use the driver).
### Passing structure as argument
Please do not passe huge structure as argument or as return type without using pointers. or as return type
This is bad:
```c
struct huge_s
{
char buff[32];
}
int sum(struct huge_s data) {
// Bad
}
```
But this is good:
```c
struct huge_s
{
char buff[32];
};
struct complex_s
{
uint32_t r;
uint32_t i;
} complex_t;
int sum(struct huge_s* data) {
// Fine
}
complex_t conjugate(complex_t val) {
val.i = -val.i;
return val;
}
```
---
## C Coding Style
### File names
All header and source files name must be in snake_case.
### Functions
Function name should be in snake_case.
Do not explicitly specify 'void' if the function does not take arguments.
Example:
```c
void i2c_read();
void i2c_write_char(i2c_t bus, char c);
```
### Function macros
Function macros and their arguments should be in PascalCase.
Example:
```c
#define LogDebug(Format, ...) vlog("Debug: " Format, __VA_ARGS__)
```
### Global constants & value macros
Gobal constants and value macros should be in UPPER_CASE.
Example:
```c
#define FREQUENCY 16000000
static const int VALUE = 42;
```
### Custom type (typedef)
Typedefs must be in snake_case and end with an '_t'.
Example:
```c
typedef struct truck_s truck_t;
```
### Structures
Structure name must be in snake_case and end with an '_s'.
Example:
```c
struct truck_s
{
int blablabla;
};
```
### Enumeration
Enumeration type must be in snake_case and end with an '_e'.
The enum's values must be in UPPER_CASE.
Example:
```c
enum truck_e
{
ENUM_VALUE,
AND_ANOTHER
};
```
### Argument/Local/Global/Member variables
Just in snake_case but please do not end with '_t' or '_s'.
Examples:
```c
int global_variable = 0;
void function(int argument)
{
char *str = "A local variable";
}
```
### Brackets
The opening bracket must be on the same column that the closing one.
```c
static const char LOOKUP_TABLE[] =
{
['n'] = '\n',
['t'] = '\t',
['r'] = '\r',
['0'] = '\0'
};
void main()
{
// TODO
}
```
### Indentation
Please indent the code with 4 space and no tabs. It's allow every reader to display rougly the same identation width because the number of space that make a tab is implementation dependants.
### Trailing spaces
Avoid useless trailling spaces at end of lines.
### Pointer position
It's better to put the asterix sticked to the variable name and not to the type, because:
```c
int* test1, test2;
// Here only 'test1' is a pointer
// So it's less confusing like this:
int *test1, test2;
```
### Blank lines, comments, and other things
There is currently no naming conventions for everything that is not explicitly specified.