Migration Guide: sl_system to sl_main for RTOS Applications#
Table of Contents#
Overview#
The Silicon Labs platform service sl_main
represents a significant evolution of the system initialization architecture previously provided by sl_system
. This migration was driven by several key factors:
Enhanced RTOS support with earlier kernel initialization for better resource management
Improved memory placement to optimize RAM usage and power consumption in em2
Improved modularity with clearer separation between initialization stages
More flexible initialization hooks allowing for greater application customization
This guide will help you migrate your RTOS-based applications from sl_system
to the new sl_main
architecture.
If your application is bare-metal, you do not need to update your application as sl_system
is compatible with sl_main
, no actions are needed.
Key Differences Between sl_main and sl_system#
Feature | sl_system | sl_main |
---|---|---|
API |
|
|
RTOS Initialization | RTOS initialized late in the process | RTOS initialized early, after hardware setup |
main() RTOS Integration | RTOS is started from the | RTOS is started before the |
start task configurability | No start task | Start task can be configured (stack size, priority and self deletion) |
Extensibility | Limited hooks for application code | Multiple weak functions for application integration at various stages |
Initialization Order Changes#
RTOS Initialization Timing#
One of the most significant changes in sl_main
is the earlier initialization of the RTOS kernel:
sl_system initialization order:#
Hardware initialization
Internal services and drivers initialization
Application initialization
RTOS kernel start
Task processing begins
sl_main initialization order:#
Hardware initialization
RTOS kernel start
Internal services and drivers initialization (now running in the context of RTOS tasks)
Application initialization (in RTOS task context)
Task scheduling and processing continues
The most impactful changes of this new initialization sequence are that the application initialization occurs after the RTOS is started and that the main() function runs in its own task.
Consequences of Earlier RTOS Initialization#
Resource availability: Services are initialized with RTOS primitives already available
Task prioritization: Stacks and application tasks can be properly prioritized from the start
Synchronization: RTOS synchronization primitives can be used throughout initialization
main() task: The
main()
function is run in a separate task at maximum priority during the initialization process.
Migration Process#
Step 1: Update Project Configuration#
If using Simplicity Studio, update your .slcp
file to replace the sl_system
component with the new sl_main
component.
If using the slc cli, update your .slcp
file to replace the sl_system
component with the new sl_main
component and re-generate your project.
If you use a custom build automation tool such as cmake, first re-generate the project with either Simplicity Studio or slc cli once. Then remove all inclusions of sl_system files and add all files under the gsdk/platform/service/sl_main repo except for the files under gsdk/platform/service/sl_main/sl_system_compatibility and gsdk/platform/service/sl_main/legacy. The files under those repositories are for bare-metal applications only.
Step 2: Update Main Function#
With sl_main, the
sl_system_init()
function no longer exists and needs to be replaced bysl_main_second_stage_init()
to finish the initialization process.Since the kernel is already started, the call to start the kernel needs to be removed from the
main()
function.
Before (sl_system)#
#include "sl_system_init.h"
#include "sl_system_kernel.h"
int main(void)
{
// Initialize Silicon Labs device, system, service(s) and protocol stack(s).
sl_system_init();
// Application-specific initialization
app_init();
// Start the kernel. Task(s) created in app_init() will start running.
sl_system_kernel_start();
}
After (sl_main)#
#include "sl_main_init.h"
int main(void)
{
// Initialize Silicon Labs device, system, service(s) and protocol stack(s).
// Note that if the kernel is present, the start task will be started and software component
// configuration will take place there.
sl_main_second_stage_init();
app_init();
}
Step 3: Update Application Initialization Functions#
Application tasks initialization functions typically don't need to change but need to account for the fact that the
app_init()
function is now called after the RTOS is startedIn the unlikely situation where you need to initialize something before the kernel starts, you can leverage the new
app_init_early()
.
Before (sl_system)#
#include "app_init.h"
void app_init(void)
{
// Initialize application resources
initialize_app_resources();
// Create application task
xTaskCreate(app_task_function, "App Task", APP_TASK_STACK_SIZE,
NULL, APP_TASK_PRIORITY, NULL);
}
After (sl_main)#
#include "sl_main_init.h"
// Same app_init() from the sl_system implementation
void app_init(void)
{
// Initialize application resources
initialize_app_resources();
// Create application task
xTaskCreate(app_task_function, "App Task", APP_TASK_STACK_SIZE,
NULL, APP_TASK_PRIORITY, NULL);
}
// Optional: Early initialization before RTOS is initialized
void app_init_early(void)
{
// Any pre-RTOS initialization specific to application
}
// Optional: Typically unused in RTOS applications, but can be implemented if needed
void app_process_action(void)
{
// No action required for RTOS applications
}
Step 4: Configure Start Task#
The main function is now executed in its own task. By default, the main stack size is 4096 and the task deletes itself after the initialization process is done. When deleting itself no memory is leaked and its deleted stack is repurposed to general purpose heap.
You can change the stack size in sl_main_start_task_config.h
with SL_MAIN_START_TASK_STACK_SIZE_BYTES
to a different size if needed either by changing the value manually in the file or by using Simplicity Studio's configuration tool with the sl_main
component. If you changed SL_STACK_SIZE
in your application, you should consider changing SL_MAIN_START_TASK_STACK_SIZE_BYTES
to the same value.
You can also change the priority of the start task in sl_main_start_task_config.h
by enabling SL_MAIN_ENABLE_START_TASK_PRIORITY_CHANGE
and changing the priority of SL_MAIN_START_TASK_PRIORITY
. This can be done either by changing the value manually in the file or by using Simplicity Studio's configuration tool with the sl_main
component. The start task will always be at maximum priority (osPriorityRealtime7
) when it starts. The priority set in SL_MAIN_START_TASK_PRIORITY
will take effect just before the call to app_init()
. Be mindful about the priority you set as other tasks may preempt app_init()
if SL_MAIN_START_TASK_PRIORITY
is too low. By default, SL_MAIN_ENABLE_START_TASK_PRIORITY_CHANGE
is disabled to ensure that app_init()
completes without getting preempted by other tasks.
Troubleshooting Common Issues#
Initialization Order Issues#
Problem: Components are being initialized in an unexpected order leading to dependency failures.
Solution:
Review the
sl_main_second_stage_init()
sequenceReview tasks' priorities
Keep in mind that the start task executes at maximum priority during the initialization process
Move hardware-dependent initialization to
app_init_early()
Called before RTOS is initializedMove RTOS-dependent initialization to
app_init()
Called after RTOS is initialized and started
Missing Functionality#
Problem: Functions previously available in sl_system
are not found in sl_main
.
Solution:
Check the new function naming in
sl_main_init.h
Make sure you are calling
sl_main_second_stage_init()
instead ofsl_system_init()
in yourmain()
functionMake sure you removed the call to
sl_system_kernel_start()
from yourmain()
function
Use the "weak" function overrides in
sl_main
to implement custom behaviorAvailable functions are:
app_init_early()
Called before RTOS is initializedapp_init()
Called after RTOS is initialized and started
RTOS Task Creation Timing#
Problem: Tasks created during initialization are starting too early or too late.
Solution:
Review tasks priorities
Tasks should be created in
app_init()
to ensure they start after all system components are initialized
Resource Availability#
Problem: RTOS resources (semaphores, queues, etc.) are being accessed before they're initialized.
Solution:
Ensure all RTOS resource creation happens in
app_init()
or laterHardware-specific resources that must be configured before the RTOS is initialized should be initialized in
app_init_early()
Tasks Starving#
Problem: Stack and application tasks are starving after initialization.
Solution:
Review tasks priorities
app_init() is never reached#
Problem: The app_init() function is never reached.
Solution:
Review
SL_MAIN_START_TASK_PRIORITY
insl_main_start_task_config.h
versus other task priorities, and make sure the start task is not getting preempted