diff --git a/doc/sphinx/source/developer_guide/abi.rst b/doc/sphinx/source/developer_guide/abi.rst
new file mode 100644
index 0000000000..209922f440
--- /dev/null
+++ b/doc/sphinx/source/developer_guide/abi.rst
@@ -0,0 +1,199 @@
+.. developer_guide abi
+
+=============
+ABI messaging
+=============
+
+Paparazzi use a custom publish/subscribe middleware to exchange data between software components named ``ABI``.
+
+.. note:: This middleware was named *ABI* for *AirBorne Ivy*
+
+General Idea
+------------
+
+* Give an easy way to allow software components to exchange data with minimum delay nor execution overhead.
+* The components don't need to know each other, they only need the message format.
+* Each subscriber set a callback function that will be called when new data are sent.
+
+.. warning:: This middleware is **NOT** thread safe. Threads are not widely used in Paparazzi but remember this if you use them.
+
+
+Message definition
+------------------
+
+The messages are described in ``conf/abi.xml`` analoguous to other messages in paparazzi. Name are unique, IDs starts from 0. "type" field should be a valid C type or pointer.
+
+.. code-block:: xml
+
+
+
+
+
+
+
+ ...
+
+
+Airborne code for subscriber
+----------------------------
+
+Include header and declare an ``abi_event`` as a global ``static`` variable (but **not** ``const``). Write the callback function with the proper prototype, matching the message.
+
+.. code-block:: C
+
+ #include "subsystems/abi.h"
+
+ static abi_event ev;
+
+ void data_cb(uint8_t sender_id, float a, struct bla b, struct foo * c) {
+ // do something here
+ }
+
+In the initialization function (or later) call the binding function for the message you want to receive.
+
+.. code-block:: C
+
+ AbiBindMsgDATA(ABI_BROADCAST, &ev, data_cb);
+
+
+The first parameter is the sender ID you want to receive the message from.
+
+* ``ABI_BROADCAST`` is used to receive messages from all senders.
+* ``ABI_DISABLE`` disable the callback (it will never be called).
+* Senders IDs can be found in the file ``sw/airborne/subsystems/abi_sender_ids.h``
+
+The second parameter is a pointer to the global ``abi_event`` you declared. This variable **can't** be reused for another bind. You must declare one abi_event per bind.
+
+The last parameter is your callback.
+
+.. note:: When creating your module with the Module Creator (in the Paparazzi Center : Tools -> Module Creator), you can add subcriptions to ABI messages.
+
+Airborne code for publisher
+---------------------------
+
+Include header, then call the send function with the appropriate parameters
+
+.. code-block:: C
+
+ float var = 2.;
+ struct bla s;
+ struct foo f;
+ AbiSendMsgDATA(SENDER_ID, var, s, &f);
+
+Replace ``SENDER_ID`` by your sender ID defined in ``sw/airborne/subsystems/abi_sender_ids.h``.
+
+Your sender ID identifier should be constructed as the concatenation of the name of the message and the name of your module, suffixed with ``_ID``.
+
+.. admonition:: example
+
+ A good sender ID for a module ``toto`` sending the message ``DATA`` may be ``DATA_TOTO_ID``
+
+.. warning::
+
+ The values 0 and 255 are reserved for ``ABI_DISABLE`` and ``ABI_BROADCAST`` and thus shall not be used.
+
+ You must also avoid using an ID already used to send the same message type.
+
+
+Code generation
+---------------
+
+The generated code will be in ``var/include/abi_messages.h`` and include some structure definition from ``sw/airborne/subsystems/abi_common.h`` (``sw/airborne/subsystems/abi.h`` is a convenience header that only includes ``var/include/abi_messages.h``).
+
+Bind and Send functions are generated, as well as callback type definition. A linked list is used to store the binded callbacks for each message. The head of the list is in an array to allow a fast access.
+
+The code is generated by ``/sw/tools/generators/gen_abi.xml``.
+
+In depth
+--------
+
+Generated code
+______________
+
+Here is the code of ``sw/airborne/subsystems/abi_common.h``:
+
+.. code-block:: C
+
+ /* Include here headers with structure definition you may want to use with ABI
+ * Ex: '#include "subsystems/gps.h"' in order to use the GpsState structure
+ */
+ #include "subsystems/gps.h"
+
+ #include "subsystems/abi_sender_ids.h"
+
+ #ifdef ABI_C
+ #define ABI_EXTERN
+ #else
+ #define ABI_EXTERN extern
+ #endif
+
+ /** Generic callback definition */
+ typedef void (*abi_callback)(void);
+
+ // ABI Broadcast address.
+ #define ABI_BROADCAST 255
+
+ // ABI disable address
+ #define ABI_DISABLE 0
+
+ /** Event structure to store callbacks in a linked list */
+ struct abi_struct {
+ uint8_t id;
+ abi_callback cb;
+ struct abi_struct *next;
+ };
+ typedef struct abi_struct abi_event;
+
+ /** Macros for linked list */
+ #define ABI_FOREACH(head,el) for(el=head; el; el=el->next)
+ #define ABI_PREPEND(head,add) { (add)->next = head; head = add; }
+
+
+
+
+The generated code in ``var/include/abi_messages.h`` for the message defined above will look like this:
+
+.. code-block:: C
+
+ // Code generated in var/include/abi_messages.h
+ #include "subsystems/abi_common.h
+ // Message IDs
+ #define ABI_DATA_ID 0
+
+ // Array and linked list
+ #define ABI_MESSAGE_NB
+ ABI_EXTERN abi_event* abi_queues[ABI_MESSAGE_NB]; // Magic trick to avoid generating .c file
+
+ // Callbacks
+ typedef void (*abi_callbackDATA)(uint8_t sender_id, float a, struct bla b, struct foo * c); // Specific callback for DATA message (arguments are const to prevent modifying them)
+
+ // Bind and Send for each messages
+ static inline void AbiBindMsgDATA(uint8_t sender_id, abi_event * ev, abi_callbackDATA cb) {
+ if (abi_queues[ABI_BARO_ABS_ID] == ev) return;
+ ev->id = sender_id;
+ ev->cb = (abi_callback)cb;
+ ABI_PREPEND(abi_queues[ABI_BARO_ABS_ID],ev);
+ }
+
+ static inline void AbiSendMsgDATA(uint8_t sender_id, float a, struct bla b, struct foo * c) {
+ // Call all callback functions
+ abi_event* e;
+ ABI_FOREACH(abi_queues[ABI_DATA_ID],e) {
+ if (e->id == ABI_BROADCAST || e->id == sender_id) { // call function only if selected source or broadcast address
+ abi_callbackDATA cb = (abi_callbackDATA)(e->cb); // C black magic
+ cb(sender_id, a, b, c);
+ }
+ }
+ }
+
+Using ABI in custom code
+________________________
+
+
+If you want to use ABI outside of one of the Paparazzi firmwares (``rotorcraft``, ``rover`` or ``fixedwing``), this code snippet should be written and called only once in a .c file (most probably your ``main.c``) to enable ABI:
+
+.. code-block:: C
+
+ #define ABI_C 1
+ #include "subsystems/abi.h"
+
diff --git a/doc/sphinx/source/developer_guide/index_developer.rst b/doc/sphinx/source/developer_guide/index_developer.rst
index 30a2cee1f7..5b3a5297c6 100644
--- a/doc/sphinx/source/developer_guide/index_developer.rst
+++ b/doc/sphinx/source/developer_guide/index_developer.rst
@@ -12,4 +12,5 @@ TBD
system_overview
communication
modules
+ abi