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

Reply via email to