Flows

Memory initialization

Main goal of Memory initialization is to unmap unused memory after firmware load and create heaps for supported memory zones.

@startuml

box "SOF" #LightBlue
	participant "MPP Memory Manager" as mpp_memory_manager
end box

box "Zephyr" #LightGreen
	participant "Memory Manager" as zephyr_memory_manager
	participant "Memory Management Driver" as memory_management_driver
end box

box "Hardware" #LightGrey
	participant "Memory" as hw_memory
end box


-> memory_management_driver: sys_mm_drv_mm_init
	activate memory_management_driver
	memory_management_driver -> memory_management_driver: read unused_main_mem_start_marker\nfrom linker
	note right: The marker is used to\n identify where base firmware\n ends in memory (text, data, bss)

	memory_management_driver -> memory_management_driver: sys_mm_drv_unmap_region(unused_main_mem_start, unused_size)
		activate memory_management_driver
		opt If architecture support granular memory banks power control
			memory_management_driver -> hw_memory: power down unused memory banks
			deactivate memory_management_driver
		end

	deactivate memory_management_driver

-> mpp_memory_manager: mpp_mem_init
	activate mpp_memory_manager
	mpp_memory_manager -> mpp_memory_manager: read memory zones\nbase address and size
	loop for each memory region create heap
		mpp_memory_manager -> zephyr_memory_manager: k_heap_init\n(heap, mem*, size)
			activate zephyr_memory_manager
			return
	end

	deactivate mpp_memory_manager

@enduml

Figure 61 Memory initialization flow

Memory allocation

The common memory allocation is expected to use one of the available memory zones via Zephyr Heap that was created during initialization.

@startuml

box "SOF" #LightBlue
	participant "Component Management" as component_management
	participant "MPP Memory Manager" as mpp_memory_manager
end box

box "Zephyr" #LightGreen
	participant "Zephyr Memory Manager" as zephyr_memory_manager
end box

activate component_management
component_management -> mpp_memory_manager: rmalloc(mem_zone, flags, caps, size)
	activate mpp_memory_manager

	mpp_memory_manager -> mpp_memory_manager: find memory heap that\nmatch zone and caps
	mpp_memory_manager -> zephyr_memory_manager: k_heap_alloc (heap, size)
		activate zephyr_memory_manager
		return
	mpp_memory_manager --> component_management
@enduml

Figure 62 Memory allocation example flow

Memory allocation directly using Memory Management Driver

In specific use cases (e.g. Dynamic Component Load) it may be required to allocate memory directly using Memory Management Driver to control what virtual address will be mapped to physical memory.

@startuml

box "SOF" #LightBlue
	participant "Library Manager" as library_manager
end box

box "Zephyr" #LightGreen
	participant "Memory Management Driver" as memory_management_driver
end box

box "Hardware" #LightGrey
	participant "Memory" as hw_memory
end box

activate library_manager

library_manager -> memory_management_driver: sys_mm_drv_map_region\n(virt*, phys=NULL, size, flags)
	activate memory_management_driver
	memory_management_driver -> memory_management_driver: allocate memory phys pages
	opt if phys memory pages require power up
		memory_management_driver -> hw_memory: power up memory banks
	end

	return

@enduml

Figure 63 Example memory allocation using Memory Management Driver

Dynamic Component Load

The loadable components are stored in Loadable Library memory zone and can be loaded on instantiate request to System memory. The components load to System memory is optional and integrator can indicate if the components can be executed directly from the Loadable Library memory zone.

@startuml

box "Host" #LightGreen
	participant "Driver" as host_driver
end box

box "Media Processing Pipelines Layer" #LightSkyBlue
	participant "Component Manager" as component_manager
	participant "Library Manager" as lib_manager
	participant "MPP Memory Manager" as mpp_memory_manager
end box

box "Zephyr RTOS" #LightBlue
	participant "Memory Management Driver" as memory_management_driver
end box

box "Hardware" #LightGrey
	participant "Memory" as hw_memory
end box

host_driver -> lib_manager: Load Library
	activate lib_manager
	lib_manager -> mpp_memory_manager: rmalloc(MEM_ZONE_RUNTIME, flags=NULL, MEM_CAPS_LOADABLE_LIBRARY, size)
		activate mpp_memory_manager
		return address to store library
	lib_manager --> host_driver
	deactivate lib_manager

host_driver -> lib_manager: Transfer library over DMA\nto given address

host_driver -> component_manager: Instantiate Component
	activate component_manager

	opt  if Component is Loadable and it is first instance
		component_manager -> lib_manager: Load component
		activate lib_manager

		loop repeat for Component TEXT, RODATA
			lib_manager -> lib_manager: read Component virtual address and size from manifest

			lib_manager -> memory_management_driver: sys_mm_drv_map_region(virt*, phys=NULL, size, flags=NULL)
				activate memory_management_driver
				memory_management_driver -> memory_management_driver: allocate free phys pages
				opt power up memory banks for allocated phys pages
					memory_management_driver -> hw_memory: power up memory banks
				end
				memory_management_driver --> lib_manager
				deactivate memory_management_driver

			lib_manager -> lib_manager: read Component address offset from library manifest
			lib_manager -> lib_manager: mem_copy(virt*, library_store_addr + offset, size)
			lib_manager -> memory_management_driver: sys_mm_drv_update_region(virt*, size, flags= CODE / RODATA)
				activate memory_management_driver
				note right: update region flags to prevent overwrite
				return

		end

		opt if Component has BSS
			lib_manager -> memory_management_driver: sys_mm_drv_map_region(virt*, phys=NULL, bss_size, flags)
			activate memory_management_driver
			memory_management_driver -> memory_management_driver: allocate free phys pages
			opt power up memory banks for allocated phys pages
				memory_management_driver -> hw_memory: power up memory banks
			end
			memory_management_driver --> lib_manager
			deactivate memory_management_driver
		end

		lib_manager --> component_manager
		deactivate lib_manager
	end

	component_manager -> component_manager: Instantiate Component
	component_manager --> host_driver

@enduml

Figure 64 Dynamic component load and instantiation flow