- Custom Development
This is an old revision of the document!
First of all, make sure to properly clone the project with its submodules. Unless you are a Dephy employee, use the 'public' branch. The same code base is used by many projects, many different circuits, and many different versions of these circuits. Only one source file needs to be changed to select the active project (and its configuration, if necessary). The rest of the options will be selected with pre-processor directives.
Navigate to /flexsea-projects/inc/user-mn.h and look for this section:
//Step 1) Select active project (from list): //========================================== #define ACTIVE_PROJECT PROJECT_BAREBONE #define ACTIVE_SUBPROJECT SUBPROJECT_A
Pick a project from the list above. Sub-projects are mainly used for bilateral or multi-DoF applications. For unilateral, 1-DoF applications the value doesn't matter; by default we select A.
Scroll down to the Active Project:
//Barebone FlexSEA-Manage project - no external peripherals. #if(ACTIVE_PROJECT == PROJECT_BAREBONE) //Enable/Disable sub-modules: #define USE_RS485 #define USE_USB #define USE_COMM //Requires USE_RS485 and/or USE_USB #define USE_I2C_1 //3V3, IMU & Digital pot //#define USE_I2C_2 //3V3, Expansion #define USE_I2C_3 //Onboard, Regulate & Execute #define USE_IMU //Requires USE_I2C_1 //#define USE_FLASH_MEM //FLASH memory //#define USE_COMM_TEST //Comm. characterization tool #define USE_UART3 //Bluetooth #define USE_SPI_PLAN //Expansion/Plan //#define USE_BATTBOARD //Battery Board, requires USE_I2C_2 #define USE_EEPROM //Emulated EEPROM, onboard FLASH //Runtime finite state machine (FSM): #define RUNTIME_FSM1 DISABLED #define RUNTIME_FSM2 DISABLED #define MULTI_DOF_N 0 //Project specific definitions: //... #endif //PROJECT_BAREBONE
The many USE_x #define statements are used to enable or disable peripherals and functionality. The example above has only the essential features enabled, won't work with Bluetooth or with an SPI Master, and doesn't have user state machines enabled. If you are using a project prepared by Dephy you normally won't have to change this, unless you are debugging something specific. If you are using your own project, it is expected that you will start with most features disabled and that you will enable them as you test. These values are defined here, they do not come from a list. If you are writing code for an EMG sensor, you can type #define USE_EMG (or any other name you want) and then use it in your code.
If all you are doing is selecting the project as PROJECT_ACTPACK you probably don't need to review the settings.
Because the flexsea-projects submodule is shared with all projects, and used by many people, the active project will often have to be changed after you clone or pull. Moving to your own submodule is the only way to avoid this (very minor) inconvenience.
Q: What's “preprocessor”?
A: C preprocessor - Wikipedia. In this case, we use it for conditional compilation.
Q: Why do we need this in addition to user-mn.h?
A: Including the same .h file in many .c and .h files can lead to circular inclusion. It's also very easy to forget to include it. When you do that, the symbol is not defined. It compiles just fine, but it doesn't do what you want. Using the preprocessor makes this way cleaner and reduces human errors.
In Eclipse, either go to Project > Properties, or right click on your project in the Project Explorer window and click on Properties.
Navigate to C/C++ Build > Settings. Under ARM C compiler click on Preprocessor. You can change symbols for the Release or Debug version, or use All Configurations to change all (recommended by default).
Some of those symbols were defined when the project was generated and will never have to be changed by a typical user: NULL, HSE_VALUE, USE_HAL_DRIVER, STM32F427x, ARM_MATH_CM4. BOARD_TYPE_FLEXSEA_MANAGE is used to tell the FlexSEA stack that this board is in the Manage family.
When symbols are defined without a value (ex: BOARD_TYPE_FLEXSEA_MANAGE) they are used with the “defined” statement (#ifdef, #ifndef, #if(defined A || defined B), etc.) It will evaluate as true if the symbol is defined. Rather than deleting the statements to disable them, we usually change them by adding “NOT” or “DO_NOT” (ex.: DO_NOT_INCLUDE_UPROJ_MIT_DLEG). This creates a new symbol, unused in the code. Any expression using the correct spelling will evaluate as false. This strategy makes it easier to change projects; one only needs to add/remove DO_NOT rather than remembering the exact name.
Symbols defined with a value will be used with the #if statement. The code below assigns a different pin based on the version.
//Blinking LED: #if (HW_VER == 1) __GPIOC_CLK_ENABLE(); GPIO_InitStruct.Pin = GPIO_PIN_14; #else __GPIOA_CLK_ENABLE(); GPIO_InitStruct.Pin = GPIO_PIN_1; #endif
Lesser and greater operators can also be used. Ex.: #if (HW_VER < 10) can be used for all v0.x boards.
Now, let's look at some flags/symbols that are used by typical users: