Modules¶
Modules are the building blocks of the firmware image, and where you will be spending the most time. There are a number of Lantronix-provided modules that you can include in your project. This means that your code only needs to take care of what you need to customize, and you don't need to re-create network configuration and management utilities.
The Lantronix modules are provided as binaries in the lantronix/modules
directory, while the source examples and your custom modules are in the custom/module
directory.
Naming¶
Directory and file names should not contain spaces or special characters. Do not create or rename a module that conflicts with the name of any Lantronix module. Lantronix modules can be found in lantronix/modules
.
Important
Custom module names must not conflict with Lantronix module names.
Don't use these names for custom modules, as they conflict with Lantronix-provided module names:
aes azure_iot ble_beacon_scanner bluetooth
bridge cli consoleflow discovery
gatt_server lpd main modbus
modem_emulation monitor mqtt mux
ntp security smtp spp
tunnel usb_device usb_host user_data
virtual_line websockets xnetwork xserial
Structure¶
Modules have the following directory tree and files:
xPortEdge/custom/module/
> /module_name/
module_code.c
more_module_code.c
> /bom/
cfiles.make
> /includes/
custom_includes.h
> /libraries/
custom_libraries.a
> /http/help/
module.module_name.html
The includes
, libraries
, and http/help
directories are optional.
Creating Modules¶
You have two options when creating modules. You can either copy one of the sample modules and modify it, or you can create a new module from scratch.
Option 1: Copy an existing module
-
In
custom/module
, copy a module directory. Take care not to use a name that conflicts with a Lantronix-provided module. See Naming. -
Modify the code in the C file(s) or add more C files as needed.
-
If you change the name of existing C files or add new C files, update the
CFILES
variable inmodule_name/bom/cfiles.make
to define the C file name(s). -
Optionally, create an
includes
directory. See Includes. -
Optionally, create a
libraries
directory andextend.make
. See Libraries.
You should have a File Structure similar to the one outlined above.
Lantronix modules are not designed to work with other Lantronix modules without modification. To use multiple modules correctly, you may need to modify the code.
Option 2: Create a module from scratch
-
In
custom/module
, create a directory for the new module. Take care not to use a name that conflicts with a Lantronix-provided module. See Naming. -
Create your C file(s) in the new
module_name
directory. -
In
module_name
, create abom
directory. -
In
bom
, createcfiles.make
and define theCFILES
variable as the location and name of the C file(s) inmodule_name
. -
Optionally, create an
includes
directory. See Includes. -
Optionally, create a
libraries
directory. See Libraries.
You should have a File Structure similar to the one outlined above.
Registration, Startup, and Shutdown¶
Each module must provide a registration, startup, and shutdown functions that will be called automatically.
The registration function is module_name_module_registration
and should contain all of the module's registration calls.
The startup function is module_name_module_startup
. All of the module registration functions are called before any of the startup functions, so at startup all of the registrations from other modules will be visible.
The shutdown function is module_name_module_shutdown
. The shutdown function of each module is called just prior to the device powering down.
Includes¶
There are several Lantronix-provided includes available, and you can create your own. Lantronix includes are located in lantronix/includes
. Refer to File List in the Developer Reference for information about includes that are available as part of the SDK.
When creating your own includes, you can either store them within the module that uses them, in custom/module/module_name/includes
, or place them in custom/includes
to allow multiple modules to make use of the same files.
Required includes¶
Two includes are required for all modules:
-
module_name_module_defs.h
is automatically generated when you run the make command. The name of the include is the module name with"_module_defs.h"
appended. -
ltrx_compile_defines.h
is delivered with SDK and is required for all modules.
extend.make¶
When your module makes use of includes, that module's directory should also include an extend.make
file to define where the includes are located. Definemodule_name_INCLUDE_PATHS
in the module's extend.make
file to specify the paths to the includes used by the module.
Note
Files used in the variable should maintain alphabetical order.
Example:
sample_module_INCLUDE_PATHS := \
$(LANTRONIX_DIRECTORY)/includes/system/sample_feature \
Libraries¶
There are several Lantronix-provided libraries available, and you can create your own. Lantronix libraries are located in lantronix/libraries
. Refer to File List in the Developer Reference for information about libraries that are available as part of the SDK.
When creating your own libraries, you can either store them within the module that uses them, in custom/module/module_name/libraries
, or place them in custom/libraries
to allow multiple modules to make use of the same files.
extend.make¶
When your modules make use of libraries, that module's directory should also include an extend.make
file to define where libraries are located. Define module_name_LIBRARIES
in the module's extend.make
file to specify the paths to the libraries used by the module.
Note
Files used in the variable should maintain alphabetical order.
Example:
sample_module_LIBRARIES := $(MY_DIR)/libraries/sample_feature.a \
$(MY_DIR)/libraries/sample_feature.ThreadX.NetX.ARM_CR4.release.a
Inter-module Communications¶
The SDK has functionality to allow different modules to communicate via exported functions. To achieve that, one module has to export functions, while another has to import the functions from the exporter.
Note
Modules can both export functions, as well as import functions from another module.
Exporting functions¶
For a module to export functions, it must define them in the file module_defs.m4d (at the root of the module directory, e.g: <SDK root>/custom/module/<module name>/module_defs.m4d).
The format to export a function is as follows:
define_external_function(
`output_data',
`bool',
`char *data')
Note
- The opening and closing quotes are different.
- There must be a newline after the closing parenthesis.
- The name of the function is the first parameter.
- The return value of the function is the second parameter.
- Any parameters passed to the function come third and later.
At compile time, the SDK takes the definitions from module_defs.m4d and creates the function prototypes in a file named <module name>_module_defs.h. For the case above, the exporting module will need to have the following code:
#include "<module name>_module_defs.h"
bool output_data(char *data)
{
TLOG(TLOG_SEVERITY_LEVEL__INFORMATIONAL, "Sent: %s", data);
return true;
}
Importing functions¶
For the module that will be importing functions to call, it must first include the file generated by the SDK named <module name>_module_libs.h. Then, it must populate a pointer named g_<module name>ExternalFunctionEntry_pointer using the ltrx_module_functions_lookup() API. It can then call the functions directly.
If in the example above, the exporting module is named output_tlog, then the importing module will need the following:
#include "output_tlog_module_libs.h"
const struct output_tlog_external_functions *g_output_tlogExternalFunctionEntry_pointer;
g_output_tlogExternalFunctionEntry_pointer = ltrx_module_functions_lookup("output_tlog");
if (g_output_tlogExternalFunctionEntry_pointer == 0)
{
TLOG(TLOG_SEVERITY_LEVEL__INFORMATIONAL, "Error loading module");
}
Data can be sent by using the following:
output_data(buf);