Compare commits
58 Commits
v2.0.0
...
v1.7.0-rc2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
46a38ee460 | ||
|
|
25281db44c | ||
|
|
f20dc053b5 | ||
|
|
4791c83864 | ||
|
|
03dc412517 | ||
|
|
ec8c508153 | ||
|
|
9b9f679b90 | ||
|
|
6b0903bcf9 | ||
|
|
3a8753d0fe | ||
|
|
dba515fd61 | ||
|
|
655b2bf361 | ||
|
|
460ffe7601 | ||
|
|
d17f16d8d7 | ||
|
|
1d32ad0dc3 | ||
|
|
7635965b1a | ||
|
|
781e6c388a | ||
|
|
9be5f9ebfd | ||
|
|
a976b8db67 | ||
|
|
26464f8caa | ||
|
|
177ab6e27e | ||
|
|
8c7f5cca69 | ||
|
|
ad6aa86df1 | ||
|
|
fea5778664 | ||
|
|
c8c6bee8a2 | ||
|
|
37e830a1da | ||
|
|
0d1db8fccd | ||
|
|
47c83debea | ||
|
|
91568e0137 | ||
|
|
1db37bb98b | ||
|
|
1f7e43569b | ||
|
|
217049d42f | ||
|
|
171b25f1cb | ||
|
|
009105706f | ||
|
|
62ddee16e6 | ||
|
|
e72156fa17 | ||
|
|
cb3569d412 | ||
|
|
f768b3e968 | ||
|
|
6bbd662ac0 | ||
|
|
4bbeabb359 | ||
|
|
63a9b84322 | ||
|
|
1d69c0cb67 | ||
|
|
d5318e79ca | ||
|
|
9088de298d | ||
|
|
33cbbd95c4 | ||
|
|
1a9c57a493 | ||
|
|
bf82f14d25 | ||
|
|
eba6eef71b | ||
|
|
9b4afd36fc | ||
|
|
10561731df | ||
|
|
cc8354a359 | ||
|
|
a4951b6b29 | ||
|
|
ab2159f52f | ||
|
|
7ef1c66593 | ||
|
|
1d66fab0c4 | ||
|
|
9fc3173c96 | ||
|
|
920f335d9f | ||
|
|
0c0ec4a0e2 | ||
|
|
cd98edf028 |
6
Makefile
6
Makefile
@@ -1,8 +1,8 @@
|
||||
VERSION_MAJOR = 1
|
||||
VERSION_MINOR = 6
|
||||
PATCHLEVEL = 99
|
||||
VERSION_MINOR = 7
|
||||
PATCHLEVEL = 0
|
||||
VERSION_RESERVED = 0
|
||||
EXTRAVERSION =
|
||||
EXTRAVERSION = -rc2
|
||||
NAME = Zephyr Kernel
|
||||
|
||||
export SOURCE_DIR PROJECT MDEF_FILE
|
||||
|
||||
@@ -154,8 +154,9 @@ endif # GPIO
|
||||
if I2C
|
||||
|
||||
config I2C_QMSI
|
||||
def_bool y
|
||||
def_bool n
|
||||
|
||||
if I2C_QMSI
|
||||
config I2C_0
|
||||
def_bool y
|
||||
|
||||
@@ -189,9 +190,12 @@ config I2C_SDA_TX_HOLD
|
||||
config I2C_SDA_RX_HOLD
|
||||
default 24
|
||||
|
||||
endif
|
||||
|
||||
config I2C_QMSI_SS
|
||||
def_bool y
|
||||
|
||||
if I2C_QMSI_SS
|
||||
config I2C_SS_0
|
||||
def_bool y
|
||||
|
||||
@@ -216,6 +220,8 @@ config I2C_SS_SDA_SETUP
|
||||
config I2C_SS_SDA_HOLD
|
||||
default 10
|
||||
|
||||
endif
|
||||
|
||||
endif # I2C
|
||||
|
||||
if ADC
|
||||
|
||||
@@ -555,6 +555,41 @@ context, navigate to: :file:`\$ZEPHYR_BASE/samples/philosophers/src`.
|
||||
obj-y = main.o
|
||||
|
||||
|
||||
Support for building third-party library code
|
||||
=============================================
|
||||
|
||||
It is possible to build library code outside the application's :file:`src`
|
||||
directory but it is important that both application and library code targets
|
||||
the same Application Binary Interface (ABI). On most architectures there are
|
||||
compiler flags that control the ABI targeted, making it important that both
|
||||
libraries and applications have certain compiler flags in common. It may also
|
||||
be useful for glue code to have access to Zephyr kernel header files.
|
||||
|
||||
To make it easier to integrate third-party components, the Zephyr build system
|
||||
includes a special build target, ``outputexports``, that takes a number of
|
||||
critical variables from the Zephyr build system and copies them into
|
||||
:file:`Makefile.export`. This allows the critical variables to be included by
|
||||
wrapper code for use in a third-party build system.
|
||||
|
||||
The following variables are recommended for use within the third-party build
|
||||
(see :file:`Makefile.export` for the complete list of exported variables):
|
||||
|
||||
* ``CROSS_COMPILE``, together with related convenience variables to call the
|
||||
cross-tools directly (including ``AR``, ``AS``, ``CC``, ``CXX``, ``CPP``
|
||||
and ``LD``).
|
||||
|
||||
* ``ARCH`` and ``BOARD``, together with several variables that identify the
|
||||
Zephyr kernel version.
|
||||
|
||||
* ``KBUILD_CFLAGS``, ``NOSTDINC_FLAGS`` and ``ZEPHYRINCLUDE`` all of which
|
||||
should normally be added, in that order, to ``CFLAGS`` (or
|
||||
``CXXFLAGS``).
|
||||
|
||||
* All kconfig variables, allowing features of the library code to be
|
||||
enabled/disabled automatically based on the Zephyr kernel configuration.
|
||||
|
||||
:file:`samples/static_lib` is a sample project that demonstrates
|
||||
some of these features.
|
||||
|
||||
Build an Application
|
||||
********************
|
||||
|
||||
69
doc/glossary.rst
Normal file
69
doc/glossary.rst
Normal file
@@ -0,0 +1,69 @@
|
||||
.. _glossary:
|
||||
|
||||
Glossary of Terms
|
||||
#################
|
||||
|
||||
.. glossary::
|
||||
:sorted:
|
||||
|
||||
API
|
||||
(Application Program Interface) A defined set of routines and protocols for
|
||||
building application software.
|
||||
|
||||
application
|
||||
The set of user-supplied files that the Zephyr build system uses
|
||||
to build an application image for a specified board configuration.
|
||||
It can contain application-specific code, kernel configuration settings,
|
||||
and at least one Makefile.
|
||||
The application's kernel configuration settings direct the build system
|
||||
to create a custom kernel that makes efficient use of the board's
|
||||
resources.
|
||||
An application can sometimes be built for more than one type of board
|
||||
configuration (including boards with different CPU architectures),
|
||||
if it does not require any board-specific capabilities.
|
||||
|
||||
application image
|
||||
A binary file that is loaded and executed by the board for which
|
||||
it was built.
|
||||
Each application image contains both the application's code and the
|
||||
Zephyr kernel code needed to support it. They are compiled as a single,
|
||||
fully-linked binary.
|
||||
Once an application image is loaded onto a board, the image takes control
|
||||
of the system, initializes it, and runs as the system's sole application.
|
||||
Both application code and kernel code execute as privileged code
|
||||
within a single shared address space.
|
||||
|
||||
board
|
||||
A target system with a defined set of devices and capabilities,
|
||||
which can load and execute an application image. It may be an actual
|
||||
hardware system or a simulated system running under QEMU.
|
||||
The Zephyr kernel supports a :ref:`variety of boards <boards>`.
|
||||
|
||||
board configuration
|
||||
A set of kernel configuration options that specify how the devices
|
||||
present on a board are used by the kernel.
|
||||
The Zephyr build system defines one or more board configurations
|
||||
for each board it supports. The kernel configuration settings that are
|
||||
specified by the build system can be over-ridden by the application,
|
||||
if desired.
|
||||
|
||||
IDT
|
||||
(Interrupt Descriptor Table) a data structure used by the x86
|
||||
architecture to implement an interrupt vector table. The IDT is used
|
||||
to determine the correct response to interrupts and exceptions.
|
||||
|
||||
ISR
|
||||
(Interrupt Service Routine) Also known as an interrupt handler, an ISR
|
||||
is a callback function whose execution is triggered by a hardware
|
||||
interrupt (or software interrupt instructions) and is used to handle
|
||||
high-priority conditions that require interrupting the current code
|
||||
executing on the processor.
|
||||
|
||||
kernel
|
||||
The set of Zephyr-supplied files that implement the Zephyr kernel,
|
||||
including its core services, device drivers, network stack, and so on.
|
||||
|
||||
XIP
|
||||
(eXecute In Place) a method of executing programs directly from long
|
||||
term storage rather than copying it into RAM, saving writable memory for
|
||||
dynamic data and not the staic program code.
|
||||
@@ -42,6 +42,7 @@ Sections
|
||||
contribute/code.rst
|
||||
release-notes.rst
|
||||
LICENSING.rst
|
||||
glossary.rst
|
||||
|
||||
You can find further information on the `Zephyr Project Wiki`_.
|
||||
|
||||
@@ -53,6 +54,7 @@ Indices and Tables
|
||||
* :ref:`search`
|
||||
|
||||
.. _Zephyr Project Wiki: https://wiki.zephyrproject.org/view/Main_Page
|
||||
.. _Zephyr 1.7.0: https://www.zephyrproject.org/doc/1.7.0/
|
||||
.. _Zephyr 1.6.0: https://www.zephyrproject.org/doc/1.6.0/
|
||||
.. _Zephyr 1.5.0: https://www.zephyrproject.org/doc/1.5.0/
|
||||
.. _Zephyr 1.4.0: https://www.zephyrproject.org/doc/1.4.0/
|
||||
|
||||
@@ -64,50 +64,4 @@ small-footprint OSes:
|
||||
Fundamental Terms and Concepts
|
||||
******************************
|
||||
|
||||
This section outlines the basic terms used by the Zephyr kernel ecosystem.
|
||||
|
||||
:dfn:`kernel`
|
||||
The set of Zephyr-supplied files that implement the Zephyr kernel,
|
||||
including its core services, device drivers, network stack, and so on.
|
||||
|
||||
:dfn:`application`
|
||||
The set of user-supplied files that the Zephyr build system uses
|
||||
to build an application image for a specified board configuration.
|
||||
It can contain application-specific code, kernel configuration settings,
|
||||
and at least one Makefile.
|
||||
|
||||
The application's kernel configuration settings direct the build system
|
||||
to create a custom kernel that makes efficient use of the board's resources.
|
||||
|
||||
An application can sometimes be built for more than one type of board
|
||||
configuration (including boards with different CPU architectures),
|
||||
if it does not require any board-specific capabilities.
|
||||
|
||||
:dfn:`application image`
|
||||
A binary file that is loaded and executed by the board for which
|
||||
it was built.
|
||||
|
||||
Each application image contains both the application's code and the
|
||||
Zephyr kernel code needed to support it. They are compiled as a single,
|
||||
fully-linked binary.
|
||||
|
||||
Once an application image is loaded onto a board, the image takes control
|
||||
of the system, initializes it, and runs as the system's sole application.
|
||||
Both application code and kernel code execute as privileged code
|
||||
within a single shared address space.
|
||||
|
||||
:dfn:`board`
|
||||
A target system with a defined set of devices and capabilities,
|
||||
which can load and execute an application image. It may be an actual
|
||||
hardware system or a simulated system running under QEMU.
|
||||
|
||||
The Zephyr kernel supports a :ref:`variety of boards <boards>`.
|
||||
|
||||
:dfn:`board configuration`
|
||||
A set of kernel configuration options that specify how the devices
|
||||
present on a board are used by the kernel.
|
||||
|
||||
The Zephyr build system defines one or more board configurations
|
||||
for each board it supports. The kernel configuration settings that are
|
||||
specified by the build system can be over-ridden by the application,
|
||||
if desired.
|
||||
See :ref:`glossary`
|
||||
|
||||
@@ -9,8 +9,9 @@ This section describes other services provided by the kernel.
|
||||
:maxdepth: 1
|
||||
|
||||
interrupts.rst
|
||||
cpu_idle.rst
|
||||
atomic.rst
|
||||
float.rst
|
||||
polling.rst
|
||||
ring_buffers.rst
|
||||
float.rst
|
||||
cxx_support.rst
|
||||
cpu_idle.rst
|
||||
|
||||
291
doc/kernel/other/polling.rst
Normal file
291
doc/kernel/other/polling.rst
Normal file
@@ -0,0 +1,291 @@
|
||||
.. _polling_v2:
|
||||
|
||||
Polling API
|
||||
###########
|
||||
|
||||
The polling API is used to wait concurrently for any one of multiple conditions
|
||||
to be fulfilled.
|
||||
|
||||
.. contents::
|
||||
:local:
|
||||
:depth: 2
|
||||
|
||||
Concepts
|
||||
********
|
||||
|
||||
The polling API's main function is :cpp:func:`k_poll()`, which is very similar
|
||||
in concept to the POSIX :cpp:func:`poll()` function, except that it operates on
|
||||
kernel objects rather than on file descriptors.
|
||||
|
||||
The polling API allows a single thread to wait concurrently for one or more
|
||||
conditions to be fulfilled without actively looking at each one individually.
|
||||
|
||||
There is a limited set of such conditions:
|
||||
|
||||
- a semaphore becomes available
|
||||
- a kernel FIFO contains data ready to be retrieved
|
||||
- a poll signal is raised
|
||||
|
||||
A thread that wants to wait on multiple conditions must define an array of
|
||||
**poll events**, one for each condition.
|
||||
|
||||
All events in the array must be initialized before the array can be polled on.
|
||||
|
||||
Each event must specify which **type** of condition must be satisfied so that
|
||||
its state is changed to signal the requested condition has been met.
|
||||
|
||||
Each event must specify what **kernel object** it wants the condition to be
|
||||
satisfied.
|
||||
|
||||
Each event must specify which **mode** of operation is used when the condition
|
||||
is satisfied.
|
||||
|
||||
Each event can optionally specify a **tag** to group multiple events together,
|
||||
to the user's discretion.
|
||||
|
||||
Apart from the kernel objects, there is also a **poll signal** pseudo-object
|
||||
type that be directly signaled.
|
||||
|
||||
The :cpp:func:`k_poll()` function returns as soon as one of the conditions it
|
||||
is waiting for is fulfilled. It is possible for more than one to be fulfilled
|
||||
when :cpp:func:`k_poll()` returns, if they were fulfilled before
|
||||
:cpp:func:`k_poll()` was called, or due to the preemptive multi-threading
|
||||
nature of the kernel. The caller must look at the state of all the poll events
|
||||
in the array to figured out which ones were fulfilled and what actions to take.
|
||||
|
||||
Currently, there is only one mode of operation available: the object is not
|
||||
acquired. As an example, this means that when :cpp:func:`k_poll()` returns and
|
||||
the poll event states that the semaphore is available, the caller of
|
||||
:cpp:func:`k_poll()` must then invoke :cpp:func:`k_sem_take()` to take
|
||||
ownership of the semaphore. If the semaphore is contested, there is no
|
||||
guarantee that it will be still available when :cpp:func:`k_sem_give()` is
|
||||
called.
|
||||
|
||||
Implementatioe
|
||||
**************
|
||||
|
||||
Using k_poll()
|
||||
==============
|
||||
|
||||
The main API is :cpp:func:`k_poll()`, which operates on an array of poll events
|
||||
of type :c:type:`struct k_poll_event`. Each entry in the array represents one
|
||||
event a call to :cpp:func:`k_poll()` will wait for its condition to be
|
||||
fulfilled.
|
||||
|
||||
They can be initialized using either the runtime initializers
|
||||
:c:macro:`K_POLL_EVENT_INITIALIZER()` or :cpp:func:`k_poll_event_init()`, or
|
||||
the static initializer :c:macro:`K_POLL_EVENT_STATIC_INITIALIZER()`. An object
|
||||
that matches the **type** specified must be passed to the initializers. The
|
||||
**mode** *must* be set to :c:macro:`K_POLL_MODE_NOTIFY_ONLY`. The state *must*
|
||||
be set to :c:macro:`K_POLL_STATE_NOT_READY` (the initializers take care of
|
||||
this). The user **tag** is optional and completely opaque to the API: it is
|
||||
there to help a user to group similar events together. Being optional, it is
|
||||
passed to the static initializer, but not the runtime ones for performance
|
||||
reasons. If using runtime initializers, the user must set it separately in the
|
||||
:c:type:`struct k_poll_event` data structure. If an event in the array is to be
|
||||
ignored, most likely temporarily, its type can be set to K_POLL_TYPE_IGNORE.
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
struct k_poll_event events[2] = {
|
||||
K_POLL_EVENT_STATIC_INITIALIZER(K_POLL_TYPE_SEM_AVAILABLE,
|
||||
K_POLL_MODE_NOTIFY_ONLY,
|
||||
&my_sem, 0),
|
||||
K_POLL_EVENT_STATIC_INITIALIZER(K_POLL_TYPE_FIFO_DATA_AVAILABLE,
|
||||
K_POLL_MODE_NOTIFY_ONLY,
|
||||
&my_fifo, 0),
|
||||
};
|
||||
|
||||
or at runtime
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
struct k_poll_event events[2];
|
||||
void some_init(void)
|
||||
{
|
||||
k_poll_event_init(K_POLL_TYPE_SEM_AVAILABLE,
|
||||
K_POLL_MODE_NOTIFY_ONLY,
|
||||
&my_sem);
|
||||
|
||||
k_poll_event_init(K_POLL_TYPE_FIFO_DATA_AVAILABLE,
|
||||
K_POLL_MODE_NOTIFY_ONLY,
|
||||
&my_fifo);
|
||||
|
||||
// tags are left uninitialized if unused
|
||||
}
|
||||
|
||||
|
||||
After the events are initialized, the array can be passed to
|
||||
:cpp:func:`k_poll()`. A timeout can be specified to wait only for a specified
|
||||
amount of time, or the special values :c:macro:`K_NO_WAIT` and
|
||||
:c:macro:`K_FOREVER` to either not wait or wait until an event condition is
|
||||
satisfied and not sooner.
|
||||
|
||||
Only one thread can poll on a semaphore or a FIFO at a time. If a second thread
|
||||
tries to poll on the same semaphore or FIFO, :cpp:func:`k_poll()` immediately
|
||||
returns with the return value :c:macro:`-EADDRINUSE`. In that case, if other
|
||||
conditions passed to :cpp:func:`k_poll` were met, their state will be set in
|
||||
the corresponding poll event.
|
||||
|
||||
In case of success, :cpp:func:`k_poll()` returns 0. If it times out, it returns
|
||||
:c:macro:`-EAGAIN`.
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
// assume there is no contention on this semaphore and FIFO
|
||||
// -EADDRINUSE will not occur; the semaphore and/or data will be available
|
||||
|
||||
void do_stuff(void)
|
||||
{
|
||||
rc = k_poll(events, 2, 1000);
|
||||
if (rc == 0) {
|
||||
if (events[0].state == K_POLL_STATE_SEM_AVAILABLE) {
|
||||
k_sem_take(events[0].sem, 0);
|
||||
} else if (events[1].state == K_POLL_STATE_FIFO_DATA_AVAILABLE) {
|
||||
data = k_fifo_get(events[1].fifo, 0);
|
||||
// handle data
|
||||
}
|
||||
} else {
|
||||
// handle timeout
|
||||
}
|
||||
}
|
||||
|
||||
When :cpp:func:`k_poll()` is called in a loop, the events state must be reset
|
||||
to :c:macro:`K_POLL_STATE_NOT_READY` by the user.
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
void do_stuff(void)
|
||||
{
|
||||
for(;;) {
|
||||
rc = k_poll(events, 2, K_FOREVER);
|
||||
if (events[0].state == K_POLL_STATE_SEM_AVAILABLE) {
|
||||
k_sem_take(events[0].sem, 0);
|
||||
} else if (events[1].state == K_POLL_STATE_FIFO_DATA_AVAILABLE) {
|
||||
data = k_fifo_get(events[1].fifo, 0);
|
||||
// handle data
|
||||
}
|
||||
events[0].state = K_POLL_STATE_NOT_READY;
|
||||
events[1].state = K_POLL_STATE_NOT_READY;
|
||||
}
|
||||
}
|
||||
|
||||
Using k_poll_signal()
|
||||
=====================
|
||||
|
||||
One of the types of events is :c:macro:`K_POLL_TYPE_SIGNAL`: this is a "direct"
|
||||
signal to a poll event. This can be seen as a lightweight binary semaphore only
|
||||
one thread can wait for.
|
||||
|
||||
A poll signal is a separate object of type :c:type:`struct k_poll_signal` that
|
||||
must be attached to a k_poll_event, similar to a semaphore or FIFO. It must
|
||||
first be initialized either via :c:macro:`K_POLL_SIGNAL_INITIALIZER()` or
|
||||
:cpp:func:`k_poll_signal_init()`.
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
struct k_poll_signal signal;
|
||||
void do_stuff(void)
|
||||
{
|
||||
k_poll_signal_init(&signal);
|
||||
}
|
||||
|
||||
It is signaled via the :cpp:func:`k_poll_signal()` function. This function
|
||||
takes a user **result** parameter that is opaque to the API and can be used to
|
||||
pass extra information to the thread waiting on the event.
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
struct k_poll_signal signal;
|
||||
|
||||
// thread A
|
||||
void do_stuff(void)
|
||||
{
|
||||
k_poll_signal_init(&signal);
|
||||
|
||||
struct k_poll_event events[1] = {
|
||||
K_POLL_EVENT_INITIALIZER(K_POLL_TYPE_SIGNAL,
|
||||
K_POLL_MODE_NOTIFY_ONLY,
|
||||
&signal);
|
||||
};
|
||||
|
||||
k_poll(events, 1, K_FOREVER);
|
||||
|
||||
if (events.signal->result == 0x1337) {
|
||||
// A-OK!
|
||||
} else {
|
||||
// weird error
|
||||
}
|
||||
}
|
||||
|
||||
// thread B
|
||||
void signal_do_stuff(void)
|
||||
{
|
||||
k_poll_signal(&signal, 0x1337);
|
||||
}
|
||||
|
||||
If the signal is to be polled in a loop, *both* its event state and its
|
||||
**signaled** field *must* be reset on each iteration if it has been signaled.
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
struct k_poll_signal signal;
|
||||
void do_stuff(void)
|
||||
{
|
||||
k_poll_signal_init(&signal);
|
||||
|
||||
struct k_poll_event events[1] = {
|
||||
K_POLL_EVENT_INITIALIZER(K_POLL_TYPE_SIGNAL,
|
||||
K_POLL_MODE_NOTIFY_ONLY,
|
||||
&signal);
|
||||
};
|
||||
|
||||
for (;;) {
|
||||
k_poll(events, 1, K_FOREVER);
|
||||
|
||||
if (events[0].signal->result == 0x1337) {
|
||||
// A-OK!
|
||||
} else {
|
||||
// weird error
|
||||
}
|
||||
|
||||
events[0].signal->signaled = 0;
|
||||
events[0].state = K_POLL_STATE_NOT_READY;
|
||||
}
|
||||
}
|
||||
|
||||
Suggested Uses
|
||||
**************
|
||||
|
||||
Use :cpp:func:`k_poll()` to consolidate multiple threads that would be pending
|
||||
on one object each, saving possibly large amounts of stack space.
|
||||
|
||||
Use a poll signal as a lightweight binary semaphore if only one thread pends on
|
||||
it.
|
||||
|
||||
.. note::
|
||||
Because objects are only signaled if no other thread is waiting for them to
|
||||
become available and only one thread can poll on a specific object, polling
|
||||
is best used when objects are not subject of contention between multiple
|
||||
threads, basicallly when a single thread operates as a main "server" or
|
||||
"dispatcher" for multiple objects and is the only one trying to acquire
|
||||
these objects.
|
||||
|
||||
Configuration Options
|
||||
*********************
|
||||
|
||||
Related configuration options:
|
||||
|
||||
* :option:`CONFIG_POLL`
|
||||
|
||||
APIs
|
||||
****
|
||||
|
||||
The following polling APIs are provided by :file:`kernel.h`:
|
||||
|
||||
* :c:macro:`K_POLL_EVENT_INITIALIZER`
|
||||
* :c:macro:`K_POLL_EVENT_STATIC_INITIALIZER`
|
||||
* :cpp:func:`k_poll_event_init()`
|
||||
* :cpp:func:`k_poll()`
|
||||
* :cpp:func:`k_poll_signal_init()`
|
||||
* :cpp:func:`k_poll_signal()`
|
||||
@@ -1,17 +0,0 @@
|
||||
.. _glossary_v2:
|
||||
|
||||
Glossary of Terms [TBD]
|
||||
#######################
|
||||
|
||||
API (Application Program Interface)
|
||||
A defined set of routines and protocols for building software inputs
|
||||
and output mechanisms.
|
||||
|
||||
IDT (Interrupt Descriptor Table)
|
||||
[TBD]
|
||||
|
||||
ISR (Interrupt Service Routine)
|
||||
[TBD]
|
||||
|
||||
XIP (eXecute In Place)
|
||||
[TBD]
|
||||
@@ -25,5 +25,4 @@ include: fitness wearables, smart watches, and IoT wireless gateways.
|
||||
:maxdepth: 1
|
||||
|
||||
source_tree.rst
|
||||
glossary.rst
|
||||
changes.rst
|
||||
|
||||
@@ -286,8 +286,8 @@ static int stm32f10x_clock_control_init(struct device *dev)
|
||||
pllmul(CONFIG_CLOCK_STM32F10X_CONN_LINE_PLL_MULTIPLIER);
|
||||
#endif /* CONFIG_CLOCK_STM32F10X_CONN_LINE_PLL_MULTIPLIER */
|
||||
#ifdef CONFIG_CLOCK_STM32F10X_CONN_LINE_PLL2_MULTIPLIER
|
||||
uint32_t pll2mul =
|
||||
pllmul(CLOCK_STM32F10X_CONN_LINE_PLL2_MULTIPLIER);
|
||||
uint32_t pll2_mul =
|
||||
pll2mul(CONFIG_CLOCK_STM32F10X_CONN_LINE_PLL2_MULTIPLIER);
|
||||
#endif /* CONFIG_CLOCK_STM32F10X_CONN_LINE_PLL2_MULTIPLIER */
|
||||
#ifdef CONFIG_CLOCK_STM32F10X_CONN_LINE_PREDIV1
|
||||
uint32_t prediv1 =
|
||||
@@ -341,7 +341,14 @@ static int stm32f10x_clock_control_init(struct device *dev)
|
||||
rcc->cfgr2.bit.prediv1src = STM32F10X_RCC_CFG2_PREDIV1_SRC_PLL2;
|
||||
|
||||
rcc->cfgr2.bit.prediv2 = prediv2;
|
||||
rcc->cfgr2.bit.pll2mul = pll2mul;
|
||||
rcc->cfgr2.bit.pll2mul = pll2_mul;
|
||||
|
||||
/* enable PLL2 */
|
||||
rcc->cr.bit.pll2on = 1;
|
||||
|
||||
/* wait for PLL to become ready */
|
||||
while (rcc->cr.bit.pll2rdy != 1) {
|
||||
}
|
||||
|
||||
#endif /* CONFIG_CLOCK_STM32F10X_CONN_LINE_PREDIV1_SRC_HSE */
|
||||
#endif /* CONFIG_CLOCK_STM32F10X_CONN_LINE_PLL_SRC_PREDIV1 */
|
||||
|
||||
@@ -684,7 +684,8 @@ static void eth_enc28j60_iface_init_0(struct net_if *iface)
|
||||
|
||||
SYS_LOG_DBG("");
|
||||
|
||||
net_if_set_link_addr(iface, mac_address_0, sizeof(mac_address_0));
|
||||
net_if_set_link_addr(iface, mac_address_0, sizeof(mac_address_0),
|
||||
NET_LINK_ETHERNET);
|
||||
context->iface = iface;
|
||||
}
|
||||
|
||||
|
||||
@@ -474,7 +474,8 @@ static void eth_0_iface_init(struct net_if *iface)
|
||||
struct eth_context *context = dev->driver_data;
|
||||
|
||||
net_if_set_link_addr(iface, context->mac_addr,
|
||||
sizeof(context->mac_addr));
|
||||
sizeof(context->mac_addr),
|
||||
NET_LINK_ETHERNET);
|
||||
context->iface = iface;
|
||||
}
|
||||
|
||||
|
||||
@@ -749,7 +749,8 @@ static void eth0_iface_init(struct net_if *iface)
|
||||
|
||||
/* Register Ethernet MAC Address with the upper layer */
|
||||
net_if_set_link_addr(iface, dev_data->mac_addr,
|
||||
sizeof(dev_data->mac_addr));
|
||||
sizeof(dev_data->mac_addr),
|
||||
NET_LINK_ETHERNET);
|
||||
|
||||
dev_data->iface = iface;
|
||||
}
|
||||
|
||||
@@ -335,15 +335,42 @@ GPIO_DEVICE_INIT("GPIOE", e, GPIOE_BASE, STM32_PORTE,
|
||||
|
||||
#ifdef CONFIG_GPIO_STM32_PORTF
|
||||
GPIO_DEVICE_INIT("GPIOF", f, GPIOF_BASE, STM32_PORTF,
|
||||
STM32_PERIPH_GPIOF, STM32_CLOCK_BUS_GPIO);
|
||||
#ifdef CONFIG_CLOCK_CONTROL_STM32_CUBE
|
||||
STM32_PERIPH_GPIOF, STM32_CLOCK_BUS_GPIO
|
||||
#else
|
||||
#ifdef CONFIG_SOC_SERIES_STM32F1X
|
||||
STM32F10X_CLOCK_SUBSYS_IOPF
|
||||
| STM32F10X_CLOCK_SUBSYS_AFIO
|
||||
#elif CONFIG_SOC_SERIES_STM32F4X
|
||||
STM32F4X_CLOCK_ENABLE_GPIOF
|
||||
#endif
|
||||
#endif /* CONFIG_CLOCK_CONTROL_STM32_CUBE */
|
||||
);
|
||||
#endif /* CONFIG_GPIO_STM32_PORTF */
|
||||
|
||||
#ifdef CONFIG_GPIO_STM32_PORTG
|
||||
GPIO_DEVICE_INIT("GPIOG", g, GPIOG_BASE, STM32_PORTG,
|
||||
STM32_PERIPH_GPIOG, STM32_CLOCK_BUS_GPIO);
|
||||
#ifdef CONFIG_CLOCK_CONTROL_STM32_CUBE
|
||||
STM32_PERIPH_GPIOG, STM32_CLOCK_BUS_GPIO
|
||||
#else
|
||||
#ifdef CONFIG_SOC_SERIES_STM32F1X
|
||||
STM32F10X_CLOCK_SUBSYS_IOPG
|
||||
| STM32F10X_CLOCK_SUBSYS_AFIO
|
||||
#elif CONFIG_SOC_SERIES_STM32F4X
|
||||
STM32F4X_CLOCK_ENABLE_GPIOG
|
||||
#endif
|
||||
#endif /* CONFIG_CLOCK_CONTROL_STM32_CUBE */
|
||||
);
|
||||
#endif /* CONFIG_GPIO_STM32_PORTG */
|
||||
|
||||
#ifdef CONFIG_GPIO_STM32_PORTH
|
||||
GPIO_DEVICE_INIT("GPIOH", h, GPIOH_BASE, STM32_PORTH,
|
||||
STM32_PERIPH_GPIOH, STM32_CLOCK_BUS_GPIO);
|
||||
#ifdef CONFIG_CLOCK_CONTROL_STM32_CUBE
|
||||
STM32_PERIPH_GPIOH, STM32_CLOCK_BUS_GPIO
|
||||
#else
|
||||
#ifdef CONFIG_SOC_SERIES_STM32F4X
|
||||
STM32F4X_CLOCK_ENABLE_GPIOH
|
||||
#endif
|
||||
#endif /* CONFIG_CLOCK_CONTROL_STM32_CUBE */
|
||||
);
|
||||
#endif /* CONFIG_GPIO_STM32_PORTH */
|
||||
|
||||
@@ -58,6 +58,8 @@ source "drivers/ieee802154/Kconfig.cc2520"
|
||||
|
||||
source "drivers/ieee802154/Kconfig.mcr20a"
|
||||
|
||||
source "drivers/ieee802154/Kconfig.nrf5"
|
||||
|
||||
menuconfig IEEE802154_UPIPE
|
||||
bool "UART PIPE fake radio driver support for QEMU"
|
||||
depends on BOARD_QEMU_X86
|
||||
|
||||
72
drivers/ieee802154/Kconfig.nrf5
Normal file
72
drivers/ieee802154/Kconfig.nrf5
Normal file
@@ -0,0 +1,72 @@
|
||||
# Kconfig.nrf5 - Nordic Semiconductor nRF5 802.15.4 configuration options
|
||||
#
|
||||
|
||||
menuconfig IEEE802154_NRF5
|
||||
bool "nRF52 series IEEE 802.15.4 Driver support"
|
||||
depends on NETWORKING && SOC_NRF52840
|
||||
select NET_L2_IEEE802154
|
||||
select HAS_NORDIC_DRIVERS
|
||||
default n
|
||||
|
||||
if IEEE802154_NRF5 || IEEE802154_NRF5_RAW
|
||||
|
||||
config IEEE802154_NRF5_DRV_NAME
|
||||
string "nRF52 IEEE 802.15.4 Driver's name"
|
||||
default "IEEE802154_nrf5"
|
||||
help
|
||||
This option sets the driver name
|
||||
|
||||
config IEEE802154_NRF5_RX_STACK_SIZE
|
||||
int "Driver's internal rx thread stack size"
|
||||
default 800
|
||||
help
|
||||
This option sets the driver's stack size for its internal rx thread.
|
||||
The default value should be sufficient, but in case it proves to be
|
||||
a too little one, this option makes it easy to play with the size.
|
||||
|
||||
config IEEE802154_NRF5_INIT_PRIO
|
||||
int "nRF52 IEEE 802.15.4 intialization priority"
|
||||
default 80
|
||||
help
|
||||
Set the initialization priority number. Do not mess with it unless
|
||||
you know what you are doing.
|
||||
|
||||
choice IEEE802154_NRF5_CCA_MODE
|
||||
prompt "nRF52 IEEE 802.15.4 CCA mode"
|
||||
default IEEE802154_NRF5_CCA_MODE_ED
|
||||
help
|
||||
CCA mode
|
||||
|
||||
config IEEE802154_NRF5_CCA_MODE_ED
|
||||
bool "Energy Above Threashold"
|
||||
|
||||
config IEEE802154_NRF5_CCA_MODE_CARRIER
|
||||
bool "Carrier Seen"
|
||||
|
||||
config IEEE802154_NRF5_CCA_MODE_CARRIER_AND_ED
|
||||
bool "Energy Above Threshold AND Carrier Seen"
|
||||
|
||||
config IEEE802154_NRF5_CCA_MODE_CARRIER_OR_ED
|
||||
bool "Energy Above Threshold OR Carrier Seen"
|
||||
|
||||
endchoice
|
||||
|
||||
config IEEE802154_NRF5_CCA_ED_THRESHOLD
|
||||
int "nRF52 IEEE 802.15.4 CCA Energy Detection threshold"
|
||||
default 45
|
||||
help
|
||||
If energy detected in a given channel is above the value then the channel
|
||||
is deemed busy. The unit is defined as per 802.15.4-2006 spec.
|
||||
|
||||
config IEEE802154_NRF5_CCA_CORR_THRESHOLD
|
||||
int "nRF52 IEEE 802.15.4 CCA Correlator threshold"
|
||||
default 45
|
||||
|
||||
config IEEE802154_NRF5_CCA_CORR_LIMIT
|
||||
int "nRF52 IEEE 802.15.4 CCA Correlator limit"
|
||||
default 2
|
||||
help
|
||||
Limit for occurrences above correlator threshold. When not equal to zero the
|
||||
corrolator based signal detect is enabled.
|
||||
|
||||
endif
|
||||
@@ -3,3 +3,4 @@ obj-$(CONFIG_IEEE802154_CC2520_RAW) += ieee802154_cc2520.o
|
||||
obj-$(CONFIG_IEEE802154_UPIPE) += ieee802154_uart_pipe.o
|
||||
obj-$(CONFIG_IEEE802154_MCR20A) += ieee802154_mcr20a.o
|
||||
obj-$(CONFIG_IEEE802154_MCR20A_RAW) += ieee802154_mcr20a.o
|
||||
obj-$(CONFIG_IEEE802154_NRF5) += ieee802154_nrf5.o
|
||||
|
||||
@@ -1056,7 +1056,7 @@ static void cc2520_iface_init(struct net_if *iface)
|
||||
|
||||
SYS_LOG_DBG("");
|
||||
|
||||
net_if_set_link_addr(iface, mac, 8);
|
||||
net_if_set_link_addr(iface, mac, 8, NET_LINK_IEEE802154);
|
||||
|
||||
cc2520->iface = iface;
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -36,13 +36,13 @@ struct mcr20a_context {
|
||||
struct gpio_callback irqb_cb;
|
||||
struct mcr20a_spi spi;
|
||||
uint8_t mac_addr[8];
|
||||
struct k_mutex phy_mutex;
|
||||
struct k_sem isr_sem;
|
||||
/*********TX + CCA*********/
|
||||
struct k_sem seq_sync;
|
||||
atomic_t busy;
|
||||
atomic_t seq_retval;
|
||||
/************RX************/
|
||||
char __stack mcr20a_rx_stack[CONFIG_IEEE802154_MCR20A_RX_STACK_SIZE];
|
||||
struct k_sem trig_sem;
|
||||
uint8_t lqi;
|
||||
};
|
||||
|
||||
@@ -174,6 +174,8 @@ DEFINE_BURST_WRITE(t3cmp, MCR20A_T3CMP_LSB, 3, true)
|
||||
DEFINE_BURST_WRITE(t4cmp, MCR20A_T4CMP_LSB, 3, true)
|
||||
DEFINE_BURST_WRITE(t2primecmp, MCR20A_T2PRIMECMP_LSB, 2, true)
|
||||
DEFINE_BURST_WRITE(pll_int0, MCR20A_PLL_INT0, 3, true)
|
||||
DEFINE_BURST_WRITE(irqsts1_irqsts3, MCR20A_IRQSTS1, 3, true)
|
||||
DEFINE_BURST_WRITE(irqsts1_ctrl1, MCR20A_IRQSTS1, 4, true)
|
||||
|
||||
DEFINE_BURST_WRITE(pan_id, MCR20A_MACPANID0_LSB, 2, false)
|
||||
DEFINE_BURST_WRITE(short_addr, MCR20A_MACSHORTADDRS0_LSB, 2, false)
|
||||
|
||||
411
drivers/ieee802154/ieee802154_nrf5.c
Normal file
411
drivers/ieee802154/ieee802154_nrf5.c
Normal file
@@ -0,0 +1,411 @@
|
||||
/* ieee802154_nrf5.c - nRF5 802.15.4 driver */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2017 Nordic Semiconductor ASA
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#define SYS_LOG_LEVEL CONFIG_SYS_LOG_IEEE802154_DRIVER_LEVEL
|
||||
#define SYS_LOG_DOMAIN "dev/nrf5_802154"
|
||||
#include <logging/sys_log.h>
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#include <kernel.h>
|
||||
#include <arch/cpu.h>
|
||||
|
||||
#include <board.h>
|
||||
#include <device.h>
|
||||
#include <init.h>
|
||||
#include <net/net_if.h>
|
||||
#include <net/nbuf.h>
|
||||
|
||||
#include <misc/byteorder.h>
|
||||
#include <string.h>
|
||||
#include <rand32.h>
|
||||
|
||||
#include <net/ieee802154_radio.h>
|
||||
#include <drivers/clock_control/nrf5_clock_control.h>
|
||||
#include <clock_control.h>
|
||||
|
||||
#include "nrf52840.h"
|
||||
#include "ieee802154_nrf5.h"
|
||||
#include "nrf_drv_radio802154.h"
|
||||
|
||||
struct nrf5_802154_config {
|
||||
void (*irq_config_func)(struct device *dev);
|
||||
};
|
||||
|
||||
static struct nrf5_802154_data nrf5_data;
|
||||
|
||||
/* Convenience defines for RADIO */
|
||||
#define NRF5_802154_DATA(dev) \
|
||||
((struct nrf5_802154_data * const)(dev)->driver_data)
|
||||
|
||||
#define NRF5_802154_CFG(dev) \
|
||||
((struct nrf5_802154_config * const)(dev)->config->config_info)
|
||||
|
||||
static void nrf5_get_eui64(uint8_t *mac)
|
||||
{
|
||||
memcpy(mac, (const uint32_t *)&NRF_FICR->DEVICEID, 8);
|
||||
}
|
||||
|
||||
static void nrf5_rx_thread(void *arg1, void *arg2, void *arg3)
|
||||
{
|
||||
struct device *dev = (struct device *)arg1;
|
||||
struct nrf5_802154_data *nrf5_radio = NRF5_802154_DATA(dev);
|
||||
struct net_buf *pkt_buf = NULL;
|
||||
enum net_verdict ack_result;
|
||||
struct net_buf *buf;
|
||||
uint8_t pkt_len;
|
||||
|
||||
ARG_UNUSED(arg2);
|
||||
ARG_UNUSED(arg3);
|
||||
|
||||
while (1) {
|
||||
buf = NULL;
|
||||
|
||||
SYS_LOG_DBG("Waiting for frame");
|
||||
k_sem_take(&nrf5_radio->rx_wait, K_FOREVER);
|
||||
|
||||
SYS_LOG_DBG("Frame received");
|
||||
|
||||
buf = net_nbuf_get_reserve_rx(0, K_NO_WAIT);
|
||||
if (!buf) {
|
||||
SYS_LOG_ERR("No buf available");
|
||||
goto out;
|
||||
}
|
||||
|
||||
pkt_buf = net_nbuf_get_reserve_data(0, K_NO_WAIT);
|
||||
if (!pkt_buf) {
|
||||
SYS_LOG_ERR("No pkt_buf available");
|
||||
goto out;
|
||||
}
|
||||
|
||||
net_buf_frag_insert(buf, pkt_buf);
|
||||
|
||||
/* rx_mpdu contains length, psdu, [fcs], lqi
|
||||
* FCS filed (2 bytes) is not present if CRC is enabled
|
||||
*/
|
||||
pkt_len = nrf5_radio->rx_psdu[0] - NRF5_FCS_LENGTH;
|
||||
|
||||
/* Skip length (first byte) and copy the payload */
|
||||
memcpy(pkt_buf->data, nrf5_radio->rx_psdu + 1, pkt_len);
|
||||
net_buf_add(pkt_buf, pkt_len);
|
||||
|
||||
nrf_drv_radio802154_buffer_free(nrf5_radio->rx_psdu);
|
||||
|
||||
ack_result = ieee802154_radio_handle_ack(nrf5_radio->iface,
|
||||
buf);
|
||||
if (ack_result == NET_OK) {
|
||||
SYS_LOG_DBG("ACK packet handled");
|
||||
goto out;
|
||||
}
|
||||
|
||||
SYS_LOG_DBG("Caught a packet (%u) (LQI: %u)",
|
||||
pkt_len, nrf5_radio->lqi);
|
||||
|
||||
if (net_recv_data(nrf5_radio->iface, buf) < 0) {
|
||||
SYS_LOG_DBG("Packet dropped by NET stack");
|
||||
goto out;
|
||||
}
|
||||
|
||||
net_analyze_stack("nRF5 rx stack",
|
||||
(unsigned char *)nrf5_radio->rx_stack,
|
||||
CONFIG_IEEE802154_NRF5_RX_STACK_SIZE);
|
||||
continue;
|
||||
|
||||
out:
|
||||
if (buf) {
|
||||
net_buf_unref(buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Radio device API */
|
||||
|
||||
static int nrf5_cca(struct device *dev)
|
||||
{
|
||||
struct nrf5_802154_data *nrf5_radio = NRF5_802154_DATA(dev);
|
||||
|
||||
/* Current implementation of the NRF5 radio driver doesn't provide an
|
||||
* explicit API to perform CCA. However, Mode1 CCA (energy above
|
||||
* threshold), can be achieved using energy detection function.
|
||||
*/
|
||||
if (!nrf_drv_radio802154_energy_detection(nrf5_radio->channel, 128)) {
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
/* The nRF driver guarantees that a callback will be called once
|
||||
* the ED function is done, thus unlocking the semaphore.
|
||||
*/
|
||||
k_sem_take(&nrf5_radio->cca_wait, K_FOREVER);
|
||||
SYS_LOG_DBG("CCA: %d", nrf5_radio->channel_ed);
|
||||
|
||||
if (nrf5_radio->channel_ed > CONFIG_IEEE802154_NRF5_CCA_ED_THRESHOLD) {
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nrf5_set_channel(struct device *dev, uint16_t channel)
|
||||
{
|
||||
struct nrf5_802154_data *nrf5_radio = NRF5_802154_DATA(dev);
|
||||
|
||||
SYS_LOG_DBG("%u", channel);
|
||||
|
||||
if (channel < 11 || channel > 26) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!nrf_drv_radio802154_receive(channel, false)) {
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
nrf5_radio->channel = channel;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nrf5_set_pan_id(struct device *dev, uint16_t pan_id)
|
||||
{
|
||||
uint8_t pan_id_le[2];
|
||||
|
||||
ARG_UNUSED(dev);
|
||||
|
||||
sys_put_le16(pan_id, pan_id_le);
|
||||
nrf_drv_radio802154_pan_id_set(pan_id_le);
|
||||
|
||||
SYS_LOG_DBG("0x%x", pan_id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nrf5_set_short_addr(struct device *dev, uint16_t short_addr)
|
||||
{
|
||||
uint8_t short_addr_le[2];
|
||||
|
||||
ARG_UNUSED(dev);
|
||||
|
||||
sys_put_le16(short_addr, short_addr_le);
|
||||
nrf_drv_radio802154_short_address_set(short_addr_le);
|
||||
|
||||
SYS_LOG_DBG("0x%x", short_addr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nrf5_set_ieee_addr(struct device *dev, const uint8_t *ieee_addr)
|
||||
{
|
||||
ARG_UNUSED(dev);
|
||||
|
||||
SYS_LOG_DBG("IEEE address %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
|
||||
ieee_addr[7], ieee_addr[6], ieee_addr[5], ieee_addr[4],
|
||||
ieee_addr[3], ieee_addr[2], ieee_addr[1], ieee_addr[0]);
|
||||
|
||||
nrf_drv_radio802154_extended_address_set(ieee_addr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nrf5_set_txpower(struct device *dev, int16_t dbm)
|
||||
{
|
||||
struct nrf5_802154_data *nrf5_radio = NRF5_802154_DATA(dev);
|
||||
|
||||
SYS_LOG_DBG("%d", dbm);
|
||||
nrf5_radio->txpower = dbm;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nrf5_tx(struct device *dev,
|
||||
struct net_buf *buf,
|
||||
struct net_buf *frag)
|
||||
{
|
||||
struct nrf5_802154_data *nrf5_radio = NRF5_802154_DATA(dev);
|
||||
uint8_t payload_len = net_nbuf_ll_reserve(buf) + frag->len;
|
||||
uint8_t *payload = frag->data - net_nbuf_ll_reserve(buf);
|
||||
|
||||
SYS_LOG_DBG("%p (%u)", payload, payload_len);
|
||||
|
||||
nrf5_radio->tx_success = false;
|
||||
nrf5_radio->tx_psdu[0] = payload_len + NRF5_FCS_LENGTH;
|
||||
|
||||
memcpy(nrf5_radio->tx_psdu + 1, payload, payload_len);
|
||||
|
||||
if (!nrf_drv_radio802154_transmit(nrf5_radio->tx_psdu,
|
||||
nrf5_radio->channel,
|
||||
nrf5_radio->txpower)) {
|
||||
SYS_LOG_ERR("Cannot send frame");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
SYS_LOG_DBG("Sending frame (ch:%d, txpower:%d)",
|
||||
nrf5_radio->channel,
|
||||
nrf5_radio->txpower);
|
||||
|
||||
/* The nRF driver guarantees that either
|
||||
* nrf_drv_radio802154_transmitted() or
|
||||
* nrf_drv_radio802154_energy_detected()
|
||||
* callback is called, thus unlocking the semaphore.
|
||||
*/
|
||||
k_sem_take(&nrf5_radio->tx_wait, K_FOREVER);
|
||||
|
||||
SYS_LOG_DBG("Result: %d", nrf5_data.tx_success);
|
||||
|
||||
return nrf5_radio->tx_success ? 0 : -EBUSY;
|
||||
}
|
||||
|
||||
static int nrf5_start(struct device *dev)
|
||||
{
|
||||
struct nrf5_802154_data *nrf5_radio = NRF5_802154_DATA(dev);
|
||||
|
||||
nrf_drv_radio802154_receive(nrf5_radio->channel, false);
|
||||
SYS_LOG_DBG("nRF5 802154 radio started (channel: %d)",
|
||||
nrf5_radio->channel);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nrf5_stop(struct device *dev)
|
||||
{
|
||||
ARG_UNUSED(dev);
|
||||
|
||||
if (!nrf_drv_radio802154_sleep()) {
|
||||
SYS_LOG_ERR("Error while stopping radio");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
SYS_LOG_DBG("nRF5 802154 radio stopped");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint8_t nrf5_get_lqi(struct device *dev)
|
||||
{
|
||||
struct nrf5_802154_data *nrf5_radio = NRF5_802154_DATA(dev);
|
||||
|
||||
return nrf5_radio->lqi;
|
||||
}
|
||||
|
||||
static void nrf5_radio_irq(void *arg)
|
||||
{
|
||||
ARG_UNUSED(arg);
|
||||
|
||||
nrf_drv_radio802154_irq_handler();
|
||||
}
|
||||
|
||||
static void nrf5_config(struct device *dev)
|
||||
{
|
||||
ARG_UNUSED(dev);
|
||||
|
||||
IRQ_CONNECT(NRF5_IRQ_RADIO_IRQn, 0, nrf5_radio_irq, NULL, 0);
|
||||
irq_enable(NRF5_IRQ_RADIO_IRQn);
|
||||
}
|
||||
|
||||
static int nrf5_init(struct device *dev)
|
||||
{
|
||||
const struct nrf5_802154_config *nrf5_radio_cfg = NRF5_802154_CFG(dev);
|
||||
struct nrf5_802154_data *nrf5_radio = NRF5_802154_DATA(dev);
|
||||
struct device *clk_m16;
|
||||
|
||||
k_sem_init(&nrf5_radio->rx_wait, 0, 1);
|
||||
k_sem_init(&nrf5_radio->tx_wait, 0, 1);
|
||||
k_sem_init(&nrf5_radio->cca_wait, 0, 1);
|
||||
|
||||
clk_m16 = device_get_binding(CONFIG_CLOCK_CONTROL_NRF5_M16SRC_DRV_NAME);
|
||||
if (!clk_m16) {
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
clock_control_on(clk_m16, NULL);
|
||||
|
||||
nrf_drv_radio802154_init();
|
||||
|
||||
nrf5_radio_cfg->irq_config_func(dev);
|
||||
|
||||
k_thread_spawn(nrf5_radio->rx_stack,
|
||||
CONFIG_IEEE802154_NRF5_RX_STACK_SIZE,
|
||||
nrf5_rx_thread,
|
||||
dev, NULL, NULL,
|
||||
K_PRIO_COOP(2), 0, 0);
|
||||
|
||||
SYS_LOG_INF("nRF5 802154 radio initialized");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void nrf5_iface_init(struct net_if *iface)
|
||||
{
|
||||
struct device *dev = net_if_get_device(iface);
|
||||
struct nrf5_802154_data *nrf5_radio = NRF5_802154_DATA(dev);
|
||||
|
||||
SYS_LOG_DBG("");
|
||||
|
||||
nrf5_get_eui64(nrf5_radio->mac);
|
||||
net_if_set_link_addr(iface, nrf5_radio->mac, sizeof(nrf5_radio->mac));
|
||||
|
||||
nrf5_radio->iface = iface;
|
||||
ieee802154_init(iface);
|
||||
}
|
||||
|
||||
/* nRF5 radio driver callbacks */
|
||||
|
||||
void nrf_drv_radio802154_received(uint8_t *p_data, int8_t power, int8_t lqi)
|
||||
{
|
||||
nrf5_data.rx_psdu = p_data;
|
||||
nrf5_data.rssi = power;
|
||||
nrf5_data.lqi = lqi;
|
||||
|
||||
k_sem_give(&nrf5_data.rx_wait);
|
||||
}
|
||||
|
||||
void nrf_drv_radio802154_transmitted(bool pending_bit)
|
||||
{
|
||||
ARG_UNUSED(pending_bit);
|
||||
|
||||
nrf5_data.tx_success = true;
|
||||
k_sem_give(&nrf5_data.tx_wait);
|
||||
}
|
||||
|
||||
void nrf_drv_radio802154_busy_channel(void)
|
||||
{
|
||||
k_sem_give(&nrf5_data.tx_wait);
|
||||
}
|
||||
|
||||
void nrf_drv_radio802154_energy_detected(int8_t result)
|
||||
{
|
||||
nrf5_data.channel_ed = result;
|
||||
k_sem_give(&nrf5_data.cca_wait);
|
||||
}
|
||||
|
||||
static const struct nrf5_802154_config nrf5_radio_cfg = {
|
||||
.irq_config_func = nrf5_config,
|
||||
};
|
||||
|
||||
static struct ieee802154_radio_api nrf5_radio_api = {
|
||||
.iface_api.init = nrf5_iface_init,
|
||||
.iface_api.send = ieee802154_radio_send,
|
||||
|
||||
.cca = nrf5_cca,
|
||||
.set_channel = nrf5_set_channel,
|
||||
.set_pan_id = nrf5_set_pan_id,
|
||||
.set_short_addr = nrf5_set_short_addr,
|
||||
.set_ieee_addr = nrf5_set_ieee_addr,
|
||||
.set_txpower = nrf5_set_txpower,
|
||||
.start = nrf5_start,
|
||||
.stop = nrf5_stop,
|
||||
.tx = nrf5_tx,
|
||||
.get_lqi = nrf5_get_lqi,
|
||||
};
|
||||
|
||||
NET_DEVICE_INIT(nrf5_154_radio, CONFIG_IEEE802154_NRF5_DRV_NAME,
|
||||
nrf5_init, &nrf5_data, &nrf5_radio_cfg,
|
||||
CONFIG_IEEE802154_NRF5_INIT_PRIO,
|
||||
&nrf5_radio_api, IEEE802154_L2,
|
||||
NET_L2_GET_CTX_TYPE(IEEE802154_L2), 125);
|
||||
|
||||
NET_STACK_INFO_ADDR(RX, nrf5_154_radio,
|
||||
CONFIG_IEEE802154_NRF5_RX_STACK_SIZE,
|
||||
CONFIG_IEEE802154_NRF5_RX_STACK_SIZE,
|
||||
((struct nrf5_802154_data *)
|
||||
(&__device_nrf5_154_radio))->rx_stack, 0);
|
||||
59
drivers/ieee802154/ieee802154_nrf5.h
Normal file
59
drivers/ieee802154/ieee802154_nrf5.h
Normal file
@@ -0,0 +1,59 @@
|
||||
/* ieee802154_nrf5.h - nRF5 802.15.4 driver */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2017 Nordic Semiconductor ASA
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#ifndef __IEEE802154_NRF5_H__
|
||||
#define __IEEE802154_NRF5_H__
|
||||
|
||||
#include <sections.h>
|
||||
#include <atomic.h>
|
||||
|
||||
#define NRF5_FCS_LENGTH (2)
|
||||
#define NRF5_PSDU_LENGTH (125)
|
||||
#define NRF5_PHR_LENGTH (1)
|
||||
|
||||
struct nrf5_802154_data {
|
||||
/* Pointer to the network interface. */
|
||||
struct net_if *iface;
|
||||
/* Pointer to a received frame. */
|
||||
uint8_t *rx_psdu;
|
||||
/* TX buffer. First byte is PHR (length), remaining bytes are
|
||||
* MPDU data.
|
||||
*/
|
||||
uint8_t tx_psdu[NRF5_PHR_LENGTH + NRF5_PSDU_LENGTH];
|
||||
/* 802.15.4 HW address. */
|
||||
uint8_t mac[8];
|
||||
/* RX thread stack. */
|
||||
char __stack rx_stack[CONFIG_IEEE802154_NRF5_RX_STACK_SIZE];
|
||||
|
||||
/* CCA complete sempahore. Unlocked when CCA is complete. */
|
||||
struct k_sem cca_wait;
|
||||
/* RX synchronization semaphore. Unlocked when frame has been
|
||||
* received.
|
||||
*/
|
||||
struct k_sem rx_wait;
|
||||
/* TX synchronization semaphore. Unlocked when frame has been
|
||||
* sent or CCA failed.
|
||||
*/
|
||||
struct k_sem tx_wait;
|
||||
/* TX result. Set to 1 on success, 0 otherwise. */
|
||||
bool tx_success;
|
||||
|
||||
/* CCA channel energy. Unit as per 802.15.4-2006 specification. */
|
||||
int8_t channel_ed;
|
||||
|
||||
/* TX power, in dBm, to be used when sending a frame. */
|
||||
int8_t txpower;
|
||||
/* 802.15.4 channel to be used when sending a frame. */
|
||||
uint8_t channel;
|
||||
|
||||
/* Last received frame LQI value. */
|
||||
uint8_t lqi;
|
||||
/* Last received frame RSSI value. */
|
||||
int8_t rssi;
|
||||
};
|
||||
|
||||
#endif /* __IEEE802154_NRF5_H__ */
|
||||
@@ -84,7 +84,7 @@ static uint8_t *upipe_rx(uint8_t *buf, size_t *off)
|
||||
|
||||
goto flush;
|
||||
out:
|
||||
net_buf_unref(nbuf);
|
||||
net_nbuf_unref(nbuf);
|
||||
flush:
|
||||
upipe->rx = false;
|
||||
upipe->rx_len = 0;
|
||||
@@ -257,7 +257,7 @@ static void upipe_iface_init(struct net_if *iface)
|
||||
|
||||
SYS_LOG_DBG("");
|
||||
|
||||
net_if_set_link_addr(iface, mac, 8);
|
||||
net_if_set_link_addr(iface, mac, 8, NET_LINK_IEEE802154);
|
||||
|
||||
upipe_dev = dev;
|
||||
upipe->iface = iface;
|
||||
|
||||
@@ -41,6 +41,9 @@ enum slip_state {
|
||||
|
||||
struct slip_context {
|
||||
bool init_done;
|
||||
bool first; /* SLIP received it's byte or not after
|
||||
* driver initialization or SLIP_END byte.
|
||||
*/
|
||||
uint8_t buf[1]; /* SLIP data is read into this buf */
|
||||
struct net_buf *rx; /* and then placed into this net_buf */
|
||||
struct net_buf *last; /* Pointer to last fragment in the list */
|
||||
@@ -54,9 +57,6 @@ struct slip_context {
|
||||
#define SLIP_STATS(statement)
|
||||
#else
|
||||
uint16_t garbage;
|
||||
uint16_t multi_packets;
|
||||
uint16_t overflows;
|
||||
uint16_t ip_drop;
|
||||
#define SLIP_STATS(statement) statement
|
||||
#endif
|
||||
};
|
||||
@@ -173,15 +173,29 @@ static int slip_send(struct net_if *iface, struct net_buf *buf)
|
||||
|
||||
for (i = 0; i < frag->len; ++i) {
|
||||
c = *ptr++;
|
||||
if (c == SLIP_END) {
|
||||
slip_writeb(SLIP_ESC);
|
||||
c = SLIP_ESC_END;
|
||||
} else if (c == SLIP_ESC) {
|
||||
slip_writeb(SLIP_ESC);
|
||||
c = SLIP_ESC_ESC;
|
||||
}
|
||||
|
||||
slip_writeb(c);
|
||||
switch (c) {
|
||||
case SLIP_END:
|
||||
/* If it's the same code as an END character,
|
||||
* we send a special two character code so as
|
||||
* not to make the receiver think we sent
|
||||
* an END.
|
||||
*/
|
||||
slip_writeb(SLIP_ESC);
|
||||
slip_writeb(SLIP_ESC_END);
|
||||
break;
|
||||
case SLIP_ESC:
|
||||
/* If it's the same code as an ESC character,
|
||||
* we send a special two character code so as
|
||||
* not to make the receiver think we sent
|
||||
* an ESC.
|
||||
*/
|
||||
slip_writeb(SLIP_ESC);
|
||||
slip_writeb(SLIP_ESC_ESC);
|
||||
break;
|
||||
default:
|
||||
slip_writeb(c);
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(CONFIG_SLIP_DEBUG)
|
||||
@@ -258,31 +272,46 @@ static inline int slip_input_byte(struct slip_context *slip,
|
||||
if (c == SLIP_ESC) {
|
||||
slip->state = STATE_ESC;
|
||||
return 0;
|
||||
} else if (c == SLIP_END) {
|
||||
}
|
||||
|
||||
if (c == SLIP_END) {
|
||||
slip->state = STATE_OK;
|
||||
return 1;
|
||||
slip->first = false;
|
||||
|
||||
if (slip->rx) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (slip->first && !slip->rx) {
|
||||
/* Must have missed buffer allocation on first byte. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!slip->first) {
|
||||
slip->first = true;
|
||||
|
||||
slip->rx = net_nbuf_get_reserve_rx(0, K_NO_WAIT);
|
||||
if (!slip->rx) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
slip->last = net_nbuf_get_reserve_data(0, K_NO_WAIT);
|
||||
if (!slip->last) {
|
||||
net_nbuf_unref(slip->rx);
|
||||
slip->rx = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
net_buf_frag_add(slip->rx, slip->last);
|
||||
slip->ptr = net_nbuf_ip_data(slip->rx);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (!slip->rx) {
|
||||
slip->rx = net_nbuf_get_reserve_rx(0, K_NO_WAIT);
|
||||
if (!slip->rx) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
slip->last = net_nbuf_get_reserve_data(0, K_NO_WAIT);
|
||||
if (!slip->last) {
|
||||
net_nbuf_unref(slip->rx);
|
||||
slip->rx = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
net_buf_frag_add(slip->rx, slip->last);
|
||||
slip->ptr = net_nbuf_ip_data(slip->rx);
|
||||
}
|
||||
|
||||
if (!net_buf_tailroom(slip->last)) {
|
||||
/* We need to allocate a new fragment */
|
||||
struct net_buf *frag;
|
||||
@@ -366,6 +395,7 @@ static int slip_init(struct device *dev)
|
||||
|
||||
slip->state = STATE_OK;
|
||||
slip->rx = NULL;
|
||||
slip->first = false;
|
||||
|
||||
#if defined(CONFIG_SLIP_TAP) && defined(CONFIG_NET_IPV4)
|
||||
SYS_LOG_DBG("ARP enabled");
|
||||
@@ -402,7 +432,8 @@ static void slip_iface_init(struct net_if *iface)
|
||||
|
||||
slip->init_done = true;
|
||||
|
||||
net_if_set_link_addr(iface, ll_addr->addr, ll_addr->len);
|
||||
net_if_set_link_addr(iface, ll_addr->addr, ll_addr->len,
|
||||
NET_LINK_ETHERNET);
|
||||
}
|
||||
|
||||
static struct net_if_api slip_if_api = {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Nordic Semiconductor ASA
|
||||
* Copyright (c) 2016-2017 Nordic Semiconductor ASA
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -10,130 +10,261 @@
|
||||
#include <drivers/clock_control/nrf5_clock_control.h>
|
||||
#include <arch/arm/cortex_m/cmsis.h>
|
||||
|
||||
#define RTC_TICKS ((uint32_t)(((((uint64_t)1000000UL / \
|
||||
/*
|
||||
* Convenience defines.
|
||||
*/
|
||||
#define SYS_CLOCK_RTC NRF_RTC1
|
||||
#define RTC_COUNTER SYS_CLOCK_RTC->COUNTER
|
||||
#define RTC_CC_VALUE SYS_CLOCK_RTC->CC[0]
|
||||
#define RTC_CC_EVENT SYS_CLOCK_RTC->EVENTS_COMPARE[0]
|
||||
|
||||
/* Minimum delta between current counter and CC register that the RTC is able
|
||||
* to handle
|
||||
*/
|
||||
#define RTC_MIN_DELTA 2
|
||||
#define RTC_MASK 0x00FFFFFF
|
||||
/* Maximum difference for RTC counter values used. Half the maximum value is
|
||||
* selected to be able to detect overflow (a negative value has the same
|
||||
* representation as a large positive value).
|
||||
*/
|
||||
#define RTC_HALF (RTC_MASK / 2)
|
||||
#define RTC_TICKS_PER_SYS_TICK ((uint32_t)((((uint64_t)1000000UL / \
|
||||
CONFIG_SYS_CLOCK_TICKS_PER_SEC) * \
|
||||
1000000000UL) / 30517578125UL)) & 0x00FFFFFF)
|
||||
1000000000UL) / 30517578125UL) & RTC_MASK)
|
||||
|
||||
extern int64_t _sys_clock_tick_count;
|
||||
extern int32_t _sys_idle_elapsed_ticks;
|
||||
static uint32_t rtc_clock_tick_count;
|
||||
|
||||
/*
|
||||
* rtc_past holds the value of RTC_COUNTER at the time the last sys tick was
|
||||
* announced, in RTC ticks. It is therefore always a multiple of
|
||||
* RTC_TICKS_PER_SYS_TICK.
|
||||
*/
|
||||
static uint32_t rtc_past;
|
||||
|
||||
#ifdef CONFIG_TICKLESS_IDLE
|
||||
static uint8_t volatile isr_req;
|
||||
static uint8_t isr_ack;
|
||||
/*
|
||||
* Holds the maximum sys ticks the kernel expects to see in the next
|
||||
* _sys_clock_tick_announce().
|
||||
*/
|
||||
static uint32_t expected_sys_ticks;
|
||||
#endif /* CONFIG_TICKLESS_IDLE */
|
||||
|
||||
static uint32_t rtc_compare_set(uint32_t rtc_ticks)
|
||||
/*
|
||||
* Set RTC Counter Compare (CC) register to a given value in RTC ticks.
|
||||
*/
|
||||
static void rtc_compare_set(uint32_t rtc_ticks)
|
||||
{
|
||||
uint32_t prev, cc, elapsed_ticks;
|
||||
uint8_t retry = 10;
|
||||
uint32_t rtc_now;
|
||||
|
||||
prev = NRF_RTC1->COUNTER;
|
||||
/* Try to set CC value. We assume the procedure is always successful. */
|
||||
RTC_CC_VALUE = rtc_ticks;
|
||||
rtc_now = RTC_COUNTER;
|
||||
|
||||
do {
|
||||
/* Assert if retries failed to set compare in the future */
|
||||
__ASSERT_NO_MSG(retry);
|
||||
retry--;
|
||||
|
||||
/* update with elapsed ticks from h/w */
|
||||
elapsed_ticks = (prev - rtc_clock_tick_count) & 0x00FFFFFF;
|
||||
|
||||
/* setup next RTC compare event by ticks */
|
||||
cc = (rtc_clock_tick_count + elapsed_ticks + rtc_ticks) &
|
||||
0x00FFFFFF;
|
||||
|
||||
NRF_RTC1->CC[0] = cc;
|
||||
|
||||
prev = NRF_RTC1->COUNTER;
|
||||
} while (((cc - prev) & 0x00FFFFFF) < 3);
|
||||
|
||||
#ifdef CONFIG_TICKLESS_IDLE
|
||||
/* If system clock ticks have elapsed, pend RTC IRQ which will
|
||||
* call announce
|
||||
/* The following checks if the CC register was set to a valid value.
|
||||
* The first test checks if the distance between the current RTC counter
|
||||
* and the value (in the future) set in the CC register is too small to
|
||||
* guarantee a compare event being triggered.
|
||||
* The second test checks if the current RTC counter is higher than the
|
||||
* value written to the CC register, i.e. the CC value is in the past,
|
||||
* by checking if the unsigned subtraction wraps around.
|
||||
* If either of the above are true then instead of waiting for the CC
|
||||
* event to trigger in the form of an interrupt, trigger it directly
|
||||
* using the NVIC.
|
||||
*/
|
||||
if (elapsed_ticks >= rtc_ticks) {
|
||||
uint8_t req;
|
||||
|
||||
/* pending the interrupt does not trigger the RTC event, hence
|
||||
* use a request/ack mechanism to let the ISR know that the
|
||||
* interrupt was requested
|
||||
*/
|
||||
req = isr_req + 1;
|
||||
if (req != isr_ack) {
|
||||
isr_req = req;
|
||||
}
|
||||
|
||||
if ((((rtc_ticks - rtc_now) & RTC_MASK) < RTC_MIN_DELTA) ||
|
||||
(((rtc_ticks - rtc_now) & RTC_MASK) > RTC_HALF)) {
|
||||
NVIC_SetPendingIRQ(NRF5_IRQ_RTC1_IRQn);
|
||||
}
|
||||
#endif /* CONFIG_TICKLESS_IDLE */
|
||||
|
||||
return elapsed_ticks;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_TICKLESS_IDLE
|
||||
void _timer_idle_enter(int32_t ticks)
|
||||
/*
|
||||
* @brief Announces the number of sys ticks, if any, that have passed since the
|
||||
* last announcement, and programs the RTC to trigger the interrupt on the next
|
||||
* sys tick.
|
||||
*
|
||||
* This function is not reentrant. It is called from:
|
||||
*
|
||||
* * _timer_idle_exit(), which in turn is called with interrupts disabled when
|
||||
* an interrupt fires.
|
||||
* * rtc1_nrf5_isr(), which runs with interrupts enabled but at that time the
|
||||
* device cannot be idle and hence _timer_idle_exit() cannot be called.
|
||||
*
|
||||
* Since this function can be preempted, we need to take some provisions to
|
||||
* announce all expected sys ticks that have passed.
|
||||
*
|
||||
*/
|
||||
static void rtc_announce_set_next(void)
|
||||
{
|
||||
/* restrict ticks to max supported by RTC */
|
||||
if ((ticks < 0) || (ticks > (0x00FFFFFF / RTC_TICKS))) {
|
||||
ticks = 0x00FFFFFF / RTC_TICKS;
|
||||
}
|
||||
uint32_t rtc_now, rtc_elapsed, sys_elapsed;
|
||||
|
||||
/* Postpone RTC compare event by requested system clock ticks */
|
||||
rtc_compare_set(ticks * RTC_TICKS);
|
||||
}
|
||||
|
||||
void _timer_idle_exit(void)
|
||||
{
|
||||
/* Advance RTC compare event to next system clock tick */
|
||||
rtc_compare_set(RTC_TICKS);
|
||||
}
|
||||
#endif /* CONFIG_TICKLESS_IDLE */
|
||||
|
||||
static void rtc1_nrf5_isr(void *arg)
|
||||
{
|
||||
#ifdef CONFIG_TICKLESS_IDLE
|
||||
uint8_t req;
|
||||
|
||||
ARG_UNUSED(arg);
|
||||
|
||||
req = isr_req;
|
||||
/* iterate here since pending the interrupt can be done from higher
|
||||
* priority, and thus queuing multiple triggers
|
||||
/* Read the RTC counter one single time in the beginning, so that an
|
||||
* increase in the counter during this procedure leads to no race
|
||||
* conditions.
|
||||
*/
|
||||
while (NRF_RTC1->EVENTS_COMPARE[0] || (req != isr_ack)) {
|
||||
uint32_t elapsed_ticks;
|
||||
rtc_now = RTC_COUNTER;
|
||||
|
||||
NRF_RTC1->EVENTS_COMPARE[0] = 0;
|
||||
/* Calculate how many RTC ticks elapsed since the last sys tick. */
|
||||
rtc_elapsed = (rtc_now - rtc_past) & RTC_MASK;
|
||||
|
||||
if (req != isr_ack) {
|
||||
isr_ack = req;
|
||||
req = isr_req;
|
||||
/* If no sys ticks have elapsed, there is no point in incrementing the
|
||||
* counters or announcing it.
|
||||
*/
|
||||
if (rtc_elapsed >= RTC_TICKS_PER_SYS_TICK) {
|
||||
#ifdef CONFIG_TICKLESS_IDLE
|
||||
/* Calculate how many sys ticks elapsed since the last sys tick
|
||||
* and notify the kernel if necessary.
|
||||
*/
|
||||
sys_elapsed = rtc_elapsed / RTC_TICKS_PER_SYS_TICK;
|
||||
|
||||
elapsed_ticks = (NRF_RTC1->COUNTER -
|
||||
rtc_clock_tick_count)
|
||||
& 0x00FFFFFF;
|
||||
} else {
|
||||
elapsed_ticks = rtc_compare_set(RTC_TICKS);
|
||||
if (sys_elapsed > expected_sys_ticks) {
|
||||
/* Never announce more sys ticks than the kernel asked
|
||||
* to be idle for. The remainder will be announced when
|
||||
* the RTC ISR runs after rtc_compare_set() is called
|
||||
* after the first announcement.
|
||||
*/
|
||||
sys_elapsed = expected_sys_ticks;
|
||||
}
|
||||
#else
|
||||
ARG_UNUSED(arg);
|
||||
/* Never announce more than one sys tick if tickless idle is not
|
||||
* configured.
|
||||
*/
|
||||
sys_elapsed = 1;
|
||||
#endif /* CONFIG_TICKLESS_IDLE */
|
||||
|
||||
if (NRF_RTC1->EVENTS_COMPARE[0]) {
|
||||
uint32_t elapsed_ticks;
|
||||
|
||||
NRF_RTC1->EVENTS_COMPARE[0] = 0;
|
||||
|
||||
elapsed_ticks = rtc_compare_set(RTC_TICKS);
|
||||
#endif
|
||||
|
||||
rtc_clock_tick_count += elapsed_ticks;
|
||||
rtc_clock_tick_count &= 0x00FFFFFF;
|
||||
|
||||
/* update with elapsed ticks from the hardware */
|
||||
_sys_idle_elapsed_ticks = elapsed_ticks / RTC_TICKS;
|
||||
/* Store RTC_COUNTER floored to the last sys tick. This is
|
||||
* done, so that ISR can properly calculate that 1 sys tick
|
||||
* has passed.
|
||||
*/
|
||||
rtc_past = (rtc_past +
|
||||
(sys_elapsed * RTC_TICKS_PER_SYS_TICK)
|
||||
) & RTC_MASK;
|
||||
|
||||
_sys_idle_elapsed_ticks = sys_elapsed;
|
||||
_sys_clock_tick_announce();
|
||||
}
|
||||
|
||||
/* Set the RTC to the next sys tick */
|
||||
rtc_compare_set(rtc_past + RTC_TICKS_PER_SYS_TICK);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_TICKLESS_IDLE
|
||||
/**
|
||||
* @brief Place system timer into idle state.
|
||||
*
|
||||
* Re-program the timer to enter into the idle state for the given number of
|
||||
* sys ticks, counted from the previous sys tick. The timer will fire in the
|
||||
* number of sys ticks supplied or the maximum number of sys ticks (converted
|
||||
* to RTC ticks) that can be programmed into the hardware.
|
||||
*
|
||||
* This will only be called from idle context, with IRQs disabled.
|
||||
*
|
||||
* A value of -1 will result in the maximum number of sys ticks.
|
||||
*
|
||||
* Example 1: Idle sleep is entered:
|
||||
*
|
||||
* sys tick timeline: (1) (2) (3) (4) (5) (6)
|
||||
* rtc tick timeline : 0----100----200----300----400----500----600
|
||||
* ******************
|
||||
* 150
|
||||
*
|
||||
* a) The last sys tick was announced at 100
|
||||
* b) The idle context enters sleep at 150, between sys tick 1 and 2, with
|
||||
* sys_ticks = 3.
|
||||
* c) The RTC is programmed to fire at sys tick 1 + 3 = 4 (RTC tick 400)
|
||||
*
|
||||
* @return N/A
|
||||
*/
|
||||
void _timer_idle_enter(int32_t sys_ticks)
|
||||
{
|
||||
/* Restrict ticks to max supported by RTC without risking overflow. */
|
||||
if ((sys_ticks < 0) ||
|
||||
(sys_ticks > (RTC_HALF / RTC_TICKS_PER_SYS_TICK))) {
|
||||
sys_ticks = RTC_HALF / RTC_TICKS_PER_SYS_TICK;
|
||||
}
|
||||
|
||||
expected_sys_ticks = sys_ticks;
|
||||
|
||||
/* If ticks is 0, the RTC interrupt handler will be set pending
|
||||
* immediately, meaning that we will not go to sleep.
|
||||
*/
|
||||
rtc_compare_set(rtc_past + (sys_ticks * RTC_TICKS_PER_SYS_TICK));
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief Handling of tickless idle when interrupted
|
||||
*
|
||||
* The function will be called by _sys_power_save_idle_exit(), called from
|
||||
* _arch_isr_direct_pm() for 'direct' interrupts, or from _isr_wrapper for
|
||||
* regular ones, which is called on every IRQ handler if the device was
|
||||
* idle, and optionally called when a 'direct' IRQ handler executes if the
|
||||
* device was idle.
|
||||
*
|
||||
* Example 1: Idle sleep is interrupted before time:
|
||||
*
|
||||
* sys tick timeline: (1) (2) (3) (4) (5) (6)
|
||||
* rtc tick timeline : 0----100----200----300----400----500----600
|
||||
* **************!***
|
||||
* 150 350
|
||||
*
|
||||
* Assume that _timer_idle_enter() is called at 150 (1) to sleep for 3
|
||||
* sys ticks. The last sys tick was announced at 100.
|
||||
*
|
||||
* On wakeup (non-RTC IRQ at 350):
|
||||
*
|
||||
* a) Notify how many sys ticks have passed, i.e., 350 - 150 / 100 = 2.
|
||||
* b) Schedule next sys tick at 400.
|
||||
*
|
||||
*/
|
||||
void _timer_idle_exit(void)
|
||||
{
|
||||
/* Clear the event flag and interrupt in case we woke up on the RTC
|
||||
* interrupt. No need to run the RTC ISR since everything that needs
|
||||
* to run in the ISR will be done in this call.
|
||||
*/
|
||||
RTC_CC_EVENT = 0;
|
||||
NVIC_ClearPendingIRQ(NRF5_IRQ_RTC1_IRQn);
|
||||
|
||||
rtc_announce_set_next();
|
||||
|
||||
/* After exiting idle, the kernel no longer expects more than one sys
|
||||
* ticks to have passed when _sys_clock_tick_announce() is called.
|
||||
*/
|
||||
expected_sys_ticks = 1;
|
||||
}
|
||||
#endif /* CONFIG_TICKLESS_IDLE */
|
||||
|
||||
/*
|
||||
* @brief Announces the number of sys ticks that have passed since the last
|
||||
* announcement, if any, and programs the RTC to trigger the interrupt on the
|
||||
* next sys tick.
|
||||
*
|
||||
* The ISR is set pending due to a regular sys tick and after exiting idle mode
|
||||
* as scheduled.
|
||||
*
|
||||
* Since this ISR can be preempted, we need to take some provisions to announce
|
||||
* all expected sys ticks that have passed.
|
||||
*
|
||||
* Consider the following example:
|
||||
*
|
||||
* sys tick timeline: (1) (2) (3) (4) (5) (6)
|
||||
* rtc tick timeline : 0----100----200----300----400----500----600
|
||||
* !**********
|
||||
* 450
|
||||
*
|
||||
* The last sys tick was anounced at 200, i.e, rtc_past = 200. The ISR is
|
||||
* executed at the next sys tick, i.e. 300. The following sys tick is due at
|
||||
* 400. However, the ISR is preempted for a number of sys ticks, until 450 in
|
||||
* this example. The ISR will then announce the number of sys ticks it was
|
||||
* delayed (2), and schedule the next sys tick (5) at 500.
|
||||
*/
|
||||
static void rtc1_nrf5_isr(void *arg)
|
||||
{
|
||||
ARG_UNUSED(arg);
|
||||
|
||||
RTC_CC_EVENT = 0;
|
||||
rtc_announce_set_next();
|
||||
}
|
||||
|
||||
int _sys_clock_driver_init(struct device *device)
|
||||
@@ -149,16 +280,23 @@ int _sys_clock_driver_init(struct device *device)
|
||||
|
||||
clock_control_on(clock, (void *)CLOCK_CONTROL_NRF5_K32SRC);
|
||||
|
||||
rtc_past = 0;
|
||||
|
||||
#ifdef CONFIG_TICKLESS_IDLE
|
||||
expected_sys_ticks = 1;
|
||||
#endif /* CONFIG_TICKLESS_IDLE */
|
||||
|
||||
/* TODO: replace with counter driver to access RTC */
|
||||
NRF_RTC1->PRESCALER = 0;
|
||||
NRF_RTC1->CC[0] = RTC_TICKS;
|
||||
NRF_RTC1->EVTENSET = RTC_EVTENSET_COMPARE0_Msk;
|
||||
NRF_RTC1->INTENSET = RTC_INTENSET_COMPARE0_Msk;
|
||||
SYS_CLOCK_RTC->PRESCALER = 0;
|
||||
SYS_CLOCK_RTC->CC[0] = RTC_TICKS_PER_SYS_TICK;
|
||||
SYS_CLOCK_RTC->EVTENSET = RTC_EVTENSET_COMPARE0_Msk;
|
||||
SYS_CLOCK_RTC->INTENSET = RTC_INTENSET_COMPARE0_Msk;
|
||||
|
||||
IRQ_CONNECT(NRF5_IRQ_RTC1_IRQn, 1, rtc1_nrf5_isr, 0, 0);
|
||||
irq_enable(NRF5_IRQ_RTC1_IRQn);
|
||||
|
||||
NRF_RTC1->TASKS_START = 1;
|
||||
SYS_CLOCK_RTC->TASKS_CLEAR = 1;
|
||||
SYS_CLOCK_RTC->TASKS_START = 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -167,8 +305,9 @@ uint32_t k_cycle_get_32(void)
|
||||
{
|
||||
uint32_t elapsed_cycles;
|
||||
|
||||
elapsed_cycles = (NRF_RTC1->COUNTER -
|
||||
(_sys_clock_tick_count * RTC_TICKS)) & 0x00FFFFFF;
|
||||
elapsed_cycles = (RTC_COUNTER -
|
||||
(_sys_clock_tick_count * RTC_TICKS_PER_SYS_TICK))
|
||||
& RTC_MASK;
|
||||
|
||||
return (_sys_clock_tick_count * sys_clock_hw_cycles_per_tick) +
|
||||
elapsed_cycles;
|
||||
@@ -177,7 +316,7 @@ uint32_t k_cycle_get_32(void)
|
||||
#ifdef CONFIG_SYSTEM_CLOCK_DISABLE
|
||||
/**
|
||||
*
|
||||
* @brief Stop announcing ticks into the kernel
|
||||
* @brief Stop announcing sys ticks into the kernel
|
||||
*
|
||||
* This routine disables the RTC1 so that timer interrupts are no
|
||||
* longer delivered.
|
||||
@@ -188,7 +327,7 @@ void sys_clock_disable(void)
|
||||
{
|
||||
irq_disable(NRF5_IRQ_RTC1_IRQn);
|
||||
|
||||
NRF_RTC1->TASKS_STOP = 1;
|
||||
SYS_CLOCK_RTC->TASKS_STOP = 1;
|
||||
|
||||
/* TODO: turn off (release) 32 KHz clock source.
|
||||
* Turning off of 32 KHz clock source is not implemented in clock
|
||||
|
||||
@@ -30,4 +30,10 @@
|
||||
|
||||
&uart0 {
|
||||
status = "ok";
|
||||
baud-rate = <115200>;
|
||||
};
|
||||
|
||||
&uart3 {
|
||||
status = "ok";
|
||||
baud-rate = <115200>;
|
||||
};
|
||||
|
||||
@@ -31,4 +31,10 @@
|
||||
|
||||
&uart0 {
|
||||
status = "ok";
|
||||
baud-rate = <115200>;
|
||||
};
|
||||
|
||||
&uart4 {
|
||||
status = "ok";
|
||||
baud-rate = <115200>;
|
||||
};
|
||||
|
||||
@@ -75,7 +75,6 @@
|
||||
interrupt-names = "status", "error";
|
||||
zephyr,irq-prio = <0>;
|
||||
|
||||
baud-rate = <115200>;
|
||||
pinctrl-0 = <&uart0_default>;
|
||||
pinctrl-names = "default";
|
||||
|
||||
|
||||
@@ -3,3 +3,4 @@ obj-$(CONFIG_QMSI_BUILTIN) += qmsi/
|
||||
obj-$(CONFIG_HAS_STM32CUBE) += st/stm32cube/
|
||||
obj-$(CONFIG_HAS_CC3200SDK) += ti/cc3200sdk/
|
||||
obj-$(CONFIG_HAS_NORDIC_HAL) += nordic/
|
||||
obj-$(CONFIG_HAS_NORDIC_DRIVERS) += nordic/drivers/
|
||||
|
||||
@@ -8,4 +8,8 @@ config HAS_NORDIC_MDK
|
||||
bool
|
||||
|
||||
config HAS_NORDIC_HAL
|
||||
bool
|
||||
bool
|
||||
|
||||
config HAS_NORDIC_DRIVERS
|
||||
bool
|
||||
select HAS_NORDIC_HAL
|
||||
|
||||
@@ -5,3 +5,7 @@ endif
|
||||
ifdef CONFIG_HAS_NORDIC_HAL
|
||||
ZEPHYRINCLUDE += -I$(srctree)/ext/hal/nordic/hal
|
||||
endif
|
||||
|
||||
ifdef CONFIG_HAS_NORDIC_DRIVERS
|
||||
ZEPHYRINCLUDE += -I$(srctree)/ext/hal/nordic/drivers
|
||||
endif
|
||||
|
||||
33
ext/hal/nordic/drivers/Kbuild
Normal file
33
ext/hal/nordic/drivers/Kbuild
Normal file
@@ -0,0 +1,33 @@
|
||||
obj-$(CONFIG_IEEE802154_NRF5) += nrf_drv_radio802154.o
|
||||
|
||||
ifeq ($(CONFIG_IEEE802154_NRF5),y)
|
||||
# A common prefix used for placing radio buffer in a named
|
||||
# memory section.
|
||||
KBUILD_CFLAGS += -DRADIO_SECTION_PREFIX="\".top_of_image_ram\""
|
||||
|
||||
# Number of slots containing short addresses of nodes for which pending data is stored.
|
||||
KBUILD_CFLAGS += -DRADIO_PENDING_SHORT_ADDRESSES=1
|
||||
|
||||
# Number of slots containing extended addresses of nodes for which pending data is stored.
|
||||
KBUILD_CFLAGS += -DRADIO_PENDING_EXTENDED_ADDRESSES=1
|
||||
|
||||
# Number of buffers in receive queue.
|
||||
KBUILD_CFLAGS += -DRADIO_RX_BUFFERS=1
|
||||
|
||||
# CCA mode
|
||||
ifeq ($(CONFIG_IEEE802154_NRF5_CCA_MODE_ED),y)
|
||||
KBUILD_CFLAGS += -DRADIO_CCA_MODE=NRF_RADIO_CCA_MODE_ED
|
||||
else ifeq ($(CONFIG_IEEE802154_NRF5_CCA_MODE_CARRIER),y)
|
||||
KBUILD_CFLAGS += -DRADIO_CCA_MODE=NRF_RADIO_CCA_MODE_CARRIER
|
||||
else ifeq ($(IEEE802154_NRF5_CCA_MODE_CARRIER_AND_ED),y)
|
||||
KBUILD_CFLAGS += -DRADIO_CCA_MODE=NRF_RADIO_CCA_MODE_CARRIER_AND_ED
|
||||
else ifeq ($(IEEE802154_NRF5_CCA_MODE_CARRIER_OR_ED),y)
|
||||
KBUILD_CFLAGS += -DRADIO_CCA_MODE=NRF_RADIO_CCA_MODE_CARRIER_OR_ED
|
||||
endif
|
||||
|
||||
# CCA mode options
|
||||
KBUILD_CFLAGS += -DRADIO_CCA_CORR_LIMIT=$(CONFIG_IEEE802154_NRF5_CCA_CORR_LIMIT)
|
||||
KBUILD_CFLAGS += -DRADIO_CCA_CORR_THRESHOLD=$(CONFIG_IEEE802154_NRF5_CCA_CORR_THRESHOLD)
|
||||
KBUILD_CFLAGS += -DRADIO_CCA_ED_THRESHOLD=$(CONFIG_IEEE802154_NRF5_CCA_ED_THRESHOLD)
|
||||
|
||||
endif
|
||||
3
ext/hal/nordic/drivers/Makefile
Normal file
3
ext/hal/nordic/drivers/Makefile
Normal file
@@ -0,0 +1,3 @@
|
||||
ifeq ($(CONFIG_IEEE802154_NRF5),y)
|
||||
ZEPHYRINCLUDE += -I$(srctree)/ext/hal/nordic/drivers
|
||||
endif
|
||||
128
ext/hal/nordic/drivers/README.md
Normal file
128
ext/hal/nordic/drivers/README.md
Normal file
@@ -0,0 +1,128 @@
|
||||
# nRF 802.15.4 radio driver.
|
||||
|
||||
This driver implements only __non-beacon mode__ of operation.
|
||||
It supports following __features__:
|
||||
* reception of unicast and broadcast frames (with filtering),
|
||||
* automatic sending ACK frames,
|
||||
* setting pending bit in ACK frame according to pending data for given
|
||||
destination,
|
||||
* transmission of unicast and broadcast frames,
|
||||
* automatic CCA procedure before transmission,
|
||||
* automatic receiving ACK frames,
|
||||
* low power mode (sleep),
|
||||
* energy detection,
|
||||
* promiscuous mode.
|
||||
|
||||
## Implementation details
|
||||
|
||||
The driver is a FSM. From API perspective it has 4 states. Most of those states
|
||||
contains sub-states in implementation.
|
||||
|
||||
### FSM description
|
||||
|
||||
```
|
||||
receive() transmit()
|
||||
--------> -------->
|
||||
Sleep Receive Transmit
|
||||
<-------- | /|\<--------
|
||||
sleep() | | receive() / transmitted() / busy_channel()
|
||||
| |
|
||||
energy_detection() | | energy_detected()
|
||||
\|/ |
|
||||
Energy detection
|
||||
```
|
||||
|
||||
#### Transitions
|
||||
|
||||
The driver is initialized in the Sleep state. The higher layer should call
|
||||
the receive() function to make the driver enter the Receive state and start
|
||||
radio operations.
|
||||
|
||||
In basic applications radio should be most time in a Receive state. In this
|
||||
state the radio receives incoming frames. Changing to any other state should be
|
||||
performed from Receive state.
|
||||
|
||||
When a frame is received in Receive state the driver notifies the higher layer
|
||||
by calling received() function. This function is called after reception of a
|
||||
broadcast frame or after sending an ACK to a unicast frame.
|
||||
In the promiscuous mode the higher layer is notified about all of the received
|
||||
frames. Even if the frame was not destined to the receiving node.
|
||||
|
||||
To transmit a frame the higher layer should call the transmit() function. If
|
||||
channel is busy the driver goes back to the Receive state and notifies the
|
||||
higher layer by calling the busy_channel() function. If a broadcast frame was
|
||||
transmitted the driver goes back to the Receive state and notifies the higher
|
||||
layer by calling the transmitted() function. If a unicast frame was transmitted
|
||||
and an ACK was received the driver goes back to the Receive state and notifies
|
||||
the higher layer by calling the transmitted() function. If a unicast frame was
|
||||
transmitted and there was no expected ACK received the higher layer shall call
|
||||
the receive() function after the ACK timeout to make the driver go back to the
|
||||
Receive state.
|
||||
|
||||
To perform an Energy Detection procedure the higher layer should call the
|
||||
energy_detection() function. When the procedure is completed the driver goes
|
||||
automatically back to the Receive state and notifies the higher layer with the
|
||||
energy_detected() function.
|
||||
|
||||
#### States
|
||||
|
||||
##### Sleep
|
||||
In this state the radio is in low power mode. It cannot transmit or receive any
|
||||
frame.
|
||||
|
||||
##### Receive
|
||||
In this state the radio receives 802.15.4 frames. It filters out frames with
|
||||
invalid CRC, length, type, destination address.
|
||||
If the driver receives unicast frame destined to the receiving node it
|
||||
automatically transmits an ACK frame. According to 802.15.4 standard, an ACK
|
||||
frame should be delayed aTurnaroundTime (192 uS) after reception of the ACKed
|
||||
frame. To perform this delay the driver uses the TIFS timer in the radio
|
||||
peripheral. This timer requires 3 shorts to work correctly:
|
||||
1. END -> DISABLE
|
||||
2. DISABLE -> TXEN
|
||||
3. READY -> START
|
||||
The driver has limited time after receiving of a frame to decide if an ACK
|
||||
should be transmitted. If ACK should not be transmitted the driver must abort
|
||||
sending ACK by disabling those shorts and triggering DISABLE task.
|
||||
To use this limited time most effective the driver uses the Bit Counter feature
|
||||
of the radio peripheral to get notification when the Frame Control field is
|
||||
received and when the destination address is received. Those fields are used to
|
||||
filter the frame before whole frame is received.
|
||||
If all 3 shorts used to send ACK automatically are enabled the radio peripheral
|
||||
sends ACK frames in loop. To prevent this during debugging process there are
|
||||
only 2 shorts enabled when waiting for frame (1. and 2.) and 2 other shorts are
|
||||
enabled in DISABLED event handler (1. and 3.). The first short is still enabled
|
||||
to automatically disable transmitter after transmission of the ACK frame.
|
||||
|
||||
##### Transmit
|
||||
In this state the radio performs the CCA procedure. If channel is free the radio
|
||||
transmits requested frame. If an ACK was requested in the transmitted frame
|
||||
the driver automatically receives the ACK frame in this state.
|
||||
To prevent the TXIDLE peripheral state the driver uses 2 shorts in Transmit
|
||||
state:
|
||||
1. READY -> START
|
||||
2. END -> DISABLE
|
||||
Those shorts automatically start transmission of the frame when transmitter is
|
||||
ready and disable transmitter when the frame was transmitted.
|
||||
|
||||
##### Energy detection
|
||||
In this state the radio performs the Energy Detection procedure. During this
|
||||
procedure the radio is busy and cannot change state to any other. The end of
|
||||
this procedure is notified to the higher layer by a function call.
|
||||
|
||||
### Mutex and critical sections.
|
||||
|
||||
State transitions in the FSM can be requested simultaneously by the higher layer
|
||||
and the IRQ handler. To prevent race conditions in the driver there is a mutex.
|
||||
The mutex is unlocked only in the *Receive* state (*WaitingRxFrame* substate).
|
||||
If there is requested state transition, the procedure shall lock the mutex
|
||||
before state is changed. If mutex cannot be locked, another procedure has locked
|
||||
it and is going to change the state.
|
||||
The mutex is unlocked when the driver enters *Receive* state.
|
||||
|
||||
A race condition could also occur during handle of a requests from the higher
|
||||
layer. Even if the receiver is stopped (TASK STOP) the END or DISABLED event can
|
||||
be raised for a few uS after triggering the task. To prevent interrupt of the
|
||||
higher layer request handler by IRQ handler, the higher layer request handlers
|
||||
are performend in critical sections. The critical sections are implemented as
|
||||
software interrupt requests with priority equal to the RADIO IRQ.
|
||||
1649
ext/hal/nordic/drivers/nrf_drv_radio802154.c
Normal file
1649
ext/hal/nordic/drivers/nrf_drv_radio802154.c
Normal file
File diff suppressed because it is too large
Load Diff
348
ext/hal/nordic/drivers/nrf_drv_radio802154.h
Normal file
348
ext/hal/nordic/drivers/nrf_drv_radio802154.h
Normal file
@@ -0,0 +1,348 @@
|
||||
/* Copyright (c) 2016, Nordic Semiconductor ASA
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief This module contains generic 802.15.4 radio driver for nRF SoC devices.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef NRF_RADIO802154_H_
|
||||
#define NRF_RADIO802154_H_
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Initialize 802.15.4 driver.
|
||||
*
|
||||
* @note This function shall be called once, before any other function from this module.
|
||||
*
|
||||
* Initialize radio peripheral to Sleep state.
|
||||
*/
|
||||
void nrf_drv_radio802154_init(void);
|
||||
|
||||
/**
|
||||
* @brief Get channel on which the radio operates right now.
|
||||
*/
|
||||
uint8_t nrf_drv_radio802154_channel_get(void);
|
||||
|
||||
/**
|
||||
* @section Setting addresses and Pan Id of this device.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Set PAN Id used by this device.
|
||||
*
|
||||
* @param[in] p_pan_id Pointer to PAN Id (2 bytes, little-endian).
|
||||
*
|
||||
* This function makes copy of the PAN Id.
|
||||
*/
|
||||
void nrf_drv_radio802154_pan_id_set(const uint8_t *p_pan_id);
|
||||
|
||||
/**
|
||||
* @brief Set Extended Address of this device.
|
||||
*
|
||||
* @param[in] p_extended_address Pointer to extended address (8 bytes, little-endian).
|
||||
*
|
||||
* This function makes copy of the address.
|
||||
*/
|
||||
void nrf_drv_radio802154_extended_address_set(const uint8_t *p_extended_address);
|
||||
|
||||
/**
|
||||
* @brief Set Short Address of this device.
|
||||
*
|
||||
* @param[in] p_short_address Pointer to short address (2 bytes, little-endian).
|
||||
*
|
||||
* This function makes copy of the address.
|
||||
*/
|
||||
void nrf_drv_radio802154_short_address_set(const uint8_t *p_short_address);
|
||||
|
||||
|
||||
/**
|
||||
* @section Functions to request FSM transitions.
|
||||
*
|
||||
* receive() transmit()
|
||||
* --------> -------->
|
||||
* Sleep Receive Transmit
|
||||
* <-------- | /|\<--------
|
||||
* sleep() | | receive() / transmitted() / busy_channel()
|
||||
* | |
|
||||
* energy_detection() | | energy_detected()
|
||||
* \|/ |
|
||||
* Energy detection
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Change radio state to Sleep.
|
||||
*
|
||||
* @note This function should be called only if radio is in Receive state.
|
||||
*
|
||||
* Sleep state is the lowest power state. In this state radio cannot transmit or receive frames.
|
||||
*
|
||||
* @return true If the radio changes it's state to low power mode.
|
||||
* @return false If the driver could not schedule changing state.
|
||||
*/
|
||||
bool nrf_drv_radio802154_sleep(void);
|
||||
|
||||
/**
|
||||
* @brief Change radio state to Receive.
|
||||
*
|
||||
* @note This function should be called in Sleep or Transmit state.
|
||||
*
|
||||
* In Receive state radio receives frames and automatically sends ACK frames when appropriate.
|
||||
* Received frame is reported to higher layer by nrf_radio802154_received() call.
|
||||
*
|
||||
* @param[in] channel Channel number on which radio will receive.
|
||||
* @param[in] force_rx If set to true then function is allowed to stop an ongoing
|
||||
* operation. If set to false then the function will succeed
|
||||
* only when radio is in RX or SLEEP state.
|
||||
*
|
||||
* @return true If the reception procedure was scheduled.
|
||||
* @return false If the driver could not schedule the reception procedure.
|
||||
*/
|
||||
bool nrf_drv_radio802154_receive(uint8_t channel, bool force_rx);
|
||||
|
||||
/**
|
||||
* @brief Change radio state to Transmit.
|
||||
*
|
||||
* @note This function should be called in Receive state. In other states transmission will be
|
||||
* scheduled.
|
||||
*
|
||||
* In Transmit state radio transmits given frame. If requested it waits for ACK frame.
|
||||
* Radio driver wait infinitely for ACK frame. Higher layer is responsible to call
|
||||
* nrf_radio802154_receive() after ACK timeout.
|
||||
* Transmission result is reported to higher layer by nrf_radio802154_transmitted() or
|
||||
* nrf_radio802154_busy_channel() calls.
|
||||
*
|
||||
* @param[in] p_data Pointer to array containing data to transmit. First byte should contain
|
||||
* frame length and following bytes should contain data. CRC is computed
|
||||
* automatically by radio hardware and can contain any bytes.
|
||||
* @param[in] channel Channel number on which radio will transmit given frame.
|
||||
* @param[in] power Transmission power [dBm]. Given value is rounded up to nearest permitted
|
||||
* value.
|
||||
*
|
||||
* @return true If the transmission procedure was scheduled.
|
||||
* @return false If the driver could not schedule the transmission procedure.
|
||||
*/
|
||||
bool nrf_drv_radio802154_transmit(const uint8_t *p_data, uint8_t channel, int8_t power);
|
||||
|
||||
/**
|
||||
* @brief Change radio state to Energy Detection.
|
||||
*
|
||||
* @note This function should be called in Receive state. In other states energy detection
|
||||
* procedure will be scheduled.
|
||||
*
|
||||
* In Energy Detection state radio detects maximum energy for given time. Result of the detection
|
||||
* is reported to the higher layer by nrf_radio802154_energy_detected() call.
|
||||
*
|
||||
* @param[in] channel Channel number on which radio will detect energy.
|
||||
* @param[in] time_us Duration of energy detection procedure. Given value is rounded up to
|
||||
* multiplication of 10s (128 us).
|
||||
*
|
||||
* @return true If the energy detection procedure was scheduled.
|
||||
* @return false If the driver could not schedule the energy detection procedure.
|
||||
*/
|
||||
bool nrf_drv_radio802154_energy_detection(uint8_t channel, uint32_t time_us);
|
||||
|
||||
|
||||
/**
|
||||
* @section Calls to higher layer.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Notify that frame was received.
|
||||
*
|
||||
* @note Buffer pointed by the p_data pointer is not modified by the radio driver (and can't
|
||||
* be used to receive a frame) until nrf_drv_radio802154_buffer_free() function is called.
|
||||
* @note Buffer pointed by the p_data pointer may be modified by the function handler (and other
|
||||
* modules) until nrf_drv_radio802154_buffer_free() function is called.
|
||||
*
|
||||
* @param[in] p_data Pointer to buffer containing received data. First byte in the buffer is
|
||||
* length of the frame and following bytes is the frame itself (after PHR).
|
||||
* @param[in] power RSSI of received frame.
|
||||
* @param[in] lqi LQI of received frame.
|
||||
*/
|
||||
void nrf_drv_radio802154_received(uint8_t * p_data, int8_t power, int8_t lqi);
|
||||
|
||||
/**
|
||||
* @brief Notify that frame was transmitted.
|
||||
*
|
||||
* @note If ACK was requested for transmitted frame this function is called after proper ACK is
|
||||
* received. If ACK was not requested this function is called just after transmission is
|
||||
* ended.
|
||||
*
|
||||
* @param[in] pending_bit Value of pending bit in received ACK or false if ACK was not requested.
|
||||
*/
|
||||
void nrf_drv_radio802154_transmitted(bool pending_bit);
|
||||
|
||||
/**
|
||||
* @brief Notify that frame was not transmitted due to busy channel.
|
||||
*
|
||||
* This function is called if CCA procedure (performed just before transmission) fails.
|
||||
*/
|
||||
void nrf_drv_radio802154_busy_channel(void);
|
||||
|
||||
/**
|
||||
* @brief Notify that Energy Detection procedure finished.
|
||||
*
|
||||
* @param[in] result Maximum energy detected during Energy Detection procedure.
|
||||
*/
|
||||
void nrf_drv_radio802154_energy_detected(int8_t result);
|
||||
|
||||
|
||||
/**
|
||||
* @section Driver memory management
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Notify driver that buffer containing received frame is not used anymore.
|
||||
*
|
||||
* @note The buffer pointed by the @p p_data pointer may be modified by this function.
|
||||
*
|
||||
* @param[in] p_data A pointer to the buffer containing received data that is no more needed by
|
||||
* the higher layer.
|
||||
*/
|
||||
void nrf_drv_radio802154_buffer_free(uint8_t * p_data);
|
||||
|
||||
|
||||
/**
|
||||
* @section RSSI measurement function.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Begin RSSI measurement.
|
||||
*
|
||||
* @note This function should be called in Receive state.
|
||||
*
|
||||
* Begin RSSI measurement. The result will be available in 8 uS. The result can be read by
|
||||
* nrf_radio802154_rssi_last_get() function.
|
||||
*/
|
||||
void nrf_drv_radio802154_rssi_measure(void);
|
||||
|
||||
/**
|
||||
* @brief Get result of last RSSI measurement.
|
||||
*
|
||||
* @returns RSSI measurement result [dBm].
|
||||
*/
|
||||
int8_t nrf_drv_radio802154_rssi_last_get(void);
|
||||
|
||||
|
||||
/**
|
||||
* @section Promiscuous mode.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Enable or disable promiscuous radio mode.
|
||||
*
|
||||
* In promiscuous mode driver notifies higher layer that it received any frame (regardless
|
||||
* frame type or destination address).
|
||||
* In normal mode (not promiscuous) higher layer is not notified about ACK frames and frames with
|
||||
* unknown type. Also frames with destination address not matching this device address are ignored.
|
||||
*
|
||||
* @param[in] enabled If promiscuous mode should be enabled.
|
||||
*/
|
||||
void nrf_drv_radio802154_promiscuous_set(bool enabled);
|
||||
|
||||
/**
|
||||
* @brief Check if radio is in promiscuous mode.
|
||||
*
|
||||
* @retval True Radio is in promiscuous mode.
|
||||
* @retval False Radio is not in promiscuous mode.
|
||||
*/
|
||||
bool nrf_drv_radio802154_promiscuous_get(void);
|
||||
|
||||
|
||||
/**
|
||||
* @section Setting pending bit in automatically transmitted ACK frames.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Enable or disable setting pending bit in automatically transmitted ACK frames.
|
||||
*
|
||||
* Radio driver automatically sends ACK frames in response to unicast frames destined to this node.
|
||||
* Pending bit in ACK frame can be set or cleared regarding data in pending buffer destined to ACK
|
||||
* destination.
|
||||
*
|
||||
* If setting pending bit in ACK frames is disabled, pending bit in every ACK frame is set.
|
||||
* If setting pending bit in ACK frames is enabled, radio driver checks if there is data
|
||||
* in pending buffer destined to ACK destination. If there is no such data, pending bit is cleared.
|
||||
*
|
||||
* @note It is possible that if there is a lot of supported peers radio driver cannot verify
|
||||
* if there is pending data before ACK is sent. In this case pending bit is set.
|
||||
*
|
||||
* @param[in] enabled If setting pending bit in ACK frames is enabled.
|
||||
*/
|
||||
void nrf_drv_radio802154_auto_pending_bit_set(bool enabled);
|
||||
|
||||
/**
|
||||
* @brief Add address of peer node for which there is pending data in the buffer.
|
||||
*
|
||||
* @note This function makes a copy of given address.
|
||||
*
|
||||
* @param[in] p_addr Array of bytes containing address of the node (little-endian).
|
||||
* @param[in] extended If given address is Extended MAC Address or Short MAC Address.
|
||||
*
|
||||
* @retval True Address successfully added to the list.
|
||||
* @retval False There is not enough memory to store this address in the list.
|
||||
*/
|
||||
bool nrf_drv_radio802154_pending_bit_for_addr_set(const uint8_t *p_addr, bool extended);
|
||||
|
||||
/**
|
||||
* @brief Remove address of peer node for which there is no more pending data in the buffer.
|
||||
*
|
||||
* @param[in] p_addr Array of bytes containing address of the node (little-endian).
|
||||
* @param[in] extended If given address is Extended MAC Address or Short MAC Address.
|
||||
*
|
||||
* @retval True Address successfully removed from the list.
|
||||
* @retval False There is no such address in the list.
|
||||
*/
|
||||
bool nrf_drv_radio802154_pending_bit_for_addr_clear(const uint8_t *p_addr, bool extended);
|
||||
|
||||
/**
|
||||
* @brief Remove all addresses of given type from pending bit list.
|
||||
*
|
||||
* @param[in] extended If function should remove all Exnteded MAC Adresses of all Short Addresses.
|
||||
*/
|
||||
void nrf_drv_radio802154_pending_bit_for_addr_reset(bool extended);
|
||||
|
||||
/**
|
||||
* @brief Radio IRQ handler.
|
||||
*/
|
||||
void nrf_drv_radio802154_irq_handler(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* NRF_RADIO802154_H_ */
|
||||
@@ -8,7 +8,8 @@ Microcontroller products. It currently supports the following SoCs:
|
||||
- Intel® Quark™ D2000 Microcontroller
|
||||
- Intel® Quark™ SE Microcontroller
|
||||
|
||||
The current version supported in Zephyr is QMSI 1.4 RC2. See:
|
||||
The current version supported in Zephyr is QMSI 1.4 Release Candidate 3.
|
||||
See:
|
||||
|
||||
https://github.com/quark-mcu/qmsi/releases
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Intel Corporation
|
||||
* Copyright (c) 2017, Intel Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Intel Corporation
|
||||
* Copyright (c) 2017, Intel Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Intel Corporation
|
||||
* Copyright (c) 2017, Intel Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Intel Corporation
|
||||
* Copyright (c) 2017, Intel Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Intel Corporation
|
||||
* Copyright (c) 2017, Intel Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Intel Corporation
|
||||
* Copyright (c) 2017, Intel Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Intel Corporation
|
||||
* Copyright (c) 2017, Intel Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Intel Corporation
|
||||
* Copyright (c) 2017, Intel Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Intel Corporation
|
||||
* Copyright (c) 2017, Intel Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -36,7 +36,9 @@ static void *callback_data[QM_FLASH_NUM];
|
||||
|
||||
QM_ISR_DECLARE(qm_flash_mpr_0_isr)
|
||||
{
|
||||
(*callback[QM_FLASH_0])(callback_data[QM_FLASH_0]);
|
||||
if (callback[QM_FLASH_0]) {
|
||||
(*callback[QM_FLASH_0])(callback_data[QM_FLASH_0]);
|
||||
}
|
||||
QM_FLASH[QM_FLASH_0]->mpr_vsts = QM_FPR_MPR_VSTS_VALID;
|
||||
|
||||
QM_ISR_EOI(QM_IRQ_FLASH_MPR_0_INT_VECTOR);
|
||||
@@ -45,7 +47,9 @@ QM_ISR_DECLARE(qm_flash_mpr_0_isr)
|
||||
#if (QUARK_SE)
|
||||
QM_ISR_DECLARE(qm_flash_mpr_1_isr)
|
||||
{
|
||||
(*callback[QM_FLASH_1])(callback_data[QM_FLASH_1]);
|
||||
if (callback[QM_FLASH_1]) {
|
||||
(*callback[QM_FLASH_1])(callback_data[QM_FLASH_1]);
|
||||
}
|
||||
QM_FLASH[QM_FLASH_1]->mpr_vsts = QM_FPR_MPR_VSTS_VALID;
|
||||
|
||||
QM_ISR_EOI(QM_IRQ_FLASH_MPR_1_INT_VECTOR);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Intel Corporation
|
||||
* Copyright (c) 2017, Intel Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Intel Corporation
|
||||
* Copyright (c) 2017, Intel Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Intel Corporation
|
||||
* Copyright (c) 2017, Intel Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Intel Corporation
|
||||
* Copyright (c) 2017, Intel Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Intel Corporation
|
||||
* Copyright (c) 2017, Intel Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Intel Corporation
|
||||
* Copyright (c) 2017, Intel Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Intel Corporation
|
||||
* Copyright (c) 2017, Intel Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Intel Corporation
|
||||
* Copyright (c) 2017, Intel Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Intel Corporation
|
||||
* Copyright (c) 2017, Intel Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Intel Corporation
|
||||
* Copyright (c) 2017, Intel Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Intel Corporation
|
||||
* Copyright (c) 2017, Intel Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Intel Corporation
|
||||
* Copyright (c) 2017, Intel Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Intel Corporation
|
||||
* Copyright (c) 2017, Intel Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Intel Corporation
|
||||
* Copyright (c) 2017, Intel Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Intel Corporation
|
||||
* Copyright (c) 2017, Intel Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Intel Corporation
|
||||
* Copyright (c) 2017, Intel Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Intel Corporation
|
||||
* Copyright (c) 2017, Intel Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Intel Corporation
|
||||
* Copyright (c) 2017, Intel Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Intel Corporation
|
||||
* Copyright (c) 2017, Intel Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Intel Corporation
|
||||
* Copyright (c) 2017, Intel Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Intel Corporation
|
||||
* Copyright (c) 2017, Intel Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Intel Corporation
|
||||
* Copyright (c) 2017, Intel Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Intel Corporation
|
||||
* Copyright (c) 2017, Intel Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Intel Corporation
|
||||
* Copyright (c) 2017, Intel Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Intel Corporation
|
||||
* Copyright (c) 2017, Intel Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Intel Corporation
|
||||
* Copyright (c) 2017, Intel Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Intel Corporation
|
||||
* Copyright (c) 2017, Intel Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Intel Corporation
|
||||
* Copyright (c) 2017, Intel Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Intel Corporation
|
||||
* Copyright (c) 2017, Intel Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Intel Corporation
|
||||
* Copyright (c) 2017, Intel Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Intel Corporation
|
||||
* Copyright (c) 2017, Intel Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Intel Corporation
|
||||
* Copyright (c) 2017, Intel Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Intel Corporation
|
||||
* Copyright (c) 2017, Intel Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Intel Corporation
|
||||
* Copyright (c) 2017, Intel Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Intel Corporation
|
||||
* Copyright (c) 2017, Intel Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Intel Corporation
|
||||
* Copyright (c) 2017, Intel Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Intel Corporation
|
||||
* Copyright (c) 2017, Intel Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Intel Corporation
|
||||
* Copyright (c) 2017, Intel Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Intel Corporation
|
||||
* Copyright (c) 2017, Intel Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Intel Corporation
|
||||
* Copyright (c) 2017, Intel Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Intel Corporation
|
||||
* Copyright (c) 2017, Intel Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Intel Corporation
|
||||
* Copyright (c) 2017, Intel Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Intel Corporation
|
||||
* Copyright (c) 2017, Intel Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Intel Corporation
|
||||
* Copyright (c) 2017, Intel Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Intel Corporation
|
||||
* Copyright (c) 2017, Intel Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Intel Corporation
|
||||
* Copyright (c) 2017, Intel Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Intel Corporation
|
||||
* Copyright (c) 2017, Intel Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Intel Corporation
|
||||
* Copyright (c) 2017, Intel Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Intel Corporation
|
||||
* Copyright (c) 2017, Intel Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Intel Corporation
|
||||
* Copyright (c) 2017, Intel Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Intel Corporation
|
||||
* Copyright (c) 2017, Intel Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Intel Corporation
|
||||
* Copyright (c) 2017, Intel Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Intel Corporation
|
||||
* Copyright (c) 2017, Intel Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user