esp_netif_driver.rst 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. ESP-NETIF Custom I/O Driver
  2. ===========================
  3. This section outlines implementing a new I/O driver with esp-netif connection capabilities.
  4. By convention, the I/O driver has to register itself as an esp-netif driver, and thus holds a dependency on esp-netif component and is responsible for providing data path functions, post-attach callback and in most cases, also default event handlers to define network interface actions based on driver's lifecycle transitions.
  5. Packet Input/Output
  6. ^^^^^^^^^^^^^^^^^^^
  7. As shown in the diagram, the following three API functions for the packet data path must be defined for connecting with esp-netif:
  8. * :cpp:func:`esp_netif_transmit()`
  9. * :cpp:func:`esp_netif_free_rx_buffer()`
  10. * :cpp:func:`esp_netif_receive()`
  11. The first two functions for transmitting and freeing the rx buffer are provided as callbacks, i.e., they get called from esp-netif (and its underlying TCP/IP stack) and I/O driver provides their implementation.
  12. The receiving function on the other hand gets called from the I/O driver, so that the driver's code simply calls :cpp:func:`esp_netif_receive()` on a new data received event.
  13. Post Attach Callback
  14. ^^^^^^^^^^^^^^^^^^^^
  15. A final part of the network interface initialization consists of attaching the esp-netif instance to the I/O driver, by means of calling the following API:
  16. .. code:: c
  17. esp_err_t esp_netif_attach(esp_netif_t *esp_netif, esp_netif_iodriver_handle driver_handle);
  18. It is assumed that the ``esp_netif_iodriver_handle`` is a pointer to driver's object, a struct derived from ``struct esp_netif_driver_base_s``, so that the first member of I/O driver structure must be this base structure with pointers to
  19. * post-attach function callback
  20. * related esp-netif instance
  21. As a consequence the I/O driver has to create an instance of the struct per below:
  22. .. code:: c
  23. typedef struct my_netif_driver_s {
  24. esp_netif_driver_base_t base; /*!< base structure reserved as esp-netif driver */
  25. driver_impl *h; /*!< handle of driver implementation */
  26. } my_netif_driver_t;
  27. with actual values of ``my_netif_driver_t::base.post_attach`` and the actual drivers handle ``my_netif_driver_t::h``.
  28. So when the :cpp:func:`esp_netif_attach()` gets called from the initialization code, the post-attach callback from I/O driver's code gets executed to mutually register callbacks between esp-netif and I/O driver instances. Typically the driver is started as well in the post-attach callback. An example of a simple post-attach callback is outlined below:
  29. .. code:: c
  30. static esp_err_t my_post_attach_start(esp_netif_t * esp_netif, void * args)
  31. {
  32. my_netif_driver_t *driver = args;
  33. const esp_netif_driver_ifconfig_t driver_ifconfig = {
  34. .driver_free_rx_buffer = my_free_rx_buf,
  35. .transmit = my_transmit,
  36. .handle = driver->driver_impl
  37. };
  38. driver->base.netif = esp_netif;
  39. ESP_ERROR_CHECK(esp_netif_set_driver_config(esp_netif, &driver_ifconfig));
  40. my_driver_start(driver->driver_impl);
  41. return ESP_OK;
  42. }
  43. Default Handlers
  44. ^^^^^^^^^^^^^^^^
  45. I/O drivers also typically provide default definitions of lifecycle behaviour of related network interfaces based on state transitions of I/O drivers. For example *driver start* ``->`` *network start*, etc.
  46. An example of such a default handler is provided below:
  47. .. code:: c
  48. esp_err_t my_driver_netif_set_default_handlers(my_netif_driver_t *driver, esp_netif_t * esp_netif)
  49. {
  50. driver_set_event_handler(driver->driver_impl, esp_netif_action_start, MY_DRV_EVENT_START, esp_netif);
  51. driver_set_event_handler(driver->driver_impl, esp_netif_action_stop, MY_DRV_EVENT_STOP, esp_netif);
  52. return ESP_OK;
  53. }
  54. Network Stack Connection
  55. ------------------------
  56. The packet data path functions for transmitting and freeing the rx buffer (defined in the I/O driver) are called from the esp-netif, specifically from its TCP/IP stack connecting layer.
  57. Note, that ESP-IDF provides several network stack configurations for the most common network interfaces, such as for the WiFi station or Ethernet.
  58. These configurations are defined in :component_file:`esp_netif/include/esp_netif_defaults.h` and should be sufficient for most network drivers. (In rare cases, expert users might want to define custom lwIP based interface layers; it is possible, but an explicit dependency to lwIP needs to be set)
  59. The following API reference outlines these network stack interaction with the esp-netif:
  60. .. include-build-file:: inc/esp_netif_net_stack.inc