1# EDTT transport for BabbleSim devices 2 3This is a description of the inner workings of the 4EDTT transport for BabbleSim (`edttt_bsim.py` and associated embedded driver) 5 6## Introduction 7 8In simulation the picture of how the communication between the EDTT and the 9devices looks as follows: 10 11``` 12 _____________ __________ 13 | | --> | | 14 ______ | | | Device 0 | 15| | --> | | <-- |__________| 16| EDTT | | EDTT Bridge | __________ 17|______| <-- | | --> | | 18 | | | Device 1 | 19 |_____________| <-- |__________| 20 21``` 22 23 24Each of the “-->” is a POSIX named pipe (FIFO) (which by default can buffer up to 2564KB in each direction). 26 27The bridge has 2 main purposes: 28 29* It routes the EDTT data to the appropriate device 30* It pauses the simulation while the EDTT is processing, so there is no asynchronous 31 behaviour 32 33This is done by having the EDTT command the brdige to either: 34 35 * read to a device 36 * write to a devices 37 * let simulation time advance 38 * terminate the simulation 39 40 411. The EDTT, will only run while the simulation itself is paused. 42 The EDTT can interact in 3 ways with the devices (thru the bridge)<br> 43 When the EDTT writes to a device, that data is piped immediately to the 44 bridge.<br> 45 When the EDTT reads from the device, it actually sends a command to the 46 bridge requesting N bytes with a timeout.<br> 47 When the EDTT does `transport.wait(time)`, it tells the bridge to just let 48 the simulation time go ahead for `<time>` without doing anything. 49 502. The Bridge will fully block the simulation until it gets a new command from 51 the EDTT 52 53 * If the bridge is commanded to write to a device, it pipes it to the 54 device immediately (without unblocking the simulation) and blocks until it 55 gets a new command again from the EDTT 56 * If it is commanded to “read” from a device, it tries to read from the 57 device pipe immediately: 58 59 * If it succeeds it sends it immediately to the EDTT 60 * If there is not enough data yet from the device, it will wait 61 `<recv_wait_us>` in simulated time, that is, it will let the 62 simulation time to advance by `<recv_wait_us>`, and try again. 63 (`<recv_wait_us>` is a bridge command line option, by default 10ms) 64 653. The embedded device transport 66 67 * When the app tries to read from the EDTT transport: it will try 68 immediately 69 70 * If there is enough data, it just returns it to the caller 71 * If it does not have enough data yet, and the read was blocking, 72 will wait for `EDTT_IF_RECHECK_DELTA` (5ms) and retry 73 74 * When told to write it will pipe it to the bridge immediately without any 75 delay 76 77 78So effectively: 79 80* Writing from the EDTT to the device can be aparent to the device only the next 81 time the device checks (up to EDTT_IF_RECHECK_DELTA later) 82* Reading from the device can take up to the next `<recv_wait_us>` boundary 83 for the EDTT bridge to read it out, apart from the simulated time it may 84 take for the device to generate it. 85 86 87## Implementation details: 88 89The named pipes are placed in /tmp/bsim_<user>/<sim_id>/ 90There is 2 to communicate between the python tests and the bridge: 91 92* Device<bridge_id>.ToEDTT 93* Device<bridge_id>.ToBRIDGE 94 95And 2 from the bridge to each device 96 97* Device<device_id>.EDTTin 98* Device<device_id>.EDTTout 99 100Between the EDTT bsim transport and the bridge there is a simple protocol, 101in which the EDTT side is the master. 102Any action performed by the bridge is initiated by the EDTT transport side. 103 104The protocol with the EDTTool is as follows: 105``` 106 1 byte commands are sent from the EDTTool 107 The commands are: SEND, RCV, WAIT, DISCONNECT 108 SEND is followed by: 109 1 byte : device idx 110 2 bytes: (uint16_t) number of bytes 111 N bytes: payload to forward 112 RCV is followed by: 113 1 byte : device idx 114 8 bytes: timeout time (simulated absolute time) 115 2 bytes: (uint16_t) number of bytes 116 WAIT: 117 8 bytes: (uint64_t) absolute time stamp until which to wait 118 (not the wait duration, but the end of the wait) 119 DISCONNECT: 120 - nothing 121 122 After receiving a command (and its payload) the bridge device will respond: 123 to a SEND: nothing 124 to a RCV: 125 1 byte : reception done (0) or timeout (1) 126 8 bytes: timestamp when the reception or timeout actually happened 127 0/N bytes: (0 bytes if timeout, N bytes as requested otherwise) 128 to a WAIT: nothing 129 to a DISCONNECT: nothing 130``` 131 132That is, when the EDTT writtes to a DUT, a prefix starting with the SEND 133command is sent ahead of the data. The bridge looks into this header to know 134for which device this message is meant, and how many bytes the message has. 135The header is thrown away in the bridge and the message itself forwarded to 136that DUT. 137 138A read from the EDTT to a DUT is effectively a command to the bridge to let 139the simulation run until that amount of requested data has been received in 140the bridge from that DUT, or the timeout has been reached. 141 142### Notes about the transport in the EDTT side 143 144When connect() is called the FIFOs to the bridge will be created 145(if not yet there), and the EDTT will be blocked until the bridge 146connects on the other side. 147 148Immediately after the number of devices the bridge is connected to 149will be read out from the FIFO. 150 151When disconnecting, the transport will attempt to delete the FIFOs 152(the last one who disconnects from its end succeds) 153 154### Notes about the bridge 155 156At startup it will create and connect to its end of the pipes 157to the EDTT and devices. 158It will then send the number of DUTs it is connected to the EDTT 159transport side. 160After that it will as described before enter an infinite loop 161waiting for commands from the EDTT transport, and reacting accordingly. 162 163### Notes about the transport in the DUT side 164 165On the initial connection, edtt_start(), the pipes are opened, 166and the simulated device execution is blocked until the bridge 167connects to the other side. 168 169When sending and receiving data to and towards the EDTT, 170the byte stream is passed through unaltered. 171 172Reads can be blocking (EDTTT_BLOCK), waiting for the bytes to arrive, 173or non-blocking (EDTTT_NONBLOCK). 174 175Writes are always treated as non-blocking in this trasnport, assuming that 176the FIFO is large enough to queue the request. In the very unlikely case in which 177it would not be, an error would be printed. 178 179When the transport layer is closed, the EDTT Bridge FIFOs are closed and deleted. 180