mirror of
				https://gitea.osmocom.org/cellular-infrastructure/osmo-trx.git
				synced 2025-10-31 12:13:34 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			139 lines
		
	
	
		
			5.6 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
			
		
		
	
	
			139 lines
		
	
	
		
			5.6 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
| [[code_architecture]]
 | |
| == Code Architecture
 | |
| 
 | |
| [[fig-code-architecture-general]]
 | |
| .General overview of main OsmoTRX components
 | |
| [graphviz]
 | |
| ----
 | |
| digraph hierarchy {
 | |
| node[shape=record,style=filled,fillcolor=gray95]
 | |
| edge[dir=back, arrowtail=empty]
 | |
| 
 | |
| 2[label = "{Transceiver|+ constructor()\l+ destructor()\l+ init()\l+ numChans()\l+ receiveFIFO()\l+ setSignalHandler()\l}"]
 | |
| 3[label = "{RadioInterface|...}"]
 | |
| 4[label = "{RadioInterfaceResamp|...}"]
 | |
| 5[label = "{RadioInterfaceMulti|...}"]
 | |
| 6[label = "{RadioDevice|...}"]
 | |
| 7[label = "{UHDDevice|...}"]
 | |
| 8[label = "{LMSDevice|...}"]
 | |
| 9[label = "{USRPDevice|...}"]
 | |
| 10[label = "{IPCDevice|...}"]
 | |
| 
 | |
| 2->3[arrowtail=odiamond]
 | |
| 3->4[constraint=false]
 | |
| 3->5[constraint=false]
 | |
| 3->6[arrowtail=odiamond]
 | |
| 6->7
 | |
| 6->8
 | |
| 6->9
 | |
| 6->10
 | |
| }
 | |
| ----
 | |
| 
 | |
| [[fig-code-architecture-threads]]
 | |
| .Example of thread architecture with OsmoTRX configured to use 2 logical RF channels (Trx=Transceiver, RI=RadioIface)
 | |
| [graphviz]
 | |
| ----
 | |
| digraph hierarchy {
 | |
| node[shape=record,style=filled,fillcolor=gray95]
 | |
| 
 | |
| trans [label="Transceiver"];
 | |
| radioiface [label="RadioInterface"];
 | |
| radiodev [label="RadioDevice"];
 | |
| 
 | |
| trans:nw->trans:ne [label="Main"];
 | |
| trans:w->radioiface:w [label="Trx.TxPriorityQueueServiceLoop_0"];
 | |
| trans:w->radioiface:w [label="Trx.TxPriorityQueueServiceLoop_1"];
 | |
| radioiface:e->trans:e [label="Trx.RxServiceLoop_0"];
 | |
| radioiface:e->trans:e [label="Trx.RxServiceLoop_1"];
 | |
| radioiface->radiodev[label="RI.AlignRadioServiceLoop"];
 | |
| radioiface:sw->radiodev:nw [label="Trx.TxLowerLoop"];
 | |
| radiodev:ne->radioiface:se [label="Trx.RxLowerLoop"];
 | |
| }
 | |
| ----
 | |
| 
 | |
| [[code_component_transceiver]]
 | |
| === Transceiver
 | |
| 
 | |
| The Transceiver is the main component managing the other components running in
 | |
| the OsmoTRX process. There's a unique instance per process.
 | |
| 
 | |
| This class is quite complex from code point of view, as it starts lots of
 | |
| different threads and hence the interaction with this class from the outside is
 | |
| quite limited. Only interaction possible is to:
 | |
| 
 | |
| * `Transceiver()`: Create an instance through its constructor, at this time most
 | |
|   configuration is handed to it.
 | |
| * `init()`: Start running all the threads.
 | |
| * `receiveFIFO()`: Attach a `radioInterface` channel FIFO in order to use it.
 | |
| * `setSignalHandler()`: Used to set up a callback to receive certain events
 | |
|   asynchronously from the Transceiver. No assumptions can be made about from
 | |
|   which thread is the callback being called, which means multi-thread locking
 | |
|   precautions may be required in certain cases, similar to usual signal handler
 | |
|   processing. One important event received through this path is for instance
 | |
|   when the Transceiver detected a fatal error which requires it to stop. Since
 | |
|   it cannot stop itself (see destructor below), stopping procedure must be
 | |
|   delegated to the user who created the instance.
 | |
| * `~Transceiver()`: The destructor, which stops all running threads created at
 | |
|   `init()` time. Destroying the object is the only way to stop the `Transceiver`
 | |
|   completely, and must be called from a thread not managed by the
 | |
|   `Transceiver`, otherwise it will deadlock. Usually it is stopped from the main
 | |
|   thread, the one that called the constructor during startup.
 | |
| 
 | |
| During `init()` time, `Transceiver` will create a noticeable amount of threads,
 | |
| which may vary depending on the amount of RF channels requested.
 | |
| 
 | |
| Static amount of Threads (1 per `Transceiver` instance):
 | |
| 
 | |
| * `RxLowerLoop`: This thread is responsible for reading bursts from the
 | |
|   `RadioInterface`, storing them into its FIFO and sending Clock Indications
 | |
|   (<<trx_if_clock_ind>>) to _osmo-bts_trx_.
 | |
| * `TxLowerLoop`: Manages pushing bursts from buffers in the FIFO into the
 | |
|   `RadioInterface` at expected correct time based on the Transceiver clock.
 | |
| 
 | |
| Dynamic amount of Threads (1 per RF logical channel on the `Transceiver` instance):
 | |
| 
 | |
| * `RxServiceLoop`: Each thread of this type pulls bursts from the
 | |
|   `RadioInterface` FIFO for one specific logical RF channel and handles it
 | |
|   according to the slot and burst correlation type, finally sending proper data
 | |
|   over the TRX Manager UDP socket (<<trx_if>>).
 | |
| * `TxPriorityQueueServiceLoop`: Blocks reading from one ARFCN specific TRX
 | |
|   Manager UDP socket (<<trx_if>>), and fills the `RadioInterface` with it
 | |
|   setting clock related information.
 | |
| 
 | |
| All the Per-ARFCN Control Interface socket (<<trx_if_control>>) commands are
 | |
| handled by the event loop runnnig on the main thread. This is the only thread
 | |
| expected to use the private `start()` and `stop()` methods.
 | |
| 
 | |
| [[code_component_radioiface]]
 | |
| === RadioInterface
 | |
| 
 | |
| The `RadioInterface` sits between the `Transceiver` and the `RadioDevice`,  and
 | |
| provides extra features to the pipe like channelizers, resamplers, Tx/Rx
 | |
| synchronization on some devices, etc.
 | |
| 
 | |
| If the `RadioDevice` it drives requires it (only _USRP1_ so far), the
 | |
| `RadioIntercace` will start and manage a thread internally called
 | |
| `AlignRadioServiceLoop` which will align current RX and TX timestamps.
 | |
| 
 | |
| Different features are offered through different `RadioInterface` subclasses
 | |
| which are selected based on configuration and device detected at runtime. Using
 | |
| these features may impact on the amount of CPU required to run the entire pipe.
 | |
| 
 | |
| ==== RadioInterfaceResamp
 | |
| 
 | |
| This subclass of `RadioInterface` is automatically selected when some known
 | |
| specific UHD are to be used, since they require resampling to work properly.
 | |
| Some of this devices are for instance Ettus B100, USRP2 and X3XX models.
 | |
| 
 | |
| ==== RadioInterfaceMulti
 | |
| 
 | |
| This subclass of `RadioInterface` is used when <<multiarfcn_mode>> is requested.
 | |
| 
 | |
| [[code_component_radiodev]]
 | |
| === RadioDevice
 | |
| 
 | |
| The `RadioDevice` class is responsible for driving the actual Hardware device.
 | |
| It is actually only an interface, and it is implemented in each backend which in
 | |
| turn becomes a specific OsmoTRX binary, see <<trx_backends>>.
 |