Hi Khaled, On Wed, Jun 07, 2017 at 04:26:01PM +0200, Khaled Elsayed wrote: [...] > So, it has the controller and uart only. My questions are: > > 1) What glues the different parts together? How does the code identify that > when I include the transport/ram that host and link layer will communicate > via RAM not uart. Where in the code is this handled? > Similarly, if host, gap, gatt, etc are missing from pkg.yml where in the > code are these modules avoided to be initialized or loaded (or more clearly > where in the code are they loaded and initialized when they exist in the > dependency)?
The answer to both questions lies in the sysinit() call. The code that ultimately gets executed by sysinit() is magically generated by newt each time you build a target. The sysinit function initializes each package in the project. Each package specifies zero or more "init" functions, each with a corresponding stage number. The generated sysinit function is a flat sequence calls to each of these init functions, ordered by stage. The benefits of this mechanism are: 1. Apps can be configured and re-used without needing code modifications. 2. App code is simplified by the elimination of boilerplate initialization code. The downside is, of course, generated code, which everyone hates :). This is discussed in more detail at: http://mynewt.apache.org/latest/os/modules/sysinitconfig/sysinitconfig/ This explains the initialization of the host, gap, and gatt packages. If these packages get pulled in to your project, newt generates calls to their initialization function in sysinit(). The BLE transport case is slightly more complicated. Here, another Mynewt concept is required: APIs. When a package declares that it supports a particular API, it promises to the rest of the system that it exposes a set of functions and global variables. This allows another package to express an "abstract dependency." That is, a package depends on a particular interface, but it doesn't care which package actually provides that interface. The collection of bluetooth HCI transports packages is an example of this. The host and controller code is written such that they don't know the specific transport being used; they just use the abstract API provided by all the HCI transport packages. The host package doesn't have a hard dependency on a specific transport package. Instead, it requires the "ble_transport" API. At build time, newt ensures that one (and only one) package provides the required API, and it gives the host code access to the transport package's header files. Note: The newt tool doesn't verify that a package actually implements the APIs is claims to. The newt tool just makes sure that for each required API, one and only one package that supplies the API gets pulled in to the build. At init time, the host package configures the transport package (whichever one it may be) with function pointer callbacks. In this way, the host doesn't need to know which transport is actually being used, and the transport doesn't need to depend on the host or controller. > 2) If one wants to use mynewt as host only with nordic soft device as is, > certainly pkg.yml will not include net/nimble/controller. So, how to tell > the build system to load or leave nordic controller in place? You need to make sure your project does not depend on the controller package. Generally, there are two changes you would make to an app's pkg.yml file to convert it from a combined-host-controller app to a host-only app: 1. Remove from pkg.deps: @apache-mynewt-core/net/nimble/controller @apache-mynewt-core/net/nimble/transport/ram 2. Add your desired transport package to pkg.deps, e.g., @apache-mynewt-core/net/nimble/transport/uart Chris