pw_system#

Pigweed AI summary: The pw_system module is an early work-in-progress towards an opinionated framework for new projects built on Pigweed. It pulls together many modules across Pigweed to construct a working system with RPC, Logging, an OS Abstraction layer, and more, greatly simplifying the process of starting a new project using Pigweed. The module includes a target toolchain template called pw_system_target that reduces the amount of work required to declare a target toolchain with pre-selected backends for pw_log, pw_assert

Warning

This module is an early work-in-progress towards an opinionated framework for new projects built on Pigweed. It is under active development, so stay tuned!

pw_system is quite different from typical Pigweed modules. Rather than providing a single slice of vertical functionality, pw_system pulls together many modules across Pigweed to construct a working system with RPC, Logging, an OS Abstraction layer, and more. pw_system exists to greatly simplify the process of starting a new project using Pigweed by drastically reducing the required configuration space required to go from first signs of on-device life to a more sophisticated production-ready system.

Trying out pw_system#

Pigweed AI summary: The article provides instructions for trying out pw_system, a software system, on a STM32F429I Discovery board or a simulated device on a local machine. The article directs readers to the board's target documentation or the steps for trying out the simulated device.

If you’d like to give pw_system a spin and have a STM32F429I Discovery board, refer to the board’s target documentation for instructions on how to build the demo and try things out

If you don’t have a discovery board, there’s a simulated device variation that you can run on your local machine with no additional hardware. Check out the steps for trying this out here.

Target Bringup#

Pigweed AI summary: This section provides instructions on how to bring up a new device using Pigweed's pw_system. The process involves creating a pw_system_target in your GN build, writing target-specific initialization, and implementing pw::system::UserAppInit() in your application. The section also includes a note on the limitations of pw_system_target and a GN Target Toolchain Template called pw_system_target that reduces the amount of work required to declare a target toolchain with pre-selected backends for pw_log, pw_assert,

Bringing up a new device is as easy as 1-2-3! (Kidding, this is a work in progress)

  1. Create a ``pw_system_target`` in your GN build. This is what will control the configuration of your target from a build system level. This includes which compiler will be used, what architecture flags will be used, which backends will be used, and more. A large quantity of configuration will be pre-set to work with pw_system after you select the CPU and scheduler your target will use, but your target will likely need to set a few other things to get to a fully working state.

  2. Write target-specific initialization. Most embedded devices require a linker script, manual initialization of memory, and some clock initialization. pw_system leaves this to users to implement as the exact initialization sequence can be very project-specific. All that’s required is that after early memory initialization and clock configuration is complete, your target initialization should call pw::system::Init() and then start the RTOS scheduler (e.g. vTaskStartScheduler()).

  3. Implement ``pw::system::UserAppInit()`` in your application. This is where most of your project’s application-specific logic goes. This could be starting threads, registering RPC services, turning on Bluetooth, or more. In UserAppInit(), the RTOS will be running so you’re free to use OS primitives and use features that rely on threading (e.g. RPC, logging).

Pigweed’s stm32f429i_disc1_stm32cube target demonstrates what’s required by the first two steps. The third step is where you get to decide how to turn your new platform into a project that does something cool! It might be as simple as a blinking LED, or something more complex like a Bluetooth device that brews you a cup of coffee whenever pw watch kicks off a new build.

Note

Because of the nature of the hard-coded conditions in pw_system_target, you may find that some options are missing for various RTOSes and architectures. The design of the GN integration is still a work-in-progress to improve the scalability of this, but in the meantime the Pigweed team welcomes contributions to expand the breadth of RTOSes and architectures supported as pw_system_targets.

GN Target Toolchain Template#

Pigweed AI summary: The GN Target Toolchain Template module includes a pre-configured target toolchain called pw_system_target that simplifies the process of declaring a target toolchain with pre-selected backends for various components. The template is not highly customizable or extensible, but serves as a starting point for building a toolchain. The module includes examples of how to use the template for specific hardware configurations.

This module includes a target toolchain template called pw_system_target that reduces the amount of work required to declare a target toolchain with pre-selected backends for pw_log, pw_assert, pw_malloc, pw_thread, and more. The configurability and extensibility of this template is relatively limited, as this template serves as a “one-size-fits-all” starting point rather than being foundational infrastructure.

# Declare a toolchain with suggested, compiler, compiler flags, and default
# backends.
pw_system_target("stm32f429i_disc1_stm32cube_size_optimized") {
  # These options drive the logic for automatic configuration by this
  # template.
  cpu = PW_SYSTEM_CPU.CORTEX_M4F
  scheduler = PW_SYSTEM_SCHEDULER.FREERTOS

  # Optionally, override pw_system's defaults to build with clang.
  system_toolchain = pw_toolchain_arm_clang

  # The pre_init source set provides things like the interrupt vector table,
  # pre-main init, and provision of FreeRTOS hooks.
  link_deps = [ "$dir_pigweed/targets/stm32f429i_disc1_stm32cube:pre_init" ]

  # These are hardware-specific options that set up this particular board.
  # These are declared in ``declare_args()`` blocks throughout Pigweed. Any
  # build arguments set by the user will be overridden by these settings.
  build_args = {
    pw_third_party_freertos_CONFIG = "$dir_pigweed/targets/stm32f429i_disc1_stm32cube:stm32f4xx_freertos_config"
    pw_third_party_freertos_PORT = "$dir_pw_third_party/freertos:arm_cm4f"
    pw_sys_io_BACKEND = dir_pw_sys_io_stm32cube
    dir_pw_third_party_stm32cube = dir_pw_third_party_stm32cube_f4
    pw_third_party_stm32cube_PRODUCT = "STM32F429xx"
    pw_third_party_stm32cube_CONFIG =
        "//targets/stm32f429i_disc1_stm32cube:stm32f4xx_hal_config"
    pw_third_party_stm32cube_CORE_INIT = ""
    pw_boot_cortex_m_LINK_CONFIG_DEFINES = [
      "PW_BOOT_FLASH_BEGIN=0x08000200",
      "PW_BOOT_FLASH_SIZE=2048K",
      "PW_BOOT_HEAP_SIZE=7K",
      "PW_BOOT_MIN_STACK_SIZE=1K",
      "PW_BOOT_RAM_BEGIN=0x20000000",
      "PW_BOOT_RAM_SIZE=192K",
      "PW_BOOT_VECTOR_TABLE_BEGIN=0x08000000",
      "PW_BOOT_VECTOR_TABLE_SIZE=512",
    ]
  }
}

# Example for the Emcraft SmartFusion2 system-on-module
pw_system_target("emcraft_sf2_som_size_optimized") {
  cpu = PW_SYSTEM_CPU.CORTEX_M3
  scheduler = PW_SYSTEM_SCHEDULER.FREERTOS

  link_deps = [ "$dir_pigweed/targets/emcraft_sf2_som:pre_init" ]
  build_args = {
    pw_log_BACKEND = dir_pw_log_basic #dir_pw_log_tokenized
    pw_log_tokenized_HANDLER_BACKEND = "//pw_system:log"
    pw_third_party_freertos_CONFIG = "$dir_pigweed/targets/emcraft_sf2_som:sf2_freertos_config"
    pw_third_party_freertos_PORT = "$dir_pw_third_party/freertos:arm_cm3"
    pw_sys_io_BACKEND = dir_pw_sys_io_emcraft_sf2
    dir_pw_third_party_smartfusion_mss = dir_pw_third_party_smartfusion_mss_exported
    pw_third_party_stm32cube_CONFIG =
        "//targets/emcraft_sf2_som:sf2_mss_hal_config"
    pw_third_party_stm32cube_CORE_INIT = ""
    pw_boot_cortex_m_LINK_CONFIG_DEFINES = [
      "PW_BOOT_FLASH_BEGIN=0x00000200",
      "PW_BOOT_FLASH_SIZE=200K",

      # TODO(b/235348465): Currently "pw_tokenizer/detokenize_test" requires at
      # least 6K bytes in heap when using pw_malloc_freelist. The heap size
      # required for tests should be investigated.
      "PW_BOOT_HEAP_SIZE=7K",
      "PW_BOOT_MIN_STACK_SIZE=1K",
      "PW_BOOT_RAM_BEGIN=0x20000000",
      "PW_BOOT_RAM_SIZE=64K",
      "PW_BOOT_VECTOR_TABLE_BEGIN=0x00000000",
      "PW_BOOT_VECTOR_TABLE_SIZE=512",
    ]
  }
}

Metrics#

Pigweed AI summary: The log backend is keeping track of metrics to demonstrate the usage of pw_metric and how to retrieve them through Device.get_and_log_metrics().

The log backend is tracking metrics to illustrate how to use pw_metric and retrieve them using Device.get_and_log_metrics().

Console#

Pigweed AI summary: The pw-system-console can be used to interact with targets and the pw_system CLI reference provides detailed information on CLI usage.

The pw-system-console can be used to interact with the targets. See pw_system CLI reference for detailed CLI usage information.