Zephyr based kernel

Zephyr has been introduced as an IP agnostic solution that replaced existing SOF audio specific kernel. The Zephyr base kernel has been complemented with SOF Low Level Drivers, SoC HAL and kernel extensions. The new solution continues scalable kernel concept and it serves as a generic part of infrastructure that can be statically and dynamically customized based on usage, compute, and memory constrains, HW configuration etc.

As a result of the kernel customization, a firmware infrastructure is produced. This firmware infrastructure can run on a given processor type and it is tuned for specified usage.

For more Zephyr kernel details, see Zephyr Introduction documentation

The Zephyr based kernel consists of the following components:

  • Hardware integration layer: XTHAL,

  • Low Level Drivers,

    • DMIC,

    • I2S,

    • SNDW,

    • GPIO,

    • I2C,

    • I3C,

    • timers,

    • GPDMA,

    • IDC,

    • IPC,

    • watchdog,

    • etc.

  • SoC HAL,

    • OEM SoC specific code,

  • Services: shared resource services, communication services, memory manager, power manager, interrupt manager, system service, etc.

  • Kernel extensions:

    • AVS schedulers,

    • Firmware Manager,

    • Media Processing Pipeline Components,

The Zephyr base kernel expectations:

  • it can scale down to meet all KPIs via static and dynamic scaling options,

  • Zephyr itself is IP agnostic and shared across other SW and FW projects,

  • it is available and maintain under open source license,

@startuml
allowmixing

scale max 1280 width

package "Kernel space" {

  package "Media Processing Pipelines - kernel extension" as MPP_KERNEL_EXTENSION {
    interface "Extended System Services" as ESS

    component "Firmware Manager" as FIRMWARE_MANAGER

    package "Communication" as COMMUNICATION {
        component "IPC Message Processing" as IPC_MESSAGE_PROCESSING
        component "Async Messaging" as ASYNC_MESSAGING

        IPC_MESSAGE_PROCESSING -[hidden]right- ASYNC_MESSAGING
    }

    package "Pipeline/Component Infrastructure" as PIPELINE_COMPONENT_INFRASTRUCTURE {
        component "Pipeline Management" as PIPELINE_MANAGEMENT
        component "Host/DAI Gateways" as HOST_DAI_GATEWAYS
        component "Processing Component Management" as PROCESSING_COMPONENT_MANAGEMENT

        PIPELINE_MANAGEMENT -[hidden]right- HOST_DAI_GATEWAYS
        HOST_DAI_GATEWAYS -[hidden]right- PROCESSING_COMPONENT_MANAGEMENT
    }

    package "AVS Scheduling" as AVS_SCHEDULING {
        component "Data Processing (DP) Tasks (EDF based)" as DP_TASKS
        component "Low Latency (LL) Tasks" as LL_TASKS

        DP_TASKS -[hidden]right- LL_TASKS
    }

    FIRMWARE_MANAGER -[hidden]right- PIPELINE_COMPONENT_INFRASTRUCTURE
    FIRMWARE_MANAGER -[hidden]down- COMMUNICATION
    COMMUNICATION -[hidden]right- AVS_SCHEDULING

    ESS -[hidden]down- FIRMWARE_MANAGER
    ESS -[hidden]down- PIPELINE_COMPONENT_INFRASTRUCTURE
  }

  package "Zephyr" as Zephyr_RTOS {
    interface "Zephyr System Services" as SS

    package "Schedulers" as SCHEDULERS {
        component "RTOS Scheduling" as RTOS_SCHEDULER
    }

    package "Services" as SERVICES {
        component "Memory Manager" as MEMORY_MANAGER
        component "Power Manager" as POWER_MANAGER
        component "IPC/IDC" as IXC
        component "Logging" as LOGGING
        component "Debug" as DEBUG
        component "Timer Manager" as TIMER_MANAGER
        component "Interrupt Handler" as INTERRUPT_HANDLER

        MEMORY_MANAGER -[hidden]right- POWER_MANAGER
        POWER_MANAGER -[hidden]right- IXC
        IXC -[hidden]down- LOGGING
        LOGGING -[hidden]right- TIMER_MANAGER
        TIMER_MANAGER -[hidden]right- INTERRUPT_HANDLER
    }

    package "SoC HAL" as SOC {
        component "OEM SoC 1" as SOC_1
        component "OEM SoC 2" as SOC_2
        component "Other SoCs" as OTHER_SOCS

        SOC_1 -[hidden]right- SOC_2
        SOC_2 -[hidden]right- OTHER_SOCS
    }

    package "Drivers" as DRIVERS {
        package "Common Drivers" as COMMON_DRIVERS {
          component "GPDMA" as GPDMA
          component "Timer" as TIMER
          component "SHA-384" as SHA384
          component "Watchdog" as WATCHDOG
          component "IPC" as IPC
          component "IDC" as IDC
        }

          package "Audio Drivers" as AUDIO_DRIVERS{
          component "DMIC" as DMIC
          component "I2S" as I2S
          component "SDW" as SDW
          component "HDA" as HDA

          DMIC -[hidden]right- I2S
          I2S -[hidden]right- SDW
          SDW -[hidden]right- HDA
        }

        package "Sensing Drivers" as SENSING_DRIVERS {
          component "I2C" as I2C
          component "GPIO" as GPIO
          component "I3C" as I3C
          component "SPI" as SPI
          component "UART" as UART

          I2C -[hidden]right- GPIO
          GPIO -[hidden]right- I3C
          I3C -[hidden]right- SPI
          SPI -[hidden]right- UART
        }
    }

    component "XTHAL" as XTHAL

    SS -[hidden]down- SCHEDULERS
    SS -[hidden]down- SERVICES
    SCHEDULERS -[hidden]right- SERVICES
    SERVICES -[hidden]right- SOC
    SERVICES --[hidden]down-- DRIVERS
    DRIVERS -[hidden]down- XTHAL
  }

  MPP_KERNEL_EXTENSION --[hidden]down-- Zephyr_RTOS
}

@enduml

Figure 57 Zephyr Kernel diagram

Scaling Options

Zephyr kernel offers scaling options to adjust to selected HW configuration, scale down to meet aggressive KPIs on a given platform, scale up to meet functional requirements.

The scaling is achieved in two ways:

  • static, kernel components can be selectively enabled in the build process

    • Drivers selected depending on SoC Configuration

    • Services and execution frameworks chosen in Zephyr

  • dynamic, not used parts can be unloaded and saved in “backup storage” memory, that typically has large capacity and high access latency. They will be loaded again once a specific event will happen

    • It is only applicable to SoCs that support it.

    • It is achieved via one of the following mechanisms:

      • Firmware Paging (if present) - Only currently executing modules are in SRAM.

      • Split Firmware into modules - Modules are loaded from “backup storage” or unloaded on explicit request. No runtime dynamism.

Handling Project Configuration

Zephyr is prepared to be configured via device tree that describe given SoC board audio hardware configuration.

A SoC board device tree allows configuring:

  • HW configuration

    • number of HP DSP cores,

    • types of memories available per cores,

    • supported clocks,

    • number of I/Os,

    • number of IPC and IDC interfaces for DSP cores,

    • etc.

  • DSP memory space,

  • IPC mailbox address,

  • etc.

Low Level Drivers

SOF is capable to support hardware with several audio I/Os, sensor I/Os, DSP accelerators and DMAs which count can be customized per architcture.

HW resources with low level drivers:

  • Audio I/Os: I2S, DMIC, SNDW, HD/A,

  • Sensor I/Os: I2C, I3C, GPIO, UART, SPI, ADC, PWM,

  • Common resources: HP GPDMA, IPC, IDC, Timers, SHA-384, Watchdog

NOTE: Not all I/Os are supported in each SoC board.

Zephyr based firmware provides low level drivers for all these resources. A specific driver can be enabled during build process.

SoC HAL

The SoC HAL include implementation and configuration details specific for selected SoC architecture. The SoC HAL abstraction allow to seamlesly switch between target SoC configuration builds.

More details can be found in Zephyr documentation:

Services

@startuml
allowmixing

scale max 1280 width

package "SOF" {
  package "Kernel Infrastructure" {
    interface "Zephyr System Services" as SS

    package "Services" {
        component "Memory Manager" as MEMORY_MANAGER
        component "Power Manager" as POWER_MANAGER
        component "IPC/IDC" as IXC
        component "Logging" as LOGGING
        component "Debug" as DEBUG
        component "Interrupt Handler" as INTERRUPT_HANDLER
    }

    SS .down. MEMORY_MANAGER
    SS .down. POWER_MANAGER
    SS .down. IXC
    SS .down. LOGGING
    SS .down. DEBUG
    SS .down. INTERRUPT_HANDLER
  }

  package "Kernel Extension" {
    interface "Extended System Services" as ESS

    component "AVS Scheduling" as AVS_Scheduling

    package "Extended Services" as EXTENDED_SERVICES {
          component "Firmware Manager" as FIRMWARE_MANAGEMENT
          component "Pipeline Management" as PIPELINE_MANAGEMENT
          component "Async Messaging" as ASYNC_MESSAGING
          component "Processing Component Management" as COMPONENT_MANAGEMENT
          component "IPC Message Processing" as IPC_MESSAGE_PROCESSING
    }

    ESS .down. FIRMWARE_MANAGEMENT
    ESS .down. PIPELINE_MANAGEMENT
    ESS .down. ASYNC_MESSAGING
    ESS .down. IPC_MESSAGE_PROCESSING
    ESS .down. COMPONENT_MANAGEMENT

    AVS_Scheduling -[hidden]down- EXTENDED_SERVICES
  }

  package "Loadable modules" {
      component "WoV" as WOV

      WOV .down. SS
      WOV .down. ESS
  }
}

@enduml

Figure 58 Example of kernel services

The base Zephyr services provide generic system management functionality for memory, interrupts, autonomous power control (clock and power gating, clock management).

The SOF specific functionality is exposed in a form of an extended kernel services. The extended services utilize Zephyr base services infrastructure and low level drivers to supply user space interface for the firmware application layer components. The user space separation from hardware and low level drivers significantly increase the firmware security and stability.

Firmware Management

The firmware manager is a core service that is responsible for:

  • reading HW capabilities (number of cores, memory available, etc.),

  • firmware initialization,

  • instantiation and initialization of Low Level drivers for the existing HW components,

    • memory type drivers initialization with size read form capability registers

    • audio drivers for supported interfaces

  • instantiate and initialize Extended Kernel Services

    • component manager

    • pipeline manager

    • IPC/IDC communication service

    • async messaging service

    • debug service

Interrupt Management

The interrupt handler service allows to:

  • enable and disable an interrupt for DSP core,

  • register a callback that will be called once a specified interrupt occur,

For more details, see Zephyr Interrupts documentation

Memory Management

The Memory Manager provides a service to other FW components to allocate a block out of available memory pools, it provides high level API, scans for unused memory areas, handles physical memory defragmentation, prefetch and cache policies. Most of the memory is expected to be paged.

All allocation requests refer to virtual memory address space, which shall be continuous. This also applies to DMA buffer allocations, where continuous memory is guaranteed by either continuous physical memory or VA/PA translation.

The map of available memory resources is passed to the Memory Manager during initialization of Memory Manager via firmware infrastructure.

For more details, see Zephyr Memory Management documentation.

Power Management

The power management behavior highly depends on platform that firmware runs on, and it can be configured during build time. There are platforms that only allow clock gating and power gating is not applicable.

The power management interface provides the following functionality:

  • allow and prevent power gating,

  • allow and prevent clock gating,

  • allow and prevent slower clock,

  • allow and prevent XTAL shutdown,

In all cases, the implementation relies on atomic counter which is incremented every time when prevent function is called and decremented when allow function is called.

Zephyr Power Management documentation.

IPC and IDC Service

The IPC and IDC Service provides communication channel over IPC or IDC. IPCs are used for the external communication with Host, other processors within SoC or other subsystems within PCH. IDCs are used for the internal communication between processors within SOF subsystem.

The introduction of SOF with Zephyr is followed with new IPC4 interface and message formats that replaced IPC3.

The following types of sequences are supported:

  • request-response initiated by Host,

    • it is synchronous sequence,

    • long-running operations shall queue request and send response immediately. The actual completion information should be sent via one-way asynchronous notification,

  • one-way asynchronous notification,

Debugging

The Zephyr based kernel provides a few services that helps with debugging FW.

Logging

The Logger Service provides a lightweight mechanism to push log entries to all firmware modules that are based on Zephyr logging infrastructure.

It is a very useful mechanism to do a first level of debugging.

Zephyr related documentation:

Probes

SOF supports injection and extraction probes. The probes are mainly used to extract audio data from queues between components.

The other probe use cases include:

  • injection of audio data to a component input queue - useful during testing and debugging,

  • injection of data to internal probes,

  • extraction of data from internal probes i.e. internal component states, intermediate data, debug information,

  • logging - probes can be used as transport for firmware logs,

Performance Measurements

The firmware infrastructures support performance measurements to collect information about DSP cycles or amount of data moved via interfaces.

Telemetry

Firmware infrastructure supports collection of telemetry events which then can be read by the Host Software. The modules running in FW infrastructure can push telemetry events via System Services.

If the telemetry collection is started, the telemetry events will be written to a common circular buffer.

If the telemetry collection is stopped/disabled, the telemetry events will be dropped at telemetry service level and they will not be written to the telemetry circular buffer. During transition from started to stopped state, the telemetry events that are already in the circular buffer will be dropped.

Schedulers

The scheduling method depends on compute and memory available for firmware running on processor as well as type of workloads executed on given domain.

There are following types of schedulers supported in SOF

  • AVS scheduling,

Async Messaging Service

Asynchronous Messaging Service (AMS) is mechanism to exchange asynchronous events between components running in the same firmware infrastructure or running on the another processor (e.g. between HiFi and Fusion cores).

The Async Messages can be also injected and extracted via Host Async Message Gateway module by Host SW.

System Services

The FW components do not know location of driver and service functions in base firmware library, so they need to access base firmware services via System Services.

In SOF with Zephyr the Zephyr interfaces for drivers were adopted. All newly developed drivers must be compliant to this standard and the legacy ones must be ported to it.

In Zephyr based firmware, a driver instance is obtained via device_get_binding function call with a name of a driver instance. There is no explicit driver initialization call as a driver instance is initialized with the first call.

A driver implementation must be ready for using the same hardware instance from many modules and from many cores (it must be thread-safe implementation). There can be more than one device instance if there is more than 1 instance of a hardware (i.e. 2 I2C owner controllers).

The example functionalities that should be exposed via system services:

  • IPC and IDC,

  • Logger Service,

  • RTOS scheduler functionalities, like yield,

  • Async Messaging Service,