Compare commits
85 Commits
v2.0.0-rc2
...
v2.0.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7c0ec4358a | ||
|
|
624ac4801b | ||
|
|
c1d87a5be9 | ||
|
|
0ea5f84143 | ||
|
|
02ee3754c6 | ||
|
|
9f7d4bc475 | ||
|
|
07d750efb3 | ||
|
|
168751a7b7 | ||
|
|
891e50e088 | ||
|
|
053ab4ac41 | ||
|
|
4b3f89646d | ||
|
|
bce38ba98c | ||
|
|
d0ef464201 | ||
|
|
f9c94d49e8 | ||
|
|
79f362760e | ||
|
|
03f14f2e6c | ||
|
|
cc8d92c088 | ||
|
|
f14e024c39 | ||
|
|
ee57741c8c | ||
|
|
c02288b245 | ||
|
|
58fa1a1f8f | ||
|
|
929d9d5e1a | ||
|
|
a6067a38f8 | ||
|
|
64841fb457 | ||
|
|
26c411f6bd | ||
|
|
daa0eb3359 | ||
|
|
ee74098450 | ||
|
|
31f8b6f17d | ||
|
|
861fc23d70 | ||
|
|
912c55847c | ||
|
|
b0b4597ff1 | ||
|
|
51ffabfa56 | ||
|
|
73bf27f243 | ||
|
|
6c2b7937c5 | ||
|
|
3c64a6dcb2 | ||
|
|
60136f00cb | ||
|
|
f04ca02dae | ||
|
|
1668ed70c9 | ||
|
|
551251ace9 | ||
|
|
6bae22d290 | ||
|
|
6f5dc33ef4 | ||
|
|
e5974f72ac | ||
|
|
0d766c668d | ||
|
|
98ad4bb720 | ||
|
|
9a3ee641b6 | ||
|
|
aa9b762d12 | ||
|
|
47f36afdb9 | ||
|
|
67db6162a2 | ||
|
|
1e34ea950c | ||
|
|
e9c858abc8 | ||
|
|
613655e91b | ||
|
|
351bef1dd2 | ||
|
|
9103403308 | ||
|
|
5ac014aac6 | ||
|
|
ac02b30923 | ||
|
|
5d0c6fe562 | ||
|
|
3b271b8455 | ||
|
|
68bfd1422e | ||
|
|
6a71ebf6c5 | ||
|
|
1af31671e3 | ||
|
|
dbc2142402 | ||
|
|
0fb736abfa | ||
|
|
5eb974d8e7 | ||
|
|
a358248ae0 | ||
|
|
576d74e4cd | ||
|
|
c346a62dbb | ||
|
|
7841ebf312 | ||
|
|
efecc28609 | ||
|
|
3479010e7d | ||
|
|
9fdd41be28 | ||
|
|
f4c4d12062 | ||
|
|
39bb8d5205 | ||
|
|
12a11201e2 | ||
|
|
84c38cb93a | ||
|
|
666fa31857 | ||
|
|
a58d730dae | ||
|
|
ee8c661455 | ||
|
|
ed6ce291ba | ||
|
|
9ca0d5e18b | ||
|
|
c18ff87c69 | ||
|
|
e128f3c5d9 | ||
|
|
eddf058e1e | ||
|
|
a09d3d69f9 | ||
|
|
bd4b24810a | ||
|
|
1620d29ba6 |
@@ -72,7 +72,7 @@ Here's a quick summary of resources to help you find your way around:
|
||||
* **Zephyr Project Website**: https://zephyrproject.org
|
||||
|
||||
.. _Slack Invite: https://tinyurl.com/y5glwylp
|
||||
.. _supported boards: http://docs.zephyrproject.org/latest/boards
|
||||
.. _supported boards: http://docs.zephyrproject.org/latest/boards/index.html
|
||||
.. _Zephyr Documentation: http://docs.zephyrproject.org
|
||||
.. _Introduction to Zephyr: http://docs.zephyrproject.org/latest/introduction/index.html
|
||||
.. _Getting Started Guide: http://docs.zephyrproject.org/latest/getting_started/index.html
|
||||
|
||||
2
VERSION
@@ -2,4 +2,4 @@ VERSION_MAJOR = 2
|
||||
VERSION_MINOR = 0
|
||||
PATCHLEVEL = 0
|
||||
VERSION_TWEAK = 0
|
||||
EXTRAVERSION = rc2
|
||||
EXTRAVERSION =
|
||||
|
||||
@@ -35,6 +35,168 @@ GTEXT(_rirq_common_interrupt_swap)
|
||||
* TODO: Revist this if FIRQ becomes configurable.
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
===========================================================
|
||||
RETURN FROM INTERRUPT TO COOPERATIVE THREAD
|
||||
===========================================================
|
||||
|
||||
That's a special case because:
|
||||
1. We return from IRQ handler to a cooperative thread
|
||||
2. During IRQ handling context switch did happen
|
||||
3. Returning to a thread which previously gave control
|
||||
to another thread because of:
|
||||
- Calling k_sleep()
|
||||
- Explicitly yielding
|
||||
- Bumping into locked sync primitive etc
|
||||
|
||||
What (3) means is before passing control to another thread our thread
|
||||
in question:
|
||||
a. Stashed all precious caller-saved registers on its stack
|
||||
b. Pushed return address to the top of the stack as well
|
||||
|
||||
That's how thread's stack looks like right before jumping to another thread:
|
||||
----------------------------->8---------------------------------
|
||||
PRE-CONTEXT-SWITCH STACK
|
||||
|
||||
lower_addr, let's say: 0x1000
|
||||
|
||||
--------------------------------------
|
||||
SP -> | Return address; PC (Program Counter), in fact value taken from
|
||||
| BLINK register in z_arch_switch()
|
||||
--------------------------------------
|
||||
| STATUS32 value, we explicitly save it here for later usage, read-on
|
||||
--------------------------------------
|
||||
| Caller-saved registers: some of R0-R12
|
||||
--------------------------------------
|
||||
|...
|
||||
|...
|
||||
|
||||
higher_addr, let's say: 0x2000
|
||||
----------------------------->8---------------------------------
|
||||
|
||||
When context gets switched the kernel saves callee-saved registers in the
|
||||
thread's stack right on top of pre-switch contents so that's what we have:
|
||||
----------------------------->8---------------------------------
|
||||
POST-CONTEXT-SWITCH STACK
|
||||
|
||||
lower_addr, let's say: 0x1000
|
||||
|
||||
--------------------------------------
|
||||
SP -> | Callee-saved registers: see struct _callee_saved_stack{}
|
||||
| |- R13
|
||||
| |- R14
|
||||
| | ...
|
||||
| \- FP
|
||||
| ...
|
||||
--------------------------------------
|
||||
| Return address; PC (Program Counter)
|
||||
--------------------------------------
|
||||
| STATUS32 value
|
||||
--------------------------------------
|
||||
| Caller-saved registers: some of R0-R12
|
||||
--------------------------------------
|
||||
|...
|
||||
|...
|
||||
|
||||
higher_addr, let's say: 0x2000
|
||||
----------------------------->8---------------------------------
|
||||
|
||||
So how do we return in such a complex scenario.
|
||||
|
||||
First we restore callee-saved regs with help of _load_callee_saved_regs().
|
||||
Now we're back to PRE-CONTEXT-SWITCH STACK (see above).
|
||||
|
||||
Logically our next step is to load return address from the top of the stack
|
||||
and jump to that address to continue execution of the desired thread, but
|
||||
we're still in interrupt handling mode and the only way to return to normal
|
||||
execution mode is to execute "rtie" instruction. And here we need to deal
|
||||
with peculiarities of return from IRQ on ARCv2 cores.
|
||||
|
||||
Instead of simple jump to a return address stored in the tip of thread's stack
|
||||
(with subsequent interrupt enable) ARCv2 core additionally automatically
|
||||
restores some registers from stack. Most important ones are
|
||||
PC ("Program Counter") which holds address of the next instruction to execute
|
||||
and STATUS32 which holds imortant flags including global interrupt enable,
|
||||
zero, carry etc.
|
||||
|
||||
To make things worse depending on ARC core configuration and run-time setup
|
||||
of certain features different set of registers will be restored.
|
||||
|
||||
Typically those same registers are automatically saved on stack on entry to
|
||||
an interrupt, but remember we're returning to the thread which was
|
||||
not interrupted by interrupt and so on its stack there're no automatically
|
||||
saved registers, still inevitably on RTIE execution register restoration
|
||||
will happen. So if we do nothing special we'll end-up with that:
|
||||
----------------------------->8---------------------------------
|
||||
lower_addr, let's say: 0x1000
|
||||
|
||||
--------------------------------------
|
||||
# | Return address; PC (Program Counter)
|
||||
| --------------------------------------
|
||||
| | STATUS32 value
|
||||
| --------------------------------------
|
||||
|
|
||||
sizeof(_irq_stack_frame)
|
||||
|
|
||||
| | Caller-saved registers: R0-R12
|
||||
V --------------------------------------
|
||||
|...
|
||||
SP -> | < Some data on thread's stack>
|
||||
|...
|
||||
|
||||
higher_addr, let's say: 0x2000
|
||||
----------------------------->8---------------------------------
|
||||
|
||||
I.e. we'll go much deeper down the stack over needed return address, read
|
||||
some value from unexpected location in stack and will try to jump there.
|
||||
Nobody knows were we end-up then.
|
||||
|
||||
To work-around that problem we need to mimic existance of IRQ stack frame
|
||||
of which we really only need return address obviously to return where we
|
||||
need to. For that we just shift SP so that it points sizeof(_irq_stack_frame)
|
||||
above like that:
|
||||
----------------------------->8---------------------------------
|
||||
lower_addr, let's say: 0x1000
|
||||
|
||||
SP -> |
|
||||
A | < Some unrelated data >
|
||||
| |
|
||||
|
|
||||
sizeof(_irq_stack_frame)
|
||||
|
|
||||
| --------------------------------------
|
||||
| | Return address; PC (Program Counter)
|
||||
| --------------------------------------
|
||||
# | STATUS32 value
|
||||
--------------------------------------
|
||||
| Caller-saved registers: R0-R12
|
||||
--------------------------------------
|
||||
|...
|
||||
| < Some data on thread's stack>
|
||||
|...
|
||||
|
||||
higher_addr, let's say: 0x2000
|
||||
----------------------------->8---------------------------------
|
||||
|
||||
Indeed R0-R13 "restored" from IRQ stack frame will contain garbage but
|
||||
it makes no difference because we're returning to execution of code as if
|
||||
we're returning from yet another function call and so we will restore
|
||||
all needed registers from the stack.
|
||||
|
||||
One other important remark here is R13.
|
||||
|
||||
CPU hardware automatically save/restore registers in pairs and since we
|
||||
wanted to save/restore R12 in IRQ stack frame as a caller-saved register we
|
||||
just happen to do that for R13 as well. But given compiler treats it as
|
||||
a callee-saved register we save/restore it separately in _callee_saved_stack
|
||||
structure. And when we restore callee-saved registers from stack we among
|
||||
other registers recover R13. But later on return from IRQ with RTIE
|
||||
instruction, R13 will be "restored" again from fake IRQ stack frame and
|
||||
if we don't copy correct R13 value to fake IRQ stack frame R13 value
|
||||
will be corrupted.
|
||||
|
||||
*/
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -207,6 +369,12 @@ _rirq_return_from_coop:
|
||||
bset r0, r0, _ARC_V2_SEC_STAT_IRM_BIT
|
||||
sflag r0
|
||||
#endif
|
||||
|
||||
/*
|
||||
* See verbose explanation of
|
||||
* RETURN FROM INTERRUPT TO COOPERATIVE THREAD above
|
||||
*/
|
||||
|
||||
/* carve fake stack */
|
||||
sub sp, sp, ___isf_t_pc_OFFSET
|
||||
|
||||
|
||||
@@ -609,6 +609,30 @@ static u32_t HardFault(z_arch_esf_t *esf, bool *recoverable)
|
||||
PR_FAULT_INFO("***** HARD FAULT *****");
|
||||
|
||||
#if defined(CONFIG_ARMV6_M_ARMV8_M_BASELINE)
|
||||
/* Workaround for #18712:
|
||||
* HardFault may be due to escalation, as a result of
|
||||
* an SVC instruction that could not be executed; this
|
||||
* can occur if Z_ARCH_EXCEPT() is called by an ISR,
|
||||
* which executes at priority equal to the SVC handler
|
||||
* priority. We handle the case of Kernel OOPS and Stack
|
||||
* Fail here.
|
||||
*/
|
||||
u16_t *ret_addr = (u16_t *)esf->basic.pc;
|
||||
/* SVC is a 16-bit instruction. On a synchronous SVC
|
||||
* escalated to Hard Fault, the return address is the
|
||||
* next instruction, i.e. after the SVC.
|
||||
*/
|
||||
#define _SVC_OPCODE 0xDF00
|
||||
|
||||
u16_t fault_insn = *(ret_addr - 1);
|
||||
if (((fault_insn & 0xff00) == _SVC_OPCODE) &&
|
||||
((fault_insn & 0x00ff) == _SVC_CALL_RUNTIME_EXCEPT)) {
|
||||
|
||||
PR_EXC("Z_ARCH_EXCEPT with reason %x\n", esf->basic.r0);
|
||||
reason = esf->basic.r0;
|
||||
}
|
||||
#undef _SVC_OPCODE
|
||||
|
||||
*recoverable = memory_fault_recoverable(esf);
|
||||
#elif defined(CONFIG_ARMV7_M_ARMV8_M_MAINLINE)
|
||||
*recoverable = false;
|
||||
|
||||
@@ -100,7 +100,7 @@ The STM32MP157A SoC provides the following hardware capabilities:
|
||||
- HDMI-CEC interface
|
||||
- MDIO Slave interface
|
||||
- 3 × SDMMC up to 8-bit (SD / e•MMC™ / SDIO)
|
||||
- 2 × CAN controllers supporting CAN FD protocol, TTCAN capiblity
|
||||
- 2 × CAN controllers supporting CAN FD protocol, TTCAN capability
|
||||
- 2 × USB 2.0 high-speed Host+ 1 × USB 2.0 full-speed OTG simultaneously
|
||||
- 10/100M or Gigabit Ethernet GMAC (IEEE 1588v2 hardware, MII/RMII/GMII/RGMI)
|
||||
- 8- to 14-bit camera interface up to 140 Mbyte/s
|
||||
@@ -232,7 +232,7 @@ Debugging
|
||||
You can debug an application using OpenOCD and GDB. The Solution proposed below
|
||||
is based on the Linux STM32MP1 SDK OpenOCD and is available only for a Linux
|
||||
environment. The firmware must first be loaded by the Cortex®-A7. Developer
|
||||
then attachs the debugger to the running Zephyr using OpenOCD.
|
||||
then attaches the debugger to the running Zephyr using OpenOCD.
|
||||
|
||||
Prerequisite
|
||||
------------
|
||||
|
||||
@@ -142,11 +142,11 @@ Prerequisites:
|
||||
|
||||
Download and install the latest `XDS-110 emulation package`_.
|
||||
|
||||
Follow the directions here to update the firmware:
|
||||
http://software-dl.ti.com/ccs/esd/documents/xdsdebugprobes/emu_xds110.html#updating-the-xds110-firmware
|
||||
Follow these `xds110 firmware update directions
|
||||
<http://software-dl.ti.com/ccs/esd/documents/xdsdebugprobes/emu_xds110.html#updating-the-xds110-firmware>`_
|
||||
|
||||
Note that the emulation package install may place the xdsdfu utility
|
||||
in <install_dir>/ccs_base/common/uscif/xds110/.
|
||||
in ``<install_dir>/ccs_base/common/uscif/xds110/``.
|
||||
|
||||
#. Switch Jumper SOP[2..0] (J15) back to [001].
|
||||
|
||||
@@ -214,6 +214,12 @@ To see program output from UART0, connect a separate terminal window:
|
||||
|
||||
Then press the reset button (SW1) on the board to run the program.
|
||||
|
||||
When using OpenOCD from Zephyr SDK 0.10.3 to flash the device, you may notice
|
||||
the program hangs when starting the network processor on the device, if the
|
||||
program uses it. There is a known issue with how that version of OpenOCD
|
||||
resets the network processor. You would need to manually hit the reset button
|
||||
on the board to properly reset the device after flashing.
|
||||
|
||||
Debugging
|
||||
=========
|
||||
|
||||
@@ -287,15 +293,8 @@ using the TI UniFlash tool for certificate programming.
|
||||
|
||||
Limitations
|
||||
***********
|
||||
The following features are not supported in Zephyr v1.14:
|
||||
|
||||
- IPv6: While the hardware supports it, it has yet to be fully implemented
|
||||
in the SimpleLink Wi-Fi driver.
|
||||
- static IP address: It is not currently possible to set
|
||||
:option:`CONFIG_NET_CONFIG_SETTINGS` to ``y`` and assign a static IP
|
||||
address to the device via :option:`CONFIG_NET_CONFIG_MY_IPV4_ADDR`. DHCP
|
||||
is automatically handled by the SimpleLink Wi-Fi driver to obtain an
|
||||
address dynamically.
|
||||
- While the hardware supports it, IPv6 has yet to be fully implemented
|
||||
in the SimpleLink Wi-Fi device driver in Zephyr.
|
||||
|
||||
References
|
||||
**********
|
||||
|
||||
@@ -36,6 +36,10 @@ CONFIG_CLOCK_STM32_AHB_PRESCALER=1
|
||||
CONFIG_CLOCK_STM32_APB1_PRESCALER=1
|
||||
CONFIG_CLOCK_STM32_APB2_PRESCALER=1
|
||||
|
||||
# LSE oscillator is populated, enable MSI PLL-Mode
|
||||
CONFIG_CLOCK_STM32_LSE=y
|
||||
CONFIG_CLOCK_STM32_MSI_PLL_MODE=y
|
||||
|
||||
# console
|
||||
CONFIG_CONSOLE=y
|
||||
CONFIG_UART_CONSOLE=y
|
||||
|
||||
|
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 22 KiB |
@@ -10,7 +10,7 @@ The EFM32 Pearl Gecko Starter Kit EFM32PG-STK3402A contains an MCU from the
|
||||
EFM32PG family built on an ARM® Cortex®-M4F processor with excellent low
|
||||
power capabilities.
|
||||
|
||||
.. figure:: ./efm32pg_stk3402a.png
|
||||
.. figure:: ./efm32pg_stk3402a.jpg
|
||||
:width: 375px
|
||||
:align: center
|
||||
:alt: EFM32PG-SLSTK3402A
|
||||
|
||||
|
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 22 KiB |
@@ -10,7 +10,7 @@ The EFR32 Flex Gecko Wireless Starter Kit SLWSTK6061A contains a Wireless
|
||||
System-On-Chip from the EFR32FG family built on an ARM® Cortex®-M4F processor
|
||||
with excellent low power capabilities.
|
||||
|
||||
.. figure:: ./efr32_slwstk6061a.png
|
||||
.. figure:: ./efr32_slwstk6061a.jpg
|
||||
:width: 375px
|
||||
:align: center
|
||||
:alt: EFR32-SLWSTK6061A
|
||||
|
||||
@@ -12,7 +12,7 @@ architecture. The board includes a high performance onboard debug probe, audio
|
||||
subsystem, and accelerometer, with several options for adding off-the-shelf
|
||||
add-on boards for networking, sensors, displays, and other interfaces.
|
||||
|
||||
.. image:: ./lpcxpresso55s69.png
|
||||
.. image:: ./lpcxpresso55s69.jpg
|
||||
:width: 720px
|
||||
:align: center
|
||||
:alt: LPCXPRESSO55S69
|
||||
|
||||
BIN
boards/arm/lpcxpresso55s69/doc/lpcxpresso55s69.jpg
Normal file
|
After Width: | Height: | Size: 98 KiB |
|
Before Width: | Height: | Size: 89 KiB |
@@ -95,6 +95,9 @@ config SYS_CLOCK_HW_CYCLES_PER_SEC
|
||||
config SYS_CLOCK_TICKS_PER_SEC
|
||||
default 32768
|
||||
|
||||
config ARCH_HAS_CUSTOM_BUSY_WAIT
|
||||
default y
|
||||
|
||||
endif # RTOS_TIMER
|
||||
|
||||
if !RTOS_TIMER
|
||||
|
||||
@@ -8,7 +8,7 @@ CONFIG_ARM=y
|
||||
CONFIG_SOC_MEC1501_HSZ=y
|
||||
CONFIG_SOC_SERIES_MEC1501X=y
|
||||
CONFIG_BOARD_MEC15XXEVB_ASSY6853=y
|
||||
CONFIG_RTOS_TIMER=n
|
||||
CONFIG_RTOS_TIMER=y
|
||||
|
||||
CONFIG_CONSOLE=y
|
||||
CONFIG_UART_CONSOLE=y
|
||||
|
||||
@@ -20,10 +20,19 @@ the following devices:
|
||||
:height: 335px
|
||||
:alt: ARM V2M MPS2
|
||||
|
||||
In addition to enabling actual hardware usage, this board configuration can
|
||||
also use QEMU to emulate the AN385 platform running on the MPS2+.
|
||||
|
||||
More information about the board can be found at the `V2M MPS2 Website`_.
|
||||
|
||||
The Application Note AN385 can be found at `Application Note AN385`_.
|
||||
|
||||
.. note::
|
||||
This board configuration makes no claims about its suitability for use
|
||||
with actual MPS2 hardware systems using AN385, or any other hardware
|
||||
system. It has been tested on actual hardware, but its primary purpose is
|
||||
for use with QEMU and unit tests.
|
||||
|
||||
Hardware
|
||||
********
|
||||
|
||||
|
||||
@@ -21,8 +21,17 @@ CPU and the following devices:
|
||||
:height: 546px
|
||||
:alt: ARM MPS2+ AN521
|
||||
|
||||
In addition to enabling actual hardware usage, this board configuration can
|
||||
also use QEMU to emulate the AN521 platform running on the MPS2+.
|
||||
|
||||
More information about the board can be found at the `MPS2 FPGA Website`_.
|
||||
|
||||
.. note::
|
||||
This board configuration makes no claims about its suitability for use
|
||||
with actual MPS2 hardware systems using AN521, or any other hardware
|
||||
system. It has been tested on actual hardware, but its primary purpose is
|
||||
for use with QEMU and unit tests.
|
||||
|
||||
Hardware
|
||||
********
|
||||
|
||||
|
||||
|
Before Width: | Height: | Size: 84 KiB After Width: | Height: | Size: 84 KiB |
@@ -9,7 +9,7 @@ Overview
|
||||
The OLIMEX-STM32-H407 is open source hardware and is based on
|
||||
the STMicroelectronics STM32F407ZG ARM Cortex-M4 CPU.
|
||||
|
||||
.. figure:: img/olimex_stm32_h407.png
|
||||
.. figure:: img/olimex_stm32_h407.jpg
|
||||
:width: 540px
|
||||
:align: center
|
||||
:height: 454px
|
||||
|
||||
@@ -102,6 +102,8 @@ QEMU, and display the following console output:
|
||||
threadA: Hello World from arm!
|
||||
threadB: Hello World from arm!
|
||||
|
||||
Exit QEMU by pressing :kbd:`CTRL+A` :kbd:`x`.
|
||||
|
||||
Debugging
|
||||
=========
|
||||
|
||||
|
||||
@@ -107,6 +107,8 @@ QEMU, and display the following console output:
|
||||
threadA: Hello World from arm!
|
||||
threadB: Hello World from arm!
|
||||
|
||||
Exit QEMU by pressing :kbd:`CTRL+A` :kbd:`x`.
|
||||
|
||||
Debugging
|
||||
=========
|
||||
|
||||
|
||||
@@ -52,6 +52,8 @@ QEMU, and display the following console output:
|
||||
threadA: Hello World from riscv32!
|
||||
threadB: Hello World from riscv32!
|
||||
|
||||
Exit QEMU by pressing :kbd:`CTRL+A` :kbd:`x`.
|
||||
|
||||
Debugging
|
||||
=========
|
||||
|
||||
|
||||
@@ -21,8 +21,7 @@ Get the Toolchain and QEMU
|
||||
The minimum version of the `Zephyr SDK tools
|
||||
<https://www.zephyrproject.org/developers/#downloads>`_
|
||||
with toolchain and QEMU support for the RISV64 architecture is v0.10.2.
|
||||
Please see the `installation instructions
|
||||
<https://docs.zephyrproject.org/latest/getting_started/index.html#install-the-required-tools>`_
|
||||
Please see the :ref:`installation instructions <install-required-tools>`
|
||||
for more details.
|
||||
|
||||
Programming and Debugging
|
||||
@@ -62,6 +61,8 @@ QEMU, and display the following console output:
|
||||
threadA: Hello World from riscv64!
|
||||
threadB: Hello World from riscv64!
|
||||
|
||||
Exit QEMU by pressing :kbd:`CTRL+A` :kbd:`x`.
|
||||
|
||||
Debugging
|
||||
=========
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
.. _frdm_kw41z_shield:
|
||||
|
||||
NXP FRDM-KW41Z
|
||||
##############
|
||||
NXP FRDM-KW41Z Shield
|
||||
#####################
|
||||
|
||||
Overview
|
||||
********
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
*/
|
||||
|
||||
&spi1 {
|
||||
status = "ok";
|
||||
status = "okay";
|
||||
cs-gpios = <&gpio1 3 0>;
|
||||
sck-pin = <36>;
|
||||
mosi-pin = <37>;
|
||||
|
||||
@@ -111,6 +111,8 @@ QEMU, and display the following console output:
|
||||
threadA: Hello World from x86!
|
||||
threadB: Hello World from x86!
|
||||
|
||||
Exit QEMU by pressing :kbd:`CTRL+A` :kbd:`x`.
|
||||
|
||||
Debugging
|
||||
=========
|
||||
|
||||
|
||||
@@ -18,155 +18,19 @@ a powerful and flexible Intel |reg| FPGA Altera MAX 10 onboard.
|
||||
|
||||
Up Squared (Credit: https://up-board.org)
|
||||
|
||||
This board configuration enables kernel support for the `UP Squared`_ board,
|
||||
along with the following devices:
|
||||
|
||||
* High Precision Event Timer (HPET)
|
||||
|
||||
* Serial Ports in Polling and Interrupt Driven Modes
|
||||
|
||||
* GPIO
|
||||
|
||||
* I2C
|
||||
This board configuration enables kernel support for the `UP Squared`_ board.
|
||||
|
||||
.. note::
|
||||
This board configuration works on all three variants of `UP Squared`_
|
||||
boards containing Intel |reg| Pentium |trade| SoC,
|
||||
Intel |reg| Celeron |trade| SoC, or Intel |reg| Atom |trade| SoC.
|
||||
|
||||
.. note::
|
||||
This board configuration works only with the default BIOS settings.
|
||||
Enabling/disabling LPSS devices in BIOS (under Advanced -> HAT Configurations)
|
||||
will change the MMIO addresses of these devices, and will prevent
|
||||
the drivers from communicating with these devices. For drivers that support
|
||||
PCI enumeration, :option:`CONFIG_PCI` and :option:`CONFIG_PCI_ENUMERATION`
|
||||
will allow these drivers to probe for the correct MMIO addresses.
|
||||
|
||||
Hardware
|
||||
********
|
||||
|
||||
General information about the board can be found at the `UP Squared`_ website.
|
||||
|
||||
Supported Features
|
||||
==================
|
||||
|
||||
This board supports the following hardware features:
|
||||
|
||||
* HPET
|
||||
|
||||
* Advanced Programmed Interrupt Controller (APIC)
|
||||
|
||||
* Serial Ports in Polling and Interrupt Driven Modes, High-Speed
|
||||
|
||||
* GPIO
|
||||
|
||||
* I2C
|
||||
|
||||
+-----------+------------+-----------------------+-----------------+
|
||||
| Interface | Controller | Driver/Component | PCI Enumeration |
|
||||
+===========+============+=======================+=================+
|
||||
| HPET | on-chip | system clock | Not Supported |
|
||||
+-----------+------------+-----------------------+-----------------+
|
||||
| APIC | on-chip | interrupt controller | Not Supported |
|
||||
+-----------+------------+-----------------------+-----------------+
|
||||
| UART | on-chip | serial port-polling; | Supported |
|
||||
| | | serial port-interrupt | |
|
||||
+-----------+------------+-----------------------+-----------------+
|
||||
| GPIO | on-chip | GPIO controller | Not Supported |
|
||||
+-----------+------------+-----------------------+-----------------+
|
||||
| I2C | on-chip | I2C controller | Supported |
|
||||
+-----------+------------+-----------------------+-----------------+
|
||||
|
||||
The Zephyr kernel currently does not support other hardware features.
|
||||
|
||||
Serial Port Support
|
||||
-------------------
|
||||
|
||||
Serial port I/O is supported in both polling and interrupt-driven modes.
|
||||
|
||||
Baud rates beyond 115.2Kbps (up to 3.6864Mbps) are supported, with additional
|
||||
configuration. The UARTs are fed a master clock which is fed into a PLL which
|
||||
in turn outputs the baud master clock. The PLL is controlled by a per-UART
|
||||
32-bit register called ``PRV_CLOCK_PARAMS`` (aka the ``PCP``), the format of
|
||||
which is:
|
||||
|
||||
+--------+---------+--------+--------+
|
||||
| [31] | [30:16] | [15:1] | [0] |
|
||||
+========+=========+========+========+
|
||||
| enable | ``m`` | ``n`` | toggle |
|
||||
+--------+---------+--------+--------+
|
||||
|
||||
The resulting baud master clock frequency is ``(n/m)`` * master.
|
||||
|
||||
On the UP^2, the master clock is 100MHz, and the firmware by default sets
|
||||
the ``PCP`` to ``0x3d090240``, i.e., ``n = 288``, ``m = 15625``, which
|
||||
results in the de-facto standard 1.8432MHz master clock and a max baud rate
|
||||
of 115.2k. Higher baud rates are enabled by changing the PCP and telling
|
||||
Zephyr what the resulting master clock is.
|
||||
|
||||
Use devicetree to set the value of the ``PRV_CLOCK_PARAMS`` register in
|
||||
the UART block of interest. Typically an overlay ``up_squared.overlay``
|
||||
would be present in the application directory, and would look something
|
||||
like this:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
/ {
|
||||
soc {
|
||||
uart@0 {
|
||||
pcp = <0x3d090900>;
|
||||
clock-frequency = <7372800>;
|
||||
current-speed = <230400>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
The relevant variables are ``pcp`` (the value to use for ``PRV_CLOCK_PARAMS``),
|
||||
and ``clock-frequency`` (the resulting baud master clock). The meaning of
|
||||
``current-speed`` is unchanged, and as usual indicates the initial baud rate.
|
||||
|
||||
Interrupt Controller
|
||||
--------------------
|
||||
|
||||
This board uses the kernel's static Interrupt Descriptor Table (IDT) to program the
|
||||
Advanced Programmable Interrupt Controller (APIC) interrupt redirection table.
|
||||
|
||||
|
||||
+-----+---------+--------------------------+
|
||||
| IRQ | Remarks | Used by Zephyr Kernel |
|
||||
+=====+=========+==========================+
|
||||
| 2 | HPET | timer driver |
|
||||
+-----+---------+--------------------------+
|
||||
| 4 | UART_0 | serial port when used in |
|
||||
| | | interrupt mode |
|
||||
+-----+---------+--------------------------+
|
||||
| 5 | UART_1 | serial port when used in |
|
||||
| | | interrupt mode |
|
||||
+-----+---------+--------------------------+
|
||||
| 14 | GPIO | GPIO APL driver |
|
||||
+-----+---------+--------------------------+
|
||||
| 27 | I2C_0 | I2C DW driver |
|
||||
+-----+---------+--------------------------+
|
||||
| 28 | I2C_1 | I2C DW driver |
|
||||
+-----+---------+--------------------------+
|
||||
| 29 | I2C_2 | I2C DW driver |
|
||||
+-----+---------+--------------------------+
|
||||
| 30 | I2C_3 | I2C DW driver |
|
||||
+-----+---------+--------------------------+
|
||||
| 31 | I2C_4 | I2C DW driver |
|
||||
+-----+---------+--------------------------+
|
||||
| 32 | I2C_5 | I2C DW driver |
|
||||
+-----+---------+--------------------------+
|
||||
| 33 | I2C_6 | I2C DW driver |
|
||||
+-----+---------+--------------------------+
|
||||
| 34 | I2C_7 | I2C DW driver |
|
||||
+-----+---------+--------------------------+
|
||||
|
||||
HPET System Clock Support
|
||||
-------------------------
|
||||
|
||||
The SoC uses HPET timing with legacy-free timer support. The board
|
||||
configuration uses HPET as a system clock timer.
|
||||
.. include:: ../../../../soc/x86/apollo_lake/doc/supported_features.rst
|
||||
|
||||
GPIO
|
||||
----
|
||||
@@ -187,12 +51,6 @@ Connections and IOs
|
||||
Refer to the `UP Squared`_ website and `UP Squared Pinout`_ website
|
||||
for connection diagrams.
|
||||
|
||||
Memory Mappings
|
||||
===============
|
||||
|
||||
This board configuration uses default hardware memory map
|
||||
addresses and sizes.
|
||||
|
||||
Programming and Debugging
|
||||
*************************
|
||||
|
||||
|
||||
@@ -45,6 +45,8 @@ QEMU, and display the following console output:
|
||||
threadA: Hello World from xtensa!
|
||||
threadB: Hello World from xtensa!
|
||||
|
||||
Exit QEMU by pressing :kbd:`CTRL+A` :kbd:`x`.
|
||||
|
||||
Debugging
|
||||
=========
|
||||
|
||||
|
||||
@@ -16,36 +16,11 @@ licensing in this document.
|
||||
.. _GPLv2 License:
|
||||
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/plain/COPYING
|
||||
|
||||
*kconfig* and *kbuild*
|
||||
*Origin:* Linux Kernel
|
||||
|
||||
*Licensing:* `GPLv2 License`_
|
||||
|
||||
*scripts/{checkpatch.pl,checkstack.pl,get_maintainers.pl,spelling.txt}*
|
||||
*Origin:* Linux Kernel
|
||||
|
||||
*Licensing:* `GPLv2 License`_
|
||||
|
||||
*ext/fs/fat/*
|
||||
*Origin:* FatFs is a file system based on the FAT file system specification. This is
|
||||
provided by ELM Chan http://elm-chan.org/fsw/ff/00index_e.html
|
||||
|
||||
*Licensing*:
|
||||
|
||||
Copyright (C) 2016, ChaN, all right reserved.
|
||||
|
||||
FatFs module is an open source software. Redistribution and use of FatFs in
|
||||
source and binary forms, with or without modification, are permitted provided
|
||||
that the following condition is met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
this condition and the following disclaimer.
|
||||
|
||||
This software is provided by the copyright holder and contributors "AS IS"
|
||||
and any warranties related to this software are DISCLAIMED.
|
||||
The copyright owner or contributors be NOT LIABLE for any damages caused
|
||||
by use of this software.
|
||||
|
||||
*ext/hal/cmsis/*
|
||||
*Origin:* https://github.com/ARM-software/CMSIS_5.git
|
||||
|
||||
@@ -53,12 +28,3 @@ licensing in this document.
|
||||
|
||||
.. _ext/hal/cmsis source:
|
||||
https://github.com/zephyrproject-rtos/zephyr/blob/master/ext/hal/cmsis/Include/cmsis_version.h
|
||||
|
||||
*ext/hal/nordic/*
|
||||
*Origin:* https://github.com/NordicSemiconductor/nrfx.git
|
||||
|
||||
*Licensing*: 3-clause BSD (see `ext/hal/nordic source`_)
|
||||
|
||||
.. _ext/hal/nordic source:
|
||||
https://github.com/zephyrproject-rtos/zephyr/blob/master/ext/hal/nordic/nrfx/nrfx.h
|
||||
|
||||
|
||||
@@ -178,6 +178,9 @@ rst_epilog = """
|
||||
import sphinx_rtd_theme
|
||||
html_theme = "sphinx_rtd_theme"
|
||||
html_theme_path = [sphinx_rtd_theme.get_html_theme_path()]
|
||||
html_theme_options = {
|
||||
'prev_next_buttons_location': None
|
||||
}
|
||||
|
||||
if tags.has('release'):
|
||||
is_release = True
|
||||
@@ -522,11 +525,11 @@ html_context = {
|
||||
'theme_logo_only': False,
|
||||
'current_version': version,
|
||||
'versions': ( ("latest", "/"),
|
||||
("2.0.0", "/2.0.0/"),
|
||||
("1.14.0", "/1.14.0/"),
|
||||
("1.13.0", "/1.13.0/"),
|
||||
("1.12.0", "/1.12.0/"),
|
||||
("1.11.0", "/1.11.0/"),
|
||||
("1.10.0", "/1.10.0/"),
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
|
Before Width: | Height: | Size: 59 KiB After Width: | Height: | Size: 59 KiB |
|
Before Width: | Height: | Size: 105 KiB After Width: | Height: | Size: 105 KiB |
@@ -187,7 +187,7 @@ Milestones
|
||||
The following graphic shows the timeline of phases and milestones associated
|
||||
with each release:
|
||||
|
||||
.. figure:: milestones.png
|
||||
.. figure:: milestones.jpg
|
||||
:align: center
|
||||
:alt: Release Milestones
|
||||
:figclass: align-center
|
||||
@@ -199,7 +199,7 @@ This shows how the phases and milestones of one release overlap with those of
|
||||
the next release:
|
||||
|
||||
|
||||
.. figure:: milestones2.png
|
||||
.. figure:: milestones2.jpg
|
||||
:align: center
|
||||
:alt: Release Milestones
|
||||
:figclass: align-center
|
||||
|
||||
@@ -44,6 +44,8 @@ package is already installed locally but a more recent version is available. It
|
||||
is good practice to use this flag if the latest version of a package is
|
||||
required.
|
||||
|
||||
.. _install-required-tools:
|
||||
|
||||
Install the required tools
|
||||
===========================
|
||||
|
||||
@@ -96,6 +98,16 @@ Clone all of Zephyr's repositories in a new :file:`zephyrproject` directory:
|
||||
You can replace :file:`zephyrproject` with another directory name. West creates
|
||||
the directory if it doesn't exist. See :ref:`west-multi-repo` for more details.
|
||||
|
||||
.. important::
|
||||
|
||||
You need to run ``west update`` any time :file:`zephyr/west.yml` changes.
|
||||
This command keeps :ref:`modules` in the :file:`zephyrproject` folder in sync
|
||||
with the code in the zephyr repository, so they work correctly together.
|
||||
|
||||
Some examples when ``west update`` is needed are: whenever you
|
||||
pull the :file:`zephyr` repository, switch branches in it, or perform a ``git
|
||||
bisect`` inside of it.
|
||||
|
||||
.. warning::
|
||||
|
||||
Don't clone into a directory with spaces anywhere in the path.
|
||||
|
||||
@@ -78,10 +78,10 @@ can be disabled if not needed.
|
||||
applications are implemented.
|
||||
|
||||
* **LWM2M** OMA Lightweight Machine-to-Machine Protocol
|
||||
(`LwM2M specification 1.0.2`_) is
|
||||
supported via the "Register Device" API (Register, De-Register and Update)
|
||||
and has template implementations for Security, Server, Device Management and
|
||||
Firmware objects. Bootstrap support is currently not supported.
|
||||
(`LwM2M specification 1.0.2`_) is supported via the "Bootstrap", "Client
|
||||
Registration", "Device Management & Service Enablement" and "Information
|
||||
Reporting" interfaces. The required core LwM2M objects are implemented as
|
||||
well as several IPSO Smart Objects.
|
||||
:ref:`lwm2m-client-sample` implements the library as an example.
|
||||
|
||||
* **DNS** Domain Name Service
|
||||
|
||||
@@ -81,3 +81,5 @@ In terminal #2, type:
|
||||
:gen-args: -DOVERLAY_CONFIG=overlay-e1000.conf
|
||||
:goals: run
|
||||
:compact:
|
||||
|
||||
Exit QEMU by pressing :kbd:`CTRL+A` :kbd:`x`.
|
||||
|
||||
@@ -138,6 +138,7 @@ laptop to normal Wi-Fi use.
|
||||
To stop the daemons, press Ctrl+C in the corresponding terminal windows
|
||||
(you need to stop both ``loop-slip-tap.sh`` and ``loop-socat.sh``).
|
||||
|
||||
Exit QEMU by pressing :kbd:`CTRL+A` :kbd:`x`.
|
||||
|
||||
.. _networking_internet:
|
||||
|
||||
|
||||
|
Before Width: | Height: | Size: 107 KiB After Width: | Height: | Size: 57 KiB |
@@ -139,6 +139,13 @@ commands are documented in the pages for those commands.
|
||||
- String, relative path from the :term:`west installation` root directory
|
||||
to the manifest repository used by ``west update`` and other commands
|
||||
which parse the manifest. Set locally by ``west init``.
|
||||
* - ``update.fetch``
|
||||
- String, one of ``"smart"`` (the default behavior starting in v0.6.1) or
|
||||
``"always"`` (the previous behavior). If set to ``"smart"``, the
|
||||
:ref:`west update <west-multi-repo-cmds>` command will skip fetching
|
||||
from project remotes when those projects' revisions in the manifest file
|
||||
are SHAs or tags which are already available locally. The ``"always"``
|
||||
behavior is to unconditionally fetch from the remote.
|
||||
* - ``zephyr.base``
|
||||
- String, default value to set for the :envvar:`ZEPHYR_BASE` environment
|
||||
variable while the west command is running. By default, this is set to
|
||||
|
||||
@@ -34,6 +34,8 @@ context about the tool.
|
||||
:maxdepth: 1
|
||||
|
||||
install.rst
|
||||
moving-to-west.rst
|
||||
troubleshooting.rst
|
||||
repo-tool.rst
|
||||
manifest.rst
|
||||
config.rst
|
||||
|
||||
57
doc/guides/west/moving-to-west.rst
Normal file
@@ -0,0 +1,57 @@
|
||||
.. _moving-to-west:
|
||||
|
||||
Moving to West
|
||||
##############
|
||||
|
||||
To convert a "pre-west" Zephyr setup on your computer to west, follow these
|
||||
steps. If you are starting from scratch, use the :ref:`getting_started`
|
||||
instead. See :ref:`west-troubleshooting` for advice on common issues.
|
||||
|
||||
#. Install west.
|
||||
|
||||
On Linux::
|
||||
|
||||
pip3 install --user -U west
|
||||
|
||||
On Windows and macOS::
|
||||
|
||||
pip3 install -U west
|
||||
|
||||
For details, see :ref:`west-install`.
|
||||
|
||||
#. Move your zephyr repository to a new :file:`zephyrproject` parent directory,
|
||||
and change directory there.
|
||||
|
||||
On Linux and macOS::
|
||||
|
||||
mkdir zephyrproject
|
||||
mv zephyr zephyrproject
|
||||
cd zephyrproject
|
||||
|
||||
On Windows ``cmd.exe``::
|
||||
|
||||
mkdir zephyrproject
|
||||
move zephyr zephyrproject
|
||||
chdir zephyrproject
|
||||
|
||||
The name :file:`zephyrproject` is recommended, but you can choose any name
|
||||
with no spaces anywhere in the path.
|
||||
|
||||
#. Create a :ref:`west installation <west-installation>` using the zephyr
|
||||
repository as a local manifest repository::
|
||||
|
||||
west init -l zephyr
|
||||
|
||||
This creates :file:`zephyrproject/.west`, marking the root of your
|
||||
installation, and does some other setup. It will not change the contents of
|
||||
the zephyr repository in any way.
|
||||
|
||||
#. Clone the rest of the repositories used by zephyr::
|
||||
|
||||
west update
|
||||
|
||||
**Make sure to run this command whenever you pull zephyr.** Otherwise, your
|
||||
local repositories will get out of sync. (Run ``west list`` for current
|
||||
information on these repositories.)
|
||||
|
||||
You are done: :file:`zephyrproject` is now set up to use west.
|
||||
@@ -1,7 +1,60 @@
|
||||
West Release Notes
|
||||
##################
|
||||
|
||||
v0.6.x
|
||||
v0.6.2
|
||||
******
|
||||
|
||||
This point release fixes an error in the behavior of ``west
|
||||
update --fetch=smart``, introduced in v0.6.1.
|
||||
|
||||
All v0.6.1 users must upgrade.
|
||||
|
||||
v0.6.1
|
||||
******
|
||||
|
||||
.. warning::
|
||||
|
||||
Do not use this point release. Make sure to use v0.6.2 instead.
|
||||
|
||||
The user-visible features in this point release are:
|
||||
|
||||
- The `west update <west-multi-repo-cmds>` command has a new ``--fetch``
|
||||
command line flag and ``update.fetch`` :ref:`configuration option
|
||||
<west-config>`. The default value, "smart", skips fetching SHAs and tags
|
||||
which are available locally.
|
||||
- Better and more consistent error-handling in the ``west diff``, ``west
|
||||
status``, ``west forall``, and ``west update`` commands. Each of these
|
||||
commands can operate on multiple projects; if a subprocess related to one
|
||||
project fails, these commands now continue to operate on the rest of the
|
||||
projects. All of them also now report a nonzero error code from the west
|
||||
process if any of these subprocesses fails (this was previously not true of
|
||||
``west forall`` in particular).
|
||||
- The :ref:`west manifest <west-multi-repo-misc>` command also handles errors
|
||||
better.
|
||||
- The :ref:`west list <west-multi-repo-misc>` command now works even when the
|
||||
projects are not cloned, as long as its format string only requires
|
||||
information which can be read from the manifest file. It still fails if the
|
||||
format string requires data stored in the project repository, e.g. if it
|
||||
includes the ``{sha}`` format string key.
|
||||
- Commands and options which operate on git revisions now accept abbreviated
|
||||
SHAs. For example, ``west init --mr SHA_PREFIX`` now works. Previously, the
|
||||
``--mr`` argument needed to be the entire 40 character SHA if it wasn't a
|
||||
branch or a tag.
|
||||
|
||||
The developer-visible changes to the :ref:`west-apis` are:
|
||||
|
||||
- west.log.banner(): new
|
||||
- west.log.small_banner(): new
|
||||
- west.manifest.Manifest.get_projects(): new
|
||||
- west.manifest.Project.is_cloned(): new
|
||||
- west.commands.WestCommand instances can now access the parsed
|
||||
Manifest object via a new self.manifest property during the
|
||||
do_run() call. If read, it returns the Manifest object or
|
||||
aborts the command if it could not be parsed.
|
||||
- west.manifest.Project.git() now has a capture_stderr kwarg
|
||||
|
||||
|
||||
v0.6.0
|
||||
******
|
||||
|
||||
- No separate bootstrapper
|
||||
|
||||
@@ -155,6 +155,8 @@ This distribution also includes a launcher executable, also named ``west``. When
|
||||
west is installed, the launcher is placed by :file:`pip3` somewhere in the
|
||||
user's ``PATH``. This is the command-line entry point.
|
||||
|
||||
.. _west-manifest-rev:
|
||||
|
||||
The ``manifest-rev`` branch
|
||||
***************************
|
||||
|
||||
@@ -223,13 +225,27 @@ important to understand.
|
||||
(``-m`` defaults to https://github.com/zephyrproject-rtos/zephyr, and
|
||||
the ``-mr`` default is overridden to ``v1.15.0``).
|
||||
|
||||
- ``west update [--rebase] [--keep-descendants] [--exclude-west] [PROJECT
|
||||
...]``: clone and update the specified projects based
|
||||
- ``west update [--fetch {always,smart}] [--rebase] [--keep-descendants]
|
||||
[PROJECT ...]``: clone and update the specified projects based
|
||||
on the current :term:`west manifest`.
|
||||
|
||||
This command parses the manifest, clones any project repositories that are
|
||||
not already present locally, and checks out the project revisions specified
|
||||
in the manifest file, updating ``manifest-rev`` branches along the way.
|
||||
By default, this command:
|
||||
|
||||
#. Parses the manifest file, :file:`west.yml`
|
||||
#. Clones any project repositories that are not already present locally
|
||||
#. Fetches any project revisions in the manifest file which are not already
|
||||
pulled from the remote
|
||||
#. Sets each project's :ref:`manifest-rev <west-manifest-rev>` branch to the
|
||||
current manifest revision
|
||||
#. Checks out those revisions in local working trees
|
||||
|
||||
To operate on a subset of projects only, specify them using the ``PROJECT``
|
||||
positional arguments, which can be either project names as given in the
|
||||
manifest file, or paths to the local project clones.
|
||||
|
||||
To force this command to fetch from project remotes even if the revisions
|
||||
appear to be available locally, either use ``--fetch always`` or set the
|
||||
``update.fetch`` :ref:`configuration option <west-config>` to ``"always"``.
|
||||
|
||||
For safety, ``west update`` uses ``git checkout --detach`` to check out a
|
||||
detached ``HEAD`` at the manifest revision for each updated project, leaving
|
||||
@@ -244,17 +260,22 @@ Miscellaneous Commands
|
||||
======================
|
||||
|
||||
West has a few more commands for managing the multi-repo, which are briefly
|
||||
discussed here.
|
||||
discussed here. Run ``west <command> -h`` for detailed help.
|
||||
|
||||
- ``west list``: Lists project information from the manifest (URL, revision,
|
||||
path, etc.), along with other manifest-related information.
|
||||
- ``west list [-f FORMAT] [PROJECT ...]``: Lists project information from the
|
||||
manifest file, such as URL, revision, path, etc. The printed information can
|
||||
be controlled using the ``-f`` option.
|
||||
|
||||
- ``west manifest --freeze [-o outfile]``: Save a "frozen" representation of
|
||||
the current manifest; all ``revision`` fields are converted to SHAs based on
|
||||
the current ``manifest-rev`` branches.
|
||||
|
||||
- ``west manifest --validate``: Ensure the current manifest file is
|
||||
well-formed. Print information about what's wrong and fail the process in
|
||||
case of error.
|
||||
|
||||
- ``west diff [PROJECT ...]``: Runs a multi-repo ``git diff``
|
||||
for the specified projects (default: all cloned projects).
|
||||
for the specified projects.
|
||||
|
||||
- ``west status [PROJECT ...]``: Like ``west diff``, for
|
||||
running ``git status``.
|
||||
@@ -268,6 +289,8 @@ discussed here.
|
||||
forall -c 'git <command> --options'``. Note that ``west forall`` can be used
|
||||
to run any command, though, not just Git commands.
|
||||
|
||||
- ``west help <command>``: this is equivalent to ``west <command> -h``.
|
||||
|
||||
.. _PyPI:
|
||||
https://pypi.org/project/west/
|
||||
|
||||
|
||||
51
doc/guides/west/troubleshooting.rst
Normal file
@@ -0,0 +1,51 @@
|
||||
.. _west-troubleshooting:
|
||||
|
||||
Troubleshooting West
|
||||
####################
|
||||
|
||||
This page covers common issues with west and how to solve them.
|
||||
|
||||
"invalid choice: 'post-init'"
|
||||
*****************************
|
||||
|
||||
If you see this error when running ``west init``:
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
west: error: argument <command>: invalid choice: 'post-init'
|
||||
(choose from 'init', 'update', 'list', 'manifest', 'diff',
|
||||
'status', 'forall', 'config', 'selfupdate', 'help')
|
||||
|
||||
Then you have an old version of west installed, and are trying to use it in an
|
||||
installation that requires a more recent version.
|
||||
|
||||
The easiest way to resolve this issue is to upgrade west and retry as follows:
|
||||
|
||||
#. Install the latest west with the ``-U`` option for ``pip3 install`` as shown
|
||||
in :ref:`west-install`.
|
||||
|
||||
#. Back up any contents of :file:`zephyrproject/.west/config` that you want to
|
||||
save. (If you don't have any configuration options set, it's safe to skip
|
||||
this step.)
|
||||
|
||||
#. Completely remove the :file:`zephyrproject/.west` directory (if you don't,
|
||||
you will get the "already in an installation" error message discussed next).
|
||||
|
||||
#. Run ``west init`` again.
|
||||
|
||||
"already in an installation"
|
||||
****************************
|
||||
|
||||
You may see this error when running ``west init``:
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
FATAL ERROR: already in an installation (<some directory>), aborting
|
||||
|
||||
If this is unexpected and you're really trying to create a new installation,
|
||||
then it's likely that west is using the :envvar:`ZEPHYR_BASE` :ref:`environment
|
||||
variable <env_vars>` to locate a west installation elsewhere on your system.
|
||||
This is intentional behavior; it allows you to put your Zephyr applications in
|
||||
any directory and still use west.
|
||||
|
||||
To resolve this issue, unset :envvar:`ZEPHYR_BASE` and try again.
|
||||
@@ -41,14 +41,14 @@ provided.
|
||||
|
||||
.. automethod:: __init__
|
||||
|
||||
.. versionadded:: 0.6
|
||||
.. versionadded:: 0.6.0
|
||||
The *requires_installation* parameter.
|
||||
|
||||
Methods:
|
||||
|
||||
.. automethod:: run
|
||||
|
||||
.. versionchanged:: 0.6
|
||||
.. versionchanged:: 0.6.0
|
||||
The *topdir* argument was added.
|
||||
|
||||
.. automethod:: add_parser
|
||||
@@ -86,6 +86,16 @@ provided.
|
||||
|
||||
The argument parser created by calling ``WestCommand.add_parser()``.
|
||||
|
||||
Instance properties:
|
||||
|
||||
.. py:attribute:: manifest
|
||||
|
||||
A read-only property which returns the :py:class:`west.manifest.Manifest`
|
||||
instance for the current manifest file or aborts the program if one was
|
||||
not provided. This is only safe to use from the ``do_run()`` method.
|
||||
|
||||
.. versionadded:: 0.6.1
|
||||
|
||||
.. autoclass:: west.commands.CommandError
|
||||
:show-inheritance:
|
||||
|
||||
@@ -119,7 +129,7 @@ west.configuration
|
||||
|
||||
.. autofunction:: west.configuration.read_config
|
||||
|
||||
.. versionchanged:: 0.6
|
||||
.. versionchanged:: 0.6.0
|
||||
Errors due to an inability to find a local configuration file are ignored.
|
||||
|
||||
.. autofunction:: west.configuration.update_config
|
||||
@@ -136,7 +146,7 @@ west.log
|
||||
********
|
||||
|
||||
.. automodule:: west.log
|
||||
:members: set_verbosity, VERBOSE_NONE, VERBOSE_NORMAL, VERBOSE_VERY, VERBOSE_EXTREME, dbg, inf, wrn, err, die
|
||||
:members: set_verbosity, VERBOSE_NONE, VERBOSE_NORMAL, VERBOSE_VERY, VERBOSE_EXTREME, dbg, inf, wrn, err, die, banner, small_banner
|
||||
|
||||
.. _west-apis-manifest:
|
||||
|
||||
@@ -163,6 +173,10 @@ west.manifest
|
||||
|
||||
.. automethod:: get_remote
|
||||
|
||||
.. automethod:: get_projects
|
||||
|
||||
.. versionadded:: 0.6.1
|
||||
|
||||
.. automethod:: as_frozen_dict
|
||||
|
||||
.. autoclass:: west.manifest.Defaults
|
||||
@@ -174,14 +188,35 @@ west.manifest
|
||||
:member-order: groupwise
|
||||
|
||||
.. autoclass:: west.manifest.Project
|
||||
:members:
|
||||
:member-order: groupwise
|
||||
|
||||
.. automethod:: __init__
|
||||
|
||||
.. automethod:: as_dict
|
||||
|
||||
.. automethod:: format
|
||||
|
||||
.. automethod:: git
|
||||
|
||||
.. versionchanged:: 0.6.1
|
||||
The ``capture_stderr`` kwarg.
|
||||
|
||||
.. automethod:: sha
|
||||
|
||||
.. automethod:: is_ancestor_of
|
||||
|
||||
.. automethod:: is_cloned
|
||||
|
||||
.. versionadded:: 0.6.1
|
||||
|
||||
.. automethod:: is_up_to_date_with
|
||||
|
||||
.. automethod:: is_up_to_date
|
||||
|
||||
.. autoclass:: west.manifest.ManifestProject
|
||||
:members:
|
||||
:member-order: groupwise
|
||||
|
||||
.. versionadded:: 0.6
|
||||
.. versionadded:: 0.6.0
|
||||
|
||||
.. autoclass:: west.manifest.MalformedManifest
|
||||
:show-inheritance:
|
||||
|
||||
3
doc/reference/drivers/device_driver_model.svg
Normal file
|
After Width: | Height: | Size: 43 KiB |
@@ -12,12 +12,17 @@ The Zephyr device model provides a consistent device model for configuring the
|
||||
drivers that are part of a system. The device model is responsible
|
||||
for initializing all the drivers configured into the system.
|
||||
|
||||
Each type of driver (UART, SPI, I2C) is supported by a generic type API.
|
||||
Each type of driver (e.g. UART, SPI, I2C) is supported by a generic type API.
|
||||
|
||||
In this model the driver fills in the pointer to the structure containing the
|
||||
function pointers to its API functions during driver initialization. These
|
||||
structures are placed into the RAM section in initialization level order.
|
||||
|
||||
.. image:: device_driver_model.svg
|
||||
:width: 40%
|
||||
:align: center
|
||||
:alt: Device Driver Model
|
||||
|
||||
Standard Drivers
|
||||
****************
|
||||
|
||||
@@ -38,8 +43,8 @@ are listed below.
|
||||
|
||||
.. important::
|
||||
|
||||
Certain implementations of this device driver do not generate sequences of
|
||||
values that are truly random.
|
||||
Certain implementations of the random number generator device driver
|
||||
do not generate sequences of values that are truly random.
|
||||
|
||||
Synchronous Calls
|
||||
*****************
|
||||
@@ -48,9 +53,9 @@ Zephyr provides a set of device drivers for multiple boards. Each driver
|
||||
should support an interrupt-based implementation, rather than polling, unless
|
||||
the specific hardware does not provide any interrupt.
|
||||
|
||||
High-level calls accessed through device-specific APIs, such as i2c.h
|
||||
or spi.h, are usually intended as synchronous. Thus, these calls should be
|
||||
blocking.
|
||||
High-level calls accessed through device-specific APIs, such as
|
||||
:file:`i2c.h` or :file:`spi.h`, are usually intended as synchronous. Thus,
|
||||
these calls should be blocking.
|
||||
|
||||
Driver APIs
|
||||
***********
|
||||
@@ -379,7 +384,7 @@ pathological/unrecoverable failures, etc., should be handled by
|
||||
assertions.
|
||||
|
||||
When it is appropriate to return error conditions for the caller to
|
||||
check, 0 should be returned on success and a POSIX errno.h code
|
||||
check, 0 should be returned on success and a POSIX :file:`errno.h` code
|
||||
returned on failure. See
|
||||
https://github.com/zephyrproject-rtos/zephyr/wiki/Naming-Conventions#return-codes
|
||||
for details about this.
|
||||
|
||||
@@ -21,29 +21,96 @@ devices (like Wi-Fi and Bluetooth Low Energy), and complex multi-threading,
|
||||
can also be developed using the Zephyr kernel. Examples of such systems
|
||||
include: fitness wearables, smart watches, and IoT wireless gateways.
|
||||
|
||||
Scheduling, Interrupts, and Synchronization
|
||||
*******************************************
|
||||
|
||||
These pages cover basic kernel services related to thread scheduling and
|
||||
synchronization.
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
:maxdepth: 1
|
||||
|
||||
threads/index.rst
|
||||
scheduling/index.rst
|
||||
other/interrupts.rst
|
||||
other/polling.rst
|
||||
synchronization/semaphores.rst
|
||||
synchronization/mutexes.rst
|
||||
|
||||
Data Passing
|
||||
************
|
||||
|
||||
These pages cover kernel objects which can be used to pass data between
|
||||
threads and ISRs.
|
||||
|
||||
The following table summarizes their high-level features.
|
||||
|
||||
=============== ============== =================== ============== ============== ================= ============== ===============================
|
||||
Object Bidirectional? Data structure Data item size Data Alignment ISRs can receive? ISRs can send? Overrun handling
|
||||
=============== ============== =================== ============== ============== ================= ============== ===============================
|
||||
FIFO No Queue Arbitrary [1] 4 B [2] Yes [3] Yes N/A
|
||||
LIFO No Queue Arbitrary [1] 4 B [2] Yes [3] Yes N/A
|
||||
Stack No Array Word Word Yes [3] Yes Undefined behavior
|
||||
Message queue No Ring buffer Power of two Power of two Yes [3] Yes Pend thread or return -errno
|
||||
Mailbox Yes Queue Arbitrary [1] Arbitrary No No N/A
|
||||
Pipe No Ring buffer [4] Arbitrary Arbitrary No No Pend thread or return -errno
|
||||
=============== ============== =================== ============== ============== ================= ============== ===============================
|
||||
|
||||
[1] Callers allocate space for queue overhead in the data
|
||||
elements themselves.
|
||||
|
||||
[2] Objects added with k_fifo_alloc_put() and k_lifo_alloc_put()
|
||||
do not have alignment constraints, but use temporary memory from the
|
||||
calling thread's resource pool.
|
||||
|
||||
[3] ISRs can receive only when passing K_NO_WAIT as the timeout
|
||||
argument.
|
||||
|
||||
[4] Optional.
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
data_passing/fifos.rst
|
||||
data_passing/lifos.rst
|
||||
data_passing/stacks.rst
|
||||
data_passing/message_queues.rst
|
||||
data_passing/mailboxes.rst
|
||||
data_passing/pipes.rst
|
||||
timing/clocks.rst
|
||||
other/cpu_idle.rst
|
||||
timing/timers.rst
|
||||
|
||||
Memory Management
|
||||
*****************
|
||||
|
||||
These pages cover memory allocation and management services.
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
memory/slabs.rst
|
||||
memory/pools.rst
|
||||
memory/heap.rst
|
||||
|
||||
Timing
|
||||
******
|
||||
|
||||
These pages cover timing related services.
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
timing/clocks.rst
|
||||
timing/timers.rst
|
||||
|
||||
Other
|
||||
*****
|
||||
|
||||
These pages cover other kernel services.
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
other/cpu_idle.rst
|
||||
other/atomic.rst
|
||||
other/polling.rst
|
||||
other/float.rst
|
||||
other/ring_buffers.rst
|
||||
other/cxx_support.rst
|
||||
|
||||
@@ -24,6 +24,7 @@ specific release and can be found at https://docs.zephyrproject.org/.
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
release-notes-2.0
|
||||
release-notes-1.14
|
||||
release-notes-1.13
|
||||
release-notes-1.12
|
||||
|
||||
@@ -138,7 +138,7 @@ Build and Infrastructure
|
||||
either simple one-to-one translations of KBuild features or introduce
|
||||
new concepts that replace KBuild concepts. Please re-read the Getting
|
||||
Started guide
|
||||
(https://docs.zephyrproject.org/getting_started/getting_started.html)
|
||||
(https://docs.zephyrproject.org/1.10.0/getting_started/getting_started.html)
|
||||
with updated instructions for setting up and developing on your host-OS.
|
||||
You *will* need to port your own out-of-tree scripts and Makefiles to
|
||||
CMake.
|
||||
|
||||
7
doc/static/zephyr-custom.css
vendored
@@ -64,6 +64,12 @@ div > p + ul, div > p + ol {
|
||||
margin-top: -20px;
|
||||
}
|
||||
|
||||
/* squish space before an hlist in a list */
|
||||
li table.hlist {
|
||||
margin-top: -10px;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
/* add some space before the figure caption */
|
||||
p.caption {
|
||||
# border-top: 1px solid;
|
||||
@@ -105,6 +111,7 @@ table {
|
||||
/* make .. hlist:: tables fill the page */
|
||||
table.hlist {
|
||||
width: 95% !important;
|
||||
table-layout: fixed;
|
||||
}
|
||||
|
||||
/* override rtd theme white-space no-wrap in table heading and content */
|
||||
|
||||
@@ -47,16 +47,19 @@ BUILD_ASSERT_MSG(CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC == 32768,
|
||||
#define CYCLES_PER_TICK \
|
||||
(CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC / CONFIG_SYS_CLOCK_TICKS_PER_SEC)
|
||||
|
||||
/* Mask off bits[31:28] of 32-bit count */
|
||||
#define TIMER_MAX 0x0FFFFFFFUL
|
||||
|
||||
#define CPT1000 ((CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC * 1000UL) \
|
||||
/ CONFIG_SYS_CLOCK_TICKS_PER_SEC)
|
||||
#define TIMER_COUNT_MASK 0x0FFFFFFFUL
|
||||
|
||||
#define CPT_FRACT (CPT1000 - (CYCLES_PER_TICK * 1000UL))
|
||||
#define TIMER_STOPPED 0xF0000000UL
|
||||
|
||||
/* Adjust cycle count programmed into timer for HW restart latency */
|
||||
#define TIMER_ADJUST_LIMIT 2
|
||||
#define TIMER_ADJUST_CYCLES 1
|
||||
|
||||
/* max number of ticks we can load into the timer in one shot */
|
||||
|
||||
#define MAX_TICKS (0x7FFFFFFFU / CYCLES_PER_TICK)
|
||||
#define MAX_TICKS (TIMER_MAX / CYCLES_PER_TICK)
|
||||
|
||||
/*
|
||||
* The spinlock protects all access to the RTMR registers, as well as
|
||||
@@ -68,25 +71,43 @@ BUILD_ASSERT_MSG(CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC == 32768,
|
||||
*/
|
||||
|
||||
static struct k_spinlock lock;
|
||||
static u64_t total_cycles;
|
||||
static u32_t total_cycles;
|
||||
static u32_t cached_icr = CYCLES_PER_TICK;
|
||||
|
||||
/*
|
||||
* Restart XEC RTOS timer with new count down value.
|
||||
* This timer requires its control register to be cleared, the new
|
||||
* preload value written twice, and timer started.
|
||||
*/
|
||||
static INLINE void timer_restart(u32_t val)
|
||||
static void timer_restart(u32_t countdown)
|
||||
{
|
||||
RTMR_REGS->CTRL = 0;
|
||||
RTMR_REGS->PRLD = val;
|
||||
RTMR_REGS->PRLD = val;
|
||||
RTMR_REGS->CTRL = 0U;
|
||||
RTMR_REGS->CTRL = MCHP_RTMR_CTRL_BLK_EN;
|
||||
RTMR_REGS->PRLD = countdown;
|
||||
RTMR_REGS->CTRL = TIMER_START_VAL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read the RTOS timer counter handling the case where the timer
|
||||
* has been reloaded within 1 32KHz clock of reading its count register.
|
||||
* The RTOS timer hardware must synchronize the write to its control register
|
||||
* on the AHB clock domain with the 32KHz clock domain of its internal logic.
|
||||
* This synchronization can take from nearly 0 time up to 1 32KHz clock as it
|
||||
* depends upon which 48MHz AHB clock with a 32KHz period the register write
|
||||
* was on. We detect the timer is in the load state by checking the read-only
|
||||
* count register and the START bit in the control register. If count register
|
||||
* is 0 and the START bit is set then the timer has been started and is in the
|
||||
* process of moving the preload register value into the count register.
|
||||
*/
|
||||
static INLINE u32_t timer_count(void)
|
||||
{
|
||||
u32_t ccr = RTMR_REGS->CNT;
|
||||
|
||||
if ((ccr == 0) && (RTMR_REGS->CTRL & MCHP_RTMR_CTRL_START)) {
|
||||
ccr = cached_icr;
|
||||
}
|
||||
|
||||
return ccr;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_TICKLESS_KERNEL
|
||||
|
||||
static u64_t last_announcement; /* last time we called z_clock_announce() */
|
||||
static u32_t last_announcement; /* last time we called z_clock_announce() */
|
||||
|
||||
/*
|
||||
* Request a timeout n Zephyr ticks in the future from now.
|
||||
@@ -109,6 +130,16 @@ void z_clock_set_timeout(s32_t n, bool idle)
|
||||
u32_t full_cycles; /* full_ticks represented as cycles */
|
||||
u32_t partial_cycles; /* number of cycles to first tick boundary */
|
||||
|
||||
if (idle && (n == K_FOREVER)) {
|
||||
/*
|
||||
* We are not in a locked section. Are writes to two
|
||||
* global objects safe from pre-emption?
|
||||
*/
|
||||
RTMR_REGS->CTRL = 0U; /* stop timer */
|
||||
cached_icr = TIMER_STOPPED;
|
||||
return;
|
||||
}
|
||||
|
||||
if (n < 1) {
|
||||
full_ticks = 0;
|
||||
} else if ((n == K_FOREVER) || (n > MAX_TICKS)) {
|
||||
@@ -117,53 +148,61 @@ void z_clock_set_timeout(s32_t n, bool idle)
|
||||
full_ticks = n - 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* RTMR frequency is fixed at 32KHz resulting in truncation errors.
|
||||
* Tune the denominator taking into account delay in the caller and
|
||||
* this routine.
|
||||
*/
|
||||
full_cycles = (full_ticks * CYCLES_PER_TICK)
|
||||
+ ((full_ticks * CPT_FRACT) / 1000UL);
|
||||
|
||||
/*
|
||||
* There's a wee race condition here. The timer may expire while
|
||||
* we're busy reprogramming it; an interrupt will be queued at the
|
||||
* NVIC and the ISR will be called too early, roughly right
|
||||
* after we unlock, and not because the count we just programmed has
|
||||
* counted down. We can detect this situation only by using one-shot
|
||||
* mode. The counter will be 0 for a "real" interrupt and non-zero
|
||||
* if we have restarted the timer here.
|
||||
*/
|
||||
full_cycles = full_ticks * CYCLES_PER_TICK;
|
||||
|
||||
k_spinlock_key_t key = k_spin_lock(&lock);
|
||||
|
||||
ccr = RTMR_REGS->CNT;
|
||||
total_cycles += (cached_icr - ccr);
|
||||
ccr = timer_count();
|
||||
|
||||
/* turn off to clear any pending interrupt status */
|
||||
RTMR_REGS->CTRL = 0U;
|
||||
GIRQ23_REGS->SRC = MCHP_RTMR_GIRQ_VAL;
|
||||
NVIC_ClearPendingIRQ(RTMR_IRQn);
|
||||
|
||||
temp = total_cycles;
|
||||
temp += (cached_icr - ccr);
|
||||
temp &= TIMER_COUNT_MASK;
|
||||
total_cycles = temp;
|
||||
|
||||
partial_cycles = CYCLES_PER_TICK - (total_cycles % CYCLES_PER_TICK);
|
||||
temp = full_cycles + partial_cycles;
|
||||
cached_icr = full_cycles + partial_cycles;
|
||||
/* adjust for up to one 32KHz cycle startup time */
|
||||
temp = cached_icr;
|
||||
if (temp > TIMER_ADJUST_LIMIT) {
|
||||
temp -= TIMER_ADJUST_CYCLES;
|
||||
}
|
||||
|
||||
timer_restart(temp);
|
||||
cached_icr = temp;
|
||||
|
||||
k_spin_unlock(&lock, key);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the number of Zephyr ticks elapsed from last call to
|
||||
* z_clock_announce in the ISR.
|
||||
* z_clock_announce in the ISR. The caller casts u32_t to s32_t.
|
||||
* We must make sure bit[31] is 0 in the return value.
|
||||
*/
|
||||
u32_t z_clock_elapsed(void)
|
||||
{
|
||||
u32_t ccr;
|
||||
u32_t ticks;
|
||||
s32_t elapsed;
|
||||
|
||||
k_spinlock_key_t key = k_spin_lock(&lock);
|
||||
|
||||
ccr = RTMR_REGS->CNT;
|
||||
ticks = total_cycles - last_announcement;
|
||||
ccr = timer_count();
|
||||
|
||||
/* It may not look efficient but the compiler does a good job */
|
||||
elapsed = (s32_t)total_cycles - (s32_t)last_announcement;
|
||||
if (elapsed < 0) {
|
||||
elapsed = -1 * elapsed;
|
||||
}
|
||||
ticks = (u32_t)elapsed;
|
||||
ticks += cached_icr - ccr;
|
||||
k_spin_unlock(&lock, key);
|
||||
ticks /= CYCLES_PER_TICK;
|
||||
ticks &= TIMER_COUNT_MASK;
|
||||
|
||||
k_spin_unlock(&lock, key);
|
||||
|
||||
return ticks;
|
||||
}
|
||||
@@ -172,36 +211,28 @@ static void xec_rtos_timer_isr(void *arg)
|
||||
{
|
||||
ARG_UNUSED(arg);
|
||||
|
||||
u32_t cycles, preload;
|
||||
u32_t cycles;
|
||||
s32_t ticks;
|
||||
|
||||
k_spinlock_key_t key = k_spin_lock(&lock);
|
||||
|
||||
/*
|
||||
* Clear RTOS timer interrupt RW/1C status in GIRQ23 source register.
|
||||
* NVIC will clear its pending bit on ISR exit.
|
||||
*/
|
||||
GIRQ23_REGS->SRC = MCHP_RTMR_GIRQ_VAL;
|
||||
|
||||
/*
|
||||
* If we get here and the RTMR count registers isn't zero, then
|
||||
* this interrupt is stale: it was queued while z_clock_set_timeout()
|
||||
* was setting a new counter. Just ignore it. See above for more info.
|
||||
*/
|
||||
if (RTMR_REGS->CNT != 0) {
|
||||
k_spin_unlock(&lock, key);
|
||||
return;
|
||||
}
|
||||
|
||||
/* restart the timer */
|
||||
preload = MAX_TICKS * CYCLES_PER_TICK;
|
||||
timer_restart(preload);
|
||||
/* Restart the timer as early as possible to minimize drift... */
|
||||
timer_restart(MAX_TICKS * CYCLES_PER_TICK);
|
||||
|
||||
cycles = cached_icr;
|
||||
cached_icr = preload;
|
||||
cached_icr = MAX_TICKS * CYCLES_PER_TICK;
|
||||
|
||||
total_cycles += cycles;
|
||||
ticks = (total_cycles - last_announcement) / CYCLES_PER_TICK;
|
||||
total_cycles &= TIMER_COUNT_MASK;
|
||||
|
||||
/* handle wrap by using (power of 2) - 1 mask */
|
||||
ticks = total_cycles - last_announcement;
|
||||
ticks &= TIMER_COUNT_MASK;
|
||||
ticks /= CYCLES_PER_TICK;
|
||||
|
||||
last_announcement = total_cycles;
|
||||
|
||||
k_spin_unlock(&lock, key);
|
||||
z_clock_announce(ticks);
|
||||
}
|
||||
@@ -216,14 +247,13 @@ static void xec_rtos_timer_isr(void *arg)
|
||||
|
||||
k_spinlock_key_t key = k_spin_lock(&lock);
|
||||
|
||||
/*
|
||||
* Clear RTOS timer interrupt status RW/1C status in GIRQ23 register.
|
||||
* NVIC will clear its pending bit on ISR exit.
|
||||
*/
|
||||
GIRQ23_REGS->SRC = MCHP_RTMR_GIRQ_VAL;
|
||||
|
||||
total_cycles += CYCLES_PER_TICK;
|
||||
/* Restart the timer as early as possible to minimize drift... */
|
||||
timer_restart(cached_icr);
|
||||
|
||||
u32_t temp = total_cycles + CYCLES_PER_TICK;
|
||||
|
||||
total_cycles = temp & TIMER_COUNT_MASK;
|
||||
k_spin_unlock(&lock, key);
|
||||
|
||||
z_clock_announce(1);
|
||||
@@ -237,11 +267,14 @@ u32_t z_clock_elapsed(void)
|
||||
#endif /* CONFIG_TICKLESS_KERNEL */
|
||||
|
||||
/*
|
||||
* Return an increasing hardware cycle count.
|
||||
* Implementation: We return current total number of cycles elapsed
|
||||
* from first start of the timer. The return value is 32-bits
|
||||
* resulting in only the lower 32-bits of the total count
|
||||
* being returned.
|
||||
* Warning RTOS timer resolution is 30.5 us.
|
||||
* This is called by two code paths:
|
||||
* 1. Kernel call to k_cycle_get_32() -> z_arch_k_cycle_get_32() -> here.
|
||||
* The kernel is casting return to (int) and using it uncasted in math
|
||||
* expressions with int types. Expression result is stored in an int.
|
||||
* 2. If CONFIG_ARCH_HAS_CUSTOM_BUSY_WAIT is not defined then
|
||||
* z_impl_k_busy_wait calls here. This code path uses the value as u32_t.
|
||||
*
|
||||
*/
|
||||
u32_t z_timer_cycle_get_32(void)
|
||||
{
|
||||
@@ -250,30 +283,96 @@ u32_t z_timer_cycle_get_32(void)
|
||||
|
||||
k_spinlock_key_t key = k_spin_lock(&lock);
|
||||
|
||||
ccr = RTMR_REGS->CNT;
|
||||
ret = total_cycles + (cached_icr - ccr);
|
||||
ccr = timer_count();
|
||||
ret = (total_cycles + (cached_icr - ccr)) & TIMER_COUNT_MASK;
|
||||
|
||||
k_spin_unlock(&lock, key);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void z_clock_idle_exit(void)
|
||||
{
|
||||
if (cached_icr == TIMER_STOPPED) {
|
||||
cached_icr = CYCLES_PER_TICK;
|
||||
timer_restart(cached_icr);
|
||||
}
|
||||
}
|
||||
|
||||
void sys_clock_disable(void)
|
||||
{
|
||||
RTMR_REGS->CTRL = 0U;
|
||||
}
|
||||
|
||||
int z_clock_driver_init(struct device *device)
|
||||
{
|
||||
ARG_UNUSED(device);
|
||||
|
||||
mchp_pcr_periph_slp_ctrl(PCR_RTMR, MCHP_PCR_SLEEP_DIS);
|
||||
|
||||
#ifdef CONFIG_TICKLESS_KERNEL
|
||||
cached_icr = MAX_TICKS;
|
||||
#endif
|
||||
|
||||
RTMR_REGS->CTRL = 0U;
|
||||
GIRQ23_REGS->SRC = MCHP_RTMR_GIRQ_VAL;
|
||||
NVIC_ClearPendingIRQ(RTMR_IRQn);
|
||||
|
||||
timer_restart(cached_icr);
|
||||
IRQ_CONNECT(RTMR_IRQn,
|
||||
DT_INST_0_MICROCHIP_XEC_RTOS_TIMER_IRQ_0_PRIORITY,
|
||||
xec_rtos_timer_isr, 0, 0);
|
||||
|
||||
IRQ_CONNECT(RTMR_IRQn, 1, xec_rtos_timer_isr, 0, 0);
|
||||
GIRQ23_REGS->EN_SET = MCHP_RTMR_GIRQ_VAL;
|
||||
|
||||
RTMR_REGS->CTRL = TIMER_START_VAL;
|
||||
irq_enable(RTMR_IRQn);
|
||||
|
||||
#ifdef CONFIG_ARCH_HAS_CUSTOM_BUSY_WAIT
|
||||
u32_t btmr_ctrl = B32TMR0_REGS->CTRL = (MCHP_BTMR_CTRL_ENABLE
|
||||
| MCHP_BTMR_CTRL_AUTO_RESTART
|
||||
| MCHP_BTMR_CTRL_COUNT_UP
|
||||
| (47UL << MCHP_BTMR_CTRL_PRESCALE_POS));
|
||||
B32TMR0_REGS->CTRL = MCHP_BTMR_CTRL_SOFT_RESET;
|
||||
B32TMR0_REGS->CTRL = btmr_ctrl;
|
||||
B32TMR0_REGS->PRLD = 0xFFFFFFFFUL;
|
||||
btmr_ctrl |= MCHP_BTMR_CTRL_START;
|
||||
|
||||
timer_restart(cached_icr);
|
||||
/* wait for Hibernation timer to load count register from preload */
|
||||
while (RTMR_REGS->CNT == 0)
|
||||
;
|
||||
B32TMR0_REGS->CTRL = btmr_ctrl;
|
||||
#else
|
||||
timer_restart(cached_icr);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ARCH_HAS_CUSTOM_BUSY_WAIT
|
||||
|
||||
/*
|
||||
* We implement custom busy wait using a MEC1501 basic timer running on
|
||||
* the 48MHz clock domain. This code is here for future power management
|
||||
* save/restore of the timer context.
|
||||
*/
|
||||
|
||||
/*
|
||||
* 32-bit basic timer 0 configured for 1MHz count up, auto-reload,
|
||||
* and no interrupt generation.
|
||||
*/
|
||||
void z_arch_busy_wait(u32_t usec_to_wait)
|
||||
{
|
||||
if (usec_to_wait == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
u32_t start = B32TMR0_REGS->CNT;
|
||||
|
||||
for (;;) {
|
||||
u32_t curr = B32TMR0_REGS->CNT;
|
||||
|
||||
if ((curr - start) >= usec_to_wait) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -16,17 +16,17 @@ inherits:
|
||||
!include other.yaml # or [other1.yaml, other2.yaml]
|
||||
|
||||
# If the node describes a bus, then the bus type should be given, like below
|
||||
parent:
|
||||
child:
|
||||
bus: <string describing bus type, e.g. "i2c">
|
||||
|
||||
# If the node appears on a bus, then the bus type should be given, like below.
|
||||
#
|
||||
# When looking for a binding for a node, the code checks if the binding for the
|
||||
# parent node contains 'parent: bus: <bus type>'. If it does, then only
|
||||
# bindings with a matching 'child: bus: <bus type>' are considered. This allows
|
||||
# the same type of device to have different bindings depending on what bus it
|
||||
# parent node contains 'child: bus: <bus type>'. If it does, then only bindings
|
||||
# with a matching 'parent: bus: <bus type>' are considered. This allows the
|
||||
# same type of device to have different bindings depending on what bus it
|
||||
# appears on.
|
||||
child:
|
||||
parent:
|
||||
bus: <string describing bus type, e.g. "i2c">
|
||||
|
||||
# 'sub-node' is used to simplify cases where a node has children that can all
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#
|
||||
# Copyright (c) 2018 Nordic Semiconductor ASA
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-5-Clause-Nordic
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
title: Nordic nRF Family SPI Master node
|
||||
|
||||
@@ -465,37 +465,19 @@ struct bt_uuid_128 {
|
||||
*/
|
||||
int bt_uuid_cmp(const struct bt_uuid *u1, const struct bt_uuid *u2);
|
||||
|
||||
/** @brief Copy UUID from packet data (LE) to internal bt_uuid.
|
||||
/** @brief Create a bt_uuid from a little-endian data buffer.
|
||||
*
|
||||
* Copy UUID from packet data in little endian format to internal bt_uuid
|
||||
* format. The data_len parameter is used to determine whether the received
|
||||
* UUID is of 16 or 128 bit format (length 2 or 16). 32 bit format is not
|
||||
* allowed over the air.
|
||||
* Create a bt_uuid from a little-endian data buffer. The data_len parameter
|
||||
* is used to determine whether the UUID is in 16, 32 or 128 bit format
|
||||
* (length 2, 4 or 16). Note: 32 bit format is not allowed over the air.
|
||||
*
|
||||
* @param uuid Pointer to where to write the Bluetooth UUID
|
||||
* @param data pointer to location of the UUID in the packet
|
||||
* @param data_len length of the UUID in the packet
|
||||
* @param uuid Pointer to the bt_uuid variable
|
||||
* @param data pointer to UUID stored in little-endian data buffer
|
||||
* @param data_len length of the UUID in the data buffer
|
||||
*
|
||||
* @return true if the data was valid and the UUID was successfully created.
|
||||
*/
|
||||
bool bt_uuid_create_le(struct bt_uuid *uuid, const u8_t *data, u8_t data_len);
|
||||
|
||||
/** @brief Copy UUID from internal variable to internal bt_uuid.
|
||||
*
|
||||
* Copy UUID from internal variable pointer to internal bt_uuid format.
|
||||
* The data parameter points to a variable (originally stored in bt_uuid_128,
|
||||
* bt_uuid_32 or bt_uuid_16 format) and therefore take into account of
|
||||
* alignment of the val member.
|
||||
* The data_len parameter is used to determine whether to copy the UUID from
|
||||
* 16, 32 or 128 bit format (length 2, 4 or 16).
|
||||
*
|
||||
* @param uuid Pointer to where to write the Bluetooth UUID
|
||||
* @param data pointer to location of the UUID variable
|
||||
* @param data_len length of the UUID in the packet
|
||||
*
|
||||
* @return true if the data was valid and the UUID was successfully created.
|
||||
*/
|
||||
bool bt_uuid_create(struct bt_uuid *uuid, u8_t *data, u8_t data_len);
|
||||
bool bt_uuid_create(struct bt_uuid *uuid, const u8_t *data, u8_t data_len);
|
||||
|
||||
#if defined(CONFIG_BT_DEBUG)
|
||||
/** @brief Convert Bluetooth UUID to string.
|
||||
|
||||
@@ -255,7 +255,7 @@ static inline void k_object_access_all_grant(void *object)
|
||||
#endif /* !CONFIG_USERSPACE */
|
||||
|
||||
/**
|
||||
* grant a thread access to a kernel object
|
||||
* Grant a thread access to a kernel object
|
||||
*
|
||||
* The thread will be granted access to the object if the caller is from
|
||||
* supervisor mode, or the caller is from user mode AND has permissions
|
||||
@@ -267,7 +267,7 @@ static inline void k_object_access_all_grant(void *object)
|
||||
__syscall void k_object_access_grant(void *object, struct k_thread *thread);
|
||||
|
||||
/**
|
||||
* grant a thread access to a kernel object
|
||||
* Revoke a thread's access to a kernel object
|
||||
*
|
||||
* The thread will lose access to the object if the caller is from
|
||||
* supervisor mode, or the caller is from user mode AND has permissions
|
||||
@@ -282,7 +282,7 @@ void k_object_access_revoke(void *object, struct k_thread *thread);
|
||||
__syscall void k_object_release(void *object);
|
||||
|
||||
/**
|
||||
* grant all present and future threads access to an object
|
||||
* Grant all present and future threads access to an object
|
||||
*
|
||||
* If the caller is from supervisor mode, or the caller is from user mode and
|
||||
* have sufficient permissions on the object, then that object will have
|
||||
@@ -1729,13 +1729,14 @@ __deprecated static inline void k_disable_sys_clock_always_on(void)
|
||||
/**
|
||||
* @brief Get system uptime (32-bit version).
|
||||
*
|
||||
* This routine returns the lower 32-bits of the elapsed time since the system
|
||||
* booted, in milliseconds.
|
||||
* This routine returns the lower 32 bits of the system uptime in
|
||||
* milliseconds.
|
||||
*
|
||||
* This routine can be more efficient than k_uptime_get(), as it reduces the
|
||||
* need for interrupt locking and 64-bit math. However, the 32-bit result
|
||||
* cannot hold a system uptime time larger than approximately 50 days, so the
|
||||
* caller must handle possible rollovers.
|
||||
* Because correct conversion requires full precision of the system
|
||||
* clock there is no benefit to using this over k_uptime_get() unless
|
||||
* you know the application will never run long enough for the system
|
||||
* clock to approach 2^32 ticks. Calls to this function may involve
|
||||
* interrupt blocking and 64-bit math.
|
||||
*
|
||||
* @note
|
||||
* @rst
|
||||
@@ -1744,9 +1745,12 @@ __deprecated static inline void k_disable_sys_clock_always_on(void)
|
||||
* :option:`CONFIG_SYS_CLOCK_TICKS_PER_SEC` config option
|
||||
* @endrst
|
||||
*
|
||||
* @return Current uptime in milliseconds.
|
||||
* @return The low 32 bits of the current uptime, in milliseconds.
|
||||
*/
|
||||
__syscall u32_t k_uptime_get_32(void);
|
||||
static inline u32_t k_uptime_get_32(void)
|
||||
{
|
||||
return (u32_t)k_uptime_get();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get elapsed time.
|
||||
|
||||
@@ -229,18 +229,6 @@ u32_t z_tick_get_32(void)
|
||||
#endif
|
||||
}
|
||||
|
||||
u32_t z_impl_k_uptime_get_32(void)
|
||||
{
|
||||
return __ticks_to_ms(z_tick_get_32());
|
||||
}
|
||||
|
||||
#ifdef CONFIG_USERSPACE
|
||||
Z_SYSCALL_HANDLER(k_uptime_get_32)
|
||||
{
|
||||
return z_impl_k_uptime_get_32();
|
||||
}
|
||||
#endif
|
||||
|
||||
s64_t z_impl_k_uptime_get(void)
|
||||
{
|
||||
return __ticks_to_ms(z_tick_get());
|
||||
|
||||
@@ -18,7 +18,7 @@ In loopback mode, the board receives its own messages. This could be used for
|
||||
standalone testing.
|
||||
|
||||
The sample can be built and executed on boards supporting CAN.
|
||||
The LED output pin is defined in the board's device tre.
|
||||
The LED output pin is defined in the board's device tree.
|
||||
|
||||
Sample output
|
||||
=============
|
||||
|
||||
@@ -30,3 +30,5 @@ Sample Output
|
||||
.. code-block:: console
|
||||
|
||||
Hello World! x86
|
||||
|
||||
Exit QEMU by pressing :kbd:`CTRL+A` :kbd:`x`.
|
||||
|
||||
@@ -65,19 +65,9 @@ void dns_result_cb(enum dns_resolve_status status,
|
||||
if (info->ai_family == AF_INET) {
|
||||
hr_family = "IPv4";
|
||||
addr = &net_sin(&info->ai_addr)->sin_addr;
|
||||
|
||||
#if defined(CONFIG_MDNS_RESOLVER) && defined(CONFIG_NET_IPV4)
|
||||
k_delayed_work_init(&mdns_ipv4_timer, do_mdns_ipv4_lookup);
|
||||
k_delayed_work_submit(&mdns_ipv4_timer, 0);
|
||||
#endif
|
||||
} else if (info->ai_family == AF_INET6) {
|
||||
hr_family = "IPv6";
|
||||
addr = &net_sin6(&info->ai_addr)->sin6_addr;
|
||||
|
||||
#if defined(CONFIG_MDNS_RESOLVER) && defined(CONFIG_NET_IPV6)
|
||||
k_delayed_work_init(&mdns_ipv6_timer, do_mdns_ipv6_lookup);
|
||||
k_delayed_work_submit(&mdns_ipv6_timer, 0);
|
||||
#endif
|
||||
} else {
|
||||
LOG_ERR("Invalid IP address family %d", info->ai_family);
|
||||
return;
|
||||
@@ -204,6 +194,11 @@ static void ipv4_addr_add_handler(struct net_mgmt_event_callback *cb,
|
||||
*/
|
||||
k_delayed_work_init(&ipv4_timer, do_ipv4_lookup);
|
||||
k_delayed_work_submit(&ipv4_timer, 0);
|
||||
|
||||
#if defined(CONFIG_MDNS_RESOLVER)
|
||||
k_delayed_work_init(&mdns_ipv4_timer, do_mdns_ipv4_lookup);
|
||||
k_delayed_work_submit(&mdns_ipv4_timer, 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void setup_dhcpv4(struct net_if *iface)
|
||||
@@ -226,14 +221,13 @@ static void setup_dhcpv4(struct net_if *iface)
|
||||
static void do_mdns_ipv4_lookup(struct k_work *work)
|
||||
{
|
||||
static const char *query = "zephyr.local";
|
||||
u16_t dns_id;
|
||||
int ret;
|
||||
|
||||
LOG_DBG("Doing mDNS IPv4 query");
|
||||
|
||||
ret = dns_get_addr_info(query,
|
||||
DNS_QUERY_TYPE_A,
|
||||
&dns_id,
|
||||
NULL,
|
||||
mdns_result_cb,
|
||||
(void *)query,
|
||||
DNS_TIMEOUT);
|
||||
@@ -242,7 +236,7 @@ static void do_mdns_ipv4_lookup(struct k_work *work)
|
||||
return;
|
||||
}
|
||||
|
||||
LOG_DBG("mDNS id %u", dns_id);
|
||||
LOG_DBG("mDNS v4 query sent");
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
@@ -284,6 +278,11 @@ static void setup_ipv4(struct net_if *iface)
|
||||
}
|
||||
|
||||
LOG_DBG("DNS id %u", dns_id);
|
||||
|
||||
#if defined(CONFIG_MDNS_RESOLVER) && defined(CONFIG_NET_IPV4)
|
||||
k_delayed_work_init(&mdns_ipv4_timer, do_mdns_ipv4_lookup);
|
||||
k_delayed_work_submit(&mdns_ipv4_timer, 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
#else
|
||||
@@ -319,20 +318,24 @@ static void do_ipv6_lookup(void)
|
||||
static void setup_ipv6(struct net_if *iface)
|
||||
{
|
||||
do_ipv6_lookup();
|
||||
|
||||
#if defined(CONFIG_MDNS_RESOLVER) && defined(CONFIG_NET_IPV6)
|
||||
k_delayed_work_init(&mdns_ipv6_timer, do_mdns_ipv6_lookup);
|
||||
k_delayed_work_submit(&mdns_ipv6_timer, 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(CONFIG_MDNS_RESOLVER)
|
||||
static void do_mdns_ipv6_lookup(struct k_work *work)
|
||||
{
|
||||
static const char *query = "zephyr.local";
|
||||
u16_t dns_id;
|
||||
int ret;
|
||||
|
||||
LOG_DBG("Doing mDNS IPv6 query");
|
||||
|
||||
ret = dns_get_addr_info(query,
|
||||
DNS_QUERY_TYPE_AAAA,
|
||||
&dns_id,
|
||||
NULL,
|
||||
mdns_result_cb,
|
||||
(void *)query,
|
||||
DNS_TIMEOUT);
|
||||
@@ -341,7 +344,7 @@ static void do_mdns_ipv6_lookup(struct k_work *work)
|
||||
return;
|
||||
}
|
||||
|
||||
LOG_DBG("mDNS id %u", dns_id);
|
||||
LOG_DBG("mDNS v6 query sent");
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -37,7 +37,9 @@ Build the Zephyr version of the application like this:
|
||||
:compact:
|
||||
|
||||
``board_to_use`` defaults to ``qemu_x86``. In this case, you can run the
|
||||
application in QEMU using ``make run``. If you used another BOARD, you
|
||||
application in QEMU using ``make run``.
|
||||
Exit QEMU by pressing :kbd:`CTRL+A` :kbd:`x`.
|
||||
If you used another BOARD, you
|
||||
will need to consult its documentation for application deployment
|
||||
instructions. You can read about Zephyr support for specific boards in
|
||||
the documentation at :ref:`boards`.
|
||||
|
||||
@@ -1,10 +1,18 @@
|
||||
sample:
|
||||
description: BSD Sockets big HTTP download example
|
||||
name: big_http_download
|
||||
common:
|
||||
filter: TOOLCHAIN_HAS_NEWLIB == 1
|
||||
harness: net
|
||||
min_ram: 32
|
||||
min_flash: 128
|
||||
tags: net socket
|
||||
tests:
|
||||
sample.net.sockets.big_http_download:
|
||||
filter: TOOLCHAIN_HAS_NEWLIB == 1
|
||||
harness: net
|
||||
min_ram: 32
|
||||
min_flash: 128
|
||||
tags: net socket
|
||||
extra_configs:
|
||||
- CONFIG_NET_SOCKETS_POSIX_NAMES=y
|
||||
sample.net.sockets.big_http_download.posix:
|
||||
filter: and not CONFIG_NET_SOCKETS_OFFLOAD
|
||||
extra_configs:
|
||||
- CONFIG_NET_SOCKETS_POSIX_NAMES=n
|
||||
- CONFIG_POSIX_API=y
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
|
||||
#include "mbedtls/md.h"
|
||||
|
||||
#ifndef __ZEPHYR__
|
||||
#if !defined(__ZEPHYR__) || defined(CONFIG_POSIX_API)
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
@@ -1,10 +1,18 @@
|
||||
sample:
|
||||
description: BSD Sockets API dumb HTTP server example
|
||||
name: socket_dumb_http_server
|
||||
common:
|
||||
filter: TOOLCHAIN_HAS_NEWLIB == 1
|
||||
harness: net
|
||||
min_ram: 32
|
||||
min_flash: 96
|
||||
tags: net socket
|
||||
tests:
|
||||
sample.net.sockets.dumb_http_server:
|
||||
filter: TOOLCHAIN_HAS_NEWLIB == 1
|
||||
harness: net
|
||||
min_ram: 32
|
||||
min_flash: 96
|
||||
tags: net socket
|
||||
extra_configs:
|
||||
- CONFIG_NET_SOCKETS_POSIX_NAMES=y
|
||||
sample.net.sockets.dumb_http_server.posix:
|
||||
filter: and not CONFIG_NET_SOCKETS_OFFLOAD
|
||||
extra_configs:
|
||||
- CONFIG_NET_SOCKETS_POSIX_NAMES=n
|
||||
- CONFIG_POSIX_API=y
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
|
||||
#ifndef __ZEPHYR__
|
||||
#if !defined(__ZEPHYR__) || defined(CONFIG_POSIX_API)
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
@@ -2,8 +2,17 @@ sample:
|
||||
description: BSD Sockets API TCP echo server sample
|
||||
using non-blocking sockets
|
||||
name: socket_echo_async
|
||||
common:
|
||||
filter: TOOLCHAIN_HAS_NEWLIB == 1
|
||||
harness: net
|
||||
platform_whitelist: qemu_x86
|
||||
tags: net socket
|
||||
tests:
|
||||
sample.net.sockets.echo_async:
|
||||
harness: net
|
||||
platform_whitelist: qemu_x86
|
||||
tags: net socket
|
||||
extra_configs:
|
||||
- CONFIG_NET_SOCKETS_POSIX_NAMES=y
|
||||
sample.net.sockets.echo_async.posix:
|
||||
filter: and not CONFIG_NET_SOCKETS_OFFLOAD
|
||||
extra_configs:
|
||||
- CONFIG_NET_SOCKETS_POSIX_NAMES=n
|
||||
- CONFIG_POSIX_API=y
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifndef __ZEPHYR__
|
||||
#if !defined(__ZEPHYR__) || defined(CONFIG_POSIX_API)
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
@@ -9,10 +9,11 @@
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifndef __ZEPHYR__
|
||||
#if !defined(__ZEPHYR__) || defined(CONFIG_POSIX_API)
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/select.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
@@ -154,6 +154,7 @@ Run echo-client application in QEMU:
|
||||
|
||||
Note that echo-server must be running in the Linux host terminal window
|
||||
before you start the echo-client application in QEMU.
|
||||
Exit QEMU by pressing :kbd:`CTRL+A` :kbd:`x`.
|
||||
|
||||
You can verify TLS communication with a Linux host as well. See
|
||||
https://github.com/zephyrproject-rtos/net-tools documentation for information
|
||||
|
||||
@@ -44,6 +44,7 @@ After the sample starts, it issues HTTP GET request to "google.com:80"
|
||||
and dumps the response. You can edit the source code to issue a request
|
||||
to any other site on the Internet (or on the local network, in which
|
||||
case no NAT/routing setup is needed).
|
||||
Exit QEMU by pressing :kbd:`CTRL+A` :kbd:`x`.
|
||||
|
||||
Enabling TLS support
|
||||
=================================
|
||||
|
||||
@@ -1,10 +1,21 @@
|
||||
sample:
|
||||
description: BSD Sockets API HTTP GET example
|
||||
name: socket_http_get
|
||||
common:
|
||||
filter: TOOLCHAIN_HAS_NEWLIB == 1
|
||||
harness: net
|
||||
min_ram: 32
|
||||
min_flash: 80
|
||||
tags: net socket
|
||||
tests:
|
||||
sample.net.sockets.http_get:
|
||||
filter: TOOLCHAIN_HAS_NEWLIB == 1
|
||||
harness: net
|
||||
min_ram: 32
|
||||
min_flash: 80
|
||||
tags: net socket
|
||||
extra_configs:
|
||||
- CONFIG_NET_SOCKETS_POSIX_NAMES=y
|
||||
# Forcibly defines CONFIG_POSIX_API, which is incompatible with
|
||||
# CONFIG_NET_SOCKETS_POSIX_NAMES.
|
||||
platform_exclude: cc3220sf_launchxl
|
||||
sample.net.sockets.http_get.posix:
|
||||
filter: and not CONFIG_NET_SOCKETS_OFFLOAD
|
||||
extra_configs:
|
||||
- CONFIG_NET_SOCKETS_POSIX_NAMES=n
|
||||
- CONFIG_POSIX_API=y
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifndef __ZEPHYR__
|
||||
#if !defined(__ZEPHYR__) || defined(CONFIG_POSIX_API)
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
@@ -62,4 +62,4 @@ Sample Output
|
||||
Philosopher 4 [C:-1] THINKING [ 2200 ms ]
|
||||
Philosopher 5 [C:-2] THINKING [ 1700 ms ]
|
||||
|
||||
|
||||
Exit QEMU by pressing :kbd:`CTRL+A` :kbd:`x`.
|
||||
|
||||
@@ -54,3 +54,5 @@ Sample Output
|
||||
CMSIS RTOS V1 APIs. This particular implementation demonstrates the
|
||||
usage of multiple preemptible threads of differing
|
||||
priorities, as well as semaphores and thread sleeping.
|
||||
|
||||
Exit QEMU by pressing :kbd:`CTRL+A` :kbd:`x`.
|
||||
|
||||
@@ -64,3 +64,4 @@ Sample Output
|
||||
|
||||
Sample execution successful
|
||||
|
||||
Exit QEMU by pressing :kbd:`CTRL+A` :kbd:`x`.
|
||||
|
||||
@@ -54,3 +54,5 @@ Sample Output
|
||||
CMSIS RTOS V2 APIs. This particular implementation demonstrates the
|
||||
usage of multiple preemptible threads of differing
|
||||
priorities, as well as semaphores and thread sleeping.
|
||||
|
||||
Exit QEMU by pressing :kbd:`CTRL+A` :kbd:`x`.
|
||||
|
||||
@@ -63,3 +63,5 @@ Sample Output
|
||||
Read from message queue: 15
|
||||
|
||||
Sample execution successful
|
||||
|
||||
Exit QEMU by pressing :kbd:`CTRL+A` :kbd:`x`.
|
||||
|
||||
@@ -39,3 +39,4 @@ The easiest way to run this sample is using QEMU:
|
||||
Now start pressing keys on a keyboard, and they will be printed both as
|
||||
hex values and in character form. Be sure to press Enter, Up/Down, etc.
|
||||
key to check what control characters are produced for them.
|
||||
Exit QEMU by pressing :kbd:`CTRL+A` :kbd:`x`.
|
||||
|
||||
@@ -40,3 +40,4 @@ Now start pressing keys on a keyboard, followed by Enter. The input line
|
||||
will be printed back, with a hex code of the last character, to show that
|
||||
line does not include any special "end of line" characters (like LF, CR,
|
||||
etc.)
|
||||
Exit QEMU by pressing :kbd:`CTRL+A` :kbd:`x`.
|
||||
|
||||
@@ -67,3 +67,5 @@ Sample Output
|
||||
[00:00:03.166,006] <wrn> ext_log_system: warning level log, 2 arguments: 12
|
||||
[00:00:03.166,025] <inf> ext_log_system: notice level log, 3 arguments: 105
|
||||
[00:00:03.166,044] <inf> ext_log_system: info level log, 4 arguments : 1 24
|
||||
|
||||
Exit QEMU by pressing :kbd:`CTRL+A` :kbd:`x`.
|
||||
|
||||
@@ -42,3 +42,5 @@ Sample Output
|
||||
threadB: Hello World!
|
||||
|
||||
<repeats endlessly>
|
||||
|
||||
Exit QEMU by pressing :kbd:`CTRL+A` :kbd:`x`.
|
||||
|
||||
@@ -38,6 +38,8 @@ message is the output of the first message, and the resulting
|
||||
output is the first message without spaces. The two messages are
|
||||
marked as 1 and 1' respectively.
|
||||
|
||||
Exit QEMU by pressing :kbd:`CTRL+A` :kbd:`x`.
|
||||
|
||||
Two definitions can be inserted to change the wheel settings and print
|
||||
the state information. To enable the definitions uncomment the last
|
||||
two lines in CMakelists.txt.
|
||||
|
||||
@@ -12,3 +12,4 @@ common:
|
||||
tests:
|
||||
sample.kernel.memory_protection.shared_mem:
|
||||
filter: CONFIG_ARCH_HAS_USERSPACE
|
||||
platform_exclude: twr_ke18f
|
||||
|
||||
@@ -331,9 +331,23 @@ def analyze_die_array(die):
|
||||
elements.append(ub.value + 1)
|
||||
|
||||
if not elements:
|
||||
if type_offset in type_env.keys():
|
||||
mt = type_env[type_offset]
|
||||
if mt.has_kobject():
|
||||
if isinstance(mt, KobjectType) and mt.name == STACK_TYPE:
|
||||
elements.append(1)
|
||||
type_env[die.offset] = ArrayType(die.offset, elements, type_offset)
|
||||
else:
|
||||
type_env[die.offset] = ArrayType(die.offset, elements, type_offset)
|
||||
|
||||
|
||||
def analyze_typedef(die):
|
||||
type_offset = die_get_type_offset(die)
|
||||
|
||||
if type_offset not in type_env.keys():
|
||||
return
|
||||
|
||||
type_env[die.offset] = ArrayType(die.offset, elements, type_offset)
|
||||
type_env[die.offset] = type_env[type_offset]
|
||||
|
||||
|
||||
def addr_deref(elf, addr):
|
||||
@@ -404,6 +418,8 @@ class ElfHelper:
|
||||
analyze_die_const(die)
|
||||
elif die.tag == "DW_TAG_array_type":
|
||||
analyze_die_array(die)
|
||||
elif die.tag == "DW_TAG_typedef":
|
||||
analyze_typedef(die)
|
||||
elif die.tag == "DW_TAG_variable":
|
||||
variables.append(die)
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ sphinx==1.7.5
|
||||
sphinx_rtd_theme
|
||||
sphinx-tabs
|
||||
sphinxcontrib-svg2pdfconverter
|
||||
west>=0.6.0
|
||||
west>=0.6.2
|
||||
wheel==0.30.0
|
||||
# "win32" is used for 64-bit Windows as well
|
||||
windows-curses; sys_platform == "win32"
|
||||
|
||||
@@ -36,9 +36,9 @@ of 115.2k. Higher baud rates are enabled by changing the PCP and telling
|
||||
Zephyr what the resulting master clock is.
|
||||
|
||||
Use devicetree to set the value of the ``PRV_CLOCK_PARAMS`` register in
|
||||
the UART block of interest. Typically an overlay ``up_squared.overlay``
|
||||
would be present in the application directory, and would look something
|
||||
like this:
|
||||
the UART block of interest. Typically a devicetree overlay file would be
|
||||
present in the application directory (specific to the board, such as
|
||||
``up_squared.overlay`` or ``gpmrb.overlay``), with contents like this:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
|
||||
@@ -305,8 +305,6 @@ lll_conn_isr_rx_exit:
|
||||
}
|
||||
|
||||
if (is_rx_enqueue) {
|
||||
LL_ASSERT(lll->handle != 0xFFFF);
|
||||
|
||||
ull_pdu_rx_alloc();
|
||||
|
||||
node_rx->hdr.type = NODE_RX_TYPE_DC_PDU;
|
||||
|
||||
@@ -667,8 +667,13 @@ int ull_conn_rx(memq_link_t *link, struct node_rx_pdu **rx)
|
||||
struct pdu_data *pdu_rx;
|
||||
struct ll_conn *conn;
|
||||
|
||||
conn = ll_conn_get((*rx)->hdr.handle);
|
||||
LL_ASSERT(conn);
|
||||
conn = ll_connected_get((*rx)->hdr.handle);
|
||||
if (!conn) {
|
||||
/* Mark for buffer for release */
|
||||
(*rx)->hdr.type = NODE_RX_TYPE_DC_PDU_RELEASE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
pdu_rx = (void *)(*rx)->pdu;
|
||||
|
||||
|
||||
@@ -615,8 +615,7 @@ static u8_t find_type_cb(const struct bt_gatt_attr *attr, void *user_data)
|
||||
struct bt_uuid_128 ref_uuid;
|
||||
struct bt_uuid_128 recvd_uuid;
|
||||
|
||||
if (!bt_uuid_create_le(&recvd_uuid.uuid, data->value,
|
||||
data->value_len)) {
|
||||
if (!bt_uuid_create(&recvd_uuid.uuid, data->value, data->value_len)) {
|
||||
BT_WARN("Unable to create UUID: size %u", data->value_len);
|
||||
goto skip;
|
||||
}
|
||||
@@ -904,7 +903,7 @@ static u8_t att_read_type_req(struct bt_att *att, struct net_buf *buf)
|
||||
|
||||
start_handle = sys_le16_to_cpu(req->start_handle);
|
||||
end_handle = sys_le16_to_cpu(req->end_handle);
|
||||
if (!bt_uuid_create_le(&u.uuid, req->uuid, uuid_len)) {
|
||||
if (!bt_uuid_create(&u.uuid, req->uuid, uuid_len)) {
|
||||
return BT_ATT_ERR_UNLIKELY;
|
||||
}
|
||||
|
||||
@@ -1211,7 +1210,7 @@ static u8_t att_read_group_req(struct bt_att *att, struct net_buf *buf)
|
||||
start_handle = sys_le16_to_cpu(req->start_handle);
|
||||
end_handle = sys_le16_to_cpu(req->end_handle);
|
||||
|
||||
if (!bt_uuid_create_le(&u.uuid, req->uuid, uuid_len)) {
|
||||
if (!bt_uuid_create(&u.uuid, req->uuid, uuid_len)) {
|
||||
return BT_ATT_ERR_UNLIKELY;
|
||||
}
|
||||
|
||||
@@ -1929,17 +1928,41 @@ static const struct att_handler {
|
||||
|
||||
static att_type_t att_op_get_type(u8_t op)
|
||||
{
|
||||
const struct att_handler *handler;
|
||||
int i;
|
||||
|
||||
for (i = 0, handler = NULL; i < ARRAY_SIZE(handlers); i++) {
|
||||
if (op == handlers[i].op) {
|
||||
return handlers[i].type;
|
||||
}
|
||||
}
|
||||
|
||||
if (op & ATT_CMD_MASK) {
|
||||
switch (op) {
|
||||
case BT_ATT_OP_MTU_REQ:
|
||||
case BT_ATT_OP_FIND_INFO_REQ:
|
||||
case BT_ATT_OP_FIND_TYPE_REQ:
|
||||
case BT_ATT_OP_READ_TYPE_REQ:
|
||||
case BT_ATT_OP_READ_REQ:
|
||||
case BT_ATT_OP_READ_BLOB_REQ:
|
||||
case BT_ATT_OP_READ_MULT_REQ:
|
||||
case BT_ATT_OP_READ_GROUP_REQ:
|
||||
case BT_ATT_OP_WRITE_REQ:
|
||||
case BT_ATT_OP_PREPARE_WRITE_REQ:
|
||||
case BT_ATT_OP_EXEC_WRITE_REQ:
|
||||
return ATT_REQUEST;
|
||||
case BT_ATT_OP_CONFIRM:
|
||||
return ATT_CONFIRMATION;
|
||||
case BT_ATT_OP_WRITE_CMD:
|
||||
case BT_ATT_OP_SIGNED_WRITE_CMD:
|
||||
return ATT_COMMAND;
|
||||
case BT_ATT_OP_ERROR_RSP:
|
||||
case BT_ATT_OP_MTU_RSP:
|
||||
case BT_ATT_OP_FIND_INFO_RSP:
|
||||
case BT_ATT_OP_FIND_TYPE_RSP:
|
||||
case BT_ATT_OP_READ_TYPE_RSP:
|
||||
case BT_ATT_OP_READ_RSP:
|
||||
case BT_ATT_OP_READ_BLOB_RSP:
|
||||
case BT_ATT_OP_READ_MULT_RSP:
|
||||
case BT_ATT_OP_READ_GROUP_RSP:
|
||||
case BT_ATT_OP_WRITE_RSP:
|
||||
case BT_ATT_OP_PREPARE_WRITE_RSP:
|
||||
case BT_ATT_OP_EXEC_WRITE_RSP:
|
||||
return ATT_RESPONSE;
|
||||
case BT_ATT_OP_NOTIFY:
|
||||
return ATT_NOTIFICATION;
|
||||
case BT_ATT_OP_INDICATE:
|
||||
return ATT_INDICATION;
|
||||
}
|
||||
|
||||
return ATT_UNKNOWN;
|
||||
@@ -1969,7 +1992,7 @@ static int bt_att_recv(struct bt_l2cap_chan *chan, struct net_buf *buf)
|
||||
}
|
||||
|
||||
if (!handler) {
|
||||
BT_WARN("Unknown ATT code 0x%02x", hdr->code);
|
||||
BT_WARN("Unhandled ATT code 0x%02x", hdr->code);
|
||||
if (att_op_get_type(hdr->code) != ATT_COMMAND) {
|
||||
send_err_rsp(chan->conn, hdr->code, 0,
|
||||
BT_ATT_ERR_NOT_SUPPORTED);
|
||||
@@ -2047,8 +2070,18 @@ struct net_buf *bt_att_create_pdu(struct bt_conn *conn, u8_t op, size_t len)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
buf = bt_l2cap_create_pdu(NULL, 0);
|
||||
switch (att_op_get_type(op)) {
|
||||
case ATT_RESPONSE:
|
||||
case ATT_CONFIRMATION:
|
||||
/* Use a timeout only when responding/confirming */
|
||||
buf = bt_l2cap_create_pdu_timeout(NULL, 0, ATT_TIMEOUT);
|
||||
break;
|
||||
default:
|
||||
buf = bt_l2cap_create_pdu(NULL, 0);
|
||||
}
|
||||
|
||||
if (!buf) {
|
||||
BT_ERR("Unable to allocate buffer for op 0x%02x", op);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
@@ -1198,6 +1198,17 @@ int bt_conn_send_cb(struct bt_conn *conn, struct net_buf *buf,
|
||||
static bool conn_tx_internal(bt_conn_tx_cb_t cb)
|
||||
{
|
||||
if (cb == att_pdu_sent || cb == att_cfm_sent || cb == att_rsp_sent ||
|
||||
#if defined(CONFIG_BT_SMP)
|
||||
#if defined(CONFIG_BT_PRIVACY)
|
||||
cb == smp_id_sent ||
|
||||
#endif /* CONFIG_BT_PRIVACY */
|
||||
#if defined(CONFIG_BT_SIGNING)
|
||||
cb == smp_sign_info_sent ||
|
||||
#endif /* CONFIG_BT_SIGNING */
|
||||
#if !defined(CONFIG_BT_SMP_SC_PAIR_ONLY)
|
||||
cb == smp_ident_sent ||
|
||||
#endif /* CONFIG_BT_SMP_SC_PAIR_ONLY */
|
||||
#endif /* CONFIG_BT_SMP */
|
||||
#if defined(CONFIG_BT_L2CAP_DYNAMIC_CHANNEL)
|
||||
cb == l2cap_chan_sdu_sent ||
|
||||
#endif /* CONFIG_BT_L2CAP_DYNAMIC_CHANNEL */
|
||||
@@ -2312,7 +2323,8 @@ int bt_conn_le_conn_update(struct bt_conn *conn,
|
||||
return bt_hci_cmd_send(BT_HCI_OP_LE_CONN_UPDATE, buf);
|
||||
}
|
||||
|
||||
struct net_buf *bt_conn_create_pdu(struct net_buf_pool *pool, size_t reserve)
|
||||
struct net_buf *bt_conn_create_pdu_timeout(struct net_buf_pool *pool,
|
||||
size_t reserve, s32_t timeout)
|
||||
{
|
||||
struct net_buf *buf;
|
||||
|
||||
@@ -2327,24 +2339,29 @@ struct net_buf *bt_conn_create_pdu(struct net_buf_pool *pool, size_t reserve)
|
||||
}
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_DEBUG_CONN) ||
|
||||
k_current_get() == &k_sys_work_q.thread) {
|
||||
(k_current_get() == &k_sys_work_q.thread && timeout == K_FOREVER)) {
|
||||
buf = net_buf_alloc(pool, K_NO_WAIT);
|
||||
if (!buf) {
|
||||
BT_WARN("Unable to allocate buffer");
|
||||
BT_WARN("Unable to allocate buffer with K_NO_WAIT");
|
||||
/* Cannot block with K_FOREVER on k_sys_work_q as that
|
||||
* can cause a deadlock when trying to dispatch TX
|
||||
* notification.
|
||||
*/
|
||||
if (k_current_get() == &k_sys_work_q.thread) {
|
||||
BT_WARN("Unable to allocate buffer: timeout %d",
|
||||
timeout);
|
||||
return NULL;
|
||||
}
|
||||
buf = net_buf_alloc(pool, K_FOREVER);
|
||||
buf = net_buf_alloc(pool, timeout);
|
||||
}
|
||||
} else {
|
||||
buf = net_buf_alloc(pool, K_FOREVER);
|
||||
buf = net_buf_alloc(pool, timeout);
|
||||
}
|
||||
|
||||
__ASSERT_NO_MSG(buf);
|
||||
if (!buf) {
|
||||
BT_WARN("Unable to allocate buffer: timeout %d", timeout);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
reserve += sizeof(struct bt_hci_acl_hdr) + CONFIG_BT_HCI_RESERVE;
|
||||
net_buf_reserve(buf, reserve);
|
||||
|
||||
@@ -223,7 +223,11 @@ void bt_conn_security_changed(struct bt_conn *conn, enum bt_security_err err);
|
||||
#endif /* CONFIG_BT_SMP || CONFIG_BT_BREDR */
|
||||
|
||||
/* Prepare a PDU to be sent over a connection */
|
||||
struct net_buf *bt_conn_create_pdu(struct net_buf_pool *pool, size_t reserve);
|
||||
struct net_buf *bt_conn_create_pdu_timeout(struct net_buf_pool *pool,
|
||||
size_t reserve, s32_t timeout);
|
||||
|
||||
#define bt_conn_create_pdu(_pool, _reserve) \
|
||||
bt_conn_create_pdu_timeout(_pool, _reserve, K_FOREVER)
|
||||
|
||||
/* Initialize connection management */
|
||||
int bt_conn_init(void);
|
||||
|
||||
@@ -5666,15 +5666,6 @@ int bt_le_adv_start_internal(const struct bt_le_adv_param *param,
|
||||
return -EALREADY;
|
||||
}
|
||||
|
||||
if (!dir_adv) {
|
||||
err = le_adv_update(ad, ad_len, sd, sd_len,
|
||||
param->options & BT_LE_ADV_OPT_CONNECTABLE,
|
||||
param->options & BT_LE_ADV_OPT_USE_NAME);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
(void)memset(&set_param, 0, sizeof(set_param));
|
||||
|
||||
set_param.min_interval = sys_cpu_to_le16(param->interval_min);
|
||||
@@ -5789,6 +5780,15 @@ int bt_le_adv_start_internal(const struct bt_le_adv_param *param,
|
||||
return err;
|
||||
}
|
||||
|
||||
if (!dir_adv) {
|
||||
err = le_adv_update(ad, ad_len, sd, sd_len,
|
||||
param->options & BT_LE_ADV_OPT_CONNECTABLE,
|
||||
param->options & BT_LE_ADV_OPT_USE_NAME);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
err = set_advertise_enable(true);
|
||||
if (err) {
|
||||
return err;
|
||||
|
||||
@@ -374,7 +374,15 @@ static struct net_buf *l2cap_create_le_sig_pdu(struct net_buf *buf,
|
||||
{
|
||||
struct bt_l2cap_sig_hdr *hdr;
|
||||
|
||||
buf = bt_l2cap_create_pdu(NULL, 0);
|
||||
/* Don't wait more than the minimum RTX timeout of 2 seconds */
|
||||
buf = bt_l2cap_create_pdu_timeout(NULL, 0, K_SECONDS(2));
|
||||
if (!buf) {
|
||||
/* If it was not possible to allocate a buffer within the
|
||||
* timeout return NULL.
|
||||
*/
|
||||
BT_ERR("Unable to allocate buffer for op 0x%02x", code);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
hdr = net_buf_add(buf, sizeof(*hdr));
|
||||
hdr->code = code;
|
||||
@@ -415,6 +423,9 @@ static int l2cap_le_conn_req(struct bt_l2cap_le_chan *ch)
|
||||
|
||||
buf = l2cap_create_le_sig_pdu(NULL, BT_L2CAP_LE_CONN_REQ,
|
||||
ch->chan.ident, sizeof(*req));
|
||||
if (!buf) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
req = net_buf_add(buf, sizeof(*req));
|
||||
req->psm = sys_cpu_to_le16(ch->chan.psm);
|
||||
@@ -467,9 +478,12 @@ void bt_l2cap_encrypt_change(struct bt_conn *conn, u8_t hci_status)
|
||||
}
|
||||
}
|
||||
|
||||
struct net_buf *bt_l2cap_create_pdu(struct net_buf_pool *pool, size_t reserve)
|
||||
struct net_buf *bt_l2cap_create_pdu_timeout(struct net_buf_pool *pool,
|
||||
size_t reserve, s32_t timeout)
|
||||
{
|
||||
return bt_conn_create_pdu(pool, sizeof(struct bt_l2cap_hdr) + reserve);
|
||||
return bt_conn_create_pdu_timeout(pool,
|
||||
sizeof(struct bt_l2cap_hdr) + reserve,
|
||||
timeout);
|
||||
}
|
||||
|
||||
void bt_l2cap_send_cb(struct bt_conn *conn, u16_t cid, struct net_buf *buf,
|
||||
@@ -494,6 +508,9 @@ static void l2cap_send_reject(struct bt_conn *conn, u8_t ident,
|
||||
|
||||
buf = l2cap_create_le_sig_pdu(NULL, BT_L2CAP_CMD_REJECT, ident,
|
||||
sizeof(*rej) + data_len);
|
||||
if (!buf) {
|
||||
return;
|
||||
}
|
||||
|
||||
rej = net_buf_add(buf, sizeof(*rej));
|
||||
rej->reason = sys_cpu_to_le16(reason);
|
||||
@@ -549,6 +566,9 @@ static void le_conn_param_update_req(struct bt_l2cap *l2cap, u8_t ident,
|
||||
|
||||
buf = l2cap_create_le_sig_pdu(buf, BT_L2CAP_CONN_PARAM_RSP, ident,
|
||||
sizeof(*rsp));
|
||||
if (!buf) {
|
||||
return;
|
||||
}
|
||||
|
||||
accepted = le_param_req(conn, ¶m);
|
||||
|
||||
@@ -801,6 +821,9 @@ static void le_conn_req(struct bt_l2cap *l2cap, u8_t ident,
|
||||
|
||||
buf = l2cap_create_le_sig_pdu(buf, BT_L2CAP_LE_CONN_RSP, ident,
|
||||
sizeof(*rsp));
|
||||
if (!buf) {
|
||||
return;
|
||||
}
|
||||
|
||||
rsp = net_buf_add(buf, sizeof(*rsp));
|
||||
(void)memset(rsp, 0, sizeof(*rsp));
|
||||
@@ -933,6 +956,9 @@ static void le_disconn_req(struct bt_l2cap *l2cap, u8_t ident,
|
||||
|
||||
buf = l2cap_create_le_sig_pdu(buf, BT_L2CAP_DISCONN_RSP, ident,
|
||||
sizeof(*rsp));
|
||||
if (!buf) {
|
||||
return;
|
||||
}
|
||||
|
||||
rsp = net_buf_add(buf, sizeof(*rsp));
|
||||
rsp->dcid = sys_cpu_to_le16(chan->rx.cid);
|
||||
@@ -1423,6 +1449,9 @@ static void l2cap_chan_send_credits(struct bt_l2cap_le_chan *chan,
|
||||
|
||||
buf = l2cap_create_le_sig_pdu(buf, BT_L2CAP_LE_CREDITS, get_ident(),
|
||||
sizeof(*ev));
|
||||
if (!buf) {
|
||||
return;
|
||||
}
|
||||
|
||||
ev = net_buf_add(buf, sizeof(*ev));
|
||||
ev->cid = sys_cpu_to_le16(chan->rx.cid);
|
||||
@@ -1684,6 +1713,9 @@ int bt_l2cap_update_conn_param(struct bt_conn *conn,
|
||||
|
||||
buf = l2cap_create_le_sig_pdu(NULL, BT_L2CAP_CONN_PARAM_REQ,
|
||||
get_ident(), sizeof(*req));
|
||||
if (!buf) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
req = net_buf_add(buf, sizeof(*req));
|
||||
req->min_interval = sys_cpu_to_le16(param->interval_min);
|
||||
@@ -1818,6 +1850,9 @@ int bt_l2cap_chan_disconnect(struct bt_l2cap_chan *chan)
|
||||
|
||||
buf = l2cap_create_le_sig_pdu(NULL, BT_L2CAP_DISCONN_REQ,
|
||||
ch->chan.ident, sizeof(*req));
|
||||
if (!buf) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
req = net_buf_add(buf, sizeof(*req));
|
||||
req->dcid = sys_cpu_to_le16(ch->rx.cid);
|
||||
|
||||
@@ -260,7 +260,11 @@ void bt_l2cap_chan_set_state(struct bt_l2cap_chan *chan,
|
||||
void bt_l2cap_encrypt_change(struct bt_conn *conn, u8_t hci_status);
|
||||
|
||||
/* Prepare an L2CAP PDU to be sent over a connection */
|
||||
struct net_buf *bt_l2cap_create_pdu(struct net_buf_pool *pool, size_t reserve);
|
||||
struct net_buf *bt_l2cap_create_pdu_timeout(struct net_buf_pool *pool,
|
||||
size_t reserve, s32_t timeout);
|
||||
|
||||
#define bt_l2cap_create_pdu(_pool, _reserve) \
|
||||
bt_l2cap_create_pdu_timeout(_pool, _reserve, K_FOREVER)
|
||||
|
||||
/* Prepare a L2CAP Response PDU to be sent over a connection */
|
||||
struct net_buf *bt_l2cap_create_rsp(struct net_buf *buf, size_t reserve);
|
||||
|
||||
@@ -368,14 +368,30 @@ static enum bt_security_err auth_err_get(u8_t smp_err)
|
||||
}
|
||||
}
|
||||
|
||||
static struct net_buf *smp_create_pdu(struct bt_conn *conn, u8_t op,
|
||||
size_t len)
|
||||
static struct net_buf *smp_create_pdu(struct bt_smp *smp, u8_t op, size_t len)
|
||||
{
|
||||
struct bt_smp_hdr *hdr;
|
||||
struct net_buf *buf;
|
||||
s32_t timeout;
|
||||
|
||||
buf = bt_l2cap_create_pdu(NULL, 0);
|
||||
/* NULL is not a possible return due to K_FOREVER */
|
||||
/* Don't if session had already timed out */
|
||||
if (atomic_test_bit(smp->flags, SMP_FLAG_TIMEOUT)) {
|
||||
timeout = K_NO_WAIT;
|
||||
} else {
|
||||
timeout = SMP_TIMEOUT;
|
||||
}
|
||||
|
||||
/* Use smaller timeout if returning an error since that could be
|
||||
* caused by lack of buffers.
|
||||
*/
|
||||
buf = bt_l2cap_create_pdu_timeout(NULL, 0, timeout);
|
||||
if (!buf) {
|
||||
/* If it was not possible to allocate a buffer within the
|
||||
* timeout marked it as timed out.
|
||||
*/
|
||||
atomic_set_bit(smp->flags, SMP_FLAG_TIMEOUT);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
hdr = net_buf_add(buf, sizeof(*hdr));
|
||||
hdr->code = op;
|
||||
@@ -679,14 +695,14 @@ static void smp_check_complete(struct bt_conn *conn, u8_t dist_complete)
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_BT_PRIVACY)
|
||||
static void id_sent(struct bt_conn *conn, void *user_data)
|
||||
void smp_id_sent(struct bt_conn *conn, void *user_data)
|
||||
{
|
||||
smp_check_complete(conn, BT_SMP_DIST_ID_KEY);
|
||||
}
|
||||
#endif /* CONFIG_BT_PRIVACY */
|
||||
|
||||
#if defined(CONFIG_BT_SIGNING)
|
||||
static void sign_info_sent(struct bt_conn *conn, void *user_data)
|
||||
void smp_sign_info_sent(struct bt_conn *conn, void *user_data)
|
||||
{
|
||||
smp_check_complete(conn, BT_SMP_DIST_SIGN);
|
||||
}
|
||||
@@ -975,6 +991,38 @@ static void smp_br_derive_ltk(struct bt_smp_br *smp)
|
||||
BT_DBG("LTK derived from LinkKey");
|
||||
}
|
||||
|
||||
static struct net_buf *smp_br_create_pdu(struct bt_smp_br *smp, u8_t op,
|
||||
size_t len)
|
||||
{
|
||||
struct bt_smp_hdr *hdr;
|
||||
struct net_buf *buf;
|
||||
s32_t timeout;
|
||||
|
||||
/* Don't if session had already timed out */
|
||||
if (atomic_test_bit(smp->flags, SMP_FLAG_TIMEOUT)) {
|
||||
timeout = K_NO_WAIT;
|
||||
} else {
|
||||
timeout = SMP_TIMEOUT;
|
||||
}
|
||||
|
||||
/* Use smaller timeout if returning an error since that could be
|
||||
* caused by lack of buffers.
|
||||
*/
|
||||
buf = bt_l2cap_create_pdu_timeout(NULL, 0, timeout);
|
||||
if (!buf) {
|
||||
/* If it was not possible to allocate a buffer within the
|
||||
* timeout marked it as timed out.
|
||||
*/
|
||||
atomic_set_bit(smp->flags, SMP_FLAG_TIMEOUT);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
hdr = net_buf_add(buf, sizeof(*hdr));
|
||||
hdr->code = op;
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
static void smp_br_distribute_keys(struct bt_smp_br *smp)
|
||||
{
|
||||
struct bt_conn *conn = smp->chan.chan.conn;
|
||||
@@ -1002,8 +1050,8 @@ static void smp_br_distribute_keys(struct bt_smp_br *smp)
|
||||
|
||||
smp->local_dist &= ~BT_SMP_DIST_ID_KEY;
|
||||
|
||||
buf = smp_create_pdu(conn, BT_SMP_CMD_IDENT_INFO,
|
||||
sizeof(*id_info));
|
||||
buf = smp_br_create_pdu(smp, BT_SMP_CMD_IDENT_INFO,
|
||||
sizeof(*id_info));
|
||||
if (!buf) {
|
||||
BT_ERR("Unable to allocate Ident Info buffer");
|
||||
return;
|
||||
@@ -1014,7 +1062,7 @@ static void smp_br_distribute_keys(struct bt_smp_br *smp)
|
||||
|
||||
smp_br_send(smp, buf, NULL);
|
||||
|
||||
buf = smp_create_pdu(conn, BT_SMP_CMD_IDENT_ADDR_INFO,
|
||||
buf = smp_br_create_pdu(smp, BT_SMP_CMD_IDENT_ADDR_INFO,
|
||||
sizeof(*id_addr_info));
|
||||
if (!buf) {
|
||||
BT_ERR("Unable to allocate Ident Addr Info buffer");
|
||||
@@ -1024,7 +1072,7 @@ static void smp_br_distribute_keys(struct bt_smp_br *smp)
|
||||
id_addr_info = net_buf_add(buf, sizeof(*id_addr_info));
|
||||
bt_addr_le_copy(&id_addr_info->addr, &bt_dev.id_addr[conn->id]);
|
||||
|
||||
smp_br_send(smp, buf, id_sent);
|
||||
smp_br_send(smp, buf, smp_id_sent);
|
||||
}
|
||||
#endif /* CONFIG_BT_PRIVACY */
|
||||
|
||||
@@ -1035,8 +1083,8 @@ static void smp_br_distribute_keys(struct bt_smp_br *smp)
|
||||
|
||||
smp->local_dist &= ~BT_SMP_DIST_SIGN;
|
||||
|
||||
buf = smp_create_pdu(conn, BT_SMP_CMD_SIGNING_INFO,
|
||||
sizeof(*info));
|
||||
buf = smp_br_create_pdu(smp, BT_SMP_CMD_SIGNING_INFO,
|
||||
sizeof(*info));
|
||||
if (!buf) {
|
||||
BT_ERR("Unable to allocate Signing Info buffer");
|
||||
return;
|
||||
@@ -1052,7 +1100,7 @@ static void smp_br_distribute_keys(struct bt_smp_br *smp)
|
||||
keys->local_csrk.cnt = 0U;
|
||||
}
|
||||
|
||||
smp_br_send(smp, buf, sign_info_sent);
|
||||
smp_br_send(smp, buf, smp_sign_info_sent);
|
||||
}
|
||||
#endif /* CONFIG_BT_SIGNING */
|
||||
}
|
||||
@@ -1102,7 +1150,7 @@ static u8_t smp_br_pairing_req(struct bt_smp_br *smp, struct net_buf *buf)
|
||||
return BT_SMP_ERR_ENC_KEY_SIZE;
|
||||
}
|
||||
|
||||
rsp_buf = smp_create_pdu(conn, BT_SMP_CMD_PAIRING_RSP, sizeof(*rsp));
|
||||
rsp_buf = smp_br_create_pdu(smp, BT_SMP_CMD_PAIRING_RSP, sizeof(*rsp));
|
||||
if (!rsp_buf) {
|
||||
return BT_SMP_ERR_UNSPECIFIED;
|
||||
}
|
||||
@@ -1368,8 +1416,7 @@ static int smp_br_error(struct bt_smp_br *smp, u8_t reason)
|
||||
/* reset context and report */
|
||||
smp_br_reset(smp);
|
||||
|
||||
buf = smp_create_pdu(smp->chan.chan.conn, BT_SMP_CMD_PAIRING_FAIL,
|
||||
sizeof(*rsp));
|
||||
buf = smp_br_create_pdu(smp, BT_SMP_CMD_PAIRING_FAIL, sizeof(*rsp));
|
||||
if (!buf) {
|
||||
return -ENOBUFS;
|
||||
}
|
||||
@@ -1540,7 +1587,7 @@ int bt_smp_br_send_pairing_req(struct bt_conn *conn)
|
||||
smp_br_init(smp);
|
||||
smp->enc_key_size = max_key_size;
|
||||
|
||||
req_buf = smp_create_pdu(conn, BT_SMP_CMD_PAIRING_REQ, sizeof(*req));
|
||||
req_buf = smp_br_create_pdu(smp, BT_SMP_CMD_PAIRING_REQ, sizeof(*req));
|
||||
if (!req_buf) {
|
||||
return -ENOBUFS;
|
||||
}
|
||||
@@ -1657,9 +1704,9 @@ static void smp_timeout(struct k_work *work)
|
||||
bt_keys_clear(smp->chan.chan.conn->le.keys);
|
||||
}
|
||||
|
||||
smp_pairing_complete(smp, BT_SMP_ERR_UNSPECIFIED);
|
||||
|
||||
atomic_set_bit(smp->flags, SMP_FLAG_TIMEOUT);
|
||||
|
||||
smp_pairing_complete(smp, BT_SMP_ERR_UNSPECIFIED);
|
||||
}
|
||||
|
||||
static void smp_send(struct bt_smp *smp, struct net_buf *buf,
|
||||
@@ -1677,8 +1724,7 @@ static int smp_error(struct bt_smp *smp, u8_t reason)
|
||||
/* reset context and report */
|
||||
smp_pairing_complete(smp, reason);
|
||||
|
||||
buf = smp_create_pdu(smp->chan.chan.conn, BT_SMP_CMD_PAIRING_FAIL,
|
||||
sizeof(*rsp));
|
||||
buf = smp_create_pdu(smp, BT_SMP_CMD_PAIRING_FAIL, sizeof(*rsp));
|
||||
if (!buf) {
|
||||
return -ENOBUFS;
|
||||
}
|
||||
@@ -1694,11 +1740,10 @@ static int smp_error(struct bt_smp *smp, u8_t reason)
|
||||
|
||||
static u8_t smp_send_pairing_random(struct bt_smp *smp)
|
||||
{
|
||||
struct bt_conn *conn = smp->chan.chan.conn;
|
||||
struct bt_smp_pairing_random *req;
|
||||
struct net_buf *rsp_buf;
|
||||
|
||||
rsp_buf = smp_create_pdu(conn, BT_SMP_CMD_PAIRING_RANDOM, sizeof(*req));
|
||||
rsp_buf = smp_create_pdu(smp, BT_SMP_CMD_PAIRING_RANDOM, sizeof(*req));
|
||||
if (!rsp_buf) {
|
||||
return BT_SMP_ERR_UNSPECIFIED;
|
||||
}
|
||||
@@ -1766,7 +1811,6 @@ static int smp_c1(const u8_t k[16], const u8_t r[16],
|
||||
|
||||
static u8_t smp_send_pairing_confirm(struct bt_smp *smp)
|
||||
{
|
||||
struct bt_conn *conn = smp->chan.chan.conn;
|
||||
struct bt_smp_pairing_confirm *req;
|
||||
struct net_buf *buf;
|
||||
u8_t r;
|
||||
@@ -1792,7 +1836,7 @@ static u8_t smp_send_pairing_confirm(struct bt_smp *smp)
|
||||
return BT_SMP_ERR_UNSPECIFIED;
|
||||
}
|
||||
|
||||
buf = smp_create_pdu(conn, BT_SMP_CMD_PAIRING_CONFIRM, sizeof(*req));
|
||||
buf = smp_create_pdu(smp, BT_SMP_CMD_PAIRING_CONFIRM, sizeof(*req));
|
||||
if (!buf) {
|
||||
return BT_SMP_ERR_UNSPECIFIED;
|
||||
}
|
||||
@@ -1812,7 +1856,7 @@ static u8_t smp_send_pairing_confirm(struct bt_smp *smp)
|
||||
}
|
||||
|
||||
#if !defined(CONFIG_BT_SMP_SC_PAIR_ONLY)
|
||||
static void ident_sent(struct bt_conn *conn, void *user_data)
|
||||
void smp_ident_sent(struct bt_conn *conn, void *user_data)
|
||||
{
|
||||
smp_check_complete(conn, BT_SMP_DIST_ENC_KEY);
|
||||
}
|
||||
@@ -1834,7 +1878,7 @@ static void legacy_distribute_keys(struct bt_smp *smp)
|
||||
bt_rand(&rand, sizeof(rand));
|
||||
bt_rand(&ediv, sizeof(ediv));
|
||||
|
||||
buf = smp_create_pdu(conn, BT_SMP_CMD_ENCRYPT_INFO,
|
||||
buf = smp_create_pdu(smp, BT_SMP_CMD_ENCRYPT_INFO,
|
||||
sizeof(*info));
|
||||
if (!buf) {
|
||||
BT_ERR("Unable to allocate Encrypt Info buffer");
|
||||
@@ -1852,7 +1896,7 @@ static void legacy_distribute_keys(struct bt_smp *smp)
|
||||
|
||||
smp_send(smp, buf, NULL, NULL);
|
||||
|
||||
buf = smp_create_pdu(conn, BT_SMP_CMD_MASTER_IDENT,
|
||||
buf = smp_create_pdu(smp, BT_SMP_CMD_MASTER_IDENT,
|
||||
sizeof(*ident));
|
||||
if (!buf) {
|
||||
BT_ERR("Unable to allocate Master Ident buffer");
|
||||
@@ -1863,7 +1907,7 @@ static void legacy_distribute_keys(struct bt_smp *smp)
|
||||
memcpy(ident->rand, rand, sizeof(ident->rand));
|
||||
memcpy(ident->ediv, ediv, sizeof(ident->ediv));
|
||||
|
||||
smp_send(smp, buf, ident_sent, NULL);
|
||||
smp_send(smp, buf, smp_ident_sent, NULL);
|
||||
|
||||
if (atomic_test_bit(smp->flags, SMP_FLAG_BOND)) {
|
||||
bt_keys_add_type(keys, BT_KEYS_SLAVE_LTK);
|
||||
@@ -1878,14 +1922,14 @@ static void legacy_distribute_keys(struct bt_smp *smp)
|
||||
}
|
||||
#endif /* !CONFIG_BT_SMP_SC_PAIR_ONLY */
|
||||
|
||||
static void bt_smp_distribute_keys(struct bt_smp *smp)
|
||||
static u8_t bt_smp_distribute_keys(struct bt_smp *smp)
|
||||
{
|
||||
struct bt_conn *conn = smp->chan.chan.conn;
|
||||
struct bt_keys *keys = conn->le.keys;
|
||||
|
||||
if (!keys) {
|
||||
BT_ERR("No keys space for %s", bt_addr_le_str(&conn->le.dst));
|
||||
return;
|
||||
return BT_SMP_ERR_UNSPECIFIED;
|
||||
}
|
||||
|
||||
#if !defined(CONFIG_BT_SMP_SC_PAIR_ONLY)
|
||||
@@ -1901,11 +1945,11 @@ static void bt_smp_distribute_keys(struct bt_smp *smp)
|
||||
struct bt_smp_ident_addr_info *id_addr_info;
|
||||
struct net_buf *buf;
|
||||
|
||||
buf = smp_create_pdu(conn, BT_SMP_CMD_IDENT_INFO,
|
||||
buf = smp_create_pdu(smp, BT_SMP_CMD_IDENT_INFO,
|
||||
sizeof(*id_info));
|
||||
if (!buf) {
|
||||
BT_ERR("Unable to allocate Ident Info buffer");
|
||||
return;
|
||||
return BT_SMP_ERR_UNSPECIFIED;
|
||||
}
|
||||
|
||||
id_info = net_buf_add(buf, sizeof(*id_info));
|
||||
@@ -1913,17 +1957,17 @@ static void bt_smp_distribute_keys(struct bt_smp *smp)
|
||||
|
||||
smp_send(smp, buf, NULL, NULL);
|
||||
|
||||
buf = smp_create_pdu(conn, BT_SMP_CMD_IDENT_ADDR_INFO,
|
||||
buf = smp_create_pdu(smp, BT_SMP_CMD_IDENT_ADDR_INFO,
|
||||
sizeof(*id_addr_info));
|
||||
if (!buf) {
|
||||
BT_ERR("Unable to allocate Ident Addr Info buffer");
|
||||
return;
|
||||
return BT_SMP_ERR_UNSPECIFIED;
|
||||
}
|
||||
|
||||
id_addr_info = net_buf_add(buf, sizeof(*id_addr_info));
|
||||
bt_addr_le_copy(&id_addr_info->addr, &bt_dev.id_addr[conn->id]);
|
||||
|
||||
smp_send(smp, buf, id_sent, NULL);
|
||||
smp_send(smp, buf, smp_id_sent, NULL);
|
||||
}
|
||||
#endif /* CONFIG_BT_PRIVACY */
|
||||
|
||||
@@ -1932,11 +1976,11 @@ static void bt_smp_distribute_keys(struct bt_smp *smp)
|
||||
struct bt_smp_signing_info *info;
|
||||
struct net_buf *buf;
|
||||
|
||||
buf = smp_create_pdu(conn, BT_SMP_CMD_SIGNING_INFO,
|
||||
buf = smp_create_pdu(smp, BT_SMP_CMD_SIGNING_INFO,
|
||||
sizeof(*info));
|
||||
if (!buf) {
|
||||
BT_ERR("Unable to allocate Signing Info buffer");
|
||||
return;
|
||||
return BT_SMP_ERR_UNSPECIFIED;
|
||||
}
|
||||
|
||||
info = net_buf_add(buf, sizeof(*info));
|
||||
@@ -1949,19 +1993,20 @@ static void bt_smp_distribute_keys(struct bt_smp *smp)
|
||||
keys->local_csrk.cnt = 0U;
|
||||
}
|
||||
|
||||
smp_send(smp, buf, sign_info_sent, NULL);
|
||||
smp_send(smp, buf, smp_sign_info_sent, NULL);
|
||||
}
|
||||
#endif /* CONFIG_BT_SIGNING */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_BT_PERIPHERAL)
|
||||
static u8_t send_pairing_rsp(struct bt_smp *smp)
|
||||
{
|
||||
struct bt_conn *conn = smp->chan.chan.conn;
|
||||
struct bt_smp_pairing *rsp;
|
||||
struct net_buf *rsp_buf;
|
||||
|
||||
rsp_buf = smp_create_pdu(conn, BT_SMP_CMD_PAIRING_RSP, sizeof(*rsp));
|
||||
rsp_buf = smp_create_pdu(smp, BT_SMP_CMD_PAIRING_RSP, sizeof(*rsp));
|
||||
if (!rsp_buf) {
|
||||
return BT_SMP_ERR_UNSPECIFIED;
|
||||
}
|
||||
@@ -2086,7 +2131,7 @@ static u8_t legacy_send_pairing_confirm(struct bt_smp *smp)
|
||||
struct bt_smp_pairing_confirm *req;
|
||||
struct net_buf *buf;
|
||||
|
||||
buf = smp_create_pdu(conn, BT_SMP_CMD_PAIRING_CONFIRM, sizeof(*req));
|
||||
buf = smp_create_pdu(smp, BT_SMP_CMD_PAIRING_CONFIRM, sizeof(*req));
|
||||
if (!buf) {
|
||||
return BT_SMP_ERR_UNSPECIFIED;
|
||||
}
|
||||
@@ -2189,7 +2234,7 @@ static u8_t legacy_pairing_random(struct bt_smp *smp)
|
||||
|
||||
atomic_set_bit(smp->flags, SMP_FLAG_ENC_PENDING);
|
||||
|
||||
smp_send_pairing_random(smp);
|
||||
return smp_send_pairing_random(smp);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -2271,6 +2316,7 @@ static u8_t smp_encrypt_info(struct bt_smp *smp, struct net_buf *buf)
|
||||
static u8_t smp_master_ident(struct bt_smp *smp, struct net_buf *buf)
|
||||
{
|
||||
struct bt_conn *conn = smp->chan.chan.conn;
|
||||
u8_t err;
|
||||
|
||||
BT_DBG("");
|
||||
|
||||
@@ -2299,7 +2345,10 @@ static u8_t smp_master_ident(struct bt_smp *smp, struct net_buf *buf)
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_CENTRAL) &&
|
||||
conn->role == BT_HCI_ROLE_MASTER && !smp->remote_dist) {
|
||||
bt_smp_distribute_keys(smp);
|
||||
err = bt_smp_distribute_keys(smp);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
/* if all keys were distributed, pairing is done */
|
||||
@@ -2479,7 +2528,7 @@ int bt_smp_send_security_req(struct bt_conn *conn)
|
||||
return -ENOBUFS;
|
||||
}
|
||||
|
||||
req_buf = smp_create_pdu(conn, BT_SMP_CMD_SECURITY_REQUEST,
|
||||
req_buf = smp_create_pdu(smp, BT_SMP_CMD_SECURITY_REQUEST,
|
||||
sizeof(*req));
|
||||
if (!req_buf) {
|
||||
return -ENOBUFS;
|
||||
@@ -2616,8 +2665,7 @@ static u8_t sc_send_public_key(struct bt_smp *smp)
|
||||
struct bt_smp_public_key *req;
|
||||
struct net_buf *req_buf;
|
||||
|
||||
req_buf = smp_create_pdu(smp->chan.chan.conn, BT_SMP_CMD_PUBLIC_KEY,
|
||||
sizeof(*req));
|
||||
req_buf = smp_create_pdu(smp, BT_SMP_CMD_PUBLIC_KEY, sizeof(*req));
|
||||
if (!req_buf) {
|
||||
return BT_SMP_ERR_UNSPECIFIED;
|
||||
}
|
||||
@@ -2676,7 +2724,7 @@ int bt_smp_send_pairing_req(struct bt_conn *conn)
|
||||
return -ENOBUFS;
|
||||
}
|
||||
|
||||
req_buf = smp_create_pdu(conn, BT_SMP_CMD_PAIRING_REQ, sizeof(*req));
|
||||
req_buf = smp_create_pdu(smp, BT_SMP_CMD_PAIRING_REQ, sizeof(*req));
|
||||
if (!req_buf) {
|
||||
return -ENOBUFS;
|
||||
}
|
||||
@@ -2845,8 +2893,7 @@ static u8_t sc_smp_send_dhkey_check(struct bt_smp *smp, const u8_t *e)
|
||||
|
||||
BT_DBG("");
|
||||
|
||||
buf = smp_create_pdu(smp->chan.chan.conn, BT_SMP_DHKEY_CHECK,
|
||||
sizeof(*req));
|
||||
buf = smp_create_pdu(smp, BT_SMP_DHKEY_CHECK, sizeof(*req));
|
||||
if (!buf) {
|
||||
return BT_SMP_ERR_UNSPECIFIED;
|
||||
}
|
||||
@@ -2898,8 +2945,7 @@ static u8_t compute_and_send_master_dhcheck(struct bt_smp *smp)
|
||||
}
|
||||
|
||||
atomic_set_bit(&smp->allowed_cmds, BT_SMP_DHKEY_CHECK);
|
||||
sc_smp_send_dhkey_check(smp, e);
|
||||
return 0;
|
||||
return sc_smp_send_dhkey_check(smp, e);
|
||||
}
|
||||
#endif /* CONFIG_BT_CENTRAL */
|
||||
|
||||
@@ -2907,6 +2953,7 @@ static u8_t compute_and_send_master_dhcheck(struct bt_smp *smp)
|
||||
static u8_t compute_and_check_and_send_slave_dhcheck(struct bt_smp *smp)
|
||||
{
|
||||
u8_t re[16], e[16], r[16];
|
||||
u8_t err;
|
||||
|
||||
(void)memset(r, 0, sizeof(r));
|
||||
|
||||
@@ -2963,7 +3010,10 @@ static u8_t compute_and_check_and_send_slave_dhcheck(struct bt_smp *smp)
|
||||
}
|
||||
|
||||
/* send local e */
|
||||
sc_smp_send_dhkey_check(smp, e);
|
||||
err = sc_smp_send_dhkey_check(smp, e);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
atomic_set_bit(smp->flags, SMP_FLAG_ENC_PENDING);
|
||||
return 0;
|
||||
@@ -3169,8 +3219,7 @@ static u8_t smp_pairing_random(struct bt_smp *smp, struct net_buf *buf)
|
||||
|
||||
atomic_set_bit(&smp->allowed_cmds,
|
||||
BT_SMP_CMD_PAIRING_CONFIRM);
|
||||
smp_send_pairing_confirm(smp);
|
||||
return 0;
|
||||
return smp_send_pairing_confirm(smp);
|
||||
default:
|
||||
return BT_SMP_ERR_UNSPECIFIED;
|
||||
}
|
||||
@@ -3207,7 +3256,10 @@ static u8_t smp_pairing_random(struct bt_smp *smp, struct net_buf *buf)
|
||||
|
||||
atomic_set_bit(&smp->allowed_cmds,
|
||||
BT_SMP_CMD_PAIRING_CONFIRM);
|
||||
smp_send_pairing_random(smp);
|
||||
err = smp_send_pairing_random(smp);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
smp->passkey_round++;
|
||||
if (smp->passkey_round == 20U) {
|
||||
@@ -3251,10 +3303,10 @@ static u8_t smp_pairing_random(struct bt_smp *smp, struct net_buf *buf)
|
||||
|
||||
atomic_set_bit(&smp->allowed_cmds, BT_SMP_DHKEY_CHECK);
|
||||
atomic_set_bit(smp->flags, SMP_FLAG_DHCHECK_WAIT);
|
||||
smp_send_pairing_random(smp);
|
||||
return smp_send_pairing_random(smp);
|
||||
#else
|
||||
return BT_SMP_ERR_PAIRING_NOTSUPP;
|
||||
#endif /* CONFIG_BT_PERIPHERAL */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static u8_t smp_pairing_failed(struct bt_smp *smp, struct net_buf *buf)
|
||||
@@ -3314,6 +3366,7 @@ static u8_t smp_ident_addr_info(struct bt_smp *smp, struct net_buf *buf)
|
||||
{
|
||||
struct bt_conn *conn = smp->chan.chan.conn;
|
||||
struct bt_smp_ident_addr_info *req = (void *)buf->data;
|
||||
u8_t err;
|
||||
|
||||
BT_DBG("identity %s", bt_addr_le_str(&req->addr));
|
||||
|
||||
@@ -3375,7 +3428,10 @@ static u8_t smp_ident_addr_info(struct bt_smp *smp, struct net_buf *buf)
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_CENTRAL) &&
|
||||
conn->role == BT_HCI_ROLE_MASTER && !smp->remote_dist) {
|
||||
bt_smp_distribute_keys(smp);
|
||||
err = bt_smp_distribute_keys(smp);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
/* if all keys were distributed, pairing is done */
|
||||
@@ -3390,6 +3446,7 @@ static u8_t smp_ident_addr_info(struct bt_smp *smp, struct net_buf *buf)
|
||||
static u8_t smp_signing_info(struct bt_smp *smp, struct net_buf *buf)
|
||||
{
|
||||
struct bt_conn *conn = smp->chan.chan.conn;
|
||||
u8_t err;
|
||||
|
||||
BT_DBG("");
|
||||
|
||||
@@ -3413,7 +3470,10 @@ static u8_t smp_signing_info(struct bt_smp *smp, struct net_buf *buf)
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_CENTRAL) &&
|
||||
conn->role == BT_HCI_ROLE_MASTER && !smp->remote_dist) {
|
||||
bt_smp_distribute_keys(smp);
|
||||
err = bt_smp_distribute_keys(smp);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
/* if all keys were distributed, pairing is done */
|
||||
@@ -3980,7 +4040,9 @@ static void bt_smp_encrypt_change(struct bt_l2cap_chan *chan,
|
||||
return;
|
||||
}
|
||||
|
||||
bt_smp_distribute_keys(smp);
|
||||
if (bt_smp_distribute_keys(smp)) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* if all keys were distributed, pairing is done */
|
||||
if (!smp->local_dist && !smp->remote_dist) {
|
||||
@@ -4526,6 +4588,7 @@ static inline int smp_self_test(void)
|
||||
int bt_smp_auth_passkey_entry(struct bt_conn *conn, unsigned int passkey)
|
||||
{
|
||||
struct bt_smp *smp;
|
||||
u8_t err;
|
||||
|
||||
smp = smp_chan_get(conn);
|
||||
if (!smp) {
|
||||
@@ -4547,7 +4610,8 @@ int bt_smp_auth_passkey_entry(struct bt_conn *conn, unsigned int passkey)
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_CENTRAL) &&
|
||||
smp->chan.chan.conn->role == BT_HCI_ROLE_MASTER) {
|
||||
if (smp_send_pairing_confirm(smp)) {
|
||||
err = smp_send_pairing_confirm(smp);
|
||||
if (err) {
|
||||
smp_error(smp, BT_SMP_ERR_PASSKEY_ENTRY_FAILED);
|
||||
return 0;
|
||||
}
|
||||
@@ -4557,7 +4621,8 @@ int bt_smp_auth_passkey_entry(struct bt_conn *conn, unsigned int passkey)
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_PERIPHERAL) &&
|
||||
atomic_test_bit(smp->flags, SMP_FLAG_CFM_DELAYED)) {
|
||||
if (smp_send_pairing_confirm(smp)) {
|
||||
err = smp_send_pairing_confirm(smp);
|
||||
if (err) {
|
||||
smp_error(smp, BT_SMP_ERR_PASSKEY_ENTRY_FAILED);
|
||||
return 0;
|
||||
}
|
||||
@@ -4699,9 +4764,7 @@ static int le_sc_oob_pairing_continue(struct bt_smp *smp)
|
||||
atomic_set_bit(smp->flags, SMP_FLAG_DHCHECK_WAIT);
|
||||
}
|
||||
|
||||
smp_send_pairing_random(smp);
|
||||
|
||||
return 0;
|
||||
return smp_send_pairing_random(smp);
|
||||
}
|
||||
|
||||
int bt_smp_le_oob_set_sc_data(struct bt_conn *conn,
|
||||
|
||||
@@ -147,6 +147,11 @@ int bt_smp_le_oob_get_sc_data(struct bt_conn *conn,
|
||||
const struct bt_le_oob_sc_data **oobd_local,
|
||||
const struct bt_le_oob_sc_data **oobd_remote);
|
||||
|
||||
|
||||
void smp_ident_sent(struct bt_conn *conn, void *user_data);
|
||||
void smp_id_sent(struct bt_conn *conn, void *user_data);
|
||||
void smp_sign_info_sent(struct bt_conn *conn, void *user_data);
|
||||
|
||||
/** brief Verify signed message
|
||||
*
|
||||
* @param conn Bluetooth connection
|
||||
|
||||
@@ -80,14 +80,18 @@ int bt_uuid_cmp(const struct bt_uuid *u1, const struct bt_uuid *u2)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
bool bt_uuid_create_le(struct bt_uuid *uuid, const u8_t *data, u8_t data_len)
|
||||
bool bt_uuid_create(struct bt_uuid *uuid, const u8_t *data, u8_t data_len)
|
||||
{
|
||||
/* Copy UUID from packet data to internal bt_uuid */
|
||||
/* Copy UUID from packet data/internal variable to internal bt_uuid */
|
||||
switch (data_len) {
|
||||
case 2:
|
||||
uuid->type = BT_UUID_TYPE_16;
|
||||
BT_UUID_16(uuid)->val = sys_get_le16(data);
|
||||
break;
|
||||
case 4:
|
||||
uuid->type = BT_UUID_TYPE_32;
|
||||
BT_UUID_32(uuid)->val = sys_get_le32(data);
|
||||
break;
|
||||
case 16:
|
||||
uuid->type = BT_UUID_TYPE_128;
|
||||
memcpy(&BT_UUID_128(uuid)->val, data, 16);
|
||||
@@ -98,35 +102,6 @@ bool bt_uuid_create_le(struct bt_uuid *uuid, const u8_t *data, u8_t data_len)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool bt_uuid_create(struct bt_uuid *uuid, u8_t *data, u8_t data_len)
|
||||
{
|
||||
/* Copy UUID from internal variable to internal bt_uuid */
|
||||
union {
|
||||
u16_t *u16;
|
||||
u32_t *u32;
|
||||
u8_t *u128;
|
||||
} v;
|
||||
|
||||
v.u128 = data;
|
||||
switch (data_len) {
|
||||
case 2:
|
||||
uuid->type = BT_UUID_TYPE_16;
|
||||
BT_UUID_16(uuid)->val = *v.u16;
|
||||
break;
|
||||
case 4:
|
||||
uuid->type = BT_UUID_TYPE_32;
|
||||
BT_UUID_32(uuid)->val = *v.u32;
|
||||
break;
|
||||
case 16:
|
||||
uuid->type = BT_UUID_TYPE_128;
|
||||
memcpy(&BT_UUID_128(uuid)->val, v.u128, 16);
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_BT_DEBUG)
|
||||
void bt_uuid_to_str(const struct bt_uuid *uuid, char *str, size_t len)
|
||||
{
|
||||
|
||||